Module java.naming

Package javax.naming.ldap


package javax.naming.ldap
提供对LDAPv3扩展操作和控件的支持。

此包扩展了Java命名和目录接口(JNDI)的目录操作。  JNDI为使用Java编程语言编写的应用程序提供命名和目录功能。它旨在独立于任何特定的命名或目录服务实现。因此,各种服务--新的、新兴的和已部署的服务--可以以通用方式访问。

此包适用于处理LDAPv3扩展操作和控件的应用程序和服务提供者,如RFC 2251所定义。此包中的核心接口是LdapContext,它定义了在上下文中执行扩展操作和处理控件的方法。

扩展操作

此包定义了接口ExtendedRequest来表示扩展操作的参数,以及接口ExtendedResponse来表示扩展操作的结果。扩展响应始终与扩展请求配对,但不一定反之。也就是说,您可以有一个没有对应扩展响应的扩展请求。

应用程序通常不直接处理这些接口。相反,它们处理实现这些接口的类。应用程序获取这些类,要么作为通过IETF标准化的扩展操作的一部分,要么从目录供应商获取用于特定供应商的扩展操作。请求类应具有以类型安全和用户友好的方式接受参数的构造函数,而响应类应具有以类型安全和用户友好的方式获取响应数据的访问方法。在内部,请求/响应类处理BER值的编码和解码。

例如,假设LDAP服务器支持“获取时间”扩展操作。它将提供诸如GetTimeRequestGetTimeResponse之类的类,以便应用程序可以使用此功能。应用程序将如下使用这些类:

GetTimeResponse resp =
    (GetTimeResponse) ectx.extendedOperation(new GetTimeRequest());
long time = resp.getTime();

GetTimeRequestGetTimeResponse类可能定义如下:

public class GetTimeRequest implements ExtendedRequest {
    // 用户友好的构造函数 
    public GetTimeRequest() {
    };

    // 供服务提供者使用的方法
    public String getID() {
        return GETTIME_REQ_OID;
    }
    public byte[] getEncodedValue() {
        return null;  // 获取时间请求不需要值
    }
    public ExtendedResponse createExtendedResponse(
        String id, byte[] berValue, int offset, int length) throws NamingException {
        return new GetTimeResponse(id, berValue, offset, length);
    }
}
public class GetTimeResponse() implements ExtendedResponse {
    long time;
    // GetTimeRequest.createExtendedResponse()调用
    public GetTimeResponse(String id, byte[] berValue, int offset, int length)
        throws NamingException {
        // 检查id的有效性
        long time =  ... // 解码berValue以获取时间
    }

    // 类型安全和用户友好的方法
    public java.util.Date getDate() { return new java.util.Date(time); }
    public long getTime() { return time; }

    // 低级方法
    public byte[] getEncodedValue() {
        return // 保存的berValue;
    }
    public String getID() {
        return GETTIME_RESP_OID;
    }
}

控件

此包定义了接口Control来表示LDAPv3控件。它可以是发送到LDAP服务器的控件(请求控件)或LDAP服务器返回的控件(响应控件)。与扩展请求和响应不同,请求控件和响应控件之间不一定有配对关系。您可以发送请求控件而不期望返回响应控件,或者接收响应控件而不发送任何请求控件。

应用程序通常不直接处理此接口。相反,它们处理实现此接口的类。应用程序获取控件类,要么作为通过IETF标准化的控件的一部分,要么从目录供应商获取用于特定供应商的控件。请求控件类应具有以类型安全和用户友好的方式接受参数的构造函数,而响应控件类应具有以类型安全和用户友好的方式获取响应数据的访问方法。在内部,请求/响应控件类处理BER值的编码和解码。

例如,假设LDAP服务器支持“签名结果”请求控件,当与请求一起发送时,要求服务器对操作的结果进行数字签名。它将提供一个类SignedResultsControl,以便应用程序可以使用此功能。应用程序将如下使用这个类:

Control[] reqCtls = new Control[] {new SignedResultsControl(Control.CRITICAL)};
ectx.setRequestControls(reqCtls);
NamingEnumeration enum = ectx.search(...);
SignedResultsControl类可能定义如下:
public class SignedResultsControl implements Control {
    // 用户友好的构造函数 
    public SignedResultsControl(boolean criticality) {
        // 组装请求控件的组件
    };

    // 供服务提供者使用的方法
    public String getID() {
        return // 控件的对象标识符
    }
    public byte[] getEncodedValue() {
        return // ASN.1 BER编码的控件值
    }
    ...
}

当服务提供者接收响应控件时,它使用ControlFactory类生成实现Control接口的特定类。

LDAP服务器可以在LDAP操作和枚举结果中发送响应控件,例如由列表或搜索操作返回的结果。 LdapContext提供了一个方法(getResponseControls())用于获取与LDAP操作一起发送的响应控件,而HasControls接口用于检索与枚举结果关联的响应控件。

例如,假设LDAP服务器在成功修改后向响应中发送“更改ID”控件。它将提供一个类ChangeIDControl,以便应用程序可以使用此功能。应用程序将执行更新,然后尝试获取更改ID。

// 执行更新
Context ctx = ectx.createSubsubcontext("cn=newobj");

// 获取响应控件
Control[] respCtls = ectx.getResponseControls();
if (respCtls != null) {
    // 找到我们想要的控件
    for (int i = 0; i < respCtls; i++) {
        if(respCtls[i] instanceof ChangeIDControl) {
            ChangeIDControl cctl = (ChangeIDControl)respCtls[i];
            System.out.println(cctl.getChangeID());
        }
    }
}
供应商可能提供以下ChangeIDControlVendorXControlFactory类。当服务提供者从LDAP服务器接收响应控件时,将使用VendorXControlFactory
public class ChangeIDControl implements Control {
    long id;

    // ControlFactory使用的构造函数
    public ChangeIDControl(String OID, byte[] berVal) throws NamingException {
        // 检查OID的有效性
        id = // 从berVal中提取更改ID
    };

    // 类型安全和用户友好的方法
    public long getChangeID() {
        return id;
    }

    // 低级方法
    public String getID() {
        return CHANGEID_OID;
    }
    public byte[] getEncodedValue() {
        return // 原始berVal
    }
    ...
}
public class VendorXControlFactory extends ControlFactory {
    public VendorXControlFactory () {
    }

    public Control getControlInstance(Control orig) throws NamingException {
        if (isOneOfMyControls(orig.getID())) {
            ...

            // 确定我们的控件之一并调用其构造函数
            return (new ChangeIDControl(orig.getID(), orig.getEncodedValue()));
        }
        return null;  // 不是我们的控件
    }
}

包规范

JNDI API规范和相关文档可以在JNDI文档中找到。
自版本:
1.3