Using UNO Interfaces

From Apache OpenOffice Wiki
Jump to: navigation, search



Every UNO object must inherit from the interface com.sun.star.uno.XInterface. Before using an object, know how to use it and how long it will function. By prescribing XInterface to be the base interface for each and every UNO interface, UNO lays the groundwork for object communication. For historic reasons, the UNOIDL description of XInterface lists the functionality that is associated with XInterface in the C++ (or binary UNO) language binding; other language bindings offer similar functionality by different mechanisms:

  // module com::sun::star::uno
  interface XInterface
  {
      any queryInterface( [in] type aType ); 
      [oneway] void acquire(); 
      [oneway] void release(); 
  };

The methods acquire() and release() handle the lifetime of the UNO object by reference counting. Detailed information about Reference counting is discussed in Lifetime of UNO objects. All current language bindings take care of acquire() and release() internally whenever there is a reference to a UNO object.

The queryInterface() method obtains other interfaces exported by the object. The caller asks the implementation of the object if it supports the interface specified by the type argument. The type parameter must denote a UNO interface type. The call may return with an interface reference of the requested type or with a void any. In C++ or Java simply test if the result is not equal null.

Unknowingly, we encountered XInterface when the service manager was asked to create a service instance:

  XComponentContext xLocalContext =
      com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
 
  // initial serviceManager
  XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager();
 
  // create a urlresolver
  Object urlResolver = xLocalServiceManager.createInstanceWithContext(
      "com.sun.star.bridge.UnoUrlResolver", xLocalContext);

The IDL specification of XMultiComponentFactory shows:

  // module com::sun::star::lang
  interface XMultiComponentFactory : com::sun::star::uno::XInterface
  { 
      com::sun::star::uno::XInterface createInstanceWithContext(
              [in] string aServiceSpecifier,
              [in] com::sun::star::uno::XComponentContext Context )
          raises (com::sun::star::uno::Exception);
          ...
  }

The above code shows that createInstanceWithContext() provides an instance of the given service, but it only returns a com.sun.star.uno.XInterface. This is mapped to java.lang.Object by the Java UNO binding afterwards.

In order to access a service, you need to know which interfaces the service exports. This information is available in the IDL reference. For instance, for the com.sun.star.bridge.UnoUrlResolver service, you learn:

  // module com::sun::star::bridge
  service UnoUrlResolver: XUnoUrlResolver;

This means the service you ordered at the service manager must support com.sun.star.bridge.XUnoUrlResolver. Next query the returned object for this interface:

  // query urlResolver for its com.sun.star.bridge.XUnoUrlResolver interface
  XUnoUrlResolver xUrlResolver = (XUnoUrlResolver) 
      UnoRuntime.queryInterface(UnoUrlResolver.class, urlResolver);
 
  // test if the interface was available
  if (null == xUrlResolver) {
      throw new java.lang.Exception(
          "Error: UrlResolver service does not export XUnoUrlResolver interface");
  }
  // use the interface
  Object remoteObject = xUrlResolver.resolve(
      "uno:socket,host=0,port=2002;urp;StarOffice.ServiceManager");

Template:Documentation/Note

The object decides whether or not it returns the interface. You have encountered a bug if the object does not return an interface that is specified to be mandatory in a service. When the interface reference is retrieved, invoke a call on the reference according to the interface specification. You can follow this strategy with every service you instantiate at a service manager, leading to success.

With this method, you may not only get UNO objects through the service manager, but also by normal interface calls:

  // Module com::sun::star::text
  interface XTextRange: com::sun::star::uno::XInterface
  { 
      XText getText(); 
      XTextRange getStart(); 
      ....
  };

The returned interface types are specified in the operations, so that calls can be invoked directly on the returned interface. Often, an object implementing multiple interfaces are returned, instead of an object implementing one certain interface.

You can then query the returned object for the other interfaces specified in the given old-style service, here com.sun.star.drawing.Text.

UNO has a number of generic interfaces. For example, the interface com.sun.star.frame.XComponentLoader:

  // module com::sun::star::frame
  interface XComponentLoader: com::sun::star::uno::XInterface
  {
      com::sun::star::lang::XComponent loadComponentFromURL( [in] string aURL,
              [in] string aTargetFrameName,
              [in] long nSearchFlags,
              [in] sequence<com::sun::star::beans::PropertyValue> aArgs )
          raises( com::sun::star::io::IOException,
                  com::sun::star::lang::IllegalArgumentException );
  };

It becomes difficult to find which interfaces are supported beside XComponent, because the kind of returned document (text, calc, draw, etc.) depends on the incoming URL.

These dependencies are described in the appropriate chapters of this manual.

Tools such as the InstanceInspector component is a quick method to find out which interfaces a certain object supports. The InstanceInspector component comes with the OpenOffice.org SDK that allows the inspection of a certain objects at runtime. Do not rely on implementation details of certain objects. If an object supports more interfaces than specified in the service description, query the interface and perform calls. The code may only work for this distinct office version and not work with an update of the office!

Template:Documentation/Note

There are certain specifications a queryInterface() implementation must not violate:

  • If queryInterface() on a specific object returned a valid interface reference for a given type, it must return a valid reference for any successive queryInterface() calls on this object for the same type.
  • If queryInterface() on a specific object returned a null reference for a given type, it must always return a null reference for the same type.
  • If queryInterface() on reference A returns reference B, queryInterface() on B for Type A must return interface reference A or calls made on the returned reference must be equivalent to calls made on reference A.
  • If queryInterface() on a reference A returns reference B, queryInterface() on A and B for XInterface must return the same interface reference (object identity).

These specifications must not be violated because a UNO runtime environment may choose to cache queryInterface() calls. The rules are basically identical to the rules of QueryInterface in MS COM.

Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages