You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ck...@apache.org on 2007/07/23 22:02:03 UTC

svn commit: r558849 [3/6] - in /directory/triplesec/trunk: admin-api/ admin-api/src/test/java/org/apache/directory/triplesec/admin/ admin-api/src/test/resources/ guardian-api/src/main/java/org/apache/ guardian-api/src/main/java/org/apache/directory/ gu...

Added: directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/RoleTest.java
URL: http://svn.apache.org/viewvc/directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/RoleTest.java?view=auto&rev=558849
==============================================================================
--- directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/RoleTest.java (added)
+++ directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/RoleTest.java Mon Jul 23 13:01:54 2007
@@ -0,0 +1,333 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.directory.triplesec.guardian;
+
+
+import java.security.AccessControlException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+
+
+
+/**
+ * @author <a href="mailto:akarasulu@safehaus.org">Alex Karasulu</a>
+ * @version $Rev: 74 $
+ */
+public class RoleTest extends AbstractEntityTest
+{
+    private static final ApplicationPolicy STORE1 = new TestApplicationPolicyStore(
+            "app1" );
+
+    private static final ApplicationPolicy STORE2 = new TestApplicationPolicyStore(
+            "app2" );
+
+    protected Object newInstanceA1()
+    {
+        return new Role( STORE1, "role1", null );
+    }
+
+    protected Object newInstanceA2()
+    {
+        return new Role( STORE1, "role1", null );
+    }
+
+    protected Object newInstanceB1()
+    {
+        return new Role( STORE1, "role2", null );
+    }
+
+    protected Object newInstanceB2()
+    {
+        return new Role( STORE2, "role1", null );
+    }
+
+    public void testInstantiation()
+    {
+        Permissions perms = new Permissions( "app1", null );
+
+        // Test null parameters
+        try
+        {
+            new Role( null, "role1", perms );
+            fail( "Execption is not thrown." );
+        }
+        catch( NullPointerException e )
+        {
+            // OK
+        }
+        try
+        {
+            new Role( STORE1, null, perms );
+            fail( "Execption is not thrown." );
+        }
+        catch( NullPointerException e )
+        {
+            // OK
+        }
+
+        // Test empty fields
+        try
+        {
+            new Role( STORE2, "", perms );
+            fail( "Execption is not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // OK
+        }
+        try
+        {
+            new Role( new TestApplicationPolicyStore( "" ), "role1", perms );
+            fail( "Execption is not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // OK
+        }
+        
+        // Test unknown permissions
+        try
+        {
+            Permissions wrongPerms = new Permissions( "app1", new Permission[] {
+                    new Permission( "app1", "wrongPerm" ),
+            });
+                                                                             
+            new Role( STORE1, "role1", wrongPerms );
+            fail( "Execption is not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // OK
+        }
+        
+
+        // Test mismatching application names.
+        try
+        {
+            new Role( STORE2, "role1", perms );
+            fail( "Execption is not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // OK
+        }
+
+        Role r = new Role( STORE1, "role1", null );
+        assertEquals( 0, r.getGrants().size() );
+    }
+
+    public void testProperties()
+    {
+        Permission perm1= new Permission( "app1", "perm1" );
+        Permissions perms = new Permissions( "app1", new Permission[] {
+                perm1,
+                new Permission( "app1", "perm2" ),
+                new Permission( "app1", "perm3" ), } );
+
+        Role r = new Role( STORE1, "role1", perms, "test description" );
+        assertEquals( "app1", r.getApplicationName() );
+        assertEquals( "role1", r.getName() );
+        assertEquals( perms, r.getGrants() );
+        assertEquals( "test description", r.getDescription() );
+        assertTrue( r.hasPermission( perm1 ) ) ;
+        assertTrue( r.hasPermission( perm1.getName() ) ) ;
+    }
+
+    public void testRolePermissions()
+    {
+        Permission perm = new Permission( "app1", "perm1" );
+        Permission wrongPerm = new Permission( "app1", "perm2" );
+        Permissions perms = new Permissions( "app1", new Permission[] { perm, } );
+
+        Role r = new Role( STORE1, "role1", perms );
+
+        // Check existing permissions
+        r.checkPermission( perm );
+        assertTrue( r.hasPermission( perm.getName() ) );
+        assertTrue( r.hasPermission( perm ) );
+        r.checkPermission( perm, "unused" );
+        r.checkPermission( perm.getName() );
+        r.checkPermission( perm.getName(), "unused" );
+
+        // Check null parameters
+        try
+        {
+            r.checkPermission( ( Permission ) null );
+            fail( "Exception is not thrown." );
+        }
+        catch( NullPointerException e )
+        {
+            // OK
+        }
+        try
+        {
+            r.checkPermission( ( String ) null );
+            fail( "Exception is not thrown." );
+        }
+        catch( NullPointerException e )
+        {
+            // OK
+        }
+        try
+        {
+            r.checkPermission( ( Permission ) null, "unused" );
+            fail( "Exception is not thrown." );
+        }
+        catch( NullPointerException e )
+        {
+            // OK
+        }
+        try
+        {
+            r.checkPermission( ( String ) null, "unused" );
+            fail( "Exception is not thrown." );
+        }
+        catch( NullPointerException e )
+        {
+            // OK
+        }
+
+        // Check non-existing permissions
+        try
+        {
+            r.checkPermission( wrongPerm );
+            fail( "Exception is not thrown." );
+        }
+        catch( AccessControlException e )
+        {
+            // OK
+        }
+        try
+        {
+            r.checkPermission( wrongPerm, "unused" );
+            fail( "Exception is not thrown." );
+        }
+        catch( AccessControlException e )
+        {
+            // OK
+        }
+        try
+        {
+            r.checkPermission( wrongPerm.getName() );
+            fail( "Exception is not thrown." );
+        }
+        catch( AccessControlException e )
+        {
+            // OK
+        }
+        try
+        {
+            r.checkPermission( wrongPerm.getName(), "unused" );
+            fail( "Exception is not thrown." );
+        }
+        catch( AccessControlException e )
+        {
+            // OK
+        }
+    }
+    
+    
+    
+    protected void _testClone( Object a, Object b )
+    {
+        Role ra = ( Role ) a;
+        Role rb = ( Role ) b;
+        assertEquals( ra.getGrants(), rb.getGrants() );
+    }
+
+    private static class TestApplicationPolicyStore implements
+            ApplicationPolicy
+    {
+        private final String appName;
+
+        public TestApplicationPolicyStore( String appName )
+        {
+            this.appName = appName;
+        }
+
+        public String getApplicationName()
+        {
+            return appName;
+        }
+
+        public Roles getRoles()
+        {
+            return null;
+        }
+
+        public Permissions getPermissions()
+        {
+            Permission[] perms = new Permission[] {
+                    new Permission( appName, "perm1" ),
+                    new Permission( appName, "perm2" ),
+                    new Permission( appName, "perm3" ),
+            };
+            return new Permissions( appName, perms );
+        }
+
+        public Profile getProfile( String userName )
+        {
+            return null;
+        }
+
+        public String getDescription()
+        {
+            return null;
+        }
+
+        public void close() {}
+
+        public boolean removePolicyListener( PolicyChangeListener listener )
+        {
+            return false;
+        }
+
+        public boolean addPolicyListener( PolicyChangeListener listener )
+        {
+            return false;
+        }
+
+        public Set getDependentProfileNames( Role role ) throws GuardianException
+        {
+            return null;
+        }
+
+        public Set getDependentProfileNames( Permission permission ) throws GuardianException
+        {
+            return null;
+        }
+
+        public Set getUserProfileIds( String userName ) throws GuardianException
+        {
+            return Collections.EMPTY_SET;
+        }
+
+        public Iterator getProfileIdIterator() throws GuardianException
+        {
+            return null;
+        }
+
+        public Profile getAdminProfile()
+        {
+            return null;
+        }
+    }
+}

Added: directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/RolesTest.java
URL: http://svn.apache.org/viewvc/directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/RolesTest.java?view=auto&rev=558849
==============================================================================
--- directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/RolesTest.java (added)
+++ directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/RolesTest.java Mon Jul 23 13:01:54 2007
@@ -0,0 +1,337 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.directory.triplesec.guardian;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+
+import junit.framework.Assert;
+
+
+/**
+ * 
+ *
+ * @author Trustin Lee
+ * @version $Rev: 72 $, $Date: 2005-11-07 21:37:46 -0500 (Mon, 07 Nov 2005) $
+ */
+public class RolesTest extends AbstractEntityTest
+{
+    private static final ApplicationPolicy STORE1 = new TestApplicationPolicyStore(
+            "app1" );
+
+    private static final ApplicationPolicy STORE2 = new TestApplicationPolicyStore(
+            "app2" );
+
+    protected Object newInstanceA1()
+    {
+        return new Roles( "app1", new Role[] {
+                new Role( STORE1, "role1", null ),
+                new Role( STORE1, "role2", null ),
+                new Role( STORE1, "role3", null ),
+        });
+    }
+
+    protected Object newInstanceA2()
+    {
+        return new Roles( "app1", new Role[] {
+                new Role( STORE1, "role1", null ),
+                new Role( STORE1, "role2", null ),
+                new Role( STORE1, "role3", null ),
+        });
+    }
+
+    protected Object newInstanceB1()
+    {
+        return new Roles( "app1", new Role[] {
+                new Role( STORE1, "role1", null ),
+        });
+    }
+
+    protected Object newInstanceB2()
+    {
+        return new Roles( "app2", null );
+    }
+    
+    public void testInstantiation()
+    {
+        // Test null values
+        try
+        {
+            new Roles( null, null );
+            Assert.fail( "Execption is not thrown." );
+        }
+        catch( NullPointerException e )
+        {
+            // OK
+        }
+        
+        // Test empty values
+        try
+        {
+            new Roles( "", null );
+            Assert.fail( "Execption is not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // OK
+        }
+        
+        // Test null elements
+        Roles roles = new Roles( "app1", new Role[] {
+                null, null, null,
+        });
+        Assert.assertTrue( roles.isEmpty() );
+        
+        // Test mismatching application names
+        try
+        {
+            new Roles( "app1", new Role[] {
+                    new Role( STORE2, "role1", null ),
+            });
+            Assert.fail( "Execption is not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            //OK
+        }
+        
+        Assert.assertTrue( roles.isEmpty() );
+    }
+    
+    public void testProperties()
+    {
+        Role r1 = new Role( STORE1, "role1", null );
+        Role r2 = new Role( STORE1, "role2", null );
+        Role r3 = new Role( STORE1, "role3", null );
+        Roles roles = new Roles( "app1", new Role[] {
+                r1, r2, r3,
+        });
+        
+        Assert.assertEquals( "app1", roles.getApplicationName() );
+        Assert.assertEquals( 3, roles.size() );
+        Assert.assertTrue( roles.contains( r1 ) );
+        Assert.assertTrue( roles.contains( r2 ) );
+        Assert.assertTrue( roles.contains( r3 ) );
+        Assert.assertTrue( roles.contains( r1.getName() ) );
+        Assert.assertTrue( roles.contains( r2.getName() ) );
+        Assert.assertTrue( roles.contains( r3.getName() ) );
+        Assert.assertEquals( r1, roles.get( r1.getName() ) );
+        Assert.assertEquals( r2, roles.get( r2.getName() ) );
+        Assert.assertEquals( r3, roles.get( r3.getName() ) );
+        
+        // Test iterator integrity
+        Set allRoles = new HashSet();
+        allRoles.add( r1 );
+        allRoles.add( r2 );
+        allRoles.add( r3 );
+        for( Iterator i = roles.iterator(); i.hasNext(); )
+        {
+            Role p = ( Role ) i.next();
+            Assert.assertTrue( allRoles.contains( p ) );
+            allRoles.remove( p );
+        }
+    }
+    
+    public void testSetOperations()
+    {
+        Roles roles1 = new Roles( "app1", new Role[] {
+                new Role( STORE1, "role1", null ),
+        });
+        Roles roles2 = new Roles( "app1", new Role[] {
+                new Role( STORE1, "role2", null ),
+        });
+        Roles roles12 = new Roles( "app1", new Role[] {
+                new Role( STORE1, "role1", null ),
+                new Role( STORE1, "role2", null ),
+        });
+        Roles wrongRoles = new Roles( "wrongApp", null );
+        
+        
+        // addAll
+        Assert.assertEquals( roles12, roles1.addAll( roles2 ) );
+        Assert.assertEquals( roles1, roles1.addAll( roles1 ) );
+        try
+        {
+            roles1.addAll( wrongRoles );
+            Assert.fail( "Exception is not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // OK
+        }
+        
+        // removeAll
+        Assert.assertEquals( roles1, roles12.removeAll( roles2 ) );
+        Assert.assertEquals( roles1, roles1.removeAll( roles2 ) );
+        try
+        {
+            roles1.removeAll( wrongRoles );
+            Assert.fail( "Exception is not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // OK
+        }
+        
+        // retainAll
+        Assert.assertEquals( roles1, roles12.retainAll( roles1 ) );
+        Assert.assertEquals(
+                new Roles( "role1", null ), roles1.retainAll( roles2 ) );
+        try
+        {
+            roles1.retainAll( wrongRoles );
+            Assert.fail( "Exception is not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // OK
+        }
+
+        // containsAll
+        Assert.assertTrue( roles12.containsAll( roles12 ) );
+        Assert.assertFalse( roles1.containsAll( roles12 ) );
+        try
+        {
+            roles1.containsAll( wrongRoles );
+            Assert.fail( "Exception is not thrown." );
+        }
+        catch( IllegalArgumentException e )
+        {
+            // OK
+        }
+    }
+    
+    
+    public void testGetDependentRoles()
+    {
+        Role role1 = new Role( STORE1, "role1", STORE1.getPermissions() );
+        Role role2 = new Role( STORE1, "role2", null );
+        Roles roles12 = new Roles( "app1", new Role[] { role1, role2 });
+
+        Roles dependents = roles12.getDependentRoles( "perm1" );
+        assertEquals( 1, dependents.size() );
+        assertEquals( role1, dependents.get( "role1" ) );
+        
+        dependents = roles12.getDependentRoles( STORE1.getPermissions().get( "perm1" ) );
+        assertEquals( 1, dependents.size() );
+        assertEquals( role1, dependents.get( "role1" ) );
+
+        dependents = roles12.getDependentRoles( "perm99" );
+        assertEquals( 0, dependents.size() );
+
+        dependents = roles12.getDependentRoles( new Permission( "app1", "perm99" ) );
+        assertEquals( 0, dependents.size() );
+        
+        try
+        {
+            dependents = roles12.getDependentRoles( new Permission( "blah", "perm99" ) );
+            fail( "Should never get here due to an exception" );
+        }
+        catch ( IllegalArgumentException e )
+        {
+        }
+    }
+    
+    
+    public static void main( String[] args )
+    {
+        junit.textui.TestRunner.run( RolesTest.class );
+    }
+
+    private static class TestApplicationPolicyStore implements ApplicationPolicy
+    {
+        private final String appName;
+        
+        public TestApplicationPolicyStore( String appName )
+        {
+            this.appName = appName;
+        }
+        
+        public String getApplicationName()
+        {
+            return appName;
+        }
+        
+        public Roles getRoles()
+        {
+            return null;
+        }
+        
+        public Permissions getPermissions()
+        {
+            Permission[] perms = new Permission[] {
+                    new Permission( appName, "perm1" ),
+                    new Permission( appName, "perm2" ),
+                    new Permission( appName, "perm3" ),
+            };
+            return new Permissions( appName, perms );
+        }
+        
+        public Profile getProfile( String userName )
+        {
+            return null;
+        }
+
+        public String getDescription()
+        {
+            return null;
+        }
+
+        public void close() {}
+
+        public boolean removePolicyListener( PolicyChangeListener listener )
+        {
+            return false;
+        }
+
+        public boolean addPolicyListener( PolicyChangeListener listener )
+        {
+            return false;
+        }
+
+        public Set getDependentProfileNames( Role role ) throws GuardianException
+        {
+            return null;
+        }
+
+        public Set getDependentProfileNames( Permission permission ) throws GuardianException
+        {
+            return null;
+        }
+
+        public Set getUserProfileIds( String userName ) throws GuardianException
+        {
+            return Collections.EMPTY_SET;
+        }
+
+        public Iterator getProfileIdIterator() throws GuardianException
+        {
+            return null;
+        }
+
+        public Profile getAdminProfile()
+        {
+            return null;
+        }
+    }
+}

Added: directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockApplicationPolicy.java
URL: http://svn.apache.org/viewvc/directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockApplicationPolicy.java?view=auto&rev=558849
==============================================================================
--- directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockApplicationPolicy.java (added)
+++ directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockApplicationPolicy.java Mon Jul 23 13:01:54 2007
@@ -0,0 +1,216 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.directory.triplesec.guardian.mock;
+
+
+import org.apache.directory.triplesec.guardian.*;
+
+import java.util.*;
+
+
+/**
+ * A mock implementation of an ApplicationPolicyStore for testing purposes.
+ *
+ * @author <a href="mailto:akarasulu@safehaus.org">Alex Karasulu</a>
+ * @version $Rev: 72 $
+ */
+class MockApplicationPolicy implements ApplicationPolicy
+{
+    private final Roles roles;
+    private final Permissions perms;
+    private final String name;
+    private final Map profileByName;
+
+
+    public MockApplicationPolicy()
+    {
+        name = "mockApplication";
+        profileByName = new HashMap();
+        Set permSet = new HashSet();
+        Set roleSet = new HashSet();
+
+        // --------------------------------------------------------------------------------
+        // add permissions
+        // --------------------------------------------------------------------------------
+
+        Permission perm0 = new Permission( name, "mockPerm0" ); permSet.add( perm0 );
+        Permission perm1 = new Permission( name, "mockPerm1" ); permSet.add( perm1 );
+        Permission perm2 = new Permission( name, "mockPerm2" ); permSet.add( perm2 );
+        Permission perm3 = new Permission( name, "mockPerm3" ); permSet.add( perm3 );
+        Permission perm4 = new Permission( name, "mockPerm4" ); permSet.add( perm4 );
+        Permission perm5 = new Permission( name, "mockPerm5" ); permSet.add( perm5 );
+        Permission perm6 = new Permission( name, "mockPerm6" ); permSet.add( perm6 );
+        Permission perm7 = new Permission( name, "mockPerm7" ); permSet.add( perm7 );
+        Permission perm8 = new Permission( name, "mockPerm8" ); permSet.add( perm8 );
+        Permission perm9 = new Permission( name, "mockPerm9" ); permSet.add( perm9 );
+
+        Permission[] permArray = ( Permission[] ) permSet.toArray( new Permission[0] );
+        perms = new Permissions( name, permArray );
+
+        // --------------------------------------------------------------------------------
+        // add roles
+        // --------------------------------------------------------------------------------
+
+        // role without any permissions toggled
+        Permissions grants = new Permissions( name, new Permission[0] );
+        Role role0 = new Role( this, "mockRole0", grants );
+        roleSet.add( role0 );
+
+        // role with permission mockPerm0
+        grants = new Permissions( name, new Permission[] {perm0});
+        Role role1 = new Role( this, "mockRole1", grants );
+        roleSet.add( role1 );
+
+        // role with permission mockPerm1
+        grants = new Permissions( name, new Permission[] {perm1});
+        Role role2 = new Role( this, "mockRole2", grants );
+        roleSet.add( role2 );
+
+        // role with permission mockPerm2 and mochPerm3
+        grants = new Permissions( name, new Permission[] {perm2, perm3});
+        Role role3 = new Role( this, "mockRole3", grants );
+        roleSet.add( role3 );
+
+        // role with permission mockPerm4, mockPerm5, mockPerm6, mockPerm7, mockPerm9
+        grants = new Permissions( name, new Permission[] {perm4, perm5, perm6, perm7, perm9});
+        Role role4 = new Role( this, "mockRole4", grants );
+        roleSet.add( role4 );
+
+        Role[] rolesArray = ( Role [] ) roleSet.toArray( new Role[0] );
+        roles = new Roles( name, rolesArray );
+
+        // --------------------------------------------------------------------------------
+        // add profiles
+        // --------------------------------------------------------------------------------
+
+        // a profile that has no permissions at all, and no roles (basis case)
+        grants = new Permissions( name, new Permission[0] );
+        Permissions denials = new Permissions( name, new Permission[0] );
+        Roles roles = new Roles( name, new Role[0] );
+        Profile profile = new Profile( this, "mockProfile0", "trustin", roles, grants, denials, false );
+        profileByName.put( profile.getProfileId(), profile );
+
+        // a profile for checking union of role1 and role2 - inherits perm0 and perm1
+        grants = new Permissions( name, new Permission[0] );
+        denials = new Permissions( name, new Permission[0] );
+        roles = new Roles( name, new Role[] { role1, role2 } );
+        profile = new Profile( this, "mockProfile1", "trustin", roles, grants, denials, false );
+        profileByName.put( profile.getProfileId(), profile );
+
+        // a profile for checking union of roles with grants - granted perm0 and inherits perm1
+        grants = new Permissions( name, new Permission[] { perm0 } );
+        denials = new Permissions( name, new Permission[0] );
+        roles = new Roles( name, new Role[] { role2 } );
+        profile = new Profile( this, "mockProfile2", "trustin", roles, grants, denials, false );
+        profileByName.put( profile.getProfileId(), profile );
+
+        // a profile for checking union of roles with grants - granted perm0, perm7 and inherits perm2 and perm3
+        grants = new Permissions( name, new Permission[] { perm0, perm7 } );
+        denials = new Permissions( name, new Permission[0] );
+        roles = new Roles( name, new Role[] { role3 } );
+        profile = new Profile( this, "mockProfile3", "trustin", roles, grants, denials, false );
+        profileByName.put( profile.getProfileId(), profile );
+
+        // a profile for checking union of roles with grants and denials
+        // granted perm0, in role3 and role4 but denied inherited perm7
+        grants = new Permissions( name, new Permission[] { perm0 } );
+        denials = new Permissions( name, new Permission[] { perm7 } );
+        roles = new Roles( name, new Role[] { role3, role4 } );
+        profile = new Profile( this, "mockProfile4", "trustin", roles, grants, denials, false );
+        profileByName.put( profile.getProfileId(), profile );
+    }
+
+
+    public String getApplicationName()
+    {
+        return name;
+    }
+
+
+    public Roles getRoles()
+    {
+        return roles;
+    }
+
+
+    public Permissions getPermissions()
+    {
+        return perms;
+    }
+
+
+    public Profile getProfile( String username )
+    {
+        return ( Profile ) profileByName.get( username );
+    }
+
+
+    public String getDescription()
+    {
+        return "a mock application";
+    }
+
+
+    public void close()
+    {
+    }
+
+
+    public boolean removePolicyListener( PolicyChangeListener listener )
+    {
+        return false;
+    }
+
+
+    public boolean addPolicyListener( PolicyChangeListener listener )
+    {
+        return false;
+    }
+
+
+    public Set getDependentProfileNames( Role role ) throws GuardianException
+    {
+        return null;
+    }
+
+
+    public Set getDependentProfileNames( Permission permission ) throws GuardianException
+    {
+        return null;
+    }
+
+
+    public Set getUserProfileIds( String userName ) throws GuardianException
+    {
+        return Collections.EMPTY_SET;
+    }
+
+
+    public Iterator getProfileIdIterator() throws GuardianException
+    {
+        return null;
+    }
+
+
+    public Profile getAdminProfile()
+    {
+        return null;
+    }
+}

Added: directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockApplicationPolicyTest.java
URL: http://svn.apache.org/viewvc/directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockApplicationPolicyTest.java?view=auto&rev=558849
==============================================================================
--- directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockApplicationPolicyTest.java (added)
+++ directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockApplicationPolicyTest.java Mon Jul 23 13:01:54 2007
@@ -0,0 +1,116 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.directory.triplesec.guardian.mock;
+
+
+import junit.framework.TestCase;
+import org.apache.directory.triplesec.guardian.ApplicationPolicyFactory;
+import org.apache.directory.triplesec.guardian.Profile;
+
+
+/**
+ * Test cases for the mock application policy store.
+ *
+ * @author <a href="mailto:akarasulu@safehaus.org">Alex Karasulu</a>
+ * @version $Rev$
+ */
+public class MockApplicationPolicyTest extends TestCase
+{
+    MockApplicationPolicy store;
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        Class.forName( "org.apache.directory.triplesec.guardian.mock.MockConnectionDriver" );
+        store = ( MockApplicationPolicy ) ApplicationPolicyFactory.newInstance( "mockApplication", null );
+    }
+
+
+    protected void tearDown() throws Exception
+    {
+        super.tearDown();
+        store.close();
+        store = null;
+    }
+
+
+    public void testProfile0()
+    {
+        assertEquals( 5, store.getRoles().size() );
+        Profile p = store.getProfile( "mockProfile0" );
+        assertTrue( p.getEffectivePermissions().isEmpty() );
+        assertTrue( p.getRoles().isEmpty() );
+    }
+
+    public void testProfile1()
+    {
+        Profile p = store.getProfile( "mockProfile1" );
+        assertEquals( 2, p.getEffectivePermissions().size() );
+        assertTrue( p.hasPermission( "mockPerm0" ) );
+        assertTrue( p.hasPermission( "mockPerm1" ) );
+        assertFalse( p.hasPermission( "mockPerm3") );
+        assertEquals( 2, p.getRoles().size() );
+    }
+
+    public void testProfile2()
+    {
+        Profile p = store.getProfile( "mockProfile2" );
+        assertEquals( 2, p.getEffectivePermissions().size() );
+        assertTrue( p.hasPermission( "mockPerm0" ) );
+        assertTrue( p.hasPermission( "mockPerm1" ) );
+        assertFalse( p.hasPermission( "mockPerm3") );
+        assertEquals( 1, p.getRoles().size() );
+        assertTrue( p.getRoles().contains( "mockRole2" ) );
+    }
+
+    public void testProfile3()
+    {
+        Profile p = store.getProfile( "mockProfile3" );
+        assertEquals( 4, p.getEffectivePermissions().size() );
+        assertTrue( p.hasPermission( "mockPerm0" ) );
+        assertTrue( p.hasPermission( "mockPerm7" ) );
+        assertTrue( p.hasPermission( "mockPerm2" ) );
+        assertTrue( p.hasPermission( "mockPerm3" ) );
+        assertFalse( p.hasPermission( "mockPerm4" ) );
+        assertEquals( 1, p.getRoles().size() );
+        assertTrue( p.getRoles().contains( "mockRole3" ) );
+    }
+
+    public void testProfile4()
+    {
+        Profile p = store.getProfile( "mockProfile4" );
+        assertEquals( 7, p.getEffectivePermissions().size() );
+        assertTrue( p.hasPermission( "mockPerm0" ) );
+        assertFalse( p.hasPermission( "mockPerm1" ) );
+        assertTrue( p.hasPermission( "mockPerm2" ) );
+        assertTrue( p.hasPermission( "mockPerm3" ) );
+        assertTrue( p.hasPermission( "mockPerm4" ) );
+        assertTrue( p.hasPermission( "mockPerm5" ) );
+        assertTrue( p.hasPermission( "mockPerm6" ) );
+        assertFalse( p.hasPermission( "mockPerm7" ) );
+        assertFalse( p.hasPermission( "mockPerm8" ) );
+        assertTrue( p.hasPermission( "mockPerm9" ) );
+
+        assertFalse( p.hasPermission( "mockPerm14" ) );
+        assertEquals( 2, p.getRoles().size() );
+        assertTrue( p.getRoles().contains( "mockRole3" ) );
+        assertTrue( p.getRoles().contains( "mockRole4" ) );
+    }
+}

Added: directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockConnectionDriver.java
URL: http://svn.apache.org/viewvc/directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockConnectionDriver.java?view=auto&rev=558849
==============================================================================
--- directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockConnectionDriver.java (added)
+++ directory/triplesec/trunk/guardian-api/src/test/java/org/apache/directory/triplesec/guardian/mock/MockConnectionDriver.java Mon Jul 23 13:01:54 2007
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.directory.triplesec.guardian.mock;
+
+
+import java.util.Properties;
+
+import org.apache.directory.triplesec.guardian.ApplicationPolicy;
+import org.apache.directory.triplesec.guardian.ApplicationPolicyFactory;
+import org.apache.directory.triplesec.guardian.ConnectionDriver;
+import org.apache.directory.triplesec.guardian.GuardianException;
+
+
+/**
+ * A mock connection specification.
+ *
+ * @author <a href="mailto:akarasulu@safehaus.org">Alex Karasulu</a>
+ * @version $Rev: 53 $
+ */
+public class MockConnectionDriver implements ConnectionDriver
+{
+    static
+    {
+        ApplicationPolicyFactory.registerDriver( new MockConnectionDriver() );
+    }
+
+    public boolean accept( String url )
+    {
+        if ( url.equals( "mockApplication" ) )
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    public ApplicationPolicy newStore( String url, Properties info ) throws GuardianException
+    {
+        return new MockApplicationPolicy();
+    }
+}

Modified: directory/triplesec/trunk/guardian-ldap/pom.xml
URL: http://svn.apache.org/viewvc/directory/triplesec/trunk/guardian-ldap/pom.xml?view=diff&rev=558849&r1=558848&r2=558849
==============================================================================
--- directory/triplesec/trunk/guardian-ldap/pom.xml (original)
+++ directory/triplesec/trunk/guardian-ldap/pom.xml Mon Jul 23 13:01:54 2007
@@ -57,7 +57,7 @@
         <configuration>
           <systemProperties>
             <property>
-              <name>org.safehaus.triplesec.integration.resourcesDirectory</name>
+              <name>org.apache.directory.triplesec.integration.resourcesDirectory</name>
               <value>${basedir}/src/test/resources</value>
             </property>
           </systemProperties>
@@ -79,7 +79,7 @@
               <configuration>
                 <systemProperties>
                   <property>
-                    <name>org.safehaus.triplesec.integration.resourcesDirectory</name>
+                    <name>org.apache.directory.triplesec.integration.resourcesDirectory</name>
                     <value>${basedir}/src/test/resources</value>
                   </property>
                 </systemProperties>

Added: directory/triplesec/trunk/guardian-ldap/src/main/java/org/apache/directory/triplesec/guardian/ldap/LdapApplicationPolicy.java
URL: http://svn.apache.org/viewvc/directory/triplesec/trunk/guardian-ldap/src/main/java/org/apache/directory/triplesec/guardian/ldap/LdapApplicationPolicy.java?view=auto&rev=558849
==============================================================================
--- directory/triplesec/trunk/guardian-ldap/src/main/java/org/apache/directory/triplesec/guardian/ldap/LdapApplicationPolicy.java (added)
+++ directory/triplesec/trunk/guardian-ldap/src/main/java/org/apache/directory/triplesec/guardian/ldap/LdapApplicationPolicy.java Mon Jul 23 13:01:54 2007
@@ -0,0 +1,1275 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.directory.triplesec.guardian.ldap;
+
+
+import org.apache.directory.triplesec.guardian.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.naming.directory.*;
+import javax.naming.event.EventDirContext;
+import javax.naming.event.NamespaceChangeListener;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingExceptionEvent;
+import javax.naming.event.ObjectChangeListener;
+import javax.naming.NamingException;
+import javax.naming.NamingEnumeration;
+import java.util.*;
+
+
+/**
+ * An LDAP backed implementation of an application policy store.
+ *
+ * @author <a href="mailto:akarasulu@safehaus.org">Alex Karasulu</a>
+ * @version $Rev: 72 $
+ */
+class LdapApplicationPolicy implements ApplicationPolicy
+{
+    private static final String[] PROF_ID = new String[] { "profileId" };
+    /** the logger interface for this class */
+    private static Logger log = LoggerFactory.getLogger( LdapApplicationPolicy.class );
+    /** the name of the application this store is associated with */
+    private final String applicationName;
+    /** the application base relative name to the context given: "appName=&lt;applicationName\&gt;,ou=applications" */
+    private final String baseRdn;
+    /** a breif description of this application */
+    private String description;
+
+    /** the {@link Permission}s defined for this store's application */
+    private Permissions permissions;
+    /** the {@link Role}s defined for this store's application */
+    private Roles roles;
+    /** the JNDI Context at the base under which ou=applications can be found */
+    private DirContext ctx;
+    /** the profile for the admin user with all rights in all roles */
+    private Profile adminProfile;
+
+
+    /**
+     * Creates an instance of the LDAP ApplicationPolicyStore.
+     *
+     * @param ctx the base context under which ou=applications and ou=users can be found
+     * @param info additional information needed to
+     * @throws GuardianException if failures are encountered while loading objects from the backing store
+     */
+    public LdapApplicationPolicy( DirContext ctx, Properties info ) throws GuardianException
+    {
+        if ( ctx == null )
+        {
+            throw new NullPointerException( "ctx cannot be null" );
+        }
+            
+        this.ctx = ctx;
+        
+        // extract the applicationName from the applicationPrincipalDN
+        applicationName = getApplicationName( info.getProperty( "applicationPrincipalDN" ) );
+
+        StringBuffer buf = new StringBuffer();
+        buf.append( "appName=" );
+        buf.append( applicationName );
+        buf.append( ",ou=applications" );
+        baseRdn = buf.toString();
+        
+        // load the set of permissions associated with this application
+        loadPermissions();
+
+        // load the set of roles associated with this application
+        loadRoles();
+        
+        // setup the administrator with all permissions and roles
+        adminProfile = new Profile( this, "admin", "admin", roles, permissions, 
+            new Permissions( applicationName, new Permission[0] ), false );
+
+        try
+        {
+            Attributes appAttrs = this.ctx.getAttributes( baseRdn );
+            Attribute descriptionAttr = appAttrs.get( "description" );
+
+            if ( descriptionAttr == null || descriptionAttr.size() == 0 )
+            {
+                description = null;
+            }
+            else
+            {
+                description = ( String ) descriptionAttr.get();
+            }
+        }
+        catch ( NamingException e )
+        {
+            log.error( "failed to read application entry: appName=" + applicationName + ",ou=applications" );
+        }
+        
+        initializeNotifications();
+    }
+
+    
+    private boolean initializeNotifications()
+    {
+        // attempt to get an event context and register for notifications
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+        try
+        {
+            EventDirContext eventContext = ( EventDirContext ) ctx.lookup( "" );
+            eventContext.addNamingListener( baseRdn, "(objectClass=*)", controls, new JndiListener() );
+            return true;
+        }
+        catch ( NamingException e )
+        {
+            log.error( "Failed to register listener for event context: " +
+                    "change notifications will not be recieved.", e );
+            return false;
+        }
+    }
+
+    
+    private Role getRoleFromStore( String roleName ) throws NamingException
+    {
+        SearchControls ctrls = new SearchControls();
+        ctrls.setReturningAttributes( new String[] { "roleName", "grants" } );
+        ctrls.setSearchScope( SearchControls.OBJECT_SCOPE );
+
+        StringBuffer buf = new StringBuffer();
+        buf.append( "roleName=" );
+        buf.append( roleName );
+        buf.append( ",ou=roles," );
+        buf.append( baseRdn );
+        
+        try
+        {
+            NamingEnumeration list = ctx.search( buf.toString(), "(objectClass=policyRole)", ctrls );
+            if ( list.hasMore() )
+            {
+                SearchResult result = ( SearchResult ) list.next();
+                Role role = getRole( result.getAttributes() );
+                log.debug( "fetching role '" + role.getName() + "' for application '" + applicationName + "'" );
+                return role;
+            }
+            
+            return null;
+        }
+        catch ( NamingException e )
+        {
+            String msg = "Failed on search to find roles for application " + applicationName;
+            log.error( msg, e );
+            throw new GuardianException( msg, e );
+        }
+    }
+    
+    
+    /**
+     * 
+     * @throws GuardianException
+     */
+    private void loadRoles() throws GuardianException
+    {
+        Set roleSet = new HashSet();
+        SearchControls ctrls = new SearchControls();
+        ctrls.setReturningAttributes( new String[] { "roleName", "grants" } );
+        ctrls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+
+        try
+        {
+            NamingEnumeration list = ctx.search( "ou=roles," + baseRdn,
+                    "(objectClass=policyRole)", ctrls );
+            while ( list.hasMore() )
+            {
+                SearchResult result = ( SearchResult ) list.next();
+                Role role = getRole( result.getAttributes() );
+                roleSet.add( role );
+                log.debug( "loading role '" + role.getName() + "' for application '" + applicationName + "'" );
+            }
+        }
+        catch ( NamingException e )
+        {
+            String msg = "Failed on search to find roles for application " + applicationName;
+            log.error( msg, e );
+            throw new GuardianException( msg, e );
+        }
+
+        Role[] roleArray = new Role[roleSet.size()];
+        roleArray = ( Role[] ) roleSet.toArray( roleArray );
+        this.roles = new Roles( applicationName, roleArray );
+    }
+
+
+    private void loadPermissions() throws GuardianException
+    {
+        Set permSet = new HashSet();
+        SearchControls ctrls = new SearchControls();
+        ctrls.setReturningAttributes( new String[] { "permName" } );
+        ctrls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+
+        try
+        {
+            NamingEnumeration list = ctx.search( "ou=permissions," + baseRdn,
+                    "(objectClass=policyPermission)", ctrls );
+            while ( list.hasMore() )
+            {
+                SearchResult result = ( SearchResult ) list.next();
+                String permName = ( String ) result.getAttributes().get( "permName" ).get();
+                Permission perm = getPermission( result.getAttributes() );
+                log.debug( "loading permission " + permName + " for application " + applicationName );
+                permSet.add( perm );
+            }
+        }
+        catch ( NamingException e )
+        {
+            String msg = "Failed on search to find permissions for application " + applicationName;
+            log.error( msg, e );
+            throw new GuardianException( msg, e );
+        }
+
+        Permission[] permArray = new Permission[permSet.size()];
+        permArray = ( Permission[] ) permSet.toArray( permArray );
+        this.permissions = new Permissions( applicationName, permArray );
+    }
+    
+    
+    private Permission getPermission( Attributes attrs ) throws NamingException
+    {
+        Permission perm;
+        String permName = ( String ) attrs.get( "permName" ).get();
+        Attribute description = attrs.get( "description" );
+        if ( description != null )
+        {
+            perm = new Permission( applicationName, permName, ( String ) description.get() );
+        }
+        else
+        {
+            perm = new Permission( applicationName, permName );
+        }
+        return perm;
+    }
+
+
+    public String getApplicationName()
+    {
+        return this.applicationName;
+    }
+
+
+    public String getDescription()
+    {
+        return this.description;
+    }
+
+
+    public Roles getRoles()
+    {
+        return this.roles;
+    }
+
+
+    public Permissions getPermissions()
+    {
+        return permissions;
+    }
+
+    
+    private Role getRole( Attributes attrs ) throws NamingException
+    {
+        String roleName = ( String ) attrs.get( "roleName" ).get();
+        Set permSet = new HashSet();
+        Attribute attributes = attrs.get( "grants" );
+
+        if ( attributes != null )
+        {
+            NamingEnumeration grantsEnumeration = attrs.get( "grants" ).getAll();
+            while ( grantsEnumeration.hasMore() )
+            {
+                String permName = ( String ) grantsEnumeration.next();
+                permSet.add( permissions.get( permName ) );
+                log.debug( "granting permission '" + permName + "' to role '" + roleName
+                        + " in application '" + applicationName + "'" );
+            }
+        }
+        Permission[] permArray = new Permission[permSet.size()];
+        Permissions grants = new Permissions( applicationName, ( Permission[] ) permSet.toArray( permArray ) );
+
+        Attribute description = attrs.get( "description" );
+        Role role;
+        if ( description == null || description.size() == 0 )
+        {
+            role = new Role( this, roleName, grants );
+        }
+        else
+        {
+            role = new Role( this, roleName, grants, ( String ) description.get() );
+        }
+        return role;
+    }
+    
+
+    private static boolean parseBoolean( String bool )
+    {
+        if ( bool.equals( "true" ) )
+        {
+            return true;
+        }
+        
+        return false;
+    }
+
+    
+    private Profile getProfile( Attributes attrs ) throws NamingException
+    {
+        Permissions grants;
+        Permissions denials;
+        Roles roles;
+        String profileId;
+        String userName;
+        boolean disabled = false;
+        
+        Attribute profileIdAttr = attrs.get( "profileId" );
+        if ( profileIdAttr == null )
+        {
+            return null;
+        }
+        else 
+        {
+            profileId = ( String ) profileIdAttr.get();
+        }
+
+        Attribute userAttr = attrs.get( "user" );
+        if ( userAttr == null )
+        {
+            return null;
+        }
+        else 
+        {
+            userName = ( String ) userAttr.get();
+        }
+
+        Attribute disabledAttr = attrs.get( "safehausDisabled" );
+        if ( disabledAttr != null )
+        {
+            disabled = parseBoolean( ( ( String ) disabledAttr.get() ).toLowerCase() );
+        }
+
+        // -------------------------------------------------------------------------------
+        // process and assemble the profile's granted permissions
+        // -------------------------------------------------------------------------------
+
+        Attribute grantsAttribute = attrs.get( "grants" );
+        if ( grantsAttribute != null )
+        {
+            Set grantsSet = new HashSet();
+            NamingEnumeration grantsEnumeration = grantsAttribute.getAll();
+            while ( grantsEnumeration.hasMore() )
+            {
+                String grantedPermName = ( String ) grantsEnumeration.next();
+                grantsSet.add( this.permissions.get( grantedPermName ) );
+            }
+            Permission[] grantsArray = new Permission[grantsSet.size()];
+            grants = new Permissions( applicationName, ( Permission[] ) grantsSet.toArray( grantsArray ) );
+        }
+        else
+        {
+            grants = new Permissions( applicationName, new Permission[0] );
+        }
+
+        // -------------------------------------------------------------------------------
+        // process and assemble the profile's granted permissions
+        // -------------------------------------------------------------------------------
+
+        Attribute denialsAttribute = attrs.get( "denials" );
+        if ( denialsAttribute != null )
+        {
+            Set denialsSet = new HashSet();
+            NamingEnumeration denialsEnumeration = denialsAttribute.getAll();
+            while ( denialsEnumeration.hasMore() )
+            {
+                String deniedPermName = ( String ) denialsEnumeration.next();
+                denialsSet.add( this.permissions.get( deniedPermName ) );
+            }
+            Permission[] denialsArray = new Permission[denialsSet.size()];
+            denials = new Permissions( applicationName, ( Permission[] ) denialsSet.toArray( denialsArray ) );
+        }
+        else
+        {
+            denials = new Permissions( applicationName, new Permission[0] );
+        }
+
+        // -------------------------------------------------------------------------------
+        // process and assemble the profile's assigned roles
+        // -------------------------------------------------------------------------------
+
+        Attribute rolesAttribute = attrs.get( "roles" );
+        if ( rolesAttribute != null )
+        {
+            Set rolesSet = new HashSet();
+            NamingEnumeration rolesEnumeration = rolesAttribute.getAll();
+            while ( rolesEnumeration.hasMore() )
+            {
+                String assignedRoleName = ( String ) rolesEnumeration.next();
+                rolesSet.add( this.roles.get( assignedRoleName ) );
+            }
+            Role[] rolesArray = new Role[rolesSet.size()];
+            roles = new Roles( applicationName, ( Role[] ) rolesSet.toArray( rolesArray ) );
+        }
+        else
+        {
+            roles = new Roles( applicationName, new Role[0] );
+        }
+
+        Attribute description = attrs.get( "description" );
+        Profile profile;
+
+        if ( description == null || description.size() == 0 )
+        {
+            profile = new Profile( this, profileId, userName, roles, grants, denials, disabled );
+        }
+        else
+        {
+            profile = new Profile( this, profileId, userName, roles, grants, 
+                denials, ( String ) description.get(), disabled );
+        }
+        
+        return profile;
+    }
+    
+
+    public Profile getProfile( String profileId )
+    {
+        if ( ctx == null )
+        {
+            throw new IllegalStateException( "This ApplicationProfileStore has been closed." );
+        }
+
+        if ( profileId.equals( "admin" ) )
+        {
+            return adminProfile;
+        }
+        
+        /*
+         * Searching via one level scope for a profile is better than base scope lookups because
+         * if the profile is not present search will not fail but return zero entries.  Base scope
+         * searches will raise an exception since the search base will be missing.  Plus profileId
+         * shall be indexed by default.
+         */
+        SearchControls ctrls = new SearchControls();
+        ctrls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+
+        NamingEnumeration list = null;
+        try
+        {
+            list = ctx.search( "ou=profiles," + baseRdn, "(profileId=" + profileId + ")", ctrls );
+            if ( list.hasMore() )
+            {
+                SearchResult result = ( SearchResult ) list.next();
+                Profile profile = getProfile( result.getAttributes() );
+
+                if ( log.isDebugEnabled() )
+                {
+                    log.debug( "loaded profile '" + profileId + "' in application '" + applicationName + "'" );
+                }
+
+                return profile;
+            }
+            else
+            {
+                if ( log.isInfoEnabled() )
+                {
+                    log.info( "Profile search for profileId '" + profileId + "' in application '"
+                            + applicationName + "' failed to return an entry." );
+                }
+
+                return null;
+            }
+        }
+        catch ( NamingException e )
+        {
+            String msg = "Failed on search to find profile for profileId '" + profileId + "' in '" + applicationName + "'";
+            log.error( msg, e );
+            throw new GuardianException( msg, e );
+        }
+        finally
+        {
+            if ( list != null )
+            {
+                try
+                {
+                    list.close();
+                }
+                catch ( NamingException e )
+                {
+                    log.error( "Failed to close NamingEnumeration after profile search." );
+                }
+            }
+        }
+    }
+
+
+    public void close() throws GuardianException
+    {
+        if ( ctx == null )
+        {
+            return;
+        }
+        
+        try
+        {
+            ctx.close();
+            ctx = null;
+        }
+        catch ( NamingException e )
+        {
+            log.error( "Encountered failure while trying to close JNDI context of store", e );
+        }
+    }
+
+
+    static String getApplicationName( String principalDN )
+    {
+        String rdn = principalDN.split( "," )[0].trim();
+        String[] rdnPair = rdn.split( "=" );
+
+        if ( ! rdnPair[0].trim().equalsIgnoreCase( "appName" ) )
+        {
+            throw new IllegalArgumentException( "Application principal name '" + principalDN
+                    + "' is not an application DN" );
+        }
+
+        return rdnPair[1].trim();
+    }
+
+    
+    private List listeners = new ArrayList();
+    
+
+    public boolean removePolicyListener( PolicyChangeListener listener )
+    {
+        return listeners.remove( listener );
+    }
+
+
+    public boolean addPolicyListener( PolicyChangeListener listener )
+    {
+        if ( listeners.contains( listener ) )
+        {
+            return false;
+        }
+        
+        listeners.add( listener );
+        return true;
+    }
+
+
+    public Set getDependentProfileNames( Role role ) throws GuardianException
+    {
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+        controls.setReturningAttributes( PROF_ID );
+        
+        String baseProfilesRdn = "ou=profiles," + this.baseRdn;
+        NamingEnumeration results = null;
+        Set profiles = new HashSet();
+        profiles.add( "admin" );
+        
+        StringBuffer filter = new StringBuffer();
+        filter.append( "(& (objectClass=policyProfile) (roles=" );
+        filter.append( role.getName() );
+        filter.append( ") )" );
+        
+        try
+        {
+            results = ctx.search( baseProfilesRdn, filter.toString(), controls );
+            while ( results.hasMore() )
+            {
+                SearchResult result = ( SearchResult ) results.next();
+                
+                if ( result.getAttributes().get( "profileId" ) != null )
+                {
+                    profiles.add( result.getAttributes().get( "profileId" ).get() );
+                }
+            }
+        }
+        catch ( NamingException e )
+        {
+            throw new GuardianException( "Failed to lookup profiles dependent on role '" + 
+                role.getName() + "' while searching the directory" );
+        }
+        
+        return profiles;
+    }
+
+    
+    public Set getDependentProfileNames( Permission permission ) throws GuardianException
+    {
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+        controls.setReturningAttributes( PROF_ID );
+        
+        String baseProfilesRdn = "ou=profiles," + this.baseRdn;
+        NamingEnumeration results = null;
+        Set profiles = new HashSet();
+        profiles.add( "admin" );
+        
+        StringBuffer filter = new StringBuffer();
+        filter.append( "(& (objectClass=policyProfile) (| (grants=" );
+        filter.append( permission.getName() );
+        filter.append( ") (denials=" );
+        filter.append( permission.getName() );
+        filter.append( ") ) )" );
+        
+        try
+        {
+            results = ctx.search( baseProfilesRdn, filter.toString(), controls );
+            while ( results.hasMore() )
+            {
+                SearchResult result = ( SearchResult ) results.next();
+                
+                if ( result.getAttributes().get( "profileId" ) != null )
+                {
+                    profiles.add( result.getAttributes().get( "profileId" ).get() );
+                }
+            }
+        }
+        catch ( NamingException e )
+        {
+            throw new GuardianException( "Failed to lookup profiles dependent on permission '" + 
+                permission.getName() + "' while searching the directory" );
+        }
+        
+        return profiles;
+    }
+
+    
+    private boolean hasObjectClass( Attribute oc, String value ) throws NamingException
+    {
+        if ( oc == null )
+        {
+            throw new NullPointerException( "expecting non-null object class (oc arg)" );
+        }
+        
+        if ( value == null )
+        {
+            throw new NullPointerException( "expecting non-null object class value (value arg)" );
+        }
+        
+        NamingEnumeration all = oc.getAll();
+        while( all.hasMore() )
+        {
+            String candidate = ( String ) all.next();
+            if ( candidate.equalsIgnoreCase( value ) )
+            {
+                return true;
+            }
+        }
+        
+        return false;
+    }
+    
+
+    /**
+     * An event transducer that converts JNDI notifications of change into
+     * Guardian policy change notifications.  
+     */
+    class JndiListener implements ObjectChangeListener, NamespaceChangeListener
+    {
+        private void logEvent( NamingEvent evt, Attributes entry )
+        {
+            if ( log.isDebugEnabled() )
+            {
+                StringBuffer buf = new StringBuffer();
+                buf.append( "objectChanged(evt): " ).append( evt ).append( "\n" );
+                buf.append( "\ttype          = " ).append( evt.getType() ).append( "\n" );
+                buf.append( "\tchangeInfo    = " ).append( evt.getChangeInfo() ).append( "\n" );
+                buf.append( "\teventContext  = " ).append( evt.getEventContext() ).append( "\n" );
+                buf.append( "\tnewBinding    = " ).append( evt.getNewBinding() ).append( "\n" );
+                buf.append( "\toldBinding    = " ).append( evt.getOldBinding() ).append( "\n" );
+                buf.append( "\tsource        = " ).append( evt.getSource() ).append( "\n" );
+                if ( entry == null )
+                {
+                    buf.append( "\tentry     = " ).append( "null" ).append( "\n" );
+                }
+                else
+                {
+                    buf.append( "\tentry     = " ).append( entry ).append( "\n" );
+                }
+                log.debug( buf.toString() );
+                
+                if ( evt.getNewBinding() != null )
+                {
+                    log.debug( "Binding Class = " + evt.getNewBinding().getClass() );
+                }
+            }
+        }
+
+        public void objectChanged( NamingEvent evt )
+        {
+            SearchResult result = null;
+            Attributes entry = null;
+            Attribute oc = null;
+            
+            /*
+             * Workaround until https://issues.apache.org/jira/browse/DIRSERVER-587 
+             * is fixed.  We simply lookup the object on the server rather than use
+             * the attributes delivered to us.
+             */
+            result = ( SearchResult ) evt.getNewBinding();
+            String name = result.getName();
+            
+            if ( name.indexOf( applicationName ) == -1 )
+            {
+                if ( log.isWarnEnabled() )
+                {
+                    log.warn( "Entry '" + name + "' ignored! " +
+                            "It is not specific to the application: " + applicationName );
+                }
+                return;
+            }
+            
+            try
+            {
+                entry = ctx.getAttributes( name );
+            }
+            catch ( NamingException e1 )
+            {
+                log.error( "Cannot deliver policy change notification.  " +
+                        "Failed to lookup entry attributes for " + name, e1 );
+            }
+
+            logEvent( evt, entry );
+            oc = entry.get( "objectClass" );
+            
+            try
+            {
+                if ( hasObjectClass( oc, "policyApplication" ) )
+                {
+                    log.info( "Received notification that the policyApplication has changed." );
+                    return;
+                }
+                
+                if ( hasObjectClass( oc, "policyPermission" ) )
+                {
+                    String permName = ( String ) entry.get( "permName" ).get();
+                    if ( log.isDebugEnabled() )
+                    {
+                        log.debug( "Received notification that a policyPermission " + permName + " has changed." );
+                    }
+                    
+                    /*
+                     * 1. Need to update/replace the permission itelf in Permissions.
+                     * 2. Need to update/replace all roles that now depend on this permission in Roles.
+                     * 3. Let user application know that the permission has changed.
+                     */
+                    Permissions permissions = LdapApplicationPolicy.this.permissions;
+                    Permission newPermission = getPermission( entry );
+                    Permission oldPermission = permissions.get( newPermission.getName() );
+                    Roles dependentRoles = LdapApplicationPolicy.this.roles.getDependentRoles( oldPermission );
+                    Permissions newPermissions = new Permissions( applicationName, new Permission[] { newPermission } );
+                    Permissions oldPermissions = new Permissions( applicationName, new Permission[] { oldPermission } );
+                    permissions = permissions.removeAll( oldPermissions );
+                    permissions = permissions.addAll( newPermissions );
+                    LdapApplicationPolicy.this.permissions = permissions;
+                    
+                    List oldRoleList = new ArrayList();
+                    List newRoleList = new ArrayList();
+                    for ( Iterator ii = dependentRoles.iterator(); ii.hasNext(); /* */ )
+                    {
+                        Role oldRole = ( Role ) ii.next();
+                        oldRoleList.add( oldRole );
+                        
+                        Role newRole = getRoleFromStore( oldRole.getName() );
+                        newRoleList.add( newRole );
+                    }
+                    Role[] oldRolesArray = new Role[oldRoleList.size()];
+                    oldRolesArray = ( Role[] ) oldRoleList.toArray( oldRolesArray );
+                    Roles oldRoles = new Roles( applicationName, oldRolesArray );
+                    Roles roles = LdapApplicationPolicy.this.roles;
+                    roles = roles.removeAll( oldRoles );
+                    
+                    Role[] newRolesArray = new Role[newRoleList.size()];
+                    newRolesArray = ( Role[] ) newRoleList.toArray( newRolesArray );
+                    Roles newRoles = new Roles( applicationName, newRolesArray );
+                    roles = roles.addAll( newRoles );
+                    
+                    LdapApplicationPolicy.this.roles = roles;
+                    
+                    for ( int ii = 0; ii < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.permissionChanged( LdapApplicationPolicy.this, newPermission, 
+                            ChangeType.MODIFY );
+                    }
+                }
+                else if ( hasObjectClass( oc, "policyRole" ) )
+                {
+                    String roleName = ( String ) entry.get( "roleName" ).get();
+                    
+                    if ( log.isDebugEnabled() )
+                    {
+                        log.debug( "Received notification that a policyRole " + roleName + " has changed." );
+                    }
+                    
+                    /*
+                     * 1. Need to update/replace the role itelf in Roles.
+                     * 2. Let user application know that the Role has changed.
+                     */
+
+                    Role newRole = getRole( entry );
+                    Roles roles = LdapApplicationPolicy.this.roles;
+                    Roles oldRoles = new Roles( applicationName, new Role[] { roles.get( roleName ) } );
+                    roles = roles.removeAll( oldRoles );
+                    Roles newRoles = new Roles( applicationName, new Role[] { newRole } );
+                    roles = roles.addAll( newRoles );
+                    LdapApplicationPolicy.this.roles = roles;
+                    
+                    for ( int ii = 0; ii < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.roleChanged( LdapApplicationPolicy.this, newRole, ChangeType.MODIFY );
+                    }
+                }
+                else if ( hasObjectClass( oc, "policyProfile" ) )
+                {
+                    String profileId = ( String ) entry.get( "profileId" ).get();
+                    
+                    if ( log.isDebugEnabled() )
+                    {
+                        log.debug( "Received notification that a policyProfile " + profileId + " has changed." );
+                    }
+                    
+                    /*
+                     * 1. Let user application know that the Profile has changed.
+                     */
+                    
+                    Profile profile = getProfile( entry );
+                    for ( int ii = 0; ii < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.profileChanged( LdapApplicationPolicy.this, profile, ChangeType.MODIFY );
+                    }
+                }
+                else 
+                {
+                    if ( log.isInfoEnabled() )
+                    {
+                        log.info( "Insignificant object type changed: " + entry );
+                    }
+                }
+
+                // setup the administrator with all permissions and roles
+                adminProfile = new Profile( LdapApplicationPolicy.this, "admin", "admin", roles, permissions, 
+                    new Permissions( applicationName, new Permission[0] ), false );
+            }
+            catch ( NamingException e )
+            {
+                log.error( "failed to handle a notification", e );
+            }
+        }
+
+        public void namingExceptionThrown( NamingExceptionEvent evt )
+        {
+            log.error( "Detected naming exception event in JNDI listener.", evt.getException() );
+            boolean enabled = initializeNotifications();
+            if ( enabled )
+            {
+                log.info( "Re-enabled notifications" );
+            }
+            else
+            {
+                log.error( "Could not re-enable notifications.  Notifications will no longer be recieved." );
+            }
+        }
+
+
+        public void objectAdded( NamingEvent evt )
+        {
+            SearchResult result = ( SearchResult ) evt.getNewBinding();
+            Attributes entry = result.getAttributes();
+            Attribute oc = entry.get( "objectClass" );
+            String name = result.getName();
+            logEvent( evt, entry );
+            
+            if ( name.indexOf( applicationName ) == -1 )
+            {
+                if ( log.isWarnEnabled() )
+                {
+                    log.warn( "Entry '" + name + "' ignored! " +
+                            "It is not specific to the application: " + applicationName );
+                }
+                return;
+            }
+            
+            try
+            {
+                if ( hasObjectClass( oc, "policyPermission" ) )
+                {
+                    /*
+                     * 1. Need to add the permission to the permissions of the application
+                     * 2. Need to notify of the permission's addition to all listeners
+                     */
+                    Permission permission = getPermission( entry );
+                    Permissions permissions = LdapApplicationPolicy.this.permissions;
+                    permissions = permissions.addAll( new Permissions( applicationName, 
+                        new Permission[] { permission } ) );
+                    LdapApplicationPolicy.this.permissions = permissions;
+                    
+                    for ( int ii = 0; ii < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.permissionChanged( LdapApplicationPolicy.this, permission, ChangeType.ADD );
+                    }
+                }
+                else if ( hasObjectClass( oc, "policyRole" ) )
+                {
+                    /*
+                     * 1. Need to add the role to the roles of the application
+                     * 2. Need to notify of the role's addition to all listeners
+                     */
+                    Role role = getRole( entry );
+                    add( role );
+
+                    for ( int ii = 0; ii < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.roleChanged( LdapApplicationPolicy.this, role, ChangeType.ADD );
+                    }
+                }
+                else if ( hasObjectClass( oc, "policyProfile" ) )
+                {
+                    /*
+                     * 1. Need to notify of the profile's addition to all listeners
+                     */
+                    Profile profile = getProfile( entry );
+                    for ( int ii = 0; ii < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.profileChanged( LdapApplicationPolicy.this, profile, ChangeType.ADD );
+                    }
+                }
+                else
+                {
+                    System.out.println( "Entry '" + name + "' ignored!" );
+                    return;
+                }
+                
+                // setup the administrator with all permissions and roles
+                adminProfile = new Profile( LdapApplicationPolicy.this, "admin", "admin", roles, permissions, 
+                    new Permissions( applicationName, new Permission[0] ), false );
+            }
+            catch ( NamingException e )
+            {
+                log.error( "failed to handle an event", e );
+            }
+        }
+
+
+        public void objectRemoved( NamingEvent evt )
+        {
+            SearchResult result = ( SearchResult ) evt.getOldBinding();
+            Attributes entry = result.getAttributes();
+            Attribute oc = entry.get( "objectClass" );
+            String name = result.getName();
+            logEvent( evt, entry );
+            
+            if ( name.indexOf( applicationName ) == -1 )
+            {
+                if ( log.isWarnEnabled() )
+                {
+                    System.out.println( "Entry '" + name + "' ignored! " +
+                            "It is not specific to the application: " + applicationName );
+                }
+                return;
+            }
+            
+            try
+            {
+                if ( hasObjectClass( oc, "policyPermission" ) )
+                {
+                    /*
+                     * 1. Need to remove the permission from the permissions of the application
+                     * 2. Need to notify of the permission's removal to all listeners
+                     */
+                    String profileId = ( String ) entry.get( "permName" ).get();
+                    Permissions permissions = LdapApplicationPolicy.this.permissions;
+                    Permission permission = permissions.get( profileId );
+                    permissions = permissions.removeAll( new Permissions( applicationName, 
+                        new Permission[] { permission } ) );
+                    LdapApplicationPolicy.this.permissions = permissions;
+                    
+                    for ( int ii = 0; ii < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.permissionChanged( LdapApplicationPolicy.this, permission, ChangeType.DEL );
+                    }
+                }
+                else if ( hasObjectClass( oc, "policyRole" ) )
+                {
+                    /*
+                     * 1. Need to remove the role from the roles of the application
+                     * 2. Need to notify of the role's removal to all listeners
+                     */
+                    String roleName = ( String ) entry.get( "roleName" ).get();
+                    Role role = removeRole( roleName );
+
+                    for ( int ii = 0; ii < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.roleChanged( LdapApplicationPolicy.this, role, ChangeType.DEL );
+                    }
+                }
+                else if ( hasObjectClass( oc, "policyProfile" ) )
+                {
+                    /*
+                     * 1. Need to notify of the profile's addition to all listeners
+                     */
+                    Profile profile = getProfile( entry );
+                    for ( int ii = 0; ii < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.profileChanged( LdapApplicationPolicy.this, profile, ChangeType.DEL );
+                    }
+                }
+                else
+                {
+                    System.out.println( "Entry '" + name + "' ignored!" );
+                    return;
+                }
+
+                // setup the administrator with all permissions and roles
+                adminProfile = new Profile( LdapApplicationPolicy.this, "admin", "admin", roles, permissions, 
+                    new Permissions( applicationName, new Permission[0] ), false );
+            }
+            catch ( NamingException e )
+            {
+                log.error( "failed to process an event", e );
+            }
+        }
+
+
+        public void objectRenamed( NamingEvent evt )
+        {
+            logEvent( evt, null );
+            /*
+             * For permissions and roles we need to first remove the old object from 
+             * the Permissions and Roles objects.  Then we need to add the new named
+             * object to the Permissions and Roles.  For profiles all we need is a 
+             * simple notification.  
+             */
+            String oldName = evt.getOldBinding().getName();
+            String newName = evt.getNewBinding().getName();
+            Attributes newEntry = ( ( SearchResult ) evt.getNewBinding() ).getAttributes();
+            Attribute oc = newEntry.get( "objectClass" );
+            
+            if ( oldName.indexOf( applicationName ) == -1 )
+            {
+                if ( log.isWarnEnabled() )
+                {
+                    System.out.println( "Entry '" + oldName + "' ignored! " +
+                            "It is not specific to the application: " + applicationName );
+                }
+                return;
+            }
+            
+            try
+            {
+                String oldProfileId = getRdn( oldName );
+                oldProfileId = getRdnValue( oldProfileId );
+                
+                if ( hasObjectClass( oc, "policyPermission" ) )
+                {
+                    removePermission( oldProfileId );
+                    Permission newPermission = getPermission( newEntry );
+                    add( newPermission );
+                    
+                    for ( int ii = 0; ii  < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.permissionRenamed( LdapApplicationPolicy.this, newPermission, oldProfileId );
+                    }
+                }            
+                else if ( hasObjectClass( oc, "policyRole" ) )
+                {
+                    removeRole( oldProfileId );
+                    Role newRole = getRole( newEntry );
+                    add( newRole );
+                    
+                    for ( int ii = 0; ii < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.roleRenamed( LdapApplicationPolicy.this, newRole, oldProfileId );
+                    }
+                }
+                else if ( hasObjectClass( oc, "policyProfile" ) )
+                {
+                    /*
+                     * 1. Need to notify of the profile's addition to all listeners
+                     */
+                    Profile profile = getProfile( newEntry );
+                    for ( int ii = 0; ii < listeners.size(); ii++ )
+                    {
+                        PolicyChangeListener listener = ( PolicyChangeListener ) listeners.get( ii );
+                        listener.profileRenamed( LdapApplicationPolicy.this, profile, oldProfileId );
+                    }
+                }
+                else
+                {
+                    System.out.println( "Rename of entry '" + oldName + "' to '" + newName + "' ignored!" );
+                    return;
+                }
+
+                // setup the administrator with all permissions and roles
+                adminProfile = new Profile( LdapApplicationPolicy.this, "admin", "admin", roles, permissions, 
+                    new Permissions( applicationName, new Permission[0] ), false );
+            }
+            catch ( NamingException e )
+            {
+                log.error( "failed to process an event", e );
+            }
+        }
+    }
+    
+    
+    /**
+     * Gets the value of a single name component of a distinguished name.
+     * 
+     * @param rdn the name component to get the value from
+     * @return the value of the single name component 
+     */
+    public static String getRdnValue( String rdn )
+    {
+        int index = rdn.indexOf( '=' );
+        return rdn.substring( index + 1, rdn.length() );
+    }
+
+
+    /**
+     * Quickly splits off the relative distinguished name component.
+     * 
+     * @param name the distinguished name or a name fragment
+     * @return the rdn 
+     */
+    private static String getRdn( String name )
+    {
+        if ( null == name )
+        {
+            return null;
+        }
+
+        int commaIndex = -1;
+        if ( ( commaIndex = name.indexOf( ',' ) ) == -1 )
+        {
+            return name;
+        }
+
+        return name.substring( 0, commaIndex );
+    }
+
+
+    private void add( Role role )
+    {
+        Roles addedRoles = new Roles( applicationName, new Role[] { role } );
+        this.roles = this.roles.addAll( addedRoles );
+    }
+
+    
+    private Role removeRole( String roleName )
+    {
+        Role role = this.roles.get( roleName );
+        Roles removedRoles = new Roles( applicationName, new Role[] { role } );
+        this.roles = this.roles.removeAll( removedRoles );
+        return role;
+    }
+    
+    
+    private void add( Permission permission )
+    {
+        Permissions addedPermissions = new Permissions( applicationName, new Permission[] { permission } );
+        this.permissions = this.permissions.addAll( addedPermissions );
+    }
+
+    
+    private Permission removePermission( String permName )
+    {
+        Permission permission = this.permissions.get( permName );
+        Permissions removedPermissions = new Permissions( applicationName, new Permission[] { permission } );
+        this.permissions = this.permissions.removeAll( removedPermissions );
+        return permission;
+    }
+
+
+    public Set getUserProfileIds( String userName ) throws GuardianException
+    {
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+        controls.setReturningAttributes( PROF_ID );
+        
+        String baseProfilesRdn = "ou=profiles," + this.baseRdn;
+        NamingEnumeration results = null;
+        Set profiles = new HashSet();
+        
+        StringBuffer filter = new StringBuffer();
+        filter.append( "(& (objectClass=policyProfile) (user=" );
+        filter.append( userName );
+        filter.append( ") )" );
+        
+        try
+        {
+            results = ctx.search( baseProfilesRdn, filter.toString(), controls );
+            while ( results.hasMore() )
+            {
+                SearchResult result = ( SearchResult ) results.next();
+                
+                if ( result.getAttributes().get( "profileId" ) != null )
+                {
+                    profiles.add( result.getAttributes().get( "profileId" ).get() );
+                }
+            }
+        }
+        catch ( NamingException e )
+        {
+            throw new GuardianException( "Failed to lookup profiles for user '" + 
+                userName + "' while searching the directory" );
+        }
+        
+        return profiles;
+    }
+
+
+    public Iterator getProfileIdIterator() throws GuardianException
+    {
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+        controls.setReturningAttributes( PROF_ID );
+        
+        String baseProfilesRdn = "ou=profiles," + this.baseRdn;
+        NamingEnumeration results = null;
+        try
+        {
+            results = ctx.search( baseProfilesRdn, "(objectClass=policyProfile)", controls );
+            return new ProfileIdIterator( results );
+        }
+        catch ( NamingException e )
+        {
+            throw new GuardianException( "Failed to lookup profiles while searching the directory" );
+        }
+    }
+
+
+    public Profile getAdminProfile()
+    {
+        return adminProfile;
+    }
+}