Implementing without Helpers

From Apache OpenOffice Wiki
Jump to: navigation, search



XInterface

As soon as the component implements any UNO interface, com.sun.star.uno.XInterface is included automatically. The Java interface definition generated by javamaker for com.sun.star.uno.XInterface only contains a TypeInfo member used by Java UNO internally to store certain UNO type information:

  // source file com/sun/star/uno/XInterface.java corresponding to the class generated by
 
  package com.sun.star.uno;
 
  public interface XInterface
  {
      // static Member
      public static final com.sun.star.lib.uno.typeinfo.TypeInfo UNOTYPEINFO[] = null;
  }

Note that XInterface does not have any methods, in contrast to its IDL description. That means, if implements com.sun.star.uno.XInterface is added to a class definition, there is nothing to implement.

The method queryInterface() is unnecessary in the implementation of a UNO object, because the Java UNO runtime environment obtains interface references without support from the UNO objects themselves. Within Java, the method UnoRuntime.queryInterface() is used to obtain interfaces instead of calling <idlml>com.sun.star.uno.XInterface:queryInterface</idlml>(), and the Java UNO language binding hands out interfaces for UNO objects to other processes on its own as well.

The methods acquire() and release() are used for reference counting and control the lifetime of an object, because the Java garbage collector does this, there is no reference counting in Java components.

XTypeProvider

Helper classes with default com.sun.star.lang.XTypeProvider implementations are still under development for Java. Meanwhile, every Java UNO object implementation can implement the XTypeProvider interface as shown in the following code. In your implementation, adjust getTypes():

  ...
 
  // XTypeProvider implementation
 
  // maintain a static implementation id for all instances of ImageShrink
  // initialized by the first call to getImplementationId()
  protected static byte[] _implementationId;
 
  public com.sun.star.uno.Type[] getTypes() {
 
      // instantiate Type instances for each interface you support and place them in a Type[] array
      // (this object supports XServiceInfo, XTypeProvider, and XImageShrinkFilter)
      return new com.sun.star.uno.Type[] {
          new com.sun.star.uno.Type(com.sun.star.lang.XServiceInfo.class),
          new com.sun.star.uno.Type(com.sun.star.lang.XTypeProvider.class),
          new com.sun.star.uno.Type(org.openoffice.test.XImageShrinkFilter.class) };
  }
 
  synchronized public byte[] getImplementationId() {
      if (_implementationId == null) {
          _implementationId= new byte[16];
          int hash = hashCode(); // hashCode of this object
          _implementationId[0] = (byte)(hash & 0xff);
          _implementationId[1] = (byte)((hash >>> 8) & 0xff);
          _implementationId[2] = (byte)((hash >>> 16) & 0xff);
          _implementationId[3] = (byte)((hash >>>24) & 0xff);
      }
      return _implementationId;
  }
 
  ...

The suggested implementation of the getImplementationId() method is not optimal, it uses the hashCode() of the first instance that initializes the static field. The future UNO helper class will improve this.

XComponent

XComponent is an optional interface that is useful when other objects hold references to the component. The notification mechanism of XComponent enables listener objects to learn when the component stops to provide its services, so that the objects drop their references to the component. This enables the component to delete itself when its reference count drops to zero. From section Core Interfaces to Implement, there must be three things done when dispose() is called at an XComponent:

  • Inform registered XEventListeners that the object is being disposed of by calling their method disposing().
  • Release all references the object holds, including all XEvenListener objects.
  • On further calls to the component, throw an com.sun.star.lang.DisposedException in case the required task can not be fulfilled anymore, because the component was disposed.

In Java, the object cannot be deleted, but the garbage collector will do this. It is sufficient to release all references that are currently being held to break the cyclic reference, and to call disposing() on all com.sun.star.lang.XEventListeners.

The registration and removal of listener interfaces is a standard procedure in Java. Some IDEs even create the necessary methods automatically. The following example could be written:

  ...
 
  //XComponent implementation
 
  // hold a list of eventListeners
  private java.util.ArrayList eventListeners = new java.util.ArrayList();
 
  public void dispose {
      java.util.ArrayList listeners;
      synchronized (this) {
          listeners = eventListeners;
          eventListeners = null;
      }
      for (java.util.Iterator i = listeners.iterator(); i.hasNext();) {
          fireDisposing((XEventListener) i.next());
      }
      releaseReferences();
  }
 
  public void addEventListener(XEventListener listener) {
      bool fire = false;
      synchronized (this) {
          if (eventListeners == null) {
              fire = true;
          } else {
              eventListeners.add(listener);
          }
      }
      if (fire) {
          fireDisposing(listener);
      }
  }
 
  public synchronized void removeEventListener(XEventListener listener) {
      if (eventListeners != null) {
          eventListeners.remove(listener);
      }
  }
 
  private void fireDisposing(XEventListener listener) {
      com.sun.star.uno.EventObject event = new com.sun.star.uno.EventObject(this);
      try {
          listener.disposing(event);
      } catch (com.sun.star.uno.DisposedException e) {
          // it is not an error if some listener is disposed simultaneously
      }
  }
 
  private void releaseReferences() {
      xComponentContext = null;
      // ...
  }
Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages