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:


El Sistema de Nombres Actual

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

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