<The previous article in this series | The table of contents of this series | The next article in this series>
To Know How to Handle (Read or Write) LibreOffice or Apache OpenOffice Writer or Calc Documents via Extensions from Java or Macro Programs
Now, we will create a UNO component. As our UNO component is 'thebiasplanet.uno.hiunoextensionsunoextension.HiUnoExtensionsImplementation', we create a Java source file, 'source/java/thebiasplanet/uno/hiunoextensionsunoextension/HiUnoExtensionsImplementation.java', under the project directory, and write this in the file.
// # Change the package name
package thebiasplanet.uno.hiunoextensionsunoextension;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import com.sun.star.lib.uno.helper.WeakBase;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.lang.XInitialization;
import com.sun.star.uno.XComponentContext;
// # Add necessary classes and interfaces START
import com.sun.star.lang.IllegalArgumentException;
// # Add necessary classes and interfaces END
// # Change the class name
public class HiUnoExtensionsImplementation
extends WeakBase
implements XServiceInfo, XInitialization,
// # Specify the UNO interface to implement
XHiUnoExtensions {
private static final Set <String> SERVICE_NAMES_SET = new HashSet <String> ();
private static final Class thisClass = new Object () { }.getClass ().getEnclosingClass ();
static {
// # Add service names START
SERVICE_NAMES_SET.add ("thebiasplanet.uno.hiunoextensionsunoextension.HiUnoExtensions");
// # Add service names END
}
static final String [] SERVICE_NAMES_ARRAY = SERVICE_NAMES_SET.toArray (new String [SERVICE_NAMES_SET.size ()]);
private XComponentContext componentContext = null;
// # Add member variables START
private String message = null;
// # Add member variables END
static void setThisClassToServicesProvider (Map <String, Object []> p_implementationClassNameToImplementationClassAndServiceNamesArrayMap) {
p_implementationClassNameToImplementationClassAndServiceNamesArrayMap.put (thisClass.getName (), new Object [] {thisClass, SERVICE_NAMES_ARRAY});
}
// # Change the class name
public HiUnoExtensionsImplementation (XComponentContext p_componentContext)
throws IllegalArgumentException {
componentContext = p_componentContext;
}
public final void initialize (java.lang.Object [] p_arguments)
throws com.sun.star.uno.Exception {
// # Write the initialization START
if (p_arguments != null && p_arguments.length == 1) {
if (p_arguments[0] instanceof String) {
message = (String) p_arguments[0];
if (message == null) {
throw new IllegalArgumentException ("The first argument can't be null.");
}
}
else {
throw new IllegalArgumentException("The first argument must be a String instance.");
}
}
else {
throw new IllegalArgumentException("The number of arguments must be 1.");
}
// # Write the initialization END
}
// # Add methods of the implemented UNO interface START
public String sayHi (String p_name)
throws IllegalArgumentException {
if (p_name == null) {
throw new IllegalArgumentException ("The first argument can't be null.");
}
return String.format ("%s, %s!", message, p_name);
}
// # Add methods of the implemented UNO interface END
// # Add other member methods START
// # Add other member methods END
public String getImplementationName () {
return thisClass.getName ();
}
public final boolean supportsService (String p_serviceName) {
return SERVICE_NAMES_SET.contains (p_serviceName);
}
public final String [] getSupportedServiceNames () {
return SERVICE_NAMES_ARRAY;
}
}
Hmm, . . .
The class extends 'com.sun.star.lib.uno.helper.WeakBase', which is a UNO helper class that has implemented interfaces, 'com.sun.star.lang.XTypeProvider' and 'com.sun.star.uno.XWeak'.
'com.sun.star.lang.XTypeProvider' is required to be implemented if our UNO component will be accessed from LibreOffice Basic macros. LibreOffice Basic macros have to know what UNO interfaces the UNO component implements through 'com.sun.star.lang.XTypeProvider'.
Why do LibreOffice Basic macros have to know them while Java programs don't have to?
Remember that the UNO proxy is created for a UNO interface. In Java, if we want a UNO proxy for another UNO interface, we have to explicitly get the UNO proxy by specifying the UNO interface. In LibreOffice Basic macros, that process is handled by the LibreOffice Basic runtime, which knows what UNO interfaces to be queried through 'com.sun.star.lang.XTypeProvider'.
So, in LibreOffice Basic macros, we don't have to explicitly get UNO proxies per UNO interface.
That's right.
As for 'com.sun.star.uno.XWeak', actually, we don't particularly need to implement it: we use that helper class because the helper class implements 'com.sun.star.lang.XTypeProvider', and there is no helper class that implements only 'com.sun.star.lang.XTypeProvider'.
What is the role of 'com.sun.star.uno.XWeak'?
When a UNO component implements 'com.sun.star.uno.XWeak', the UNO component can be referred by weak references. The weak reference is a reference to an object, that doesn't prevent the object from being garbage collected.
So, if an instance of our UNO component is referred by weak references and is not referred by any normal (strong) reference, the instance will be garbage collected eventually.
Yes.
And our UNO component implements 'com.sun.star.lang.XServiceInfo', 'com.sun.star.lang.XInitialization', and 'thebiasplanet.uno.hiunoextensionsunoextension.XHiUnoExtensions'.
Our UNO component implements 'com.sun.star.lang.XServiceInfo' because it will be registered as a UNO service. Otherwise, it doesn't have to implement 'com.sun.star.lang.XServiceInfo'.
The methods, 'getImplementationName', 'supportsService', and 'getSupportedServiceNames', are the methods of the interface.
The method, 'getImplementationName', returns the full name of the UNO component class.
The method, 'supportsService', takes a String instance, and judges whether the String instance equals one of UNO service names by which the UNO component is registered.
The method, 'getSupportedServiceNames', returns an array of UNO service names by which the UNO component is registered.
The UNO component seems to be able to be registered in multiple UNO service names. Is that useful?
I don't know. Anyway, the mechanism allows us to register the UNO component in multiple UNO service names.
I see.
As for 'com.sun.star.lang.XInitialization', when our UNO component is instantiated through a UNO service manager, the interface allows us to customize the initialization of those instances.
The method, 'initialize', is the method of the interface. When our UNO component is instantiated through a UNO service manager, the Java constructor of the UNO component is called with the component context passed as the argument. Then, the 'initialize' method is called with an array of parameters passed as the argument.
Ah-ha.
And obviously, our UNO component implements the interface, 'thebiasplanet.uno.hiunoextensionsunoextension.XHiUnoExtensions'.
Of course.
The static final members, 'SERVICE_NAMES_SET', 'thisClass', and 'SERVICE_NAMES_ARRAY', contain information that is required for the UNO component to be registered as UNO services. The information doesn't particularly have to be contained as those members: it's OK if aforementioned interfaces are implemented appropriately.
We can just change the UNO service name that is added to 'SERVICE_NAMES_SET'.
Yes.
The member, 'componentContext', contains the component context, which doesn't necessarily have to be saved in the UNO object, but in many cases, it's useful to save it there. We can get the global UNO service manager from it. So, we make it a default to save the component context passed as the argument in the Java constructor there.
All right.
The member, 'message', is a 'this UNO component'-specific member. For other UNO components, we will replace it with their necessary members.
I see.
The static method, 'setThisClassToServicesProvider', is a method that provides this UNO component's information to the 'global UNO services' provider. The information doesn't have to be provided by that method: it's OK if the 'global UNO services' provider can know what it has to know.
OK.
And the method, 'sayHi', is the method of the interface, 'thebiasplanet.uno.hiunoextensionsunoextension.XHiUnoExtensions'.
That's the place where we write 'our UNO component'-specific algorithm.
- Apache OpenOffice Wiki. (2014/01/02). Apache OpenOffice Developer's Guide. Retrieved from https://wiki.openoffice.org/wiki/Documentation/DevGuide/OpenOffice.org_Developers_Guide
<The previous article in this series | The table of contents of this series | The next article in this series>