The Essential Components |
list() and listBindings() generate a NamingEnumeration. A NamingEnumeration is like a java.util.Enumeration, except that it contains methods that allow a NamingException to be thrown and it contains a close() method for freeing the resources associated with the enumeration. In the flat namespace example, list() and listBindings() simply perform a lookup() on the target context (that is, the context to be listed) and then do the listing by using the empty name as the argument. If the target does not name a Context, then it throws a NotContextException.public NamingEnumeration list(Name name) throws NamingException { if (name.isEmpty()) { // Generate enumeration of context's contents return new ListOfNames(bindings.keys()); } // Perhaps "name" names a context Object target = lookup(name); if (target instanceof Context) { try { return ((Context)target).list(""); } finally { ((Context)target).close(); } } throw new NotContextException(name + " cannot be listed"); }
Implementation Note: Notice that the list() and listBindings() implementations take care to close the context that they looked up. This is good practice in case the context needs to be cleaned up. This also means that the enumeration returned by both methods should remain viable even after the Context instance from which it was obtained has been closed. When the Context instance's outstanding enumerations have been closed or completed, the final cleanup of the closed Context instance can occur.
The listing is generated by using the two internal classes ListOfNames and ListOfBindings. Here is the definition of ListOfNames.
The real work is done in the hasMore() and next() definitions. For the hash table example, ListOfNames is simply a wrapper around an Enumeration. In an actual implementation, the listing would be generated by accessing the underlying naming/directory service.// Class for enumerating name/class pairs class ListOfNames implements NamingEnumeration { protected Enumeration names; ListOfNames (Enumeration names) { this.names = names; } public boolean hasMoreElements() { try { return hasMore(); } catch (NamingException e) { return false; } } public boolean hasMore() throws NamingException { return names.hasMoreElements(); } public Object next() throws NamingException { String name = (String)names.nextElement(); String className = bindings.get(name).getClass().getName(); return new NameClassPair(name, className); } public Object nextElement() { try { return next(); } catch (NamingException e) { throw new NoSuchElementException(e.toString()); } } public void close() { } }hasMoreElements() is a wrapper around hasMore(), whereas nextElement() is a wrapper around next(). hasMoreElements() and nextElement() satisfy the java.util.Enumeration interface and are used by clients that do not care about being notified of exceptions that occur during the enumeration. These are generic definitions that can be used by any implementation.
The ListOfBindings inner class is a subclass of ListOfNames. It overrides the definition of next() to return an instance of an instance of Binding instead of NameClassPair:
This is obviously a very simplified implementation. If the object in Binding is a Context, then it should be one that can be closed (which probably means that you want to clone it before returning it).public Object next() throws NamingException { String name = (String)names.nextElement(); return new Binding(name, bindings.get(name)); }
The Essential Components |