|
|
CORBA 要求レベルのインターセプタの開発
CORBA 要求レベルのインターセプタの開発を行うには通常、次の手順に従います。
インターセプタをデプロイするマシンの識別も行います。
上記の手順は通常、繰り返し行います。たとえば、最初にインターセプタをビルドしてテストするときは、そのインターセプタが実行中であることを確認するだけの最も基本的なコードのみとします。その後のビルドとテストで、インターセプタの全機能を徐々にインプリメントしていきます。
以降の節では、BEA Tuxedo ソフトウェアに同梱されたサンプルのインターセプタを例として、各手順を詳しく説明します。
ステップ 1: CORBA アプリケーションのインターフェイスの識別
所定のマシンにインターセプタをデプロイすると、そのインターセプタはマシン上のアプリケーションが要求を発行 (クライアント側インターセプタの場合) または受信 (ターゲット側インターセプタの場合) するたびに呼び出されるため、著しいオーバヘッドが生じます。したがって、作成したインターセプタはすべて、これらのアプリケーションによく適合している必要があります。
たとえば、セキュリティ・インターセプタは通常、問題となっている要求の種類、および要求で処理されているデータの種類を認識する必要があります。
特定の要求を扱うインターセプタはすべて、要求からインターフェイス・リポジトリ ID を抽出できる必要があります。インターフェイスについてこのような情報があれば、インターセプタは要求に含まれるデータの種類を知り、そのデータを要求固有のやり方で処理できます。
さらに、対象外の要求が送信された場合、インターセプタはその要求を迅速かつ効率的に渡すことができなければなりません。
PersonQuery サンプル・アプリケーションで説明されている PersonQuery の例では、PersonQuery クライアント・アプリケーションのユーザがアドレスを受信できるかどうかを決定するインターセプタを使用します。ユーザの識別情報が特定の基準に一致する場合には、インターセプタは完全なアドレス番号をクライアントに返すことを許可します。一致しなかった場合、インターセプタはアドレスの代わりに x
文字からなる文字列のみをログ・ファイルに返します。
ステップ 2: インターセプタ・インプリメンテーション・コードの記述
インターセプタをインプリメントする場合、次の事項に留意します。
以下のトピックでは、多くのインターセプタについて一般的なインプリメンテーション上の検討事項について説明します。InterceptorData サンプル・インターセプタで説明する InterceptorData インターセプタから例を取ります。
インプリメンテーション・ファイルの起動
付録 A に示すコードの抜粋を、インターセプタのインプリメントを開始する際に使用できます。付録 A のコードを使用しても、BEA の Web サイト上の WebLogic Enterprise ディベロッパ・センタで入手できるスタータ・ファイルをコピーしてもかまいません。
ファイル名 |
説明 |
---|---|
|
インターセプタ・ヘッダのスタータ・ファイルです。このファイルの内容と、使用方法の説明は、ステップ 3: インターセプタ・ヘッダ・ファイルの作成に示しています。 |
|
インターセプタ・インプリメンテーションのスタータ・ファイルです。 |
WebLogic Enterprise ディベロッパ・センタからこれらのスタータ・ファイルを取得する方法については、『BEA Tuxedo 8.0 リリース・ノート』を参照してください。
付録 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;
}
//
// 必要なインターフェイス。ここで、要求パラメータを
// 解析できるように、呼び出されているオペレーションを識別する
//
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 つにマッピングする必要があります。
ステップ 3: インターセプタ・ヘッダ・ファイルの作成
インターセプタのインプリメンテーション・ファイル内に何らかのインプリメンテーション・コードを作成した後は、必要に応じてインターセプタ・ヘッダ・ファイルにデータまたはオペレーションを加える必要があります。
次のコード例は、クライアント側インターセプタとターゲット側インターセプタの双方をインプリメントする、インターセプタ・インプリメンテーション・ファイル用のヘッダ・ファイルで必要な基本情報を示します。
また、この例では次のものも示されます。
include
ファイルこのコード例では、YourInterceptor
は作成しているインターセプタの名前を表します。
#include <CORBA.h>
#include <RequestLevelInterceptor.h>
#include <security_c.h> // セキュリティ用
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; // セキュリティ用
Security::AttributeTypeList * m_attributes_to_get; // セキュリティ用
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);
};
ステップ 4: インターセプタのビルド
インターセプタは、共有可能ライブラリに組み込まれます。したがって、インターセプタをビルドする手順は、プラットフォーム固有です。任意の特定プラットフォーム上でインターセプタをビルドするのに使用される特定のコマンドおよびオプションの詳細を知るには、BEA Tuxedo ソフトウェア付属のインターセプタのサンプル・アプリケーションをビルドする makefile を実行し、ビルドによって生じるログ・ファイルで、ビルド結果を参照します。
サンプルのインターセプタをビルドするコマンドは、次のとおりです。
Windows 2000
> nmake -f makefile.nt
UNIX
> make -f makefile.mk
BEA Tuxedo ソフトウェアに付属するサンプルのインターセプタのビルドおよび実行の詳細については、PersonQuery サンプル・アプリケーションを参照してください。
ステップ 5: インターセプタのテスト
インターセプタをテストするには、次のタスクを実行する必要があります。
tmboot
コマンドを使用して、CORBA サーバ・アプリケーションをブートします。インターセプタの登録については、CORBA 要求レベルのインターセプタのデプロイを参照してください。
|
Copyright © 2001, BEA Systems, Inc. All rights reserved.
|