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/24 02:07:34 UTC

svn commit: r434258 - 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 17:07:33 2006
New Revision: 434258

URL: http://svn.apache.org/viewvc?rev=434258&view=rev
Log:
Added ContextAccessControlList which supports deny,allow and allow,deny access control.
Added tests for mutability of contexts and ACLs

Added:
    geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextAccessControlList.java
    geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/ContextAccessControlListTest.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/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=434258&r1=434257&r2=434258&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 17:07:33 2006
@@ -630,9 +630,7 @@
             throw new NullPointerException("name is null");
         } else if (oldName.isEmpty() || newName.isEmpty()) {
             throw new InvalidNameException("Name cannot be empty");
-        } else if (this.lookup(newName) != null) {
-            throw new NameAlreadyBoundException("The target name is already bound");
-        }
+        } 
         this.bind(newName, this.lookup(oldName));
         this.unbind(oldName);
     }

Added: geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextAccessControlList.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextAccessControlList.java?rev=434258&view=auto
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextAccessControlList.java (added)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/main/java/org/apache/xbean/naming/context/ContextAccessControlList.java Wed Aug 23 17:07:33 2006
@@ -0,0 +1,98 @@
+/**
+ *
+ * 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.Name;
+import javax.naming.NamingException;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Collections;
+import java.util.ArrayList;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ContextAccessControlList implements ContextAccess {
+    private final boolean defaultAllow;
+    private final List allow;
+    private final List deny;
+
+    public ContextAccessControlList(boolean defaultAllow, List allow, List deny) {
+        this.defaultAllow = defaultAllow;
+        this.allow = toACL(allow);
+        this.deny = toACL(deny);
+    }
+
+    private List toACL(List input) {
+        if (input == null) return Collections.EMPTY_LIST;
+        
+        ArrayList list = new ArrayList(input.size());
+        for (Iterator iterator = input.iterator(); iterator.hasNext();) {
+            Object value = iterator.next();
+            if (value instanceof Name) {
+                list.add(value);
+            } else if (value instanceof String) {
+                String string = (String) value;
+                Name name = null;
+                try {
+                    name = ContextUtil.NAME_PARSER.parse(string);
+                } catch (NamingException e) {
+                    throw new IllegalArgumentException("error while parsing name: " + value);
+                }
+                list.add(name);
+            } else {
+                throw new IllegalArgumentException("name is not an instance of Name or String: " + value);
+            }
+        }
+        return Collections.unmodifiableList(list);
+    }
+
+    public boolean isModifiable(Name name) {
+        if (name == null) throw new NullPointerException("name is null");
+        if (defaultAllow) {
+            // allow by default, so allow if it wasn't explicitly denied or was explicitly allowed
+            return !isDenied(name) || isAllowed(name);
+        } else {
+            // deny by default, so allow if it was explicitly allowed or wasn't explicitly denied
+            return isAllowed(name) && !isDenied(name);
+        }
+    }
+
+    protected boolean isAllowed(Name name) {
+        if (name == null) throw new NullPointerException("name is null");
+        for (Iterator iterator = allow.iterator(); iterator.hasNext();) {
+            Name prefix = (Name) iterator.next();
+            if (name.startsWith(prefix)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    protected boolean isDenied(Name name) {
+        if (name == null) throw new NullPointerException("name is null");
+        for (Iterator iterator = deny.iterator(); iterator.hasNext();) {
+            Name prefix = (Name) iterator.next();
+            if (name.startsWith(prefix)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}

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=434258&r1=434257&r2=434258&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 17:07:33 2006
@@ -122,12 +122,13 @@
         removeBinding(bindingsRef, name);
     }
 
-    private void removeBinding(AtomicReference bindingsRef, String name) throws NameNotFoundException {
+    private void removeBinding(AtomicReference bindingsRef, String name) {
         writeLock.lock();
         try {
             Map bindings = (Map) bindingsRef.get();
             if (!bindings.containsKey(name)) {
-                throw new NameNotFoundException(name);
+                // remove is idempotent meaning remove succeededs even if there was no value bound
+                return;
             }
 
             Map newBindings = new HashMap(bindings);

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=434258&r1=434257&r2=434258&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 17:07:33 2006
@@ -31,6 +31,9 @@
  * @version $Rev$ $Date$
  */
 public abstract class AbstractContextTest extends TestCase {
+    public static Name parse(String name) throws NamingException {
+        return ContextUtil.NAME_PARSER.parse(name);
+    }
     public static void assertEq(Map expected, Context actual) throws NamingException {
         AbstractContextTest.assertEq(ContextUtil.buildMapTree(expected), actual, actual, null);
     }
@@ -148,6 +151,83 @@
         }
     }
 
+    public static Context lookupSubcontext(Context context, String name) throws NamingException {
+        Object value = context.lookup(name);
+        assertTrue("Expected an instance of Context from look up of " + name + " in context " + context.getNameInNamespace(),
+                value instanceof Context);
+        return (Context) value;
+    }
+
+    public static void assertHasBinding(Context context, String name) {
+        String nameInNamespace = null;
+        try {
+            nameInNamespace = context.getNameInNamespace();
+        } catch (NamingException e) {
+            throw new RuntimeException("getNameInNamespace threw a NamingException", e);
+        }
+
+        try {
+            Object value = context.lookup(name);
+            if (value != null) {
+                fail("Lookup of " + name + " on context " + nameInNamespace + " return null");
+            }
+        } catch (NamingException e) {
+            fail("Lookup of " + name + " on context " + nameInNamespace + " threw " + e.getClass().getName());
+        }
+    }
+
+    public static void assertHasBinding(Context context, Name name) {
+        String nameInNamespace = null;
+        try {
+            nameInNamespace = context.getNameInNamespace();
+        } catch (NamingException e) {
+            throw new RuntimeException("getNameInNamespace threw a NamingException", e);
+        }
+
+        try {
+            Object value = context.lookup(name);
+            if (value != null) {
+                fail("Lookup of " + name + " on context " + nameInNamespace + " return null");
+            }
+        } catch (NamingException e) {
+            fail("Lookup of " + name + " on context " + nameInNamespace + " threw " + e.getClass().getName());
+        }
+    }
+
+    public static void assertNoBinding(Context context, String name) {
+        String nameInNamespace = null;
+        try {
+            nameInNamespace = context.getNameInNamespace();
+        } catch (NamingException e) {
+            throw new RuntimeException("getNameInNamespace threw a NamingException", e);
+        }
+
+        try {
+            Object value = context.lookup(name);
+            if (value == null) {
+                fail("Context " + nameInNamespace + " has a binding for " + name);
+            }
+        } catch (NamingException expected) {
+        }
+    }
+
+    public static void assertNoBinding(Context context, Name name) {
+        String nameInNamespace = null;
+        try {
+            nameInNamespace = context.getNameInNamespace();
+        } catch (NamingException e) {
+            throw new RuntimeException("getNameInNamespace threw a NamingException", e);
+        }
+
+        try {
+            Object value = context.lookup(name);
+            if (value == null) {
+                fail("Context " + nameInNamespace + " has a binding for " + name);
+            }
+        } catch (NamingException expected) {
+        }
+    }
+
     public static void assertUnmodifiable(Context context) throws Exception {
         Object value = "VALUE";
         String nameString = "TEST_NAME";
@@ -244,5 +324,89 @@
             fail("Expected an OperationNotSupportedException");
         } catch(OperationNotSupportedException expected) {
         }
+    }
+
+    public static void assertModifiable(Context context) throws Exception {
+        Object value = "VALUE";
+        Object newValue = "NEW_VALUE";
+
+        String nameString = "TEST_NAME";
+        Name name = context.getNameParser("").parse(nameString);
+
+        String newNameString = "NEW_TEST_NAME";
+        Name newName = context.getNameParser("").parse(newNameString);
+
+        assertNoBinding(context, nameString);
+        assertNoBinding(context, name);
+
+        //
+        // bind / unbind
+        //
+        context.bind(nameString, value);
+        assertSame(value, context.lookup(nameString));
+        context.unbind(nameString);
+
+        assertNoBinding(context, nameString);
+
+        context.bind(name, value);
+        assertSame(value, context.lookup(name));
+        context.unbind(name);
+
+        assertNoBinding(context, name);
+
+        //
+        // rebind
+        //
+        context.bind(nameString, value);
+        assertSame(value, context.lookup(nameString));
+        context.rebind(nameString, newValue);
+        assertSame(newValue, context.lookup(nameString));
+        context.unbind(nameString);
+
+        assertNoBinding(context, nameString);
+
+        context.bind(name, value);
+        assertSame(value, context.lookup(name));
+        context.rebind(name, newValue);
+        assertSame(newValue, context.lookup(name));
+        context.unbind(name);
+
+        assertNoBinding(context, name);
+
+        //
+        // rename
+        //
+        context.bind(nameString, value);
+        assertSame(value, context.lookup(nameString));
+        context.rename(nameString, newNameString);
+        assertSame(value, context.lookup(newNameString));
+        assertNoBinding(context, nameString);
+        context.unbind(nameString);
+
+        assertNoBinding(context, nameString);
+
+        context.bind(name, value);
+        assertSame(value, context.lookup(name));
+        context.rename(name, newName);
+        assertSame(value, context.lookup(newName));
+        assertNoBinding(context, name);
+        context.unbind(name);
+
+        assertNoBinding(context, name);
+
+        //
+        // createSubcontext / destroySubcontext
+        //
+        context.createSubcontext(nameString);
+        assertTrue(context.lookup(nameString) instanceof Context);
+        context.destroySubcontext(nameString);
+
+        assertNoBinding(context, nameString);
+
+        context.createSubcontext(name);
+        assertTrue(context.lookup(name) instanceof Context);
+        context.destroySubcontext(name);
+
+        assertNoBinding(context, name);
     }
 }

Added: geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/ContextAccessControlListTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/ContextAccessControlListTest.java?rev=434258&view=auto
==============================================================================
--- geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/ContextAccessControlListTest.java (added)
+++ geronimo/xbean/branches/colossus/xbean-naming/src/test/java/org/apache/xbean/naming/context/ContextAccessControlListTest.java Wed Aug 23 17:07:33 2006
@@ -0,0 +1,228 @@
+/**
+ *
+ * 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 java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @version $Rev: 355877 $ $Date: 2005-12-10 18:48:27 -0800 (Sat, 10 Dec 2005) $
+ */
+public class ContextAccessControlListTest extends AbstractContextTest {
+    private ContextAccessControlList allowDenyACL;
+    private ContextAccessControlList denyAllowACL;
+    private Context allowDenyContext;
+    private WritableContext denyAllowContext;
+
+    public void testAllowDeny() throws Exception {
+        // outside of listed
+        assertTrue(allowDenyACL.isModifiable(parse("foo")));
+
+        // explicitly allowed
+        assertTrue(allowDenyACL.isModifiable(parse("allow")));
+
+        // child of explicitly allowed
+        assertTrue(allowDenyACL.isModifiable(parse("allow/foo")));
+
+        // explicitly denied
+        assertFalse(allowDenyACL.isModifiable(parse("deny")));
+
+        // child of explicitly denied
+        assertFalse(allowDenyACL.isModifiable(parse("deny/foo")));
+
+        // parent of denied
+        assertTrue(allowDenyACL.isModifiable(parse("a/b")));
+        assertTrue(allowDenyACL.isModifiable(parse("one/two")));
+
+        // explicitly denied
+        assertFalse(allowDenyACL.isModifiable(parse("a/b/c")));
+        assertFalse(allowDenyACL.isModifiable(parse("one/two/three")));
+
+        // child of denied
+        assertFalse(allowDenyACL.isModifiable(parse("a/b/c/foo")));
+        assertFalse(allowDenyACL.isModifiable(parse("one/two/three/foo")));
+        assertFalse(allowDenyACL.isModifiable(parse("a/b/c/d")));
+        assertFalse(allowDenyACL.isModifiable(parse("one/two/three/four")));
+
+        // deny override
+        assertTrue(allowDenyACL.isModifiable(parse("a/b/c/d/e")));
+        assertTrue(allowDenyACL.isModifiable(parse("one/two/three/four/five")));
+
+        // child of deny override
+        assertTrue(allowDenyACL.isModifiable(parse("a/b/c/d/e/foo")));
+        assertTrue(allowDenyACL.isModifiable(parse("one/two/three/four/five/foo")));
+    }
+
+    public void testDenyAllow() throws Exception {
+        // outside of listed
+        assertFalse(denyAllowACL.isModifiable(parse("foo")));
+
+        // explicitly allowed
+        assertTrue(denyAllowACL.isModifiable(parse("allow")));
+
+        // child of explicitly allowed
+        assertTrue(denyAllowACL.isModifiable(parse("allow/foo")));
+
+        // explicitly denied
+        assertFalse(denyAllowACL.isModifiable(parse("deny")));
+
+        // child of explicitly denied
+        assertFalse(denyAllowACL.isModifiable(parse("deny/foo")));
+
+        // parent of allowed
+        assertFalse(denyAllowACL.isModifiable(parse("a/b")));
+        assertFalse(denyAllowACL.isModifiable(parse("one/two")));
+
+        // explicitly allowed
+        assertTrue(denyAllowACL.isModifiable(parse("a/b/c")));
+        assertTrue(denyAllowACL.isModifiable(parse("one/two/three")));
+
+        // child of allowed
+        assertTrue(denyAllowACL.isModifiable(parse("a/b/c/foo")));
+        assertTrue(denyAllowACL.isModifiable(parse("one/two/three/foo")));
+        assertTrue(denyAllowACL.isModifiable(parse("a/b/c/d")));
+        assertTrue(denyAllowACL.isModifiable(parse("one/two/three/four")));
+
+        // allow override
+        assertFalse(denyAllowACL.isModifiable(parse("a/b/c/d/e")));
+        assertFalse(denyAllowACL.isModifiable(parse("one/two/three/four/five")));
+
+        // children of allow override
+        assertFalse(denyAllowACL.isModifiable(parse("a/b/c/d/e/foo")));
+        assertFalse(denyAllowACL.isModifiable(parse("one/two/three/four/five/foo")));
+    }
+
+    public void testAllowDenyContext() throws Exception {
+        // outside of listed
+        assertModifiable(lookupSubcontext(allowDenyContext, "foo"));
+
+        // explicitly allowed
+        assertModifiable(lookupSubcontext(allowDenyContext, "allow"));
+
+        // child of explicitly allowed
+        assertModifiable(lookupSubcontext(allowDenyContext, "allow/foo"));
+
+        // explicitly denied
+        assertUnmodifiable(lookupSubcontext(allowDenyContext, "deny"));
+
+        // child of explicitly denied
+        assertUnmodifiable(lookupSubcontext(allowDenyContext, "deny/foo"));
+
+        // parent of denied
+        assertModifiable(lookupSubcontext(allowDenyContext, "a/b"));
+        assertModifiable(lookupSubcontext(allowDenyContext, "one/two"));
+
+        // explicitly denied
+        assertUnmodifiable(lookupSubcontext(allowDenyContext, "a/b/c"));
+        assertUnmodifiable(lookupSubcontext(allowDenyContext, "one/two/three"));
+
+        // child of denied
+        assertUnmodifiable(lookupSubcontext(allowDenyContext, "a/b/c/foo"));
+        assertUnmodifiable(lookupSubcontext(allowDenyContext, "one/two/three/foo"));
+        assertUnmodifiable(lookupSubcontext(allowDenyContext, "a/b/c/d"));
+        assertUnmodifiable(lookupSubcontext(allowDenyContext, "one/two/three/four"));
+
+        // deny override
+        assertModifiable(lookupSubcontext(allowDenyContext, "a/b/c/d/e"));
+        assertModifiable(lookupSubcontext(allowDenyContext, "one/two/three/four/five"));
+
+        // child of deny override
+        assertModifiable(lookupSubcontext(allowDenyContext, "a/b/c/d/e/foo"));
+        assertModifiable(lookupSubcontext(allowDenyContext, "one/two/three/four/five/foo"));
+    }
+
+    public void testDenyAllowContext() throws Exception {
+        // outside of listed
+        assertUnmodifiable(lookupSubcontext(denyAllowContext, "foo"));
+
+        // explicitly allowed
+        assertModifiable(lookupSubcontext(denyAllowContext, "allow"));
+
+        // child of explicitly allowed
+        assertModifiable(lookupSubcontext(denyAllowContext, "allow/foo"));
+
+        // explicitly denied
+        assertUnmodifiable(lookupSubcontext(denyAllowContext, "deny"));
+
+        // child of explicitly denied
+        assertUnmodifiable(lookupSubcontext(denyAllowContext, "deny/foo"));
+
+        // parent of allowed
+        assertUnmodifiable(lookupSubcontext(denyAllowContext, "a/b"));
+        assertUnmodifiable(lookupSubcontext(denyAllowContext, "one/two"));
+
+        // explicitly allowed
+        assertModifiable(lookupSubcontext(denyAllowContext, "a/b/c"));
+        assertModifiable(lookupSubcontext(denyAllowContext, "one/two/three"));
+
+        // child of allowed
+        assertModifiable(lookupSubcontext(denyAllowContext, "a/b/c/foo"));
+        assertModifiable(lookupSubcontext(denyAllowContext, "one/two/three/foo"));
+        assertModifiable(lookupSubcontext(denyAllowContext, "a/b/c/d"));
+        assertModifiable(lookupSubcontext(denyAllowContext, "one/two/three/four"));
+
+        // allow override
+        assertUnmodifiable(lookupSubcontext(denyAllowContext, "a/b/c/d/e"));
+        assertUnmodifiable(lookupSubcontext(denyAllowContext, "one/two/three/four/five"));
+
+        // children of allow override
+        assertUnmodifiable(lookupSubcontext(denyAllowContext, "a/b/c/d/e/foo"));
+        assertUnmodifiable(lookupSubcontext(denyAllowContext, "one/two/three/four/five/foo"));
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        allowDenyACL = new ContextAccessControlList(true,
+                Arrays.asList(new String[]{"allow", "a/b/c/d/e", "one/two/three/four/five"}),
+                Arrays.asList(new String[]{"deny", "a/b/c", "one/two/three"}));
+
+        denyAllowACL = new ContextAccessControlList(false,
+                Arrays.asList(new String[]{"allow", "a/b/c", "one/two/three"}),
+                Arrays.asList(new String[]{"deny", "a/b/c/d/e", "one/two/three/four/five"}));
+
+
+        Map map = new HashMap();
+
+        // outside of listed
+        map.put("foo/value", "bar");
+
+        // explicitly allowed
+        map.put("allow/foo/cheese", "cheddar");
+
+        // explicitly denied
+        map.put("deny/foo/cheese", "american");
+
+        // child of denied
+        map.put("a/b/c/foo/value", "bar");
+        map.put("one/two/three/foo/value", "bar");
+
+        // child of deny override
+        map.put("a/b/c/d/e/foo/value", "bar");
+        map.put("one/two/three/four/five/foo/value", "bar");
+
+        allowDenyContext = new WritableContext("", map, allowDenyACL);
+        assertEq(map, allowDenyContext);
+
+        denyAllowContext = new WritableContext("", map, denyAllowACL);
+        assertEq(map, denyAllowContext);
+    }
+
+}