Sun JNDI教程翻譯 第三部分 關於Names

本文是JNDI Tutorial系列文章的第三部分:Beyond the Basics,本部分是在接觸了前面的一些基本知識(Naming操作和Directory操作)之後,介紹一些更深入的內容。
由於筆者的時間和精力的限制,從本部分開始不再進行全文的翻譯,只進行摘要翻譯,即只翻譯教程中筆者認爲重點的地方,不到之處,還請見諒!
本部分是JNDI TutorialBeyond the Basics部分的第一部分,主要介紹了一些與Names相關的知識,比如如何使用組合名稱及混合名稱,以及字符串名稱和結構化名稱的特點,同時還介紹瞭如何使用包含特定編碼的字符。
字符串名稱VS結構化名稱
ContextDirContext接口都包含重載的命名方法,其中一個接受字符串名稱(java.lang.String),另一個接受結構化的名稱(javax.naming.Name)。例如,lookup()方法包含以下兩種形式:
lookup(java.lang.String)
lookup(javax.naming.Name)
字符串名稱
接受字符串名稱的重載方法是用起來比較方便,不需要構造一個CompositeName實例(CompositeName實現了javax.naming.Name接口)。字符串參數就已經代表了一個composite name,並且這個參數遵循CompositeName類的語法規則。
例如,下面的兩個lookup方法的調用時等效的(雖然參數不同)
Object obj1=ctx.lookup(“cn=Ted Geisel,ou=people,o=JNDITutorial”);
CompositeName cname=new CompositeName(
“cn=Ted Geisel,ou=people,o=JNDITutorial”);
Object obj2=ctx.lookup(cname);
結構化名稱
接受javax.naming.Name參數的重載方法接受一個javax.naming.CompositeName或者javax.naming.CompoundName或者任何實現了Name接口的類的實例。
如果對象是CompositeName的實例,那麼就是一個composite name。一個composite name可以適用於多個命名系統,而不僅僅是調用這個方法的系統。關於如何使用composite name,請參考後面的教程。
如果不是CompositeName的實力,那麼它被當作compound name來處理,compound name只能在一個名稱空間中使用,關於如何使用CompoundName,參考後面的教程。
使用時機
既然有兩種重載的方法,那麼每種方法是用的時機是什麼呢?一般來說,當用戶提供一個字符串名字的時候,就是用字符串名字。當用戶通過輸入一個名字的各個部分來提供名字時,可以通過使用JNDI提供的類來生成一個名字,CompositeName或者CompoundName都可以根據一定的語法生成Name實例。
Composite Names
composite name 是一個跨越多個命名系統的名字。下面是它的一個例子:cn=homedir,cn=Jon Ruiz,ou=People/tutorial/report.txt
這個字符串表示了一個composite名字,它包含兩個部分,一個LDAP名字"cn=homedir,cn=Jon Ruiz,ou=People"和一個文件名"tutorial/report.txt"。當把這個字符串傳遞給一個Context接口的方法時,例如lookup()方法,使用的名稱空間是在第二部分建立的文件系統(D:/workspace/JNDITutorial/tmp/tutorial)LDAP服務器(ldap://localhost:389/o=JNDITutorial),那麼這個方法在LDAP目錄和文件系統中進行查找,然後返回目標對象(文件)。這個方法是由底層的服務provider完成的,更多內容參考Federation。下面是這個例子:
File f = (File)ctx.lookup( "cn=homedir,cn=Jon Ruiz,ou=People/tutorial/report.txt");
字符串表示
一個composite名稱由組件組成。組件是composite名稱的一段它屬於單一的命名系統。每個組件由正斜線組成
例如下面的名字
cn=homedir,cn=Jon Ruiz,ou=People/tutorial/report.txt
包含三個組件:
cn=homedir,cn=Jon Ruiz,ou=People
tutorial
report.txt
第一個組件屬於LDAP名稱空間後二個屬於文件系統名稱空間。正如本例所演示的允許同一個名稱空間中的多個組件同時出現,但是一個組件不能同時屬於多個名稱空間。
除了正斜線字符外,composite name語法允許其他三個特殊的字符:反斜線(“/”),單引號(“’”)和雙引號(“””)。斜線、反斜線和引號叫做元字符(meta character),這意味着它們在composite name中有特殊的意義。反斜線是轉義字符,當轉義字符出現在一個元字符前面時,表示的是元字符本身。例如a//b則表示a/b,此時//轉義,不再表示元字符,即不再是組件分隔符。
可以在composite name中將元字符用引號包圍而不需要轉義。當一個組件被引用時,它的第一個和最後一個符號必須是同樣的引號字符(要麼是單引號,要麼是雙引號,不能混合使用)。下面是三個相同組件的寫法,使用轉義字符、雙引號和單引號:
a//b//c//d
"a/b/c/d"
'a/b/b/d'
之所以使用兩種引號,是由於在組件中也有可能出現單引號或者雙引號。例如/”ab或者’”ab’
composite name可以是empty的,也就是說,它包含0個組件。empty composite name通過empty字符串表示。
composite name組件可能是empty,也就是說,它包含一個empty字符串。一個前置的組件分隔符(composite name以分隔符開頭)表示一個開頭的空組件。後置的分隔符表示一個空的結束空組件。兩個分隔符表示中間的一個空組件,下面是每種情況的一個例子:
/abc
abc/
abc//xyz
詳細示例,如下圖所示:
更多討論,參考處理特殊字符
CompositeName
CompositeName composite name的一個結構化形式。構造器constructor 接受一個composite name的字符串表示,並根據composite name的語法將其轉換成組件。
下面是一個使用構造方法的例子:
String name = “abc”;// Composite name to parse
try {
    CompositeName cn = new CompositeName(name);
    System.out.println(cn + " has " + cn.size() + " components: ");
    for (int i = 0; i < cn.size(); i++) {
                    System.out.println(cn.get(i));
    }
} catch (InvalidNameException e) {
    System.out.println("Cannot parse name: " + name);
}
運行結果如下:
a/b/c has 3 components:
a
b
c
        CompositeName類包含了以下方法:訪問組件、修改CompositeName、比較兩個CompositeName和獲取CompositeName的字符串表示方法。
        訪問Composite Name的組件
        可以使用以下方法訪問Composite Name的組件:
爲了獲取指定位置的組件,可以使用get()方法。前面的例子說明了這種使用辦法。
getAll()方法返回CompositeName的所有組件,可以遍歷這個枚舉來獲取沒一個組件。上例可以通過以下方法來重寫:
try {
    CompositeName cn = new CompositeName(name);
    System.out.println(cn + " has " + cn.size() + " components: ");
    for (Enumeration all = cn.getAll(); all.hasMoreElements();) {
                    System.out.println(all.nextElement());
    }
} catch (InvalidNameException e) {
    System.out.println("Cannot parse name: " + name);
}
可以獲取CompositeName的後綴或者前綴作爲一個CompositeName實例。下面是獲取一個後綴或者前綴的例子:
CompositeName cn = new CompositeName("one/two/three");
Name suffix = cn.getSuffix(1); // 1 <= index < cn.size()
Name prefix = cn.getPrefix(1); // 0 <= index < 1
When you run this program, it generates the following output.
two/three
one
可以使用CompositeNameclone方法來獲取CompositenName的一個拷貝。
修改Composite Names
下面的方法用於修改composite name
創建一個CompositeName實體後,可以添加或者移除其中的組件。如下所示:
                    CompositeName cn = new CompositeName("1/2/3");
                    CompositeName cn2 = new CompositeName("4/5/6");
                    System.out.println(cn.addAll(cn2));     // 1/2/3/4/5/6
                    System.out.println(cn.add(0, "abc"));    // abc/1/2/3/4/5/6
                    System.out.println(cn.add("xyz"));      // abc/1/2/3/4/5/6/xyz
                    System.out.println(cn.remove(1));     // 1 remove方法返回被移除的對象
                    System.out.println(cn);                                  // abc/2/3/4/5/6/xyz
比較Composite Names
下面的方法用於比較兩個composite names
可以使用compareTo()方法來對CompositeName實例列表進行排序。下面是使用compareTo()方法進行冒泡排序算法的例子:
private static void sort(CompositeName[] names) {
    int bound = names.length-1;
    CompositeName tmp;
 
    while (true) {
        int t = -1;
        for (int j=0; j < bound; j++) {
                     int c = names[j].compareTo(names[j+1]);
                        if (c > 0) {
                                         tmp = names[j];
                                         names[j] = names[j+1];
                                         names[j+1] = tmp;
                                         t = j;
                        }
        }
        if (t == -1) break;
                    bound = t;
    }
}
           equals()方法判斷兩個CompositeNames是否語義上相等。兩個Composite Names相等的條件是組件相等並且順序相同。
           通過使用startsWith()endsWith()方法,可以判斷一個CompositeName是否以另一個CompositeName開頭或者結尾。也就是說,一個CompositeName是否是另一個CompositeName的前綴後者後綴。
           isEmpty()方法用來判斷是否包含0個組件。也可以是使用size==0來進行同樣的判斷,如下所示:
CompositeName one = new CompositeName("cn=fs/o=JNDITutorial/tmp/a/b/c");
CompositeName two = new CompositeName("tmp/a/b/c");
CompositeName three = new CompositeName("cn=fs/o=JNDITutorial");
CompositeName four = new CompositeName();
 
System.out.println(one.equals(two));              // false
System.out.println(one.startsWith(three)); // true
System.out.println(one.endsWith(two));      // true
System.out.println(one.startsWith(four));   // true
System.out.println(one.endsWith(four));     // true
System.out.println(one.endsWith(three));    // false
System.out.println(one.isEmpty());                    // false
System.out.println(four.isEmpty());                    // true
System.out.println(four.size() == 0);                   // true
String表示
下面的方法用於將一個composite name轉換爲字符串名稱。
當使用CompositeName構造器的時候,需要提供一個字符串來表示一個composite name。和這個相反的就是通過一個composite name,來獲取一個字符串名稱,通過使用toString()方法來完成這個操作。toString()方法的返回值可以構造一個和原始CompositeName等價的實例。下面是一個例子:
CompositeName cn = new CompositeName(name);
String str = cn.toString();
System.out.println(str);
CompositeName cn2 = new CompositeName(str);
System.out.println(cn.equals(cn2));                                  // true
CompositeName作爲Context藉口方法的參數
傳遞給Context DirContext 接口的CompositeName實力將作爲一個composite name來處理。下面是一個查找操作的例子,使用CompositeName實例作爲參數:
// Create the initial context
Context ctx = new InitialContext(env);
// Parse the string name into a CompositeName
Name cname = new CompositeName(
    "cn=homedir,cn=Jon Ruiz,ou=people/tutorial/report.txt");
// Perform the lookup using the CompositeName
File f = (File) ctx.lookup(cname);
 
Compound Names
           一個compound name是在單一命名系統中的名字。下面是compound name的一個例子。
cn=homedir,cn=Jon Ruiz,ou=people
           這是包含三個組件的LDAP名稱的一個字符串表示。
           ou=People
           cn=Jon Ruiz
           cn=homedir
Compound NameComposite Name的關係
           當傳遞一個字符串名字給Context的方法時,期望的名字是一個composite名字,composite name可能只有一個組件。可以傳遞一個LDAP字符串名字,這是要注意字符串中是否包含與composite name語法相沖突的字符。如果有的話,需要進行適當的轉義。
           當傳遞一個Name參數給一個Context方法時,例如lookup()方法,方法可以接受composite name或者compound name,如前所述,如果要將參數解釋成composite name,那麼就是用一個CompositeName實例。
String表示
           如上所述,compound name由組件構成。組件之間根據命名系統的語法進行分隔。例如,在LDAP中,組件使用從右至左的順序,使用逗號分割符進行分隔。所以下面的組件:
           cn=People
           cn=Jon Ruiz
           cn=homedir
的字符串表示爲:
           cn=homedir,cn=Jon Ruiz,ou=People
CompoundName
           CompoundName類是compound name的結構化表示。它的構造方法接受一個字符串形式的compound name和一些描述名稱命名語法的屬性。屬性集合CompoundName類都非常靈活的描述了大多數命名系統的語法。但是,一些具體的實現可能提供特定的compound name的實現,通過繼承CompoundName或者實現Name接口。
           一般來說,只有當實現一個服務provider的時候才使用CompoundName構造方法。應用程序開發人員在解析一個特殊命名系統的名字時會經常遇到compound names。下面是一個例子:
NameParser parser = ctx.getNameParser(“”);
Name compoundName = parser.parse(compoundStringName);
操作Compound Name
           NameParser.parse()方法返回一個實現Name接口的類的對象。實現這個接口的類有CompositeNameCompoundName類。
           下面是一個關於compound name操作的例子,在其組件的頭和尾添加組件,並替換第二個組件:
// Get the parser for this namespace
NameParser parser = ctx.getNameParser("");
// Parse the name
Name cn = parser.parse("cn=John,ou=People,ou=Marketing");
// Remove the second component from the head
System.out.println(cn.remove(1));          // ou=People
// Add to the head (first)
System.out.println(cn.add(0, "ou=East")); // cn=John,ou=Marketing,ou=East
// Add to the tail (last)
System.out.println(cn.add("cn=HomeDir")); // cn=HomeDir,cn=John,ou=Marketing,ou=East
Compound Name作爲Context方法的參數
           當一個Name參數被傳遞到Context或者DirContext的方法中時,如果這個Name參數不是CompositeName,那麼就當成一個compound name來處理。下面是使用compound name進行檢索LDAP實體的例子。它首先獲取一個LDAP名稱空間的上下文句柄,然後調用Context.getNameParser()獲取名稱空間的parser,然後使用這個parser將一個LDAP字符串名稱轉換成compound name。最後在lookup()方法中使用compound name
// Create the initial context
Context ctx = new InitialContext(env);
// Get the parser for the namespace
NameParser parser = ctx.getNameParser("");
// Parse the string name into a compound name
Name compound = parser.parse("cn=Jon Ruiz,ou=people");
// Perform the lookup using the compound name
Object obj = ctx.lookup(compound);
Fully Qualified Compound Names
           有些時候需要獲取一個對象的fully qualified name。例如,在DNS中,可能希望知道一個極其的fully qualified Internet nam,這樣就可以將之用於Kerberos認證或者Internet郵件傳輸的地址。在LDAP中,一個fully qualified distinguished name可以插入到X.509證書中,或者作爲一個郵件地址或URL的一部分。
           關於fully qualified name的使用不屬於JNDI的範疇。
           JNDI提供Context.getNameInNamespace()方法來獲取一個對象的fully qualified name,相對於自身的名稱空間。也就是說,結果是一個由底層命名系統管理的名稱空間的名字。
           下面是一個查找實體的例子,並調用getnameInNamespace()方法獲取它的fully qualified LDAP名字:
// Create the initial context
Context ctx = new InitialContext(env);
// Perform the lookup
Context jon = (Context)ctx.lookup("cn=Jon Ruiz,ou=people");
String fullname = jon.getNameInNamespace();
運行結果如下:
cn=Jon Ruiz,ou=people,o=JNDItutorial
 
總結:筆者在結束上個項目至今,有一段空閒的時間,除了總結一下項目之外,自己看了一下有關JNDILDAP相關的知識,並翻譯了JNDI教程的前兩部分。在學習的過程中深深感到計算機技術海洋之深以及自身知識之淺薄,同時也感到英語知識的薄弱。筆者很喜歡英語,但是筆者更喜歡母語,喜歡英語的最大原因是它是一個International的語言,走到哪裏都可以使用,並且計算機的發展也源於西方,ASCII中沒有中文字符,變成語言還沒發展到使用中文寫表達式及語句。喜歡中文沒有原因,因爲筆者是中國人。中國人學習外語與外國人學習中文都是一樣的原因,那就是應用,與人交流,獲取知識。
筆者馬上就要進入下一個項目,所以翻譯的工作就此擱淺,但是筆者有時間的時候可能還會繼續進行翻譯,但是可能要很長時間以後吧。如果有讀者可以繼續這部分工作,請通知筆者,筆者會去您的blog拜讀。(2007-12-6)
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章