この章では、SIPサーブレットおよびJSR-116で説明されているSIP Servlet APIの概要を説明します。内容は次のとおりです。
この章では、SIP Servlet API、SIPコンテナ、SIPサーブレット環境、SIPクラスおよびメソッド、SIPアプリケーションの構成の概要を説明します。
SIP Servlet APIは、JSR 116で定義され、SIPサービスおよびアプリケーションのプログラミング用標準インタフェースを記述します。SIPサーブレットはJava HTTPサーブレットと比較されますが、SIPプロトコル関連メソッドを備えています。実際、SIP Servlet APIは、HTTP Servlet APIと同様、一般的なServlet APIの上にビルドされています。
SIPサーブレットは、4つのカテゴリに分類されます。
ユーザー・エージェント・サーバー: ユーザー・エージェント・サーバー(UAS)として機能するサーブレットは、着信リクエストを受信し、レスポンスを送信します。
ユーザー・エージェント・クライアント: ユーザー・エージェント・クライアント(UAC)として機能するサーブレットは、発信リクエストを送信し、これらのリクエストに対するレスポンスを受信します。
プロキシ: プロキシとして機能するサーブレットは、着信リクエストを受信し、これらを他のエンドポイント(他のプロキシまたはUAS)にプロキシします。プロキシ・サーブレットは、リクエストURIを操作し、リクエストをその宛先にプロキシします。
バック・ツー・バック・ユーザー・エージェント: バック・トゥ・バック・ユーザー・エージェント(B2BUA)として機能するサーブレットは、リクエストに対してUASおよびUACの両方として機能します。1つのリクエストを受信して返信し(第1セッション)、別のリクエストを送信し、レスポンスを受信します(第2セッション)。
この項では、SIPコンテナ(図2-1)の次のコンポーネントについて説明します。
サーブレット・コンテキストは、そのコンテキストが属するSIPアプリケーションのサーブレット・ビューです。サーブレット・コンテキストを使用して、サーブレットはリスナーやコンテキストのinitパラメータなどのグローバル・アプリケーション・サービスにアクセスできます。
アプリケーションのグローバルinitパラメータは、デプロイメント・ディスクリプタのsip.xmlファイルで設定され、<context-param>マーカーで示されます。グローバル・アプリケーション・パラメータの例としては、データベースやバックエンド・アプリケーションのアドレスなどの共通リソース・アドレスがあります。
サーブレット・コンテキストには、実装済および構成済リスナーへのすべての参照も含まれます。セッションとプロキシのタイムアウトは、サーブレット・コンテキストで維持されます。これらはsip.xmlファイルで構成されます。セッション・タイムアウトは<session-config>内の<session-timeout>セクションにあります。プロキシ・タイムアウトは<proxy-config>内の<sequential-search-timeout>セクションにあります。サーブレット・コンテキストは、サーブレットからgetServletContextメソッドをコールして取得します。次に例を示します。
ServletContext servletContext = getServletContext();
アプリケーションでは複数のタイプのサーブレット・セッション(SIPやHTTPなど)が処理される場合がありますが、これらのセッションは同じアプリケーションに関連している必要があります。これは、SIPアプリケーション・セッションを通して行います。SIPアプリケーション・セッションでは複数のプロトコル・セッションを維持できます。プロトコル・セッションは同じタイプでも異なるタイプ(SIP、HTTP)でもかまいません。
SIPアプリケーション・セッションでは、そのアプリケーション・セッションに関連するすべてのプロトコル・セッションで使用できる属性を維持できます。1つのSIPアプリケーション・セッションで複数のプロトコル・セッションを維持できます。たとえば、B2BUAは、同じSIPアプリケーション・セッションに置かれる2つのセッションを作成します。
SIPアプリケーション・セッションは、タイムアウトになるまで、またはアプリケーションが明示的にinvalidateメソッドをコールするまで存在します。適切に動作するアプリケーションは、不要になったセッションを常に無効化します。SIPアプリケーション・セッションが無効化されると、すべてのプロトコル・セッション・オブジェクトも一緒に無効化されます。セッションのタイムアウト値は、sip.xmlファイルで<session-timeout>パラメータを使用して設定します。この要素内でタイムアウト値が定義されていない場合、コンテナのデフォルト値が使用されます(デフォルトは15分)。
セッションが無効化された後にリクエストが届いた場合、サーバーは、481「Call transaction does not exist」メッセージを返します。SIPアプリケーション・セッションに対応するリクエストとレスポンスは、リクエスト(SipServletRequest)またはレスポンス(SipServletResponse)オブジェクトでgetApplicationSession()メソッドを使用して取得できます。
プロトコル・セッションは、特定のプロトコルのためのセッションです。アプリケーションで複数のプロトコルを扱う場合、SIPアプリケーション・セッションには複数のプロトコル・セッションが含まれます。
SipSessionオブジェクトは、ポイント間のSIP関係、確立したSIPダイアログ、または初期状態のSIPダイアログを表すことができます。初期状態は、sipFactoryクラスでcreateRequestメソッドを使用して受信または作成されたリクエストとして説明されます。SIPセッション・オブジェクトは、最初のリクエストによって1つのサーブレットが起動されたときに、コンテナによって作成されます。
SIPセッションに対応するリクエストまたはレスポンスは、リクエスト(SipServletRequest)またはレスポンス(SipServletResponse)オブジェクトでgetSession()メソッドを使用して取得できます。アプリケーション・セッション内のすべてのプロトコル・セッションは、SipApplicationSessionオブジェクトでgetSessions()メソッドを使用して取得できます。
SIPトランザクションは、1つのSIPリクエストとそのリクエストに対するすべてのレスポンス(暫定的なレスポンスと最終レスポンスを含む)で構成されます。
SipServletRequestとSipServletResponseは常にSIPトランザクションに属します。サーブレットがSIPトランザクション状態モデルに違反するメッセージを送信しようとすると、コンテナによってIllegalStateExceptionがスローされます。SIP Servlet APIは、開発者がトランザクションを気にせずに、リクエストとレスポンスのみを考慮できるように設計されています。
デプロイメント・ディスクリプタで定義されている各サーブレットには、1つのインスタンスがあります。サーブレットはマルチスレッド環境で実行されるため、initパラメータなど、すべてのリクエストとレスポンスに共通のデータのみがメンバー変数として格納されます。
各デプロイメント・ディスクリプタ・ファイル(sip.xml)に<servlet>および<servlet-mapping>セクションを含むサーブレットには、<security-constraint>セクションもあります。これらのセクションはサーブレットとともに作成されるため、これらのサーブレットはOCMS SCEのServlet Creationウィザードを通して再使用できるようになっています。
OCMSでは、Servlet archive format(SAR)ファイルは、Sip Servlet aRchive(SSR)に名前が変更されます。2つのファイルの形式は同じで、名前が異なる理由はOCMSのサード・パーティ・アプリケーション・サーバーの要件にあります。アプリケーション・サーバーではSARファイルを処理できないため、SIP ASではかわりにSSRファイルをチェックします。この名前変更によって、異なるSIPアプリケーション・サーバー間の移植が可能になります。
|
注意: Oracle 10g Application Server Controlまたはadmin_client.jarコマンドライン・ツールを介してSIPアプリケーションをデプロイする場合は、サーブレット・アーカイブ・ファイル(SARファイル)をWARに名前変更し、WARアーカイブのようにapplication.xmlにWARファイルをリストする必要があります。また、WARにはweb.xmlファイルが含まれている必要があり、それによってOC4Jにデプロイできます。SARファイルのパッケージングおよびEARファイルのデプロイの詳細は、『Oracle Communication and Mobility Server管理者ガイド』を参照してください。 |
リスナーを登録して、イベントをリスニングし、メソッドを起動できます。各デプロイメント・ディスクリプタには、タイプごとに1つのリスナーのみ定義できます。これらの各リスナーは、開発者が実装する必要があります。次に各種リスナーを示します。
SipApplicationSessionListener: SipApplicationSessionの作成および無効化用のリスナーです。セッション拡張の依頼に使用できます。SipApplicationSessionListenerインタフェースを実装し、sip.xmlを更新する必要があります。
SipSessionListener: SIPサーブレット・アプリケーションのアクティブなSipSessionsの変化用のリスナーです。SipSessionListenerインタフェースを実装し、sip.xmlで構成する必要があります。
SipSessionAttributeListener: SipSession属性の変化用のリスナーです。SipSessionAttributeListenerインタフェースを実装する必要があります。
TimerListener: TimerListenerインタフェースが実装されている場合のみ、タイマー・サービスはサーブレットの遅延アクションを有効にします。アプリケーションごとに1つのタイマー・リスナーを使用できます(sip.xml)。
SipSessionActivationListener: SipSessionActivationListenerインタフェースが実装されている場合、セッションに依存するオブジェクトは、アクティブかどうかのステータスをリスニングできます。
SIPアプリケーションは、SIPプロトコルを使用してアクセスするJ2EE準拠アプリケーションです。Webアプリケーションが着信HTTPプロトコル・リクエストによってトリガーされるように、アプリケーションは着信SIPプロトコル・リクエストによってトリガーされます。
アプリケーションには、サーブレットや他のビジネス・オブジェクト(論理層)に達するSIPやHTTPなどのプロトコル・インタフェース(プレゼンテーション層)があり、さらにサーブレットや他のビジネス・オブジェクトは管理され、データベース(データ層)へのリソース接続を行います。ユーザーおよびアプリケーション・データには、J2EE仕様の該当するパートによって表されるデータ層を介してアクセスします。アプリケーションは、デプロイメント・ディスクリプタのsip.xmlファイルのスコープによって区切られます。
この項では、SIPサーブレットの環境と、アプリケーション・サーバー(AS)の起動中およびリクエストがSIPコンテナに入ったときに発生する処理について説明します。
サーブレット・コンテナが作成されます。
グローバルinitパラメータが設定されます。これらには、sip.xmlファイルで<context-param>というマークが付けられます。
セッション構成値が設定されます。これらには、sip.xmlファイルで<session-config>というマークが付けられます。
プロキシ構成値が設定されます。これらには、sip.xmlファイルで<proxy-config>というマークが付けられます。
コンテナが、TimerListener、SipApplicationSessionListener、SipSessionActivationListener、SipSessionAttributeListenerおよびSipSessionListenerをインスタンス化します。各リスナーには1つのインスタンスがあります(定義されている場合)。
Servlet Configオブジェクトが作成されます。Servlet Configには、サーブレットごとにすべてのinitパラメータが保存されます。これらには、sip.xmlファイルで<init-param>というマークが付けられます。グローバルinitパラメータ(context-param)も含まれます。
サーブレットは、Servlet Configが提供するinitパラメータで作成および初期化されます。各サーブレットは1つのインスタンスとして実行されます。サーブレットのinitメソッドが実行されます。
SipApplicationSessionsおよびSipFactoryの参照を含むSIPアプリケーション・マネージャが作成されます。
コンテナは初期リクエストと後続リクエストを区別します。初期リクエストはサーブレットの起動条件(またはルール)に従ってサーブレットを起動し、後続リクエストは初期リクエストで起動されたサーブレットに直接転送されます。初期リクエスト時には、次の手順が発生します。
コンテナは、「初期リクエストの処理」で説明する処理に基づいて、特定のアプリケーションを選択します。
起動するサーブレットは、サーブレット起動順序の各サーブレットのルールを評価して決定されます(図2-3)。ルールの実行順序は、sip.xmlファイルの各サーブレットの<servlet-mapping>の順序によって決まります。最上位のサーブレット・マッピングを持つサーブレットのルールが最初にチェックされます。詳細は、次の「サーブレットのマッピング」を参照してください。
SIPアプリケーション・セッションがSIPセッションとともに作成されます。
トランザクションとリクエストが作成され、作成されたSIPセッション・オブジェクトに関連付けられます。
後続リクエストの場合、コンテナがすでにダイアログ(ダイアログはLocal-tag + Remote-tag + CallIdで定義されます)を保持しているので、リクエストは初期リクエストで実行されたサーブレットに転送されます。リクエストは、初期リクエストと同じメッセージ・コンテキスト(SIPアプリケーション・セッション+SIPセッション)で機能します。
SIPアプリケーションには、1つ以上のSIPサーブレットを含めることができます。SIPコンテナがSIPリクエストを受け取ると、コンテナはリクエストを処理するSIPアプリケーションを選択します。その後、SIPアプリケーションはルール(sip.xmlファイルで定義されたサーブレットのマッピング)を評価し、リクエストに応答する適切なSIPサーブレットを見つけます。検出後、リクエストに適合する最初のSIPサーブレットを使用します。
|
注意: SIPサーブレットは、javax.servlet.ServletRequest.getRequestDispatcher()を使用して、別のSIPサーブレットにリクエストを転送できます。さらに、Application Routerを使用して、アプリケーションをつなげることができます。『Oracle Communication and Mobility Server管理者ガイド』を参照してください。 |
たとえば、SIPコンテナがINVITEリクエストを受信した場合、コンテナはリクエストに適合する次のSIPサーブレットを含むSIPアプリケーションを選択します。
SIPアプリケーションは、上から下までルールを評価して、適合するサーブレットを検索します。この場合、サーブレット1とサーブレット3の両方がINVITEリクエストに適合します。これらのサーブレットの1つのみがリクエストを処理でき、アプリケーションはルールを順番に調べるため、アプリケーションはサーブレット1を選択します。サーブレット1はサーブレット3より優先されます。SIPコンテナがMESSAGEリクエストを受信すると、アプリケーションはサーブレット2を起動します。REGISTERリクエストを受信すると、このタイプのリクエストを処理できる唯一のサーブレットであるサーブレット3が起動されます。アプリケーションにサーブレット3が含まれていない場合、アプリケーションのmatchメソッドがREGISTERリクエストにnullを返し、SIPコンテナは403レスポンス「Application choose not to service the request」を発行します。このメッセージはログ・ファイルに書き込まれます。
|
注意: SIPアプリケーションは1つのリクエストに対して1つのSIPサーブレットしか起動できませんが、SIPコンテナはApplication Routerを使用して、着信リクエストに対して複数のSIPアプリケーションを起動できます。 |
この項では、SIP Servlet APIのクラスとメソッドについて説明します。
SIPサーブレットは、javax.servlet.sip.SipServletクラスを拡張するクラスで、SIPアプリケーション・サーバーと対話して、SIPメッセージを送受信します。
サーブレットは特定サービスに必要なメソッドをオーバーライドします。SIPサーブレットがオーバーライドの実行に使用する主要な2つのメソッドは次のとおりです。
doRequest()メソッドはすべてのリクエストを処理し、doResponse()メソッドはすべてのレスポンスを処理します。
serviceメソッド以外では、doRequest()とdoResponse()が、SipServletクラスが提供する最も幅広いメソッドです。これらのメソッドを使用して、受信したメソッドまたはレスポンスと関係のないタスクを有効にできます。特定のリクエストおよびレスポンス処理タスクを実行するようにメソッドを拡張できます。
doAck: SIP ACKリクエスト用
doCancel: SIP CANCELリクエスト用
doBye: SIP BYEリクエスト用
doOptions: SIP OPTIONSリクエスト用
doRegister: SIP REGISTERリクエスト用
doSubscribe: SIP SUBSCRIBEリクエスト用
doNotify: SIP NOTIFYリクエスト用
doMessage: SIP MESSAGEリクエスト用
doInfo: SIP INFOリクエスト用
doPrack: SIP PRACKリクエスト用
doSuccessResponse: SIP 2xxレスポンス用
doRedirectResponses: SIP 3xxレスポンス用
doErrorResponse: SIP 4xx、5xxおよび6xxレスポンス用
|
注意: これらのレスポンス処理メソッドは、doAckおよびdoCancelリクエスト処理メソッドと同様、空白です。残りのリクエスト処理メソッドは、500レスポンス(「Internal Server Error」)でリクエストに応答します。 |
SIPメッセージは、RFC 822標準に従います。ヘッダー、値および内容には、javax.servlet.sip.SipServletMessageインタフェースのメソッドからアクセスできます。
SipServletRequestおよびSipServletResponseクラスはどちらも、SipServletMessageインタフェースを拡張します。
public interface SipServletRequest extends javax.servlet.ServletRequest,SipServletMessage
public interface SipServletResponse extends javax.servlet.ServletResponse, SipServletMessage
SIPサーブレット・メソッドdoRequestおよびdoResponseのSipServletRequestおよびSipServletResponseオブジェクトは、SipServletRequestインタフェースとSipServletResponseインタフェースの実装で、両方ともjavax.servlet.sipパッケージのSipServletMessageインタフェースを拡張します。
SIPリクエストは次のもので構成されます。
リクエスト行
ヘッダー
空白行
メッセージ・ボディ
SIPリクエストのすべての部分、つまりリクエストURI、ヘッダーおよびパラメータには、これらのインタフェースからアクセスできます。SIPコンテナはこれらのシステム・ヘッダーの多くを処理します。アプリケーションは、次のシステム・ヘッダーを追加、削除または変更することはできません。
From
To
Call ID
CSeq
Via
Route(pushRouteからを除く)
Record Route
Contact(Contactは、REGISTERリクエストおよびレスポンス、3xxおよび485レスポンス以外のメッセージのシステム・ヘッダー・フィールド)
着信リクエストへのレスポンスは、リクエスト・オブジェクト上でcreateResponseメソッドを使用して作成します。リクエストに従ってすべてのSIPヘッダーが設定されたレスポンスが自動的に作成されます。SIPレスポンスの構造は、リクエスト行のかわりにStatus行がある点を除いて、SIPリクエストと同じです。たとえば、doResponseメソッドからレスポンスを受け取った場合は、レスポンス・オブジェクト上でgetStatus()などのメソッドを使用して、実行するアクションを決定できます。
javax.servlet.sip.SipServletMessageには、SIPヘッダーを操作するためのメソッドが含まれています。getHeaderNames()メソッドは、メッセージのSIPヘッダーのイテレータを返す最も一般的なメソッドです。setHeaderメソッドは、ヘッダーにアドレスを設定または追加します。getHeaders(name)メソッドでヘッダーの名前を指定すると、そのヘッダーのすべての値を含むStringオブジェクトの別のイテレータが返されます。
AddressHeaderに準拠するヘッダーの場合、getAddressHeader(name)メソッドは、Addressオブジェクトとして解析されたヘッダーを返します。
setAddressHeader(name, address)、addAddressHeader(name, address, first)を使用して、ヘッダーにアドレスを追加または設定できます。nameはヘッダーの名前、addressは追加するアドレス、firstはブール値です。firstをtrueに設定すると、アドレスが最初に追加されます。falseの場合は最後に追加されます。
例2-2にSIPヘッダーの操作方法を示します。
例2-2 SIPヘッダーの操作
javax.servlet.sip.SipServletRequest req;
// Set a header with the given name and value.// Overwrites any previous header values.
req.setHeader("Accept", "application/sdp");
// Add a header value to the end of a header
req.addHeader("Accept", "text/html");
// Clear all header values
req.removeHeader("Accept");
// Add a Route header value ahead of the existing Route header// values.
req.pushRoute(sipURI);
// Get the first route as an Address object
Address first route = req.getAddressHeader("Route");
// Get all address header fields for a header
Iterator addrIter = req.getAddressHeaders("Route");
while (addrIter.hasNext())
{
Address addr = (Address) addrIter.next();
// ...
}
ベース・クラスjavax.servlet.sip.URIには、2つのサブ・クラスjavax.servlet.sip.SipURIとjavax.servlet.sip.TelURLがあります。これらは、RFC 3261およびRFC 2806で定義されたURLに従ってSIP URIとTEL URLを表します。Addressクラスは、ユーザーのアドレスとしてSipURIまたはTelURLを格納します。
URIはuser@hostとして記述できます。user部分はユーザー名または電話番号、host部分はドメイン名またはIPアドレスです。
パラメータにはgetterとsetterを使用してアクセスできます。getParameterNamesメソッドは、パラメータ名とともにイテレータを返します。パラメータには、一般的なgetParameterメソッド、またはgetUser、getHost、getLrParamなどの特定のパラメータ・メソッドを使用してアクセスできます。これらはユーザー、ホスト、およびルーズ・ルートlrが設定されている場合はtrueを返します。パラメータは、例2-3に示すように、対応するsetMethod()を使用して設定できます。
From、To、ContactなどのヘッダーにあるSIPアドレスは、javax.servlet.sip Addressオブジェクトとして格納されます。例2-4に示すように、オブジェクトにはURIの他に、オプションで表示名と、nameおよびvalueパラメータのセットが含まれます。
例2-4 java.servlet.sip Addressオブジェクトに格納されるSIPアドレス
Address contactAddress;
String displayName;
try
{
// Get the contact address
contactAdress = req.getAddressHeader("Contact");
displayName = contactAdress.getDisplayName();
}
catch (ServletParseException spe)
{
// Handle exception
}
// Create a new address
Address myNewAddress;
myNewAddress = sipFactory.createAddress(URI, "Bob's display name");
myNewAddress.setParameter("myparameter","42");
前の例のmyNewAddressの内容は次のとおりです。
DisplayName: "Bob's display name"
URI: <sip:bob@example.com;lr>;
parameter myparameter: 42
Addressクラスは、次のメソッドを提供します。
getDisplayName()
setDisplayName()
getURI()
setURI()
clone()
toString()
SIP Servlet APIでは、データをセッション属性として格納できます。セッション属性は、レスポンスおよび後続リクエストまたはリスナー・クラスから使用されるセッション固有のデータの格納に使用できます。属性は、セッション・オブジェクトでsetterとgetterを使用して直接格納およびアクセスします。セッションは、SipSessionまたはSipApplicationSessionです。属性は、設定されたセッションからのみ取得できます。次に例を示します。
session.setAttribute("key", "value");
session.getAttribute("key"); // Will return "value"
session.removeAttribute("key");
セッション属性には任意のオブジェクトを格納できますが、属性とそのキーは、分散可能なアプリケーション(高可用性のために)用にシリアライズ化できる必要があります。getAttributeNamesメソッドを使用して、設定されたすべての属性を取得します。次に例を示します。
Enumeration attributes = session.getAttributeNames();
String attributeName = null;
while (attributes.hasMoreElements())
{
attributeName = (String) attributes.nextElement();
Object attribute = session.getAttribute(attributeName);
log (attribute.toString());
}
SIPサーブレット・アプリケーション・ディスクリプタ(sip.xml)の<servlet>セクションにパラメータを追加して、サーブレットを構成できます。サーブレットは、getInitParameterメソッドを使用してこれらのパラメータにアクセスできます。例2-5に、レスポンス・コードの構成方法を示します。
例2-5 サーブレットのパラメータの構成
package com.mydomain.test;
import javax.servlet.sip.SipServlet;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.SipServletResponse;
import java.io.IOException;
public class MySipServlet extends SipServlet
{
protected void doRequest(SipServletRequest req) throws IOException
{
int responseCode = Integer.parseInt(getInitParameter("responseCode"));
SipServletResponse resp = req.createResponse(responseCode);
resp.send();
}
}
SIPサーブレットは、アプリケーションのデプロイメント・ディスクリプタのsip.xmlファイルで宣言する必要があります。sip.xmlファイルでは、initパラメータと、初期リクエストをSIPサーブレットと照合するルールを構成できます。
デプロイメント・ディスクリプタは、次のセクションに別れています。
グローバルinitパラメータ(ServletContext initパラメータ)
<context-param>
セッション構成
<session-config>
サーブレット定義
<servlet>
サーブレットのマッピング(起動ルールを含む)
<servlet-mapping>
リスナー
<listener>
アプリケーションのライフ・サイクル・リスナー・クラス
エラー・ハンドラ
セキュリティ
<context-param>および<env-entry>要素は、アプリケーションで使用するデータベースやアプリケーション全体に共通の他のリソースなど、アプリケーションのグローバル・パラメータを設定し、これらにアクセスする手段を提供します。これらの要素は、グローバル・パラメータへのアクセス方法が異なります。
<context-param>要素は、サーブレット・コンテキスト全体にグローバルなサーブレットのinitパラメータを宣言します。例2-6に、<context-param>要素内でアプリケーションのデータベースを設定する方法を示します。
SIPアプリケーション・セッションは、<session-config>句内で構成されます。セッション構成では、セッションのタイムアウト値を構成できます。この構成は、次の例に示すように、<session-timeout>句内で行います。タイムアウトは分で設定します。0以下に設定すると、アプリケーション・セッションのタイムアウトは発生しないため、明示的に無効化する必要があります。<session-timeout>内で値を設定しない場合、SIPサーブレット・コンテナに設定されているデフォルトのタイムアウト・セッションがかわりに使用されます(15分)。
<session-config> <session-timeout>10</session-timeout> </session-config>
<servlet>要素では、SIPコンテナのサーブレットを定義します。サーブレットには、サーブレット名<servlet-name>とサーブレット・クラス<servlet-class>が必要です。例2-7に示すように、名前にはアプリケーション内で一意の名前、クラスにはサーブレット・クラスの完全修飾名を指定する必要があります。
例2-7 サーブレット名とサーブレット・クラス
<servlet> <servlet-name>MyServlet</servlet-name> <servlet-class>com.company.example.MyServlet</servlet-class> </servlet>
サーブレットには、独自のinitパラメータ<init-param>と説明<description>を含めることもできます。コンテナが起動すると、例2-8に示すように、<load-on-startup>要素が設定されているサーブレットのinit()メソッドのみがインスタンス化され、コールされます。
例2-8 サーブレットの定義
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.mydomain.test.MySipServlet</servlet-class>
<init-param>
<param-name>logging</param-name>
<param-value>true</param-value>
<description>
Set if logging should be switched on (true) or not (false).
</description>
</init-param>
<init-param>
<param-name>infotainment</param-name>
<param-value>http://www.infotainmentsite.com</param-value>
<description>
The site to use as the infotainment content provider.
</description>
</init-param>
<load-on-startup/>
</servlet>
SIPサーブレット・アプリケーションのデプロイメント・ディスクリプタの<servletmapping>要素では、サーブレットを起動する条件を定義します。例2-9に、着信MESSAGEリクエストにMySipServletというサーブレットのみを起動する方法を示します。詳細は、「サーブレットのマッピング」を参照してください。
例2-9 サーブレットのマッピング
<!-- Servlet Mappings for incoming requests-->
<servlet-mapping>
<servlet-name>My Sip Servlet</servlet-name>
<pattern>
<equal>
<var>request.method</var>
<value>MESSAGE</value>
</equal>
</pattern>
</servlet-mapping>
リクエスト・オブジェクト・モデルでは、SIPリクエストを処理するためのルールを定義できます。この項では、オブジェクト・モデルとルールを作成するための基礎を説明します。
リクエスト・オブジェクトには、URIオブジェクトを拡張するSipURIなど、多くのサブ・オブジェクトが含まれます。
リクエスト・オブジェクトには次の要素があります。
method: リクエストのメソッドは、文字列として表されます。
uri: リクエスト・オブジェクトのURIオブジェクト、SipURIやTelURIなどです。
from: Addressとして表されるFromヘッダー・アドレスです。
to: Addressとして表されるToヘッダー・アドレスです。
URIオブジェクトはURIスキームで構成されます。
SipURIオブジェクトには次の要素があります。
scheme: 文字列sipまたはsips(sipsは、TLSを使用する必要があることを示します)。
user: SIPまたはSIPS URIのユーザー部分です。SIPアドレスがsip:alice@example.comの場合、request.uri.userはaliceを返します。
host: SIPまたはSIPS URIのホスト部分です。SIPアドレスがsip:alice@example.comの場合、request.uri.hostはexample.comを返します。
port: SIP URIポートです。存在しない場合、UDPおよびTCPのデフォルト値は5060、TLSのデフォルト値は5061です。
tel: パラメータuserがURIの電話に設定されている場合、SIPまたはSIPS URIのユーザー部分を返します。最初の視覚セパレータ+と-は取り除かれます。たとえば、SIP URIがsip:+12345@example.com;user=phoneの場合、request.uri.telは12345を返します。
param.name: 名前がnameのSipURIパラメータの値です。たとえば、リクエストURI: INVITE sip:23479234@oracle.com;user=phone SIP/2.0の場合、request.uri.param.userはphoneを返します。
TelURLオブジェクトには次の要素があります。
scheme: 文字列telです。
tel: tel URLサブスクライバ名です。
param.name: 名前がnameのSipURIパラメータの値です。
Addressには次の要素があります。
uri: URIオブジェクトです。
display-name: ヘッダーのToまたはFrom表示名です。
表2-1は、演算子のリストです。
表2-1 演算子
| 条件名 | 説明 |
|---|---|
|
equal |
変数の値をリテラル値と比較します。変数が定義され、その値がリテラルの値と等しい場合trueと評価されます。それ以外の場合、結果はfalseです。 |
|
exists |
変数名を調べます。変数が定義されている場合はtrueに評価され、変数が定義されていない場合はfalseに評価されます。 |
|
contains |
最初の引数である変数に、2番目の引数で指定されたリテラル文字列が含まれている場合、trueを返します。 |
|
subdomain of |
ドメイン名(SIP/SIPS URIホスト)または電話サブスクライバ(SIPまたはTel URLのtelプロパティ)を示す変数とリテラル値が指定され、変数がリテラル値のドメインのサブ・ドメインを表す場合、 |
表2-2は、論理コネクタのリストです。
例2-10に、様々なタイプの変数で参照されるリクエストの部分を示します。
例2-10 リクエスト要素の参照
MESSAGE sip:bob@example.com SIP/2.0 Call-ID: a2412d22-161b-4cff-b4a5-a4c6c1f70f18 To: <sip:bob@example.com> From: "Alice" <sip:alice@example.com>;tag=1234 Max-Forwards: 70 User-Agent: Oracle-CallTron/4.5.7.1445 Accept: text/plain CSeq: 2 MESSAGE Content-Type: text/plain; charset=UTF-8 Content-Length: 13 Via: SIP/2.0/TCP 10.0.0.20:3094;branch=z9hG4bK-477709c9-c064-4b95- 90bc-7391d0154368.1;rport Route: <sip:messageapp@sipappserver.com;lr> Proxy-Authorization: Digest username="alice", realm="example.com", nonce="MTEzNDQwMzkwMDc3NDJiM2JkY2E1ZmRiY2M4YzBjYzQ2M2VhMTM2NWFlM2Fm", uri="sip:bob@example.com", qop=auth, nc=00000001, cnonce="443857DE", response="e5c48d5d2982cf3974260511218a246a", opaque="4a94690f435b9049b896dce0b6ddb8fe" The message!
表2-3に、変数値の説明を示します。
表2-3 変数値
| 変数 | 値 |
|---|---|
|
request.method |
MESSAGE |
|
request.uri |
sip:bob@example.com |
|
request.uri.scheme |
sip |
|
request.uri.user |
bob |
|
request.uri.host |
example.com |
|
request.uri.port |
5060 |
|
request.uri.tel |
|
|
request.from |
"Alice" <sip:alice@example.com>;tag=1234 |
|
request.from.uri |
sip:alice@example.com |
|
request.from.uri.scheme |
sip |
|
request.from.uri.user |
alice |
|
request.from.uri.host |
example.com |
|
request.from.uri.port |
5060 |
|
request.from.display-name |
Alice |
|
request.to |
sip:bob@example.com |
|
request.to.uri |
sip:bob@example.com |
|
request.to.uri.scheme |
sip |
|
request.to.uri.user |
bob |
|
request.to.uri.host |
example.com |
|
request.to.uri.port |
5060 |
|
request.to.display-name |
次の例は、falseに評価されます。
<pattern>
<and>
<equal>
<var>request.method</var>
<value>MESSAGE</value>
</equal>
<contains>
<var>request.from</var>
<value>tag=1234</value>
</contains>
<equal>
<var>request.uri.host</var>
<value>otherexample.com</value>
</equal>
</and>
</pattern>
最初の条件equalは、trueに評価されます。2番目の条件containsも、trueに評価されます。3番目の条件では、otherexample.comに対するリクエストのみを処理することを示していますが、リクエストURIホストがexample.comのため、falseに評価されます。3番目の条件はすべてand条件内に含まれているので、ルール全体でもfalseと評価されます。
この項では、SIP Servlet APIに対するOCMS拡張およびその実装について説明します。次の内容について説明します。
SIPコンテナは、初期リクエストを受信すると、SIPアプリケーションの起動を試みます。SIPコンテナは、appIdパラメータに基づいてアプリケーションを選択します。appIdの詳細は、第3章「高度なSIPサーブレットの構成」を参照してください。SIPコンテナのワークフローは次のとおりです。
リクエストに、起動するアプリケーションの指示が含まれているかどうかを確認します。
起動するアプリケーションの名前がない場合、SIPコンテナはデフォルトのアプリケーションを選択します。
リクエストによってアプリケーションが指定されている場合、SIPコンテナはアプリケーションを探し、起動します。
|
注意: 初期リクエストで起動するアプリケーションが指定されていない場合、コンテナはデフォルトのアプリケーションを選択します。 |
たとえば、着信リクエストに応答するために、SIPサーブレット・コンテナは次のSIPアプリケーションを評価します。
アプリケーションAのsip.xmlでは、次の2つのSIPサーブレットが定義されています。
サーブレット1はINVITEリクエストに適合します。
サーブレット2はMESSAGEリクエストに適合します。
アプリケーションBのsip.xmlでは、次のSIPサーブレットが定義されています。
サーブレット1はINVITEリクエストに適合します。
アプリケーションCのsip.xmlでは、次の2つのSIPサーブレットが定義されています。
サーブレット1はREGISTERリクエストに適合します。
サーブレット2はすべてのリクエストに適合します。
アプリケーションDのsip.xmlでは、次の2つのSIPサーブレットが定義されています。
サーブレット1はSUBSCRIBEリクエストに適合します。
サーブレット2はPUBLISHリクエストに適合します。
アプリケーションEのsip.xmlでは、次のSIPサーブレットが定義されています。
サーブレット1はすべてのリクエストに適合します。
これらすべてのアプリケーションがSIPコンテナにデプロイされていますが、デフォルト・アプリケーションは指定されていません。SIPコンテナは、検出したすべてのSIPアプリケーションをデフォルト・アプリケーションとして指定します。たとえば、起動するアプリケーションが指定されていないINVITEリクエストを受信した場合、SIPコンテナはデフォルト・アプリケーションをチェックします。しかし、コンテナにデプロイされたアプリケーションはどれもデフォルト・アプリケーションとして構成されていないので、コンテナはすべてのアプリケーションを取得します。これらのアプリケーションの順序は次のとおりです。
アプリケーションB
アプリケーションD
アプリケーションC
アプリケーションE
アプリケーションA
SIPコンテナはアプリケーションのリストを、アプリケーションBから順番に調べます。各アプリケーションで、着信リクエストを処理できるサーブレットを問い合せます。アプリケーションに適切なサーブレットが含まれている場合、そのサーブレットが起動され、このリクエストに関して他のアプリケーションは考慮されません。例2-11に、SIPコンテナのアプリケーション評価プロセスのコンセプト・コードを示します。
例2-11 着信リクエストのSIPアプリケーションの評価
List allDeployedApplications = retrieve all applications that have been deployed;
for each application in allDeployedApplications do:
SipServlet servlet = application.match(incoming request);
if servlet is not null then:
servlet.processIncomingRequest(request);
return;
end if
end for
この場合、SIPコンテナは、着信INVITEリクエストの処理にアプリケーションBを選択します。SIPコンテナがPUBLISHリクエストを受信した場合、もう一度リストを取得して、アプリケーションB(最初のアプリケーション)に問い合せます。アプリケーションBはリクエストに適合しないため、SIPコンテナは次のアプリケーション、アプリケーションDに移ります。このアプリケーションにはこのリクエストを処理するサーブレットがあるので、SIPコンテナはアプリケーションDを選択します。
アプリケーションAはデプロイされたアプリケーションのリストの最後にあり、すべての着信イベントを受け入れるアプリケーションCが前にあるため、起動されることはありません。また、アプリケーションCの最初のサーブレットがすべてのREGISTERリクエストを処理し、2番目のサーブレットが他のすべてのリクエストを処理するため、その後ろのアプリケーションが処理に使用されることはありません。
次の項では、SIPサーブレット仕様の実装オプションについて説明します。
SIPサーブレット仕様には、HTTPなどの他のプロトコル・セッションを同じSIPアプリケーション・セッションに置けると記載されています。しかし、OCMSは現在SIPプロトコルのみをサポートしています。
|
注意: SIPとHTTPを収束したアプリケーションを作成できないわけではありません。例は、Oracle Technology Network(http://www.oracle.com/technology/index.html)でOracle Communication and Mobility Serverのドキュメントを参照してください。 |
OCMS SCEウィザードはdoPublish()メソッドを提供しています。ウィザードは、SIP PUBLISHリクエストも送信することで、doRequestメソッドを拡張しています(RFC 3903)。
SIP PUBLISHリクエストの処理にはdoPublish() メソッドが使用されます。
「リクエストとレスポンスの処理メソッド」も参照してください。
OCMSでは、サーブレットはマルチスレッド環境で実行され、複数のサーブレットが一度に同じセッション・オブジェクトにアクセスする可能性があります。リクエストとレスポンスは、コンテナのスレッド・プールから使用可能なスレッドを使用します。したがって、アプリケーション・ロジックで必要な場合は、開発者がセッションおよびそのリソースへのアクセスの同期を担当することがあります。
jcp.orgのWebページhttp://jcp.org/aboutJava/communityprocess/final/jsr116/index.htmlからJavadocをダウンロードできます。
zipファイルのダウンロードが完了したら、Javadocの新しい場所を含めるように、EclipseでのJavadocの場所を更新できます。
SIPとHTTPを収束したアプリケーションを作成できるように、OCMS ContainerはJNDIを使用した参照によるjavax.servlet.sip.SipFactoryへのアクセスを可能にしています。SIPファクトリは、例2-12に示すように、SIPサーブレットと同じ表示名で登録されます。この場合、sip.xmlの<display-name>は「My sip app」です。
OCMSは、TimesTen In-Memory Databaseに格納されているユーザー、ユーザー・ロール、ユーザー・データ、または外部RADIUS(Remote Authentication Dial-In User Service)サーバーに対してダイジェスト・アクセス認証を提供します。OCMSは、OID(Oracle Internet Directory)にプロビジョニングされたユーザーの認証および承認サービスもサポートします。
ログイン・モジュールのOCMSLoginModuleとRADIUSLoginModuleは、JAASセキュリティ・プロバイダとして機能し、SIPアプリケーションにはダイジェスト認証、J2EEアプリケーションにはBasic認証を実行するカスタム・ログイン・モジュールです。OCMSLoginModuleは、TimesTenデータベースに格納されたユーザー・データに対する認証を、RadiusLoginModuleは、外部RADIUSサーバーに対する認証を実行します。Basicアクセス認証は、ファイルベースのログイン・モジュールFileLoginModuleを使用する場合のみサポートされ、テスト時のみ使用することをお薦めします。
詳細は、『Oracle Communication and Mobility Server管理者ガイド』を参照してください。