Sistema de Nombrado en Java (JNDI) y II

Los procedimientos descritos hasta ahora funcionan bien cuando todas las implementaciones de contexto implicadas en completar un m�todo a trav�s de una federaci�n implementan los mismos interfaces. �Qu� sucede si alg�na implementaci�n de contexto intermedio no soporta todos los subinterfaces de Context? No queremos requerir que un sistema de nombres intermedio soporte todos los subinterfaces para que funcione la federaci�n. Este problema es m�s importante con los subinterfaces no est�ndars porque esperar un amplio soporte para ellos no es razonable.

Supongamos que llamamos a un m�todo del interface DirContext sobre una federaci�n que consta de cinco sistema de nombres, s�lo el primero y el �ltimo soportan DirContext.

Para que el m�todo sea invocado con �xito sobre el contexto objetivo, los sistemas de nombres intermedios deben implicarse en la fase de resoluci�n de la operaci�n y poder indicar qu� operaci�n se llam� �ltimamente. A primera vista, conseguir el paso de resoluci�n usando lookup() podr�a parecer posible. Esto es problem�tico porque queremos el context objetivo y no el objeto nombrado. Por ejemplo, si est�mos creando un subcontexto, queremos el pen�ltimo contexto nombrado por el nombre de entrada y no el objeto nombrado.

JNDI soporta la resoluci�n a trav�s de contextos intermedios mediante una implementaci�n de contexto intermedio que soporte el interface Resolver. Este interface contiene dos formas sobrecargadas de resolveToClass(); una que acepta un nombre string y una Class y otra que acepta un Name. El JNDI usa resolveToClass() para resolver parcialmente el nombre de entrada, parando en el primer contexto que sea un ejemplar de la clase/interface especificada. Una implementaci�n de contexto necesita implementar el interface Resolver y proporcionar implementaciones para este m�todo.

Aq�� tenemos una implementaci�n de ejemplo:

public ResolveResult resolveToClass(Name name, Class ctxType) 
    throws NamingException {

    // If you're it, you quit right now
    if (ctxType.isInstance(this)) {
	return new ResolveResult(this, name);
    }

    try {
	Name[] nm = parseComponents(name);
	Name mine = nm[0];
	Name rest = nm[1];
	Object nxt = null;

	if (rest == null || rest.isEmpty()) {
	    // Terminal; just use head
	    nxt = lookup_internal(mine);
	} else if (rest.get(0).equals("") && rest.size() == 1) {
	    // Terminal nns
	    nxt = lookup_nns(mine);
	} else if (mine.isEmpty() || isAllEmpty(rest)) {
	    // Intermediate; resolve current components as intermediate
	    Object obj = lookup_nns(mine);

	    // Skip leading forward slash
	    throw fillInCPE(obj, mine, rest.getSuffix(1));
	} else {
	    // Intermediate; resolve current components as intermediate
	    Object obj = resolveIntermediate_nns(mine, rest);

	    throw fillInCPE(obj, mine, rest);
	}

	if (ctxType.isInstance(nxt)) {
	    return new ResolveResult(nxt, "");
	} else {
	    // Have resolved the entire composite name but
	    // cannot find the requested context type
	    throw new NotContextException(
		"Not instanceof " + ctxType);
	}
    } catch (CannotProceedException e) {
	Context cctx = NamingManager.getContinuationContext(e);
	if (cctx instanceof Resolver) {
	    return cctx.resolveToClass(e.getRemainingName(), ctxType);
	} else {
	    // Have hit a nonResolver; give up
	    e.fillInStackTrace();
	    throw e;
        }
    }
}

En este m�todo, primero comprobamos si el contexto actual implementa el tipo requerido. Si es as�, no vamos m�s all�. De otra forma, procedemos con otras operaciones de contexto descritas en una secci�n anterior de esta lecci�n. Es decir, determinamos si el contexto actual es terminal, terminal nns, o contexto intermedio. Para los dos casos terminales, si la respuesta es un ejemplar del tipo requerido, devolvemos la respuesta y un resto de nombre vac�o en una ResolveResult. Si obtenemos una CannotProceedException, la usamos para encontrar un contexto de continuaci�n. Este contexto debe implementar el interface Resolver. De otra forma, no podemos usarlo para encontrar el contexto objetivo.

.�Contextos de Continuaci�n para Subinterfaces

Los siguientes m�todos JNDI usan resolveToClass() para resolver el contexto de continuaci�n del tipo apropiado:

Si nuestra implementaci�n de contexto soporta otro subinterface, deber�a definir un m�todo similar para ese subinterface. Por ejemplo, supongamos que necesitamos soportar el subinterface BarContext. Deber�amos definir un m�todo llamado getContinuationBarContext(). Aqu� tenemos un ejemplo.

public BarContext getContinuationBarContext(CannotProceedException cpe) {
    return new ContinuationBarCtx(cpe);
}

Entonces definimos una implementaci�n para el contexto de continuaci�n ContinuationBarCtx . Esta clase debe implementar tanto los subinterfaces Resolver y BarContext. Se han definido los siguientes m�todos de utilidad para obtener el contexto objetivo para los m�todos Context y BarContext:

// Gets the default target context, and caches it
protected Context getTargetContext() throws NamingException {
    if (cctx == null) {
	cctx = NamingManager.getContinuationContext(cpe);
    }
    return cctx;
}

protected ResolveResult getTargetContext(Name name)
    throws NamingException {

    Context ctx = getTargetContext();

    if (ctx instanceof BarContext)
	return new ResolveResult(ctx, name);

    // Have found the resolver; ask it to find BarContext
    if (ctx instanceof Resolver) {
	Resolver res = (Resolver)ctx;
	return res.resolveToClass(name, BarContext.class);
    }

    // Resolve all of the way by using lookup()
    // This may allow the operation
    // to succeed if it doesn't require the penultimate context
    Object ultimate = ctx.lookup(name);
    if (ultimate instanceof BarContext) {
	return (new ResultResult(ultimate, new CompositeName()));
    }

    throw (NamingException)cpe.fillInStackTrace();
}

Los m�todos BarContext pueden implementarse de esta forma en el contexto de continuaci�n:

public void BarMethod(Name name) throws NamingException {
    ResolveResult res = getTargetContext(name);
    return ((BarContext)res.getResolvedObj()).barMethod(res.getRemainingName());
}

El m�todo usa el BarContext resuelto y el nombre restante para continuar la operaci�n.

Todos los m�todos de Context se han implementado usando un m�todo getTargetContext() que no acepta argumentos. Estas implementaciones existen para satisfacer el interface Context. Normalmente, la implementaci�n de contexto usar�a NamingManager.getContinuationContext() directamente en lugar del contexto de continuaci�n del subinterface para los m�todos del interface Context, como se mostr� en la p�gina anterior.

Aqu� tenemos una implementaci�n de ejemplo de lookup() en el contexto de continuaci�n:

public Object lookup(Name name) throws NamingException {
    Context ctx = getTargetContext();
    return ctx.lookup(name);
}

Una implementaci�n de contexto que implemente el subinterface usar�a getContinuationBarContext() de la misma forma que usa NamingManager.getContinuationContext(). Aqu� tenemos un ejemplo:

public Object barMethod(Name name) throws NamingException {
   try {
       ...
    } catch (CannotProceedException e) {
  	BarContext cctx = ContinuationBarCtx.getContinuationBarContext(e);
	return cctx.barMethod(e.getRemainingName());
    }
}

COMPARTE ESTE ARTÍCULO

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