5 JNDIに対するJava API拡張機能の使用
5.1 Java拡張機能のインストールについて
Java拡張機能は、LDAPクライアントのインストール時に標準のJava APIとともにインストールされます。
APIとその拡張機能は、$ORACLE_HOME/jlib/ldapjclnt10.jar
にあります。
5.2 oracle.ldap.utilパッケージを使用したLDAPオブジェクトのモデル化
Javaでは、LDAPエンティティ(ユーザー、グループ、レルム、アプリケーション)は、ハンドルではなくJavaオブジェクトとしてモデル化されます。このモデル化は、oracle.java.util
パッケージで行われます。他のすべてのユーティリティ機能は、個々のオブジェクトとして(GUID
など)、あるいはユーティリティ・クラスの静的メンバー関数としてモデル化されます。
たとえば、ユーザーを認証するには、アプリケーションは次のステップに従います。
- 指定されたユーザー識別名で、
oracle.ldap.util.User
オブジェクトを作成します。 - 必要なプロパティのすべてを備えた
DirContext
JNDIオブジェクトを作成するか、あるいはDirContext
オブジェクトのプールからJNDIオブジェクトを取得します。 User.authenticateUser
メソッドを呼び出して、DirContext
オブジェクトおよびユーザー資格証明への参照を渡します。- 既存の
DirContext
オブジェクトのプールから取得したDirContext
オブジェクトは、そのプールに戻します。
CやPL/SQLのプログラマとは異なり、Javaプログラマはオブジェクトを明示的に解放する必要がありません。このタスクは、Javaのガベージ・コレクション・メカニズムが実行します。
5.3 PropertySetCollection、PropertySetおよびPropertyクラスの使用方法
Userクラス、SubscriberクラスおよびGroupクラスのほとんどのメソッドは、PropertySetCollection
オブジェクトを戻します。このオブジェクトは、1つ以上のLDAPエントリの集合を表しています。各エントリはPropertySet
オブジェクトで表され、識別名で識別されます。
PropertySetには、Propertyとして表される属性が含まれる場合があります。Propertyとは、そのPropertyが表す特定の属性に関する1つ以上の値の集合です。次に、これらのクラスの使用例を示します。
PropertySetCollection psc = Util.getGroupMembership( ctx, myuser, null, true ); // for loop to go through each PropertySet for (int i = 0; i < psc.size(); i++ ) { PropertySet ps = psc.getPropertySet(i); // Print the DN of each PropertySet System.out.println("dn: " + ps .getDN()); // Get the values for the "objectclass" Property Property objectclass = ps.getProperty( "objectclass" ); // for loop to go through each value of Property "objectclass" for (int j = 0; j< objectclass.size(); j++) { // Print each "objectclass" value System.out.println("objectclass: " + objectclass.getValue(j)); } }
エンティティmyuser
は、Userオブジェクトです。psc
オブジェクトには、myuserが属するネストされたグループがすべて含まれます。このコードは結果エントリをループし、各エントリのオブジェクト・クラス値をすべて出力します。
5.4 Javaクラスoracle.ldap.util.Userを使用したユーザーの管理
ユーザー関連機能はすべてoracle.ldap.util.User
というJavaクラスで抽象化されます。
このプロセスは、次のようになります。
- 識別名、GUIDまたは単純な名前に基づいて、
oracle.ldap.util.User
オブジェクトを構成します。 - 必要な場合は、
User.authenticateUser(DirContext, int, Object)
を呼び出して、ユーザーを認証します。 User.getProperties(DirContext)
を呼び出して、ユーザー・エントリの属性を取得します。User.getExtendedProperties(DirContext, int, String[])
を起動してユーザーの拡張プロパティを取得します。int
はsharedまたはapplication-specificのどちらかです。String[]
は必要なプロパティのタイプを表すオブジェクトです。String[]
がnullの場合、指定されたカテゴリのすべてのプロパティが取得されます。PropertySetCollection.getProperties(int)
を呼び出して、ステップ4で戻されたプロパティの解析に必要なメタデータを取得します。- 拡張プロパティを解析し、アプリケーション固有のロジックを続行します。この解析は、アプリケーション固有のロジックによっても行われます。
5.5 LDAP操作でのユーザーの認証
ユーザー認証は、ユーザーがログイン時に指定した資格証明とそのユーザーのディレクトリ内の資格証明を比較する一般的なLDAP操作です。
Oracle Internet Directoryでは、次のものがサポートされています。
-
認証時に使用可能な任意の属性。
-
認証メソッドによって戻される任意のパスワード・ポリシー例外。ただし、パスワード・ポリシーは
userpassword
属性のみに適用されることに注意してください。
次に、APIを使用してユーザーを認証するためのコード例を示します。
// User user1 - is a valid User Object try { user1.authenticateUser(ctx, User.CREDTYPE_PASSWD, "welcome"); // or // user1.authenticateUser(ctx, <any attribute>, <attribute value>); } catch (UtilException ue) { // Handle the password policy error accordingly if (ue instanceof PasswordExpiredException) // do something else if (ue instanceof GraceLoginException) // do something }
5.6 createUser( )を使用したユーザーの作成
subscriberクラスによってcreateUser()
メソッドが使用され、プログラムによりユーザーが作成されます。ユーザー・エントリに必要なオブジェクト・クラスは、Oracle Delegated Administration Servicesを介して設定可能です。
createUser()
メソッドは、ユーザーの作成時に、クライアントが要件を理解し必須の属性に対して値を提供することを前提にしています。プログラマによって必須情報が提供されない場合、サーバーはエラーを戻します。
コード例の次のスニペットは、使用方法を示します。
// Subscriber sub is a valid Subscriber object // DirContext ctx is a valid DirContext // Create ModPropertySet object to define all the attributes and their values. ModPropertySet mps = new ModPropertySet(); mps.addProperty(LDIF.ATTRIBUTE_CHANGE_TYPE_ADD,"cn", "Anika"); mps.addProperty(LDIF.ATTRIBUTE_CHANGE_TYPE_ADD,"sn", "Anika"); mps.addProperty(LDIF.ATTRIBUTE_CHANGE_TYPE_ADD,"mail", "Anika@example.com"); // Create user by specifying the nickname and the ModPropertySet just defined User newUser = sub.createUser( ctx, mps, true); // Print the newly created user DN System.out.println( newUser.getDN(ctx) ); // Perform other operations with this new user
5.7 ユーザー・オブジェクトの取得
subscriberクラスによってgetUser()
メソッドが提供され、Userクラスのパブリック・コンストラクタと置き換えられます。このメソッドは、指定された情報に基づいてUserオブジェクトを戻します。
次に、使用方法を示します。
// DirContext ctx is contains a valid directory connection with sufficient privilege to perform the operations // Creating RootOracleContext object RootOracleContext roc = new RootOracleContext(ctx); // Obtain a Subscriber object representing the default subscriber Subscriber sub = roc.getSubscriber(ctx, Util.IDTYPE_DEFAULT, null, null); // Obtain a User object representing the user whose nickname is "Anika" User user1 = sub.getUser(ctx, Util.IDTYPE_SIMPLE, "Anika", null); // Do work with this user The getUser() method can retrieve users based on DN, GUID and simple name. A getUsers() method is also available to perform a filtered search to return more than one user at a time. The returned object is an array of User objects. For example, // Obtain an array of User object where the user's nickname starts with "Ani" User[] userArr = sub.getUsers(ctx, Util.IDTYPE_SIMPLE, "Ani", null); // Do work with the User array
5.8 レルムからのオブジェクトの取得
Java APIを使用してアイデンティティ管理レルムのオブジェクトを取得できます。RootOracleContext
クラスはルートOracleコンテキストを表します。アイデンティティ管理レルムの作成に必要な情報のほとんどは、ルートOracleコンテキストに格納されています。
RootOracleContext
クラスではgetSubscriber()
メソッドが提供されます。このメソッドは、subscriberクラスのパブリック・コンストラクタと置き換えられ、指定された情報に基づいてアイデンティティ管理レルム・オブジェクトを戻します。
次に、使用方法を示します。
// DirContext ctx contains a valid directory // connection with sufficient privilege to perform the // operations // Creating RootOracleContext object RootOracleContext roc = new RootOracleContext(ctx); // Obtain a Subscriber object representing the // Subscriber with simple name "Oracle" Subscriber sub = roc.getSubscriber(ctx, Util.IDTYPE_SIMPLE, "Oracle", null); // Do work with the Subscriber object
5.9 Oracle Single Sign-Onログイン名の検索
単純な名前、GUIDまたはDNがわかっている場合は、ユーザーのログイン名を検索できます。Oracle Single Sign-Onのログイン名は、ニックネームとも呼ばれます。
この例は、2つの部分から構成されています。
- このレルムへのニックネームの保存に使用されている属性を確認します。
- ユーザー・オブジェクトを取得し、ニックネーム属性の値を確認します。
import javax.naming.*; import javax.naming.directory.*; import javax.naming.ldap.*; import oracle.ldap.util.jndi.*; import oracle.ldap.util.*; import java.io.*; public class NickNameSearch { public static void main(String[] args) throws Exception { InitialLdapContext ctx = ConnectionUtil.getDefaultDirCtx( args[0], args[1], args[2],args[3]); RootOracleContext roc=new RootOracleContext(ctx); Subscriber sub = null; sub = roc.getSubscriber(ctx, Util.IDTYPE_DEFAULT, null, null) ; PropertySetCollection psc = sub.getProperties(ctx, Subscriber.USER_NAMING_PROPERTIES, null); String nickNameAttribute = null; try { nickNameAttribute = (String) psc.getPropertySet(0).getProperty(Subscriber.USER_NAMING_ATTR_SIMPLE).getValue(0); } catch (Exception e) { // unable to retrieve the attribute name System.exit(0); } System.out.println("Nickname attribute: " + nickNameAttribute); // Retrieve user using simple name, guid or DN User user = sub.getUser(ctx, Util.IDTYPE_SIMPLE,"orcladmin", null); System.out.println("user DN: " + user.getDN(ctx)); // Retrieve nickname value using User object psc = user.getProperties(ctx, new String[]{ nickNameAttribute }); String nickName = null; try { nickName = (String) psc.getPropertySet(0).getProperty(nickNameAttribute).getValue(0); } catch (Exception e) { // unable to retrieve the attribute value System.exit(0); } System.out.println("Nickname : " + nickName); } }
5.10 ディレクトリ・サーバーを検出するためのJavaクラスの導入
Javaクラスoracle.ldap.util.discovery.DiscoveryHelper
は、指定されたソースからディレクトリ・サーバーを検出するために使用されます。
次の新しいJavaクラス(パブリック・クラス)が導入されました。
public class oracle.ldap.util.discovery.DiscoveryHelper
このクラスでは、指定されたソースから特定の情報を検出するメソッドが提供されます。
表5-1 ディレクトリ・サーバー検出のメソッド
メソッド | 説明 |
---|---|
discover |
指定されたソースから特定の情報を検出します。 |
setProperty |
検出に必要なプロパティを設定します。 |
getProperty |
プロパティの値にアクセスします。 |
既存のJavaクラスoracle.ldap.util.jndi.ConnectionUtil
に、次の2つの新しいメソッドが追加されます。
-
getDefaultDirCtx
: オーバーロードされたこのファンクションでは、oracle.ldap.util.discovery.DiscoveryHelper.discover()
に対して内部コールを実行して、SSL以外のLDAPサーバーのホスト名およびポート情報が判断されます。 -
getSSLDirCtx
: オーバーロードされたこのファンクションでは、oracle.ldap.util.discovery.DiscoveryHelper.discover()
に対して内部コールを実行して、SSLのLDAPサーバーのホスト名およびポート情報が判断されます。
5.11 ディレクトリ・サーバーの検出
ディレクトリ・サーバー検出用のサンプルのJavaプログラムを実行します。
import java.util.*; import java.lang.*; import oracle.ldap.util.discovery.*; import oracle.ldap.util.jndi.*; public class dsdtest { public static void main(String s[]) throws Exception { HashMap reshdl = new HashMap(); String result = new String(); Object resultObj = new Object(); DiscoveryHelper disco = new DiscoveryHelper(DiscoveryHelper.DNS_DISCOVER); // Set the property for the DNS_DN disco.setProperty(DiscoveryHelper.DNS_DN,"dc=us,dc=fiction,dc=com") ; // Set the property for the DNS_DISCOVER_METHOD disco.setProperty(DiscoveryHelper.DNS_DISCOVER_METHOD, DiscoveryHelper.USE_INPUT_DN_METHOD); // Set the property for the SSLMODE disco.setProperty(DiscoveryHelper.SSLMODE,"0"); // Call the discover method int res=disco.discover(reshdl); if (res!=0) System.out.println("Error Code returned by the discover method is :"+res) ; // Print the results printReshdl(reshdl); } public static void printReshdl(HashMap reshdl) { ArrayList result = (ArrayList)reshdl.get(DiscoveryHelper.DIR_SERVERS); if (result != null) { if (result.size() == 0) return; System.out.println("The hostnames are :-"); for (int i = 0; i< result.size();i++) { String host = (String)result.get(i); System.out.println((i+1)+". '"+host+"'"); } } } }
5.12 Digest-MD5を使用したSASL認証の実行
JNDIを使用してSASL接続を確立する場合、javax.naming.Context
の次のプロパティを設定する必要があります。
-
Context.SECURITY_AUTHENTICATION = "DIGEST-MD5"
-
Context.SECURITY_PRINCIPAL
後者にはプリンシパル名を設定します。この名前は、サーバー固有の形式です。次のいずれかのようになります。
-
認証されているエンティティの完全に修飾された識別名が続く識別名
dn:
-
ユーザー識別子が続く文字列
u:
。Oracleディレクトリ・サーバーは、完全に修飾された識別名(
cn=user,ou=my department,o=my company
など)のみを受け入れます。
ノート:
SASL識別名は、SASLバインドをコールするAPIに渡される前に正規化される必要があります。SASLベリファイアを生成するために、Oracle Internet Directoryでは正規化された識別名のみがサポートされます。
5.13 SASL Digest-MD5のauth-intモードおよびauth-confモードの使用方法
次のコードでは、SASL Digest-MD5を使用したJava LDAP/JNDIの例を示します。
/* $Header: LdapSasl.java 27-oct-2005.11:26:59 qdinh Exp $ */ /* Copyright (c) 2003, 2005, Oracle. All rights reserved. */ /* DESCRIPTION <short description of component this file declares/defines> PRIVATE CLASSES <list of private classes defined - with one-line descriptions> NOTES <other useful comments, qualifications, and so on.> MODIFIED (MM/DD/YY) qdinh 04/23/03 - Creation */ /** * @version $Header: LdapSasl.java 27-oct-2005.11:26:59 qdinh Exp $ * @author qdinh * @since release specific (what release of product did this appear in) */ package oracle.ldap.util.jndi; import javax.naming.*; import javax.naming.directory.*; import javax.naming.ldap.*; import oracle.ldap.util.jndi.*; import oracle.ldap.util.*; import java.lang.*; import java.util.*; public class LdapSasl { public static void main( String[] args) throws Exception { int numofargs; numofargs = args.length; Hashtable hashtable = new Hashtable(); // Look through System Properties for Context Factory if it is available // then set the CONTEXT factory only if it has not been set // in the environment - // set default to com.sun.jndi.ldap.LdapCtxFactory hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); // possible valid arguments // args[0] - hostname // args[1] - port number // args[2] - Entry DN // args[3] - Entry Password // args[4] - QoP [ auth | auth-int | auth-conf ] // args[5] - SASL Realm // args[6] - Cipher Choice // If QoP == "auth-conf" then args[6] cipher choice can be // - des // - 3des // - rc4 // - rc4-56 // - rc4-40 hashtable.put(Context.PROVIDER_URL, "ldap://"+args[0]+":"+args[1]); hashtable.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5"); System.out.println("hash put security dn: " + args[2]); hashtable.put(Context.SECURITY_PRINCIPAL, args[2] ); hashtable.put(Context.SECURITY_CREDENTIALS, args[3] ); // For Quality of Protection modes // 1. Authentication and Data Integrity Mode - "auth-int" // 2. Authentication and Data Confidentiality Mode "auth-conf" // // hashtable.put("javax.security.sasl.qop",args[4]); hashtable.put("javax.naming.security.sasl.realm", args[5]); // Setup Quality of Protection // // System.out.println("hash sasl.qop: " + args[4]); hashtable.put("javax.security.sasl.qop",args[4]); if (numofargs > 4) { if (args[4].equalsIgnoreCase("AUTH-CONF")) { // Setup a cipher choice only if QoP == "auth-conf" String strength = "high"; String cipher = new String(args[6]); if (cipher.compareToIgnoreCase("rc4-40") == 0) strength = "low"; else if (cipher.compareToIgnoreCase("rc4-56") == 0 || cipher.compareToIgnoreCase("des")== 0 ) strength = "medium"; else if (cipher.compareToIgnoreCase("3des") == 0 || cipher.compareToIgnoreCase("rc4") == 0) strength = "high"; // setup cipher choice System.out.println("hash sasl.strength:"+strength); hashtable.put("javax.security.sasl.strength",strength); } // set maxbuffer length if necessary if (numofargs > 7 && !"".equals(args[6])) hashtable.put("javax.security.sasl.maxbuf", args[5].toString()); } // Enable Debug -- // hashtable.put("com.sun.jndi.ldap.trace.ber", System.err); LdapContext ctx = new InitialLdapContext(hashtable,null); // At this stage - SASL Digest -MD5 has been successfully System.out.println("sasl bind successful"); // Ldap Search Scope Options // // - Search base - OBJECT_SCOPE // - One Level - ONELEVEL_SCOPE // - Sub Tree - SUBTREE_SCOPE // // Doing an LDAP Search PropertySetCollection psc = Util.ldapSearch(ctx,"o=oracle,dc=com","objectclass=*",SearchControls.OBJECT_SCOPE, new String[] {"*"}); // Print out the serach result Util.printResults(psc); System.exit(0); } }
5.14 LDAPトランザクションの使用
11gリリース1 (11.1.1.6)の時点で、Oracle Internet Directory SDKはRFC 5805に定義されているトランザクションをサポートしています。トランザクションは、プロビジョニングなどのいくつかのアプリケーションをサポートするために必要になります。
関連項目:
『RFC 5805 on Lightweight Directory Access Protocol (LDAP) Transactions』(http://www.ietf.org
)
トランザクションがコミットされた場合、トランザクション更新内のすべての操作が成功するか、すべて失敗するかのいずれかです。Oracle Internet Directoryは、拡張操作およびコントロールのオブジェクト識別子を、ルートDSEでsupportedExtensionおよびsupportedControlとして公開します。
5.14.1 LDAPトランザクションで使用されるエンティティ
Oracle Internet Directory LDAPトランザクションには、トランザクションのリクエストおよびレスポンスの次のエンティティがあり、トランザクションを終了します。
表5-2 LDAPトランザクションおよびエンティティ
エンティティ | 説明 |
---|---|
トランザクション開始リクエスト(オブジェクト識別子1.3.6.1.1.21.1) |
トランザクション開始に関連した操作のグループ化を容易にするLDAP拡張操作です。これはrequestNameが1.3.6.1.1.21.1でrequestValueが存在しないCHOICE extendedReqのLDAPMessageです。 |
トランザクション開始レスポンス |
トランザクション開始リクエストへのレスポンス内でOracle Internet Directoryサーバーから送信されます。これはCHOICE extendedResのLDAPMessageです。このresponseNameは存在しません。成功した場合、resultCode(0)、responseValueは存在しトランザクション識別子を保持しています。リクエスト形式が不正などの理由で失敗した場合、responseValueは存在しません。 |
トランザクション仕様コントロール(オブジェクト識別子1.3.6.1.1.21.2) |
これは、トランザクションIDをコントロールの値とし、これを利用して操作とトランザクションの関連付けを指定するLDAPコントロールです。このcriticalityはTRUEです。 |
トランザクション終了リクエスト(オブジェクト識別子1.3.6.1.1.21.3) |
トランザクションの終了を示すために使用される、もう1つのLDAP拡張操作です。このトランザクションの処理(トランザクションのコミットまたは中断)を示します。このLDAPMessageはrequestNameが1.3.6.1.1.21.3でrequestValueが存在するCHOICE extendedReqを保持し、BERでエンコードされたトランザクション・リクエストを格納します。 コミットの値がTRUEの場合、識別子で識別されたトランザクションをコミットするリクエストです。コミットの値がFALSEの場合、識別されたトランザクションを中断するリクエストです。 |
トランザクション終了レスポンス |
Oracle Internet Directoryサーバーのトランザクション終了リクエストへのLDAPMessageレスポンスです。このレスポンス名は存在しません。responseValueが存在する場合、これにはBERでエンコードされたトランザクション・レスポンスが格納されます。 |
トランザクション中断通知(オブジェクト識別子1.3.6.1.1.21.4): |
トランザクション識別子を含む、responseNameが1.3.6.1.1.21.4でresponseValueが存在する要求に基づかない通知メッセージです。 |
5.14.2 LDAPトランザクションでの一連のリクエストおよびレスポンス
LDAPトランザクションでは、Oracle Internet Directoryサーバーとクライアントの間で一連のリクエストおよびレスポンスが発生します。
LDAPトランザクションでの一連のリクエストおよびレスポンスは、次のとおりです。
-
クライアントが、Oracle Internet Directoryサーバーにトランザクション開始リクエストを発行します。
-
Oracle Internet Directoryサーバーが、トランザクション開始レスポンスにトランザクション識別子を設定し、成功のresultCode(0)でこのリクエストに応答します。不正な形式のリクエストなどの理由で失敗した場合、サーバーはエラーの種類を示す成功以外のresultCodeを含むトランザクション開始レスポンスで応答します。
成功した場合に生成されてクライアントに送信されるこのトランザクション識別子は、後続のプロトコル・メッセージでこのトランザクションを識別するために使用されます。
-
クライアントはサーバーから成功の結果コードを受け取ると、トランザクション識別子を持ったトランザクション仕様コントロールを各更新操作に添付して、単一トランザクションの一部として処理される操作であることを示します。有効な場合のレスポンスでは、Oracle Internet Directoryは成功を送信します。無効の場合、エラーの種類の詳細とともにresultCodeを含む、リクエストへの適切なレスポンスをクライアントに送信します。
-
クライアントは、トランザクション識別子を持ったトランザクション仕様コントロールが添付された、すべてのトランザクション更新操作をOracle Internet Directoryサーバーに送信すると、トランザクション識別子を格納したトランザクション終了リクエストをOracle Internet Directoryサーバーに送信し、トランザクションの処理を要求します。コミットの値がTRUEの場合はトランザクションをコミットするリクエストを表し、値がFALSEの場合はトランザクションを中断するリクエストを表します。
-
トランザクション中断のリクエストを受信すると、Oracle Internet Directoryサーバーは識別されたトランザクションを構成するすべての操作を破棄してトランザクションを中断し、成功のresultCode(0)を含むトランザクション終了レスポンスを返すことで処理の完了を表します。トランザクションをコミットするリクエストを受信すると、Oracle Internet DirectoryサーバーはDBに対して、トランザクション内のすべての操作に対して行った更新をコミットします。成功した場合、サーバーは、成功のresultCode(0)を含むトランザクション終了レスポンスを戻します。失敗した場合は、失敗の種類を表す成功以外のresultCodeを含むトランザクション終了レスポンスを戻します。
トランザクション外でリクエストされたトランザクションや更新をサーバーがシリアライズする必要はありません。つまり、サーバーは1つ以上のクライアントからの異なるエントリ・セット上で動作する複数のコミット・リクエストを同時に処理することがあります。
-
前述のクライアントとサーバーとのやりとりの際、サーバーがトランザクションの仕様を継続できなくなった場合、サーバーはトランザクション中断通知を発行します。この通知を受信すると、クライアントはトランザクション識別子の使用をすべて中止する必要があり、トランザクションはnullおよびvoidとなります。トランザクションの一部として処理が予定されていたすべての操作は暗黙的に破棄されます。クライアントが引き続きこの識別子を使用しても、Oracle Internet Directoryサーバーからは失敗のresultCodeを含むレスポンスが戻されます。
-
前述のクライアントとサーバーとのやりとりの際、クライアントがOracle Internet Directoryサーバーへの接続を閉じた場合、サーバーは必要な接続関連のクリーンアップを実行します。
5.15 JNDIベースのLDAPトランザクションの使用方法
LDAP拡張操作を使用したJNDIベースのLDAPトランザクションJavaクライアント・モジュールの開発に必要なステップについて学習します。このステップでは、トランザクション開始リクエスト、トランザクション開始レスポンス、トランザクション終了リクエストおよびトランザクション終了レスポンスの4つのインタフェースの実装を行います。
これら4つのインタフェースを実装するクラスは、トランザクション・セマンティクス内でLDAP更新操作を実行するコードで使用される必要があります。
次のサンプルのコード・スニペットは、実装される4つのインタフェースと、トランザクション・セマンティクスでのLDAP更新操作のサンプルにおけるこれらの使用方法を示します。
5.15.1 トランザクション開始リクエスト・インタフェースの実装(LdapStartTxnReq.java)
JavaクラスLdapStartTxnReq
を使用して、トランザクション開始リクエスト・インタフェースを実装できます。
次のコードに、トランザクション開始リクエスト・インタフェースの実装を示します。
import java.lang.*; import java.util.*; import java.io.*; import javax.naming.*; import javax.naming.directory.*; import javax.naming.ldap.*; public class LdapStartTxnReq implements ExtendedRequest { public static final String TXN_REQ_OID = "1.3.6.1.1.21.1"; // constructor public LdapStartTxnReq() { } // Method for getting the request ID public String getID() { return TXN_REQ_OID; } public byte[] getEncodedValue() { return null; // No value is needed for Start Txn request } public ExtendedResponse createExtendedResponse(String id, byte[] berValue, int offset, int length) throws NamingException { return new LdapStartTxnRes(id, berValue, offset, length); } }
5.15.2 トランザクション開始レスポンス・インタフェースの実装(LdapStartTxnRes.java)
JavaクラスLdapStartTxnRes
を使用して、トランザクション開始レスポンス・インタフェースを実装できます。
次のコードに、トランザクション開始レスポンス・インタフェースを示します。
import java.lang.*; import java.util.*; import java.io.*; import javax.naming.*; import javax.naming.directory.*; import javax.naming.ldap.*; public class LdapStartTxnRes implements ExtendedResponse { public String txnID; // Called by LdapStartTxnReq.createExtendedResponse() protected LdapStartTxnRes(String id, byte[] berValue, int offset, int length) throws NamingException { byte[] buff2 = new byte[length]; System.arraycopy(berValue, offset, buff2, 0, length); try { this.txnID = new String(berValue, "UTF8"); } catch (Exception e) { System.out.println(e); } } public String getTxnID() { return txnID; } // No op for our case public byte[] getEncodedValue() { return null; } public String getID() { return null; // as have no response ID. } }
5.15.3 トランザクション終了リクエスト・インタフェースの実装(LdapEndTxnReq.java)
JavaクラスLdapEndTxnReq
を使用して、トランザクション終了リクエスト・インタフェースを実装できます。
次のコードに、トランザクション終了リクエスト・インタフェースの実装を示します。
import java.lang.*; import java.util.*; import java.io.*; import javax.naming.*; import javax.naming.ldap.*; import oracle.ldap.util.ber.*; public class LdapEndTxnReq implements ExtendedRequest { public static final String TXN_END_REQ_OID = "1.3.6.1.1.21.3"; private int sequenceTag = 0x30; private boolean commitValue; private String controlValue; // constructor public LdapEndTxnReq(boolean commitVal, String controlVal) { this.commitValue = commitVal; this.controlValue = controlVal; } // Method to get End Txn Request ID public String getID() { return TXN_END_REQ_OID; } public byte[] getEncodedValue() { boolean encodeUTF8 = true; byte[] bytes = null; try { BEREncoder berElement = new BEREncoder(); berElement.beginSeq(sequenceTag); berElement.encodeBoolean(this.commitValue); berElement.encodeString(this.controlValue, encodeUTF8); berElement.endSeq(); bytes = berElement.getTrimmedBuf(); return bytes; } catch (EncodeException e) { return null; } } public ExtendedResponse createExtendedResponse(String id, byte[] berValue, int offset, int length) throws NamingException { return null; } }
5.15.4 トランザクション終了レスポンス・インタフェースの実装(LdapEndTxnRes.java)
JavaクラスLdapEndTxnRes
を使用して、トランザクション終了レスポンス・インタフェースを実装できます。
次のコードに、トランザクション終了レスポンス・インタフェースの実装を示します。
import java.lang.*; import java.util.*; import java.io.*; import javax.naming.*; import javax.naming.directory.*; import javax.naming.ldap.*; public class LdapEndTxnRes implements ExtendedResponse { // constructor LdapEndTxnRes(String id, byte[] berValue, int offset, int length) throws NamingException { ; } public String getTxnID() { return null; } public byte[] getEncodedValue() { return null; } public String getID() { return null; } }
5.15.5 トランザクション・セマンティクス内のLDAP更新操作でのJavaおよび疑似コード・インタフェース・サンプルの使用方法(LdapTxnOperation.java)
LDAP更新操作を実行するために、Javaおよび疑似コード・インタフェースを使用できます。
次のコードに、Javaおよび疑似コード・インタフェース・サンプルを示します。
import java.lang.*; import java.util.*; import java.io.*; import javax.naming.*; import javax.naming.directory.*; import javax.naming.ldap.*; . . . public class LdapTxnOperation implements ……………. { public static void main( String[] args ) { try { LdapContext ctx; Perform ldapbind against OID server on the LDAP context ctx; If bind is successful { /* Issue LDAP Start Transaction Request to OID server and receive its response */ LdapStartTxnRes startResp = (LdapStartTxnRes)ctx.extendedOperation(new LdapStartTxnReq()); /* Extract the transaction ID sent by OID server */ String txnID = startResp.getTxnID(); Issue LDAP update operations (add, delete, modify) to OID server each containing the Transaction Control with ID 1.3.6.1.1.21.2 and value of the transaction ID; /* Vendor's technical doc link is provided in Reference section below */ /* After done sending all update operations, issue LDAP End Transaction Request to OID server with your intention to either commit or abort the transaction and receive its response. */ If want to commit the transaction { /* commit request */ LdapEndTxnRes endResp = (LdapEndTxnRes)ctx.extendedOperation(new LdapEndTxnReq(true, txnID)); } Else { /* abort request */ LdapEndTxnRes endResp = (LdapEndTxnRes)ctx.extendedOperation(new LdapEndTxnReq(false, txnID)); } } catch( Exception e) { e.printStackTrace(); return; } return ; } }