Sistema de Nombrado en Java (JNDI) y II

Una implementaci�n de contexto URL es un contexto que maneja strings URL arbitrarios del esquema URL soportado por el contexto. Es una clase que implementa el interface Context o uno de sus subinterfaces. Se diferencia de la implementaci�n de contexto (plano) descrita en la lecci�n Los Componentes Esenciales en la forma en que sus m�todos aceptan y procesan el argumento nombre

.�Nombres Estructurados contra Nomres String

La lecci�n Las Reglas de Fondo sugiere que implementemos los m�todos de contexto que aceptan strings en t�rminos de sus contrapartes Name porque los nombres string deber�an ser tratados como nombres mixtos (JNDI). Esta regla no se aplica a las implementaciones de contexto URL, porque un string URL no es un nombre mixto JNDI. Un string URL deber�a procesarse de acuerdo a la s�ntaxis definida en su esquema de URL. De hecho, la dependencia tambi�n es a la inversa. es decir, las sobrecargas que aceptan Name tambi�n deber�an ser implementadas en t�rminos de sus contrapartes strings.

Si no queremos soportar federaciones, podemos s�lo lanzar una InvalidNameException cuando se presente un Name multi-componente:

public void bind(Name name, Object obj) throws NamingException {
    if (name.size() == 1) {
        bind(name.get(0), obj);
    } else {
        throw new InvalidNameException(
	    "Cannot have composite names with URLs");
    }
}

Si soportamos federaciones, entonces cuando se presente con un CompositeName cuyo primer componente sea un string URL v�lido, deber�amos tratar el primer componente como una URL y luego el resto de los componentes de la federaci�n (es decir, resolver la URL nos dir� qu� sistema de nombres utilizar para resolver la parte restante). Si se presenta con un Name que no es un CompositeName, deber�amos tratar esto como un caso de error y lanzar una InvalidNameException. Esto es as� porque una URL embebida dentro de un nombre compuesto no tiene sentido.

Este ejemplo no comprueba si la entrada es un CompositeName. Aqu� est� la definici�n de bind() del ejemplo:

public void bind(Name name, Object obj) throws NamingException {
    if (name.size() == 1) {
        bind(name.get(0), obj);
    } else {
	Context ctx = getContinuationContext(name);
	try {
	    ctx.bind(name.getSuffix(1), obj);
	} finally {
	    ctx.close();
        }
    }
}

Todas las sobrecargas que aceptan un Name usan un patr�n similar. Si el nombre contiene un �nico componente, extrae el primer componente y lo pasa a la sobrecarga que acepta un nombre string. Esto se parece al llamador usando la sobrecarga que acepta nombres string en la primera posici�n. De otra forma, usa el m�todo de utilidad getContinuationContext() para resolver el primer componente (es decir, el string URL) y contin�a la operaci�n en ese contexto. Aqu� est� la definici�n de getContinuationContext():

protected Context getContinuationContext(Name n) throws NamingException {
    Object obj = lookup(n.get(0));
    CannotProceedException cpe = new CannotProceedException();
    cpe.setResolvedObj(obj);
    cpe.setEnvironment(myEnv);
    return NamingManager.getContinuationContext(cpe);
}

Este m�todo de utilidad resuelve el primer componente del nombre y usa el resultado como el "objeto resuelto" en una llamada a NamingManager.getContinuationContext() para obtener el contexto fuente en el que continuar la operaci�n sobre el resto del nombre.

.�El Contexto Ra�z URL

Observa que hemos tenido cuidado de las sobrecargas que aceptan Name, podemos cambiar nuestra atenci�n a las sobrecargas que aceptan java.lang.String. Las implementaciones de estos m�todos dependen en gran medida de su contraparte en la implementaci�n de contexto "no-URL". Por ejemplo, una implementaci�n de contexto URL para la URL LDAP es altamente dependiente de la implementaci�n de contexto para el servicio LDAP. Una b�squeda de una URL LDAP en un contexto LDAP URL normalmente resulta en una b�squeda en un contexto LDAP (de la implementaci�n de contexto LDAP) usando un DN LDAP. En este escenario, la implementaci�n de contexto URL realmente s�lo es una imagen de la implementaci�n de contexto real del servicio. A causa de esta relaci�n cerrada, este ejemplo podr�a no aplicarse tan bien en algunas implementaciones reales.

El ejemplo usa la noci�n de un contexto raiz que se deriva de la string URL de entrada. Define un m�todo de utilidad, getRootURLContext(), que acepta un string URL. Este m�todo devuelve un paquete que consta de un contexto que est� derivado de la informaci�n de la URL y el resto del nombre de la URL para ser resuelto en relaci�n al contexto ra�z. Por ejemplo, en el ejemplo LDAP, supongamos que el string URL de entrada es "ldap://favserver:289/o=jnditutorial". El contexto ra�z podr�a ser el contexto de la ra�z del servidor LDAP en la m�quina favserver y el puerto 289. En este caso, la porci�n "ldap://favserver:289/" del string URL ser� consumida en la producci�n del contexto ra�z y el resto del nombre ser� "o=jnditutorial".

En nuestro ejemplo de URL foo, el contexto ra�z apunta a la ra�z del espacio de nombres est�tico HierCtx, y "foo:/" es consumido para producir el contexto ra�z. El resto del nombre est� representado como un s�lo componente CompositeName:

protected ResolveResult getRootURLContext(String url, Hashtable env) 
    throws NamingException {
    if (!url.startsWith("foo:/")) {
	throw new IllegalArgumentException(url + " is not a foo URL");
    }

    String objName = url.length() > 5 ? url.substring(5) : null;

    // Represent the object name as empty or a single-component composite name.
    CompositeName remaining = new CompositeName();
    if (objName != null) {
	remaining.add(objName);
    }

    // Get the handle to the static namespace to use for testing
    // In an actual implementation, this might be the root
    // namespace on a particular server
    Context ctx = tut.HierCtx.getStaticNamespace(env);

    return (new ResolveResult(ctx, remaining));
}

Las sobrecargas que aceptan nombres string usan este m�todo de utilidad para procesar el string URL y completar la operaci�n. Aqu� tenemos la definici�n de bind() para el ejemplo:

public void bind(String name, Object obj) throws NamingException {
    ResolveResult res = getRootURLContext(name, myEnv);
    Context ctx = (Context)res.getResolvedObj();
    try {
        ctx.bind(res.getRemainingName(), obj);
    } finally {
        ctx.close();
    }
}

Observa que antes de que el m�todo retorne, cierra el contexto ra�z. En este ejemplo, este paso no es realmente necesario porque fooURLContext no mantiene ninguna conexi�n ni recurso. Sin embargo, es una buena pr�ctica para asegurarse de que las implementaciones que mantienen conexiones o recursos las liberan apropiadamente. Esto tambi�n significa que los m�todos con estado como list() deben asegurarse de que la enumeraci�n resultante que devuelven permanezca utilizable despu�s de que se haya cerrado el contexto.

.�Consideraciones Espaciales para rename()

rename() es diferente de otros m�todos de contexto en que acepta dos nombres en lugar de uno. Con un nombre, podemos usar getRootURLContext() para obtener un contexto trabajable para terminar la operaci�n. Con dos nombres, no podemos llamar a getRootURLContext() dos veces, una por cada nombre, porque cada llamada podr�a devolver un contexto diferente. rename() s�lo puede tener un contexto en el que hacer el resto.

Para resolver esto en nuestro ejemplo, primero extraemos de ambos nombres un prefijo com�n (usando la utilidad interna getURLPrefix()). Luego usamos getRootURLContext() para obtener el contexto ra�z y el resto del nombre del nombre original. Para obtener el resto del nombre del nuevo nombre, usamos otra utilidad interna getURLSuffix(). Observa que es muy importante que los tres metodos --getRootURLContext(), getURLPrefix(), y getURLSuffix()-- est�n completamente de acuerdo en c�mo se analiza un string URL y que partes se designan como prefijo y sufijo.

En particular, getRootURLContext() deber�a consumir la porci�n devuelta por getURLPrefix() para crear el contexto ra�z y devolver el como el resto del nombre la porci�n que devolver� getURLSuffix(). Tambi�n deber�amos tener en cuenta las restricciones sobre la habilidad de una implementaci�n de contexto para realizar renombrados a trav�s de diferentes servidores o espacios de nombre.

Aqu� tenemos un ejemplo de rename():

public void rename(String oldName, String newName) 
    throws NamingException {
    String oldPrefix = getURLPrefix(oldName);
    String newPrefix = getURLPrefix(newName);
    if (!urlEquals(oldPrefix, newPrefix)) {
	throw new OperationNotSupportedException(
	    "Renaming using different URL prefixes not supported : " +
		oldName + " " + newName);
    }

    ResolveResult res = getRootURLContext(oldName, myEnv);
    Context ctx = (Context)res.getResolvedObj();
    try {
        ctx.rename(res.getRemainingName(), 
	    getURLSuffix(newPrefix, newName));
    } finally {
	ctx.close();
    }
}

Aqu� est�n las implementaciones de getURLPrefix() y getURLSuffix():

protected String getURLPrefix(String url) throws NamingException {
    int start = url.indexOf(":");

    if (start < 0) {
        throw new OperationNotSupportedException("Invalid URL: " + url);
    }
    ++start; // Skip ":"

    if (url.startsWith("//", start)) {
	start += 2;  // Skip the double forward slash
	    
	// Find the last forward slash
	int posn = url.indexOf("/", start);
	if (posn >= 0) {
	    start = posn;
	} else {
	    start = url.length();  // Rest of the URL
	}
    }

    // Else 0 or 1 initial slashes; the start is unchanged
    return url.substring(0, start);
}

protected Name getURLSuffix(String prefix, String url) 
    throws NamingException {
    String suffix = url.substring(prefix.length());
    if (suffix.length() == 0) {
        return new CompositeName();
    }

    if (suffix.charAt(0) == '/') {
	suffix = suffix.substring(1); // Skip the leading forward slash
    }

    // Note: This is a simplified implementation;
    // a real implementation should
    // transform any URL-encoded characters into their Unicode char
    // representations
    return new CompositeName().add(suffix);
}

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR