Sistema de Nombrado en Java (JNDI) y II

Despu�s de extraer los componentes del nombre que pertenecen a nuestro sistema de nombres actual, debemos decidir c�mo procesarlos. Tenemos tres opciones:

  • Terminal. La resoluci�n de nombres ha alcanzado el sistema de nombres objetivo. Se aplica la operaci�n al nombre.
  • Terminal sistema de nombres siguiente (terminal nns). La resoluci�n de nombres ha alcanzado el sistema de nombres objetivo. Se aplica la operaci�n al puntero nns (puntero de sistema de nombres siguiente) del nombre.
  • Intermedio. El sistema de nombres actual es un sistema de nombres intermedio. Hacer la resoluci�n de nombres necesaria para determinar el nns al que pasar la operaci�n.

Aqu� tenemos un ejemplo de implementaci�n de bind() que implementa estas tres opciones:

public void bind(Name name, Object bindObj) throws NamingException {
    try {
	Name[] nm = parseComponents(name);
	Name mine = nm[0];
	Name rest = nm[1];

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

	    // Skip the 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);
	}
    } catch (CannotProceedException e) {
	Context cctx = NamingManager.getContinuationContext(e);
	cctx.bind(e.getRemainingName(), bindObj);
    }
}

Este ejemplo y las tres alternativas se explican en m�s detalle en esta leci�n. Observa que no todos los m�todos relacionados con los nombres del interface Context deben implementarse de forma similar.

.�Terminal

Una vez que la resoluci�n de nombres ha alcanzado el sistema de nombres objetivo, basicamente no necesitamos preocuparnos por la federaci�n. En el ejemplo, este caso se maneja definiendo un m�todo xxx_internal para cada m�todo de Context. Esta t�cnica es �til para delinear claramente la porci�n de c�digo que es local o interna a esta implementaci�n de contexto:

Aqu� tenemos un ejemplo para bind():

private void bind_internal(Name name, Object obj) throws NamingException {
    if (name.isEmpty()) {
        throw new InvalidNameException("Cannot bind empty name");
    }

    // Extract the components that belong to this namespace
    String atom = getInternalName(name);
    if (bindings.get(atom) != null) {
	throw new NameAlreadyBoundException("Use rebind to override");
    }

    // Call getStateToBind for using any state factories
    obj = NamingManager.getStateToBind(obj, name, this, myEnv);

    // Add the object to the internal data structure
    bindings.put(atom, obj);
}

Si la implementaci�n de contexto soporta separaci�n d�bil din�mica (es decir, determina din�micamente los l�mites del sistema de nombres), entonces los m�todos xxx_internal() resolver�n el nombre para determinar qu� partes pertenecen al sistema de nombres actual. Si se determina que el sistema de nombres actual no es el terminal, los m�todos lanzar�n una CannotProceedException, con los componentes restantes como el nombre restante.

.�Siguiente Sistema de Nombres Terminal

Cuando la resoluci�n del nombre ha alcanzado el sistema de nombres objetivo con un resto de nombre que tiene un caracter de barra inclinada ("/"), la operaci�n debe aplicarse al puntero nns del nombre restante. Recuerda de la lecci�n Federaci�n que la implementaci�n de contexto podr�a implementar el puntero nns como expl�cita (tambien llamado junction (empalme)) o impl�cita. En el ejemplo, este caso se maneja definiendo un m�todo xxx_nns para cada uno de los m�todos del interface Context. Como en el caso de la t�cnica de nombrado xxx_internal, este t�cnica es �til para delinear la parte del c�digo que maneja punteros nns.

La implementaci�n de los m�todos xxx_nns depende de c�mo la implementaci�n de contexto maneja los punteros nns. Por ejemplo, una implementaci�n de contexto podr�a soportar impl�citamente nns teniendo una tabla que registra los nns de cada nombre unido en el contexto. En este caso su m�todo bind_nns() se podr�a parecer esto:

private void bind_nns(Name name, Object obj) throws NamingException {
    if (name.isEmpty()) {
	// Set your nns
	myNNS = NamingManager.getStateToBind(obj, 
	((Name)(name.clone())).add(""), this, myEnv);
	return;
    }
    // Extract the components that belong to this namespace
    String atom = getInternalName(name);
    if (nnsBindings.get(atom) != null) {
	throw new NameAlreadyBoundException("Use rebind to override");
    }

    // Call getStateToBind for using any state factories
    obj = NamingManager.getStateToBind(obj, 
	((Name)(name.clone())).add(""), this, myEnv);

    // Add the object to the internal nns data structure
    nnsBindings.put(atom, obj);
}

Si la implementaci�n de contexto soporta "empalmes", deber�a buscar el "empalme" y aplicar la operaci�n al nns del empalme. Esto se ilustra en el ejemplo. Como esto es un patr�n com�n usado por otros m�todos de contexto como una utilidad interna, se ha definido processJunction_nns() para este prop�sito de esta forma:

protected void processJunction_nns(Name name) throws NamingException {
    if (name.isEmpty()) {
	// Construct a new Reference that contains this context
	RefAddr addr = new RefAddr("nns") {
	    public Object getContent() {
		return FedCtx.this;
	    }
	};
	Reference ref = new Reference("java.lang.Object", addr);

	throw fillInCPE(ref, NNS_NAME, null);
    } else {
        // Look up the name to continue the operation in the nns
	Object target;
	try {
	    target = lookup_internal(name);
	} catch (NamingException e) {
	    e.appendRemainingComponent(""); // Add the nns back in
	    throw e;
	}

	throw fillInCPE(target, name, NNS_NAME);
    }
}

Si el nombre est� vac�o, entonces se le pide al usuario el nns del contexto actual. En este caso, se contruye una referencia nns (ver la lecci�n Federaci�n) usando el contexto actual como el objeto resuelto y el caracter de barra inclinada ("/") como el nombre "alt". El nombre "alt" es el nombre del objeto resuelto, resuelto en relaci�n al nombre de contexto "alt" (que en este caso es el contexto actual). Esta informaci�n se usa para crear y lanzar una CannotProceedException. Si el nombre no est� vac�o, necesitamos buscar el objeto nombrado desde el contexto actual y crear una CannotProceedException que contenga la barra inclinada como el resto del nombre. La CannotProceedException es manejada por el m�todo bind() principal, como se explica en la siguiente secci�n. bind_nns(), como otros m�todos para menejar el nns, simplemente usa la utilidad interna processJunction_nns().

private void bind_nns(Name name, Object obj) throws NamingException {
    processJunction_nns(name);
}

fillInCPE() es una utilidad interna que crea una CannotProceedException usando este contexto como el nombre de contexto "alt" y el entorno de este contexto. Aqu� est� su definici�n:

protected CannotProceedException fillInCPE(Object resolvedObj, 
	Name altName, Name remainingName) {
    CannotProceedException cpe = new CannotProceedException();

    // Generic stuff
    cpe.setEnvironment(myEnv);
    cpe.setAltNameCtx(this);

    // Specific stuff
    cpe.setResolvedObj(resolvedObj);
    cpe.setAltName(altName);
    cpe.setRemainingName(remainingName);
    return cpe;
}

.�Intermedio

Si el m�todo de utilidad parseComponents() devuelve un resultado que indica que la resoluci�n est� actualmente en un contexto intermedio, deber�amos resolver los componentes del nombre premeditado para el sistema de nombres actual para obtener una referencia al nns. C�mo ocurre la resoluci�n, depende de si se ha solicitado el nns impl�cito. El nns impl�cito ha sido solicitado si el nombre contiene una barra inclinada ("/") inicial o si los componentes del nombre que pertenecen al nns (rest) est�n todos vac�os (esto es indicado por una o m�s barras inclinadas al final). En este caso, la implementaci�n de contexto deber�a usar la utilidad itnerna lookup_nns() para obtener el nns y continuar la operaci�n sobre el resto de los componentes del nombre.

Si no se ha solicitado el nns impl�cito, entonces los componentes del nombre que pertenecen a este sistema de nombres actual (mine) podr�an tener un "empalme" o un nns impl�cito. Para procesar este caso, se ha definido una utilidad que puede ser usada por todos los m�todos de contexto llamada resolveIntermediate_nns():

protected Object resolveIntermediate_nns(Name name, Name rest, 
    Name newName)
    throws NamingException {
    CannotProceedException cpe;
    try {
	final Object obj = lookup_internal(name);

	if (obj != null && getClass().isInstance(obj)) {
	    // If "obj" is in the same type as this object, it must
	    // not be a junction; continue the lookup with "/"

	    cpe = fillInCPE(obj, name,
		((Name)(NNS_NAME.clone())).addAll(rest));
	    cpe.setRemainingNewName(newName);
	} else if (obj != null && !(obj instanceof Context)) {
	    // obj is not even a context, so try to find its nns
	    // dynamically by constructing a Reference that
	    // contains obj
	    RefAddr addr = new RefAddr("nns") {
		public Object getContent() {
		    return obj;
		}
	    };
	    Reference ref = new Reference("java.lang.Object", addr);

	    // Resolved name has a trailing slash to indicate the nns
	    CompositeName resName = (CompositeName)name.clone();
	    resName.add(""); // Add the trailing forward slash

	    cpe = fillInCPE(ref, resName, rest);
	    cpe.setRemainingNewName(newName);

	} else {
	    // Consume "/" and continue
	    return obj;
	}
    } catch (NamingException e) {
	e.appendRemainingComponent(""); // Add the nns back in
	throw e;
    }
    throw cpe;
}

Como se ha definido en el ejemplo, este m�todo soporta "empalmes" y nns impl�citos din�micos (ver la lecci�n Federaci�n). Si nuestra implementaci�n de contexto soporta nns impl�citos est�ticos, pobablemente querremos mirar al siguiente c�digo en su lugar:

private void resolveIntermediate_nns(Name name, Name rest, Name newName)
    throws NamingException {
    Object nns;
    if (name.isEmpty()) {
	nns = myNNS;   // Return this context's nns
    } else {
        // Extract the components that belong to this namespace
        String atom = getInternalName(name);

        // Get the nns from the internal table
        nns  = nnsBindings.get(atom);
        if (nns == null) {
	    throw new NameNotFoundException(atom + "/");
        }
    }
    // Call getObjectInstance for using any object factories
    try {
	return NamingManager.getObjectInstance(nns,
	    ((Name)(name.clone())).add(""), this, myEnv);
    } catch (Exception e) {
	NamingException ne = new NamingException();
	ne.setRootCause(e);
	throw ne;
    }
}

COMPARTE ESTE ARTÍCULO

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