CORBAリクエスト・レベルのインターセプタの開発を行うには通常、次の手順に従います。
上記の手順は通常、繰り返し行います。たとえば、最初にインターセプタをビルドしてテストするときは、そのインターセプタが実行中であることを確認するだけの最も基本的なコードのみとします。その後のビルドとテストで、インターセプタの全機能を徐々に実装していきます。
以降の項では、Oracle Tuxedoソフトウェアに同梱されたサンプルのインターセプタを例として、各手順を詳しく説明します。
注意: | Oracle Tuxedo CORBA JavaクライアントとOracle Tuxedo CORBA JavaクライアントORBはTuxedo 8.1で非推奨になり、サポートされなくなりました。すべてのOracle Tuxedo CORBA JavaクライアントおよびOracle Tuxedo CORBA JavaクライアントORBのテキスト・リファレンスとコード・サンプルは、サード・パーティのJava ORBライブラリを実装または実行する際の参考や、プログラマの参照用としてのみ使用してください。 |
注意: | サード・パーティのCORBA Java ORBのテクニカル・サポートは、各ベンダーによって提供されます。Oracle Tuxedoでは、サード・パーティのCORBA Java ORBに関する技術的なサポートやドキュメントは提供していません。 |
所定のマシンにインターセプタをデプロイすると、そのインターセプタはマシン上のアプリケーションがリクエストを発行(クライアント側インターセプタの場合)または受信(ターゲット・サイド・インターセプタの場合)するたびに呼び出されるため、著しいオーバーヘッドが生じます。したがって、作成したインターセプタはすべて、これらのアプリケーションによく適合している必要があります。
たとえば、セキュリティ・インターセプタは通常、問題となっているリクエストの種類、およびリクエストで処理されているデータの種類を認識する必要があります。
特定のリクエストを扱うインターセプタはすべて、リクエストからインタフェース・リポジトリIDを抽出できる必要があります。インタフェースについてこのような情報があれば、インターセプタはリクエストに含まれるデータの種類を知り、そのデータをリクエスト固有のやり方で処理できます。
さらに、対象外のリクエストが送信された場合、インターセプタはそのリクエストを迅速かつ効率的に渡すことができなければなりません。
「PersonQueryサンプル・アプリケーション」で説明されているPersonQueryの例では、PersonQueryクライアント・アプリケーションのユーザーがアドレスを受信できるかどうかを決定するインターセプタを使用します。ユーザーの識別情報が特定の基準に一致する場合には、インターセプタは完全なアドレス番号をクライアントに戻すことを許可します。一致しなかった場合、インターセプタはアドレスのかわりにx
文字からなる文字列のみをログ・ファイルに戻します。
次のトピックでは、多くのインターセプタについて一般的な実装上の検討事項について説明します。「InterceptorDataサンプル・インターセプタ」で説明するInterceptorDataインターセプタから例を取ります。
付録Aに示すコードの抜粋を、インターセプタの実装を開始する際に使用できます。付録Aのコードを使用しても、OracleのWebサイト上のWebLogic Enterpriseデベロッパ・センターで入手できるスタータ・ファイルをコピーしてもかまいません。
インターセプタ・ヘッダーのスタータ・ファイルです。このファイルの内容と、使用方法の説明は、「ステップ3:インターセプタ・ヘッダー・ファイルの作成」に示しています。
|
|
WebLogic Enterpriseデベロッパ・センターからこれらのスタータ・ファイルを取得する方法については、『リリース・ノート』を参照してください。
付録Aに示すサンプル・インターセプタのコードを使用して、インターセプタの実装を開始できます。コード中で、YourInterceptor
は実装しているインターセプタの名前を表します。ORBは常にServiceContextList
およびCORBA::DataOutputStream
の各パラメータについて、ニル・リファレンスを渡します。これらのパラメータは、使用も参照もできません。またこの制限事項は将来のバージョンで変更される可能性があるため、nil
についてのこれらのパラメータのテストはしないでください。
ORBの初期化時に、すべてのインターセプタがインスタンス化されます。それ以外では、リクエスト・レベルのインターセプタはインスタンス化されません。初期化の一環として、インターセプタの初期化ルーチンにより、インターセプタのサポート対象に応じて、クライアント・インターセプタとターゲット・インターセプタの一方または両方の実装のインスタンスをインスタンス化する必要があります。前述のように、単一の共有可能なイメージで、クライアント側インターセプタとターゲット・サイド・インターセプタの双方をサポートできます。その後、任意のインスタンス化されたインターセプタのインスタンスが、初期化ルーチンから返され、ORB実行時に登録されます。
次のコードの抜粋部分は、InterceptorDataインターセプタからのものです。クライアント側ORBの初期化時に、ORBによって呼び出された初期化オペレーションの宣言を示します。
void InterceptorDataClientInit(
CORBA::ORB_ptr TheORB,
RequestLevelInterceptor::ClientRequestInterceptor ** ClientPtr,
RequestLevelInterceptor::TargetRequestInterceptor ** TargetPtr,
CORBA::Boolean * RetStatus)
次のコードの抜粋部分は、InterceptorDataクライアント・インターセプタ・クラスをインスタンス化するための文を示します。この抜粋部分は、受信される各クライアント・リクエストの追跡を行い、ターゲット・オブジェクトから返されるレスポンスに一致させるための、tracker
というクラスを使用します。trackerクラスは、「リクエスト内のオペレーションの識別」で説明します。
ClientInterceptorData * client = new ClientInterceptorData(TheORB, tracker);
if (!client)
{
tmpfile << "InterceptorDataClientInit: Client alloc failed"
<< endl << endl;
*RetStatus = CORBA_FALSE;
delete tracker;
return;
}
次のコード抜粋部分は、インターセプタ・クラスをORBに返すための文を示します。
*ClientPtr = client;
*TargetPtr = 0;
*RetStatus = CORBA_TRUE;
return;
特定のインタフェースやリクエストで機能するインターセプタの場合は、リクエストに関連付けられたインタフェースIDを抽出する方法が必要です。それにより、インターセプタはリクエストを識別し、その中のデータをどのように処理すればよいかを理解できます。たとえば、InterceptorDataインターセプタはPersonQueryアプリケーションからのリクエストで送信されたリクエスト・パラメータを操作します。リクエスト・パラメータを操作するには、インターセプタはどのリクエストが送信されているのかを認識する必要があります。
次のInterceptorDataサンプルからのコード抜粋部分は、RequestContext構造体から抽出されたインタフェースIDを示します。
if (strcmp(request_context.interface_id.in(),
PersonQuery::_get_interface_name()) != 0)
return ret_status;
抽出されたインタフェースIDを使用して、InterceptorDataサンプルは単純なswitch
文でクライアント・リクエスト内のオペレーションを識別します。これにより、インターセプタはリクエストに含まれるリクエスト・パラメータの扱い方を認識します。
次のコード抜粋部分は、Exit
オペレーション、またはデータベースに対しある人物を名前で指定した問合せを行うためのオペレーションがあるかどうか確認する、switch文を示します。parser
オブジェクトが使用されていることに注意してください。このオブジェクトはtracker
オブジェクトより受信したリクエストからオペレーションを抽出します。
m_outfile << “ Operation: “ << request_context.operation << endl;
PQ parser;
PQ::op_key key = parser.MapOperation(request_context.operation.in());
switch (key)
{
default:
m_outfile << “ ERROR: operation is not member of “
<< request_context.interface_id.in() << endl;
excep_val = new CORBA::BAD_OPERATION();
return Interceptors::REPLY_EXCEPTION;
case PQ::Exit:
m_outfile << endl;
return ret_status;
case PQ::ByPerson:
{
PersonQuery::Person per;
parser.GetByPerson(request_arg_stream, &per);
m_outfile << “ Parameters:” << endl;
m_outfile << per << endl;
}
break;
クライアント・リクエストからインタフェースIDを抽出するのは、かなり単純な作業です。しかし、ターゲット・レスポンスで同じ処理を行う場合はそれほど単純ではありません。ORBから受信するレスポンスに関連付けられたインタフェースおよびオペレーションを知る必要がある場合、インターセプタはリクエストを追跡するための特別なロジックを必要とします。クライアントから受信したリクエストの追跡は、インターセプタの役割です。
InterceptorDataサンプルは、Tracker
と呼ばれる言語オブジェクトを実装します。これはターゲットに送られるリクエストの記録を取り、インターセプタにターゲット・レスポンスが返ると、それらのリクエストにレスポンスを適合させるオブジェクトです。
InterceptorDataサンプルのclient_response
およびtarget_response
オペレーションは、ターゲットからレスポンスが返ると、Tracker
オブジェクトからインタフェースおよびオペレーションの情報を抽出します。
次のInterceptorDataコードの抜粋部分は、レスポンスに関連付けられたリクエストを抽出するものです。
RequestInfo * req_info = m_tracker->CompleteRequest(reply_context);
if (!req_info)
{
m_outfile << “ unable to find request for this reply (must not be one
we care about)” << endl << endl;
return Interceptors::RESPONSE_NO_EXCEPTION;
}
//
// This is the interface we are expecting. Now identify the operation
// being invoked, so we can parse the request parameters.
//
m_outfile << “ ReplyStatus: “;
OutputReplyStatus(m_outfile, reply_context.reply_status);
m_outfile << endl;
m_outfile << “ Interface: “ << req_info->intf() << endl;
m_outfile << “ Operation: “ << req_info->op() << endl;
PQ parser;
PQ::op_key key = parser.MapOperation(req_info->op());
これでインターセプタはレスポンスに関連付けられたリクエストを取得したので、レスポンス内のデータを適切に処理できます。
次のコードの抜粋部分は、InterceptorDataのサンプルがどのようにして、データ・ストリームからのリクエスト・パラメータを構造体に入れるのかの例を示しています。次のコード抜粋部分のパラメータS
は、インターセプタの実装によりPersonQueryオペレーションの応答パラメータ値を取得するのに使用可能なDataInputStream
構造体へのポインタを表します。このコード抜粋部分において、中カッコで囲まれたコードは、DataInputStream
構造体からのレスポンスのパラメータを抽出するものです。DataInputStream
構造体の詳細は、「リクエスト・レベルのインターセプタのAPI」を参照してください。
void PQ::get_addr(CORBA::DataInputStream_ptr S,
PersonQuery::Address *addr)
{
addr->number = S->read_short();
addr->street = S->read_string();
addr->town = S->read_string();
addr->state = S->read_string();
addr->country = S->read_string();
}
excep_val
パラメータ経由で返されたインターセプタからの例外は、CORBA::SystemException
基本クラスから派生したタイプのみです(これ以外で、インターセプタの実装がORBに返す例外のタイプはすべて、ORBによってCORBA::UNKNOWN
例外に変換され、excep_val
パラメータを介して渡されます)。例外はCORBA::SystemException
クラスまたはその派生クラスの1つにマップする必要があります。
インターセプタの実装ファイル内に何らかの実装コードを作成した後は、必要に応じてインターセプタ・ヘッダー・ファイルにデータまたはオペレーションを加える必要があります。
次のサンプル・コードは、クライアント側インターセプタとターゲット・サイド・インターセプタの双方を実装する、インターセプタ実装ファイル用のヘッダー・ファイルで必要な基本情報を示します。
このサンプル・コードでは、YourInterceptor
は作成しているインターセプタの名前を表します。
#include <CORBA.h>
#include <RequestLevelInterceptor.h>
#include <security_c.h> //for security
class YourInterceptorClient : public virtual RequestLevelInterceptor::ClientRequestInterceptor
{
private:
YourInterceptorClient() {}
CORBA::ORB_ptr m_orb;
public:
YourInterceptor
Client(CORBA::ORB_ptr TheOrb);
~YourInterceptor
Client() {}
Interceptors::ShutdownReturnStatus shutdown(
Interceptors::ShutdownReason reason,
CORBA::Exception_ptr & excep_val);
CORBA::String id();
void exception_occurred (
const RequestLevelInterceptor::ReplyContext & reply_context,
CORBA::Exception_ptr excep_val);
Interceptors::InvokeReturnStatus client_invoke (
const RequestLevelInterceptor::RequestContext & request_context,
RequestLevelInterceptor::ServiceContextList_ptr service_context,
CORBA::DataInputStream_ptr request_arg_stream,
CORBA::DataOutputStream_ptr reply_arg_stream,
CORBA::Exception_ptr & excep_val);
Interceptors::ResponseReturnStatus client_response (
const RequestLevelInterceptor::ReplyContext & reply_context,
RequestLevelInterceptor::ServiceContextList_ptr service_context,
CORBA::DataInputStream_ptr arg_stream,
CORBA::Exception_ptr & excep_val);
};
classYourInterceptor
Target : public virtual RequestLevelInterceptor::TargetRequestInterceptor
{
private:
YourInterceptor
Target() {}
CORBA::ORB_ptr m_orb;
SecurityLevel1::Current_ptr m_security_current; //for security
Security::AttributeTypeList * m_attributes_to_get; //for security
public:
YourInterceptor
Target(CORBA::ORB_ptr TheOrb);
~YourInterceptor
Target();
Interceptors::ShutdownReturnStatus shutdown(
Interceptors::ShutdownReason reason,
CORBA::Exception_ptr & excep_val);
CORBA::String id();
void exception_occurred (
const RequestLevelInterceptor::ReplyContext & reply_context,
CORBA::Exception_ptr excep_val);
Interceptors::InvokeReturnStatus target_invoke (
const RequestLevelInterceptor::RequestContext & request_context,
RequestLevelInterceptor::ServiceContextList_ptr service_context,
CORBA::DataInputStream_ptr request_arg_stream,
CORBA::DataOutputStream_ptr reply_arg_stream,
CORBA::Exception_ptr & excep_val);
Interceptors::ResponseReturnStatus target_response (
const RequestLevelInterceptor::ReplyContext & reply_context,
RequestLevelInterceptor::ServiceContextList_ptr service_context,
CORBA::DataInputStream_ptr arg_stream,
CORBA::Exception_ptr & excep_val);
};
インターセプタは、共有可能ライブラリに組み込まれます。したがって、インターセプタをビルドする手順は、プラットフォーム固有です。任意の特定プラットフォーム上でインターセプタをビルドするのに使用される特定のコマンドおよびオプションの詳細を知るには、Oracle Tuxedoソフトウェア付属のインターセプタのサンプル・アプリケーションをビルドするmakefileを実行し、ビルドによって生じるログ・ファイルで、ビルド結果を参照します。
サンプルのインターセプタをビルドするコマンドは、次のとおりです。
> nmake -f makefile.nt
> make -f makefile.mk
Oracle Tuxedoソフトウェアに付属するサンプルのインターセプタのビルドおよび実行の詳細は、「PersonQueryサンプル・アプリケーション」を参照してください。
インターセプタをテストするには、次のタスクを実行する必要があります。
インターセプタの登録の詳細は、「CORBAリクエスト・レベルのインターセプタのデプロイ」を参照してください。