CORBAのリモートオペレーション呼び出しの途中でフックを行い、なんらかの処理を挟み込みたいことがあります。例えば、CORBAのリモートオペレーション呼び出しのログを取りたいときなどです。そのときにCORBAの実装系に依存しない標準APIとしてPortable Interceptorが用意されています。
インターセプタは、CORBAオペレーションを呼び出す側(クライアント)とCORBAオペレーションを受け取り実行する側(サーバ)とに分かれます。
ClientRequestInterceptor | TCP/IP | ServerRequestInterceptor | ||
クライアント オブジェクト |
receive_request_service_contexts | サーバ オブジェクト |
||
send_request | → | receive_request | ||
send_poll | ||||
receive_reply | ← | send_reply | ||
receive_exception | (←) | send_exception | ||
receive_other | send_other |
例えば、クライアントオブジェクトがリモートオブジェクトへオペレーションを要求するときは、まずクライアント側のインターセプタが持つsend_requestメソッドが起動されます。そして、サーバ側ではサーバントに渡る前にサーバ側のインターセプタが持つreceive_requestメソッドが起動されます。
それから、サーバントの対応するメソッドが起動されます。サーバントのメソッドが正常にreturnされると、サーバ側のインターセプタが持つsend_replyが起動されます。そして、クライアント側でインターセプタが持つreceive_replyメソッドが起動されます。
クライアント側インターセプタは、org.omg.PortableInterceptor.ClientInterceptorインタフェースを実装します。また、org.omg.CORBA.LocalObjectを継承します。
package count; import org.omg.CORBA.LocalObject; import org.omg.PortableInterceptor.ForwardRequest; import org.omg.PortableInterceptor.ClientRequestInfo; import org.omg.PortableInterceptor.ClientRequestInterceptor; public class ClientInterceptor extends LocalObject implements ClientRequestInterceptor { public ClientInterceptor() {} |
public void send_request(ClientRequestInfo info) throws ForwardRequest { printRequestInfo("send_request ", info); } |
public void send_poll(ClientRequestInfo info) {} |
public void receive_reply(ClientRequestInfo info) { printRequestInfo("receive_reply", info); } |
public void receive_exception(ClientRequestInfo info) throws ForwardRequest {} public void receive_other(ClientRequestInfo info) throws ForwardRequest {} public String name() { return "ClientInterceptor"; } public void destroy() {} private void printRequestInfo(String methodName, ClientRequestInfo info) { System.out.println("ClientInterceptor#" + methodName + ": " + "send_request: operation=" + info.operation() + ", request_id=" + info.request_id() ); } }// ClientInterceptor |
クライアント側インターセプタは、org.omg.PortableInterceptor.ClientInterceptorインタフェースを実装します。また、org.omg.CORBA.LocalObjectを継承します。
package count; import org.omg.CORBA.LocalObject; import org.omg.PortableInterceptor.ForwardRequest; import org.omg.PortableInterceptor.ServerRequestInfo; import org.omg.PortableInterceptor.ServerRequestInterceptor; public class ServerInterceptor extends LocalObject implements ServerRequestInterceptor { public ServerInterceptor() {} public void receive_request_service_contexts(ServerRequestInfo info) throws ForwardRequest {} |
public void receive_request(ServerRequestInfo info) throws ForwardRequest { printRequestInfo("receive_request ", info); } |
public void send_reply(ServerRequestInfo info) { printRequestInfo("send_reply ", info); } |
public void send_exception(ServerRequestInfo info) throws ForwardRequest {} public void send_other(ServerRequestInfo info) throws ForwardRequest {} public String name() { return "ServerInterceptor"; } public void destroy() { } private void printRequestInfo(String methodName, ServerRequestInfo info) { System.out.println("ServerInterceptor#" + methodName + ": " + "send_request: operation=" + info.operation() + ", request_id=" + info.request_id() ); } }// ServerInterceptor |
インターセプタは、インターセプタ初期化クラスによってORBに登録されます。これは、org.omg.PortableInterceptor.ORBInitializerインタフェースを実装します。また、org.omg.CORBA.LocalObjectを継承します。2つのメソッドpre_initjとpost_initを持っており、どちらかのメソッドの実装においてインターセプタを初期化しORBに登録します。これは呼ばれるタイミングが違います。
package count; import org.omg.PortableInterceptor.ORBInitInfo; import org.omg.PortableInterceptor.ORBInitializer; import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName; import org.omg.CORBA.LocalObject; public class InterceptorInitializer extends LocalObject implements ORBInitializer { ClientInterceptor clientInterceptor = new ClientInterceptor(); ServerInterceptor serverInterceptor = new ServerInterceptor(); public void pre_init(ORBInitInfo info) { System.out.println("count.InterceptorInitializer#pre_init: called"); try { info.add_client_request_interceptor(clientInterceptor); info.add_server_request_interceptor(serverInterceptor); } catch (DuplicateName e) { System.out.println("DuplicateName in InterceptorInitializer#pre_init"); } } public void post_init(ORBInitInfo info) { System.out.println("count.InterceptorInitializer#post_init: called"); } }// InterceptorInitializer |
このインターセプタ初期化クラスは、プログラム中でコーディングすることもできますが、システムプロパティに記述することもできます。
D:\develop\ex1>java -Dorg.omg.PortableInterceptor.ORBInitializerClass.count.Inter ceptorInitializer -cp $CLASSPATH:classes count.Client -ORBInitRef NameService=cor baloc:iiop:1.2@xxx.xxx.xxx.xxx:1234/NameService : |
プロパティ名: org.omg.PortableInterceptor.ORBInitializerClass.インターセプタ初期化クラスのFQCN