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());
}
}