Un control de respuesta permite al servidor enviar m�s informaci�n al cliente de la permitida por la respuesta de la operaci�n. No es necesario un mapeo de uno-a-uno entre los controles de petici�n y los controles de respuesta. Es decir, un servidor puede enviar controles de respuesta junto con cualquier respuesta--no necesita ser una respuesta a ning�n control de petici�n iniciado por el cliente.
Como un servidor LDAP podr�a enviar controles de respuesta con cualquier respuesta, podr�amos recoger controles de respuesta despu�s de cualquier llamada a m�todos de Context. Sin embargo, real�sticamente, chequeriamos los controles de respuesta s�lo si los esperaramos.
Se usa LdapContext.getResponseControls() para recuperar un control de respuesta de contexto. Cada vez que un m�todo que se comunica con el servidor se llama sobre un contexto, el proveedor de servicio LDAP elimina cualquier control de respuesta anterior y luego recoge los controles de respuesta resultantes de la llamada del m�todo actual.
Por ejemplo, el siguiente fragmento de c�digo exmina los controles de respuesta despu�s de una llamada a Context.lookup():
// Perform lookup
Object answer = ctx.lookup("ou=People");
// Retrieve the response controls
Control[] respCtls = ctx.getResponseControls();
Si llamamos a dos m�todos de contexto y luego usamos getResponseControls(), s�lo obtendremos los controles de respuesta generados por el m�todo de contexto m�s reciente.
�Enumeraciones
Los m�todos como Context.list() y DirContext.search() devuelven una NamingEnumeration. Cada miembro de una NamingEnumeration podr�a tener controles de respuesta. Uno que implemente el interface HasControls.
Aqu� tenemos un ejemplo que muestra c�mo recuperar los controles de respuesta de cada miembro de una NamingEnumeration que es generada por un m�todo 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());
Este ejemplo realiza una b�squeda, examina los controles de respuesta y luego enumera los resultados de la b�squeda. Luego, chequea si alg�n miembro de la enumeraci�n implementa el interface HasControls y, para cualquiera que lo haga, muestra los controles de respuesta asociados con el miembro. Despu�s de completar la enumeraci�n, busca controles de respuesta de contexto usando ctx.getResponseControls(). Este ejemplo define un m�todo de utilidad, printControls(), que imprime un array de Control.
�Excepciones
Si un m�todo de contexto lanza una excepci�n y el servidor LDAP ha enviado controles de respuesta con la respuesta de error que gener� la excepci�n, podremos recuperar los controles de respuesta usando ctx.getResponseControls(). Aqu� hay un ejemplo:
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
}
�Implementaciones
El interface Control es gen�rico para todos los controles de petici�n y de respuesta. Normalmente trataremos con clases de implementaci�n que implementan este interfae en vez de usar directamente sus m�todos. Dichas clases de implementaci�n normalmente tienen tipos amigables y m�todos accesores. Despu�s de obtener el control de respuesta usando getResponseControls(), podemos forzar el control a su clase m�s pr�xima y usar los m�todos accesores espec�ficos de la clase.
Por ejemplo, Sun proporciona clases que implementan algunos controles populares, como el control Sort. Este control de ordenaci�n en el lado del servidor est� representado por la clase SortResponseControl. Podemos usar el siguiente c�digo para acceder a la informaci�n sobre este control:
if (controls[i] instanceof SortResponseControl) {
SortResponseControl src = (SortResponseControl)controls[i];
if (src.isSorted()) {
// Result was sorted ...
}
}
...
Para hacer este forzado y usar clases de control espec�ficas, debemos tener algunas espectativas de recibir dicho control desde el servidor y debemos tener las clases disponibles para nuestro programa. Si no hacemos ninguna de estas dos cosas, s�lo podremos usar los m�todos del interface Control para determinar la identidad del control y decodificar su contenido.
�Factor�as de Controles de Respuesta
El JNDI permite a una aplicaci�n usar clases de implementaci�n de controles que son producidas por cualquier vendedor. Para ayudar al proveedor de servicio a alcanzar este objetivo, el JNDI proporciona el m�todo ControlFactory.getControlInstance(Control, Context, Hashtable) para que el proveedor de servicio lo use para transformar (es decir, dirigir) controles gen�ricos recibidos desde un servidor LDAP en clases de control que est�n disponibles para la aplicaci�n.
Para dirigir un control usamos una factor�a de controles, que est� representada por la clase abstracta ControlFactory. Un control recibido desde un servidor LDAP empieza su vida como un ejemplar de Control. El proveedor de servicio LDAP usa getControlInstance() para dirigir el ejemplar de control dentro de uno de tipo m�s espec�fico. Este m�todo busca la lista de clases de implementaciones de ControlFactory especificadas en la propiedad de entorno LdapContext.CONTROL_FACTORIES ("java.naming.factory.control") una clase a la que pueda dirigir el control.
Por ejemplo, si una aplicaci�n usa un servidor LDAP que devuelve un control de respuesta especial, entonces la aplicaci�n puede definir una factor�a de controles de respuesta para analizar el control y proporcionar m�todos accesores de tipo amigable. Aqu� tenemos un ejemplo de una factor�a de controles de respuesta:
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;
}
}
La clase factor�a debe tener un constructor p�blico que no acepte argumentos. Tambi�n debe proporcionar una implementaci�n del m�todo abstracto ControlFactory.getControlInstance(Control). Este m�todo deber�a chequear si el control de entrada es uno que se puede dirigir. Si es as�, el m�todo deber�a procesar el control y devolver un objeto de una clase m�s espec�fica. Si no es as�, el m�todo deber�a devolver null para que pudieran intentarlo otras factor�as.