目次
RMI レジストリサービスプロバイダを使用して、JNDI アプリケーションから RMI レジストリに登録されているリモートオブジェクトにアクセスできます。プロバイダにレジストリの位置を渡すと、そのレジストリに登録されているオブジェクトにバインドされたネーミングコンテキストが作成されます。このコンテキストは、JNDI からアクセス可能なほかの名前空間 (LDAP など) にバインドされます。各リモートオブジェクトへの参照も、同様にほかの名前空間にバインドされます。
レジストリコンテキストをほかの名前空間にバインドすると、リモートオブジェクトに対して、レジストリの位置に依存しないアクセスを行うことができます。RMI クライアントでは、レジストリのホスト名またはポート番号の情報は必要ありません。RMI サーバーでは、サーバーのサービスを潜在的なクライアントに通知するときに、この機能を利用できます。また、リモートオブジェクトから、ユーザー、組織、およびネットワークリソースの情報にアクセスするときに使用される企業ディレクトリに対して、リンクを作成できます。
このサービスプロバイダがインストールされている場合は、JNDI に java.rmi.Naming クラスの機能が組み込まれます。
このドキュメントでは、RMI レジストリサービスプロバイダの機能について説明します。
RMI レジストリサービスプロバイダでは、次の JNDI 環境プロパティーが使用されます。環境プロパティー、システムプロパティー、アプレットパラメータ、およびリソースファイルを使用してプロパティーがどのように初期化されるかについては、JNDI のドキュメントを参照してください。
java.naming.factory.initial
レジストリサービスプロバイダを選択するときに、初期コンテキストとして使用されます。プロバイダでは使用されません。プロバイダの初期コンテキストファクトリのクラス名を指定します。たとえば、
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
このプロパティーは、java.naming.provider.url プロパティーとともに使用されます。レジストリを初期コンテキストとして使用している場合は、このプロパティーを設定する必要があります。ただし、初期コンテキストに URL だけを渡した場合は、このプロパティーを指定する必要はありません。詳細は、「RMI URL」を参照してください。
java.naming.provider.url
レジストリが初期コンテキストとして使用されているときは、このプロパティーにレジストリの位置を指定します。その値は、オブジェクト名コンポーネントを含まない RMI URL です (下の「RMI URL の形式」を参照)。たとえば、
env.put(Context.PROVIDER_URL, "rmi://server:1099");
このプロパティーのデフォルト値は「rmi:」です。ローカルホストのポート 1099 上で動作するレジストリです。
このプロパティーは、java.naming.factory.initial プロパティーとともに使用されます。
java.naming.factory.state
状態ファクトリクラスの完全修飾名のリストです。コロンで区切られています。渡されたオブジェクトが格納されるときに、オブジェクトの状態を取得するために使用されます。このメカニズムを使用して、オブジェクトをレジストリに格納できる形式に変換できます。RMI レジストリサービスプロバイダは、java.rmi.Remote、javax.naming.Reference、および javax.naming.Referenceable オブジェクトの格納をサポートします。詳細は、javax.naming.spi.NamingManager.getStateToBind() を参照してください。
java.naming.factory.object
オブジェクトファクトリクラスの完全修飾名のリストです。コロンで区切られています。レジストリから読み込まれたオブジェクトが変換されます。このメカニズムを使用して、オブジェクトをアプリケーションに適した形式に変換できます。詳細は、javax.naming.spi.NamingManager.getObjectInstance() を参照してください。
com.sun.jndi.rmi.factory.socket
このプロパティーは、クライアントソケットを取得して RMI を呼び出すために、RMI ランタイムで使用するソケットファクトリを指定します。ソケットファクトリに指定される値は、java.rmi.server.RMIClientSocketFactory 型である必要があります。このプロパティーが設定されていない場合、レジストリではデフォルトのソケットファクトリが使用されます。
java.naming.rmi.security.manager
このプロパティーは、どの値に設定されていても、プロバイダが RMISecurityManager をインストールを試みることを示します。下の「セキュリティーについて」を参照してください。
RMI レジストリでは、フラットな名前空間がサポートされます。階層がないため、すべての名前は基本要素です。名前には任意の文字を使用できます。大文字小文字が区別されます。
名前は、レジストリコンテキストのメソッドに引数として渡され、これらのメソッドの結果として、Name オブジェクトまたは文字列のどちらかとして返されます。Name オブジェクトを使用するときは、レジストリに渡される基本名を値として持つコンポーネントが 1 つ必要です。文字列が名前として使用されると、合成名の文字列表現として解釈されます。そのため、たとえば ctx がレジストリコンテキストの場合、次の 2 つのバインド解除操作は同等です。
String name = ... ctx.unbind(name); ctx.unbind(new CompositeName(name));
合成名の解析中に特別に処理される 4 つのメタキャラクタ「/」、「\\」、「"」、「\'」のいずれかを含む名前には注意が必要です。これらの文字は、適切な方法でエスケープするか、引用符で囲む必要があります。たとえば、基本名 X/Y は、X と Y をコンポーネントとして含む 2 つのコンポーネントから成る名前と間違われないように、合成名 X\/Y として表すことができます。詳細は、CompositeName を参照してください。
JNDI では、オブジェクトが指定されている URL の解決がサポートされます。そして、レジストリサービスプロバイダでは、RMI URL を名前として使用できます。これにより、より汎用的な JNDI インタフェースのみを使用する、java.rmi.Naming 機能の汎用性が向上します。
com.sun.jndi.url.rmi.rmiURLContextFactory クラスは、RMI URL の URL コンテキストファクトリを実装します。このため、デフォルトの JNDI 初期コンテキストに RMI URL を名前として渡すことができます。
RMI URL では、次のどちらかの形式が使用されます。
rmi://[host][:port][/[object]] rmi:[/][object]オブジェクト名を指定しなかった場合は、指定したホストおよびポートのレジストリが URL に指定されます。オブジェクト名を指定した場合は、指定したオブジェクト名の下のレジストリに登録されているリモートオブジェクトが URL に指定されます。
ホストを省略した場合は、ローカルホストが指定されているとみなされます。ポートを省略した場合は、デフォルトレジストリのポート 1099 が指定されているとみなされます。
レジストリサービスプロバイダは、java.naming.Context および java.naming.Referenceable インタフェースを実装します。Context および Referenceable メソッドは、下で説明されているレジストリ操作にマップされます。
lookup() lookupLink()
java.rmi.Registry.lookup() メソッドが呼び出されます。返されたオブジェクトが javax.naming.Reference のラッパーである場合、参照されるオブジェクトは javax.naming.spi.NamingManager.getObjectInstance() を使用して作成されます。JNDI リンクは、現在サポートされていません。
bind()
java.rmi.Registry.bind() メソッドが呼び出されます。最初に、javax.naming.spi.NamingManager.getStateToBind() によって状態ファクトリが参照されます。バインドするオブジェクトの型は、java.rmi.Remote、javax.naming.Reference、または javax.naming.Referenceable でなければなりません。オブジェクトが javax.naming.Reference または javax.naming.Referenceable である場合、その参照は Remote ラッパー内にラップされてからバインドされます (下の「オブジェクトをレジストリにバインドする」を参照)。
rebind()
java.rmi.Registry.rebind() メソッドが呼び出されます。それ以外の場合、オブジェクトは JNDI bind() 操作のように処理されます。
unbind()
java.rmi.Registry.unbind() メソッドが呼び出されます。
rename()
このメソッドは、JNDI 操作のシーケンス (lookup()、bind()、unbind()) として実装されます。シーケンスは、基本的には実行されません。
list()
java.rmi.Registry.list() メソッドが呼び出されます。このメソッドでは、バインドされたオブジェクトの型に関する情報は提供されないため、返される各 javax.naming.NameClassPair のクラス名はジェネリックの java.lang.Object になります。
listBindings()
java.rmi.Registry.list() メソッドが呼び出されます。結果として得られた列挙から javax.naming.Binding が読み込まれるたびに、java.rmi.Registry.lookup() が呼び出され、javax.naming.spi.NamingManager.getObjectInstance() 経由で渡されます。
createSubcontext() destroySubcontext()
これらの操作はサポートされていません。
getNameParser()
大文字小文字を区別する基本名の場合に、名前パーサーが返されます。
getNameInNamespace()
空の文字列 (レジストリの名前) が返されます。
composeName()
2 つの名前の組み合わせが返されます。
addToEnvironment()
指定したプロパティーが、コンテキストの環境に追加されます。java.naming.rmi.security.manager プロパティーが追加された場合、プロバイダは、デフォルトの RMI セキュリティーマネージャーのインストールを試みます (「セキュリティーについて」を参照)。その他のプロパティーの環境への追加または変更を行うこともできますが、コンテキストには影響しません。
removeFromEnvironment()
指定したプロパティーが、コンテキストの環境から削除されます。削除されなかった場合は、コンテキストに対する影響はありません。
close()
プロバイダによって使用されている内部状態がクリアされます。クリアされなかった場合は、直接の影響はありません。
getReference()
このコンテキストが参照で構築されている場合は、その参照の複製が返されます。それ以外の場合は、ホスト名を特定でき、それが「localhost」でなければ、そのコンテキストの新しい参照が返されます (下の「レジストリコンテキストとリモートオブジェクトのバインディング」を参照)。
オブジェクトをレジストリにバインドする
オブジェクトが java.rmi.Remote インタフェースを実装している場合は、そのオブジェクトをレジストリコンテキストにバインドできます。オブジェクトはまた、JNDI Reference オブジェクトである場合や、Referenceable インタフェースを実装している場合にもバインドできます (その場合は、そのオブジェクト自体ではなく、対応する参照がバインドされます)。
レジストリコンテキストとリモートオブジェクトのバインディング
各 RMI レジストリコンテキストが Referenceable インタフェースを実装します。そのため、各コンテキストを、Referenceable オブジェクトを格納できる JNDI からアクセス可能な任意の名前空間にバインドできます。レジストリに登録されている各リモートオブジェクトへの参照も構築されます。このとき、そのオブジェクトをほかの名前空間にバインドできます。
com.sun.jndi.rmi.registry.RegistryContextFactory クラスは、レジストリ参照を対応するレジストリコンテキストまたはリモートオブジェクトに変換するオブジェクトファクトリを実装します。
レジストリコンテキストを構築する場合は、レジストリの URL が識別できなければなりません。この URL は、java.naming.provider.url プロパティーから取得されるか、初期コンテキストに名前として渡されるか、またはレジストリ参照に埋め込まれていることがあります。URL にホスト名が含まれていないか、またはホスト名「localhost」が使用されている場合、レジストリコンテキストの getReference() メソッドはコンテキストの参照を返すことができません。そのため、このようなレジストリコンテキストを別の名前空間にバインドすることはできません。
レジストリ参照の形式
RMI レジストリの JNDI 参照には、それぞれに「URL」型のタグが付けられた、文字列アドレス (StringRefAddr クラス) のリストが含まれています。各アドレスには、レジストリかレジストリに登録されているリモートオブジェクトのどちらかを示す RMI URL が含まれています (上の「RMI URL の形式」を参照)。
複数の URL が 1 つの参照に含まれるときは、各 URL は同一の論理リソースの代替アドレスです。アドレスの順番は重要ではありません。StringRefAddr クラスでないアドレスや、「URL」のアドレス型でないアドレスは無視されます。
プログラム例 1
レジストリにアクセスする初期コンテキストを作成するには、上の「環境プロパティー」の説明に従って、java.naming.factory.initial および java.naming.provider.url プロパティーを設定します。レジストリに格納された名前は、次のように出力されます。
Context ictx = new InitialContext(env); NamingEnumeration enum = ictx.list("");
プログラム例 2
プログラム例 1 のプロパティーを使用しないで、RMI URL を名前として渡し、デフォルトの初期コンテキストで解決します。
Context registryCtx = (Context)ictx.lookup("rmi://host");
プログラム例 3
レジストリコンテキストは、JNDI にアクセス可能なほかの名前空間にバインドされます。たとえば、前の例の registryCtx を LDAP ディレクトリにバインドするには、次のようにします。
Context ldapCtx = (Context)ictx.lookup("ldap://server/o=sun,c=us"); ldapCtx.bind("cn=rmi", registryCtx);名前 R1 と R2 がこのレジストリにバインドされている場合、LDAP 名前空間をブラウズしている JNDI クライアントでは、cn=rmi エントリの下に R1 と R2 が表示されます。
プログラム例 4
RMI レジストリに登録されているリモートオブジェクトは、そのオブジェクトに対する参照を構築すると、JNDI にアクセス可能なほかの名前空間にバインドされます。変数 obj に前の例の R1 という名前のオブジェクトが保持されている場合は、それを次のように LDAP ディレクトリにバインドできます。
RefAddr addr = new StringRefAddr("URL", "rmi://host/R1"); Reference ref = new Reference(obj.getClass().getName(), addr); ldapCtx.bind("cn=R1", ref);
通常の RMI セキュリティーが適用されます。RMI を使用してリモートサーバーのクラスを動的にロードするには、まずセキュリティーマネージャーをインストールする必要があります。セキュリティーマネージャーは、ほかの RMI アプリケーションと同じ方法でインストールできます。JavaTM Remote Method Invocation の仕様を参照してください。または、java.naming.rmi.security.manager 環境プロパティーがプロバイダに渡された場合、プロバイダは RMISecurityManager 自体をインストールしようとします。
JNDI および RMI レジストリプロバイダを使用するアプリケーションには、次のアクセス権が必要です。
permission java.net.SocketPermission "host[:port]", "connect";
java.naming.provider.url プロパティー、およびコンテキストメソッドに指定されている URL 文字列名で識別される各ホスト/ポート用のアクセス権です。
permission java.net.SocketPermission "host[:port]", "connect,accept";
javax.naming.References 内の URL 文字列で識別される各ホスト/ポート用のアクセス権です。
permission java.lang.RuntimePermission "setSecurityManager";
RMI レジストリプロバイダに RMISecurityManager をインストールするよう依頼する、java.naming.rmi.security.manager 環境プロパティーを使用している場合。