![]()
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