You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by da...@apache.org on 2006/08/23 22:29:24 UTC

svn commit: r434162 - in /geronimo/xbean/branches/colossus/xbean-naming/src: main/java/org/apache/xbean/naming/context/ test/java/org/apache/xbean/naming/context/

Author: dain
Date: Wed Aug 23 13:29:23 2006
New Revision: 434162

URL: http://svn.apache.org/viewvc?rev=434162&view=rev
Log:
Added basic support for federation

Added:
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextFederation.java
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/VirtualSubcontext.java
    geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/FederationTest.java
Modified:
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractContext.java
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextUtil.java
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/NestedContextFactory.java
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/UnmodifiableContext.java
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/WritableContext.java
    geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/AbstractContextTest.java

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractContext.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractContext.java?rev=434162&r1=434161&r2=434162&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractContext.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractContext.java Wed Aug 23 13:29:23 2006
@@ -36,9 +36,15 @@
 public abstract class AbstractContext implements Context, NestedContextFactory, Serializable {
     private static final long serialVersionUID = 6481918425692261483L;
     private final String nameInNamespace;
+    private final Name parsedNameInNamespace;
 
     protected AbstractContext(String nameInNamespace) {
         this.nameInNamespace = nameInNamespace;
+        try {
+            this.parsedNameInNamespace = getNameParser().parse(nameInNamespace);
+        } catch (NamingException e) {
+            throw new RuntimeException(e);
+        }
     }
 
 
@@ -134,6 +140,21 @@
         }
 
         // if we didn't find an entry, it may be an absolute name
+        Object value = faultLookup(stringName, parsedName);
+        if (value != null) {
+            return value;
+        }
+        throw new NameNotFoundException(stringName);
+    }
+
+    /**
+     * When a value can not be found within this context, this method is called as a last ditch effort befrore
+     * thowing a null pointer exception.
+     * @param stringName the string version of the name; will not be null
+     * @param parsedName the parsed name; will not be null
+     * @return the value or null if no fault value could be found
+     */
+    protected Object faultLookup(String stringName, Name parsedName) {
         if (stringName.indexOf(':') > 0) {
             try {
                 Context ctx = new InitialContext();
@@ -142,7 +163,7 @@
                 // thrown below
             }
         }
-        throw new NameNotFoundException(stringName);
+        return null;
     }
 
     protected Context lookupFinalContext(Name name) throws NamingException {
@@ -456,6 +477,15 @@
     }
 
     /**
+     * Gets the name of this context withing the global namespace.  This method may return null
+     * if the location of the node in the global namespace is not known
+     * @return the name of this context within the global namespace or null if unknown.
+     */
+    protected Name getParsedNameInNamespace() {
+        return parsedNameInNamespace;
+    }
+
+    /**
      * Gets the name of a path withing the global namespace context.
      */
     protected String getNameInNamespace(String path) {
@@ -464,6 +494,18 @@
             return path;
         } else {
             return nameInNamespace + "/" + path;
+        }
+    }
+
+    /**
+     * Gets the name of a path withing the global namespace context.
+     */
+    protected Name getNameInNamespace(Name path) throws NamingException {
+        Name nameInNamespace = getParsedNameInNamespace();
+        if (nameInNamespace == null || nameInNamespace.size() == 0) {
+            return path;
+        } else {
+            return composeName(nameInNamespace, path);
         }
     }
 

Added: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextFederation.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextFederation.java?rev=434162&view=auto
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextFederation.java (added)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextFederation.java Wed Aug 23 13:29:23 2006
@@ -0,0 +1,106 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.xbean.naming.context;
+
+import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicReference;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.NamingEnumeration;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ContextFederation {
+    private final Context actualContext;
+    private final AtomicReference federatedContextRef = new AtomicReference(Collections.EMPTY_SET);
+    public static final int MAX_WRITE_ATTEMPTS = 10;
+
+    public ContextFederation(Context actualContext) {
+        this.actualContext = actualContext;
+    }
+
+    public void addContext(Context context) {
+        Set federatedContext;
+        Set newFederatedContext;
+        for (int i = 0; i < MAX_WRITE_ATTEMPTS; i++) {
+            federatedContext = getFederatedContexts();
+
+            newFederatedContext = new LinkedHashSet(federatedContext);
+            newFederatedContext.add(context);
+            newFederatedContext = Collections.unmodifiableSet(newFederatedContext);
+            if (federatedContextRef.compareAndSet(federatedContext, newFederatedContext)) {
+                return;
+            }
+        }
+        throw new RuntimeException("Unable to update federatedContextRef within " + MAX_WRITE_ATTEMPTS + " attempts");
+    }
+
+    public Set getFederatedContexts() {
+        return (Set) federatedContextRef.get();
+    }
+
+    public Map getFederatedBindings() throws NamingException {
+        Map bindings = new HashMap();
+        for (Iterator iterator = getFederatedContexts().iterator(); iterator.hasNext();) {
+            Context context = (Context) iterator.next();
+
+            // list federated context
+            NamingEnumeration namingEnumeration = context.listBindings("");
+
+            // add to bindings
+            Map map = ContextUtil.listBindingsToMap(namingEnumeration);
+            bindings.putAll(map);
+        }
+        return bindings;
+    }
+
+    public Object lookup(Name name) {
+        for (Iterator iterator = getFederatedContexts().iterator(); iterator.hasNext();) {
+            try {
+                Context federatedContext = (Context) iterator.next();
+                Object value = federatedContext.lookup(name);
+                if (value instanceof Context) {
+                    return new VirtualSubcontext(name, actualContext);
+                } else {
+                    return value;
+                }
+            } catch (NamingException ignored) {
+            }
+        }
+        return null;
+    }
+
+    public ContextFederation createSubcontextFederation(String subcontextName, Context actualSubcontext) throws NamingException {
+        Name parsedSubcontextName = actualContext.getNameParser("").parse(subcontextName);
+
+        ContextFederation subcontextFederation = new ContextFederation(actualSubcontext);
+        for (Iterator iterator = getFederatedContexts().iterator(); iterator.hasNext();) {
+            Context federatedContext = (Context) iterator.next();
+            VirtualSubcontext virtualSubcontext = new VirtualSubcontext(parsedSubcontextName, federatedContext);
+            subcontextFederation.addContext(virtualSubcontext);
+        }
+        return subcontextFederation;
+    }
+}

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextUtil.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextUtil.java?rev=434162&r1=434161&r2=434162&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextUtil.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextUtil.java Wed Aug 23 13:29:23 2006
@@ -20,20 +20,20 @@
 
 import javax.naming.Binding;
 import javax.naming.CompoundName;
+import javax.naming.Context;
 import javax.naming.Name;
 import javax.naming.NameClassPair;
 import javax.naming.NameParser;
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
 import javax.naming.Reference;
-import javax.naming.Context;
 import javax.naming.spi.NamingManager;
+import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Properties;
-import java.util.HashMap;
-import java.util.Enumeration;
 
 /**
  * @version $Rev$ $Date$
@@ -86,6 +86,26 @@
         }
     }
 
+    public static Map listToMap(NamingEnumeration enumeration) {
+        Map result = new HashMap();
+        while (enumeration.hasMoreElements()) {
+            NameClassPair nameClassPair = (NameClassPair) enumeration.nextElement();
+            String name = nameClassPair.getName();
+            result.put(name, nameClassPair.getClassName());
+        }
+        return result;
+    }
+
+    public static Map listBindingsToMap(NamingEnumeration enumeration) {
+        Map result = new HashMap();
+        while (enumeration.hasMoreElements()) {
+            Binding binding = (Binding) enumeration.nextElement();
+            String name = binding.getName();
+            result.put(name, binding.getObject());
+        }
+        return result;
+    }
+
     public static final class ListEnumeration implements NamingEnumeration {
         private final Iterator iterator;
 
@@ -226,7 +246,7 @@
         return localBindings;
     }
 
-    private static Map createBindings(String nameInNameSpace, Node node, NestedContextFactory factory) {
+    private static Map createBindings(String nameInNameSpace, Node node, NestedContextFactory factory) throws NamingException {
         Map bindings = new HashMap(node.size());
         for (Iterator iterator = node.entrySet().iterator(); iterator.hasNext();) {
             Map.Entry entry = (Map.Entry) iterator.next();

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/NestedContextFactory.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/NestedContextFactory.java?rev=434162&r1=434161&r2=434162&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/NestedContextFactory.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/NestedContextFactory.java Wed Aug 23 13:29:23 2006
@@ -17,6 +17,7 @@
 package org.apache.xbean.naming.context;
 
 import javax.naming.Context;
+import javax.naming.NamingException;
 import java.util.Map;
 
 /**
@@ -36,5 +37,5 @@
      * @param bindings the initial bindings for the context
      * @return the new nested context
      */
-    Context createNestedSubcontext(String path, Map bindings);
+    Context createNestedSubcontext(String path, Map bindings) throws NamingException;
 }

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/UnmodifiableContext.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/UnmodifiableContext.java?rev=434162&r1=434161&r2=434162&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/UnmodifiableContext.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/UnmodifiableContext.java Wed Aug 23 13:29:23 2006
@@ -53,8 +53,8 @@
         return false;
     }
 
-    public Context createNestedSubcontext(String path, Map bindings) {
-        return new NestedUnmodifiableContext(path,bindings);
+    public Context createNestedSubcontext(String path, Map bindings) throws NamingException {
+        return new NestedUnmodifiableContext(path, bindings, contextFederation);
     }
 
     public final void bind(Name name, Object obj) throws NamingException {
@@ -113,12 +113,8 @@
      * Nested context which shares the absolute index map in MapContext.
      */
     public class NestedUnmodifiableContext extends NestedWritableContext {
-        public NestedUnmodifiableContext(String path, String key, Object value) {
-            super(path, key, value);
-        }
-
-        public NestedUnmodifiableContext(String path, Map bindings) {
-            super(path, bindings);
+        public NestedUnmodifiableContext(String path, Map bindings, ContextFederation contextFederation) throws NamingException {
+            super(path, bindings, contextFederation);
         }
 
         public boolean isNestedSubcontext(Object value) {
@@ -129,8 +125,8 @@
             return false;
         }
 
-        public Context createNestedSubcontext(String path, Map bindings) {
-            return new NestedUnmodifiableContext(path, bindings);
+        public Context createNestedSubcontext(String path, Map bindings) throws NamingException {
+            return new NestedUnmodifiableContext(path, bindings, contextFederation);
         }
 
         protected UnmodifiableContext getUnmodifiableContext() {

Added: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/VirtualSubcontext.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/VirtualSubcontext.java?rev=434162&view=auto
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/VirtualSubcontext.java (added)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/VirtualSubcontext.java Wed Aug 23 13:29:23 2006
@@ -0,0 +1,169 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.xbean.naming.context;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NameParser;
+import java.util.Hashtable;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class VirtualSubcontext implements Context {
+    private final Name nameInContext;
+    private final Context context;
+
+    public VirtualSubcontext(Name nameInContext, Context context) throws NamingException {
+        if (context instanceof VirtualSubcontext) {
+            VirtualSubcontext virtualSubcontext = (VirtualSubcontext) context;
+            this.nameInContext = virtualSubcontext.getNameInContext(nameInContext);
+            this.context = virtualSubcontext.context;
+        } else {
+            this.nameInContext = nameInContext;
+            this.context = context;
+        }
+    }
+
+    private Name getNameInContext(Name name) throws NamingException {
+        return context.composeName(nameInContext, name);
+    }
+
+    private Name getNameInContext(String name) throws NamingException {
+        Name parsedName = context.getNameParser("").parse(name);
+        return context.composeName(nameInContext, parsedName);
+    }
+
+    public Object lookup(Name name) throws NamingException {
+        return context.lookup(getNameInContext(name));
+    }
+
+    public Object lookup(String name) throws NamingException {
+        return context.lookup(getNameInContext(name));
+    }
+
+    public void bind(Name name, Object obj) throws NamingException {
+        context.bind(getNameInContext(name), obj);
+    }
+
+    public void bind(String name, Object obj) throws NamingException {
+        context.bind(getNameInContext(name), obj);
+    }
+
+    public void rebind(Name name, Object obj) throws NamingException {
+        context.rebind(getNameInContext(name), obj);
+    }
+
+    public void rebind(String name, Object obj) throws NamingException {
+        context.rebind(getNameInContext(name), obj);
+    }
+
+    public void unbind(Name name) throws NamingException {
+        context.unbind(getNameInContext(name));
+    }
+
+    public void unbind(String name) throws NamingException {
+        context.unbind(getNameInContext(name));
+    }
+
+    public void rename(Name oldName, Name newName) throws NamingException {
+        context.rename(getNameInContext(oldName), getNameInContext(newName));
+    }
+
+    public void rename(String oldName, String newName) throws NamingException {
+        context.rename(getNameInContext(oldName), getNameInContext(newName));
+    }
+
+    public NamingEnumeration list(Name name) throws NamingException {
+        return context.list(getNameInContext(name));
+    }
+
+    public NamingEnumeration list(String name) throws NamingException {
+        return context.list(getNameInContext(name));
+    }
+
+    public NamingEnumeration listBindings(Name name) throws NamingException {
+        return context.listBindings(getNameInContext(name));
+    }
+
+    public NamingEnumeration listBindings(String name) throws NamingException {
+        return context.listBindings(getNameInContext(name));
+    }
+
+    public void destroySubcontext(Name name) throws NamingException {
+        context.destroySubcontext(getNameInContext(name));
+    }
+
+    public void destroySubcontext(String name) throws NamingException {
+        context.destroySubcontext(getNameInContext(name));
+    }
+
+    public Context createSubcontext(Name name) throws NamingException {
+        return context.createSubcontext(getNameInContext(name));
+    }
+
+    public Context createSubcontext(String name) throws NamingException {
+        return context.createSubcontext(getNameInContext(name));
+    }
+
+    public Object lookupLink(Name name) throws NamingException {
+        return context.lookupLink(getNameInContext(name));
+    }
+
+    public Object lookupLink(String name) throws NamingException {
+        return context.lookupLink(getNameInContext(name));
+    }
+
+    public NameParser getNameParser(Name name) throws NamingException {
+        return context.getNameParser(getNameInContext(name));
+    }
+
+    public NameParser getNameParser(String name) throws NamingException {
+        return context.getNameParser(getNameInContext(name));
+    }
+
+    public Name composeName(Name name, Name prefix) throws NamingException {
+        return context.composeName(name, prefix);
+    }
+
+    public String composeName(String name, String prefix) throws NamingException {
+        return context.composeName(name, prefix);
+    }
+
+    public Object addToEnvironment(String propName, Object propVal) throws NamingException {
+        return context.addToEnvironment(propName, propVal);
+    }
+
+    public Object removeFromEnvironment(String propName) throws NamingException {
+        return context.removeFromEnvironment(propName);
+    }
+
+    public Hashtable getEnvironment() throws NamingException {
+        return context.getEnvironment();
+    }
+
+    public void close() throws NamingException {
+        context.close();
+    }
+
+    public String getNameInNamespace() throws NamingException {
+        Name parsedNameInNamespace = context.getNameParser("").parse(context.getNameInNamespace());
+        return context.composeName(parsedNameInNamespace, nameInContext).toString();
+    }
+}

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/WritableContext.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/WritableContext.java?rev=434162&r1=434161&r2=434162&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/WritableContext.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/WritableContext.java Wed Aug 23 13:29:23 2006
@@ -16,21 +16,20 @@
  */
 package org.apache.xbean.naming.context;
 
+import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicReference;
 import edu.emory.mathcs.backport.java.util.concurrent.locks.Lock;
 import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
-import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicReference;
+import org.apache.xbean.naming.reference.CachingReference;
 
 import javax.naming.Context;
-import javax.naming.NameAlreadyBoundException;
-import javax.naming.NamingException;
-import javax.naming.OperationNotSupportedException;
+import javax.naming.Name;
 import javax.naming.NameNotFoundException;
-import java.util.HashMap;
-import java.util.Map;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
-
-import org.apache.xbean.naming.reference.CachingReference;
+import java.util.Map;
 
 /**
  * @version $Rev$ $Date$
@@ -39,7 +38,7 @@
     private final Lock writeLock = new ReentrantLock();
     private final AtomicReference bindingsRef;
     private final AtomicReference indexRef;
-    public static final int MAX_WRITE_ATTEMPTS = 3;
+    protected final ContextFederation contextFederation = new ContextFederation(this);
 
     public WritableContext() throws NamingException {
         this("", Collections.EMPTY_MAP, true);
@@ -70,12 +69,55 @@
         this.indexRef = new AtomicReference(Collections.unmodifiableMap(buildIndex("", localBindings)));
     }
 
+    protected Object faultLookup(String stringName, Name parsedName) {
+        Object value = contextFederation.lookup(parsedName);
+        if (value != null) {
+            return value;
+        }
+        return super.faultLookup(stringName, parsedName);
+    }
+
+    protected NamingEnumeration list() throws NamingException {
+        Map bindings = getListBindings();
+        return new ContextUtil.ListEnumeration(bindings);
+    }
+
+    protected NamingEnumeration listBindings() throws NamingException {
+        Map bindings = getListBindings();
+        return new ContextUtil.ListBindingEnumeration(bindings);
+    }
+
+    protected Map getListBindings() throws NamingException {
+        Map bindings = new HashMap();
+        bindings.putAll(getBindings());
+        bindings.putAll(contextFederation.getFederatedBindings());
+        return bindings;
+    }
+
     protected void addBinding(String name, Object value, boolean rebind) throws NamingException {
+        addBinding(bindingsRef, name, value);
+    }
+
+    protected void addBinding(AtomicReference bindingsRef, String name, Object value) throws NamingException {
         writeLock.lock();
         try {
             Map bindings = (Map) bindingsRef.get();
-            if (bindings.containsKey(name)) {
-                throw new NameAlreadyBoundException(name);
+
+            if (value instanceof Context && !isNestedSubcontext(value)) {
+                Context federatedContext = (Context) value;
+
+                // if we already have a context bound at the specified value
+                if (bindings.containsKey(name)) {
+                    NestedWritableContext nestedContext = (NestedWritableContext) bindings.get(name);
+                    // push new context into all children
+                    Map nestedBindings = (Map) nestedContext.bindingsRef.get();
+                    addFederatedContext(nestedBindings, federatedContext);
+                    return;
+                }
+
+                NestedWritableContext nestedContext = (NestedWritableContext) createNestedSubcontext(name, Collections.EMPTY_MAP);
+                nestedContext.contextFederation.addContext(federatedContext);
+                value = nestedContext;
             }
 
             Map newBindings = new HashMap(bindings);
@@ -89,6 +131,18 @@
         }
     }
 
+    protected void addFederatedContext(Map bindings, Context federatedContext) {
+        for (Iterator iterator = bindings.values().iterator(); iterator.hasNext();) {
+            Object value = iterator.next();
+            if (value instanceof NestedWritableContext) {
+                NestedWritableContext nestedContext = (NestedWritableContext) value;
+                nestedContext.contextFederation.addContext(federatedContext);
+                Map nestedBindings = (Map) nestedContext.bindingsRef.get();
+                addFederatedContext(nestedBindings, federatedContext);
+            }
+        }
+    }
+
     private Map addToIndex(String name, Object value) {
         Map index = (Map) indexRef.get();
         Map newIndex = new HashMap(index);
@@ -102,6 +156,10 @@
     }
 
     protected void removeBinding(String name) throws NamingException {
+        removeBinding(bindingsRef, name);
+    }
+
+    private void removeBinding(AtomicReference bindingsRef, String name) throws NameNotFoundException {
         writeLock.lock();
         try {
             Map bindings = (Map) bindingsRef.get();
@@ -143,8 +201,8 @@
         return false;
     }
 
-    public Context createNestedSubcontext(String path, Map bindings) {
-        return new NestedWritableContext(path,bindings);
+    public Context createNestedSubcontext(String path, Map bindings) throws NamingException {
+        return new NestedWritableContext(path,bindings, contextFederation);
     }
 
     private static Map buildIndex(String nameInNamespace, Map bindings) {
@@ -183,18 +241,17 @@
     public class NestedWritableContext extends AbstractContext {
         private final AtomicReference bindingsRef;
         private final String pathWithSlash;
+        protected final ContextFederation contextFederation;
 
-        public NestedWritableContext(String path, String key, Object value) {
-            this(path, Collections.singletonMap(key, value));
-        }
-
-        public NestedWritableContext(String path, Map bindings) {
+        public NestedWritableContext(String path, Map bindings, ContextFederation parentContextFederation) throws NamingException {
             super(WritableContext.this.getNameInNamespace(path));
 
             if (!path.endsWith("/")) path += "/";
             this.pathWithSlash = path;
 
             this.bindingsRef = new AtomicReference(Collections.unmodifiableMap(bindings));
+
+            this.contextFederation = parentContextFederation.createSubcontextFederation(path, this);
         }
 
         public boolean isNestedSubcontext(Object value) {
@@ -205,8 +262,8 @@
             return false;
         }
 
-        public Context createNestedSubcontext(String path, Map bindings) {
-            return new NestedWritableContext(path, bindings);
+        public Context createNestedSubcontext(String path, Map bindings) throws NamingException {
+            return new NestedWritableContext(path, bindings, contextFederation);
         }
 
         protected Object getDeepBinding(String name) {
@@ -219,40 +276,37 @@
             return bindings;
         }
 
-        protected void addBinding(String name, Object value, boolean rebind) throws NamingException {
-            if (rebind) {
-                throw new OperationNotSupportedException("This conext does not support rebind");
+        protected Object faultLookup(String stringName, Name parsedName) {
+            Object value = contextFederation.lookup(parsedName);
+            if (value != null) {
+                return value;
             }
+            return super.faultLookup(stringName, parsedName);
+        }
 
-            writeLock.lock();
-            try {
-                Map currentBindings = (Map) bindingsRef.get();
-                Map newBindings = new HashMap(currentBindings);
-                newBindings.put(name, value);
-                newBindings = Collections.unmodifiableMap(newBindings);
-                bindingsRef.set(newBindings);
-
-                Map newIndex = addToIndex(name, value);
-                indexRef.set(newIndex);
-            } finally {
-                writeLock.unlock();
-            }
+        protected NamingEnumeration list() throws NamingException {
+            Map bindings = getListBindings();
+            return new ContextUtil.ListEnumeration(bindings);
         }
 
-        protected void removeBinding(String name) {
-            writeLock.lock();
-            try {
-                Map currentBindings = (Map) bindingsRef.get();
-                Map newBindings = new HashMap(currentBindings);
-                newBindings.remove(name);
-                newBindings = Collections.unmodifiableMap(newBindings);
-                bindingsRef.set(newBindings);
-
-                Map newIndex = removeFromIndex(name);
-                indexRef.set(newIndex);
-            } finally {
-                writeLock.unlock();
-            }
+        protected NamingEnumeration listBindings() throws NamingException {
+            Map bindings = getListBindings();
+            return new ContextUtil.ListBindingEnumeration(bindings);
+        }
+
+        protected Map getListBindings() throws NamingException {
+            Map bindings = new HashMap();
+            bindings.putAll(getBindings());
+            bindings.putAll(contextFederation.getFederatedBindings());
+            return bindings;
+        }
+
+        protected void addBinding(String name, Object value, boolean rebind) throws NamingException {
+            WritableContext.this.addBinding(bindingsRef, name, value);
+        }
+
+        protected void removeBinding(String name) throws NameNotFoundException {
+            WritableContext.this.removeBinding(bindingsRef, name);
         }
 
         private WritableContext getUnmodifiableContext() {

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/AbstractContextTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/AbstractContextTest.java?rev=434162&r1=434161&r2=434162&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/AbstractContextTest.java (original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/AbstractContextTest.java Wed Aug 23 13:29:23 2006
@@ -22,12 +22,9 @@
 import javax.naming.NamingException;
 import javax.naming.Name;
 import javax.naming.NamingEnumeration;
-import javax.naming.NameClassPair;
-import javax.naming.Binding;
 import java.util.Map;
 import java.util.Iterator;
 import java.util.TreeSet;
-import java.util.HashMap;
 
 /**
  * @version $Rev$ $Date$
@@ -114,9 +111,9 @@
     public static void assertListResults(ContextUtil.Node node, NamingEnumeration enumeration, String contextName, String name, boolean wasListBinding) {
         Map actualValues;
         if (wasListBinding) {
-            actualValues = AbstractContextTest.toListBindingResults(enumeration);
+            actualValues = ContextUtil.listBindingsToMap(enumeration);
         } else {
-            actualValues = AbstractContextTest.toListResults(enumeration);
+            actualValues = ContextUtil.listToMap(enumeration);
         }
 
         for (Iterator iterator = node.entrySet().iterator(); iterator.hasNext();) {
@@ -129,14 +126,14 @@
             assertNotNull("list of " + name + " on " + contextName + " did not find value for " + name, actualValue);
             if (wasListBinding) {
                 if (expectedValue instanceof ContextUtil.Node) {
-                    assertTrue("Expected list of " + name + " on " + contextName + " result value for " + name + " to return a Context, but got a " + actualValue.getClass().getName(),
+                    assertTrue("Expected list of " + name + " on " + contextName + " result value for " + expectedName + " to return a Context, but got a " + actualValue.getClass().getName(),
                         actualValue instanceof Context);
                 } else {
-                    assertEquals("list of " + name + " on " + contextName + " for value for " + name, expectedValue, actualValue);
+                    assertEquals("list of " + name + " on " + contextName + " for value for " + expectedName, expectedValue, actualValue);
                 }
             } else {
                 if (!(expectedValue instanceof ContextUtil.Node)) {
-                    assertEquals("list of " + name + " on " + contextName + " for value for " + name, expectedValue.getClass().getName(), actualValue);
+                    assertEquals("list of " + name + " on " + contextName + " for value for " + expectedName, expectedValue.getClass().getName(), actualValue);
                 } else {
                     // can't really test this since it the value is the name of a nested node class
                 }
@@ -146,29 +143,7 @@
         TreeSet extraNames = new TreeSet(actualValues.keySet());
         extraNames.removeAll(node.keySet());
         if (!extraNames.isEmpty()) {
-            fail("list of " + name + " on " + contextName + " found extra values: " + extraNames);
+            fail("list of " + name + " on " + contextName + " did not find values: " + extraNames);
         }
-    }
-
-    private static Map toListResults(NamingEnumeration enumeration) {
-        Map result = new HashMap();
-        while (enumeration.hasMoreElements()) {
-            NameClassPair nameClassPair = (NameClassPair) enumeration.nextElement();
-            String name = nameClassPair.getName();
-            assertFalse(result.containsKey(name));
-            result.put(name, nameClassPair.getClassName());
-        }
-        return result;
-    }
-
-    private static Map toListBindingResults(NamingEnumeration enumeration) {
-        Map result = new HashMap();
-        while (enumeration.hasMoreElements()) {
-            Binding binding = (Binding) enumeration.nextElement();
-            String name = binding.getName();
-            assertFalse(result.containsKey(name));
-            result.put(name, binding.getObject());
-        }
-        return result;
     }
 }

Added: geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/FederationTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/FederationTest.java?rev=434162&view=auto
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/FederationTest.java (added)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/FederationTest.java Wed Aug 23 13:29:23 2006
@@ -0,0 +1,141 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.xbean.naming.context;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.Name;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * @version $Rev: 355877 $ $Date: 2005-12-10 18:48:27 -0800 (Sat, 10 Dec 2005) $
+ */
+public class FederationTest extends AbstractContextTest {
+    private static final String STRING_VAL = "some string";
+
+    public void testBasic() throws Exception {
+        Map map = new HashMap();
+        map.put("string", FederationTest.STRING_VAL);
+        map.put("nested/context/string", FederationTest.STRING_VAL);
+        map.put("java:comp/env/string", FederationTest.STRING_VAL);
+        map.put("java:comp/env/one", new Integer(1));
+        map.put("java:comp/env/two", new Integer(2));
+        map.put("java:comp/env/three", new Integer(3));
+
+        Context context = new WritableContext();
+        FederationTest.bind(context, map);
+
+        assertEq(map, context);
+
+        Map env2Map = new HashMap();
+        env2Map.put("string", FederationTest.STRING_VAL);
+        env2Map.put("one", new Integer(1));
+        env2Map.put("two", new Integer(2));
+        env2Map.put("three", new Integer(3));
+
+        ImmutableContext actualEnv2Context = new ImmutableContext(env2Map);
+        assertEq(env2Map, actualEnv2Context);
+
+        context.bind("java:comp/env2", actualEnv2Context);
+
+        Context env2Context = (Context) context.lookup("java:comp/env2");
+        assertEq(env2Map, env2Context);
+
+        putAllBindings(map, "java:comp/env2", env2Map);
+        assertEq(map, context);
+    }
+
+    public void testAddBinding() throws Exception {
+        Map map = new HashMap();
+        map.put("string", FederationTest.STRING_VAL);
+        map.put("nested/context/string", FederationTest.STRING_VAL);
+        map.put("a/b/c/d/e/string", FederationTest.STRING_VAL);
+        map.put("a/b/c/d/e/one", new Integer(1));
+        map.put("a/b/c/d/e/two", new Integer(2));
+        map.put("a/b/c/d/e/three", new Integer(3));
+
+        Context context = new WritableContext();
+        FederationTest.bind(context, map);
+
+        assertEq(map, context);
+
+        // add a new deep tree
+        map.put("a/b/c/d/e/forty-two", new Integer(42));
+        context.bind("a/b/c/d/e/forty-two", new Integer(42));
+
+        assertEq(map, context);
+
+    }
+
+
+    public void testRemoveBinding() throws Exception {
+        Map map = new HashMap();
+        map.put("string", FederationTest.STRING_VAL);
+        map.put("nested/context/string", FederationTest.STRING_VAL);
+        map.put("a/b/c/d/e/string", FederationTest.STRING_VAL);
+        map.put("a/b/c/d/e/one", new Integer(1));
+        map.put("a/b/c/d/e/two", new Integer(2));
+        map.put("a/b/c/d/e/three", new Integer(3));
+
+        Context context = new WritableContext();
+        FederationTest.bind(context, map);
+
+        assertEq(map, context);
+
+        // remove from an exisitng node
+        map.remove("a/b/c/d/e/three");
+        context.unbind("a/b/c/d/e/three");
+
+        assertEq(map, context);
+    }
+
+    public static void putAllBindings(Map rootBindings, String nestedPath, Map nestedBindings) {
+        for (Iterator iterator = nestedBindings.entrySet().iterator(); iterator.hasNext();) {
+            Map.Entry entry = (Map.Entry) iterator.next();
+            String name = (String) entry.getKey();
+            Object value = entry.getValue();
+            String fullName = nestedPath + "/" + name;
+            rootBindings.put(fullName, value);
+        }
+    }
+
+    public static void bind(Context context, Map bindings) throws NamingException {
+        for (Iterator iterator = bindings.entrySet().iterator(); iterator.hasNext();) {
+            Map.Entry entry = (Map.Entry) iterator.next();
+            String name = (String) entry.getKey();
+            Object value = entry.getValue();
+            Name parsedName = context.getNameParser("").parse(name);
+            for (int i =1; i < parsedName.size(); i++) {
+                Name contextName = parsedName.getPrefix(i);
+                if (!FederationTest.bindingExists(context, contextName)) {
+                    context.createSubcontext(contextName);
+                }
+            }
+            context.bind(name, value);
+        }
+    }
+
+    public static boolean bindingExists(Context context, Name contextName) {
+        try {
+            return context.lookup(contextName) != null;
+        } catch (NamingException e) {
+        }
+        return false;
+    }
+}