Sun JNDI教程翻译 第三部分 关于Names

本文是JNDI Tutorial 系列文章的第三部分: Beyond the Basics ,本部分是在接触了前面的一些基本知识( Naming 操作和 Directory 操作)之后,介绍一些更深入的内容。
由于笔者的时间和精力的限制,从本部分开始不再进行全文的翻译,只进行摘要翻译,即只翻译教程中笔者认为重点的地方,不到之处,还请见谅!
本部分是 JNDI Tutorial Beyond the Basics 部分的第一部分,主要介绍了一些与 Names 相关的知识,比如如何使用组合名称及混合名称,以及字符串名称和结构化名称的特点,同时还介绍了如何使用包含特定编码的字符。
字符串名称 VS 结构化名称
Context DirContext 接口都包含重载的命名方法,其中一个接受字符串名称 (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
可以使用 CompositeName clone 方法来获取 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 Name Composite 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 接口的类的对象。实现这个接口的类有 CompositeName CompoundName 类。
           下面是一个关于 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
 
总结:笔者在结束上个项目至今,有一段空闲的时间,除了总结一下项目之外,自己看了一下有关 JNDI LDAP 相关的知识,并翻译了 JNDI 教程的前两部分。在学习的过程中深深感到计算机技术海洋之深以及自身知识之浅薄,同时也感到英语知识的薄弱。笔者很喜欢英语,但是笔者更喜欢母语,喜欢英语的最大原因是它是一个 International 的语言,走到哪里都可以使用,并且计算机的发展也源于西方, ASCII 中没有中文字符,变成语言还没发展到使用中文写表达式及语句。喜欢中文没有原因,因为笔者是中国人。中国人学习外语与外国人学习中文都是一样的原因,那就是应用,与人交流,获取知识。
笔者马上就要进入下一个项目,所以翻译的工作就此搁浅,但是笔者有时间的时候可能还会继续进行翻译,但是可能要很长时间以后吧。如果有读者可以继续这部分工作,请通知笔者,笔者会去您的 blog 拜读。 (2007-12-6)
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值