API Training

Embed Size (px)

Citation preview

Inhaltsverzeichnis

1 Einleitung und Vorbereitung4

1.1 Ziel dieses Dokuments4

1.2 Das StarOffice Software Development Kit (SDK)4

2 Programmieren mit UNO6

2.1 Was ist UNO?6

2.2 Interfaces7

2.3 Die UNO Interface Definition Language (IDL)9

2.4 Services11

2.5 Typen in UNO16

Interfaces16

Elementare Typen 17

Der Datentyp type17

Der Datentyp any17

Der Datentyp sequence17

Enumerationen (enum) und Constant Groups18

Strukturierte Datentypen (struct)19

Exceptions in UNO19

Services20

Properties20

2.6 UNO in den verschiedenen Programmiersprachen21

3 StarOffice Programmierung in Java26

3.1 Allgemeines26

3.2 Besonderheiten des Java UNO Language Bindings28

Abbildung elementarer UNO-Datentypen28

Abbildung des UNO-Typs string29

Abbildung des UNO-Typs type29

Abbildung von UNO-Enumerationstypen29

Abbildung von UNO Constant Groups (constants)29

Abbildung von UNO struct-Typen30

Abbildung von UNO sequence 30

Abbildung von UNO exception30

Abbildung von UNO-Interface Typen31

Abbildung des UNO-Typs any32

Abbildung von UNO-Services33

4 StarOffice-Programmierung in C++34

4.1 Allgemeines34

4.2 Besonderheiten des C++ UNO Language Bindings37

Abbildung elementarer UNO-Datentypen37

Abbildung des UNO-Datentyps string37

Abbildung des UNO-Typs type37

Abbildung von UNO Constant Groups (constants) und UNO-Enumerationstypen38

Abbildung von UNO struct-Typen38

Abbildung von UNO sequence 38

Abbildung des UNO-Typs any39

Abbildung von UNO-Interface Typen41

Abbildung von UNO-Services42

Exception handling in C++ UNO42

5 StarOffice Basic und UNO43

5.1 Allgemeines43

5.2 Besonderheiten der Basic-Sprachanbindung44

Benutzung von UNO-Objekten in Basic44

Abbildung von numerischen UNO Typen46

Abbildung von UNO sequence47

Abbildung von UNO struct Typen49

Abbildung von UNO-Enumerationstypen und Constant Groups49

Typsichere Parameterbergabe in Basic50

Exception Handling in Basic51

7 Spezielle Aspekte der UNO-Programmierung52

7.1 Lebensdauer von UNO-Objekten52

7.2 WEAK References ?!54

7.3 Arbeiten mit Dokumenten54

Erzeugen von Dokumenten55

Der MediaDescriptor56

Speichern von Dokumenten60

Drucken von Dokumenten62

Schlieen von Dokumenten63

7.4 StarOffice Application Framework API65

Frames65

StarOffice Component Framework67

Der Desktop Service71

7.5 Ereignisse (Events), Listener und Broadcaster73

7.6 Listener in Basic74

7.7 Dokumentereignisse74

7.8 Event Bindings77

7.9 Dokumenteigenschaften (Metadaten)79

8 Textdokumente83

8.1 Arbeiten mit Textdokumenten83

Text, TextRanges und Cursor83

Textinhalte84

Einfgen oder Lschen von Abstzen an speziellen, schwer erreichbaren Positionen85

Formatierung85

Navigation87

8.2 Tabellen88

Tabellenarchitektur88

Benannte Tabellenzellen, Spalten und der TableCursor90

Zugriff auf bereits existierende Tabellen91

8.3 Weitere Aspekte von Textdokumenten91

Feldbefehle91

Zugriff auf existierende Feldbefehle92

AutoText92

8.4 Weitere Programmierbeispiele93

Beispiel Absatz, Vorlagen setzen, Text einfgen93

Beispiel - TextCursor94

Beispiel Text in Tabellenzelle einfgen94

Beispiel fr Feldbefehle95

9 Entwicklung von UNO-Komponenten96

9.1 Was macht eine UNO-Komponente aus?96

9.2 Entwicklung von UNO-Komponenten96

TODO:

Muteces

Was muss ich beachten, wenn ich UNO-Objekte implementiere/Benutze?

Wann sollte ich UNO-Objekte benutzen, Vor/Nachteile

Einleitung und VorbereitungZiel dieses Dokuments

Die Programmierung mit UNO und StarOffice ist sehr ausfhrlich im StarOffice 8 Developers Guide beschrieben, der zusammen mit der Referenzdokumentation des StarOffice API und der Java UNO Runtime Library Bestandteil der Dokumentation im StarOffice Software Development Kit (SDK) ist. Weitere Dokumentation zu diversen Fragen der UNO-Programmierung und des StarOffice API finden sich auf den Projektseiten der UDK- und API-Projekte von Openoffice.org unter http://udk.openoffice.org und http://api.openoffice.org. Insbesondere sind die dazugehrigen Mailing-Listen [email protected] und [email protected] zu empfehlen, wo man in einen direkten Kontakt mit anderen Entwicklern, speziell auch den StarOffice/OpenOffice.org-Entwicklern treten kann.

Der Developers Guide ist sehr umfangreich, da er weite Teile der StarOffice-Programmierung abdeckt und sie z.T. auch technisch sehr detailliert beschreibt. Er beschreibt auch detailliert alle Details der vorhandenen Sprachanbindungen und wie man eigene implementiert, geht also weit ber das hinaus, was man im Rahmen einer Einfhrung behandeln mchte. Nichtsdestotrotz ist er die primre Referenz fr alle Entwickler, die schon etwas Erfahrung mit der StarOffice-Programmierung gemacht haben und die UNOIDL-Referenz zu benutzen gelernt haben.

Die UNOIDL-Referenz enthlt die Deklaration des kompletten StarOffice-API zusammen mit meist sehr ausfhrlicher Dokumentation der einzelnen Methoden. Sie ist der beste Weg, sich die Funktionalitt der StarOffice-Komponenten systematisch zu erschlieen.

Das Ziel der vorliegenden Einfhrung ist es, die grundlegenden Kenntnisse der StarOffice-Programmierung zu vermitteln und den Leser in die Lage zu versetzen, sich weitergehende Informationen aus den oben genannten Quellen besorgen zu knnen. Sie konzentriert sich dabei auf die Sprachen StarOffice Basic und Java, auch wenn C++ hin und wieder erwhnt wird.

Das StarOffice Software Development Kit (SDK)

Das SDK, ergnzt um ein GNU make, enthlt alles, was ein Java oder C++-Programmierer bentigt, um Komponenten fr oder Programme mit StarOffice zu entwickeln. Java-Entwickler werden in der Regel eine IDE benutzen und vom SDK nur die Dokumentation einbinden, daher soll in dieser Einfhrung das direkte Arbeiten mit dem SDK nicht weiter erlutert, sondern nur die einzelnen Bestandteile aufgefhrt und kurz beschrieben werden.

Das Root-Verzeichnis des SDK enthlt neben Scripts und Batchdateien zur Konfiguration (fr die, die damit direkt programmieren wollen) einen Lizenztext und mit der Datei index.html einen Einstieg in die komplette Dokumentation, die im SDK im Unterverzeichnis doc abgelegt ist. In dessen Unterverzeichnissen befinden sich, jeweils ber index.html verlinkt:

die komplette Referenzdokumentation des StarOffice Dateiformats im Unterverzeichnis common/spec im PDF-Format;

die komplette API-Referenzdokumentation im HTML-Format im Unterverzeichnis common/ref;

die komplette Referenzdokumentation der Java UNO Runtime Environment Klassen im HTML-Format im Unterverzeichnis java;

die komplette Referenzdokumentation der C++ UNO Runtime Environment Klassen im HTML-Format im Unterverzeichnis cpp;

den kompletten StarOffice8 Developers Guide sowohl im HTML-Format als auch im PDF-Format im Unterverzeichnis DevelopersGuide;

eine kurze Beschreibung der Entwicklungswerkzeuge im HTML-Format in der Datei tools.html.

Im Unterverzeichnis idl befindet sich das komplette StarOffice8 API in Form von UNOIDL-Dateien. Diese werden aber nur von C++-Entwicklern zur Generierung von Header-Dateien bentigt, die dort enthaltene Dokumentation befindet sich in wesentlich besser lesbarer Form in den daraus generierten HTML-Dateien im Verzeichnis docs/common/ref.

Im Verzeichnis include befinden sich alle C++-Headerdateien der C++ UNO Runtime Libraries, dazu kommt noch mindestens ein (plattformabhngiges) Verzeichnis mit den dazugehrigen Bibliotheken und den SDK-Tools (also z.B. ein Verzeichnis windows mit den Unterverzeichnissen lib und bin). In diesem Verzeichnis landen auch die beim direkten Arbeiten mit dem SDK erzeugten Binaries.

Das Verzeichnis examples enthlt lauffhige Programmierbeispiele fr StarOffice Basic, Java, C++, CLI (C#, VB.NET) und OLE Automation (Delphi, VB Script, C++). Weiterhin befinden sich dort alle Beispiele aus dem Developers Guide.

Die Verzeichnisse classes enthlt ein paar Java-Klassen, die fr das Simple Bootstrapping (also die komfortabelste Art, sich mit einem StarOffice-Prozess zu verbinden) bentigt wird. Wie diese eingebunden werden, ist abhngig von der verwendeten IDE.

Die Dateien im Unterverzeichnis xml werden nur fr interne Zwecke verwendet.

Programmieren mit UNOWas ist UNO?

UNO ist zunchst eine Technologie, die die Interoperabilitt von Objekten ermglicht, vergleichbar mit hnlichen Technologien wie CORBA, (D)COM oder .NET. Ohne eine solche Middleware knnen Objekte nur zusammenarbeiten, wenn sie innerhalb einer gemeinsamen Applikation existieren und in den allermeisten Fllen auch nur dann, wenn sie mit der gleichen Programmiersprache implementiert sind und so die zur Kommunikation notwendigen Informationen auf Quellcode-Ebene austauschen knnen (Header Files etc.).

Mit einer Technologie wie UNO knnen Objekte auch dann zusammenarbeiten, wenn sie in unterschiedlichen Programmiersprachen implementiert sind oder in verschiedenen Applikationen (Prozessen) existieren, ja sogar wenn sie auf verschiedenen Rechnern laufen, sofern diese Rechner ber eine geeignete Verbindung kommunizieren knnen (UNO verwendet dafr TCP/IP).

UNO erreicht das, indem es die Kommunikation der Objekte untereinander auf binrer Ebene standardisiert und klar definierte Regeln aufstellt, wie diese standardisierte Kommunikation auf die verschiedenen Programmiersprachen, Compiler und Systeme abgebildet (bersetzt) wird. Auerdem liefert UNO auch die entsprechenden Abbildungen (Bindings) fr eine Reihe von Kombinationen dieser drei Faktoren (als Beispiel: C++ mit gcc unter Linux).

Wichtig zu wissen ist weiterhin, dass ein Objekt, das ber UNO mit einem anderen Objekt zusammenarbeitet, prinzipiell nicht nur nicht wei, in welchem Prozess oder auf welchem Rechner dieses luft, sondern auch von diesem Objekt nur eine externe Schnittstelle sieht, aber nichts darber wei, wie diese intern realisiert wurde. Dies ist quasi die Weiterentwicklung des Prinzips der Trennung von Implementierung und Schnittstelle, die ja ansonsten auf Quellcode-Ebene angewendet wird. Dieses Prinzip zusammen mit der garantierten Stabilitt von Schnittstellen und der Sprachunabhngigkeit sind die Essenz von UNO.

Die Schnittstelle eines Objekts, sein Application Programming Interface (API) wird blicherweise durch seine Methoden (Funktionen) und Properties (Eigenschaften) beschrieben, Begriffe, die so oder in hnlicher Form nicht nur aus objektorientierten Programmiersprachen, sondern auch aus objektbasierten wie Visual Basic und StarOffice Basic bekannt sind. UNO fasst allerdings zustzlich Methoden zu sogenannten Interfaces zusammen, was im nchsten Kapitel erlutert wird. Die Schnittstelle eines Objekts ist dann gegeben durch die Summe aller untersttzten Interfaces und Properties.

Die Rolle von UNO wird vielleicht klarer, wenn man sich Objekte als Bausteine vorstellt, die nach auen eine Kontaktstelle aufweisen, ber die man durch das Senden von Signalen innerhalb der Bausteine bestimmte Funktionen auslsen kann. Die Summe aller vom Objekt verstandenen Kommandos, die man ber diesen Kontakt senden kann (seine Methoden), ergnzt um die Summe aller Zustnde, die man darber abfragen oder setzen kann (seine Properties), bildet seine Schnittstelle. Intern benutzt ein solcher Baustein eine bestimmte Implementierungssprache, um auf ein ber seine Kontaktstelle eintreffendes Kommando hin Aktionen auszufhren. So kann ein Baustein intern optische Signalverarbeitung benutzen, ein anderer akustische.

Damit ein Baustein eintreffende Kommandos auch versteht, mssen diese eine definierte bertragungsform verwenden, und jeder Baustein bentigt ein bersetzungsmodul, das die in dieser definierten Form bertragenen Kommandos in eine fr die Implementierungssprache verstndliche Form berfhrt. Das gleiche Modul bersetzt auch Kommandos, die der Baustein an andere sendet, in diese definierte Form, in der die Kommandos dann zu dem bersetzungsmodul des Zielbausteins bertragen und dort verarbeitet werden knnen. So kann beispielsweise die Informationsbertragung durch elektrische Signalverarbeitung erfolgen, und ein Baustein, der intern mit einer akustischen Signalverarbeitung arbeitet, wrde dann einen Akustikkoppler bentigen.

UNO ist hierbei das Medium, das nicht nur die Bausteine als Kabel miteinander verbindet, sondern auch die bertragungssprache definiert und die bersetzungsmodule von Implementierungssprache zu bertragungssprache und zurck zur Verfgung stellt. Natrlich verwendet UNO dabei eine andere Terminologie, die im Folgenden noch erlutert wird:

Beispiel

UNO

Baustein

Objekt

Kommandos und Zustnde

Interfaces, Properties

Befehlssatz

Schnittstelle (API)

bertragungsform

UNO Interface Definition Language (IDL)

Technologie des internen Aufbaus

Programmiersprache der Implementierung

Ausfhrung von Aktionen

Ausfhrung von Programmcode

Kabelverbindung

UNO Runtime und UNO Protokoll

bersetzungsmodul

UNO Language Binding

Der Begriff Objekt bedarf noch einer etwas nheren Erluterung. Er ist nicht deckungsgleich mit dem, was ein C++ - oder Javaprogrammierer als Objekt kennt. Er bezeichnet zunchst nur die Auensicht auf eine Softwareeinheit, wie deren innere Organisation aussieht, ist damit nicht festgelegt. Es ist durchaus mglich, dass ein UNO-Objekt intern durch mehrere C++ oder Javaobjekte implementiert ist. Dem Entwickler, der das UNO-Objekt benutzt kann das aber egal sein, er spricht das Objekt nur ber seine definierte Schnittstelle an, das Objekt ist dann einfach die gesamte Implementierung, die sich hinter dieser verbirgt.

Nachdem wir bis jetzt definiert haben, wie UNO solche Objekte behandelt, macht es vielleicht mehr Sinn, den Spie umzudrehen und zu sagen, dass ein UNO-Objekt eine in ihren Ausmaen nicht nher beschriebene Einheit ist, von der andere Objekte nur eine definierte Schnittstelle wie oben beschrieben sehen.

Programmierer knnen UNO einerseits verwenden, um eigene Anwendungen zu schreiben, die UNO-Objekte benutzen, sie knnen aber andererseits auch selbst UNO-Objekte implementieren, die dann wiederum von ihren oder anderen Anwendungen benutzt werden knnen. Auch StarOffice selbst ist eine solche Anwendung, die zunchst nur die eigenen UNO-Objekte benutzt, aber auch definierte Mglichkeiten bietet, durch Einbinden von als externe Komponente bereitgestellten UNO-Objekten die eigene Funktionalitt zu erweitern oder zu verndern. UNO-Schnittstellen sind also gewissermaen aktiv und passiv nutzbar, ersteres, indem man Objekte einbindet, letzteres indem man vordefinierte Schnittstellen implementiert und sich so einbinden lsst. Diese beiden Anwendungsflle werden uns spter noch beschftigen.

Interfaces

Wie schon erwhnt gruppiert UNO (ebenso wie COM) die Methoden eines Objekts zustzlich zu sog. Interfaces. Das Interface ist ein Konzept, das einem Java Programmierer unter genau diesem Namen bekannt sein drfte, ein C++-Entwickler kennt es als rein abstrakte Basisklasse. Im technischen Sinne ist ein Interface einfach eine Sammlung von Methoden, die derart in einem sinnvollen Zusammenhang miteinander stehen, dass es nach Meinung des Autors dieser Methoden keinen Sinn macht, in einem Objekt nur eine dieser Methoden zu implementieren, sondern im Regelfall alle. Man sagt dann nicht, das Objekt X bietet die Methoden a,b und c an sondern das Objekt X implementiert das Interface Y, das die Methoden a,b und c umfat. Ein einfaches Beispiel dafr ist ein Objekt, das es erlaubt, andere Objekte als sog. Listener anzumelden, die dann ber bestimmte Ereignisse in dem ersten Objekt informiert werden werden knnen. Es macht berhaupt keinen Sinn, nur eine Methode zum Anmelden anzubieten, man bentigt auch automatisch eine zum Abmelden. Daher wird das Objekt ein entsprechendes Interface anbieten, das diese beiden Methoden umfat.

Im bertragenen Sinne kann ein Interface als ein spezieller Aspekt eines Objekts gesehen werden, das Ergebnis einer klassifizierenden Betrachtungsweise. Ein Objekt kann mehrere solche Aspekte aufweisen, so wie in der realen Welt z.B. eine menschliche Person die Aspekte Frau, Lehrer und Deutschsprachig aufweisen kann. Jedes dieser Interfaces ermglicht es, das gesamte Objekt jeweils nur unter dem dadurch reprsentierten Teilaspekt zu sehen und anzusprechen, wodurch einerseits weitere, hier nicht interessierende Aspekte des Objekts ausgeblendet werden knnen, andererseits andere Objekte, die das gleiche Interface aufweisen, identisch behandelt werden knnen, auch wenn sie ansonsten ganz andere Interfaces haben. Ein mnnlicher, deutschsprachiger Maurer kann also mit identischen Algorithmen behandelt werden wie die deutschsprachige Lehrerin, sofern diese nur das Deutsch-Interface ansprechen, also z.B. in einem Programm, das die Personen in deutscher Grammatik oder Rechtschreibung testet.

Weiterhin wird dieses Programm auch dann immer noch funktionieren, wenn die Lehrerin spter dann auch noch zur Schachspielerin wird, da dieses neue Interface ebenso irrelevant fr den Test ist wie z.B. das bereits frher bekannte Lehrer-Interface. UNO-Objekte knnen also spter neue Interfaces hinzufgen, ohne dass Programme, die die Objekte benutzen, ihre Funktion einben.

Dies gilt natrlich nicht, wenn bei einem UNO-Objekt einmal garantierte Interfaces entfernt oder die Interfaces selbst gendert werden. Solche nderungen betreffen Rckgabewerte und Parameter, aber auch die definierte Art und Weise, wie die einzelnen Methoden im Fehlerfall reagieren.

Es ist aber ein Ziel von UNO, dass Anwendungen, die UNO-Objekte verwenden, ohne nderung funktionsfhig bleiben, auch wenn die Objektimplementierungen durch neuere Versionen ausgetauscht oder stark verndert werden. Daher definiert das UNO-Konzept eine Reihe von Regeln, wie mit Interfaces umgegangen werden darf.

Zunchst unterscheidet UNO zwischen published und unpublished Interfaces.

Fr erstere garantieren die Entwickler, dass die Interfaces in Zukunft nicht mehr verndert werden. Eine Applikation, die UNO-Objekte nur ber solche Interfaces anspricht, mu also in Zukunft weder neu kompiliert noch gendert werden, selbst wenn die Implementierungen hinter den Interfaces komplett ausgetauscht oder massiv verndert werden.

Fr Interfaces der zweiten Art gibt es diese Garantie nicht. Sie knnen natrlich trotzdem auch in Anwendungen verwendet werden, allerdings besteht ein gewisses Risiko, dass es in nchster Zeit (typischerweise bis zum nchsten Major Release von StarOffice) noch ein paar nderungen geben kann, die dann den Anwendungsentwickler zwingen, seine Anwendung entweder neu zu kompilieren oder sogar seinen Code an nderungen im Interface anzupassen.

Das ndern von published Interfaces ist also ein schwerwiegender Programmierfehler, das gilt aber auch fr das Entfernen von garantierten Interfaces aus der Schnittstelle eines Objekts, da der Anwendungsentwickler sich ja darauf verlt, dass das verwendete Objekt dieses untersttzt. Dies wre im obigen Beispiel das deutschsprachig Interface. Ein solches Interface ist dann ein garantiertes Interface (aus Sicht des Objekts: notwendig, mandatory).

Das erwhnte Schachspieler-Interface ist ein nicht garantiertes (aus Sicht des Objekts: optionales) Interface. Das Hinzufgen solcher Interfaces zu der Schnittstelle eines Objekts oder das ihr Entfernen daraus ist erlaubt, da Anwendungsentwickler sich nicht darauf verlassen drfen, dass das Interface untersttzt wird. Falls sie ein optionales Interface dennoch benutzen wollen, mssen sie zur Laufzeit die Existenz dieses Interface in der Schnittstelle berprfen (wofr UNO entsprechende Mittel bereitstellt, die von der jeweils in der Anwendung verwendeten Programmiersprache abhngen).

Welche Interfaces eines Objekts garantiert sind und welche nicht, ist ebenso Bestandteil der Schnittstelle dieses Objekts wie die Definition der Interfaces selbst. Aus dem deklarierten API kann der Anwendungsprogrammierer ganz genau entnehmen, welche Teile davon absolut verlsslich sind und welche nicht. Diese Thematik wird im Kapitel ber Services behandelt.

Vor StarOffice 8 erstellte Interfaces waren immer automatisch published im Sinne der obigen Beschreibung, ohne dass sie explizit so bezeichnet wurden. Erst ab StarOffice 8 wird diese Unterscheidung vorgenommen, wobei natrlich alle bis dahin existierenden Interfaces als published bernommen wurden. Man sollte daher immer die Dokumentation des StarOffice 8 SDK verwenden, um diesbezgliche Verwirrungen zu vermeiden.

Der Basic-Programmierer muss sich (wie noch gezeigt wird) auf der Ebene seines Codes hufig gar nicht mit Interfaces befassen. Trotzdem mssen Basic-Programmierer das Konzept verstehen, damit sie die Referenzdokumentation des StarOffice API lesen und benutzen knnen, denn diese basiert auf den Interfaces.

PUBLISHED/UNPUBLISHED: klarer

Die UNO Interface Definition Language (IDL)

Interfaces von UNO-Objekten werden in einer Beschreibungssprache formuliert, der Interface Definition Language (IDL). Deren Syntax hnelt der objektorientierter Programmiersprachen wie Java oder C++ und enthlt elementare (int, string, bool etc.) und strukturierte Datentypen, Konstanten, Ableitungen etc. Da sie sich nur mit der Beschreibung von Schnittstellen beschftigt, enthlt sie nur die dafr bentigten Sprachelemente, aber keine Elemente, die man zum Schreiben von Programmen bentigt (wie z.B. Control Statements).

Die Definition eines Interface in dieser abstrakten, programmiersprachenunabhngigen Form knnte dann, auf das Wesentliche reduziert, wie folgt aussehen:

module com { module sun { module star { module frame {// (1)

published interface XLoadable: com::sun::star::uno::XInterface// (2)


{


void initNew()// (3)

raises( DoubleInitializationException, // (4)

com::sun::star::io::IOException,

com::sun::star::uno::Exception );

void load( [in] sequence lArguments )// (5)

raises( DoubleInitializationException,

com::sun::star::io::IOException,

com::sun::star::uno::Exception );

};

}; }; }; };

Dieses Interface definiert Funktionalitt, mit der ein Objekt wahlweise in einen definierten Initialisierungszustand gebracht oder aus einer nicht nher spezifizierten Quelle geladen werden kann. Ein Anwendungsbeispiel dafr wre ein Dokument, das entweder mit Datei-Neu oder mit Datei-ffnen erzeugt werden kann. Einer Konvention folgend haben alle Interface-Namen als ersten Buchstaben ein X (im Gegensatz zu allen anderen Typen der UNOIDL).

Die mit Nummern in Kommentaren markierten Zeilen weisen Merkmale auf, die grundlegende Konzepte der UNOIDL benutzen. Diese werden im Folgenden erlutert:

UNOIDL verwendet das Konzept der name spaces (die hier als modules bezeichnet werden), das C++ oder Javaentwicklern bekannt ist (letzteren als packages), dem Basicprogrammierer aber eher fremd sein drfte. Die Motivation fr dieses Konzept ist, dass man in einem prinzipiell offenen System wie UNO die Namen von Interfaces nicht zentral vergeben kann, zufllige Namensbereinstimmungen aber vermeiden muss, da Namen von Interfaces wie die aller anderen Symbole natrlich eindeutig sein mssen.

Durch die Verlngerung der Namen mit name spaces soll dies erreicht werden. So kann ein Interface MyInterface sowohl im name space module1 als auch im name space module2 existieren, module1.MyInterface und module2.MyInterface sind verschiedene Symbole.

Natrlich ist durch die bloe Verwendung von name spaces die Eindeutigkeit noch nicht garantiert, schlielich knnen Namensbereinstimmungen auch innerhalb der name spaces auftreten. Innerhalb einer geschlossenen Gruppe von Entwicklern sollte es kein Problem sein, die Verwendung der name spaces und Symbolnamen zu kontrollieren, aber UNO ist wie erwhnt prinzipiell offen, daher kann man nicht von einer geschlossenen Gruppe ausgehen. So wird ergnzend die Konvention benutzt, dass die verwendeten name spaces durch einen Prfix erweitert werden, der eine jeweils hinreichend geschlossene Gruppe von Entwicklern kennzeichnet, innerhalb derer dann eine Kontrolle sichergestellt werden kann. Die Vergabe des Prfix erfolgt dabei hnlich der von Internet Domains, d.h. die Namen der entwickelnden Organisation oder Firma ist ein Teil davon. com.sun.star ist dabei z.B. fr UNOIDL - Symbole reserviert, die von der Firma Sun fr StarOffice definiert wurden. Eine Firma foo, die fr ein Projekt bar Symbole definieren will, sollte dann com.foo.bar als Prfix verwenden.

Nach dem Prfix folgt dann das Package (die logische Gruppe), zu der das Symbol gehrt. So gibt es unterhalb der Hierarchie com.sun.star beispielsweise die Packages frame und text fr Symbole aus dem Framework oder der Textverarbeitung.

Das definierte Interface ist published, d.h. es ist ffentlich zugesichert und darf sich daher in Zukunft nicht mehr ndern, damit alle Programme, die es benutzen, auch in Zukunft ohne Neukompilationen oder gar Code-nderungen funktionieren knnen, so wie oben beschrieben. Fehlt das Wort published, handelt es sich um ein Interface, das sich evtl. in nchster Zeit noch etwas ndern kann. Man kann es verwenden, muss aber damit rechnen, dass man bis zum nchsten StarOffice Release noch Code-nderungen vornehmen muss.

Weiterhin sieht man, dass in dieser Zeile hinter dem so definierten Interface noch der Name eines weiteren Interface steht. Diese Schreibweise kennzeichnet eine Ableitung, wieder ein Konzept, dass C++ und Javaprogrammierern bekannt ist, dem Basicprogrammierer aber eher nicht. Durch die Ableitung von einem anderen Interface erbt ein Interface alle Methoden des letzteren (auch als Basis-Interface bezeichnet), d.h. dessen Methoden gehren auch zu denen des abgeleiteten Interface. In unserem Beispiel hat also das Interface com::sun::star::frame::XLoadable neben den zwei oben definierten Methoden noch die des Interface com::sun::star::uno::XInterface (mehr zu diesem Interface spter). Ab StarOffice 8 sind auch Mehrfachableitungen mglich, d.h. ein Interface kann mehrere Basis-Interfaces haben.

Diese Zeile definiert eine Methode. Der Rckgabewert ist hier void (in Basic also: kein Rckgabewert), aber natrlich sind im allgemeinen auch andere Datentypen mglich, sowohl Basistypen wie string oder int, aber auch zusammengesetzte Typen oder Interfaces. Mehr zu den UNO-Datentypen findet sich in einem spteren Kapitel.

Dieser Teil gehrt mit zur Definition der Methode, er definiert die mglichen Exceptions, die ein C++ oder Javaprogrammierer von einem Objekt, das dieses Interface implementiert, beim Aufruf dieser Methode im Fehlerfalle erwarten muss. Damit ist schon gesagt: UNO verwendet Exceptions um Fehler zu melden, keine Error Codes. Viele Programmiersprachen wie Java und C++ haben eine direkte Untersttzung dafr, die UNO nutzen kann. In anderen Fllen, wo das nicht mglich ist, wie im Basic, mssen Exceptions von der UNO Runtime Library fr die jeweilige Sprache behandelt werden. In StarOffice Basic beispielsweise werden alle Exceptions grundstzlich vom Interpreter gefangen und in eine interne Fehlerbehandlung umgesetzt. Auch Exceptions sind UNO-Datentypen, die spter noch erlutert werden.

Die folgenden Zeilen definieren eine weitere Methode, diesmal eine, die Parameter empfngt. Unterschieden wird dabei zwischen reinen Eingabe , Ausgabe sowie Ein/Ausgabe-Parametern, jeweils durch ein [in], [out] oder [inout] gekennzeichnet. Der bergebene Parameter hier ist vom Typ sequence, also ein Array-Parameter. Wie der auf die jeweilige Programmiersprache abgebildet wird, wird spter beschrieben.

NAMEN knnen spter nicht gendert werden, sinnvolle und schne verwenden!

Jede einzelne solcher in der IDL dokumentierten Einheiten wird in UNO als Typ (type) bezeichnet. Ein Typ kann also z.B. ein bestimmter struct oder ein bestimmtes Interface sein. Mehr zu den wichtigsten Typen spter.

Die IDL-Dateien aller in StarOffice verwendeten Typen sind Bestandteil des StarOffice Software Development Kit (SDK). Das SDK enthlt auch Werkzeuge, um aus diesen Dateien verschiedene andere Dateien zu erzeugen, die man fr die Benutzung der Typen in den verschiedenen Programmiersprachen, aber auch in UNO selbst (Typinformationen) bentigt. Welche Dateien das im einzelnen sind, hngt natrlich von der verwendeten Sprache ab.

Services

Die UNOIDL kennt im Gegensatz zu Java oder C++ keine Klassen und Objekte, stattdessen neben den Interfaces auch das Konzept der Services. Die Idee dahinter ist, dass es Kombinationen von Interfaces gibt, die in bestimmten Zusammenhngen hufig benutzt werden. Diese Kombination stellt dann einen service dar, der auch in UNOIDL als UNO-Typ deklariert wird:

module com { module sun { module star { module document {

published service OfficeDocument

{

interface com::sun::star::frame::XModel;

interface com::sun::star::util::XModifiable;

interface com::sun::star::frame::XStorable;

interface com::sun::star::view::XPrintable;

[optional] interface com::sun::star::frame::XLoadable;

[optional] interface XEventBroadcaster;

[optional] interface XEventsSupplier;

[optional] interface XDocumentInfoSupplier;

[optional] interface XViewDataSupplier;

[optional] interface com::sun::star::view::XPrintJobBroadcaster;

[property, optional] boolean AutomaticControlFocus;

[property, optional] boolean ApplyFormDesignMode;

[property, optional, readonly] string RuntimeUID;

};

}; }; }; };

Ein derart deklarierter Service ist zunchst einmal etwas sehr abstraktes, er fasst mehrere Aspekte eines Objekts zu einem neuen, bergeordneten zusammen, der Aspekt Officedokument also die Aspekte Model, Storable, Modifiable, Printable. Jeder Aspekt fr sich kann in einem bestimmten Zusammenhang ausreichend sein, um mit dem Objekt zu arbeiten, z.B. wird sich ein Print Server nur fr den Aspekt Printable interessieren, es gibt aber offensichtlich genug Anwendungsflle, wo alle genannten Aspekte zusammen bentigt werden. Genauso wie bei Interfaces sagt man: Das Objekt O implementiert den Service S. Ein Objekt kann aber prinzipiell nicht nur mehrere Interfaces, sondern auch mehrere Services implementieren.

Der Service com::sun::star::document::OfficeDocument enthlt 4 garantierte Interfaces und 5 optionale. Des weiteren enthlt er drei (optionale) Properties. Der Zugriff auf Properties ist abhngig von der verwendeten Programmiersprache und wird im Kapitel ber Typen in UNO sowie in denen zu den einzelnen Programmiersprachen erlutert.

Wenn man sieht, welche Elemente optional sind und welche nicht, findet man nicht immer eine einleuchtende Begrndung. Das ist auch nicht verwunderlich, denn in vielen Fllen (so auch hier) ist das eine historische gewachsene Deklaration. So ist es durchaus sinnvoll, den Support fr Dokument Events Bindings (XEventsSupplier) und Metadaten (XDocumentInfoSupplier) optional zu deklarieren, da das sehr einschrnkend wre, dies von allen denkbaren Dokumenten zu verlangen. Optional meint hier, dass die Untersttzung dieses Interface in einem Objekt, das den Service implementiert, unter Umstnden sinnvoll, aber nicht zwingend erforderlich ist, es hat also eine semantische Motivation.

Der Support fr das XLoadable Interface ist aber nur deshalb optional, weil zum Zeitpunkt des ursprnglichen Entwurfs dieses Service ein entsprechendes Interface noch nicht existierte und das Laden eines Dokuments ber ein Hilfsobjekt vorgenommen wurde. Mittlerweile existiert nun ein Interface, mit dem man das Laden direkt am Dokument veranlassen kann, ein Hinzufgen dieses Interface als nicht-optionales wrde aber dazu fhren, dass Code, der diesen Service und dieses Interface benutzt, nur in der neueren Version von StarOffice, nicht aber in einer lteren funktioniert, obwohl die Dokumentation das Gegenteil suggeriert (denn auch die ltere Version liefert einen solchen Service, nur fehlt dem dann das Interface!).

Das sieht anders aus, wenn das hinzugefgte Interface als optional deklariert wird. Wenn ein Programmierer dieses Interface an einem Objekt benutzen will, muss er erst das Objekt fragen, ob es das Interface untersttzt, und wenn das Objekt das verneint, andere Wege beschreiten. Dieser Code funktioniert natrlich auch mit der lteren Version. Optional meint hier, dass es ltere Implementierungen dieses Service geben kann, die das Interface nicht untersttzen, es hat also mehr eine versionierende Motivation.

Eine andere Methode, Services um neue Interfaces zu erweitern, ist es, weitere Services zu definieren, die den zu erweiternden mit enthalten, sowie zustzlich die gewnschten Interfaces. Dadurch, dass dieser Service einen neuen Namen erhlt, sind alle Anforderungen bezglich Kompatibilitt erfllt: ein solcher Service existiert nicht in der lteren StarOffice-Version, der Programmierer muss also zunchst versuchen, den neuen Service zu bekommen und im Nicht-Erfolgsfall mit dem alten vorlieb nehmen. Die Service-Deklaration wrde etwas so aussehen:

module com { module sun { module star { module document {

published service OfficeDocument2

{

service OfficeDocument;

interface com::sun::star::frame::XLoadable;

};

}; }; }; };

Wie man sieht, wird hier nicht wie bei Interfaces Ableitung verwendet, sondern der Basis-Service wird als Bestandteil (member) des erweiterten deklariert. Ein Service, der einen anderen enthlt, untersttzt dann auch dessen Methoden und Properties, zustzlich dazu alle Methoden der hinzugefgten Interfaces und alle hinzugefgten Properties. Man darf hier auch nicht auf irgendeine Implementationsvererbung schlieen, lediglich die Spezifikationen der beiden Services werden hier zusammengefasst. (Anmerkung: der Service OfficeDocument2 ist im Gegensatz zu den anderen hier gezeigten Beispielen hypothetisch und existiert nicht.)

Aber nicht nur zu diesem Zweck kann man Services als Teil von anderen Services deklarieren, das Einbetten von Services in andere dient meistens der Spezialisierung: aus einem relativ generischen Service (hier: OfficeDocument) wird durch zustzliche Funktionalitt eine bestimmte Ausprgung geschaffen. Ein Beispiel ist der Service, der die Dokumente von StarOffice Calc charakterisiert:

module com { module sun { module star { module sheet {

published service SpreadsheetDocument

{

service com::sun::star::document::OfficeDocument;

interface com::sun::star::lang::XMultiServiceFactory;

interface com::sun::star::frame::XModel;

interface com::sun::star::document::XActionLockable;

interface com::sun::star::document::XLinkTargetSupplier;

interface com::sun::star::util::XProtectable;

interface com::sun::star::sheet::XSpreadsheetDocument;

interface com::sun::star::sheet::XCalculatable;

interface com::sun::star::sheet::XDocumentAuditing;

interface com::sun::star::sheet::XConsolidatable;

interface com::sun::star::sheet::XGoalSeek;

interface com::sun::star::drawing::XDrawPagesSupplier;

interface com::sun::star::style::XStyleFamiliesSupplier;

interface com::sun::star::util::XNumberFormatsSupplier;

[readonly, property] com::sun::star::sheet::XNamedRanges NamedRanges;

[readonly, property] com::sun::star::sheet::XDatabaseRanges DatabaseRanges;

[readonly, property] com::sun::star::sheet::XLabelRanges ColumnLabelRanges;

[readonly, property] com::sun::star::sheet::XLabelRanges RowLabelRanges;

[readonly, property] com::sun::star::container::XNameAccess SheetLinks;

[readonly, property] com::sun::star::sheet::XAreaLinks AreaLinks;

[readonly, property] com::sun::star::container::XNameAccess DDELinks;

};

}; }; }; };

Analoge Services gibt es natrlich auch fr die anderen Dokumenttypen von StarOffice wie z.B. com::sun::star::text::TextDocument fr Writer-Dokumente.

Das Wesen von Services und insbesondere ihre Beziehung zu Objekten wird verstndlicher, wenn man sich ansieht, wie ein Programmierer Zugriff auf sie erhlt.

UNO bietet dem Programmierer einen sog. Service Manager an. Dies ist ein UNO-Objekt, ber dessen Interface com::sun::star::lang::XMultiServiceFactory man andere UNO-Services erzeugen kann. Dafr mssen diese sich vorher auf irgendeine Art und Weise dem Service Manager bekannt gemacht haben, z.B. durch Erzeugen von Eintrgen in einer Service Registry beim Installieren einer UNO-Komponente. Fr die Zusammenarbeit mit der Service Registry (Registrierung) und dem Service Manager (Instantiierung) implementiert ein solcher Service das Interface com::sun::star::lang::XServiceInfo, das spter noch nher erlutert wird.

module com { module sun { module star { module lang {

published interface XMultiServiceFactory: com::sun::star::uno::XInterface

{

com::sun::star::uno::XInterface createInstance( [in] string aServiceSpecifier )

raises( com::sun::star::uno::Exception );

com::sun::star::uno::XInterface createInstanceWithArguments(

[in] string ServiceSpecifier,

[in] sequence Arguments )

raises( com::sun::star::uno::Exception );

sequence getAvailableServiceNames();

};

}; }; }; };

Die Methode createInstance erzeugt das gewnschte Objekt und gibt eine Referenz auf ein Interfaces dieses Objekts zurck (wie das in den verschiedenen Programmiersprachen aussieht, wird im nchsten Kapitel erlutert). Damit das fr jedes beliebige Objekt funktioniert, gleich welche Interfaces dieses implementiert, muss es also ein Basis-Interface geben, das alle Objekte implementieren, nmlich com::sun::star::uno::XInterface, wie am Rckgabewert der Methode createInstance zu sehen. Fr UNO wurde die Entscheidung getroffen, dieses dadurch sicherzustellen, indem einfach alle Interfaces von com::sun::star::uno::XInterface abgeleitet werden. Dies kann man an beiden bisher gezeigten Interface-Beispielen sehen. Beginnend mit dem SDK fr StarOffice 8 muss man diese Ableitung nicht mehr explizit in die IDL-Datei schreiben, die Ableitung wird einfach automatisch ergnzt, wenn mit Hilfe der SDK-Tools die Typinformation und die sprachabhngigen Dateien erzeugt werden.

Eine weitere Methode im Interface com::sun::star::lang::XMultiServiceFactory ist createInstanceWithArguments, die es erlaubt, dem Objekt bei der Erzeugung noch ein paar Parameter mitzugeben, die hier als sequence bergeben werden. Was es damit auf sich hat, wird spter erlutert.

Die dritte Methode schlielich ist getAvailableServiceNames. Wie leicht zu erraten erhlt man durch sie eine Liste aller Service-Namen, fr die man von diesem Service Manager ein Objekt erhalten kann.

Am Prinzip des Service Managers zeigt sich auch das eigentliche und wesentliche Element des Service-Konzepts: wenn ein Programmierer ein Objekt mit bestimmter Funktionalitt benutzen will, instantiiert er dafr dann nicht eine konkrete Implementierung (wie er es tte, wenn er ein Java oder C++ - Objekt erzeugen wrde), sondern einen Service, der ihm die gewnschte Funktionalitt garantiert. Natrlich versteckt sich dahinter dann auch eine konkrete Implementierung, diese kann aber prinzipiell gendert oder ausgetauscht werden, ohne dass der Programmierer das wissen mte. Wenn fr einen Service spter einmal eine neue, bessere Implementierung zur Verfgung steht, mu diese nur am Service Manager registriert werden, damit alle Anwendungen diese automatisch nutzen knnen. Im Falle der direkten C++ oder Java-Programmierung mten die Anwendungen dafr gendert werden.

Wie man an den Service Manager selbst kommt, hngt davon ab, welche Programmiersprache man benutzt und wie der eigene Code aufgerufen wird:

Ein UNO-Objekt bekommt ihn bei seiner Konstruktion bergeben

Eine UNO basierte Anwendung, die zwar UNO-Objekte benutzt, aber selbst keines ist, erzeugt ihn bei der notwendigen UNO-Initialisierung (Bootstrapping)

In manchen Programmiersprachen (z.B. Basic) ist er Teil des Runtime Environments.

Vom Service Manager erhlt man ein Objekt, das den gewnschten Service implementiert, indem man seine Methode createInstance aufruft und dabei den Service Name bergibt (Beispiele dafr folgen spter).

Der Service com::sun::star::sheet::SpreadSheetDocument ist ein solcher Service, nicht aber der Service com::sun::star::document::OfficeDocument. Dieser ist vielmehr ein abstrakter Service, der nur eine Gruppierung von Interfaces und Properties beschreibt. Einen solchen Service erhlt man immer als Rckgabewert (oder Out-Parameter) eines Methodenaufrufs, also hier z.B. einer Methode, die ein Dokument erzeugt. Der Rckgabewert einer solchen Methode ist immer ein Interface, auf der Code-Ebene hat der Begriff Service also nur dokumentarische Bedeutung: indem man beschreibt, dass eine Methode das Interface XMyInterface eines Objekts zurckgibt, das den Service MyService implementiert, kann der Programmierer der Dokumentation von MyService entnehmen, welche Interfaces er an dem erhaltenen Objekt voraussetzen darf und welche eventuell vorhanden sein knnten.

Nun knnte man meinen, dass ein solcher abstrakter Service auch sehr gut (oder sogar viel besser) selbst als Interface beschrieben werden knnte, das wiederum von anderen Interfaces abgeleitet ist (nmlich von den nicht optionalen Interfaces des abstrakten Service, den das Interface ersetzen soll). Und in der Tat ist das eigentlich auch die bessere Beschreibungsweise. Da aber vor StarOffice 8 die Mehrfachableitung von Interfaces nicht erlaubt war, wurden abstrakte Services als Ersatz benutzt. In StarOffice 8 drfen Interfaces nun auch von mehreren anderen abgeleitet werden, daher ist diese Einschrnkung nicht mehr gegeben.

Daher wurde mit StarOffice 8 ein neuer, klarerer Service-Begriff eingefhrt. Ein solcher neuartiger service wird immer von einem Service Manager erzeugt (ist also ein echter Service) und implementiert genau ein Interface, das dann selbst wiederum von beliebig vielen anderen Interfaces abgeleitet sein kann. Auf diese Weise wird die Trennung von Implementierung (Service) und Schnittstelle (Interfaces und Properties) noch deutlicher herausgearbeitet.

Die Verwendung der mehrfach erbenden Interfaces hat den groen Vorteil, dass der Programmieraufwand bei der Benutzung der Interfaces stark verringert wird, wie im nchsten Kapitel erlutert wird. Der Nutzen wird noch dadurch erhht, dass die neuartigen Services eine alternative Art der Erzeugung anbieten, mit Methoden, die eine Referenz auf genau das implementierte Interface des Service zurckgeben und nicht nur eine Referenz auf das bliche Basis-Interface com::sun::star::uno::XInterface (s.u.).

Wenn ein Objekt in einer neuen Version neue Interfaces oder Properties untersttzt, kann man bei altmodischen Services entweder dieses neue Interface der Servicespezifikation hinzufgen, es aber als optional kennzeichnen (wie im Beispiel des OfficeDocument Service zu sehen) oder aber man kreiert einen neuen Service, der den alten umfat und zustzlich das neue Interface oder Property enthlt. Neuartige Services implementieren aber immer genau ein Interface, daher knnen sie keine optionalen Interfaces haben. Das ist aber auch im Sinne des neuen Konzepts, das mit den mehrfach erbenden Interfaces auf hhere Typsicherheit setzt. Daher steht einem bei neuartigen Service nur der zweite Weg der Erweiterung offen, wenn man neue Interfaces an einem Objekt auch per IDL dokumentieren mchte, nmlich die Erzeugung eines neuen Interface und Service. Zwar kann das Interface selbst optionale Elemente enthalten, aber diese knnen nicht nachtrglich hinzugefgt werden, sie sind integraler Bestandteil des Typs. optional wird also nur noch semantisch motiviert gebraucht, nicht versionierend. Streng genommen hat dieses Wort aber ohnehin nur dokumentarischen Charakter, insofern verliert man damit kein essentielles Feature.

Zustzlich kann natrlich auch ein neuartiger Service Properties haben, diese drfen auch optional sein wie bei den altmodische Services, allerdings werden diese jetzt als attribute an dem Interface, das der Service implementiert, deklariert. Der Gedanke ist, dass Attribute zur Schnittstelle gehren und dass daher die Service-Definition der falsche Ort ist. Attribute werden ebenso wie Properties im Kapitel ber UNO-Typen nher erlutert.

Eine Definition sieht dann beispielsweise so aus:

module com { module sun { module star { module mail {

interface XMailMessage: com::sun::star::uno::XInterface

{

[attribute, readonly] string SenderAddress;

[attribute] string ReplyToAddress;

void addRecipient([in] string sRecipientAddress);

void addCcRecipient([in] string sRecipientAddress);

void addBccRecipient([in] string sRecipientAddress);

sequence getRecipients();

sequence getCcRecipients();

sequence getBccRecipients();

[attribute] string Subject;

[attribute] com::sun::star::datatransfer::XTransferable Body;

void addAttachment([in] MailAttachment aMailAttachment);

sequence getAttachments();

};

service MailMessage: XMailMessage

{

create([in] string sTo, [in] string sFrom, [in] string sSubject, [in] com::sun::star::datatransfer::XTransferable xBody);

createWithAttachment([in] string sTo, [in] string sFrom, [in] string sSubject, [in] com::sun::star::datatransfer::XTransferable xBody, [in] MailAttachment aMailAttachment);

};

}; }; }; };

Dieses Beispiel zeigt auch, dass Services nun Methoden zu ihrer Konstruktion anbieten knnen, die, wie schon erwhnt nicht mehr einfach nur com::sun::star::uno::XInterface, sondern das implementierte Interface zurckgeben und so den Programmieraufwand bei der Benutzung des Service stark reduzieren, wie im nchsten Kapitel erlutert. Diese Konstruktoren erlauben darberhinaus auch die bergabe genau definierter Argumente bei der Erzeugung, nicht nur eine nicht-typsichere Sequence wie im Falle der createInstanceWithArguments-Methode des Service Manager.

Da der neuartige Service-Begriff auerdem auch wesentlich klarer und verstndlicher ist, werden alle in Zukunft neu definierten Services ausschlielich solche des neuartigen Typs sein. Neu eingefhrte Services, die nicht genau ein Interface implementieren, wird es in Zukunft nicht mehr geben, also vor allem auch keine zustzlichen abstrakten Services mehr, stattdessen werden mehrfach erbende Interfaces benutzt, um Interfaces zu gruppieren. Natrlich sind die neuartigen Services nicht so einfach erweiterbar, d.h. im Falle substantieller Erweiterungen wird man nicht um die Definition neuer Interfaces und Services herumkommen, aber die hhere Typsicherheit und der dadurch leichter zu schreibende und potentiell bessere Code berwiegen, auerdem bleibt das API durch die Mglichkeit, die neuen Interfaces von den alten abzuleiten, gut wartbar und ist in der Benutzbarkeit der alten Variante mit optionalen Interfaces nicht unterlegen.

Leider knnen bereits existierende abstrakte Services wie der oben beschriebene Service com::sun::star::document::OfficeDocument nicht einfach durch entsprechende Interfaces, die von allen Interfaces erben, die der abstrakte Service umfasst, ersetzt werden, da UNO ja garantiert, dass published Typen nicht nachtrglich entfernt werden. Aus dem gleichen Grund knnen alle bisher existierenden altmodischen echten Services nicht durch neuartige ersetzt werden.

Es wird daher ein Nebeneinander der verschiedenen Arten von Services geben, wobei z.T. einzelne Objekte neben dem altmodischen auch einen neuartigen Service bzw. ein entsprechendes mehrfach erbendes Interface anbieten werden. Auf diese Weise kann neuer Anwendungscode, der nicht mit lteren Versionen von StarOffice arbeiten muss, die neuen Service-Namen und die neuen Interfaces benutzen, alter Anwendungscode oder solcher, der auch mit bereits existierenden StarOffice-Versionen laufen soll, benutzt dann eben die alten Service-Namen.

Typen in UNO

Neben den bereits erwhnten Interfaces und Services kennt UNO noch eine ganze Reihe weitere Typen, die im Folgenden kurz erlutert werden. Mehr zu einzelnen dieser Typen findet sich dann bei der Beschreibung der Umsetzung dieser Typen in die jeweilige Programmiersprache und in der IDL-Referenz im Anhang. Ebenso wie Interfaces knnen auch alle anderen benutzerdefinierten Typen published oder unpublished sein.

Interfaces

Jedes in UNOIDL deklarierte Interface stellt einen UNO-Typ dar, fr den auch Typinformation vorhanden ist.

Im Gegensatz zu den Interfaces werden Werte der anderen Typen in Methodenaufrufen im Remote-Fall (also ber Prozessgrenzen hinweg) immer by value bergeben, d.h. es werden Kopien davon in den anderen Prozess transportiert (und dabei ggf. in die der Sprachanbindung der jeweiligen Zielapplikation genehme Form umgewandelt), bei Interfaces wird nur eine Art Hlle (ein sogenannter Proxy) im Zielprozess erzeugt, ein Objekt in der jeweiligen Programmiersprache, das alle Methodenaufrufe an das eigentliche Objekt ber eine UNO-Verbindung weiterreicht. Ein solcher Proxy ist dabei immer nur fr das jeweilige Interface gltig und kann nicht fr einen direkten Zugriff auf Methoden von anderen Interfaces des gleichen Objekts verwendet werden. Dieser Unterschied hat Konsequenzen fr die Remote Performance der jeweiligen Typen und fr die Art und Weise, wie mit Interfaces umgegangen wird.

Eine wichtige Frage in Zusammenhang mit Interfaces ist die nach der Objektidentitt. Wenn man zwei Interfaces (gleichen oder verschiedenen Typs) hat, ist es manchmal wichtig zu wissen, ob sie beide zu dem gleichen Objekt gehren. Ein Beispiel sind Methoden, mit deren Aufruf sich Listener abmelden. Das aufgerufene Objekt muss dann herausfinden, ob das Objekt, das sich hier abmeldet, mit einem der bereits angemeldeten identisch ist, damit es dieses aus seiner Liste entfernen kann. Objektidentitt wird ber Funktionen des Runtime Environments der jeweiligen Sprachanbindung geprft, Details finden sich daher in den entsprechenden Kapiteln.

Elementare Typen

Dies sind Typen wie boolean, short, long, float, string. Details dazu in der Tabelle im nchsten Kapitel.

Der Datentyp type

Ein Teil des StarOffice API bentigt die explizite Bereitstellung von Typ-Information, z.B. die im Basic-Interpreter verwendete Introspection von Objekten. Fr solcherlei Information stellt UNO den Datentyp type bereit, dessen Werte jeweils einen mglichen UNO-Datentyp reprsentieren. Auch im spter diskutierten queryInterface-Konzept findet Typ-Information Verwendung.

Der Datentyp any

Eine ganze Reihe von UNO-Interfaces sind generischen Typs, z.B. Interfaces, die Container verwalten. Damit diese Daten beliebigen Typs aufnehmen knnen, bentigt man einen UNO-Typ, der alle anderen aufnehmen kann. Hier ein Beispiel fr einen Container, dessen Elemente ber einen Index identifiziert werden:

module com { module sun { module star { module container {

published interface XElementAccess: com::sun::star::uno::XInterface

{

type getElementType();

boolean hasElements();

};

published interface XIndexAccess: com::sun::star::container::XElementAccess

{

long getCount();

any getByIndex( [in] long Index )

raises( com::sun::star::lang::IndexOutOfBoundsException,

com::sun::star::lang::WrappedTargetException ); };

}; }; }; };

Der Rckgabewert, mit dem ein Element ber die Methode getByIndex aus dem Container geholt wird, ist vom Typ any. Das ist ein Typ, der die Werte aller anderen Typen (also nicht nur Interface-Referenzen wie im obigen Beispiel, auch short, string, struct etc.) annehmen kann und zustzlich noch Information in Form eines type darber bereithlt, von welchem Typ der angenommene Wert ist.

Das Basis-Interface com::sun::star::container::XElementAccess hat eine Methode getElementType, die Auskunft darber gibt, von welchem Typ ein Element dieses Containers ist (er enthlt also nur Elemente gleichen Typs). Man kann also je nach Typ entsprechenden Code schreiben, um das Element korrekt zu verarbeiten.

Der Datentyp sequence

Eine sequence ist eine homogene Zusammenstellung von Werten eines einzigen UNO-Typs mit einer variablen Anzahl von Elementen. Im Prinzip ist eine solche Sequence mit einem Container vergleichbar, der wie oben seine Element ber com::sun::star::container::XIndexAccess zugnglich macht. Der entscheidende Unterschied ist, dass man den Container implementierten muss, whrend die sequence Teil der UNO-Schicht ist, und dass Container-Interfaces wie alle Interfaces immer by reference bergeben werden, whrend eine Sequence grundstzlich per value bergeben, ihre Elemente also bei einem Remote-Aufruf kopiert werden. Das hat zunchst einmal einen erhhten Aufwand zur Folge, der aber unter bestimmten Umstnden dadurch berkompensiert wird, dass dann die eigentliche Verarbeitung der Elemente komplett im Zielprozess erfolgen kann, whrend im Falle des Containers jeder einzelne Elementzugriff einen Remote Call erfordert.

In den meisten Programmiersprachen wird eine sequence als Array abgebildet. Ein Beispiel fr den Gebrauch in UNOIDL findet sich im vorherigen Kapitel in der Definition des Interface com::sun::star::mail::XMailMessage.

Enumerationen (enum) und Constant Groups

Dies sind zwei Konstrukte, die auf den ersten Blick ziemlich hnlich aussehen, da sie beide eine Gruppierung von Werten darstellen. Im Gegensatz zu den Constant Groups knnen Enumerationen aber spter nicht mehr erweitert werden. Enumerationen knnen auf jeden Fall dort zur Anwendung kommen, wo die Umstnde die mglichen Werte eines bestimmten Kontexts begrenzen, also z.B. die Namen der Wochentage oder die der Monate. In anderen Fllen wird man mglicherweise erst einmal eine Constant Group in Erwgung ziehen, sofern nicht andere berlegungen, die unten noch erlutert werden, eine Enumeration doch ratsamer erscheinen lassen.

Ein Beispiel fr eine Enumeration ist die Anzahl der Werte fr die Paperorientation, also z.B. die Ausrichtung des Papiers beim Drucken:

module com { module sun { module star { module view {

published enum PaperOrientation

{

PORTRAIT,

LANDSCAPE

};

}; }; }; };

Ein Beispiel fr eine Constant Group findet sich z.B. bei den verschiedenen Mglichkeiten, wie mit dem Updaten von Links in einem Dokument beim Laden verfahren werden soll:

module com { module sun { module star { module document {

published constants LinkUpdateModes

{

const long NEVER = 0;

const long MANUAL = 1;

const long AUTO = 2;

const long GLOBAL_SETTING = 3;

};

}; }; }; };

Die Formulierung als Constant Group lt einem die Mglichkeit, spter auch problemlos weitere Varianten anzubieten, allerdings kann man am API dann nicht erkennen, ob diese von dem Objekt auch wie erwartet verarbeitet werden. Letztendlich stellt eine Constant Group eigentlich immer das Abbild einer Implementierung dar und hat so mehr dokumentarischen Wert, whrend eine Enumeration eher eine unabhngig von mglichen Implementierungen feststehende Wertemenge ist.

Das hat dann letztlich die Konsequenz, dass die Implementierung von APIs, die Werte von Constants Groups verarbeiten, hinreichend robust implementiert werden mssen (sprich: nur bekannte Werte verarbeiten und unbekannte mit einer Fehlermeldung quittieren) und der aufrufende Code damit rechnen muss, dass es bei jedem Wert theoretisch einen Fehler geben kann, denn auer per Dokumentation kann man fr keine Implementierung erfahren, welche Werte sie untersttzt. Das ist bei Enumerationen anders, hier darf der Aufrufer vertrauen, dass jeder Wert der Enumeration jeder Implementierung eines sie benutzenden API auch bekannt ist.

Man kann das auch so ausdrcken: Enumerationen sind typsicher, Konstanten nicht. So kann man an eine Methode, die als Input-Parameter eine Enumeration erwartet, nur genau die Werte bergeben, die zu der Enumeration gehren, bei einem Input-Parameter, dem man Integer-Konstanten bergibt, kann prinzipiell jeder beliebige Wert bergeben werden, sodass man sich nicht sicher sein kann, dass auch sinnvolle Werte verwendet werden.

Es gilt also abzuwgen, ob eher eine hhere Typsicherheit (und damit potentiell besserer Code) oder Erweiterbarkeit das Ziel sein sollen. Da der Fokus des StarOffice API in Zukunft eher in Richtung Typsicherheit und damit besserer und einfacher zu schreibender Code geht, wird man dann auch viele Enumerationen finden, wo zumindest theoretisch in Zukunft Erweiterungen mglich sind. Sollte das tatschlich passieren, mten dann neue APIs erstellt werden.

Strukturierte Datentypen (struct)

struct-Typen sind zusammengesetzte Datentypen, deren einzelne Elemente Werte jedes vorher genannten Typs annehmen knnen. Jeder in UNOIDL deklarierte struct stellt einen UNO-Typ dar, fr den auch Typinformation vorhanden ist. Ein Beispiel:

module com { module sun { module star { module frame {

published struct FeatureStateEvent: com::sun::star::lang::EventObject

{

com::sun::star::util::URL FeatureURL;

string FeatureDescriptor;

boolean IsEnabled;

boolean Requery;

any State;

};

}; }; }; };

Dieser struct enthlt neben einem string und 2 boolean auch ein any und einen weiteren struct.

Ab StarOffice 8 kennt UNO auch sogenannte polymorphic structs, die aber bisher kaum verwendet werden. Nheres dazu findet man im Developers Guide.

Exceptions in UNO

Der Typ exception zeigt dem Aufrufer einer Methode einen Fehler an. Sein exakter Typ ist ein erster Hinweis auf den Grund fr diesen Fehler, weitere Informationen knnen als Bestandteile der exception wie bei einem struct gegeben sein. Auch wenn Exceptions in ihrem Aufbau strukturierten Datentypen hneln, werden sie z.B. nicht als Argumente von Methoden oder als Teile von structs sondern ausschlielich im Rahmen der Fehlerbehandlung verwendet.

Alle UNO-Exceptions leiten sich von der Basis com::sun::star::uno::Exception ab. Welche Exception von einer Methode geworfen werden knnen, wird in der IDL-Datei des Interface deklariert, zustzlich kann jede Methode eine com::sun::star::uno::RuntimeException werfen, auch wenn das nicht explizit deklariert wurde. Ein Beispiel:

module com { module sun { module star { module uno {

published exception Exception

{

string Message;

com::sun::star::uno::XInterface Context;

};

}; }; }; };

module com { module sun { module star { module io {

published exception IOException: com::sun::star::uno::Exception

{

};

Diese Exception zeigt einen Fehler bei einer I/O-Operation an. Da sie wie alle UNO-Exceptions von com::sun::star::uno::Exception abgeleitet ist, kann sie auch einen Text zur nheren Beschreibung der Fehlerursache und eine Referenz auf das den Fehler meldende Objekt enthalten.

Services

Siehe entsprechendes Kapitel. Services sind eigentlich kein UNO-Typ im eigentlichen Sinne, allerdings werden sie wie richtige UNO-Typen in der UNOIDL deklariert. Fr neuartige Services werden auch Daten (ber die Konstruktoren) in der Typinformationsdatei abgelegt.

Properties

Mit Properties bezeichnet man gemeinhin gewisse Elemente von Objekten, die man sich abholen oder setzen kann. UNOIDL kennt zwei Mglichkeiten, das auszudrcken: bei altmodischen Services als property und bei neuartigen Services als attribute am Interface, das der Service implementiert. Beispiele dafr wurden im Kapitel ber Services gezeigt.

Das Property-Konzept wird von der Sprachanbindung in die jeweilige Programmiersprache bersetzt. ((Die blichen Implementierungssprachen fr UNO-Objekte sind Java und C++. In beiden Sprachen gibt es keine direkten Zugriffe auf UNO-Properties, sie werden vielmehr ber Methoden eines Interface angesprochen.)) Alle Objekte, die einen Service mit Properties implementieren, mssen dafr das Interface com::sun::star::beans::XPropertySet untersttzen:

module com { module sun { module star { module beans {

published interface XPropertySet: com::sun::star::uno::XInterface

{

com::sun::star::beans::XPropertySetInfo getPropertySetInfo();

void setPropertyValue( [in] string aPropertyName,

[in] any aValue )

raises( com::sun::star::beans::UnknownPropertyException,

com::sun::star::beans::PropertyVetoException,

com::sun::star::lang::IllegalArgumentException,

com::sun::star::lang::WrappedTargetException );

any getPropertyValue( [in] string PropertyName )

raises( com::sun::star::beans::UnknownPropertyException,

com::sun::star::lang::WrappedTargetException );

void addPropertyChangeListener( [in] string aPropertyName,

[in] com::sun::star::beans::XPropertyChangeListener xListener )

raises( com::sun::star::beans::UnknownPropertyException,

com::sun::star::lang::WrappedTargetException );

void removePropertyChangeListener( [in] string aPropertyName,

[in] com::sun::star::beans::XPropertyChangeListener aListener )

raises( com::sun::star::beans::UnknownPropertyException,

com::sun::star::lang::WrappedTargetException );

void addVetoableChangeListener( [in] string PropertyName,

[in] com::sun::star::beans::XVetoableChangeListener aListener )

raises( com::sun::star::beans::UnknownPropertyException,

com::sun::star::lang::WrappedTargetException );

void removeVetoableChangeListener( [in] string PropertyName,

[in] com::sun::star::beans::XVetoableChangeListener aListener )

raises( com::sun::star::beans::UnknownPropertyException,

com::sun::star::lang::WrappedTargetException );

};

}; }; }; };

ber dieses Interface knnen Properties gelesen und gesetzt werden sowie eine Information ber alle vorhandenen Properties und ihre Typen erfragt werden (die anderen Methoden sollen hier erst einmal auer Betracht bleiben).

Bei einem attribute, das ja immer Teil eines Interface ist, wird im Java oder C++-Interface automatisch fr jedes attribute eine get und eine set Methode hinzugefgt (bzw. nur eine get-Methode, wenn es readonly ist). Beispiel:

interface XMyInterface

{

[attribute, readonly] string FirstAttribute;

[attribute] string SecondAttribute;

void doSomething();

};

Dies ist aus Objektsicht analog zu folgender Deklaration:

interface XMyInterface

{

string getFirstAttribute();

string getSecondAttribute();

void setSecondAttribute( [in] string value ):

void doSomething();

};

Im Gegensatz zum Interface XPropertySet sind die Getter- und Setter- Methoden typsicher, da sie keine Any-Parameter verwenden, es werden also eine ganze Reihe von mglichen Problemen im Zusammenhang mit diesen vermieden.

UNO in den verschiedenen Programmiersprachen

Prinzipiell ist die Verwendung UNO-basierter Typen wie bereits erwhnt nicht an eine bestimmte Programmiersprache gebunden, da UNO Mittel dafr bereitstellt, die Typen in die jeweilige Sprache zu bersetzen. Dadurch knnen z.B. die Objekte von StarOffice, die berwiegend in C++ implementiert sind, in Sprachen wie Java oder StarOffice Basic angesprochen werden. Es ist auch anders herum mglich, in Java implementierte Objekte in das weitgehend C++-basierte StarOffice einzugliedern. Wie die einzelnen Typen in die jeweilige Sprache abgebildet werden, wird spter noch im einzelnen erlutert.

Damit eine bestimmte Programmiersprache aber auch tatschlich UNO-Typen benutzen kann, mu sie UNO-fhig gemacht werden. Es gibt dabei mehrere Mglichkeiten:

Man erstellt ein sogenanntes Language Binding fr die gewhlte Sprache. Beispiele dafr sind die Bindings fr Java und C++

Man benutzt eine interpretierte Sprache, deren Interpreter in einer Programmiersprache implementiert ist, die wiederum selbst UNO-fhig ist. Beispiele dafr sind das StarOffice Basic (Interpreter in C++) und der JavaScript-Interpreter aus dem StarOffice Scripting Framework, der in Java implementiert ist.

Man verwendet eine andere Middleware und deren Language Bindings, sofern es eine Brcke von UNO zu dieser Technologie gibt. So gibt es eine UNO-Bridge zu .NET, wodurch UNO-Typen auch in .NET-Sprachen wie C# benutzt werden knnen.

Einen Sonderfall stellt die OLE Automation Bridge dar. Es gibt zwar keine allgemeine COM Bridge fr UNO, aber zumindest der fr OLE Automation ntige Teil wird untersttzt. Man kann daher auch aus allen Sprachen, die Objekte ber OLE Automation scripten knnen, UNO-Typen benutzen, komfortabel ist das aber nur in Sprachen, die die Schnittstelle von Objekten interpretierend benutzen, also z.B. Visual Basic.

Ein Language Binding ermglicht es, eine UNO-Umgebung innerhalb des Prozesses einer Anwendung zu starten und dort einen eigenen Service Manager zu instantiieren und mit seiner Hilfe eigene UNO-Objekte zu erzeugen oder sich mit einer anderen UNO-Anwendung zu verbinden und ber diese Verbindung (die auch ber Rechnergrenzen hinweg funktioniert!) deren Service Manager zu empfangen und damit UNO-Objekt zu erzeugen.

Je nach Sprache pat sich das Binding nahtlos durch Benutzung vorhandener Sprachkonstrukte wie z.B. Templates oder durch Zuhilfenahme einiger spezieller Runtime-Funktionen ein, entsprechend gehren zu dem Binding sowohl deklarative Elemente wie C++ Header Files als auch Libraries oder jar files, die zu der das Binding benutzenden Applikation hinzugelinkt werden mssen. Zusammen mit den bereits erwhnten vom SDK aus den IDL-Dateien erzeugten Typinformationen bersetzt das Binding die UNOIDL Sicht in die analogen Konstrukte der jeweiligen Programmiersprache, diese Sprache mu also alle IDL-Features (z.B. Methoden, Structs und Ableitungen) abbilden knnen.

In diesem Sinne wre Basic eigentlich als UNO-Programmiersprache vllig ungeeignet, allerdings ist StarOffice Basic in C++ implementiert und kann daher die UNO-Fhigkeiten dieser Sprache ausnutzen, indem die Implementierung des Interpreters die UNO-Konstrukte fr die interpretierte Sprache aufbereitet. Dabei gehen natrlich einige Dinge verloren, in erster Linie das Konzept der Interfaces (da Basic keine abstrakten Klassen und Ableitungen kennt): StarOffice Basic sieht ein Objekt immer als die Summe aller seiner Interfaces, es kennt aber weder Services noch Interfaces als Typen, sondern nur einen Typ Object. Das hat Konsequenzen fr die Art und Weise, wie der Programmierer mit Objekten umgeht.

In Programmiersprachen wie Java und C++ sind UNO-Objekte wie in der IDL nicht durch Objekte reprsentiert, sondern durch Referenzen (bzw. Pointer) auf Interfaces, die wiederum in C++ durch eine abstrakte Basisklasse, in Java aber durch ein Java Interface abgebildet werden. In beiden Fllen sind diese Referenzen daher streng typisiert und man kann an ihnen nur solche Methoden aufrufen, die Bestandteil des jeweiligen Interfaces sind, der verwendete Compiler wird ansonsten den Code einfach nicht fehlerfrei bersetzen knnen. Es nutzt einem gar nichts zu wissen, dass das Objekt, von dem man eine Referenz auf sein Interface X1 hat, doch einen Service S implementiert und daher ganz sicher auch das Interface X2 untersttzt, man braucht zum erfolgreichen Aufruf der Methoden aus Interfaces X2 eine Referenz auf das Interface, um den Compiler zufrieden zu stellen. Diese Auswertung zur Compile-Zeit bezeichnet man auch als early binding. Was im Gegensatz dazu late binding ist, werden wir noch am Beispiel von Basic kennenlernen.

Hat man nun eine beliebige Referenz auf ein Interface eines Objekts und will dann ein anderes Interface des gleichen Objekts benutzen, muss man es darum bitten, eine entsprechende Referenz auf dieses herauszugeben. Dafr kennt UNO das queryInterface-Konzept. Wie dieses umgesetzt wird, ist abhngig von der jeweiligen Programmiersprache, manche (wie StarOffice Basic) bentigen es gar nicht, da sie nicht mit Interfaces arbeiten, sondern immer mit Objekten. Die Essenz dieses Konzepts ist, dass die Sprachanbindung eine Funktion zur Verfgung stellt, der man eine Referenz auf das zu befragende Objekt (genauer auf eines seiner Interfaces) und die Typinformation (den UNO type) fr das gewnschte Interface zur Verfgung stellt und dann eine Referenz auf dieses gewnschte Interface zurckerhlt. Wenn das Objekt das gewnschte Interface nicht untersttzt, erhlt man eine leere Referenz.

Ursprnglich wurde dieses Konzept dadurch ausgedrckt, dass eine entsprechende Methode queryInterface im Basis-Interface com::sun::star::uno::XInterface existiert, von dem ja alle anderen Interfaces abgeleitet sind, sodass man diese Methode an beliebigen Referenzen auf irgendwelche Interfaces aufrufen kann und dann als Rckgabewert die Referenz auf das gewnschte Interface erhlt.

Das ist allerdings im Nachhinein betrachtet keine glckliche Wahl gewesen. Wie sich noch zeigen wird, ist die Umsetzung des Konzepts als Detail der Sprachanbindung zu sehen, daher sollte man es auch losgelst von einem UNO-Interface betrachten, das ja selbst sprachunabhngig ist. Das Interface com::sun::star::uno::XInterface hat seine Berechtigung lediglich als Basis-Interface aller anderen Interfaces, seine Methoden bildet UNO nicht in allen Sprachanbindungen ab, auch wenn diese Methode in der Implementierung der Anbindungen, die diese Methode nicht prsentieren, intern verwendet werden.

Durch die stndige Notwendigkeit, queryInterface fr jedes Interface eines Service, das man benutzen will, aufzurufen, wird natrlich ein erheblicher Mehraufwand an Code ntig. Zwar erlaubt das sehr flexible Entscheidungen zur Laufzeit darber was ein Objekt kann und wie man dann mit ihm arbeiten kann, es hat sich im Laufe der Zeit aber gezeigt, dass man ein queryInterface nur dort verwenden mchte, wo es wirklich ntig ist, also nach Mglichkeit nicht, wenn man die garantierten Interfaces eines Service benutzen will. Diese Erkenntnis fhrte dann auch zur Entwicklung der mehrfach erbenden Interfaces und der neuartigen Services in StarOffice 8. Wenn bei der Erzeugung eines Service ber einen seiner Konstruktoren gleich eine Referenz auf ein Interface zurckgegeben wird, das alle Methoden umfat, die der Service ber seine Interfaces garantiert, bentigt man fr deren Benutzung berhaupt kein queryInterface mehr. Natrlich kann das Objekt immer noch mit der Zeit um andere Interfaces wachsen, die man dann per queryInterface erfragen kann. Man behlt also Flexibilitt, wo es ntig ist und gewinnt Einfachheit, wo es mglich ist.

In StarBasic ist, wie bereits erwhnt, kein Pendant zu Interfaces vorhanden, und anstelle von Interface-Referenzen verwendet man Objects. Bei einem solchen Typ wird erst zur Laufzeit entschieden, welche Methoden und Properties es besitzt, man kann also beliebige Methoden an ihm aufrufen und der Code wird problemlos bersetzt. Wenn das Objekt allerdings die gewhlte Methode nicht hat, wird es einen Laufzeitfehler geben. Dies ist das, was man als late Binding bezeichnet.

Um das zu erreichen, benutzt der Basic-Interpreter die Fhigkeit von UNO-Objekten, sich inspizieren zu lassen, d.h. es zur Laufzeit (am lebenden Objekt) zu befragen, was es kann. Der dazu notwendige Code ist Teil des UNO-fhigen Basic Interpreters, der natrlich auch den Code beisteuert, mit dem die Methoden des UNO-Objekts ber das C++ Language Binding ausgefhrt werden.

Um Laufzeitfehler beim Aufruf optionaler Interfaces zu vermeiden, bietet Basic aber auch eine Mglichkeit, ein Objekt zu befragen, ob es ein bestimmtes Interface untersttzt, bevor man dann versucht, Methoden aus ihm zu benutzen. Dazu und zu weiteren Basic-Details spter mehr.

Hier eine Tabelle der elementaren UNO-Typen und ihren Pendants in den wichtigsten von UNO untersttzten Programmiersprachen.

UNO

Beschreibung

Java

C++

Basic

void

Leerer Typ, nur benutzt als Rckgabewert oder in einem any (s.u.)

void

void

-

boolean

Boolscher Wert, true oder false

boolean

sal_Bool

Boolean

byte

signed 8-bit integer type

byte

sal_Int8

Integer

short

signed 16-bit integer type

short

sal_Int16

Integer

unsigned short

unsigned 16-bit integer type

(-)

sal_uInt16

(-)

long

signed 32-bit integer type

int

sal_Int32

Long

unsigned long

unsigned 32-bit integer type

(-)

sal_uInt32

(-)

hyper

signed 64-bit integer type

long

sal_Int64

(-)

unsigned hyper

unsigned 64-bit integer type

(-)

sal_uInt64

(-)

float

IEC 60559 single precision floating point type

float

float

Single

double

IEC 60559 double precision floating point type

double

double

Double

char

16-bit Unicode character type (genauer: UTF-16 code units)

char

sal_Unicode

-

string

Unicode string type; String aus Unicode-Zeichen

java.lang.String

rtl.OUString

String

Die Verwendung von unsigned Typen ist unerwnscht (deprecated), es hat sich im Nachhinein als unglcklich herausgestellt, sie anzubieten, da nicht alle Programmiersprachen damit umgehen knnen. Entfernen kann man sie allerdings aus UNOIDL nicht mehr, da sich schon in bereits vorhandenen Typen Verwendung finden.

Die Benutzung von unsigned Integer Typen in Java oder Basic kann aber durchaus funktionieren, weil Integer-Typen grundstzlich ineinander umgewandelt werden knnen, sofern der Wertebereich des Zieltyps dabei nicht berschritten wird. Es ist also ohne weiteres mglich, den Wert 40000 in einem Basic-Programm an eine Methode zu bergeben, die einen unsigned short erwartet. Basic wird die Zahl zunchst in einen Long aufnehmen und beim Aufruf der UNO-Methode versuchen, sie in ein sal_uInt16 umzuwandeln (zur Erinnerung: der Interpreter ist in C++ implementiert!). Das wird hier problemlos funktionieren, whrend bei einem Wert 80000 natrlich dann ein Fehler auftritt. hnliches gilt fr die Benutzung von hyper Typen in Basic (also 64 Bit Integer).

In einer weiteren Tabelle nun die nicht-elementaren UNO-Typen und ihre Pendants in den wichtigsten von UNO untersttzen Programmiersprachen.

UNO

Beschreibung

Java

C++

Basic

enum

Enumeration

class

enum

Long

constant group

Gruppe von Konstanten

interface

name space

Long

struct

Aus anderen Typen zusammengesetzter Typ

class

struct

Object

sequence

UNO-quivalent zu Arrays

array

template< class t >

com::sun::star::uno::Sequence< t >

Array

any

Container, der jeden beliebigen Typ aufnehmen kann

java.lang.object,

class com.sun.star.uno.Any

com::sun::star::uno::Any

Variant

type

Meta-Typ: identifiziert einen Typ, Teil eines jeden any

class com.sun.star.uno.Type

class com::sun::star::uno::Type

-

exception

-

class

class

-

interface

-

interface

(abstract) class

-

Einige dieser Mappings lassen sich in einer Tabelle nur sehr verkrzt wiedergeben, eine nhere Diskussion erfolgt in den Kapiteln ber die einzelnen Language Bindings.

Die verschiedenen Anbindungen an Programmiersprachen bieten auch komfortable Wege, mit any-Typen umzugehen. Wenn man wei, welchen Typ in einem erhaltenen any steckt (z.B. weil es das Element eines Containers ist, den man selbst gefllt hat), mchte man gerne diesen any einfach einer Variable dieses Typs zuweisen knnen, ohne mhsam selbst Typabfragen vornehmen zu mssen. Da das any ja wie erwhnt auch die notwendige Typinformation enthlt, kann eine solche einfache Zuweisung durch das dem any entsprechende Sprachelement der jeweiligen Programmiersprache auch implementiert werden. Whrend das in C++ durch einen Operator der Any-Klasse erledigt wird, nutzt man in Java die Klasse com.sun.star.uno.AnyConverter aus dem Language Binding. In Basic ist auer in wenigen Fllen, die mit den unterschiedlichen Typsystemen von Basic und UNO zu tun haben, berhaupt kein explizites Behandeln von Any-Typen (Variant) ntig.

Services haben allerdings in keiner Programmiersprache ein quivalent. Altmodische Services dienen ausschlielich der Dokumentation und fassen einfach mehrere Aspekte eines Objekts (Interfaces, Properties) zu einem neuen, bergeordneten zusammen. Neuartige Services beschreiben nur, mit welchen Service-Namen man am Service Manager Services instantiieren kann, lediglich ihre Konstruktoren werden als statische Methoden einer Klasse abgebildet, die aber selbst nicht instantiierbar ist.

StarOffice Programmierung in JavaAllgemeines

Im Folgenden werden einige Java-Klassen erwhnt, die Bestandteil der Java UNO Runtime Library sind. Diese werden hier nur soweit erlutert, wie es fr das Verstndnis des Diskussionsgegenstands erforderlich ist. Eine ausfhrliche Referenz dieser Klassen findet sich im SDK.

Der Java-Programmierer hat prinzipiell drei Mglichkeiten, StarOffice und seine Objekte zu benutzen:

er implementiert selbst einen UNO-Service als Komponente, die sich ber gewisse Schnittstellen in StarOffice integriert;

er schreibt ein Java-Programm, das sich mit StarOffice verbindet;

er schreibt ein Java-Programm und bindet es ber das StarOffice Scripting Framework als Macro ein.

Der erste Fall wird in einem eigenen Kapitel ber Komponentenentwicklung behandelt so wie der dritte Fall in einem solchen ber das Scripting Framework, ber das man sich im Developers Guide informieren kann. Hier soll es um den zweiten Fall gehen.

Um UNO-Objekte in einem eigenen Java-Programm erzeugen zu knnen, bentigt man einen Service Manager, wie im Kapitel ber Services beschrieben. Ein Service Manager kann durch Bereitstellung einiger Konfigurations und Typinformationsdateien erzeugt werden, genauso wie es StarOffice selbst beim Starten tut. Interessanter ist es natrlich, den Service Manager des StarOffice Prozess zu verwenden, denn ber den kommt man an die Objekte heran, die das Office ausmachen. Dazu mu zunchst eine Instanz von StarOffice gestartet und/oder zur laufenden Instanz eine geeignete Verbindung (Socket oder Pipe) aufgebaut werden. ber diese Remote-Verbindung kann UNO dann eine Referenz auf den Service Manager transportieren. Seit StarOffice 8 mu der Programmierer sich um diese Details nicht mehr selbst kmmern, da es das sogenannte Simple Bootstrapping gibt. Der Zugriff auf den StarOffice Service Manager erfolgt dann prinzipiell mit einer einzigen Zeile Code:

public class FirstUnoContact {

public static void main(String[] args) {

try {

com.sun.star.uno.XComponentContext xContext =

com.sun.star.comp.helper.Bootstrap.bootstrap();

com.sun.star.lang.XMultiComponentFactory xServiceManager =

xContext.getServiceManager();

}

catch (java.lang.Exception e){

e.printStackTrace();

}

finally {

System.exit(0);

}

}

}

(Anmerkung: in StarOffice-Versionen vor StarOffice 8 gab es das Simple Bootstrapping nicht und die Herstellung einer Verbindung war deutlich aufwendiger. Details dazu finden sich im Developers Guide im Kapitel UNO Concepts.)

com.sun.star.comp.helper.Bootstrap ist eine Klasse der Java UNO Runtime, die in ihrer bootstrap-Methode folgendes tut:

sucht die StarOffice-Installation (das ist systemabhngig implementiert);

startet StarOffice aus dieser Installation mit einer geeigneten Kommandozeile, die es veranlasst, eine Verbindung (named pipe) aufzumachen;

sollte schon ein StarOffice laufen, wird die Kommandozeile an diese Instanz weitergereicht, sodass dann das bereits laufende Office die Verbindung ffnet; die gestartete zweite Instanz beendet sich dann;

verbindet sich mit StarOffice ber die named pipe und etabliert eine UNO Remote Connection;

fordert ber diese Verbindung den Component Context an und liefert einen Proxy dafr an den Aufrufer zurck.

Ein Component Context stellt quasi ein Environment dar, in dem eine Komponente luft. Dieses Environment setzt sich aus einer Reihe von Objekten zusammen, die alle vom Component Context ber ihren Namen abgefragt werden knnen, der Service Manager ist eines davon. Da er von sehr zentraler Bedeutung ist, gibt es im Interface dafr eine spezialisierte und typsichere Methode, whrend alle anderen Objekte ber eine generische Schnittstelle abgefragt werden:

module com { module sun { module star { module uno {

published interface XComponentContext : XInterface

{

any getValueByName( [in] string Name );

com::sun::star::lang::XMultiComponentFactory getServiceManager();

};

}; }; }; };

Im Prinzip kann es beliebig viele solche Komponentenkontexte geben, und jeder UNO-Service wird mit einem solchen erzeugt, das heit, er wird ihm bei der Konstruktion bergeben. Mit dem Service Manager, den das Objekt sich von seinem Kontext abholen kann, kann das Objekt dann selbst andere erzeugen. Hier knnte z.B. einem Objekt ein Kontext mit einem eingeschrnkten Service Manager bergeben werden, der nur ganz bestimmte Objekt erzeugen kann. Mehr ber Komponentenkontexte findet sich im Kapitel UNO Concepts des Developers Guide.

Beim Starten von StarOffice legt dieses selbst einen Kontext an und erzeugt damit seine Objekte, und dieser Kontext ist der, der auch beim Simple Bootstrapping erhalten wird und so dem Java-Programmierer zur Verfgung steht.

Der erhaltene Service Manager kann nun zur Erzeugung von Objekten benutzt werden. Ein sehr zentrales Objekt im StarOffice API ist das Desktop-Objekt, das u.a. einen Zugriff auf alle offenen Dokumentfenster gewhrt, aber auch zum Laden und Erzeugen von Dokumenten samt Fenstern benutzt werden kann.

Die Erzeugung dieses Objektes, das den Service com::sun::star::frame::Desktop implementiert, geschieht folgendermaen (Service Manager und Context aus obigem Beispielcode):

java.lang.Object desktop = xServiceManager.createInstanceWithContext(

"com.sun.star.frame.Desktop", xContext);

Der Rckgabewert von createInstanceWithContext ist vom Typ java.lang.Object, die Java- Reprsentation einer Referenz auf ein com::sun::star::uno::XInterface (aus der UNOIDL). Wenn man jetzt mit diesem Objekt arbeiten will, mu man von ihm zunchst eine Referenz auf das bentigte Interface erfragen, denn der Java Compiler wird einen Aufruf der gewnschten Methoden nicht ber eine java.lang.Object-Referenz zulassen. Dafr enthlt das Java-UNO Language Binding eine entsprechende Methode an einer Runtime-Klasse, die die Implementierung des im letzten Kapitel beschriebenen queryInterface-Konzepts in Java darstellt. Als Beispiel sei der Zugriff auf das Interfaces des Desktop-Objekts gezeigt, das man zum Laden von Dokumenten verwendet:

com.sun.star.frame.XComponentLoader xLoader = (com.sun.star.frame.XComponentLoader)

UnoRuntime.queryInterface(com.sun.star.frame.XComponentLoader.class, desktop);

Der Methode UnoRuntime.queryInterface wird der Typ bergeben, den man gerne htte. Dies erfolgt im Beispielcode als java.lang.Class Objekt, das die Java-Klasse bezeichnet, die das UNO-Interface in Java reprsentiert, aber es ist auch eine Variante mit einem com.sun.star.uno.Type mglich, der direkt das Interface bezeichnet. Weiter wird die Referenz auf das Objekt bergeben, das man nach dem gewnschten Interface befragen mchte. Der erhaltene Wert ist zwar zunchst auch nur ein java.lang.Object, das dann aber mit einem Java type cast auf den gewnschten Typ in die passende Referenz berfhrt werden kann.

Es stellt sich die Frage, warum man nicht einfach einen direkten Type Cast auf das gewnschte Interface machen kann. Der Grund dafr, dass das nicht funktioniert, ist, dass dafr in der Java-Applikation das komplette Objekt mit allen seinen Interfaces bekannt sein msste, so wie es bei den innerhalb der Applikation deklarierten Java-Klassen der Fall ist. Dort kann der Compiler ganz einfach am Layout der Klasse ermitteln, wie eine Referenz auf das Interface X in eine auf das Interface Y des gleichen Objekts umgewandelt werden kann. Das java.lang.Object, das eine Referenz auf ein bestimmtes UNO-Interface reprsentiert, ist nur eine Abbildung eines Aspekts des Objekts in die Java-Applikation, es ist wie bereits erwhnt nur ein Proxy fr das eigentliche Objekt. Er ist nur fr das jeweilige Interface gltig, fr das man ihn erhalten hat, UNO mappt immer nur das jeweilige Interface, nicht das komplette Objekt in den Prozess der Java-Applikation. Es ist also gar nicht bekannt, wie ein cast von einem Interface des Objekts zum anderen ausgefhrt werden knnte. Erst die sichere Gewiheit, dass das vom queryInterface-Call zurck gegebene java.lang.Object ein Proxy fr das angeforderte Interface ist, weil das ja in der Methode queryInterface so spezifiziert wurde, erlaubt es, dieses Java-Objekt auf das entsprechende Java-Interface zu casten.

Ein queryInterface-Aufruf wird auch benutzt, um von einem Interface zum anderen zu gelangen, also z.B. vom com.sun.star.frame.XComponentLoader-Interface des Desktop-Objekts zu dessen com.sun.star.frame.XFramesSupplier-Interface, das Zugriff auf alle offenen Dokumentfenster gewhrt:

com.sun.star.frame.XFramesSupplier xSup = (com.sun.star.frames.XFramesSupplier)

UnoRuntime.queryInterface(com.sun.star.frame.XFramesSupplier.class, xLoader);

Damit ist schon der wichtigste Teil der Java-UNO-Eigenheiten erlutert. Mit dem Wissen um die Art und Weise, wie der Java-Programmierer UNO-Objekte erzeugt und wie er an ihre Interfaces herankommt, kann er mit Hilfe der IDL-Referenz sich das API aller StarOffice-Objekt erschlieen. Im Detail wird er allerdings noch von Fall zu Fall auf Besonderheiten der Art und Weise stoen, wie die UNO-Typen auf Java-Typen abgebildet werden. Die Tabelle im letzten Kapitel gibt darber einen berblick, es folgt noch eine genauere Erluterung.

Besonderheiten des Java UNO Language BindingsAbbildung elementarer UNO-Datentypen

Wie bereits im allgemeinen Kapitel ber Datentypen erwhnt, kennt Java keine unsigned Integer-Typen, der Programmierer muss also selbst Vorkehrungen treffen, wenn er durch UNO-Schnittstellen mit unsigned-Parametern oder - Rckgabewerten konfrontiert wird.

Man kann unsigned Zahlenwerte explizit auf den signed-Typ der gleichen Lnge casten, Java interpretiert dann einfach das Bitmuster der Zahl um. Bei der bergabe dieser signed-Variablen an einen unsigned-Parameter einer UNO Interface-Methode wird durch das Java UNO Runtime Environment das Bitmuster wieder als unsigned zurck interpretiert. Umgekehrt kann man bei der Implementierung einer UNO-Interface Methode in Java einen empfangenen unsigned-Parameter (der ja den Java-Programmierer als signed-Wert erreicht) explizit auf einen positiven Wert des nchstgreren Integer-Typs uminterpretieren.

Abbildung des UNO-Typs string

UNO strings werden auf java.lang.String abgebildet. Dabei gilt es zwei Details zu beachten:

im Kontext von UNO drfen keine Null-Referenzen fr Strings verwendet werden

Ein Objekt vom Typ java.lang.String kann eine beliebige Folge von UTF-16 code units reprsentieren, UNO strings sind andererseits eine beliebige Folge von Unicode scalar values. Einige UTF-16 code units (die high-surrogate und low-surrogate code points im Bereich D800-DFFF) haben keine entsprechenden Unicode scalar values und sind daher im Kontext von UNO verboten. Details dazu siehe www.unicode.org.

Abbildung des UNO-Typs type

Der UNO-Typ type wird durch die Java-Klasse com.sun.star.uno.Type reprsentiert. Im UNO-Kontext sind keine null-Referenzen dafr erlaubt. Flschlicherweise wurde diese Klasse nicht als final deklariert. Man sollte sich aber trotzdem nicht von ihr ableiten.

Methoden in der Java UNO runtime, die die bergabe eines com.sun.star.uno.Type erwarten, bieten meist auch ein Pendant an, das st