Programación en castellano Añadir una dirección | Buscador | Cursos | Artículos | Foros | Formación

Sistema de Nombrado en Java (JNDI) y II
Autor: Sun
Traductor: Juan Antonio Palos (Ozito)


En esta página:


Resolver a través de Interfaces

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

Principio Página
© 1999-2002, Programación en castellano, s.l.
Contacto - Datos legales

ReD Internet: Hospedaje Web | envio sms gratis | Salvapantallas | Fondos de Escritorio, famosas | melodias moviles gratis| Gratis