<このシリーズの、前の記事 | このシリーズの目次 | このシリーズの、次の記事>
第2のサンプルUNO拡張機能プロジェクト、'heyUnoExtensionsUnoExtension'を作る。プロジェクトディレクトリを開発ディレクトリ直下に作る。
次に、プロジェクト別GradleビルドスクリプトまたはAntビルドファイルをプロジェクトディレクトリ直下に作る。Gradleビルドスクリプトの内容は以下のとおりだ。
// # Change the target name
ext.TARGET_NAME = "thebiasplanet.heyunoextensionsunoextension.uno"
apply ("from": "../commonBuild01.gradle")
// # Change the default task
defaultTasks ("registerUnoExtension")
ext ({
// Add this if necessary
//CHECKSTYLE = "ON"
// Add this if necessary
//JAR_DEPLOY_DIRECTORY_NAME = "?"
// Add this if necessary
//WAR_DEPLOY_DIRECTORY_NAME = "?"
// # Change this if necessary
INCLUDED_JAR_FILE_NAMES = []
// # Change this if necessary
OTHER_CLASSES_PATHS = [JAVA_FILES_BASE_DIRECTORY_NAME, CLASSES_BASE_DIRECTORY_NAME, "../unoAdditionalDataTypesToDisclose/target/thebiasplanet.unoadditionaldatatypes.uno.jar", "../unoUtilitiesToDisclose/target/thebiasplanet.unoutilities.jar", "../coreUtilitiesToDisclose/target/thebiasplanet.coreutilities.jar", LIBREOFFICE_CLASSES_BASE_DIRECTORY_NAME + "/unoil.jar", LIBREOFFICE_CLASSES_BASE_DIRECTORY_NAME + "/jurt.jar", LIBREOFFICE_CLASSES_BASE_DIRECTORY_NAME + "/ridl.jar", LIBREOFFICE_CLASSES_BASE_DIRECTORY_NAME + "/juh.jar"]
REFERENCED_PROJECT_DIRECTORY_NAMES = ["../coreUtilitiesToDisclose", "../unoUtilitiesToDisclose", "../unoAdditionalDataTypesToDisclose"]
})
apply ("from": "../commonBuild02.gradle")
UNOデータタイププロジェクトJarファイル、UNO ユーティリティプロジェクトJarファイル、コアユーティリティプロジェクトJarファイルが参照されているが、これらはこのプロジェクトのJarファイルの中には格納されないことに注意しよう。
ああ、第1のサンプルUNO拡張機能では、UNOユーティリティプロジェクトJarファイルはサンプルUNO拡張機能のJarファイルの中に格納されている。この違いは、UNOユーティリティプロジェクトJarファイルがGradleビルドスクリプトに設定されている位置から来ている。
そう。これらのJarファイルをLibreOfficeに直接登録したから、これらのJarファイルをUNO拡張機能に含める必要はもうない。しかし、もちろん、これらのJarファイルをビルド時に参照する必要はある。そのため、これらのJarファイルはGradleビルドスクリプトのあの位置に設定されている。
いいだろう。
項目4にしたがって、UNOインターフェース、'thebiasplanet.uno.heyunoextensionsunoextension.XHeyUnoExtensions'を実装するUNOコンポーネント、'thebiasplanet.uno.heyunoextensionsunoextension.HeyUnoExtensionsUnoComponent'を作成する。
このUNOインターフェースは、既に、UNOデータタイププロジェクトに作ってある。
そう。'source'ディレクトリをサンプルUNO拡張機能プロジェクトディレクトリ直下に作成し、Javaクラスソースファイル、'java/thebiasplanet/uno/heyunoextensionsunoextension/HeyUnoExtensionsUnoComponent.java'を作成する。このソースファイルの内容は以下のとおりだ。
// # Change the package name
package thebiasplanet.uno.heyunoextensionsunoextension;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
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 HeyUnoExtensionsUnoComponent
extends WeakBase
implements XServiceInfo, XInitialization,
// # Specify the UNO interface to implement
XHeyUnoExtensions {
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.heyunoextensionsunoextension.HeyUnoExtensionsService");
// # 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;
private Map <String, Object> componentContextExtraNameValueMap = null;
// # Add member variables END
static void setThisClassToServicesProvider (Map <String, Object []> p_unoComponentClassNameToUnoComponentClassAndServiceNamesArrayMap) {
p_unoComponentClassNameToUnoComponentClassAndServiceNamesArrayMap.put (thisClass.getName (), new Object [] {thisClass, SERVICE_NAMES_ARRAY});
}
// # Change the class name
public HeyUnoExtensionsUnoComponent (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 sayHey (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;
}
}
基本的に、内容は第1のサンプルUNO拡張機能のものと同じだ。
この時点ではそうだ。後で、我々はこのファイルにコードを追加するだろう。
次に、'グローバルUNOサービス'プロバイダーを作る。そのJavaソースファイルは、'java/thebiasplanet/uno/heyunoextensionsunoextension/HeyUnoExtensionsUnoExtensionGlobalServicesProvider.java'だ。このファイルの内容は以下のとおりだ。
// # Change the package name
package thebiasplanet.uno.heyunoextensionsunoextension;
import java.util.Map;
import java.util.HashMap;
import com.sun.star.lang.XSingleComponentFactory;
import com.sun.star.registry.XRegistryKey;
import thebiasplanet.unoutilities.serviceshandling.GlobalUnoServicesProviderUtility;
// # Change the class name
public class HeyUnoExtensionsUnoExtensionGlobalServicesProvider {
private static final Map <String, Object []> UNO_COMPONENT_CLASS_NAME_TO_UNO_COMPONENT_CLASS_AND_SERVICE_NAMES_ARRAY_MAP = new HashMap <String, Object []> ();
static {
// # Add UNO component classes START
HeyUnoExtensionsUnoComponent.setThisClassToServicesProvider (UNO_COMPONENT_CLASS_NAME_TO_UNO_COMPONENT_CLASS_AND_SERVICE_NAMES_ARRAY_MAP);
// # Add UNO component classes END
}
public static XSingleComponentFactory __getComponentFactory (String p_unoComponentClassName) {
return GlobalUnoServicesProviderUtility.getSingleComponentFactory (UNO_COMPONENT_CLASS_NAME_TO_UNO_COMPONENT_CLASS_AND_SERVICE_NAMES_ARRAY_MAP, p_unoComponentClassName);
}
public static boolean __writeRegistryServiceInfo (XRegistryKey p_registryKey) {
return GlobalUnoServicesProviderUtility.writeServicesInformationToRegistry (UNO_COMPONENT_CLASS_NAME_TO_UNO_COMPONENT_CLASS_AND_SERVICE_NAMES_ARRAY_MAP, p_registryKey);
}
}
前記事の記述を覚えていれば、これに説明は何もいらないだろう。
オーケー。
次に、リソースファイル、'MANIFEST.MF.addition'、'thebiasplanet.heyunoextensionsunoextension.uno.components'、'manifest.xml'を作る。
ここに'MANIFEST.MF.addition'の内容を示すのはやめよう。わかりきっているから。
'thebiasplanet.heyunoextensionsunoextension.uno.components'の内容は以下のとおりだ。
<?xml version="1.0" encoding="UTF-8"?>
<components xmlns="http://openoffice.org/2010/uno-components">
<!-- # Change the jar file uri -->
<component loader="com.sun.star.loader.Java2" uri="thebiasplanet.heyunoextensionsunoextension.uno.jar">
<!-- # Add UNO component class names -->
<implementation name="thebiasplanet.uno.heyunoextensionsunoextension.HeyUnoExtensionsUnoComponent">
<!-- # Add service names -->
<service name="thebiasplanet.uno.heyunoextensionsunoextension.HeyUnoExtensionsService"/>
</implementation>
</component>
</components>
'manifest.xml'の内容は以下のとおりだ。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest 1.0//EN" "Manifest.dtd">
<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
<!-- # Change the components file path -->
<manifest:file-entry manifest:media-type="application/vnd.sun.star.uno-components" manifest:full-path="thebiasplanet.heyunoextensionsunoextension.uno.components"/>
</manifest:manifest>
UNOデータタイプレジストリファイルを何も指定していないことに注意しよう。このプロジェクトにはないから。
分かった。
'グローバルUNOサービス'インスタンスファクトリはここでは作らない。グローバルUNOサービスをグローバルUNOサービスマネージャーをとおしてインスタンス化するのであれば、それが必要ないことを実証するためだ。
オーケー。
これで、サンプルUNO拡張機能をビルドして登録できる。いつものように、'gradle'コマンドか'ant'コマンドを実行して、これを行なおう。
その後、以下のような、LibreOffice BasicマクロのSubを作る。
Sub testsUnoExtension2
Dim l_args (0)
l_args (0) = "Good morning"
Dim l_heyUnoExtensionsService As Variant
l_heyUnoExtensionsService = GetProcessServiceManager ().createInstanceWithArguments ("thebiasplanet.uno.heyunoextensionsunoextension.HeyUnoExtensionsService", l_args ())
Msgbox (l_heyUnoExtensionsService.sayHey ("guys"))
End Sub
ふーむ、こうやって、グローバルUNOサービスをグローバルUNOサービスマネージャーをとおしてインスタンス化するのか。
そう。このマクロSubを実行しよう。
ふーむ、グローバルUNOサービスがインスタンス化できた。
こうして、我々が'グローバルUNOサービス'インスタンスファクトリと呼んでいるものが単にファクトリであって、参考文書にかかれているような「UNO新スタイルサービス」そのものではないことを、我々は実証した。
項目5にしたがって、新たにUNOコンポーネントを作るが、これをUNOサービスとしては登録しないことにしよう。
ふーむ。
UNOコンポーネントを、グローバルUNOサービスマネージャーをとおしてではなく、第1のUNOコンポーネント、'thebiasplanet.uno.heyunoextensionsunoextension.HeyUnoExtensionsUnoComponent'に追加するあるメソッドをとおして、インスタンス化する。
分かった。
第1に、第2のUNOコンポーネント用に、UNOインターフェース、'thebiasplanet.uno.heyunoextensionsunoextension.XRanter'を作成する。
UNOデータタイププロジェクトで、'source'ディレクトリ配下に、UNOIDLファイル、'unoIdl/thebiasplanet/uno/heyunoextensionsunoextension/XRanter.idl'を作成し、以下を書く。
// # Change the defined variable name START
#ifndef __thebiasplanet_uno_hiunoextensionsunoextension_XRanter_idl__
#define __thebiasplanet_uno_hiunoextensionsunoextension_XRanter_idl__
// # Change the defined variable name END
#include <com/sun/star/uno/XInterface.idl>
// # Add necessary idls START
#include <com/sun/star/lang/IllegalArgumentException.idl>
// # Add necessary idls END
// # Change the module name
module thebiasplanet { module uno { module heyunoextensionsunoextension {
// # Change the interface name and the parent interface
interface XRanter: com::sun::star::uno::XInterface
{
// # Add methods START
string rant ( [in] string p_name)
raises (com::sun::star::lang::IllegalArgumentException);
// # Add methods END
};
}; }; };
#endif
ふーむ、説明が必要なことは何もないようだ。
第2に、UNOインターフェース、'thebiasplanet.uno.heyunoextensionsunoextension.XHeyUnoExtensions'にメソッド、'getInnerRanter'を、以下のように追加する。
XRanter getInnerRanter ( [in] string p_message)
raises (com::sun::star::lang::IllegalArgumentException);
このメソッドは、第2のUNOインターフェース、'thebiasplanet.uno.heyunoextensionsunoextension.XRanter'のインスタンスを戻す。
第3に、UNOデータタイププロジェクトをビルドする。
オーケー。
第4に、UNO拡張機能プロジェクトで、第2のUNOコンポーネントのJavaソースファイル、'java/thebiasplanet/uno/heyunoextensionsunoextension/RanterUnoComponent.java'を作り、以下を書く。
// # Change the package name
package thebiasplanet.uno.heyunoextensionsunoextension;
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.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 RanterUnoComponent
extends WeakBase
implements XInitialization,
// # Specify the UNO interface to implement
XRanter {
private static final Class thisClass = new Object () { }.getClass ().getEnclosingClass ();
private XComponentContext componentContext = null;
// # Add member variables START
private String message = null;
// # Add member variables END
// # Change the class name
public RanterUnoComponent (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 rant (String p_name)
throws IllegalArgumentException {
if (p_name == null) {
throw new IllegalArgumentException ("The first argument can't be null.");
}
return String.format ("%s? No way! Go to hell, %s!", message, p_name);
}
// # Add methods of the implemented UNO interface END
// # Add other member methods START
// # Add other member methods END
}
ふーむ、このUNOコンポーネントは、UNOサービスとして登録されないので、'com.sun.star.lang.XServiceInfo'を実装せず、第1のUNOコンポーネントにあるコードの一部が必要でなくなった。
第5に、第1のUNOコンポーネントJavaソースファイル、'java/thebiasplanet/uno/heyunoextensionsunoextension/HeyUnoExtensionsUnoComponent.java'に以下のコードを追加してメソッド、'getInnerRanter'を追加する。
public XRanter getInnerRanter (String p_message)
throws IllegalArgumentException {
RanterUnoComponent l_innerRanter = new RanterUnoComponent (componentContext);
try {
l_innerRanter.initialize (new String [] {p_message});
}
catch (IllegalArgumentException l_exception) {
throw l_exception;
}
catch (com.sun.star.uno.Exception l_exception) {
}
return l_innerRanter;
}
ああ、このメソッドは、第2のUNOコンポーネントをnew演算子によってインスタンス化している。
そう。
第6に、UNOコンポーネント設定ファイルに以下のコードを追加して、第2のUNOコンポーネントを設定する。
<implementation name="thebiasplanet.uno.heyunoextensionsunoextension.RanterUnoComponent">
</implementation>
グローバルUNOサービスとして登録されないので、'service'タグが含まれていない。
これで、UNO拡張機能をビルドして登録できる。
変更をテストするために、先ほどのLibreOffice Basic Subの最後に以下のコードを追加する。
Dim l_ranter As Variant
l_ranter = l_heyUnoExtensionsService.getInnerRanter ("Good afternoon")
Msgbox (l_ranter.rant ("bro"))
うむ。Subは予期通り動作した。
こうして、UNOコンポーネントをUNOサービスとして登録せずに作成・利用する方法を我々は実証した。