Java IDL および Java RMI-IIOP テクノロジ: ポータブルインタセプタ (PI) の使用

最終更新日: 4/25/2002

注: このドキュメントは、高度な知識を持つ CORBA 開発者を対象としています。

Java CORBA Object Request Broker (ORB) は、フック (遮断点) を提供し、ORB サービスはこのフックを使って ORB の通常の実行の流れを遮断することができます。これらの「ポータブルインタセプタ」は、追加の ORB の動作をプラグインするためのメカニズムと、クライアントとサーバー間の通信を変更することによって ORB の動作を変更するためのメカニズムを提供します。このあとのでは、ポータブルインタセプタのさまざまな使い方について説明します。

ポータブルインタセプタのサポートは、CORBA 仕様に最近追加された重要な機能です。RequestInterceptor を使用すると、ORB が仲介する任意の呼び出しを遮断するポータブル ORB フックを簡単に記述して接続することができます。IORInterceptor を使用すると、CORBA オブジェクト参照に注釈を付けるためのコードを記述できます。

このドキュメントを読む前に、ポータブルインタセプタの仕様 (ptc/2001-03-04) をお読みになることを強くお勧めします。

このドキュメントでは、次のようなトピックについて説明します。

インタセプタの型

現在、登録できるインタセプタには次の 3 つの型があります。それぞれの例についてはこのあとので説明します。

Java での ORBInitializers の登録

ORBInitializer インタフェースを利用すると、インタセプタの登録と ORB の初期化が簡単になります。

インタセプタは、ORB サービスが ORB 処理にアクセスして、事実上 ORB の一部になるための手段となるよう意図されています。インタセプタは ORB の一部であるため、ORB.init が ORB を返すときは、インタセプタの登録が完了しています。ORB.init への呼び出しで返されたあとは、インタセプタはその ORB に登録できません。

ORBInitializers は、Java ORB プロパティーを経由して登録されます。インタセプタの登録は、ORBInitializer インタフェースを実装する関連付けられている ORBInitializer オブジェクトを登録する方法で行われます。ORB は、初期化しているときに、登録されている各 ORBInitializer を呼び出し、そのインタセプタの登録に使用される ORBInitInfo オブジェクトをそれに渡します。

プロパティー名は、次の形式をとります。

org.omg.PortableInterceptor.ORBInitializerClass.<Service>

<Service> は、次のプロパティーを実装するクラスの文字列名です。

org.omg.PortableInterceptor.ORBInitializer
名前の競合を防ぐため、逆方向の DNS 命名規則が使用されます。たとえば、Example 社に初期化子が 3 つある場合、次のプロパティーを定義できます。

注: ORBInitializerClass プロパティーに値を関連付けても、すべて無視されます。

ORB.init の実行中は、org.omg.PortableInterceptor.ORBInitializerClass で始まるこれらの ORB プロパティーが収集され、各プロパティーの <Service> 部分が取り出され、クラス名に <Service> 文字列を使用してオブジェクトがインスタンス化され、そのオブジェクトに対して pre_initpost_init の各メソッドが呼び出されます。例外が発生しても、ORB はそれを無視して、処理を続行します。

インタセプタのスコープに関する注意

インタセプタの順序に関する注意

インタセプタ登録時の注意

Portable Interceptor Current (PICurrent)

PortableInterceptor::Current オブジェクト (これ以降 PICurrent と呼ぶ) は、ポータブルインタセプタが、スレッドのコンテキスト情報を要求コンテキストに転送するために使用する Current オブジェクトです。ポータブルインタセプタは、PICurrent を常に使用する必要はありませんが、インタセプタの遮断点で、クライアントのスレッドコンテキストの情報が必要な場合は、PICurrent を使用してその情報を伝播することができます。PICurrent を使用すると、ORB のスレッドモデルにかかわらず移植性のあるサービスコードを記述できます。

注: PICurrent は通常、CORBA のクライアントコードまたはサーバーコードから直接使用されることはありません。一般には、このあと説明する AService というインタセプタの例で紹介されているように、インタセプタベースのサービス実装により使用されます。

PICurrent の取得

PICurrent は、呼び出しを行う前に、ORB::resolve_initial_references (PICurrent) の呼び出しによって取得されます。スレッドスコープから要求スコープに移動した PICurrent のデータは、遮断点の内部から、RequestInfo オブジェクトに対する get_slot オペレーションを介して利用できます。PICurrent は引き続き resolve_initial_references を介して取得できますが、それはインタセプタのスレッドスコープの PICurrent となります。

要求スコープとスレッドスコープの比較

スレッドスコープの PICurrent (TSC) は、スレッドのコンテキスト内に存在する PICurrent です。要求スコープの PICurrent (RSC) は、要求に関連付けられている PICurrent です。クライアント側では、要求の開始時に、スレッドスコープの PICurrent が、スレッドコンテキストから要求スコープの PICurrent に論理的にコピーされ、ClientRequestInfo オブジェクトに接続されます。サーバー側では、要求スコープの PICurrentServerRequestInfo に接続されてから、要求の処理が行われます。要求スコープの PICurrent は、receive_request_service_contexts 遮断点のリストが処理されたあとに、スレッドスコープの PICurrent に論理的にコピーされます。PICurrent のスコープの詳細については、『Updated Interceptors specification』の「21.4.4.5 Flow of PICurrent between Scopes」を参照してください。

ポータブルインタセプタの例

ここでは、ロギングサービスアプリケーションの例について説明します。このアプリケーションのサンプルコードは、複雑かつ「特殊なケース」を扱うため、非常に複雑になっています。このサンプルアプリケーションでは次のシナリオを扱います。

  1. 呼び出しをログに記録するロギングサービス。クライアントとサーバーのどちらもこのロギングサービスを明示的に使用しない。
  2. クライアントからサーバーに情報を渡す「空の」サービス。クライアントとサーバーは、このサービスを明示的に使用するが、インタセプタを使用してサービスが実装されていることを認識していない。

注: 次の例では、コードを簡単に試してセットアップできるように、ORBInitializer を明示的に登録しています。一般的にはこのような処理は行いません。通常、この情報は、アプリケーションの起動時に -D プロパティーとして Java 仮想マシンに渡されます。この方法を使うと、サービス (たとえばロギングサービス) が存在するかどうか、あるいはアプリケーションが明示的に使用するサービス (たとえば AService インタフェース) がインタセプタとして実装されるかどうかという事実にアプリケーションが束縛されなくなります。

ロギングサービスの例を紹介する目的は、遮断点内から発信呼び出し (つまり、CORBA 参照に対する呼び出し) を行うときに無限再帰を回避する方法を説明することです。これは、あらゆるケースを網羅しようとすると、かなり複雑になることがあります。

「空の」サービスの例を紹介する目的は、コンテキスト情報をクライアントとサーバーの間でやり取りするサービスの実装方法を説明することです。

クライアントとサーバーの間でのコンテキスト情報のやり取り

典型的なインタセプタベースのサービスでは、コンテキスト情報をクライアントとサーバーの間でやり取りします。AService の例は、この情報がクライアントのスレッドからクライアントのインタセプタに流れ、ワイヤーを経由してサーバーのインタセプタに入り、サーバントのスレッドに届くというフローや、その逆のフローについて説明するものです。

サービスがインタセプタを使用して実装されているということを、クライアントとサーバントがどちらも意識しないという点が重要です。そのどちらも、ローカルオブジェクト参照 (この例では aService 参照) を介してサービスと対話しているだけです。

AService の説明図

AService の説明図

AService の説明図にある各ステップについての説明は次のとおりです。

  1. クライアントが aService.begin() を呼び出します。

    1.a. aService.begin() は、PICurrent に予約済みのスロットに、サービスのコンテキスト情報を設定します。

  2. クライアントは、何らかの参照上にあるメソッド (つまり、ref.method()) を呼び出します。この呼び出しは、aService.begin() を呼び出した以降のサービスコンテキスト内で行われます。
  3. ref.method call のために、send_request に入ります。
  4. 呼び出された参照がサービスとの対話を必要とするかどうかを判別するために、get_effective_component(s) が呼び出されます。
  5. ステップ 1a で設定されたコンテキストを取得するために、get_slot が呼び出されます。PICurrent に設定されたスロットが論理的にコピーされて、ClientRequestInfo がそのスロットを利用できるようになります。
  6. サービスインタセプタが、適切なコンテキスト (ほとんどの場合、ステップ 1a で設定されたコンテキストと、ステップ 4 で取得されたコンポーネントによって決まる) を含むサービスコンテキストを追加します。サービスインタセプタは add_request_service_context を使用して、ワイヤー上を送信される要求にこのコンテキスト情報を追加します。
  7. ref.method request がサーバーに到着し、receive_request_service_contexts 遮断点を起動します。
  8. get_request_service_context を使用して、ステップ 6 で追加されたサービスコンテキストが取得されます。
  9. ServerRequestInfo.set_slot を使用して、ステップ 8 で取得されたサービスコンテキストが、論理的なスレッドローカルのデータに転送されます。
  10. receive_request に入ります。
  11. 「ref」サーバントの「メソッド」に入ります。
  12. サーバントのメソッドは、aService.verify() を呼び出してサービスと対話します。
  13. サービスは、PICurrent に対し get_slot を使用して、クライアント側から送信されたコンテキスト情報を取得します。さらに、サービスは、PICurrent に対して set_slot を使用して、返信するためのコンテキスト情報を設定することもあります。
  14. サーバントの処理が完了すると、send_* 遮断点に入ります。サービスが返信用のコンテキスト情報を設定した場合は、返信の内容にサービスコンテキストが追加されます。この点は、この例では示されていません。
  15. 応答がクライアントに到着すると、receive_* 遮断点に入ります。サービスが返信用のコンテキスト情報を設定した場合は、この時点でその情報が取得されます。この点は、この例では示されていません。

インタセプタの発信呼び出し時の無限再帰を回避する

サービスによっては、遮断点内から別の CORBA オブジェクト参照に対する呼び出しを行う必要があります。遮断点内から発信呼び出しを行うときには、無限再帰を回避するための処置をとる必要があります。それらの発信呼び出しが遮断点を経由するからです。LoggingService の例では、このケースについて説明します。

LoggingService の例は、クライアントプログラムに登録された ClientRequestInterceptors と、サーバープログラムに登録された ServerRequestInterceptors とで構成されます。これらのインタセプタは、クライアントおよびサーバーから LoggingService の実装に情報を送信します。LoggingService の実装は、その情報をログに記録します。

ただし、LoggingService の実装はそれ自体が CORBA サーバーであるので、ロガーに対する呼び出しはログに記録しないようにする必要があります。次の図は、無限再帰を回避するためにとるべき処置を示しています。

次の図では、インタセプタ内から外部のロガーを呼び出すという、再帰を回避するべきもっとも単純なケースを示します。ここで説明する手順は、クライアント ORB に ClientRequestInterceptors だけを含み、サーバー ORB に ServerRequestInterceptors だけを含み、LoggingService がクライアント ORB とサーバー ORB の両方に対して外部にあるというケースに役立ちます。

LoggingService の説明図

ロギングサービスの説明図

LoggingService の説明図にある各ステップについて、次に説明します。

  1. クライアントは、何かの参照上にあるメソッドを呼び出します。
  2. ステップ 1 で呼び出されたメソッドのために、クライアントインタセプタの send_request メソッドに入ります。
  3. 発信呼び出しを示すために予約済みの PICurrent 上のスロットが true に設定されます。
  4. get_slot により、ClientRequestInfo 上の同じスロットがチェックされます。この値は、ステップ 1 でのクライアントのスレッドの状態を表しているため、設定されていません。したがって、ロガーに対する呼び出しが実行されることになります。
  5. ステップ 4 で行われたロガー呼び出しのために、send_request に再帰的に入ります。
  6. 発信呼び出しを示すために予約済みの PICurrent 上のスロットが true に設定されます。このスロットは、いつも無条件で設定されることに注意してください。それは、発信呼び出しを行うインタセプタが 2 つ以上あるときに必要な処置です。各インタセプタはほかのインタセプタの存在を認識していないので、いつも PICurrent スロットを設定することにします。
  7. get_slot により、ClientRequestInfo 上のスロットがチェックされます。今回は、値が設定されています (ステップ 3 より)。したがって、この呼び出し (ロガーそのものに対する呼び出し) はログに記録しません。ステップ 5 で入った send_request ポイントが終了します。
  8. ORB は、ステップ 4 で行われたログ呼び出しをロギングサービスに送信します。
  9. ステップ 2 で入った send_request ポイントが終了します。ORB は、ステップ 1 で行われた最初のクライアント呼び出しを、サーバーの該当する参照に対して送信します。
  10. サーバーの receive_request_service_contexts ポイントに入ります。これにより、着信要求がログに記録されます。発信呼び出しを行うクライアントインタセプタが含まれておらず、ロガーの実装そのものも含まれていないサーバーの場合、再帰を回避するスロットを設定する必要はありません。この図は、そのようなケースを表しています。
  11. -   13.    したがって、サーバー側の遮断点にはすべて余分なチェックなしで入り、クライアントによって最初に呼び出されたメソッドからの応答がクライアント ORB に返信されます。
  12. クライアントの receive_* ポイントに入ります。この時点で発信呼び出しを行う必要がある場合には、ステップ 2 - 9 と同様の処理を行います。

発信呼び出しの参照先が同じ場所にある場合に再帰を回避する

次の図は、クライアントによって呼び出される参照と同じ ORB に LoggingService があるというケースを示しています。一般に、特定のオブジェクト参照が、その ORB によってホストされているほかのオブジェクトと同じ場所にないということを識別するのは不可能です。したがって、あらゆるケースを網羅するために、さらに処置をとる必要があります。

この図は、サーバー側だけを示したものです。クライアント側の手順は、前の図にある手順と同じです。

LoggingServiceColocated の説明図

LoggingServiceColocated の説明図

LoggingServiceColocated の説明図にある各ステップについて、次に説明します。

  1. クライアント ORB から要求がサーバーに到着し、receive_request_service_contexts 遮断点を起動します。
  2. 発信呼び出しを示すために予約済みの PICurrent 上のスロットが true に設定されます。
  3. ServerRequestInfo.get_request_service_context を使用して、発信呼び出しを示すサービスコンテキストが存在するかどうかがチェックされます。サービスコンテキストが存在しないため、遮断点内からロガーが呼び出されます。
  4. ロガー要求のために、send_request 遮断点に入ります。
  5. get_slot により、発信呼び出しインジケータがチェックされます。
  6. 発信呼び出しインジケータは (ステップ 2 で) 設定されているため、add_request_service_context を使用して、発信呼び出しを示すサービスコンテキストが追加されます。クライアントのスレッドとサーバーのスレッドの間には論理的な関係がないので、この処理が必要になります。
  7. ロガー呼び出しが receive_request_service_contexts に到着します。
  8. 発信呼び出しを示すために予約済みの PICurrent 上のスロットが true に設定されます。
  9. ServerRequestInfo.get_request_service_context を使用して、発信呼び出しを示すサービスコンテキストが存在するかどうかがチェックされます。サービスコンテキストが存在するため、これ以上の処理は行われません。receive_request_service_contexts から出ます。
  10. ロガー要求が receive_request に進みます。receive_request 遮断点でロガーが呼び出される場合は、receive_request_service_context 内で行われるのと同様の処理が必要です。この処理は図には示されていません (ただし、コード例ではすべての遮断点をログに記録する)。
  11. ロガー要求が LoggingService サーバントに到着します。このサーバントにより、最初のクライアント要求 (ロガーの呼び出しではない) がログに記録されます。
  12. ロガー要求が ServerRequestInterceptor.send_* (ほとんどの場合は send_reply) に進みます。
  13. ロガー要求が ClientRequestInterceptor.receive_* (ほとんどの場合は receive_reply) に進みます。

    ステップ 13 の後、ステップ 3 で残っている元の要求が処理されることになります。

この例で説明した内容の要点は、クライアントインタセプタとサーバーインタセプタの両方を、発信呼び出しを示す PICurrent スロットおよびサービスコンテキストと一緒に使用する必要があるということです。

複数の ORB を使用することで再帰を回避する

再帰を回避するもっと簡単な方法として、発信呼び出しの参照先を、ロギングインタセプタが登録されていない別の ORB に関連付けるという方法があります。こうすれば、発信呼び出しがインタセプタに入っていくことがありません。

これは簡単な解決方法に思えますが、一般にインタセプタは、起動時に VM に渡すプロパティーによって登録されます。そうすると、その VM 内で作成されるすべての ORB はすべてのインタセプタを含んでいることになるため、この方法はうまくいきません。

この方法がうまくいくようにするには、ORB.init の際にクライアントコード内でインタセプタを明示的に登録します。しかし、そのような方法でインタセプタベースのサービスを登録することは一般的でないため、推奨されていません。

コード例

これまでに紹介した図で説明されているコードが、次のファイルに含まれています。これらの例をコンパイルして実行する方法は、コードの後に記載します。この例に含まれるファイルは次のとおりです。

serviceexample.idl

このファイルは、インタフェース定義言語 (IDL) ファイルで、呼び出しの対象となる任意のオブジェクトの定義と、その任意のオブジェクトに対する呼び出しを実行する 2 つのサービスを含んでいます。


// serviceexample.idl
// Copyright and License 

module pi
{
module serviceexample
{

    // Create some arbitrary object to call.  Those calls
    // will be serviced by the service implemented using interceptors.

    exception ArbitraryObjectException { string reason; };

    interface ArbitraryObject
    {
             string         arbitraryOperation1 ( in string a1 );

        oneway void         arbitraryOperation2 ( in long a1 );

               void         arbitraryOperation3 ( in string a1 )
                                raises (ArbitraryObjectException);
    };


    // This would typically be in a file separate from the "ArbitraryObject"
    // and probably unknown to it.

    interface LoggingService
    {
        void log ( in string a1 );
    };

    // This would also typically be in a file of its own.
    // IMPORTANT: the interface should be a local object to avoid
    // unnecessary overhead.
    
    /*local*/ interface AService
    {
        void begin();
        void end();
        void verify();
    };

    // Tagged component for adding to an IOR to indicate that
    // the AService must be in effect when invocations are made 
    // on the object containing this tagged component.

    // Note: we explicitly declare the tag type rather than using
    // the IOP typedef (commented out) to simplify compiling this
    // example (i.e., to avoid includes and make include path directives).
    //const IOP::ComponentId TAG_ASERVICE_COMPONENT = 2345;
    const unsigned long TAG_ASERVICE_COMPONENT = 2345;

    struct ASERVICE_COMPONENT {
        boolean requiresAService;
    };

}; // module serviceexample

}; // module pi

LoggingServiceClientORBInitializer.java

このファイルでは、オブジェクトのクライアントによって使用されるロギングサービスインタセプタを作成して登録します。


// LoggingServiceClientORBInitializer.java
// Copyright and License 

package pi.serviceexample;

import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.PortableInterceptor.Current;
import org.omg.PortableInterceptor.CurrentHelper;
import org.omg.PortableInterceptor.ORBInitInfo;

public class LoggingServiceClientORBInitializer 
    extends org.omg.CORBA.LocalObject
    implements org.omg.PortableInterceptor.ORBInitializer
{
    public void pre_init(ORBInitInfo info)
    {
    }

    public void post_init(ORBInitInfo info)
    {
        try {

            // Get a reference to the LoggingService object.

            NamingContext nameService = 
                NamingContextHelper.narrow(
                    info.resolve_initial_references("NameService"));

            NameComponent path[] =
                { new NameComponent("LoggingService", "") };
            LoggingService loggingService = 
                LoggingServiceHelper.narrow(nameService.resolve(path));

            // Get a reference to TSC PICurrent.

            Current piCurrent =
                CurrentHelper.narrow(
                    info.resolve_initial_references("PICurrent"));

            // Allocate a slot id to use for the interceptor to indicate
            // that it is making an outcall.  This is used to avoid
            // infinite recursion.

            int outCallIndicatorSlotId = info.allocate_slot_id();

            // Create (with the above data) and register the client
            // side interceptor.

            LoggingServiceClientInterceptor interceptor =
                new LoggingServiceClientInterceptor(loggingService, 
                                                    piCurrent,
                                                    outCallIndicatorSlotId);

            info.add_client_request_interceptor(interceptor);
        } catch (Throwable t) {
            System.out.println("Exception handling not shown.");
        }
    }
}

LoggingServiceClientInterceptor.java

このインタセプタは、クライアント側の遮断点をログに記録します。次のコードは、インタセプタ内からほかのオブジェクトの呼び出しを実行する方法と、それらの「発信」呼び出しでの無限回帰を回避する方法を示しています。


// LoggingServiceClientInterceptor.java
// Copyright and License 

package pi.serviceexample;

import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TCKind;
import org.omg.IOP.ServiceContext;
import org.omg.PortableInterceptor.ClientRequestInterceptor;
import org.omg.PortableInterceptor.ClientRequestInfo;
import org.omg.PortableInterceptor.Current;
import org.omg.PortableInterceptor.InvalidSlot;

public class LoggingServiceClientInterceptor
    extends org.omg.CORBA.LocalObject
    implements ClientRequestInterceptor
{
    private LoggingService loggingService;
    private Current piCurrent;
    private int outCallIndicatorSlotId;

    public LoggingServiceClientInterceptor(LoggingService loggingService,
                                           Current piCurrent,
                                           int outCallIndicatorSlotId)
    {
        this.loggingService = loggingService;
        this.piCurrent = piCurrent;
        this.outCallIndicatorSlotId = outCallIndicatorSlotId;
    }

    //
    // Interceptor operations
    //

    public String name() 
    {
        return "LoggingServiceClientInterceptor";
    }

    public void destroy() 
    {
    }

    //
    // ClientRequestInterceptor operations
    //

    public void send_request(ClientRequestInfo ri)
    {
        log(ri, "send_request");
    }

    public void send_poll(ClientRequestInfo ri)
    {
        log(ri, "send_poll");
    }

    public void receive_reply(ClientRequestInfo ri)
    {
        log(ri, "receive_reply");
    }

    public void receive_exception(ClientRequestInfo ri)
    {
        log(ri, "receive_exception");
    }

    public void receive_other(ClientRequestInfo ri)
    {
        log(ri, "receive_other");
    }

    //
    // Utilities.
    //

    public void log(ClientRequestInfo ri, String point)
    {
        // IMPORTANT: Always set the TSC out call indicator in case
        // other interceptors make outcalls for this request.
        // Otherwise the outcall will not be set for the other interceptor's
        // outcall resulting in infinite recursion.

        Any indicator = ORB.init().create_any();
        indicator.insert_boolean(true);
        try {
            piCurrent.set_slot(outCallIndicatorSlotId, indicator);
        } catch (InvalidSlot e) { }

        try {
            indicator = ri.get_slot(outCallIndicatorSlotId);

            // If the RSC out call slot is not set then log this invocation.
            // If it is set that indicates the interceptor is servicing the
            // invocation of loggingService itself.  In that case do
            // nothing (to avoid infinite recursion).

            if (indicator.type().kind().equals(TCKind.tk_null)) {
                loggingService.log(ri.operation() + " " + point);
            }
        } catch (InvalidSlot e) {
            System.out.println("Exception handling not shown.");            
        }
    }
}

LoggingServiceServerORBInitializer.java

このファイルでは、オブジェクトのサーバーによって使用されるロギングサービスインタセプタを作成して登録します。このインタセプタはサーバー側の遮断点だけをログに記録しますが、クライアントとサーバーの両方のインタセプタになります。次のコードは、呼び出されるオブジェクトが、インタセプタが登録された ORB と同じ ORB に置かれている場合に無限回帰を回避する方法を示しています。

// LoggingServiceServerORBInitializer.java
// Copyright and License 

package pi.serviceexample;

import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.PortableInterceptor.Current;
import org.omg.PortableInterceptor.CurrentHelper;
import org.omg.PortableInterceptor.ORBInitInfo;

public class LoggingServiceServerORBInitializer 
    extends org.omg.CORBA.LocalObject
    implements org.omg.PortableInterceptor.ORBInitializer
{
    public void pre_init(ORBInitInfo info)
    {
    }

    public void post_init(ORBInitInfo info)
    {
        try {

            // Create and register the logging service interceptor.
            // Give that interceptor references to the NameService and
            // PICurrent to avoid further lookups (i.e., optimization).
            // More importantly, allocate and give the interceptor
            // a slot id which is will use to tell itself not to
            // log calls that the interceptor makes to the logging process.

            NamingContext nameService = 
                NamingContextHelper.narrow(
                    info.resolve_initial_references("NameService"));

            Current piCurrent =
                CurrentHelper.narrow(
                    info.resolve_initial_references("PICurrent"));

            int outCallIndicatorSlotId = info.allocate_slot_id();

            LoggingServiceServerInterceptor interceptor =
                new LoggingServiceServerInterceptor(nameService,
                                                    piCurrent,
                                                    outCallIndicatorSlotId);

            info.add_client_request_interceptor(interceptor);
            info.add_server_request_interceptor(interceptor);
        } catch (Throwable t) {
            System.out.println("Exception handling not shown.");
        }
    }
}

LoggingServiceServerInterceptor.java

このインタセプタは、サーバー側の遮断点をログに記録しますが、ClientRequestInterceptor および ServerRequestInterceptor の両方として実装されます。これは、LoggingServiceServerORBInitializer.java の説明で触れたようなケースでの無限回帰を回避するために、「発信呼び出し」サービスコンテキストのデータの一部を (発信呼び出しスロットに加えて) 設定する必要があることを説明するためです。


// LoggingServiceServerInterceptor.java
// Copyright and License 

package pi.serviceexample;

import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TCKind;
import org.omg.IOP.ServiceContext;
import org.omg.PortableInterceptor.ClientRequestInterceptor;
import org.omg.PortableInterceptor.ClientRequestInfo;
import org.omg.PortableInterceptor.Current;
import org.omg.PortableInterceptor.InvalidSlot;
import org.omg.PortableInterceptor.ServerRequestInterceptor;
import org.omg.PortableInterceptor.ServerRequestInfo;

public class LoggingServiceServerInterceptor
    extends org.omg.CORBA.LocalObject
    implements ClientRequestInterceptor,
               ServerRequestInterceptor
{
    private NamingContext nameService;
    private LoggingService loggingService;
    private Current piCurrent;
    private int outCallIndicatorSlotId;
    private static final int serviceContextId = 100001;
    private static final byte[] serviceContextData = {1};

    // Returns a reference to the logging process.

    private LoggingService loggingService()
    {
        if (loggingService == null) {
            NameComponent path[] =
                { new NameComponent("LoggingService", "") };
            try {
                loggingService = 
                    LoggingServiceHelper.narrow(nameService.resolve(path));
            } catch (Throwable t) {
                System.out.println("Exception handling not shown.");
            }
        }
        return loggingService;
    }

    public LoggingServiceServerInterceptor(NamingContext nameService,
                                           Current piCurrent,
                                           int outCallIndicatorSlotId)
    {
        this.nameService = nameService;
        this.piCurrent = piCurrent;
        this.outCallIndicatorSlotId = outCallIndicatorSlotId;
    }

    //
    // Interceptor operations
    //

    public String name() 
    {
        return "LoggingServiceServerInterceptor";
    }

    public void destroy() 
    {
    }

    //
    // ClientRequestInterceptor operations
    //

    public void send_request(ClientRequestInfo ri)
    {

        // If the server interceptor sets the recursion slot then
        // put in the service context so the server doesn't make
        // the call again in the case where the server side interceptor
        // is colocated in the same ORB as the object being invoked.

        try {
            Any indicator = ri.get_slot(outCallIndicatorSlotId);
            if (indicator.type().kind().equals(TCKind.tk_boolean)) {
                ServiceContext serviceContext =
                    new ServiceContext(serviceContextId, serviceContextData);
                ri.add_request_service_context(serviceContext, false);
            }
        } catch (InvalidSlot e) {
            System.out.println("Exception handling not shown.");
        }
    }

    public void send_poll(ClientRequestInfo ri)
    {
    }

    public void receive_reply(ClientRequestInfo ri)
    {
    }

    public void receive_exception(ClientRequestInfo ri)
    {
    }

    public void receive_other(ClientRequestInfo ri)
    {
    }

    //
    // ServerRequestInterceptor operations
    //

    public void receive_request_service_contexts(ServerRequestInfo ri)
    {
        log(ri, "receive_request_service_contexts");
    }

    public void receive_request(ServerRequestInfo ri)
    {
        log(ri, "receive_request");
    }

    public void send_reply(ServerRequestInfo ri)
    {
        log(ri, "send_reply");
    }

    public void send_exception(ServerRequestInfo ri)
    {
        log(ri, "send_exception");
    }

    public void send_other(ServerRequestInfo ri)
    {
        log(ri, "send_other");
    }

    //
    // Utilities.
    //

    public void log(ServerRequestInfo ri, String point)
    {
        // This is only relevant for the colocated example.
        // Do not attempt to log until the logging service object
        // has been bound in naming.  Otherwise the attempt to call
        // rebind on naming will call log which will fail.
        if (! ColocatedServers.colocatedBootstrapDone) {
            return;
        }

        // IMPORTANT:
        // The conditional logging of the invocation is only necessary
        // if there is a chance that the object being invoked is colocated
        // in the same ORB as this interceptor.  Otherwise the outcall to 
        // the logging service can be made unconditionally.

        // Always set the recursion slot.

        Any indicator = ORB.init().create_any();
        indicator.insert_boolean(true);
        try {
            piCurrent.set_slot(outCallIndicatorSlotId, indicator);
        } catch (InvalidSlot e) {
            System.out.println("Exception handling not shown.");
        }

        // Make the out call if you have not already done so.

        try {

            // Only the presence of the service context counts.
            // The data is ignored.

            ri.get_request_service_context(serviceContextId);
        } catch (BAD_PARAM e) {
            // Recursion indicator not set so make the call.
            loggingService().log(ri.operation() + " " + point);
        }
    }
}

LoggingServiceImpl.java

このファイルは、ロギングサービスインタセプタがデータを送信する先のロギングオブジェクトの実装です。

// 
// Copyright and License 

package pi.serviceexample;

import org.omg.CORBA.ORB;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.PortableServer.POAHelper;

import java.util.Properties;

class LoggingServiceImpl
    extends LoggingServicePOA
{
    public static ORB orb;

    //
    // The IDL operations.
    //

    public void log(String a1)
    {
        System.out.println(a1);
    }

    //
    // The server.
    //

    public static void main(String[] av)
    {
        try {
            if (orb == null) {
                orb = ORB.init(av, null);
            }
            
            POA rootPOA =  POAHelper.narrow( orb.resolve_initial_references("RootPOA"));
            rootPOA.the_POAManager().activate();
            
            byte[] objectId =
                rootPOA.activate_object(new LoggingServiceImpl());
            org.omg.CORBA.Object ref = rootPOA.id_to_reference(objectId);

            NamingContext nameService = 
                NamingContextHelper.narrow(
                    orb.resolve_initial_references("NameService"));
            NameComponent path[] =
                { new NameComponent("LoggingService", "") };
            nameService.rebind(path, ref);

            // Only relevant for colocated example.
            ColocatedServers.colocatedBootstrapDone = true;

            System.out.println("LoggingService ready.");

            orb.run();

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
        System.exit(0);
    }
}

AServiceORBInitializer.java

このファイルは、AServiceInterceptor をクライアントとサーバーの両方のインタセプタとして作成して登録し、TaggedComponent を IOR に挿入する AServiceIORInterceptor を作成して登録します。さらに、AService によって提供されるサービスをアプリケーションが明示的に制御するために使用するローカルオブジェクトを作成します。クライアントが org.omg.CORBA.ORB.resolve_initial_references を使用してこのローカルオブジェクトを取得できるように、このローカルオブジェクトは初期サービスとして ORB に登録されます。

// AServiceORBInitializer.java
// Copyright and License 

package pi.serviceexample;

import org.omg.IOP.Codec;
import org.omg.IOP.CodecFactory;
import org.omg.IOP.CodecFactoryHelper;
import org.omg.IOP.Encoding;
import org.omg.PortableInterceptor.Current;
import org.omg.PortableInterceptor.CurrentHelper;
import org.omg.PortableInterceptor.ORBInitInfo;


public class AServiceORBInitializer 
    extends org.omg.CORBA.LocalObject
    implements org.omg.PortableInterceptor.ORBInitializer
{
    private AServiceImpl aServiceImpl;
    private AServiceInterceptor aServiceInterceptor;

    public void pre_init(ORBInitInfo info)
    {
        try {
            int id = info.allocate_slot_id();

            aServiceInterceptor = new AServiceInterceptor(id);

            info.add_client_request_interceptor(aServiceInterceptor);
            info.add_server_request_interceptor(aServiceInterceptor);

            // Create and register a reference to the service to be
            // used by client code.

            aServiceImpl = new AServiceImpl(id);

            info.register_initial_reference("AService", aServiceImpl);

        } catch (Throwable t) {
            System.out.println("Exception handling not shown.");
        }
    }

    public void post_init(ORBInitInfo info)
    {
        try {

            Current piCurrent =
                CurrentHelper.narrow(
                    info.resolve_initial_references("PICurrent"));
            aServiceImpl.setPICurrent(piCurrent);

            CodecFactory codecFactory =
                CodecFactoryHelper.narrow(
                    info.resolve_initial_references("CodecFactory"));
            Encoding encoding = new Encoding((short)0, (byte)1, (byte)2);
            Codec codec = codecFactory.create_codec(encoding);
            aServiceInterceptor.setCodec(codec);
            
            AServiceIORInterceptor aServiceIORInterceptor =
                new AServiceIORInterceptor(codec);
            info.add_ior_interceptor(aServiceIORInterceptor);

        } catch (Throwable t) {
            System.out.println("Exception handling not shown.");
        }
    }

}

AServiceImpl.java

このファイルは、クライアントとサーバントのコードがサービスと通信するために明示的に使用するオブジェクトを含んでいます。クライアントがサービスに対する begin() を呼び出すと、サービスに固有の ServiceID が、このサービスによって予約されている TSC PICurrent スロットに置かれます。クライアントがサービスに対する end() を呼び出すと、サービスが有効になっていないことを示すために、サービスによって TSC スロットが無効な値に設定されます。サーバントは、verify() メソッドを使用して、ServiceID がクライアント側からサーバー側に渡されたかどうかを調べます。

// 
// Copyright and License 

package pi.serviceexample;

import org.omg.CORBA.Any;
import org.omg.CORBA.TCKind;
import org.omg.CORBA.LocalObject;
import org.omg.CORBA.ORB;
import org.omg.PortableInterceptor.Current;
import org.omg.PortableInterceptor.InvalidSlot;

class AServiceImpl
    extends LocalObject
    implements AService
{
    private int slotId;

    private int currentServiceId = 0;

    private Current piCurrent;

    private Any NOT_IN_EFFECT;

    public AServiceImpl(int slotId)
    {
        this.slotId = slotId;
        NOT_IN_EFFECT = ORB.init().create_any();
    }

    // Package protected so the AService ORBInitializer can access this
    // non-IDL defined method.
    void setPICurrent(Current piCurrent)
    {
        this.piCurrent = piCurrent;
    }

    public void begin()
    {
        Any any = ORB.init().create_any();
        any.insert_long(++currentServiceId);
        setSlot(any);
    }

    public void end()
    {
        setSlot(NOT_IN_EFFECT);
    }

    public void verify()
    {
        try {
            Any any = piCurrent.get_slot(slotId);
            if (any.type().kind().equals(TCKind.tk_long)) {
                System.out.println("Service present: " + any.extract_long());
            } else {
                System.out.println("Service not present");
            }
        } catch (InvalidSlot e) {
            System.out.println("Exception handling not shown.");
        }
    }

    // Synchronized because two threads in the same ORB could be
    // sharing this object.
    synchronized private void setSlot(Any any)
    {
        try {
            piCurrent.set_slot(slotId, any);
        } catch (InvalidSlot e) {
            System.out.println("Exception handling not shown.");
        }
    }
}

AServiceInterceptor.java

このインタセプタは、クライアント側の AService 情報をサービス側に渡すための準備を行います。

クライアント側では、AService.begin() が呼び出されると、send_request(ri) ポイントが RSC スロット内のサービス ID を確認します。この場合、これはサービス ID の値を org.omg.CORBA.ServiceContext に挿入し、そのサービスコンテキストを呼び出しで渡されるデータに追加します。

サーバー側では、receive_request_service_context(ri) が、そのサービスコンテキストの存在を確認します。存在している場合、これは ServiceContext からサービス ID 値を抽出し、RSC スロットをその値に設定します。サーバントの実行中は、RSC スロットの値を TSC スロット内で使用できます。


// AServiceInterceptor.java
// Copyright and License 

package pi.serviceexample;

import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TCKind;
import org.omg.IOP.Codec;
import org.omg.IOP.CodecPackage.FormatMismatch;
import org.omg.IOP.CodecPackage.TypeMismatch;
import org.omg.IOP.ServiceContext;
import org.omg.IOP.TaggedComponent;
import org.omg.PortableInterceptor.ClientRequestInterceptor;
import org.omg.PortableInterceptor.ClientRequestInfo;
import org.omg.PortableInterceptor.InvalidSlot;
import org.omg.PortableInterceptor.ServerRequestInterceptor;
import org.omg.PortableInterceptor.ServerRequestInfo;

public class AServiceInterceptor
    extends org.omg.CORBA.LocalObject
    implements ClientRequestInterceptor, ServerRequestInterceptor
{
    private int slotId;
    private Codec codec;

    private static final int serviceContextId = 1234;

    public AServiceInterceptor(int slotId)
    {
        this.slotId = slotId;
    }

    void setCodec(Codec codec)
    {
        this.codec = codec;
    }

    //
    // Interceptor operations
    //

    public String name() 
    {
        return "AServiceInterceptor";
    }

    public void destroy() 
    {
    }

    //
    // ClientRequestInterceptor operations
    //

    public void send_request(ClientRequestInfo ri)
    {
        //
        // See if the target object contains an ASERVICE_COMPONENT.
        //

        try {
            TaggedComponent taggedComponent =
                ri.get_effective_component(TAG_ASERVICE_COMPONENT.value);

            Any sAny = null;
            try {
                sAny = codec.decode_value(taggedComponent.component_data,
                                          ASERVICE_COMPONENTHelper.type());
            } catch (TypeMismatch e) {
                System.out.println("Exception handling not shown.");
            } catch (FormatMismatch e) {
                System.out.println("Exception handling not shown.");
            }

            ASERVICE_COMPONENT aServiceComponent =
                ASERVICE_COMPONENTHelper.extract(sAny);

            //
            // Only send the service context if the target object requires it.
            //

            if (aServiceComponent.requiresAService) {
                try {
                    Any any = ri.get_slot(slotId);
                    if (any.type().kind().equals(TCKind.tk_long)) {
                        int serviceId = any.extract_long();
                        byte[] serviceContextData = {
                            // Little endian to make it
                            // easier to see in debugger.
                            (byte)((serviceId >>>  0) &  0xFF),
                            (byte)((serviceId >>>  8) &  0xFF),
                            (byte)((serviceId >>> 16) &  0xFF),
                            (byte)((serviceId >>> 24) &  0xFF)
                        };
                        ri.add_request_service_context(
                            new ServiceContext(serviceContextId,
                                               serviceContextData),
                            false);
                    }
                } catch (InvalidSlot e) {
                    System.out.println("Exception handling not shown.");
                }
            }
        } catch (BAD_PARAM e) {
            // If it is not present, do nothing.
            ;
        }
    }

    public void send_poll(ClientRequestInfo ri)
    {
    }

    public void receive_reply(ClientRequestInfo ri)
    {
    }

    public void receive_exception(ClientRequestInfo ri)
    {
    }

    public void receive_other(ClientRequestInfo ri)
    {
    }

    //
    // ServerRequestInterceptor operations
    //

    public void receive_request_service_contexts(ServerRequestInfo ri)
    {
        try {
            ServiceContext serviceContext =
                ri.get_request_service_context(serviceContextId);
            byte[] data = serviceContext.context_data;
            int b1, b2, b3, b4;
            b4 = (data[0] <<  0) & 0x000000FF;
            b3 = (data[1] <<  8) & 0x0000FF00;
            b2 = (data[2] << 16) & 0x00FF0000;
            b1 = (data[3] << 24) & 0xFF000000;
            int serviceId = (b1 | b2 | b3 | b4);
            Any any = ORB.init().create_any();
            any.insert_long(serviceId);
            ri.set_slot(slotId, any);
        } catch (BAD_PARAM e) {
            // Not present means service is not in effect.
            // Do nothing.
            ;
        } catch (InvalidSlot e) {
            System.out.println("Exception handling not shown.");
        }
    }

    public void receive_request(ServerRequestInfo ri)
    {
    }

    public void send_reply(ServerRequestInfo ri)
    {
    }

    public void send_exception(ServerRequestInfo ri)
    {
    }

    public void send_other(ServerRequestInfo ri)
    {
    }
}

AServiceIORInterceptor.java

このファイルは、TaggedComponent を IOR に追加します。

// AServiceIORInterceptor.java
// Copyright and License 

package pi.serviceexample;

import org.omg.CORBA.Any;
import org.omg.CORBA.LocalObject;
import org.omg.CORBA.ORB;
import org.omg.IOP.TaggedComponent;
import org.omg.IOP.Codec;
import org.omg.IOP.CodecPackage.InvalidTypeForEncoding;
import org.omg.PortableInterceptor.IORInfo;
import org.omg.PortableInterceptor.IORInterceptor;

public class AServiceIORInterceptor
    extends org.omg.CORBA.LocalObject
    implements IORInterceptor
{
    private Codec codec;

    public AServiceIORInterceptor(Codec codec)
    {
        this.codec = codec;
    }

    //
    // Interceptor operations
    //

    public String name() 
    {
        return "AServiceInterceptor";
    }

    public void destroy() 
    {
    }

    //
    // IOR Interceptor operations
    //

    public void establish_components(IORInfo info)
    {
        //
        // Note: typically, rather than just inserting a tagged component
        // this interceptor would check info.get_effective_policy(int)
        // to determine if a tagged component reflecting that policy
        // should be added to the IOR.  That is not shown in this example.
        // 

        ASERVICE_COMPONENT aServiceComponent = new ASERVICE_COMPONENT(true);
        Any any = ORB.init().create_any();
        ASERVICE_COMPONENTHelper.insert(any, aServiceComponent);
        byte[] value = null;
        try {
            value = codec.encode_value(any);
        } catch (InvalidTypeForEncoding e) {
            System.out.println("Exception handling not shown.");
        }
        TaggedComponent taggedComponent =
            new TaggedComponent(TAG_ASERVICE_COMPONENT.value, value);
        info.add_ior_component(taggedComponent);
    }

}

ArbitaryObjectImpl.java

このファイルは、ArbitraryObject IDL インタフェースのサーバーおよび実装です。この IDL インタフェースオペレーションの実装では、クライアントからサーバントへの AService.begin() を使用したエンドツーエンドデータの受け渡しを説明するために、AServiceImpl.verify() メソッドを明示的に呼び出しています。


// ArbitaryObjectImpl.java
// Copyright and License 

package pi.serviceexample;

import org.omg.CORBA.ORB;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.PortableServer.POAHelper;

import java.util.Properties;

class ArbitraryObjectImpl
    extends ArbitraryObjectPOA
{
    public static ORB orb;

    private AService aService;

    //
    // The IDL operations.
    //

    public String arbitraryOperation1(String a1)
    {
        verifyService();
        return "I got this from the client: " + a1;
    }

    public void arbitraryOperation2 (int a1)
    {
        verifyService();
    }

    public void arbitraryOperation3(String a1)
        throws ArbitraryObjectException
    {
        verifyService();
        if (a1.equals("throw exception")) {
            throw new ArbitraryObjectException("because you told me to");
        }
    }

    private void verifyService()
    {
        getAService().verify();
    }

    private AService getAService()
    {
        // Only look up the service once, then cache it.

        if (aService == null) {
            try {
                aService =      
                    AServiceHelper.narrow(
                        orb.resolve_initial_references("AService"));
            } catch (InvalidName e) {
                System.out.println("Exception handling not shown.");
            }
        }
        return aService;
    }

    //
    // The server.
    //

    public static void main(String[] av)
    {
        try {
            if (orb == null) {
                Properties props = new Properties();
                props.put("org.omg.PortableInterceptor.ORBInitializerClass."
                          + "pi.serviceexample.AServiceORBInitializer",
                          "");
                props.put("org.omg.PortableInterceptor.ORBInitializerClass."
                          + "pi.serviceexample.LoggingServiceServerORBInitializer",
                          "");
                orb = ORB.init(av, props);
            }
            
            POA rootPOA =  POAHelper.narrow( orb.resolve_initial_references("RootPOA"));
            // Create a POA so the IOR interceptor executes.
            POA childPOA = rootPOA.create_POA("childPOA", null, null);
            childPOA.the_POAManager().activate();
            
            byte[] objectId =
                childPOA.activate_object(new ArbitraryObjectImpl());
            org.omg.CORBA.Object ref = childPOA.id_to_reference(objectId);

            NamingContext nameService = 
                NamingContextHelper.narrow(
                    orb.resolve_initial_references("NameService"));
            NameComponent path[] =
                { new NameComponent("ArbitraryObject", "") };
            nameService.rebind(path, ref);

            System.out.println("ArbitaryObject ready.");

            orb.run();

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
        System.exit(0);
    }
}

Client.java

これは、ArbitraryObject に対するメソッドを呼び出すクライアントです。このクライアントは、AService のコンテキストの内部と外部で、それらの呼び出しをいくつか実行します。クライアントは、ロギングインタセプタの存在を認識しません。ただし、前の例のように LoggingServerClientORBInitializer を明示的に登録します。


// Client.java
// Copyright and License 

package pi.serviceexample;

import org.omg.CORBA.ORB;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;

import java.util.Properties;

public class Client 
{
    public static void main(String av[])
    {
        try {
            Properties props = new Properties();
            props.put("org.omg.PortableInterceptor.ORBInitializerClass."
                      + "pi.serviceexample.AServiceORBInitializer",
                      "");
            props.put("org.omg.PortableInterceptor.ORBInitializerClass."
                      + "pi.serviceexample.LoggingServiceClientORBInitializer",
                      "");
            ORB orb = ORB.init(av, props);

            //
            // The client obtains a reference to a service.
            // The client does not know the service is implemented
            // using interceptors.
            //

            AService aService = 
                AServiceHelper.narrow(
                    orb.resolve_initial_references("AService"));

            //
            // The client obtains a reference to some object that
            // it will invoke.
            //

            NamingContext nameService = 
                NamingContextHelper.narrow(
                    orb.resolve_initial_references("NameService"));
            NameComponent arbitraryObjectPath[] =
                { new NameComponent("ArbitraryObject", "") };
            ArbitraryObject arbitraryObject =
                ArbitraryObjectHelper.narrow(nameService.resolve(arbitraryObjectPath));

            //
            // The client begins the service so that invocations of
            // any object will be done with that service in effect.
            //

            aService.begin();
            
            arbitraryObject.arbitraryOperation1("one");
            arbitraryObject.arbitraryOperation2(2);

            //
            // The client ends the service so that further invocations
            // of any object will not be done with that service in effect.
            //

            aService.end();

            // This invocation is not serviced by aService since
            // it is outside the begin/end.
            arbitraryObject.arbitraryOperation3("just return");


            aService.begin();
            try {
                arbitraryObject.arbitraryOperation3("throw exception");
                throw new RuntimeException("should not see this");
            } catch (ArbitraryObjectException e) {
                // Expected in this example, so do nothing.
            }
            aService.end();

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
        System.out.println("Client done.");
        System.exit(0);
    }
}

ColocatedServers.java

このファイルは、ArbitraryObject および LoggingService の両方を同一の ORB 内で実行するサーバーです。つまり、これらのオブジェクトは「同じ場所に置かれています」。

このサーバーは、LoggingServiceServerInterceptor 内のコードを試すために、このような方法で作成されています。このコードは、インタセプタが、同じ ORB 内に置かれている複数のオブジェクトに対する呼び出しを実行するときに、無限回帰を回避するために追加の処理を実行する必要があることを示しています。


// ColocatedServers.java
// Copyright and License 

package pi.serviceexample;

import org.omg.CORBA.ORB;
import java.util.Properties;

public class ColocatedServers
{
    public static ORB orb;

    public static boolean colocatedBootstrapDone = false;

    public static void main (String[] av)
    {
        try {

            //
            // Share an ORB between objects servers.
            //

            Properties props = new Properties();
            props.put("org.omg.PortableInterceptor.ORBInitializerClass."
                      + "pi.serviceexample.AServiceORBInitializer",
                      "");
            props.put("org.omg.PortableInterceptor.ORBInitializerClass."
                      + "pi.serviceexample.LoggingServiceServerORBInitializer",
                      "");
            ORB orb = ORB.init(av, props);
            ArbitraryObjectImpl.orb = orb;
            LoggingServiceImpl.orb = orb;

            //
            // Start both object servers.
            //

            ServerThread ServerThread = new ServerThread(av);
            ServerThread.start();
            ArbitraryObjectImpl.main(av);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }
}

class ServerThread extends Thread
{
    String[] av;
    ServerThread (String[] av)
    {
        this.av = av;
    }
    public void run ()
    {
        LoggingServiceImpl.main(av);
    }
}

アプリケーションのコンパイルと実行

ロギングの例とサービスの例が含まれているこれらのコード例は、次のような Makefile を使用してコンパイルおよび実行することができます。


# Makefile for the Example Files
# Copyright and License 

JAVA_HOME=/path_to_J2SE_installation

CLASSPATH=.

JAVAC=$(JAVA_HOME)/bin/javac
JAVA=$(JAVA_HOME)/bin/java

ORB_INITIAL_PORT=1050

IDLJ=$(JAVA_HOME)/bin/idlj
IDLJ_FLAGS=-fall -td $(CLASSPATH) -verbose

ORBD=${JAVA_HOME}/bin/orbd -ORBInitialPort ${ORB_INITIAL_PORT}

build:
        $(IDLJ) $(IDLJ_FLAGS) serviceexample.idl
        $(JAVAC) -d $(CLASSPATH) *.java
        $(JAVAC) pi/serviceexample/*.java

runorbd:
        $(ORBD)

runloggingservice:
        $(JAVA) -classpath $(CLASSPATH) pi.serviceexample.LoggingServiceImpl \
                -ORBInitialPort ${ORB_INITIAL_PORT}

runarbitraryobject:
        $(JAVA) -classpath $(CLASSPATH) pi.serviceexample.ArbitraryObjectImpl \
                -ORBInitialPort ${ORB_INITIAL_PORT}

runcolocatedservers:
        $(JAVA) -classpath $(CLASSPATH) pi.serviceexample.ColocatedServers \
                -ORBInitialPort ${ORB_INITIAL_PORT}

runclient:
        $(JAVA) -classpath $(CLASSPATH) pi.serviceexample.Client \
                -ORBInitialPort ${ORB_INITIAL_PORT}
        
clean: 
        rm -rf pi
        rm -rf orb.db

# Order of steps:
# Build:     clean build
# Remote:    runorbd runloggingservice runarbitraryobjectimpl runclient
# Colocated: runorbd runcolocatedservers runclient

次に、上記の Makefile を使用して Solaris オペレーティングシステム上でこの例をビルドし、実行するための手順を紹介します。ここで紹介するコマンドを、コマンドプロンプトから実行してください。% 記号は、記載されているコマンドをコマンドプロンプトから実行するべきであることを示すために使用しています。

  1. % make clean
  2. % make build
  3. % make runorbd &
  4. % make runloggingservice &
  5. % make runarbitraryobject &
  6. % make runclient

    このステップの後、次のような出力が表示されます。

    resolve send_request
    resolve receive_reply
    arbitraryOperation1 send_request
    Service present: 1
    arbitraryOperation1 receive_reply
    arbitraryOperation2 send_request
    Service present: 1
    arbitraryOperation2 receive_other
    arbitraryOperation3 send_request
    Service not present
    arbitraryOperation3 receive_reply
    arbitraryOperation3 send_request
    Service present: 2
    arbitraryOperation3 receive_exception
    Client done.
    
  7. % jobs

    このステップの後、次のような出力が表示されます。

    [1]   Running                 make runorbd &
    [2]-  Running                 make runloggingservice &
    [3]+  Running                 make runarbitraryobject &
    
  8. % kill %2 %3
  9. % make runcolocatedservers &
  10. % make runclient

    このステップの後、次のような出力が表示されます。

    log receive_request_service_contexts
    log receive_request
    resolve send_request
    log send_reply
    log receive_request_service_contexts
    log receive_request
    resolve receive_reply
    log send_reply
    log receive_request_service_contexts
    log receive_request
    arbitraryOperation1 send_request
    log send_reply
    arbitraryOperation1 receive_request_service_contexts
    arbitraryOperation1 receive_request
    Service present: 1
    arbitraryOperation1 send_reply
    log receive_request_service_contexts
    log receive_request
    arbitraryOperation1 receive_reply
    log send_reply
    log receive_request_service_contexts
    log receive_request
    arbitraryOperation2 send_request
    log send_reply
    arbitraryOperation2 receive_request_service_contexts
    arbitraryOperation2 receive_request
    log receive_request_service_contexts
    Service present: 1
    arbitraryOperation2 send_reply
    log receive_request
    arbitraryOperation2 receive_other
    log send_reply
    log receive_request_service_contexts
    log receive_request
    arbitraryOperation3 send_request
    log send_reply
    arbitraryOperation3 receive_request_service_contexts
    arbitraryOperation3 receive_request
    Service not present
    arbitraryOperation3 send_reply
    log receive_request_service_contexts
    log receive_request
    arbitraryOperation3 receive_reply
    log send_reply
    log receive_request_service_contexts
    log receive_request
    arbitraryOperation3 send_request
    log send_reply
    arbitraryOperation3 receive_request_service_contexts
    arbitraryOperation3 receive_request
    Service present: 2
    arbitraryOperation3 send_exception
    log receive_request_service_contexts
    log receive_request
    arbitraryOperation3 receive_exception
    log send_reply
    Client done.
    
  11. % jobs

    このステップの後、次のような出力が表示されます。

    [1]-  Running                 make runorbd &
    [4]+  Running                 make runcolocatedservers &
    
  12. % kill %1 %4
  13. % make clean
関連項目:
ORBInitInfo
org.omg.PortableInterceptor パッケージ
ポータブルインタセプタの仕様 (ptc/2001-08-31)

Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.
連絡先