Java-IDL

Um eigenständig IDL-Beschreibungen erstellen zu können, werden im Folgenden die Grundlagen von IDL bzw. die Abbildung auf Java erläutert. Die Programmierkonventionen von Java und von IDL ähneln sich sehr. Allerdings existieren auch einige kleinere Unterschiede. So fordert IDL nicht, dass die Namen von Modulen, Interfaces oder Operationen mit einem Großbuchstaben beginnen müssen. Weiterhin werden in IDL immer dann Underscore-Zeichen verwendet, wenn in Java eine Mischung aus Klein- und Großbuchstaben vorliegt. IDL verfolgt die folgenden weiteren Richtlinien:

  • Eine IDL-Datei besteht aus Elementen, die zusammen einen Namensraum aufspannen.
  • IDL-Bezeichner sind unabhängig von der Groß- oder Kleinschreibung (case insensitive) und können in einem Namensraum höchstens einmal verwendet werden.
  • IDL unterstützt weder das Überladen noch das Überschreiben von Operationen, obgleich die (einfache und mehrfache) Vererbung zugelassen ist.

Im Folgenden sind die wichtigsten Sprachkonstrukte von IDL aufgeführt.

IDL-Module

Das IDL-Konstrukt module wird zur Definition einer Gruppe von IDL-Interfaces verwendet. Ein Modul kann ein oder mehrere Interfaces beinhalten und andere Modulkonstrukte schachteln. Jedes Modulkonstrukt wird in Java in einen eigenen Package-Namen übersetzt. Ein Beispiel für ein Modul wurde bereits erläutert:

code 

module OpenJavaApp {

    interface OJ{

      string gutenTag();

    };

};

Der Java-Code, der vom Compiler idltojava generiert wird, beinhaltet dann die Package-Definition package OpenJavaApp.

IDL-Interfaces

IDL-Interfaces können Attribute, Exceptions und Operationen enthalten. Ein Attribut definiert einen CORBA-Variablentyp, der von vorab definierten Methoden abgefragt werden kann. CORBA-Typen können entweder einfache Typen (siehe Tab. 12-1) oder weitere IDL-Interfaces sein.

IDL-Typ

Java-Typ

boolean

byte

char, wchar

char

double

double

enum, struct, union

class

float

float

long, unsigned long

int

long long, unsigned long long

long

octet

byte

short, unsigned short

short

string, wstring

java.lang.String

unsigned long

int

unsigned short

short

Tab. 12.1: IDL-Typen und Java-Typen

Das IDL-Konstrukt interface wird auf Java-Interfaces abgebildet. Der Compiler idltojava erzeugt die folgenden Java-Dateien aus einem IDL-Interface-Konstrukt:

  • Eine Interface-Klasse mit demselben Namen wie der Interface-Bezeichner.
  • Eine Implementierungsbasisklasse, die den Skeleton-Code enthält, der für die Anwendung auf der Server-Seite notwendig ist.
  • Eine Stub-Klasse.
  • Eine Helper-Klasse, mit der die Objektreferenz auf das Stub-Objekt, das der Client angefordert hat, eingeschränkt werden kann. Die Objektreferenz wird hierbei vom Naming Service zurückgegeben.
  • Eine sog. Holder-Klasse, die eine Referenz zum IDL-Interface-Objekt aufnehmen kann, wenn das Interface als Argument übergeben wird.
  • Ein Attribut erzeugt jeweils eine Zugriffs- und eine Veränderungsmethode. Deklariert man bspw. das folgende Attribut, so ergibt sich der anschließend dargestellte Java-Code.

code 

attribute long zaehler;

//Java-Code
int zaehler();
void zaehler(int arg);

Ein Attribut kann als readonly deklariert werden, um verändernde Zugriffe auszuschließen. In diesem Fall wird keine Veränderungsmethode erzeugt. Es sei darauf hingewiesen, dass der Compiler nie Variablen, sondern immer nur Methoden zum Variablenzugriff erzeugt.

IDL-Operationen werden jeweils auf Java-Methoden abgebildet. Jede Operation muss einen Rückgabewert deklarieren und kann entweder keinen oder eine bestimmte Anzahl an Argumenten verarbeiten. Die Operationsargumente definieren hierbei die Aufrufsemantik der einzelnen Argumente. Die Semantik wird festgelegt, indem einer der Bezeichner in, out oder inout definiert wird. in-Parameter werden als Call-by-Value übergeben, out-Parameter als Call-by-Reference. Da in Java das Konzept der Call-by-Reference-Parameter nicht unterstützt wird, werden solche Parameter auf die Klasse <Java-Typ>Holder abgebildet. Diese Klasse kapselt eine Datenvariable, die den Parameter enthält. Übergeben wird dann eine Klassenreferenz. Der inout-Parameter wird als Kombination aus Call-by-Value und Call-by-Reference übergeben. Auch dieser Parametertyp wird auf eine Holder-Klasse abgebildet.

Operationen können weiterhin angeben, dass eine Exception ausgelöst werden kann, indem der Bezeichner raises verwendet wird. Exceptions müssen allerdings deklariert werden, bevor sie verwendet werden können. Das folgende Beispiel verdeutlicht die Verwendung der Parameter und der Exceptions. In diesem Beispiel wird eine Methode zur Passwortabfrage angegeben, die ein Argument pwd erwartet und die eine Ausnahme vom Typ PwdException auslösen kann.

code 

//IDL-Code ....

interface passwort {

    void getPasswort (out string pwd) raises (PwdException)

};

IDL-Exceptions

IDL-Exceptions werden als Objektreferenzen übergeben, ähnlich wie auch in Java. Allerdings werden diese Referenzen nicht direkt auf Java-Exceptions abgebildet. IDL-Exceptions erweitern die Klasse org.omg.CORBA.UserException und können Daten enthalten, die als public deklarierte Teile einer Klasse sind. Die Übergabe der Daten erfolgt bei der Erzeugung der Exception. Definiert man bspw. eine Passwort-Exception wie im Folgenden angegeben, so ergibt sich der Java-Code, der anschließend aufgeführt ist.

code 

exception PwdException {

    string grund;

}

code 

/*
 * File: ./PWDEXCEPTION.JAVA
 * From: EXCEPTION.IDL
 * Date: Thu May 27 14:05:18 1999
 *   By: idltojava Java IDL 1.2 Aug 18 1998 16:25:34
 */

public final class PwdException extends org.omg.CORBA.UserException implements org.omg.CORBA.portable.IDLEntity {

    //instance variables
    public String grund;

    //constructors
    public PwdException() {

      super();

    }
    public PwdException(String __grund) {

      super();
      grund = __grund;

    }

}

IDL-struct

Die IDL-Anweisung struct ist eine Container-Klasse zur Datengruppierung, mittels derer eine Menge an Daten in einem Schritt übergeben werden kann. Ein IDL-struct wird auf eine Java-Klasse abgebildet, deren Elemente als public deklariert sind. Im Folgenden ist ein IDL-struct und die entsprechende Java-Klasse angegeben.

code 

struct Person {

    string pname;
    string email;

};

code 

/*
 * File: ./PERSON.JAVA
 * From: PERSON.IDL
 * Date: Thu May 27 14:14:52 1999
 *   By: idltojava Java IDL 1.2 Aug 18 1998 16:25:34
 */

public final class Person implements org.omg.CORBA.portable.IDLEntity {

    //instance variables
    public String pname;
    public String email;

    //constructors
    public Person() { }

    public Person(String __pname, String __email) {

      pname = __pname;
      email = __email;

    }

}

IDL-typedef

Um neue Typen in IDL definieren zu können, wird der Bezeichner typedef verwendet. Derartige Konstrukte werden nicht direkt auf Java abgebildet. Der IDL-Compiler ersetzt daher typedef-Vorkommen mit dem passenden IDL-Typ, bevor die IDL-Spezifikation übersetzt wird. Mittels typedef können IDL-Spezifikationen klarer gegliedert werden, insbesondere dann, wenn zusätzlich der im Folgenden erläuterte Bezeichner sequence verwendet wird. Im Folgenden ist ein Beispiel für die Verwendung dieses Bezeichners angegeben:

code 

typedef string Passwort;

IDL-sequence

Mittels des IDL-Bezeichners sequence werden eindimensionale Arrays definiert, die feste Grenzen haben, die aber auch nicht näher bezeichnete Intervalle umfassen können. Ein begrenzter Array definiert die Anzahl der Elemente einer Liste.

Wird ein Argument verpackt (Marshaling) und gesendet, so wird geprüft, ob die Begrenzung des Arrays eingehalten worden ist. Ist dies nicht der Fall, so wird eine MARSHAL-Ausnahme erzeugt. Sowohl begrenzte als auch unbegrenzte Sequenzen erzeugen eine Helper- und eine Holder-Klasse in Java für jede Sequenz. Ein Beispiel für dieses Konstrukt ist im Folgenden angegeben.

code 

typedef sequence <string, 10> passwoerter;

IDL-Arrays

Um einen Array mit einer festen Begrenzung zu erzeugen, wird eine Notation verwendet, die der in Java ähnelt (eckige Klammern). Array-Konstrukte werden auf dieselbe Art und Weise in Java umgewandelt, wie begrenzte Sequenzen, allerdings mit einer anderen Semantik. Das folgende Beispiel verdeutlicht die Verwendung von Arrays:

code 

typedef string passwoerter[10];

IDL-enum

Um eine Aufzählung zu verwenden, wird in IDL der Bezeichner enum verwendet. Dieses Konstrukt wird auf eine Java-Klasse abgebildet, die als final deklariert ist. Das folgende Beispiel definiert zuerst eine IDL-Aufzählung und zeigt anschließend die entsprechende Java-Klasse.

code 

enum PasswoerterListe {pwd1, pwd2, stephan, abed};

code 

/*
 * File: ./PASSWOERTERLISTE.JAVA
 * From: PWDLISTE.IDL
 * Date: Thu May 27 14:45:38 1999
 *   By: idltojava Java IDL 1.2 Aug 18 1998 16:25:34
 */

public final class PasswoerterListe implements  org.omg.CORBA.portable.IDLEntity {

    public static final int _pwd1 = 0,_pwd2 = 1,_stephan = 2, _abed = 3;

    public static final PasswoerterListe pwd1 = new PasswoerterListe(_pwd1);

    public static final PasswoerterListe pwd2 = new PasswoerterListe(_pwd2);

    public static final PasswoerterListe stephan = new PasswoerterListe(_stephan);

    public static final PasswoerterListe abed = new PasswoerterListe(_abed);

    public int value() {

      return _value;

    }

    public static final PasswoerterListe from_int(int i)  throws  org.omg.CORBA.BAD_PARAM {

      switch (i) {

        case _pwd1:

          return pwd1;

        case _pwd2:

          return pwd2;

        case _stephan:

          return stephan;

        case _abed:

          return abed;

        default:

          throw new org.omg.CORBA.BAD_PARAM();

      }

    }

    private PasswoerterListe(int _value){

      this._value = _value;

    }

    private int _value;

}

Nachdem nun die wichtigsten Konzepte von CORBA und IDL erklärt wurden, wird im Folgenden im Rahmen des Anwendungsbeispiels die Verwendung von CORBA anhand einer praktischen Implementierung erläutert.


SPNavRight SPNavRight SPNavRight
BuiltByNOF