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)
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章