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