OpenOffice.org, meglio conosciuto semplicemente come Open Office o anche "OOo", è la nota suite di programmi per l'ufficio open source e cross-platform. Pochi sanno che Open Office è anche una piattaforma di servizi invocabili da remoto grazie ai quali poter creare applicazioni ad hoc ed offrire servizi automatizzati per la manipolazione di documenti elettronici.
Per fare ciò, OOo mette a disposizione un SDK per l'estensione del prodotto mediante l'innesto di nuovi componenti, e la tecnologia Universal Network Objects (UNO), per certi versi simile a COM e CORBA, che consente di sfruttare da remoto i servizi messi a disposizione dagli applicativi della suite.
In questo articolo esamineremo le principali caratteristiche di UNO di OOo e delle API per Java. Dopo aver discusso le basi del modello di interazione, si forniranno degli snippet di codice per un approccio pratico ai servizi.
UNO: Universal Network Objects
Come abbiamo detto UNO è il Component Model di OOo e funge da interfaccia tra diversi linguaggi di programmazione, come Java, e gli oggetti di OpenOffice. Quindi mette a disposizione tutte le classi necessarie a trattare i tipi di dato e le relative operazioni.
Le principali caratteristiche di UNO sono:
- interfaccia unificata di accesso: i servizi di OOo sono mappati da un framework accessibile da diversi linguaggi di programmazione
- accesso agli oggetti da remoto, mediante l'utilizzo di opportune tecniche di interazione con oggetti remoti (network objects) messe a disposizione dallo strato middleware implementato dallo stesso strato UNO
L'architettura di UNO è basata principalmente su un Runtime Environment (RE), che prende il nome di URE, nel quale si svolge il ciclo di vita di ognuna delle componenti; le componenti di OOo sono a loro volta definite mediante l'UNOIDL (UNO Interface Development Language) che è un linguaggio generico (non è vincolato nella sintassi ad alcun linguaggio di programmazione particolare) di descrizione delle interfacce dei servizi. Grazie a UNOIDL è possibile generare delle implementazioni dei componenti (oggetti, ad es., nel caso banale di assenza di livelli di nesting nell'IDL di definizione) definiti nei linguaggi di programmazione desiderati (i tipici in OOo sono C++, Java e Python).
Lo scopo principale dello strato UNO è quello di realizzare componenti indipendenti ed interoperanti (a partire dalla compilazione dell'UNOIDL), e di fornirle all'utilizzatore finale anche in codizioni come:
- linguaggi di programmazione differenti
- architetture di calcolatori differenti
- domini di rete differenti
- tecnologie impiegate per l'implementazione delle componenti differenti
I punti di sopra si traducono in interoperabilità rispetto ai linguaggi di programmazione e in trasparenza rispetto alla locazione dei processi che rispettivamente istanziano e richiedono gli oggetti di servizio di OOo.
Un esempio di queste due caratteristiche è la capacità di poter sviluppare add-in per uno degli applicativi di OOo in un linguaggio di macro-scripting come star basic (nativamente disponibile nella suite OOo), e richiamare da remoto il componente a cui è stato aggiunto l'add-in mediante l'interfaccia di UNO.
I singoli applicativi di Open Office, in effetti, possono essere visti come un'insieme di componenti di UNO. Quindi tutto ciò che può essere utilizzato grazie all'interfaccia grafica, può essere utilizzato anche dai nostri applicativi in modo automatico.
Il paradigma di comunicazione impiegato da UNO è la classica architettura client/server basata su TCP/IP. In particolare, OOo possiede un proprio protocollo di comunicazione denominato UNO Remote Protocol (URP) che è per certi versi simile/comparabile al protocollo definito da CORBA, ed è per altri versi più performante di quest'ultimo.
Lo strato UNO esporta al programmatore i propri servizi di accesso alle componenti che, di fatto, realizzano complessivamente OOo; l'esportazione avviene mediante uno strato di API che può essere acceduto sia da Java, che da C++, Javascript e altri linguaggi di scripting, come Visual Basic.
A partire dalla pagina seguente, esamineremo le caratteristiche dell'interazione con UNO tramite Java.
Context e Service Manager
L'interfaccia del servizio che si intende invocare consente di effettuare una query al Service Manager che, a seconda del Context a runtime, restituisce l'oggetto UNO di servizio (UNO service object) desiderato. Lo scopo principale del Service Manager è quello di fungere da factory per gli oggetti di servizio, a seguito dell'invocazione mediante interfaccia.
Una volta ottenuto un 'service object', è possibile invocare le sue funzionalità e costruire l'automazione per creare o manipolare un documento. Mediante URP è quindi possibile, lato client, lavorare con un surrogato dell'oggetto di servizio che vive in URE lato server e che, mediante l'URL appositamente fornitagli, ottiene il documento su cui effettuare l'elaborazione richiesta lato client. I surrogati degli oggetti di servizio sono detti desktop service object e sono forniti proprio dall'istanza locale di service manager.
Client e server possono risiedere anche sulla stessa macchina, questo accade ad esempio nel normale utilizzo di OOo, mediante interfaccia grafica. Il client per identificare e connettersi all'istanza di server usa un opportuno resolver.
Per ottenere il service manager, e quindi la factory dei service object, è necessario avviare un'istanza di URE. Pertanto sono necessarie le fasi preliminari di start-up e bootstrapping per usare i servizi forniti dallo strato UNO. Chiariremo questo passaggio più avanti, grazie ad alcuni snippet di codice.
Manipolazione di Documenti di testo: le principali Interfacce
Un documento di testo è tipicamente inteso come il risultato del lavoro di un utente, che scrive un certo contenuto, con una certa formattazione, ed immagazzinato il tutto in un file serializzato su disco.
Per OOo un documento di testo è rappresentato da un Document Model, che ci permette di agire sul testo a prescindere dalla resa o dalla visualizzazione finale (grazie all' interfaccia XTextDocument
, metodo getText()
, otteniamo un service object XText
)
Il document model di OOo è quindi un'entità utile ad astrarre e quindi gestire/manipolare i metadati (dati che descrivono altri dati, nella fattispecie contenuto testuale) di un documento di testo.
Una volta dispobibile il testo e il relativo Document Model, possiamo utilizzare il Controller (interfaccia XModel
, servizio getCurrentController()
, restituisce un service object XController
), che ci consente di navigare il documento e di individuare pagine, sezioni, sottosezioni, paragrafi, elenchi, immagini e tabelle.
Il document model è 'consapevole' del proprio controller e può, mediante quest'ultimo, bloccare le interazioni dell'utente. Il controller, tra l'altro, è utilizzato dalla suite per presentare i contenuti nella versione GUI (Graphical User Interface) degli applicativi.
Mediante il controller è possibile ottenere particolari oggetti, denominati cursor, che a loro volta consentono di lavorare con un dato grado di specializzazione rispetto alle parti del documento. Il principale servizio svolto dai cursor consta nel far sì che il programmatore possa navigare il documento di testo automaticamente (mediante apposito codice scritto), alla stregua di quanto egli stesso potrebbe fare navigando il documento manualmente. Tra l'altro, di rilevante importanza è il fatto che mediante l'uso dei cursor è possibile selezionare la parte di documento desiderata per poterla poi modificare secondo le esigenze del caso.
Document Model
Il Document Model di OOo è di importanza fondamentale per il Document Text Service Manager, da non confondere con quello, discusso in precedenza, che ci consente di creare un contesto OOo a partire da una connessione ad un'istanza avviata dello stesso Open Office.
Il service manager in questione consente di creare, a partire da un Document Model, il contenuto testuale del documento. Come accennato in precedenza, possiamo possiamo creare o aggiungere al nostro testo diversi elementi:
- Tabelle
- Oggetti grafici
- Frame della pagina
- Contenuto di testo
- Semplice
- Formattato con elenchi puntati e numerati
- Formattato con direttive di stile
Tutti i contenuti precedentemente elencati, così come possono essere creati, possono anche essere recuperati dal document model per poi essere modificati, utilizzando gli opportuni Text Suppliers che illustreremo brevemente nella prossima tabella.
Invece, la Figura 3, nella pagina precedente, mostra il servizio Text dell'omonima componente di OOo che mette a disposizione le interfacce XText
(di lavoro rispetto al contenuto del corpo del documento) e XEnumerationAccess
(di lavoro rispetto al contenuto del corpo del testo rappresentato come una lista/enumerazione di elementi).
Su di un document model è possibile definire una serie di Document Aspects che rappresentano altrettanti aspetti operativi del documento: stampa, modifica, memorizzazione e così via.
Nella tabella vediamo le categorie (definite per aree di competenza rispetto al 'contenitore' e 'fornitore' document model) di "servizi" che possono essere utilizzati/invocati mediante API di OOo su di un document model, al fine di modificare dati e testo.
Categorie di Servizi | Descrizione | |
---|---|---|
Interfacce di Rilievo | Ruolo | |
Controller & View Data |
ViewCursor LayoutCursor |
Consentire l'interazione automatizzata: il programmatore può scorrere il testo sino al punto desiderato e apportare le desiderate modifiche. |
Styles & Layout | XStyleFamiliesSupllier |
Consente l'accesso alle varie famiglie di stili (intese come insieme di attributi) del documento di testo: 1) CharacterStyles, 2) ParagraphStyles, 3)FrameStyles, 4) PageStyles e 5) NumberingStyles. |
Draw Page | XDrawPageSupplier |
Consentire l'accesso ai contenuti del documento, in quanto supplier, e fornire la capacità di accedere, ridefinire e creare degli oggetti di tipo Shapes (figure/form che si possono disegnare nel documento di testo mediante l'apposita barra nella GUI di OOo) all'interno del corpo del document model. |
Outline & Line Numbering |
XChapterNumberingSupplier XLineNumberingProperties |
Consentire l'accesso diretto agli attributi di stile che consentono di definire la strutturazione del documento di testo in capitoli, sezioni, sottosezioni, paragrafi, etc. |
Document Aspects |
XPrintable |
Consentire in maniera efficace l'accesso ad aspetti operativi del document model, quali, ad es., la possibilità di memorizzare su disco il documento serializzato, la possibilità di chiudere l'istanza della service factory che mantiene l'istanza del documento, la possibilità di stampare il documento aperto, etc. Gli aspetti operativi variano a seconda delle tipologia di documento: un documento di OOo Draw non ha gli stessi aspetti operativi di un documento di OOo Writer. |
Text Content Suppliers |
XTextTablesSupplier |
Consentire l'accesso come semplici liste di elementi a tutti i contenuti di un testo: l'accesso ad una data tabella sarà fornito, trasparentemente, come accesso all'elemento della lista che mantiene le tabelle del document model. |
I concetti espressi in questo paragrafo saranno chiariti dall'esempio che tratteremo nella seconda parte dell'articolo, grazie ad un esempio concreto di manipolazione di un documento di testo.
Un esempio concreto di utilizzo di OOo API
Attraverso UNO è possibile accedere a qualunque servizio di qualunque componente, pertanto è possibile sfruttare in maniera automatizzata qualsiasi applicativo della suite. Ciò si traduce nella possibilità di operare su qualsiasi tipo di documento attraverso codice Java.
Spesso, in contesti reali, è richiesto di realizzare automaticamente dei documenti che rispettino determinati template ma che contengano dati dinamici, ad esempio informazioni inserite da un utente Web.
Altra esigenza reale è quella di manipolare dei documenti preesistenti, magari generati con altri software come MS Office. Questo accade soprattutto quando c'è necessità di far interoperare sistemi documentali diversi. In questi casi è importante che ciascun contesto mantenga il proprio standard per i documenti, pur consentendo la lettura e la trasformazione di dati e testi nello standard reciproco.
Per i nostri esempi utilizzeremo OpenOffice Writer, il programma di videoscrittura della suite, per compiere le operazioni più importanti in modo automatico:
- aprire un documento
- modificare il testo
- impostare i margini secondo uno standard predefinito
- esportare il documento in PDF e HTML
- chiudere il documento insieme all'istanza di Writer
Passi preliminari
Per poter sfruttare le API di UNO è necessario installare Open Office sulla propria macchina e referenziare quattro JAR messi a disposizione dell'installazione stessa:
juh.jar
jurt.jar
ridl.jar
unoil.jar
Nella versione 2 di OpenOffice i file si trovano al percorso:
<ooo_installation_path>/openoffice.org2.x/program/classes
Nella versione 3 l'organizzazione delle cartelle cambia leggermente e i primi tre file JAR si possono trovare in:
<ooo_installation_path>/openoffice.org3/ure/java
mentre il quarto al percorso:
<ooo_installation_path>/openoffice.org/basis3.0/program/classes
L'ultima operazione di configurazione è l'impostazione del classpath, che dovrà includere la directory:
<ooo_installation_path>/openoffice.org/program
dove ci sono gli eseguibili necessari per avviare l'istanza di OpenOffice da codice Java. Se dimentichiamo quest'ultimo passo, gli esempi che scriveremo produrranno l'errore "no office executable found".
La connessione ad un'istanza di OOo
La fase di start-up e bootstrapping di un'istanza di swriter di OOo è caratterizzata dai seguenti passi:
- richiedere la fase di bootstrap di URE
- creare un contesto locale di URE
- creare il service manager o factory dal contesto ottenuto al passo 2
- recuperare mediante il desktop service l'interfaccia desktop interface object affinché, mediante quest'ultima, sia possibile richiedere un component loader
- recuperare il component loader grazie alle operazioni del passo 4
- utilizzare il component loader per avviare un'istanza del word processor component
l'ultimo passo della sequenza sarà esplicitamente trattato nel prossimo paragrafo, per ora l'obiettivo è descrivere le fasi che vanno dai passi 1 a 3 che realizzano la connessione ad un'istanza di OOo.
Listato 1: connessione ad un'istanza di OOo
// recupera l'oggetto remoto context
// effettua il bootstrap di UNO Runtime Environment
XComponentContext context = Bootstrap.bootstrap();
System.out.println("Trying to connect to OOo service... ");
// recupera il service manager
XMultiComponentFactory factory = context.getServiceManager();
String available = (factory != null ? "available" : "not available");
System.out.println("… the service is '" +available +"'! ");
// avvia (start-up) un'istanza di Open Office
Object desktop = factory.createInstanceWithContext(
"com.sun.star.frame.Desktop",
context);
Nel listato vediamo i primi tre passi della fase di bootstrap del runtime di UNO, seguita dal recupero del contesto locale che consente l'avvio di un'istanza di Open Office e quindi della relativa fase di start-up.
Oltre alla modalità di connessione appena vista, ne esiste un'altra che assume un'istanza di Open Office avviata e raggiungibile mediante la rete: questa modalità richiede che l'istanza di Open Office sia avviata in modalità listening con particolari parametri che specifichino la possibilità di accettare richieste remote, provenienti da altre macchine della rete. Per approdonfire questa modalità è possibile consultare la Developer Guide di Open Office.
Aprire un file .doc
Con la fase di start-up abbiamo ottenuto un'istanza di OpenOffice, che possiamo ora utilizzare per caricare un documento. Per farlo ci serviremo dell'URL del documento, come vediamo nel prossimo listato, che completa la procedura vista in precedenza, realizzando i passi 4, 5 e 6.
Listato 2: caricamento di una risorsa mediante URL
// recupera l'oggetto service XDesktop interface
XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class, desktop);
// recupera l'oggetto service interface XComponentLoader
XComponentLoader loader = (XComponentLoader) UnoRuntime.queryInterface(
XComponentLoader.class,
xDesktop);
// URL della risorsa da aprire con swriter
String doc_url = "file:///"
+ "C:/Users/Paolo Maresca/Documents/JWorkspace/Intro_OOo_APIs/docs/"
+ "test.doc";
// dichiarazione dei filtri di importazione del documento
// Ms Word 97 (formato *.doc) avviene mediante service object
// di tipo property
PropertyValue[] properties = new PropertyValue[1];
properties[0] = new PropertyValue();
properties[0].Name = "FilterName";
properties[0].Value = "MS Word 97";
// recupera l'oggetto document da UNO runtime environment
// mediante il loader precedentemente acquisito
XComponent document = loader.loadComponentFromURL(doc_url, "_blank", 0, properties);
Otteniamo prima un'implementazione dell'interfaccia XDesktop
, poi il servizio XComponentLoader
che ci consente di aprire un documento preesistente. Specifichiamo quindi l'URL e il fatto che ci aspettiamo un documento in formato "MS Word 97"
, per farlo ci serviamo dell'apposito filtro di importazione.
Modificare il testo
Possiamo apportare automaticamente qualunque tipo di modifica ai documenti, al costo ovviamente di un sforzo di programmazione crescente al crescere della difficoltà della manipolazione desiderata.
Nel prossimo listato vediamo come modificare il carattere usato nel documento, in termini di dimensioni (ad es. 10 punti) e famiglia (ad es., Arial).
Listato 3: operazioni di modifica del corpo del testo
// recupera il service object che rappresenta il documento
XTextDocument text_document = (XTextDocument) UnoRuntime.queryInterface(
XTextDocument.class,
document);
// preleva il testo del documento
XText text = text_document.getText();
// sul testo richiede un cursore
XTextRange xTextRange = text.createTextCursor();
// spostamento del cursore alla fine del testo
// procedendo contestualmente anche ad una selezione
((XTextCursor) xTextRange).gotoEnd(true);
// recupera un oggetto service in grado di accedere alle
// proprietà del testo ed alla loro descrizione
XPropertySet xTextProps = (XPropertySet) UnoRuntime.queryInterface(
XPropertySet.class,
xTextRange);
// per il testo selezionato imposta un carattere con corpo 10
// di tipo Arial
xTextProps.setPropertyValue("CharFontName", "Arial");
xTextProps.setPropertyValue("CharHeight", new Float(10));
Il cursore
Nel codice viene introdotta un'entità fondamentale per la manipolazione automatizzata dei documenti con OOo: il cursore. L'oggetto cursore consente di scorrere il documento, con granularità variabile del passo (il numero di caratteri per passo è arbitrario), in tutta la sua interezza e apportare le modifiche desiderate nella posizione desiderata. L'azione è simile all'operazione che l'utente compie col mouse quando seleziona parte/i o tutto il documento.
Nell'esempio proposto, la necessità primaria è quella di selezionare tutto il testo del documento per effettuare il cambio nello stile e nella dimensione del carattere, ed è per questo che il cursore, posizionato inizialmente di default all'inizio del documento, è pilotato automaticamente sino alla fine del documento selezionando così l'intero insieme di caratteri. Semplice è la modifica da effettuare, una volta selezionato il testo, dal momento che essa richiede una semplice impostazione di due property predefinite con i valori desiderati.
Impostare Margini e Orientamento della pagina
Nel prossimo listato, a partire dal documento caricato, vediamo come indicare uno standard per i margini e l'orientamento delle pagine.
Nel nostro esempio, tra l'altro, impostiamo l'orientamento orizzontale (landscape) per tutte le pagine del documento. Un'esigenza più verosimile potrebbe essere quella di ruotare selettivamente solo alcune pagine, cosa che potremmo realizzare semplicemente scandendo le pagine con dei cursori e modificando le proprietà di orientamento (Paper Orientation) solo dove serve.
Listato 4: impostazione dei margini e dell'orientamento
// aggiunge funzionalità di stampa alla risorsa
// precedentemente aperta
XPrintable xPrintable = (XPrintable) UnoRuntime.queryInterface(
XPrintable.class,
document);
// dichiarazione di un'array di property di due elementi:
// 1. un elemento per definire l'orientamento delle pagine;
// 2. un secondo elemento per definire il formato delle pagine.
PropertyValue[] printerDesc = new PropertyValue[2];
// property che definisce l'orientamento LANDSCAPE per le
// pagine del documento aperto ed in fase di manipolazione
printerDesc[0] = new PropertyValue();
printerDesc[0].Name = "PaperOrientation";
printerDesc[0].Value = PaperOrientation.LANDSCAPE;
// property che definisce il formato dei margini delle
// pagine del documento aperto ed in fase di manipolazione
printerDesc[1] = new PropertyValue();
printerDesc[1].Name = "PaperFormat";
printerDesc[1].Value = PaperFormat.A3;
// impostazione del formato di pagina
xPrintable.setPrinter(printerDesc);
Esportare e salvare il documento in diversi formati
OpenOffice.org ci permette di esportare il documento in diversi formati standard, come il PDF. Questo è uno dei più grossi vantaggi Di OOo rispetto a MS Office che, per salvare un documento in PDF, richiede l'installazione di un plug-in.
Nel prossimo listato vediamo come esportare il nostro documento nel formato ODT e in PDF. Anche questa volta basterà semplicemente impostare i valori delle apposite property per i filtri.
Listato 5: esportare il documento in ODT e in PDF
// definisce l'URL della risorsa da esportare
String storeUrl = "file:///"
+ "C:/Users/PaoloMaresca/Documents/JWorkspace/Intro_OOo_APIs/docs/modified/"
+ "OOo_doc.odt";
// recupera un oggetto service che consente di effettuare
// il salvataggio della risorsa a partire da una URL
XStorable xStorable = (XStorable)UnoRuntime.queryInterface(
XStorable.class,
document);
// dichiarazione delle proprietà per l'esportazione in ODT
PropertyValue[] storeProps = new PropertyValue[1];
storeProps[0] = new PropertyValue();
storeProps[0].Name = "FilterName";
storeProps[0].Value = "OpenDocument Text"
// esportazione in ODT
xStorable.storeAsURL(storeUrl, storeProps);
storeUrl = "file:///"
+"C:/Users/PaoloMaresca/Documents/JWorkspace/Test/docs/modified/"
+"OOo_doc.pdf";
// dichiarazione delle proprietà per l'esportazione in PDF
storeProps = new PropertyValue();
storeProps[0].Name = "FilterName";
storeProps[0].Value = "writer_pdf_Export";
// esportazione in PDF
xStorable.storeToURL(storeUrl, storeProps);
Come si evince dal listato, c'è una differenza tra i servizi storeAsURL() e storeToURL().
- Il metodo
storeAsURL
lavora corrisponde al salva come di OOo, quindi scrive un file all'URL specificato. Possiamo poi continuare ad utilizzare l'oggetto di servizio istanziato per modificare i dati del nuovo file. - Il metodo
storeToURL
, invece, corrisponde alla funzione Esporta di OOo, quindi salva il nuovo file, ma non ci permette di modificarlo: il servizio continua a fare riferimento all'URL originale. Questo accade anche perché il filtro utilizza un formato non accessibile in modifica a OOo.
Chiudere il documento
Il prossimo listato effettua automaticamente le operazioni che ognuno di noi fa quando ha terminato di lavorare al suo documento, ovvero: a seguito del salvataggio, chiusura del documento e dell'istanza dell'applicativo che lo deteneva.
Listato 6: chiusura del documento originario e dell'istanza di Open Office che lo detiene
// recupera un oggetto service che rappresenta la risorsa
// (documento) precedentemente aperta a partire da un URL
XModel xModel = (XModel)UnoRuntime.queryInterface(XModel.class, document);
// recupera un oggetto service in grado di rilasciare il documeto
// precedentemente aperto e rappresentato dal model
XCloseable xCloseable = (XCloseable)UnoRuntime.queryInterface(
XCloseable.class,
xModel);
// tenta il rilascio definitivo della risorsa, se possibile, altri-
// menti, recupera un service object che rompe le referenze cicliche
// e chiude la risorsa
if(xCloseable != null)
{
xCloseable.close();
}else
{
XComponent xComp =(XComponent)UnoRuntime.queryInterface(
XComponent.class,
xStorable);
xComp.dispose();
}
Il codice mette in risalto una peculiarità della gestione di OOo dei documenti/oggetti mediante conteggio dei riferimenti alle istanze.
Ogni implementazione di UNO RE definisce ed implementa le proprie specifiche rispetto al ciclo di vita degli oggetti. La specifica UNO gestisce il ciclo di vita degli oggetti mediante meccanismi di reference counting (conteggio dei riferimenti all'istanza), così come avviene per la tecnologia COM di Microsoft.
L'implementazione Java di UNO gestisce, a differenza di quella C++, il ciclo di vita degli oggetti mediante Garbage Collection di Java stesso, in particolare le acquire()
(incrementa di uno il contatore dei riferimenti all'istanza) e release()
(decrementa di uno il contatore dei riferimenti all'istanza) su di un oggetto sono implicitamente gestite dalla chiamata UnoRuntime.queryInterface(…)
necessaria ad ottenere l'istanza dell'oggetto desiderato.
Nonostante le peculiarità dei vari RE, è necessario che l'implementazione delle specifiche renda coerente la semantica di gestione del meccanismo dei riferimenti, affinché quest'ultima sia interoperabile e trasparente alle implementazioni.
Premesso ciò, senza scendere eccessivamente nei dettagli (che troviamo nel manuale ufficiale di OOo), è necessario osservare che nella fase di chiusura di un documento acquisito mediante UNO è necessario controllare che il documento non sia più 'riferito' da altri oggetti, altrimenti il programma non sarà in grado di chiudere l'istanza del documento.
Ciò può verificarsi all'occorrenza di riferimenti ciclici (l'oggetto A ha un riferimento all'oggetto B, e l'oggetto B al suo interno un riferimento diretto o indiretto all'oggetto A) che impediscono il meccanismo di distruzione, provocando così dei memory leak. La prossima tabella mostra questa problematica e la soluzione fornita da UNO.
Tabella 2.1: illustrazione di una tipica situazione in cui si verifica un riferimento ciclico tra l’oggetto A e l’oggetto B. | Tabella 2.2: soluzione alla problematica dei riferimenti ciclici mediante l’uso dell’interfaccia XComponente che è in grado di gestire le richieste di dispose da parte dell’oggetto C (riferito dall’oggetto A mediante B), e le successive notifiche. |
In Java, in realtà, il problema dei riferimenti ciclici è risolto nativamente dalla Garbage Collection; il limite della Garbage Collection, nel contesto d'utilizzo di OOo API, si sente quando gli oggetti che si referenziano ciclicamente risiedono in JVM differenti. Per ovviare a questo tipo di circostanze, che se non opportunamente gestite comportano il lock permanente della risorsa a livello di sistema, c'è la possibilità di usare un apposita interfaccia XComponent
che consente la chiusura del documento, nonostante quest'ultimo sia ancora riferito. Invocando direttamente su XComponent
il metodo dispose()
, il riferimento ciclico decadrà immediatamente ed il documento che si desidera chiudere verrà immediatamente chiuso, a dispetto di quanto sarebbe fatto nel normale ciclo di vita gestito dalla Garbage Collection.
Conclusioni
L'architettura di UNO consente l'accesso alle componenti di OOo in maniera sistematica, indipendentemente dal linguaggio di programmazione. Attraverso il runtime di UNO è possibile avere l'accesso a tutte le funzionalità di automazione d'ufficio messe a disposizione dalla suite OOo. Oltre alle semplici operazioni di manipolazione mostrate, esistono una molteplicità di altre possibilità, a partire anche da template di altre suite.
Grazie ad UNO, quindi, la suite OpenOffice.org nel complesso può essere integrata in sistemi di gestione documentale.
OOo può essere esteso mediante SDK e linguaggi di scripting, pertanto è possibile estendere le componenti della suite desiderate con funzionalità custom e richiamare queste ultime, una volta integrate a dovere, mediante UNO direttamente dalla propria applicazione.
Riferimenti
- The OpenOffice.org Documentation Project
- Getting started using openoffice in java
- Understanding UNO
- UNO
- Luis Botterelli, OpenOffice (3.0) / UNO API
- Raveesh Rajappan, OpenOffice.org UNO API
- Uche Ogbuji, Thinking XML: The open office file format