Java ORB の移植性インタフェース

8


8.1 はじめに

ここで示す API は、移植可能なスタブやスケルトンを Java ORB で使用できるようにするために必要な、最低限の機能群を提供します。Java の相互運用性には、ほかの言語より厳しい要件が要求されます。Java のクラスは、使用される ORB とは関係のない場所からダウンロードされることが多いため、スタブとスケルトンが使うインタフェースの定義が不可欠です。インタフェースが定義されていない場合は、スタブまたはスケルトンの使用には、ORB ベンダーが提供するツールでスタブやスケルトンが生成されていること (つまり使用される ORB と互換性があること)、またはスタブやスケルトンと一緒に ORB のランタイム全体がダウンロードされることが必要になります。どちらの方法も受け入れにくいものです。

8.1.1 設計の目標

設計では、いくつかの目標があります。

ブラウザ環境でダウンロードに要する時間を短くし、Java VM にバンドルされる際のメモリの必要量を最小にするには (特にセットトップボックスなどの特殊な環境において)、スタブとスケルトンのバイトコードサイズを小さくする必要があります。
当然のことながら、生成されたスタブコードの実行時のパフォーマンスが優れていなければなりません。特に、Java VM のガベージコレクションによるオーバーヘッドを避けるには、呼び出し中の一時的な Java オブジェクトの作成が最小限になるように注意する必要があります。
IDL から Java へのコンパイラと Java から IDL への逆方向のマッピングツールによって生成されるスタブとスケルトンが相互運用性を持ちバイナリ互換であることを保証するために、構造体や例外などのユーザ定義型にメソッドを追加することは要求されていません。

ここでは、非常に単純な委譲の方式が規定されています。基本的に、インタフェース API を実装している限り、ORB ベンダーは、自分たちが提供する ORB インタフェースに最大限の柔軟性を持たせることができます。もちろんベンダーは、自らの ORB ランタイムに独自の拡張を自由に施すことができます。独自の拡張が必要なスタブやスケルトンは、移植性や相互運用性を必ずしも備えているとは限らず、また対応するランタイムのダウンロードが必要な場合もあります。

8.1.2 移植性のあるパッケージ

移植性の実装が必要な API は、org.omg.CORBA.portable パッケージの中にあります。

移植性のあるパッケージには、ORB の実装者が使用することを想定して設計された、インタフェースとクラスが含まれています。パッケージでは public として定義された API が公開されており、この API を使ってスタブやスケルトンを ORB に接続します。

8.2 アーキテクチャ

スタブやスケルトンの移植性アーキテクチャにより、DII や DSI を移植性を持つレイヤーとして使用できます。DII と DSI PIDL のマッピングは、移植性のあるスタブやスケルトンの効率的な実装をサポートするオペレーションを備えています。

すべてのスタブは、共通の基底クラス org.omg.CORBA.portable.ObjectImpl を継承します。このクラスを通して、is_a() などの共有機能がベンダー固有の実装に委譲されます。このモデルにより、ベンダーに依存する実装には幅広い選択肢が与えられる一方で、クライアント側やサーバでの「コードの肥大化」が緩和されます。

DSI ベースのスケルトンはすべて、org.omg.CORBA.DynamicImplementation を継承します。

8.3 ストリーマブル API

ストリーマブルインタフェース API は、複雑なデータ型の読み取りと書き込みをサポートします。この API は、ヘルパークラスの static メソッドとして実装されます。また、ホルダークラスでも、out や inout のパラメータとして渡される複雑なデータ型の読み取りと書き込みに使用されます。

package org.omg.CORBA.portable;
public interface Streamable {
    void _read(org.omg.CORBA.portable.InputStream
istream);
    void _write(org.omg.CORBA.portable.OutputStream
ostream);
    org.omg.CORBA.TypeCode _type();
}

8.4 ストリーム API

ストリーム API は、マッピングされるすべての IDL 型をストリームから読み取ったりストリームに書き込んだりするための、Java インタフェースです。ORB の内部では、この API の実装を使ってパラメータを整列化したり、Any に対する複雑なデータ型の挿入や取得を行なったりします。

ストリーム API は、org.omg.CORBA.portable パッケージの中にあります。

ORB オブジェクトは、出力ストリームを作るためのファクトリとして使われます。入力ストリームは、出力ストリームから作成される場合があります。

package org.omg.CORBA;
interface ORB {
        OutputStream        create_output_stream();
};

package org.omg.CORBA.portable;
public abstract class InputStream {
    public abstract boolean read_boolean();
    public abstract char    read_char();
    public abstract char    read_wchar();
    public abstract byte    read_octet();
    public abstract short   read_short();
    public abstract short   read_ushort();
    public abstract int     read_long();
    public abstract int     read_ulong();
    public abstract long    read_longlong();
    public abstract long    read_ulonglong();
    public abstract float   read_float();
    public abstract double  read_double();
    public abstract String  read_string();
    public abstract String  read_wstring();
    public abstract void    read_boolean_array(boolean[] value,
                            int offset, int length);
    public abstract void    read_char_array(char[] value,
                            int offset, int length);
    public abstract void    read_wchar_array(char[] value,
                            int offset, int length);
    public abstract void    read_octet_array(byte[] value,
                            int offset, int length);
    public abstract void    read_short_array(short[] value,
                            int offset, int length);
    public abstract void    read_ushort_array(short[] value,
                            int offset, int length);
    public abstract void    read_long_array(int[] value,
                            int offset, int length);
    public abstract void    read_ulong_array(int[] value,
                            int offset, int length);
    public abstract void    read_longlong_array(long[] value,
                            int offset, int length);
    public abstract void    read_ulonglong_array(long[] value,
                            int offset, int length);
    public abstract void    read_float_array(float[] value,
                            int offset, int length);
    public abstract void    read_double_array(double[] value,
                            int offset, int length);
    public abstract org.omg.CORBA.Object read_Object();
    public abstract org.omg.CORBA.TypeCode read_TypeCode();
    public abstract org.omg.CORBA.Any read_any();
    public abstract org.omg.CORBA.Principal read_Principal();
}

public abstract class OutputStream {
    public abstract InputStream create_input_stream();
    public abstract void         write_boolean(boolean value);
    public abstract void         write_char(char value);
    public abstract void         write_wchar(char value);
    public abstract void         write_octet(byte value);
    public abstract void         write_short(short value);
    public abstract void         write_ushort(short value);
    public abstract void         write_long(int value);
    public abstract void         write_ulong(int value);
    public abstract void         write_longlong(long value);
    public abstract void         write_ulonglong(long value);
    public abstract void         write_float(float value);
    public abstract void         write_double(double value);
    public abstract void         write_string(String value);
    public abstract void         write_wstring(String value);
    public abstract void         write_boolean_array(boolean[] value,
                                 int offset, int length);
    public abstract void         write_char_array(char[] value,
                                 int offset, int length);
    public abstract void         write_wchar_array(char[] value,
                                 int offset, int length);
    public abstract void         write_octet_array(byte[] value,
                                 int offset, int length);
    public abstract void         write_short_array(short[] value,
                                 int offset, int length);
    public abstract void         write_ushort_array(short[] value,
                                 int offset, int length);
    public abstract void         write_long_array(int[] value,
                                 int offset, int length);
    public abstract void         write_ulong_array(int[]value,
                                 int offset, int length);
    public abstract void         write_longlong_array(long[]value,
                                 int offset, int length);
    public abstract void         write_ulonglong_array(long[] value,
                                 int offset, int length);
    public abstract void         write_float_array(float[] value,
                                 int offset, int length);
    public abstract void         write_double_array(double[]value,
                                 int offset, int length);
    public abstract void         write_Object(org.omg.CORBA.Object value);
    public abstract void         write_TypeCode(org.omg.CORBA.TypeCode value);
    public abstract void         write_any(org.omg.CORBA.Any value);
    public abstract void         write_Principal(org.omg.CORBA.Principal value);
}

8.5 移植性のあるスタブインタフェース

8.5.1 スタブの設計

スタブクラスは、DII の最上位に実装されます。

8.5.2 移植性のある ObjectImpl

ObjectImpl クラスは、スタブとスケルトンの基底クラスです。このクラスは、基本的な委譲機構を提供しています。

メソッド _ids() は、オブジェクトが実装するリポジトリ ID の配列を返します。添え字が 0 の文字列は、もっとも派生の多いインタフェースを表しています。CORBA の汎用オブジェクト (つまり IDL:omg.org/CORBA/Object:1.0) を示す最後の ID は、そのように想定されてはいますが、実際には存在していません。

package org.omg.CORBA.portable;
abstract public class ObjectImpl implements
org.omg.CORBA.Object {
    private Delegate __delegate;
    public Delegate _get_delegate() {
        if (__delegate == null) {
            throw new org.omg.CORBA.BAD_OPERATION();
        }
        return _delegate;
    }
    public void _set_delegate(Delegate delegate) {
        __delegate = delegate;
    }
    public abstract String[] _ids() {...}
// methods for standard CORBA stuff
    public org.omg.CORBA.ImplementationDef
      _get_implementation() {
        return _get_delegate().get_implementation(this);
    }
    public org.omg.CORBA.InterfaceDef
      _get_interface() {
        return _get_delegate().get_interface(this);
    }
    public org.omg.CORBA.Object _duplicate() {
        return _get_delegate().duplicate(this);
    }
    public void _release() {
        _get_delegate().release(this);
    }
    public boolean _is_a(String repository_id) {
        return _get_delegate().is_a(this, repository_id);
    }
    public boolean _is_equivalent(org.omg.CORBA.Object rhs) {
        return _get_delegate().is_equivalent(this, rhs);
    }
    public boolean _non_existent() {
        return _get_delegate().non_existent(this);
    }
    public int _hash(int maximum) {
        return _get_delegate().hash(this, maximum);
    }
    public org.omg.CORBA.Request _request(String operation) {
        return _get_delegate().request(this, operation);
    }
    public org.omg.CORBA.Request _create_request(
                 org.omg.CORBA.Context ctx,
                 String operation,
                 org.omg.CORBA.NVList arg_list,
                 org.omg.CORBA.NamedValue result) {
                   return _get_delegate().create_request(this, ctx,
                      operation, arg_list, result);
    }
    public Request _create_request(
                 org.omg.CORBA.Context ctx,
                 String operation,
                 org.omg.CORBA.NVList arg_list,
                 org.omg.CORBA.NamedValue result,
                 org.omg.CORBA.ExceptionList exceptions,
                 org.omg.CORBA.ContextList contexts) {
                   return _get_delegate().create_request(this, ctx, operation,
                     arg_list, result,exceptions, contexts);
    }
}

8.6 Delegate

Delegate クラスを使うと、ORB ベンダーは個別に CORBA オブジェクトを実装できます。

// Java
package org.omg.CORBA.portable;
public abstract class Delegate {
    public abstract org.omg.CORBA ImplementationDef get_implementation(
                                org.omg.CORBA.Object self);
    public abstract org.omg.CORBA.InterfaceDef get_interface(
                                org.omg.CORBA.Object self);
    public abstract org.omg.CORBA.Object duplicate(
                                org.omg.CORBA.Object self);
    public abstract void release(org.omg.CORBA.Object self);
    public abstract boolean is_a(org.omg.CORBA.Object self,
                                String repository_id);
    public abstract boolean non_existent(org.omg.CORBA.Object self);
    public abstract boolean is_equivalent(org.omg.CORBA.Object self,
                                org.omg.CORBA.Object rhs);
    public abstract int hash(org.omg.CORBA.Object self,
                                int max);
    public abstract org.omg.CORBA.Request request(org.omg.CORBA.Object self,
                                String operation);
    public abstract org.omg.CORBA.Request create_request(
                                org.omg.CORBA.Object self,
                                org.omg.CORBA.Context ctx,
                                String operation,
                                org.omg.CORBA.NVList arg_list,
                                org.omg.CORBA.NamedValue result);
    public abstract org.omg.CORBA.Request create_request(
                                org.omg.CORBA.Object self,
                                org.omg.CORBA.Context ctx,
                                String operation,
                                org.omg.CORBA.NVList arg_list,
                                org.omg.CORBA.NamedValue result,
                                org.omg.CORBA.ExceptionList excepts,
                                org.omg.CORBA.ContextList contexts);
}

8.7 スケルトン

スケルトンは、DynamicImplementation (「6.10 ServerRequest と DynamicImplementation」を参照) を使用します。

詳細については、「7.2.2 サーバントクラス」を参照してください。

8.8 ORB の初期化

ORB クラスは、CORBA ORB の実装を表しています。ベンダー固有の ORB の実装では、このクラスを継承して、新しい機能を追加できます。

ORB のインスタンスを作成する際には、考慮すべき事柄がいくつかあります。使われているのがブラウザのアプレットか、またはスタンドアロンの Java アプリケーションかということは、重要な要素です。

ORB インスタンスの作成時には、常に、実装されている ORB のクラス名が次の順序で探索されます。

8.8.1 標準のプロパティ

次の表は、OMG の標準プロパティの定義です。

表  8-1
プロパティの名前
プロパティの値

org.omg.CORBA.ORBClass

実装された ORB のクラス名

org.omg.CORBA.ORBSingletonClass

実装された単独 ORB のクラス名

8.8.2 ORB の初期化メソッド

次に示すように、初期化には 3 種類の形式があります。さらに、ORB の実際の実装 (ORB からのサブクラス化) では、初期化パラメータが初期化メソッドから ORB に渡されるように、set_parameters() メソッドを実装する必要があります。

// Java
package org.omg.CORBA;
abstract public class ORB {
    // Application init
    public static ORB init(String[] args,
      java.util.Properties props) {
        // call to: set_parameters(args, props);
        ...
        }
    // Applet init
    public static ORB init(java.applet.Applet app,
      java.util.Properties props) {
        // call to: set_parameters(app, props);
        ...
        }
    // Default (singleton) init
    public static ORB init()
        {...}
    // Implemented by subclassed ORB implementations
    //  and called by init methods to pass in their params
    abstract protected void set_parameters(String[] args,
        java.util.Properties props);
    abstract protected void set_parameters(Applet app,
        java.util.Properties props);
}

8.8.2.1 デフォルトの初期化

デフォルトの初期化メソッドからは、単独 ORB が返されます。繰り返し呼び出された場合は、常に同じ Java オブジェクトが返されます。

引数がない形式の ORB.init() を使う主な目的は、type() メソッドを実装するヘルパークラスが使用できるように TypeCode にファクトリを提供すること、および union TypeCode の作成の一部として union ラベルを記述するために使われる Any インスタンスを作ることです。ヘルパークラスはブラウザに組み込まれている場合があるため (インタフェースリポジトリスタブまたはほかの広く利用されている IDL など)、ブラウザにダウンロードされた信頼性のないアプレットの間で共有される可能性があります。返される ORB のインスタンスは、すべてのアプレットによって共有されるので、関係のないアプレット同士が分離されるように、機能を明確に制限する必要があります。アプレットからインスタンスが直接使用されることは想定されていません。したがって、ORB.init() から返される ORB は、Java アプレットから呼び出される場合、Typecode を作るためだけに使われます。ほかの「正規の」ORB オペレーションを呼び出そうとすると、システム例外が発生します。

アプリケーションから呼び出される場合は、完全な機能を備えた ORB オブジェクトが返されます。

8.8.2.2 アプリケーションの初期化

アプリケーション初期化メソッドは、スタンドアロンの Java アプリケーションから使う必要があります。メソッドには、コマンドの引数および Java プロパティのリストである文字列の配列を渡します。引数配列またはプロパティのどちらか一方には、null を指定できます。

メソッドを呼び出すたびに、完全な機能を備えた新しい ORB Java オブジェクトが返されます。

8.8.2.3 アプレットの初期化

アプレット初期化メソッドは、アプレットから使う必要があります。メソッドには、「アプレット」と Java プロパティのリストを渡します。アプレットまたはプロパティのどちらか一方には、null を指定できます。

メソッドを呼び出すたびに、完全な機能を備えた新しい ORB Java オブジェクトが返されます。