dilluns, 8 de novembre del 2010

Com fer un component UNO amb java

El capítol clau del Developer's Guide (DG) és http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/WritingUNO/Writing_UNO_Components
En particular: http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/WritingUNO/Simple_Component_in_Java

El procés general queda descrit en aquesta esquema extret de JavaEclipse tutorial i que ja hem presentat en un post anterior


El que faré serà seguir aquest esquema aplicant-lo al codi d'exemple inclòs a l'SDK de l'OpenOffice.org.

Desenvoluparé aquest experiment sobre un Ubuntu 10.04 Lucid Lynx amb un OpenOffice.org 3.2.

En altres plataformes i versions les ubicacions poden ser diferents.

El codi d'exemple és el MinimalComponent que es troba a /opt/openoffice.org/basis3.2/sdk/examples/java/MinimalComponent/

El contingut de la carpeta és el següent:

BuildMinimalComponent.xml: un fitxer build d'ant per a generar el component. Lamentablement les ubicacions corresponen a les d'OpenOffice.org sobre Windows i cal corregir les adreces.

Makefile: un makefile per a generar el component fent servir el tradicional make.

MinimalComponent.idl: El primer pas per a crear un component és definir-ne la seva interfase. Tots els components han d'implementar certes interfases. El que es fa en l'exemple és crear un component que implementa una d'aquestes interfases obligatòries: la com/sun/star/lang/XServiceInfo.idl la qual proporciona mètodes que informen sobre les serveis que implementa el component.

Un component útil tindria una interfase específica que es definiria al fitxer .idl i, a més, també implementarà les interfases obligatòries (XServiceInfo, XInitialize i XTypeProvider).

El llenguatge de deficició de interfases idl de UNO, el UNOIDL, es descriu en el capítol del DG: http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/WritingUNO/Using_UNOIDL_to_Specify_New_Components.
També és interessant consultar http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/WritingUNO/Generating_Source_Code_from_UNOIDL_Definitions


MinimalComponent.java: La implementació del component. He dit abans que tots els components han d'implementar obligatòriament XServiceInfo, XInitialize i XTypeProvider. El que es fa en aquesta classe és heredar de WeakBase que ja implementa XTypeProvider, de forma que només resta per implementar XServiceinfo i XInitialize. WeakBase és una de les classes que es poden fer servir de base per a implementar components (Al DG les en diuen Helper Classes).

TestMinimalComponent.java: Finalment, una classe conductora per a provar  el component que hem creat. Hi trobem codi per a instanciar el nou component i executar-ne els mètodes de la seva interfase.

El que faré serà seguir pas a pas el diagrama. Així doncs, el primer de tot és compilar la descripció de la interfase. Això es fa amb la utilitat idlc (IDL compiler) de l'SDK de l'OpenOffice.org.

En el meu cas, he creat un projecte de java nou amb l'Eclipse i hi he copiat la carpeta MinimalComponent sencera.

Observant amb atenció l'esquema, s'observa que té dues entrades possibles.
- a partir del .idl
- a partir del .java


compilar .idl (especificació)

La primera cadena, a partir de l'idl,

Em situo en aquesta carpeta i invoco l'idlc tenint en compte que em caldrà incloure la definició (amb opció -I) de la XServiceInfo.

Això últim es fa evident sense més que examinar MinimalComponent.idl

#ifndef _org_openoffice_MinimalComponent_idl_ 
#define _org_openoffice_MinimalComponent_idl_ 


#include <com/sun/star/lang/XServiceInfo.idl> 


// org
module org {
    // openoffice
    module openoffice {
        // example service, XServiceInfo is implemented here for demonstration
        // issues. XServiceInfo must be implemented by all components. But
        // here it is used to show the new code generation feature for services.
        // See the TestMinimalComponent.java how it can be used!
        service MinimalComponent: ::com::sun::star::lang::XServiceInfo;
    };
};


#endif 


Per compilar l'idl, doncs, faig servir la següent instrucció

/opt/openoffice.org/basis3.2/sdk/bin/idlc -I /opt/openoffice.org/basis3.2/sdk/idl MinimalComponent.idl

El resultat és el fitxer MinimalComponent.urd  que hauria de contenir la definició del nou tipus descrit per la interfase. Cal incloure aquesta nova definició a un Registre de tipus per a que es pugui invocar i sigui utilitzable. (per a més detalls sobre el registre, consulteu  la DG, http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/WritingUNO/Running_and_Debugging_Java_Components)

Això ho faig amb el programa regmerge.

/opt/openoffice.org/ure/bin/regmerge MinimalComponent.rdb /UCR MinimalComponent.ure

Amb el que obtinc una base de dades de registre: el fitxer MinimalComponent.rdb.

Ara bé, si observem el contingut d'aquesta base de dades de registre amb l'eina regview /opt/openoffice.org/ure/bin/regview ./MinimalComponent.rdb (suposant que estic a la mateixa carpeta que el .rdb), obtinc:


/
 / UCR
   / org
     / openoffice
       / MinimalComponent
         Value: Type = RG_VALUETYPE_BINARY
                Size = 142
                Data = version: 1
                       documentation: ""
                       file name: ""
                       type class: service
                       type name: "org/openoffice/MinimalComponent"
                       super type count: 1
                       super type name 0: "com/sun/star/lang/XServiceInfo"
                       field count: 0
                       method count: 1
                       method 0:
                           documentation: ""
                           flags: synchronous
                           name: ""
                           return type name: "void"
                           parameter count: 0
                           exception count: 0
                       reference count: 0


       Value: Type = RG_VALUETYPE_BINARY
              Size = 57
              Data = version: 0
                     documentation: ""
                     file name: ""
                     type class: module
                     type name: "org/openoffice"
                     super type count: 0
                     field count: 0
                     method count: 0
                     reference count: 0


     Value: Type = RG_VALUETYPE_BINARY
            Size = 46
            Data = version: 0
                   documentation: ""
                   file name: ""
                   type class: module
                   type name: "org"
                   super type count: 0
                   field count: 0
                   method count: 0
                   reference count: 0




El pas següent és  invocar el javamaker per a obtindre els .class corresponents al nou servei (org.openoffice.MinimalComponent)

La sintaxi d'us de javamaker és:

/opt/openoffice.org/basis3.2/sdk/bin/javamaker -BUCR -Torg.openoffice.MinimalComponent -nD /opt/openoffice.org/ure/share/misc/types.rdb ./MinimalComponent.rdb

I obtinc la classe

org.openoffice.MinimalComponent

He d'afegir la classe al classpath per a compilar la MinimalComponent de la implementació (és dir, la classe que està en Default Package) que és el segon camí d'entrada descrit en l'esquema.


compilar .java (implementació)

En el cas del MinimalComponent.java  n'hi ha prou amb afegir org.openoffice.MinimalComponent al build, compilar i empaquetar amb jar, indicant en el manifest del META-INF que la classe a registrar és MinimalComponent, això ho aconseguiré amb el següent build.xml per a l'ant. És interessant remarcar quines són les llibreries utilitzades en el classpath (en negreta): les mateixes que per a compilar una macro java  i les d'addcionals,  officebean.jar i unoloader.jar.

<project name="ComponentUNO" default="jar" basedir=".">
  <description>
  genera el zip del component UNO per a l'OpenOffice
  </description>

  <!-- estableix propietats globals -->
  <property name="src" location="src"/>
  <property name="build" location="build"/>
  <property name="dist"  location="jar"/>
  <property name="zip.dir"  location="ComponentUNO"/>
  <property name="cp-java-OOo-1" location="/opt/openoffice.org/ure/share/java/" />
  <property name="cp-java-OOo-2" location="/opt/openoffice.org/basis3.2/program/classes/" />
  <property name="OOo-user-macros" location="/home/albert/.openoffice.org/3/user/Scripts/java/" />
  <property name="OOo-shared-macros" location="/opt/openoffice.org/basis3.2/share/Scripts/java/" />



  <target name="init">
    <!-- time stap -->
    <tstamp/>
    <!-- Crea el directory build utilitzat en la compilació -->
    <mkdir dir="${build}"/>
  </target>


  <target name="compile" depends="init" description="compila els fitxers font" >
    <!-- Compila les fonts java de ${src} en ${build} -->
    <javac srcdir="${src}" destdir="${build}">
      <classpath>
       <pathelement location="${cp-java-OOo-1}/juh.jar"/>
        <pathelement location="${cp-java-OOo-1}/jurt.jar"/>
       <pathelement location="${cp-java-OOo-1}/ridl.jar"/>
       <pathelement location="${cp-java-OOo-1}/unoloader.jar"/>
       <pathelement location="${cp-java-OOo-2}/unoil.jar"/>
       <pathelement location="${cp-java-OOo-2}/officebean.jar"/>
      </classpath>
   </javac>
  </target>




  <target name="jar" depends="compile" description="genera el jar">
    <!-- Crea el directori de distribució -->
    <mkdir dir="${dist}"/>


    <jar jarfile="${dist}/MinimalComponent.1.uno.jar" basedir="${build}"> 
      <include name="**/*.class"/>
      <manifest>
        <attribute name="RegistrationClassName" value="MinimalComponent"/>
      </manifest>
    </jar>
  </target>


</project>



En compilar amb ant, obtinc el jar MinimalComponent.1.one.jar
En aquest punt, ja tinc el component. Com provar-lo? Primer cal fer-ne el desplegament. Un cop desplegat, escriuré una macro amb OOoBasic que n'invoqui un mètode.

En aquest punt  deixaré de seguir l'esquema.

L'eina per a registrar components des de les primeres versions de l'OpenOffice.org ha estat regcomp. Tanmateix, aquesta eina ha estat superada per eines posteriors i des de fa algunes versions el que es pot fer servir és l'eina unopkg.

L'eina unopkg permet desplegar  components en java (.jar), en c++ (.so o .dll), add-ons (.oxt)...  A més, és una eina que es pot fer servir des de línia d'ordres, però també es pot usar com una GUI. De fet, la GUI que activa és la mateixa que la del gestor d'extensions  de l'OpenOffice.org. El capítol de la DG que parla d'això és el de les Extensions.

Per tant,  executo '/opt/openoffice.org3/program/unopkg gui' i puc registrar el meu component fàcilment. Recordar que el path fins unopkg '/opt/openoffice.org3/program/' pot ser un de diferent a altres versions  d'Ubuntu i d'OpenOffice.org.

Se m'obre el gestor d'extensions on puc veure les extensions que tinc instal·lades:


Faig click a "Afegeix..."


Trio el tipus de fitxer  "Component Java UNO"


Obro i el meu component queda instal·lat


Si el vull desinstal·lar, puc fer-ho des del mateix gestor d'extensions.

Finalment, per acabar, provaré que el nou component es utilitzable. Creo una petita macro que l'invoca. 
Primer de tot engego l'OpenOffice.org, vaig a l'editor de macros. La macro que escric utilitza la popular  XrayTool per analitzar l'objecte UNO que he creat. A continuació invoco el mètode getImplementationName().

Sub Main
    provaComponentUNO
End Sub

sub provaComponentUNO
    Dim oMinimal as Object

    BasicLibraries.loadLibrary("XrayTool")

oMinimal = CreateUnoService("org.openoffice.MinimalComponent")
xray oMinimal
msgbox oMinimal.getImplementationName()
end sub

A  MinimalComponent.java trobem l'explicació de l'argument de CreateUnoService:

public class MinimalComponent {
    /** This class implements the component. At least the interfaces XServiceInfo,
     * XTypeProvider, and XInitialization should be provided by the service.
     */
    public static class _MinimalComponent extends WeakBase
        implements XInitialization, XServiceInfo {
        /** The service name, that must be used to get an instance of this service.
         */
        static private final String __serviceName =
        "org.openoffice.MinimalComponent";


El resultat de l'execució és:


i, finalment:



Albert Baranguer
Barcelona, 08/11/2010

Cap comentari:

Publica un comentari a l'entrada