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