| Controls and Extensions

## Response Controls

> A response control allows a server to send more information to the client than is allowed by the operation's response. A one-to-one mapping between request controls and response controls is not needed. That is, a server can send response controls along with any response--they need not be in response to any client-initiated request control.

> Because an LDAP server might send response controls with any response, you might be able to collect response controls after any `Context` method invocation. However, realistically, you would check for response controls only if you were expecting them.

> `LdapContext.getResponseControls()` is used to retrieve a context's response controls. Each time that a method that communicates with the server is invoked on a context, the LDAP service provider clears any previously collected response controls and then collects all response controls resulting from the current method invocation.

> For example, the following code fragment examines the response controls after a `Context.lookup()` call.

> >     // Perform lookup
> >     Object answer = ctx.lookup("ou=People");

> >     // Retrieve the response controls
> >     Control[] respCtls = ctx.getResponseControls();

> If you invoke two context methods and then use `getResponseControls()`, you will get only the response controls generated by the most recent context method.

> #### Enumerations

> Methods such as `Context.list()` and `DirContext.search()` return a `NamingEnumeration`. Each member of a `NamingEnumeration` might have response controls. One that does will implement the `HasControls` interface.

> Here is an example that shows you how to retrieve the response controls from each member of a `NamingEnumeration` that is generated by a `search()`.

> >     // Perform the search
> >     NamingEnumeration answer = ctx.search("ou=People", "(cn=*)", null);

> >     // Examine the response controls (if any)
> >     printControls("After search", ctx.getResponseControls());

> >     // Enumerate the answers
> >     while (answer.hasMore()) {
> >         SearchResult si = (SearchResult)answer.next();
> >         System.out.println(si);

> >         // Examine the response controls (if any)
> >         if (si instanceof HasControls) {
> >             printControls(si.getName(), ((HasControls)si).getControls());
> >         }
> >     }

> >     // Examine the response controls (if any)
> >     printControls("After enumeration", ctx.getResponseControls());

> This example performs a search, examines the response controls after the search, and then enumerates the search results. Next, it checks whether any member of the enumeration implements the `HasControls` interface and, for any that do, displays the response controls associated with the member. After the enumeration completes, it checks for context response controls by using `ctx.getResponseControls()`. This example defines a utility method, `printControls()`, that prints out a `Control` array.

> #### Exceptions

> If a context method throws an exception and the LDAP server had sent response controls with the error response that generated the exception, then you can retrieve the response controls by using `ctx.getResponseControls()`. Here is an example.

> >     try {
> >         // Perform the lookup
> >         Object answer = ctx.lookup("ou=People");

> >         // Retrieve the response controls
> >         Control[] respCtls = ctx.getResponseControls();

> >         // Display respCtls
> >     } catch (NamingException e) {
> >         // Retrieve the response controls
> >         Control[] respCtls = ctx.getResponseControls();

> >         // Handle the exception
> >     }

> #### Implementations

> The `Control` interface is generic for all request and response controls. Typically, you will deal with implementation classes that implement this interface rather than directly use the methods in this interface. Such implementation classes typically have type-friendly and accessor methods. After getting the response controls by using `getResponseControls()`, you can cast the control to its most derived class and use the class-specific accessor methods.

> For example, Sun provides classes that implement some popular controls, such as the server-side Sort control. The server-side Sort response control is represented by the `SortResponseControl` class. You can use the following code to access information about the server-side Sort response control.

> >     if (controls[i] instanceof SortResponseControl) {
> >         SortResponseControl src = (SortResponseControl)controls[i];

> >         if (src.isSorted()) {
> >     	// Result was sorted ...
> >         }
> >     }
> >     ...

> To do this casting and use specific control classes, you must have some expectation of receiving such a control from the server and must have made the control classes available to your program. If either of these is lacking, then you can use only the methods in the `Control` interface to determine the identity of the control and to decode its contents.

> #### Response Control Factories

> The JNDI allows an application to use control implementation classes that are produced by any vendor. To help service providers achieve this goal, the JNDI provides the method `ControlFactory.getControlInstance(Control, Context, Hashtable)` for service providers to use to transform (that is, to narrow) generic controls received from an LDAP server into control classes that are made available to the application.

> To narrow a control, you use a control factory, which is represented by the abstract class `ControlFactory`. A control received from an LDAP server begins life as a `Control` instance. The LDAP service provider uses `getControlInstance()` to narrow the control instance into a more type-specific one. This method searches the list of `ControlFactory` class implementations specified in the `LdapContext.CONTROL_FACTORIES` (`"java.naming.factory.control"`) environment property for a class that can narrow the control.

> For example, if an application uses an LDAP server that returns a special response control, then the application can define a response control factory to parse the control and to provide type-friendly accessor methods. Here is an example of a response control factory.

> >     public  class SampleResponseControlFactory extends ControlFactory {
> >         public SampleResponseControlFactory() {
> >         }

> >         public Control getControlInstance(Control ctl) throws NamingException {
> >     	String id = ctl.getID();

> >     	// See if it's one of yours
> >     	if (id.equals(SampleResponseControl.OID)) {
> >     	    return new SampleResponseControl(id, ctl.isCritical(),
> >     		ctl.getEncodedValue());
> >     	}

> >     	// It's not one of yours, so return null and
> >     	// let someone else try
> >     	return null;
> >         }
> >     }

> The factory class must have a public constructor that accepts no arguments. It also must provide an implementation for the abstract method `ControlFactory.getControlInstance(Control)` . This method should check whether the input control is one that it can narrow. If it is, then the method should process the control and return an object of a more type-specific class. If it is not, then it should return `null` so that other factories may be tried.

| Controls and Extensions