Controls and Extensions

 


"Extended" Operations

As mentioned earlier in this lesson, the LDAP v3 defines the "extended" operation, which takes a request as the argument and returns a response. The request contains an identifier that identifies the request and the arguments of the request. The response contains the results of performing the request. The pair of "extended" operation request/response is called an extension. For example, there can be an extension for Start TLS, which is a request for the client to the server to activate the TLS protocol. These extensions can be standard (defined by the LDAP community) or proprietary (defined by a particular directory vendor).

The javax.naming.ldap package defines the interface ExtendedRequest to represent the argument to an "extended" operation, and the interface ExtendedResponse to represent the result of the operation. An extended response is usually paired with an extended request but not necessarily vice versa. That is, you can have an extended request that has no corresponding extended response. An unpaired extended response is called an unsolicited notification, described in detail in the Event Notification lesson.

An application typically does not deal directly with these interfaces. Instead, it deals with classes that implement these interfaces. The application gets these classes either as part of a repertoire of "extended" operations standardized through the IETF or from directory vendors for vendor-specific "extended" operations. The request classes should have constructors that accept arguments in a type-safe and user-friendly manner, whereas the response classes should have access methods for getting the data of the response in a type-safe and user-friendly manner. Internally, the request/response classes deal with encoding and decoding BER values.

Examples of extension classes are the StartTlsRequest and StartTlsResponse classes. See the next section for a detailed description of this extension and sample code that uses these classes.

 

 

Extensions Supported by LDAP Servers

Support for specific extensions is LDAP server-dependent. Eventually, when extensions are standardized, a set of popular extensions supported by most LDAP servers might be available. However, proprietary and vendor-specific extensions might still be around.

Here is a simple program for finding out the list of extensions that an LDAP server supports.

// Create the initial context
DirContext ctx = new InitialDirContext();

// Read supportedextension from the root DSE
Attributes attrs = ctx.getAttributes(
    "ldap://localhost:389", new String[]{"supportedextension"});
Here is the output produced by running this program against an LDAP server.
{supportedextension=supportedextension: 
  1.3.6.1.4.1.1466.20037
}

 

 

Implementations

You typically will deal with implementation classes that implement ExtendedRequest and ExtendedResponse rather than directly use their methods. Such implementation classes typically have type-friendly constructors and accessor methods.

For example, suppose that an LDAP server supports a Get Time "extended" operation. It would supply classes such as GetTimeRequest and GetTimeResponse, so that applications can use this feature. An application would use these classes as follows.

// Invoke the "extended" operation
GetTimeResponse resp =
    (GetTimeResponse) lctx.extendedOperation(new GetTimeRequest());

// Get the "extended" operation's (decoded) response
long time = resp.getTime();

The GetTimeRequest and GetTimeResponse classes might be defined as follows.

public class GetTimeRequest implements ExtendedRequest {
    // User-friendly constructor 
    public GetTimeRequest() {
    };

    // Methods used by service providers
    public String getID() {
        return GETTIME_REQ_OID;
    }
    public byte[] getEncodedValue() {
        return null;  // No value is needed for the Get Time request
    }
    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;
    // Called by GetTimeRequest.createExtendedResponse()
    GetTimeResponse(String id, byte[] berValue, int offset, int length) 
        throws NamingException {
        // Check the validity of the id
        long time =  ... // Decode berValue to get the time
    }

    // These are type-safe and user-friendly methods
    public java.util.Date getDate() { return new java.util.Date(time); }
    public long getTime() { return time; }

    // These are low-level methods
    public byte[] getEncodedValue() {
        return // berValue saved;
    }
    public String getID() {
        return GETTIME_RESP_OID;
    }
}