Possible Structures for Java Components
- Class Definition with Helper Class
- Implementing Your Own Interfaces
- Providing a Single Factory Using a Helper Method
- Write Registration Info Using a Helper Method
- Implementing without Helpers
- Storing the Service Manager for Further Use
- Create Instance with Arguments
- Possible Structures for Java Components
- Running and Debugging Java Components
The implementation of a component depends on the needs of the implementer. The following examples show some possible ways to assemble a component. There can be one implemented object or several implemented objects per component file.
One Implementation per Component File
There are additional options if implementing one service per component file:
- Use a flat structure with the static component operations added to the service implementation class directly.
- Reserve the class with the implementation name for the static component operation and use an inner class to implement the service.
Implementation Class with Component Operations
An implementation class contains the static component operations. The following sample implements an interface com.sun.star.test.XSomething
in an implementation class JavaComp.TestComponent
:
// UNOIDL: interface example specification module com { module sun { module star { module test { interface XSomething: com::sun::star::uno::XInterface { string methodOne([in]string val); }; }; }; }; };
A component that implements only one service supporting XSomething
can be assembled in one class as follows:
package JavaComp; ... public class TestComponent implements XSomething, XTypeProvider, XServiceInfo { public static final String __serviceName="com.sun.star.test.JavaTestComponent"; public static XSingleServiceFactory __getServiceFactory(String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey) { XSingleServiceFactory xSingleServiceFactory = null; if (implName.equals( TestComponent.class.getName()) ) xSingleServiceFactory = FactoryHelper.getServiceFactory( TestComponent.class, TestComponent.__serviceName, multiFactory, regKey); return xSingleServiceFactory; } public static boolean __writeRegistryServiceInfo(XRegistryKey regKey){ return FactoryHelper.writeRegistryServiceInfo( TestComponent.class.getName(), TestComponent.__serviceName, regKey); } // XSomething string methodOne(String val) { return val; } //XTypeProvider public com.sun.star.uno.Type[] getTypes( ) { ... } // XTypeProvider public byte[] getImplementationId( ) { ... } //XServiceInfo public String getImplementationName( ) { ... } // XServiceInfo public boolean supportsService( /*IN*/String serviceName ) { ... } //XServiceInfo public String[] getSupportedServiceNames( ) { ... } }
The class implements the XSomething
interface. The IDL description and documentation provides information about its functionality. The class also contains the functions for factory creation and registration, therefore the manifest entry must read as follows:
RegistrationClassName: JavaComp.TestComponent
Implementation Class with Component Operations and Inner Implementation Class
To implement the component as inner class of the one that provides the service factory through __getServiceFactory()
, it must be a static inner class, otherwise the factory provided by the FactoryHelper
cannot create the component. An example for an inner implementation class is located in the sample com.sun.star.comp.demo.DemoComponent.java
provided with the SDK. The implementation of __getServiceFactory()
and __writeRegistryServiceInfo()
is omitted here, because they act the same as in the implementation class with component operations above.
package com.sun.star.comp.demo; public class DemoComponent { ... // static inner class implements service com.sun.star.demo.DemoComponent static public class _Implementation implements XTypeProvider, XServiceInfo, XInitialization, XWindowListener, XActionListener, XTopWindowListener { static private final String __serviceName = "com.sun.star.demo.DemoComponent"; private XMultiServiceFactory _xMultiServiceFactory; // Constructor public _Implementation(XMultiServiceFactory xMultiServiceFactory) { } } // static method to get a single factory creating the given service from the factory helper public static XSingleServiceFactory __getServiceFactory(String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey) { ... } // static method to write the service information into the given registry key public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { ... } }
The manifest entry for this implementation structure again has to point to the class with the static component operations:
RegistrationClassName: com.sun.star.comp.demo.DemoComponent
Multiple Implementations per Component File
To assemble several service implementations in one component file, implement each service in its own class and add a separate class containing the static component operations. The following code sample features two services: TestComponentA
and TestComponentB
implementing the interfaces XSomethingA
and XSomethingB
with a separate static class TestServiceProvider
containing the component operations.
The following are the UNOIDL specifications for XSomethingA
and XSomethingB
:
module com { module sun { module star { module test { interface XSomethingA: com::sun::star::uno::XInterface { string methodOne([in]string value); }; }; }; }; }; module com { module sun { module star { module test { interface XSomethingB: com::sun::star::uno::XInterface { string methodTwo([in]string value); }; }; }; }; };
TestComponentA
implements XSomethingA
:
package JavaComp; public class TestComponentA implements XTypeProvider, XServiceInfo, XSomethingA { static final String __serviceName= "JavaTestComponentA"; static byte[] _implementationId; public TestComponentA() { } // XSomethingA public String methodOne(String val) { return val; } //XTypeProvider public com.sun.star.uno.Type[] getTypes( ) { Type[] retValue= new Type[3]; retValue[0]= new Type( XServiceInfo.class); retValue[1]= new Type( XTypeProvider.class); retValue[2]= new Type( XSomethingA.class); return retValue; } //XTypeProvider synchronized public byte[] getImplementationId( ) { if (_implementationId == null) { _implementationId= new byte[16]; int hash = hashCode(); _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; } //XServiceInfo public String getImplementationName( ) { return getClass().getName(); } // XServiceInfo public boolean supportsService( /*IN*/String serviceName ) { return serviceName.equals( __serviceName); } //XServiceInfo public String[] getSupportedServiceNames( ) { String[] retValue= new String[0]; retValue[0]= __serviceName; return retValue; } }
TestComponentB
implements XSomethingB
. Note that it receives the component context and initialization arguments in its constructor.
package JavaComp; public class TestComponentB implements XTypeProvider, XServiceInfo, XSomethingB { static final String __serviceName= "JavaTestComponentB"; static byte[] _implementationId; private XComponentContext context; private Object[] args; public TestComponentB(XComponentContext context, Object[] args) { this.context= context; this.args= args; } // XSomethingB public String methodTwo(String val) { if (args.length > 0 && args[0] instanceof String ) return (String) args[0]; return val; } //XTypeProvider public com.sun.star.uno.Type[] getTypes( ) { Type[] retValue= new Type[3]; retValue[0]= new Type( XServiceInfo.class); retValue[1]= new Type( XTypeProvider.class); retValue[2]= new Type( XSomethingB.class); return retValue; } //XTypeProvider synchronized public byte[] getImplementationId( ) { if (_implementationId == null) { _implementationId= new byte[16]; int hash = hashCode(); _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; } //XServiceInfo public String getImplementationName( ) { return getClass().getName(); } // XServiceInfo public boolean supportsService( /*IN*/String serviceName ) { return serviceName.equals( __serviceName); } //XServiceInfo public String[] getSupportedServiceNames( ) { String[] retValue= new String[0]; retValue[0]= __serviceName; return retValue; } }
TestServiceProvider
implements __getServiceFactory()
and __writeRegistryServiceInfo()
:
package JavaComp; ... public class TestServiceProvider { public static XSingleServiceFactory __getServiceFactory(String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey) { XSingleServiceFactory xSingleServiceFactory = null; if (implName.equals( TestComponentA.class.getName()) ) xSingleServiceFactory = FactoryHelper.getServiceFactory( TestComponentA.class, TestComponentA.__serviceName, multiFactory, regKey); else if (implName.equals(TestComponentB.class.getName())) xSingleServiceFactory= FactoryHelper.getServiceFactory( TestComponentB.class, TestComponentB.__serviceName, multiFactory, regKey); return xSingleServiceFactory; } public static boolean __writeRegistryServiceInfo(XRegistryKey regKey){ boolean bregA= FactoryHelper.writeRegistryServiceInfo( TestComponentA.class.getName(), TestComponentA.__serviceName, regKey); boolean bregB= FactoryHelper.writeRegistryServiceInfo( TestComponentB.class.getName(), TestComponentB.__serviceName, regKey); return bregA && bregB; } }
The corresponding manifest entry must point to the static class with the component operations, in this case JavaComp.TestServiceProvider
:
RegistrationClassName: JavaComp.TestServiceProvider
Additional UNO Types
To make the Java UNO runtime more robust and efficient, each component is loaded with its own class loader, with one UnoClassLoader
at the root that takes care of loading all Java classes
representing UNO types in such a way that they are available across the whole Java UNO runtime environment.
If a Java UNO component requires additional UNO types, it must use a UNO-Type-Path
manifest entry to specify the location of the UNO types. The UNO-Type-Path
is similar to the Class-Path
manifest entry and can contain URLs of jars and directories that contain the Java classes that represent additional UNO types. The UnoClassLoader
evaluates the UNO-Type-Path
manifest entry to ensure that the additional UNO types are available to the Java UNO environment. The UNO-Type-Path
can have one of the following formats.
- Current jar does not contain UNO types:
UNO-Type-Path:
(Note the final space character.) - Current jar contains UNO types:
UNO-Type-Path: <>
- Current jar brings other jars that contain UNO types:
UNO-Type-Path: any/other/jar.jar yet/another/jar.jar
- Current jar and other jars that the current jar uses contain UNO types:
UNO-Type-Path: any/other/jar.jar <> yet/another/jar.jar
Note: For backwards compatibility, if you do not include the UNO-Type-Path manifest entry at all, the UNO runtime assumes that the current jar does contain UNO types. |
Content on this page is licensed under the Public Documentation License (PDL). |