geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d...@apache.org
Subject svn commit: r433400 - in /geronimo/xbean/branches/colossus/xbean-naming/src: main/java/org/apache/xbean/naming/context/ test/java/org/apache/xbean/naming/context/
Date Mon, 21 Aug 2006 22:30:24 GMT
Author: dain
Date: Mon Aug 21 15:30:24 2006
New Revision: 433400

URL: http://svn.apache.org/viewvc?rev=433400&view=rev
Log:
Pulled up support for automatic pruning of empty contexts during remove from AbstractUnmodifiableContext
to AbstractContext.

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/AbstractUnmodifiableContext.java
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ImmutableContext.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/UnmodifiableContextTest.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=433400&r1=433399&r2=433400&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
Mon Aug 21 15:30:24 2006
@@ -172,11 +172,7 @@
             Context context = lookupFinalContext(name);
 
             String lastSegment = name.get(name.size() - 1);
-            if (rebind) {
-                context.rebind(lastSegment, value);
-            } else {
-                context.bind(lastSegment, value);
-            }
+            addBinding(context, lastSegment, value, rebind);
         } else {
             Context currentContext = this;
             for (int i = 0; i < name.size(); i++) {
@@ -198,21 +194,17 @@
                 } else {
                     Object currentValue = getBinding(currentContext, part);
                     if (currentValue == null) {
-                        if (createIntermediateContexts) {
-                            // the next step in the tree is not present, so create everything
down
-                            // and add it to the current bindings
-                            Context subcontext = createSubcontextTree(name.getPrefix(i).toString(),
name.getSuffix(i), value);
-                            addBinding(currentContext, part, subcontext, rebind);
-
-                            // all done
-                            break;
-                        } else {
-                            throw new NotContextException("The intermediate context " + name.get(name.size()
- 1) + " does not exist");
-                        }
+                        // the next step in the tree is not present, so create everything
down
+                        // and add it to the current bindings
+                        Context subcontext = createSubcontextTree(name.getPrefix(i).toString(),
name.getSuffix(i), value);
+                        addBinding(currentContext, part, subcontext, rebind);
+
+                        // all done
+                        break;
                     } else {
                         // the current value must be a nested subcontext
-                        if (!isNestedSubcontext(currentValue)) {
-                            throw new NotContextException("Expected a nested subcontext to
be bound at " +
+                        if (!(currentContext instanceof Context)) {
+                            throw new NotContextException("Expected an instance of context
to be bound at " +
                                     part + " but found an instance of " + currentValue.getClass().getName());
                         }
                         currentContext = (Context) currentValue;
@@ -247,17 +239,18 @@
     }
 
     /**
-     * Gets the value bound to the specified name within the specified context.  If the specified
context is an
-     * AbstractContext this method will call the faster getBinding method, otherwise it will
call lookup.
+     * Binds the specified value to the specified name within the specified context.  If
the specified context is an
+     * AbstractContext and is a nested subcontext, this method will call the direct addBinding
method, otherwise it
+     * will call public (re)bind method.
      *
-     * @param context the context to get the binding from
+     * @param context the context to add the binding to
      * @param name the binding name
      * @param value the value to bind
      * @param rebind if true, this method will replace any exsiting binding, otherwise a
NamingException will be thrown
-     * @throws NamingException
+     * @throws NamingException if a problem occurs while (re)binding
      */
-    private static void addBinding(Context context, String name, Object value, boolean rebind)
throws NamingException {
-        if (context instanceof AbstractContext) {
+    private void addBinding(Context context, String name, Object value, boolean rebind) throws
NamingException {
+        if (context == this || (context instanceof AbstractContext && isNestedSubcontext(context)))
{
             AbstractContext abstractContext = (AbstractContext) context;
             abstractContext.addBinding(name, value, rebind);
         } else {
@@ -278,7 +271,7 @@
      * @param name the name under which the value should be bound
      * @param value the vale
      * @return a context with the value bound at the specified name
-     * @throws NamingException
+     * @throws NamingException if a problem occurs while creating the subcontext tree
      */
     protected Context createSubcontextTree(String path, Name name, Object value) throws NamingException
{
         if (path == null) throw new NullPointerException("path is null");
@@ -302,15 +295,99 @@
 
     protected abstract void removeBinding(String name) throws NamingException;
 
-    protected void removeBindings(Name name) throws NamingException {
+    protected void removeDeepBinding(Name name, boolean pruneEmptyContexts) throws NamingException
{
+        if (name == null) throw new NullPointerException("name is null");
+        if (name.isEmpty()) {
+            throw new InvalidNameException("Name is empty");
+        }
+
         if (name.size() == 1) {
             removeBinding(name.get(0));
             return;
         }
 
-        Context context = lookupFinalContext(name);
+        if (!pruneEmptyContexts) {
+            Context context = lookupFinalContext(name);
+            context.unbind(name.getSuffix(name.size() - 1));
+        } else {
+            // we serch the tree for a target context and name to remove
+            // this is normally the last context in the tree and the final name part, but
+            // it may be farther up the path if the intervening nodes are empty
+            Context targetContext = this;
+            String targetName = name.get(0);
+
+            Context currentContext = this;
+            for (int i = 0; i < name.size(); i++) {
+                String part = name.get(i);
+
+                // empty path parts are not allowed
+                if (part.length() == 0) {
+                    throw new InvalidNameException("Name part " + i + " is empty: " + name);
+                }
 
-        context.unbind(name.getSuffix(name.size() - 1));
+                // update targets
+                if (isEmpty(currentContext)) {
+                    targetContext = currentContext;
+                    targetName = part;
+                }
+
+
+                // Is this the last element in the name?
+                if (i == name.size() - 1) {
+                    // we're at the end... unbind value
+                    unbind(targetContext, targetName);
+
+                    // all done... this is redundant but makes the code more readable
+                    break;
+                } else {
+                    Object currentValue = getBinding(currentContext, part);
+                    if (currentValue == null) {
+                        // path not found we are done, but first prune the empty contexts
+                        if (targetContext != currentContext) {
+                            unbind(targetContext, targetName);
+                        }
+                        break;
+                    } else {
+                        // the current value must be a context
+                        if (!(currentValue instanceof Context)) {
+                            throw new NotContextException("Expected an instance of context
to be bound at " +
+                                    part + " but found an instance of " + currentValue.getClass().getName());
+                        }
+                        currentContext = (Context) currentValue;
+                        // now we recurse into the current context
+                    }
+                }
+            }
+        }
+    }
+
+    private static boolean isEmpty(Context context) throws NamingException {
+        if (context instanceof AbstractContext) {
+            AbstractContext abstractContext = (AbstractContext) context;
+            Map currentBindings = abstractContext.getBindings();
+            return currentBindings.size() > 1;
+        } else {
+            NamingEnumeration namingEnumeration = context.list("");
+            return namingEnumeration.hasMore();
+        }
+    }
+
+    /**
+     * Unbinds any value bound to the specified name within the specified context.  If the
specified context is an
+     * AbstractContext and is a nested context, this method will call the direct removeBinding
method, otherwise it
+     * will call public unbind.
+     *
+     * @param context the context to remove the binding from
+     * @param name the binding name
+     * @throws NamingException if a problem occurs while unbinding
+     */
+    private void unbind(Context context, String name) throws NamingException {
+        if (context == this || (context instanceof AbstractContext && isNestedSubcontext(context)))
{
+            AbstractContext abstractContext = (AbstractContext) context;
+            abstractContext.removeBinding(name);
+        } else {
+            context.unbind(name);
+        }
     }
 
     //
@@ -459,7 +536,7 @@
         if (name.isEmpty()) {
             throw new NameAlreadyBoundException("Cannot bind to an empty name (this context)");
         }
-        addDeepBinding(name, obj, false, true);
+        addDeepBinding(name, obj, false, false);
     }
 
     public void rebind(String name, Object obj) throws NamingException {
@@ -472,7 +549,7 @@
         if (name.isEmpty()) {
             throw new NameAlreadyBoundException("Cannot rebind an empty name (this context)");
         }
-        addDeepBinding(name, obj, true, true);
+        addDeepBinding(name, obj, true, false);
     }
 
     public void rename(String oldName, String newName) throws NamingException {
@@ -503,7 +580,7 @@
         if (name.isEmpty()) {
             throw new InvalidNameException("Cannot unbind empty name");
         }
-        removeBindings(name);
+        removeDeepBinding(name, false);
     }
 
     //
@@ -615,7 +692,7 @@
             throw new InvalidNameException("Cannot create a subcontext if the name is empty");
         }
         Context abstractContext = createNestedSubcontext(name.toString(), Collections.EMPTY_MAP);
-        addDeepBinding(name, abstractContext, false, true);
+        addDeepBinding(name, abstractContext, false, false);
         return abstractContext;
     }
 

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractUnmodifiableContext.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractUnmodifiableContext.java?rev=433400&r1=433399&r2=433400&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractUnmodifiableContext.java
(original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/AbstractUnmodifiableContext.java
Mon Aug 21 15:30:24 2006
@@ -18,10 +18,8 @@
 package org.apache.xbean.naming.context;
 
 import javax.naming.Context;
-import javax.naming.InvalidNameException;
 import javax.naming.Name;
 import javax.naming.NamingException;
-import javax.naming.NotContextException;
 import javax.naming.OperationNotSupportedException;
 import java.io.Serializable;
 import java.util.Map;
@@ -40,10 +38,6 @@
         throw new OperationNotSupportedException("Context is read only");
     }
 
-    protected final void removeBindings(Name name) throws NamingException {
-        throw new OperationNotSupportedException("Context is read only");
-    }
-
     //
     //  Lookup Binding
     //
@@ -109,64 +103,6 @@
      */
     protected void removeBinding(String name) throws NamingException {
         throw new OperationNotSupportedException("Context is read only");
-    }
-
-    protected void removeDeepBinding(String name) throws NamingException {
-        if (name == null) throw new NullPointerException("name is null");
-
-        Name compoundName = ContextUtil.parseName(name);
-        if (compoundName.isEmpty()) {
-            throw new InvalidNameException("Name is empty");
-        }
-
-        // we serch the tree for a target context and name to remove
-        // this is normally the last context in the tree and the final name part, but
-        // it may be farther up the path if the intervening nodes are empty
-        AbstractUnmodifiableContext targetContext = this;
-        String targetName = compoundName.get(0);
-
-        AbstractUnmodifiableContext currentContext = this;
-        for (int i = 0; i < compoundName.size(); i++) {
-            String part = compoundName.get(i);
-
-            // empty path parts are not allowed
-            if (part.length() == 0) {
-                throw new InvalidNameException("Name part " + i + " is empty: " + name);
-            }
-
-            Map currentBindings = currentContext.getBindings();
-
-            // update targets
-            if (currentBindings.size() > 1) {
-                targetContext = currentContext;
-                targetName = part;
-            }
-
-
-            // Is this the last element in the name?
-            if (i == compoundName.size() - 1) {
-                // we're at the end... bind the value into the parent context
-                targetContext.removeBinding(targetName);
-
-                // all done... this is redundant but makes the code more readable
-                break;
-            } else {
-                Object currentValue = currentBindings.get(part);
-                if (currentValue == null) {
-                    // path not found we are done
-                    break;
-                } else {
-                    // the current value must be an abstract read only context
-                    // todo this is a problem since a nested node could be an AbstractReadOnlyContext
but not one of our contexts
-                    if (!(currentValue instanceof AbstractUnmodifiableContext)) {
-                        throw new NotContextException("Expected an instance of AbstractReadOnlyContext
to be bound at " +
-                                part + " but found an instance of " + currentValue.getClass().getName());
-                    }
-                    currentContext = (AbstractUnmodifiableContext) currentValue;
-                    // now we recurse into the current context
-                }
-            }
-        }
     }
 
     // ==================================================================================

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ImmutableContext.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ImmutableContext.java?rev=433400&r1=433399&r2=433400&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ImmutableContext.java
(original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ImmutableContext.java
Mon Aug 21 15:30:24 2006
@@ -97,7 +97,11 @@
     }
 
     public boolean isNestedSubcontext(Object value) {
-        return value instanceof NestedImmutableContext;
+        if (value instanceof NestedImmutableContext) {
+            NestedImmutableContext context = (NestedImmutableContext) value;
+            return this == context.getImmutableContext();
+        }
+        return false;
     }
 
     public Context createNestedSubcontext(String path, Map bindings) {
@@ -142,11 +146,19 @@
         }
 
         public boolean isNestedSubcontext(Object value) {
-            return value instanceof NestedImmutableContext;
+            if (value instanceof NestedImmutableContext) {
+                NestedImmutableContext context = (NestedImmutableContext) value;
+                return getImmutableContext() == context.getImmutableContext();
+            }
+            return false;
         }
 
         public Context createNestedSubcontext(String path, Map bindings) {
             return new NestedImmutableContext(path, bindings);
+        }
+
+        private ImmutableContext getImmutableContext() {
+            return ImmutableContext.this;
         }
     }
 }

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=433400&r1=433399&r2=433400&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
Mon Aug 21 15:30:24 2006
@@ -131,7 +131,11 @@
     }
 
     public boolean isNestedSubcontext(Object value) {
-        return value instanceof NestedUnmodifiableContext;
+        if (value instanceof NestedUnmodifiableContext) {
+            NestedUnmodifiableContext context = (NestedUnmodifiableContext) value;
+            return this == context.getUnmodifiableContext();
+        }
+        return false;
     }
 
     public Context createNestedSubcontext(String path, Map bindings) {
@@ -189,7 +193,11 @@
         }
 
         public boolean isNestedSubcontext(Object value) {
-            return value instanceof NestedUnmodifiableContext;
+            if (value instanceof NestedUnmodifiableContext) {
+                NestedUnmodifiableContext context = (NestedUnmodifiableContext) value;
+                return getUnmodifiableContext() == context.getUnmodifiableContext();
+            }
+            return false;
         }
 
         public Context createNestedSubcontext(String path, Map bindings) {
@@ -240,6 +248,10 @@
             } finally {
                 writeLock.unlock();
             }
+        }
+
+        private UnmodifiableContext getUnmodifiableContext() {
+            return UnmodifiableContext.this;
         }
     }
 }

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=433400&r1=433399&r2=433400&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
Mon Aug 21 15:30:24 2006
@@ -39,7 +39,7 @@
     }
 
     public boolean isNestedSubcontext(Object value) {
-        return value instanceof WritableContext;
+        return false;
     }
 
     public Context createNestedSubcontext(String path, Map bindings) {

Modified: geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/UnmodifiableContextTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/UnmodifiableContextTest.java?rev=433400&r1=433399&r2=433400&view=diff
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/UnmodifiableContextTest.java
(original)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/UnmodifiableContextTest.java
Mon Aug 21 15:30:24 2006
@@ -38,8 +38,8 @@
             super.addDeepBinding(name, value, rebind, createIntermediateContexts);
         }
 
-        public void removeDeepBinding(String name) throws NamingException {
-            super.removeDeepBinding(name);
+        protected void removeDeepBinding(Name name, boolean pruneEmptyContexts) throws NamingException
{
+            super.removeDeepBinding(name, pruneEmptyContexts);
         }
     }
 
@@ -100,13 +100,14 @@
 
         // remove from an exisitng node
         map.remove("a/b/c/d/e/three");
-        context.removeDeepBinding("a/b/c/d/e/three");
+        NameParser parser = context.getNameParser();
+        context.removeDeepBinding(parser.parse("a/b/c/d/e/three"), true);
 
         assertEq(map, context);
 
         // remove a deep single element element... empty nodes should be removed
         map.remove("nested/context/string");
-        context.removeDeepBinding("nested/context/string");
+        context.removeDeepBinding(parser.parse("nested/context/string"), true);
 
         assertEq(map, context);
     }



Mime
View raw message