このドキュメントを J2SETM ドキュメントバンドルの一部としてダウンロードした場合は、Web サイト http://java.sun.com/j2se/1.4/docs/guide/idl/PI.html を参照して、更新されているかどうかを確認してください。
注: このドキュメントは、高度な知識を持つ CORBA 開発者を対象としています。
JavaTM CORBA Object Request Broker (ORB) は、フック (遮断点) を提供し、ORB サービスはこのフックを使って ORBの通常の実行の流れを遮断することができます。 これらの「ポータブルインタセプタ」は、追加の ORB の動作をプラグインするための機構と、クライアントとサーバ間の通信を変更することによって ORB の動作を変更するための機構を提供します。 このあとの例では、ポータブルインタセプタのさまざまな使い方について説明します。
ポータブルインタセプタのサポートは、CORBA 仕様に最近追加された重要な機能です。 RequestInterceptor を使用すると、ORB が仲介する任意の呼び出しを遮断するポータブル ORB フックを簡単に記述して接続することができます。 IORInterceptor を使用すると、CORBA オブジェクト参照に注釈を付けるためのコードを記述できます。
IORInterceptor
場合によっては、クライアント上の ORB サービス実装を正しく機能させるために、ポータブル ORB サービスの実装で、サーバまたはオブジェクトの ORB サービス関連機能を説明する情報をオブジェクト参照に追加する必要があります。 この処理は、IORInterceptor インタフェースと IORInfo インタフェースによってサポートされます。 IOR インタセプタは、Interoperable Object Reference (IOR) のプロファイル内にタグ付きコンポーネントを確立するために使います。
IOR インタセプタの例は、このあとに説明する例の AServiceIORInterceptor.java ファイルに示します。
ClientRequestInterceptor
要求インタセプタは、ORB の応答や要求シーケンスの流れを特定のポイントで遮断できるように設計されています。これにより、サービスは、要求情報を問い合わせたり、クライアントとサーバ間で伝播されるサービスコンテキストを操作したりできます。 要求インタセプタは主に、ORB サービスがクライアントとサーバ間でコンテキスト情報を転送できるようにするために使用されます。
ClientRequestInterceptor
は、クライアント側の ORB の要求や応答シーケンスの流れを遮断します。
ClientRequestInterceptor の例は、このあとに説明する例の LoggingServiceClientInterceptor.java ファイルに示します。
ServerRequestInterceptor
ServerRequestInterceptor
は、サーバ側の ORB の要求や応答シーケンスの流れを遮断します。
ServerRequestInterceptor の例は、このあとに説明する例の LoggingServiceServerInterceptor.java ファイルに示します。
クラス 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 命名規則が使用されます。 たとえば、X 社に初期化子が 3 つある場合、次のプロパティを定義できます。
org.omg.PortableInterceptor.ORBInitializerClass.com.x.Init1
org.omg.PortableInterceptor.ORBInitializerClass.com.x.Init2
org.omg.PortableInterceptor.ORBInitializerClass.com.x.Init3
org.omg.PortableInterceptor.ORBInitializerClass
で始まる ORB プロパティが収集され、それぞれのプロパティから <Service>
の部分が抽出され、オブジェクトはクラス名として <Service>
文字列でインスタンスが生成され、そのオブジェクトで pre_init
メソッドおよび post_init
メソッドが呼び出されます。 例外があっても ORB は無視して処理を行います。
orb_id
で ORB.init
を呼び出さないようにします。 ORB の初期化中に登録が発生するので、この状態でこの ORB を呼び出しても結果は定義されません。
PortableInterceptor::Current オブジェクト (これ以降 PICurrent と呼ぶ) は、ポータブルインタセプタが、スレッドのコンテキスト情報を要求コンテキストに転送するために使用する Current オブジェクトです。 ポータブルインタセプタは、PICurrent を常に使用する必要はありませんが、インタセプタの遮断点で、クライアントのスレッドコンテキストの情報が必要な場合は、PICurrent を使用してその情報を伝播することができます。 PICurrent を使用すると、ORB のスレッドモデルにかかわらず移植性のあるサービスコードを記述できます。
クライアント側では、この情報に、サービスコンテキストを介してサーバに伝播されるスレッドコンテキストの情報やその他の情報が含まれます。
サーバ側では、この情報に、クライアントから受け取るサービスコンテキストの情報やその他の情報が含まれます。サービスコンテキストの情報は目的のスレッドコンテキストに伝播されます。
PICurrentは、呼び出しを行う前に、ORB::resolve_initial_references ( PICurrent ) の呼び出しによって取得されます。 遮断点で、RequestInfo オブジェクトに対する get_slot オペレーションを実行すると、スレッドスコープから要求スコープに移動された PICurrent に関するデータを取得できます。 PICurrent は、resolve_initial_references を使用して取得することもできますが、この場合はインタセプタのスレッドスコープの PICurrent が取得されます。
スレッドスコープの PICurrent (TSC) は、スレッドのコンテキスト内に存在する PICurrent です。 要求スコープの PICurrent (RSC) は、要求に関連付けられている PICurrent です。 クライアント側では、要求の開始時に、スレッドスコープの PICurrent が、スレッドコンテキストから要求スコープの PICurrent に論理的にコピーされ、ClientRequestInfo オブジェクトに接続されます。 サーバ側では、要求スコープの PICurrent が ServerRequestInfo に接続されてから、要求の処理が行われます。 要求スコープの PICurrent は、receive_request_service_contexts 遮断点のリストが処理されたあとに、スレッドスコープの PICurrent に論理的にコピーされます。 PICurrent のスコープの詳細については、Updated Interceptors specification の 21.4.4.5 節の「Flow of PICurrent between Scopes」を参照してください。
ここでは、ロギングサービスアプリケーションの例について説明します。 このアプリケーションのサンプルコードは、複雑かつ「特殊なケース」を扱うため、非常に複雑になっています。 このサンプルアプリケーションでは以下のシナリオを扱います。
注: 以下の例では、コードを簡単に試してセットアップできるように、ORBInitializer を明示的に登録しています。 一般的にはこのような処理は行いません。 通常、この情報は、アプリケーションの起動時に -D プロパティとして Java 仮想マシンに渡されます。 この方法を使うと、サービス (たとえばロギングサービス) が存在するかどうか、あるいはアプリケーションが明示的に使用するサービス (たとえば AService インタフェース) がインタセプタとして実装されるかどうかという事実にアプリケーションが束縛されなくなります。 たとえば、このロギングサービスを使って MyApp
というプログラムを実行するには、ユーザは次のように入力します。
java -Dorg.omg.PortableInterceptor.ORBInitializerClass.com.x.Logging.LoggingService MyApp
このアプリケーションの例では、次のようなインタセプタを使用したロギングサービスアプリケーションの作成方法を示します。
次の図は、ロギングサービスでの情報の流れを示しています。
次の図は、同じ場所に置かれたロギングサービスでの情報の流れを示しています。
次の図は、AService での情報の流れを示しています。
このアプリケーションを作成して実行する場合は、以下の節に示すようにコードを入力し、「アプリケーションのコンパイルと実行」の指示に従ってください。
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
// 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.POA; 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
// 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
// // 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 を確認します。 この場合、send_request(ri) は、サービス ID の値を org.omg.CORBA.ServiceContext に挿入し、そのサービスコンテキストを呼び出しで渡されるデータに追加します。
サーバ側では、receive_request_service_context(ri) が、そのサービスコンテキストの存在を確認します。 サービスコンテキストが存在している場合、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
// 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.POA; 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); } }
このアプリケーションをコンパイルして実行するには
.
.
.
.
.
.
ORBInitInfo
コメントの送付先: JavaIDL@eng.sun.com. |