You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tb...@apache.org on 2006/12/12 16:24:14 UTC

svn commit: r486187 [13/49] - in /directory/trunks/triplesec: ./ admin-api/ admin-api/src/ admin-api/src/main/ admin-api/src/main/java/ admin-api/src/main/java/org/ admin-api/src/main/java/org/safehaus/ admin-api/src/main/java/org/safehaus/triplesec/ a...

Added: directory/trunks/triplesec/guardian-ldap/src/test/java/org/safehaus/triplesec/guardian/ldap/LdapApplicationPolicyIntegrationTest.java
URL: http://svn.apache.org/viewvc/directory/trunks/triplesec/guardian-ldap/src/test/java/org/safehaus/triplesec/guardian/ldap/LdapApplicationPolicyIntegrationTest.java?view=auto&rev=486187
==============================================================================
--- directory/trunks/triplesec/guardian-ldap/src/test/java/org/safehaus/triplesec/guardian/ldap/LdapApplicationPolicyIntegrationTest.java (added)
+++ directory/trunks/triplesec/guardian-ldap/src/test/java/org/safehaus/triplesec/guardian/ldap/LdapApplicationPolicyIntegrationTest.java Tue Dec 12 07:23:31 2006
@@ -0,0 +1,818 @@
+/*
+ *  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.safehaus.triplesec.guardian.ldap;
+
+
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.ldap.InitialLdapContext;
+
+import org.safehaus.triplesec.guardian.ApplicationPolicy;
+import org.safehaus.triplesec.guardian.ApplicationPolicyFactory;
+import org.safehaus.triplesec.guardian.ChangeType;
+import org.safehaus.triplesec.guardian.Permission;
+import org.safehaus.triplesec.guardian.PolicyChangeListener;
+import org.safehaus.triplesec.guardian.Profile;
+import org.safehaus.triplesec.guardian.Role;
+import org.safehaus.triplesec.integration.TriplesecIntegration;
+
+
+/**
+ * TestCase to test the LDAP ApplicationPolicyStore implementation.
+ *
+ * @author <a href="mailto:akarasulu@safehaus.org">Alex Karasulu</a>
+ * @version $Rev$
+ */
+public class LdapApplicationPolicyIntegrationTest extends TriplesecIntegration
+{
+    private Object lockObject = new Object();
+    private String originalName;
+    private ChangeType changeType;
+    private Profile profile;
+    private Role role;
+    private Permission permission;
+    private LdapApplicationPolicy store;
+
+
+    public LdapApplicationPolicyIntegrationTest( String string ) throws Exception
+    {
+        super( string );
+    }
+
+
+    public LdapApplicationPolicyIntegrationTest() throws Exception
+    {
+        super();
+    }
+
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        Properties props = new Properties();
+        props.setProperty( "applicationPrincipalDN", "appName=mockApplication,ou=applications,dc=example,dc=com" );
+        props.setProperty( "applicationCredentials", "testing" );
+
+        Class.forName( "org.safehaus.triplesec.guardian.ldap.LdapConnectionDriver" );
+        store = ( LdapApplicationPolicy ) ApplicationPolicyFactory.
+                newInstance( "ldap://localhost:"+super.getLdapPort()+"/dc=example,dc=com", props );
+    }
+
+
+    protected void tearDown() throws Exception
+    {
+        super.tearDown();
+        store.close();
+        store = null;
+        changeType = null;
+        profile = null;
+        role = null;
+        permission = null;
+        originalName = null;
+    }
+
+
+    public void testGetApplicationNameAndProfile()
+    {
+        String applicationName = LdapApplicationPolicy.getApplicationName(
+                "appName=testingApp,ou=applications,dc=example,dc=com" );
+        assertEquals( "testingApp", applicationName );
+
+        try
+        {
+            LdapApplicationPolicy.getApplicationName( "notanapp=blahblah" );
+            fail( "should never get here due to an exception" );
+        }
+        catch ( IllegalArgumentException e )
+        {
+
+        }
+
+        Profile p = store.getProfile( "nonexistant" );
+        assertNull( p );
+
+        p = store.getProfile( "mockProfile0" );
+        assertTrue( p.getEffectivePermissions().isEmpty() );
+        assertEquals( 5, store.getRoles().size() );
+        assertEquals( p, store.getProfile( "mockProfile0" ) );
+
+        p = store.getProfile( "mockProfile1" );
+        assertEquals( 2, p.getEffectivePermissions().size() );
+        assertTrue( p.hasPermission( "mockPerm0" ) );
+        assertTrue( p.hasPermission( "mockPerm1" ) );
+        assertFalse( p.hasPermission( "mockPerm3") );
+        assertEquals( p, store.getProfile( "mockProfile1" ) );
+
+        p = store.getProfile( "mockProfile2" );
+        assertEquals( 2, p.getEffectivePermissions().size() );
+        assertTrue( p.hasPermission( "mockPerm0" ) );
+        assertTrue( p.hasPermission( "mockPerm1" ) );
+        assertFalse( p.hasPermission( "mockPerm3") );
+        assertEquals( p, store.getProfile( "mockProfile2" ) );
+
+        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( p, store.getProfile( "mockProfile3" ) );
+
+        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( p, store.getProfile( "mockProfile4" ) );
+
+        store.close();
+
+        try
+        {
+            store.getProfile( "asdf" );
+            fail( "should never get here due to an exception" );
+        }
+        catch ( IllegalStateException e )
+        {
+
+        }
+    }
+
+    
+    public void testGetDependantProfilesRole() throws Exception
+    {
+        Role role0 = store.getRoles().get( "mockRole0" );
+        Set dependents = store.getDependentProfileNames( role0 );
+        assertEquals( 1, dependents.size() );
+        
+        Role role1 = store.getRoles().get( "mockRole1" );
+        dependents = store.getDependentProfileNames( role1 );
+        assertEquals( 2, dependents.size() );
+        assertTrue( dependents.contains( "mockProfile1" ) );
+        
+        Role role2 = store.getRoles().get( "mockRole2" );
+        dependents = store.getDependentProfileNames( role2 );
+        assertEquals( 3, dependents.size() );
+        assertTrue( dependents.contains( "mockProfile1" ) );
+        assertTrue( dependents.contains( "mockProfile2" ) );
+        
+        Permission perm1 = store.getPermissions().get( "mockPerm1" );
+        dependents = store.getDependentProfileNames( perm1 );
+        assertEquals( 1, dependents.size() );
+
+        Permission perm7 = store.getPermissions().get( "mockPerm7" );
+        dependents = store.getDependentProfileNames( perm7 );
+        assertEquals( 3, dependents.size() );
+        assertTrue( dependents.contains( "mockProfile3" ) );
+        assertTrue( dependents.contains( "mockProfile4" ) );
+
+        Permission perm0 = store.getPermissions().get( "mockPerm0" );
+        dependents = store.getDependentProfileNames( perm0 );
+        assertEquals( 4, dependents.size() );
+        assertTrue( dependents.contains( "mockProfile2" ) );
+        assertTrue( dependents.contains( "mockProfile3" ) );
+        assertTrue( dependents.contains( "mockProfile4" ) );
+    }
+    
+    
+    public void testGetUserProfileIds() throws Exception
+    {
+        assertEquals( 5, this.store.getUserProfileIds( "akarasulu" ).size() );
+        assertEquals( 0, this.store.getUserProfileIds( "trustin" ).size() );
+    }
+
+
+    public void testGetProfileIds() throws Exception
+    {
+        Set ids = new HashSet();
+        for ( Iterator ii = this.store.getProfileIdIterator(); ii.hasNext(); /**/ )
+        {
+            ids.add( ii.next() );
+        }
+        assertEquals( 5, ids.size() );
+        assertTrue( ids.contains( "mockProfile0" ) );
+        assertTrue( ids.contains( "mockProfile1" ) );
+        assertTrue( ids.contains( "mockProfile2" ) );
+        assertTrue( ids.contains( "mockProfile3" ) );
+        assertTrue( ids.contains( "mockProfile4" ) );
+        assertFalse( ids.contains( "bogus" ) );
+    }
+
+
+    private InitialLdapContext getNewAppContext() throws NamingException
+    {
+        Hashtable env = new Hashtable();
+        env.put( "java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory" );
+        env.put( "java.naming.provider.url", "ldap://localhost:" +  super.getLdapPort()
+            + "/appName=mockApplication,ou=applications,dc=example,dc=com" );
+        env.put( "java.naming.security.principal", "uid=admin,ou=system" );
+        env.put( "java.naming.security.credentials", "secret" );
+        env.put( "java.naming.security.authentication", "simple" );
+        return new InitialLdapContext( env, null );
+    }
+    
+    
+    public void testAddDelNotifications() throws Exception
+    {
+        // get a connection to the server to be used for alterations
+        InitialLdapContext ctx = getNewAppContext();
+        
+        // prepare listener for notifications
+        store.addPolicyListener( new TestListener() );
+        Thread.sleep( 200 );
+        
+        // -------------------------------------------------------------------
+        // Test Permission Addition and Notification
+        // -------------------------------------------------------------------
+
+        Attributes attrs = new BasicAttributes( "objectClass", "policyPermission", true );
+        attrs.put( "permName", "mockPerm10" );
+        attrs.put( "description", "testValue" );
+        ctx.createSubcontext( "permName=mockPerm10,ou=permissions", attrs );
+
+        // wait until the object is set or exit in 10 seconds
+        long startTime = System.currentTimeMillis();
+        long totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 200 );
+                if ( this.permission != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNull( this.profile );
+        assertNull( this.role );
+        assertNotNull( this.permission );
+        assertEquals( "mockPerm10", this.permission.getName() );
+        assertEquals( ChangeType.ADD, this.changeType );
+        assertEquals( "testValue", this.permission.getDescription() );
+        
+        // make sure that policy is updated with this new perm
+        assertEquals( this.permission, this.store.getPermissions().get( "mockPerm10" ) );
+        this.permission = null;
+        this.changeType = null;
+        
+        // -------------------------------------------------------------------
+        // Test Permission Deletion and Notification
+        // -------------------------------------------------------------------
+
+        ctx.destroySubcontext( "permName=mockPerm10,ou=permissions" );
+        
+        // wait until the object is set or exit in 10 seconds
+        startTime = System.currentTimeMillis();
+        totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 200 );
+                if ( this.permission != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNull( this.profile );
+        assertNull( this.role );
+        assertNotNull( this.permission );
+        assertEquals( "mockPerm10", this.permission.getName() );
+        assertEquals( ChangeType.DEL, this.changeType );
+        assertEquals( "testValue", this.permission.getDescription() );
+        
+        // make sure that policy is updated with this new perm
+        assertNull( this.store.getPermissions().get( "mockPerm10" ) );
+        this.permission = null;
+        this.changeType = null;
+
+        // -------------------------------------------------------------------
+        // Test Role Addition and Notification
+        // -------------------------------------------------------------------
+
+        attrs = new BasicAttributes( "objectClass", "policyRole", true );
+        attrs.put( "roleName", "mockRole5" );
+        attrs.put( "description", "testValue" );
+        attrs.put( "grants", "mockPerm8" );
+        ctx.createSubcontext( "roleName=mockRole5,ou=roles", attrs );
+
+        // wait until the object is set or exit in 10 seconds
+        startTime = System.currentTimeMillis();
+        totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 200 );
+                if ( this.role != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNull( this.profile );
+        assertNull( this.permission );
+        assertNotNull( this.role );
+
+        assertEquals( "mockRole5", this.role.getName() );
+        assertEquals( ChangeType.ADD, this.changeType );
+        assertEquals( "testValue", this.role.getDescription() );
+        assertTrue( role.hasPermission( "mockPerm8" ) );
+        assertFalse( role.hasPermission( "mockPerm1" ) );
+        
+        // make sure that policy is updated with this new role
+        assertEquals( this.role, this.store.getRoles().get( "mockRole5" ) );
+        this.role = null;
+        this.changeType = null;
+
+        // -------------------------------------------------------------------
+        // Test Role Deletions and Notification
+        // -------------------------------------------------------------------
+
+        ctx.destroySubcontext( "roleName=mockRole5,ou=roles" );
+
+        // wait until the object is set or exit in 10 seconds
+        startTime = System.currentTimeMillis();
+        totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 200 );
+                if ( this.role != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNull( this.profile );
+        assertNull( this.permission );
+        assertNotNull( this.role );
+
+        assertEquals( "mockRole5", this.role.getName() );
+        assertEquals( ChangeType.DEL, this.changeType );
+        assertEquals( "testValue", this.role.getDescription() );
+        assertTrue( role.hasPermission( "mockPerm8" ) );
+        assertFalse( role.hasPermission( "mockPerm1" ) );
+        
+        // make sure that policy is updated with this new role
+        assertNull( this.store.getRoles().get( "mockRole5" ) );
+        this.role = null;
+        this.changeType = null;
+
+        // -------------------------------------------------------------------
+        // Test Profile Addition and Notification
+        // -------------------------------------------------------------------
+
+        attrs = new BasicAttributes( "objectClass", "policyProfile", true );
+        attrs.put( "profileId", "mockProfile5" );
+        attrs.put( "description", "testValue" );
+        attrs.put( "grants", "mockPerm8" );
+        attrs.put( "user", "akarasulu" );
+        ctx.createSubcontext( "profileId=mockProfile5,ou=profiles", attrs );
+
+        // wait until the object is set or exit in 10 seconds
+        startTime = System.currentTimeMillis();
+        totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 200 );
+                if ( this.profile != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNull( this.role );
+        assertNull( this.permission );
+        assertNotNull( this.profile );
+
+        assertEquals( "mockProfile5", this.profile.getProfileId() );
+        assertEquals( ChangeType.ADD, this.changeType );
+        assertEquals( "testValue", this.profile.getDescription() );
+        assertTrue( profile.hasPermission( "mockPerm8" ) );
+        assertFalse( profile.hasPermission( "mockPerm1" ) );
+
+        // -------------------------------------------------------------------
+        // Test Profile Deletion and Notification
+        // -------------------------------------------------------------------
+
+        ctx.destroySubcontext( "profileId=mockProfile5,ou=profiles" );
+
+        // wait until the object is set or exit in 10 seconds
+        startTime = System.currentTimeMillis();
+        totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 200 );
+                if ( this.profile != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNull( this.role );
+        assertNull( this.permission );
+        assertNotNull( this.profile );
+
+        assertEquals( "mockProfile5", this.profile.getProfileId() );
+        assertEquals( ChangeType.DEL, this.changeType );
+        assertEquals( "testValue", this.profile.getDescription() );
+        assertTrue( profile.hasPermission( "mockPerm8" ) );
+        assertFalse( profile.hasPermission( "mockPerm1" ) );
+    }
+
+    
+    public void testModifyNotifications() throws Exception
+    {
+        // get a connection to the server to be used for alterations
+        InitialLdapContext ctx = getNewAppContext();
+        
+        // prepare listener for notifications
+        store.addPolicyListener( new TestListener() );
+        Thread.sleep( 200 );
+        
+        // -------------------------------------------------------------------
+        // Test Profile Alteration and Notification
+        // -------------------------------------------------------------------
+
+        ctx.modifyAttributes( "profileId=mockProfile3,ou=profiles", new ModificationItem[] {
+            new ModificationItem( DirContext.ADD_ATTRIBUTE, 
+                new BasicAttribute( "description", "testValue" ) ),
+            new ModificationItem( DirContext.REPLACE_ATTRIBUTE, 
+                new BasicAttribute( "grants", "mockPerm1" ) )
+        } );
+        
+        // wait until the object is set or exit in 10 seconds
+        long startTime = System.currentTimeMillis();
+        long totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 200 );
+                if ( profile != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNotNull( profile );
+        assertEquals( "mockProfile3", profile.getProfileId() );
+        assertEquals( ChangeType.MODIFY, changeType );
+        assertEquals( "testValue", profile.getDescription() );
+        assertTrue( profile.getGrants().contains( "mockPerm1" ));
+        assertFalse( profile.getGrants().contains( "mockPerm0" ));
+        assertFalse( profile.getGrants().contains( "mockPerm7" ));
+        profile = null;
+        changeType = null;
+        
+        // -------------------------------------------------------------------
+        // Test Role Alteration and Notification
+        // -------------------------------------------------------------------
+
+        ctx.modifyAttributes( "roleName=mockRole1,ou=roles", new ModificationItem[] {
+            new ModificationItem( DirContext.ADD_ATTRIBUTE, 
+                new BasicAttribute( "description", "testValue" ) ),
+            new ModificationItem( DirContext.REPLACE_ATTRIBUTE, 
+                new BasicAttribute( "grants", "mockPerm1" ) )
+        } );
+        
+        // wait until the object is set or exit in 10 seconds
+        startTime = System.currentTimeMillis();
+        totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 200 );
+                if ( role != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNull( profile );
+        assertNotNull( role );
+        assertEquals( "mockRole1", role.getName() );
+        assertEquals( ChangeType.MODIFY, changeType );
+        assertEquals( "testValue", role.getDescription() );
+        assertTrue( role.getGrants().contains( "mockPerm1" ));
+        assertFalse( role.getGrants().contains( "mockPerm0" ));
+        
+        // make sure that policy is updated with this changed role
+        assertEquals( role, store.getRoles().get( "mockRole1" ) );
+        this.role = null;
+        this.changeType = null;
+        
+        // -------------------------------------------------------------------
+        // Test Permission Alteration and Notification
+        // -------------------------------------------------------------------
+
+        ctx.modifyAttributes( "permName=mockPerm1,ou=permissions", new ModificationItem[] {
+            new ModificationItem( DirContext.ADD_ATTRIBUTE, 
+                new BasicAttribute( "description", "testValue" ) )
+        } );
+        
+        // wait until the object is set or exit in 10 seconds
+        startTime = System.currentTimeMillis();
+        totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 200 );
+                if ( this.permission != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNull( this.profile );
+        assertNull( this.role );
+        assertNotNull( this.permission );
+        assertEquals( "mockPerm1", this.permission.getName() );
+        assertEquals( ChangeType.MODIFY, this.changeType );
+        assertEquals( "testValue", this.permission.getDescription() );
+        
+        // make sure that policy is updated with this changed perm
+        assertEquals( this.permission, this.store.getPermissions().get( "mockPerm1" ) );
+        assertEquals( this.permission, this.store.getRoles().get( "mockRole1" ).getGrants().get( "mockPerm1" ) );
+        assertEquals( this.permission, this.store.getRoles().get( "mockRole2" ).getGrants().get( "mockPerm1" ) );
+        assertNull( this.store.getRoles().get( "mockRole0" ).getGrants().get( "mockPerm1" ) );
+        assertNull( this.store.getRoles().get( "mockRole3" ).getGrants().get( "mockPerm1" ) );
+        assertNull( this.store.getRoles().get( "mockRole4" ).getGrants().get( "mockPerm1" ) );
+        
+        ctx.close();
+    }
+    
+    
+    public void testRenameNotifications() throws Exception
+    {
+        // get a connection to the server to be used for alterations
+        InitialLdapContext ctx = getNewAppContext();
+        
+        // prepare listener for notifications
+        store.addPolicyListener( new TestListener() );
+        Thread.sleep( 200 );
+        
+        // -------------------------------------------------------------------
+        // Test Profile Rename and Notification
+        // -------------------------------------------------------------------
+
+        ctx.rename( "profileId=mockProfile3,ou=profiles", "profileId=renamed,ou=profiles" );
+        
+        // wait until the object is set or exit in 10 seconds
+        long startTime = System.currentTimeMillis();
+        long totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 200 );
+                if ( profile != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNotNull( profile );
+        assertEquals( "renamed", profile.getProfileId() );
+        assertNotNull( originalName );
+        assertEquals( "mockProfile3", originalName );
+        profile = null;
+        originalName = null;
+        
+        // -------------------------------------------------------------------
+        // Test Role Rename and Notification
+        // -------------------------------------------------------------------
+
+        assertNotNull( store.getRoles().get( "mockRole0" ) );
+        assertNull( store.getRoles().get( "renamed" ) );
+        ctx.rename( "roleName=mockRole0,ou=roles", "roleName=renamed,ou=roles" );
+        
+        // wait until the object is set or exit in 10 seconds
+        startTime = System.currentTimeMillis();
+        totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 200 );
+                if ( role != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNull( profile );
+        assertNull( permission );
+        assertNull( store.getRoles().get( "mockRole0" ) );
+        assertNotNull( store.getRoles().get( "renamed" ) );
+        assertNotNull( role );
+        assertEquals( "renamed", role.getName() );
+        assertNotNull( originalName );
+        assertEquals( "mockRole0", originalName );
+        role = null;
+        originalName = null;
+
+        // -------------------------------------------------------------------
+        // Test Permission Rename and Notification
+        // -------------------------------------------------------------------
+
+        Attributes attrs = new BasicAttributes( "objectClass", "policyPermission", true );
+        attrs.put( "permName", "mockPerm10" );
+        attrs.put( "description", "testValue" );
+        ctx.createSubcontext( "permName=mockPerm10,ou=permissions", attrs );
+        ctx.rename( "permName=mockPerm10,ou=permissions", "permName=renamed,ou=permissions" );
+
+        // wait until the object is set or exit in 10 seconds
+        startTime = System.currentTimeMillis();
+        totalWaitTime = 0;
+        while ( totalWaitTime < 10000 )
+        {
+            synchronized( lockObject )
+            {
+                lockObject.wait( 250 );
+                if ( permission != null )
+                {
+                    break;
+                }
+                else
+                {
+                    totalWaitTime = System.currentTimeMillis() - startTime;
+                }
+            }
+        }
+
+        assertNull( profile );
+        assertNull( role );
+        assertNotNull( permission );
+        assertNotNull( store.getPermissions().get( "renamed" ) );
+        assertEquals( "renamed", permission.getName() );
+        assertNotNull( originalName );
+        assertEquals( "mockPerm10", originalName );
+    }
+
+
+    class TestListener implements PolicyChangeListener
+    {
+        public void roleChanged( ApplicationPolicy policy, Role role, ChangeType changeType )
+        {
+            synchronized( lockObject )
+            {
+                LdapApplicationPolicyIntegrationTest.this.role = role;
+                LdapApplicationPolicyIntegrationTest.this.changeType = changeType;
+                LdapApplicationPolicyIntegrationTest.this.lockObject.notifyAll();
+            }
+        }
+
+        public void roleRenamed( ApplicationPolicy policy, Role role, String oldName )
+        {
+            synchronized( lockObject )
+            {
+                LdapApplicationPolicyIntegrationTest.this.originalName = oldName;
+                LdapApplicationPolicyIntegrationTest.this.role = role;
+                LdapApplicationPolicyIntegrationTest.this.lockObject.notifyAll();
+            }
+        }
+
+        public void permissionChanged( ApplicationPolicy policy, Permission permission, ChangeType changeType )
+        {
+            synchronized( lockObject )
+            {
+                LdapApplicationPolicyIntegrationTest.this.permission = permission;
+                LdapApplicationPolicyIntegrationTest.this.changeType = changeType;
+                LdapApplicationPolicyIntegrationTest.this.lockObject.notifyAll();
+            }
+        }
+
+        public void permissionRenamed( ApplicationPolicy policy, Permission permission, String oldName )
+        {
+            synchronized( lockObject )
+            {
+                LdapApplicationPolicyIntegrationTest.this.originalName = oldName;
+                LdapApplicationPolicyIntegrationTest.this.permission = permission;
+                LdapApplicationPolicyIntegrationTest.this.lockObject.notifyAll();
+            }
+        }
+
+        public void profileChanged( ApplicationPolicy policy, Profile profile, ChangeType changeType )
+        {
+            synchronized( lockObject )
+            {
+                LdapApplicationPolicyIntegrationTest.this.profile = profile;
+                LdapApplicationPolicyIntegrationTest.this.changeType = changeType;
+                LdapApplicationPolicyIntegrationTest.this.lockObject.notifyAll();
+            }
+        }
+
+        public void profileRenamed( ApplicationPolicy policy, Profile profile, String oldName )
+        {
+            synchronized( lockObject )
+            {
+                LdapApplicationPolicyIntegrationTest.this.originalName = oldName;
+                LdapApplicationPolicyIntegrationTest.this.profile = profile;
+                LdapApplicationPolicyIntegrationTest.this.lockObject.notifyAll();
+            }
+        }
+    }
+}
+                                                     
\ No newline at end of file

Added: directory/trunks/triplesec/guardian-ldap/src/test/java/org/safehaus/triplesec/guardian/ldap/LdapConnectionDriverTest.java
URL: http://svn.apache.org/viewvc/directory/trunks/triplesec/guardian-ldap/src/test/java/org/safehaus/triplesec/guardian/ldap/LdapConnectionDriverTest.java?view=auto&rev=486187
==============================================================================
--- directory/trunks/triplesec/guardian-ldap/src/test/java/org/safehaus/triplesec/guardian/ldap/LdapConnectionDriverTest.java (added)
+++ directory/trunks/triplesec/guardian-ldap/src/test/java/org/safehaus/triplesec/guardian/ldap/LdapConnectionDriverTest.java Tue Dec 12 07:23:31 2006
@@ -0,0 +1,102 @@
+/*
+ *  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.safehaus.triplesec.guardian.ldap;
+
+
+import junit.framework.TestCase;
+
+import java.util.Properties;
+
+
+/**
+ * Tests the LDAP ConnectionDriver.
+ *
+ * @author <a href="mailto:akarasulu@safehaus.org">Alex Karasulu</a>
+ * @version $Rev$
+ */
+public class LdapConnectionDriverTest extends TestCase
+{
+    public void testNullProperties()
+    {
+        LdapConnectionDriver driver = new LdapConnectionDriver();
+
+        try
+        {
+            driver.newStore( "", null );
+            fail( "should not get here due to exception" );
+        }
+        catch( IllegalArgumentException e )
+        {
+        }
+    }
+
+
+    public void testNullUrl()
+    {
+        LdapConnectionDriver driver = new LdapConnectionDriver();
+        Properties props = new Properties();
+        props.setProperty( "applicationPrincipalDN", "appName=something" );
+        props.setProperty( "applicationCredentials", "secret" );
+        try
+        {
+            driver.newStore( null, props );
+            fail( "should never get here due to an exception" );
+        }
+        catch ( IllegalArgumentException e )
+        {
+
+        }
+    }
+
+
+    public void testNoPrincipalName()
+    {
+        LdapConnectionDriver driver = new LdapConnectionDriver();
+
+        try
+        {
+            Properties props = new Properties();
+            props.setProperty( "applicationCredentials", "secret" );
+            driver.newStore( "", props );
+            fail( "should never get here due to an exception" );
+        }
+        catch ( IllegalArgumentException e )
+        {
+
+        }
+    }
+
+
+    public void testNoCredentials()
+    {
+        LdapConnectionDriver driver = new LdapConnectionDriver();
+        Properties props = new Properties();
+        props.setProperty( "applicationPrincipalDN", "appName=something" );
+        try
+        {
+            driver.newStore( "", props );
+            fail( "should never get here due to an exception" );
+        }
+        catch ( IllegalArgumentException e )
+        {
+
+        }
+    }
+}

Added: directory/trunks/triplesec/guardian-ldap/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/directory/trunks/triplesec/guardian-ldap/src/test/resources/log4j.properties?view=auto&rev=486187
==============================================================================
--- directory/trunks/triplesec/guardian-ldap/src/test/resources/log4j.properties (added)
+++ directory/trunks/triplesec/guardian-ldap/src/test/resources/log4j.properties Tue Dec 12 07:23:31 2006
@@ -0,0 +1,11 @@
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=ERROR, A1
+
+# A1 is set to be a ConsoleAppender.
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+# A1 uses PatternLayout.
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+
+

Added: directory/trunks/triplesec/guardian-ldap/src/test/resources/server.ldif
URL: http://svn.apache.org/viewvc/directory/trunks/triplesec/guardian-ldap/src/test/resources/server.ldif?view=auto&rev=486187
==============================================================================
--- directory/trunks/triplesec/guardian-ldap/src/test/resources/server.ldif (added)
+++ directory/trunks/triplesec/guardian-ldap/src/test/resources/server.ldif Tue Dec 12 07:23:31 2006
@@ -0,0 +1,334 @@
+#
+#  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. 
+#  
+#
+#
+#   EXAMPLE.COM is freely and reserved for testing according to this RFC:
+#
+#   http://www.rfc-editor.org/rfc/rfc2606.txt
+#
+#
+
+#
+# This ACI allows brouse access to the root suffix and one level below that to anyone.
+# At this level there is nothing critical exposed.  Everything that matters is one or
+# more levels below this.
+#
+
+dn: cn=browseRootAci,dc=example,dc=com
+objectClass: top
+objectClass: subentry
+objectClass: accessControlSubentry
+subtreeSpecification: { maximum 1 }
+prescriptiveACI: { identificationTag "browseRoot", precedence 100, authenticationLevel none, itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { protectedItems {entry}, grantsAndDenials { grantReturnDN, grantBrowse } } } } }
+
+dn: ou=Users, dc=example, dc=com
+objectclass: top
+objectclass: organizationalunit
+ou: Users
+
+#
+# This ACI allows users to modify a limited set of attributes in their own user
+# entry as well as read, compare those attributes.  The user's entry must be 
+# browseable and the DN must be returnable.
+#
+
+dn: cn=allowSelfModificationsAci,dc=example,dc=com
+objectClass: top
+objectClass: subentry
+objectClass: accessControlSubentry
+subtreeSpecification: { base "ou=users", maximum 1 }
+prescriptiveACI: { identificationTag "allowSelfModifications", precedence 14, authenticationLevel simple, itemOrUserFirst userFirst: { userClasses { thisEntry }, userPermissions  {  { protectedItems {entry}, grantsAndDenials { grantReturnDN, grantModify, grantBrowse, grantRead, grantDiscloseOnError } }, { protectedItems {allAttributeValues {userPassword, krb5Key, givenName, cn, commonName, surName, sn, objectClass }}, grantsAndDenials { grantModify, grantAdd, grantRemove, grantRead, grantDiscloseOnError, grantCompare } } } } }
+
+#
+# This ACI allows users to access a limited set of attributes in their own user
+# entry as well as compare those attributes.  The user's entry must be browseable 
+# and the DN must be returnable.
+#
+
+dn: cn=allowSelfAccessAci,dc=example,dc=com
+objectClass: top
+objectClass: subentry
+objectClass: accessControlSubentry
+subtreeSpecification: { base "ou=users", maximum 1 }
+prescriptiveACI: { identificationTag "allowSelfAccess", precedence 15, authenticationLevel simple, itemOrUserFirst userFirst: { userClasses { thisEntry }, userPermissions  {  { protectedItems {entry}, grantsAndDenials { grantReturnDN, grantBrowse, grantRead, grantDiscloseOnError } }, { protectedItems {allAttributeValues {uid, userPassword, givenName, cn, commonName, surName, sn, objectClass, creatorsName, modifiersName, createTimestamp, modifyTimestamp, krb5AccountDisabled, description, apacheSamType }}, grantsAndDenials { grantRead, grantDiscloseOnError, grantCompare } } } } }
+
+dn: ou=Groups, dc=example, dc=com
+objectclass: top
+objectclass: organizationalunit
+ou: Groups
+
+dn: cn=superUsers, ou=Groups, dc=example, dc=com
+objectClass: top
+objectClass: groupOfUniqueNames
+cn: superUsers
+uniqueMember: uid=admin, ou=system
+
+dn: cn=userAdmins, ou=Groups, dc=example, dc=com
+objectClass: top
+objectClass: groupOfUniqueNames
+cn: userAdmin
+uniqueMember: uid=admin, ou=system
+
+dn: cn=applicationAdmins, ou=Groups, dc=example, dc=com
+objectClass: top
+objectClass: groupOfUniqueNames
+cn: applicationAdmin
+uniqueMember: uid=admin, ou=system
+
+dn: cn=groupAdmins, ou=Groups, dc=example, dc=com
+objectClass: top
+objectClass: groupOfUniqueNames
+cn: groupAdmin
+uniqueMember: uid=admin, ou=system
+
+#
+# This ACI allows members of the superUsers group to have full modify and read access
+# to the entire realm as does the system administrator principal: uid=admin, ou=system.
+#
+# The only thing these users cannot do is modify the system partition.  They are only
+# restricted to superUser rights within this realm partition
+#
+ 
+dn: cn=superUsersAci,dc=example,dc=com
+objectClass: top
+objectClass: subentry
+objectClass: accessControlSubentry
+subtreeSpecification: { }
+prescriptiveACI: { identificationTag "superUsersAci", precedence 20, authenticationLevel simple,  itemOrUserFirst userFirst: { userClasses { userGroup { "cn=superUsers,ou=groups,dc=example,dc=com" } }, userPermissions { { protectedItems {entry, allUserAttributeTypesAndValues},  grantsAndDenials { grantRead, grantReturnDN, grantBrowse, grantDiscloseOnError, grantCompare, grantAdd, grantRename, grantRemove, grantModify, grantImport, grantExport } } } } }
+
+#
+# This ACI allows members of the userAdmin group to have full modify and read access
+# to user accounts besides their own.  Hence they can administer users in the system.
+#
+ 
+dn: cn=userAdminsAci,dc=example,dc=com
+objectClass: top
+objectClass: subentry
+objectClass: accessControlSubentry
+subtreeSpecification: { base "ou=users", maximum 1 }
+prescriptiveACI: { identificationTag "userAdminsAci", precedence 16, authenticationLevel simple,  itemOrUserFirst userFirst: { userClasses { userGroup { "cn=userAdmins,ou=groups,dc=example,dc=com" } }, userPermissions { { protectedItems {entry, allUserAttributeTypesAndValues},  grantsAndDenials { grantRead, grantReturnDN, grantBrowse, grantDiscloseOnError, grantCompare, grantAdd, grantRename, grantRemove, grantModify, grantImport, grantExport } } } } }
+
+
+#
+# This ACI allows members of the applicationAdmin group to have full modify and read access
+# to all applications in the realm.  Adding users to this group is like a wild card for 
+# application access.
+#
+ 
+dn: cn=applicationAdminsAci,dc=example,dc=com
+objectClass: top
+objectClass: subentry
+objectClass: accessControlSubentry
+subtreeSpecification: { base "ou=applications" }
+prescriptiveACI: { identificationTag "applicationAdminsAci", precedence 17, authenticationLevel simple,  itemOrUserFirst userFirst: { userClasses { userGroup { "cn=applicationAdmins,ou=groups,dc=example,dc=com" } }, userPermissions { { protectedItems {entry, allUserAttributeTypesAndValues},  grantsAndDenials { grantRead, grantReturnDN, grantBrowse, grantDiscloseOnError, grantCompare, grantAdd, grantRename, grantRemove, grantModify, grantImport, grantExport } } } } }
+
+
+#
+# This ACI allows members of the groupAdmins group to have full modify and read access
+# to all groups in the realm other than the superUsers, userAdmins, groupAdmins, and the 
+# applicationAdmins groups.
+#
+# The rational behind this is to prevent these users from changing their or other
+# users' access rights for the entire system by modifying their membership in these 
+# groups. Making someone a groupAdmin should not open the door to their ability to
+# grant themselves or others system wide administrative abilities.
+#
+# Really the groupAdmins group is intended for users that have the ability to manage 
+# group membership in specific application administration groups and that's all.  
+# These types of admins should not have the right to promote others to system level
+# administrators or complete super users.
+#
+ 
+dn: cn=groupAdminsAci,dc=example,dc=com
+objectClass: top
+objectClass: subentry
+objectClass: accessControlSubentry
+subtreeSpecification: { base "ou=groups", specificExclusions { chopBefore: "cn=userAdmins", chopBefore: "cn=groupAdmins", chopBefore: "cn=applicationAdmins", chopBefore: "cn=superUsers" } }
+prescriptiveACI: { identificationTag "groupAdminsAci", precedence 18, authenticationLevel simple,  itemOrUserFirst userFirst: { userClasses { userGroup { "cn=groupAdmins,ou=groups,dc=example,dc=com" } }, userPermissions { { protectedItems {entry, allUserAttributeTypesAndValues},  grantsAndDenials { grantRead, grantReturnDN, grantBrowse, grantDiscloseOnError, grantCompare, grantAdd, grantRename, grantRemove, grantModify, grantImport, grantExport } } } } }
+
+dn: uid=krbtgt, ou=Users, dc=example,dc=com
+cn: Kerberos Server
+sn: Server
+givenname: Kerberos
+objectclass: top
+objectclass: uidObject
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+objectclass: krb5Principal
+objectclass: krb5KDCEntry
+ou: Users
+uid: krbtgt
+krb5PrincipalName: krbtgt/EXAMPLE.COM@EXAMPLE.COM
+krb5KeyVersionNumber: 0
+mail: admin@example.com
+roomnumber: 667
+userpassword: secret
+
+dn: ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: organizationalunit
+ou: applications
+
+dn: appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyApplication
+appName: mockApplication
+userPassword:: dGVzdGluZw==
+
+dn: ou=permissions,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: organizationalUnit
+ou: permissions
+
+dn: permName=mockPerm0,ou=permissions,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyPermission
+permName: mockPerm0
+
+dn: permName=mockPerm1,ou=permissions,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyPermission
+permName: mockPerm1
+
+dn: permName=mockPerm2,ou=permissions,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyPermission
+permName: mockPerm2
+
+dn: permName=mockPerm3,ou=permissions,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyPermission
+permName: mockPerm3
+
+dn: permName=mockPerm4,ou=permissions,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyPermission
+permName: mockPerm4
+
+dn: permName=mockPerm5,ou=permissions,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyPermission
+permName: mockPerm5
+
+dn: permName=mockPerm6,ou=permissions,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyPermission
+permName: mockPerm6
+
+dn: permName=mockPerm7,ou=permissions,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyPermission
+permName: mockPerm7
+
+dn: permName=mockPerm8,ou=permissions,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyPermission
+permName: mockPerm8
+
+dn: permName=mockPerm9,ou=permissions,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyPermission
+permName: mockPerm9
+
+dn: ou=roles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: organizationalUnit
+ou: roles
+
+dn: roleName=mockRole0,ou=roles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: policyRole
+objectClass: top
+roleName: mockRole0
+
+dn: roleName=mockRole1,ou=roles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyRole
+grants: mockPerm0
+roleName: mockRole1
+
+dn: roleName=mockRole2,ou=roles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyRole
+grants: mockPerm1
+roleName: mockRole2
+
+dn: roleName=mockRole3,ou=roles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyRole
+grants: mockPerm3
+grants: mockPerm2
+roleName: mockRole3
+
+dn: roleName=mockRole4,ou=roles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyRole
+grants: mockPerm9
+grants: mockPerm7
+grants: mockPerm6
+grants: mockPerm5
+grants: mockPerm4
+roleName: mockRole4
+
+dn: ou=profiles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: organizationalUnit
+ou: profiles
+
+dn: profileId=mockProfile0,ou=profiles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyProfile
+user: akarasulu
+profileId: mockProfile0
+
+dn: profileId=mockProfile1,ou=profiles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyProfile
+roles: mockRole2
+roles: mockRole1
+user: akarasulu
+profileId: mockProfile1
+
+dn: profileId=mockProfile2,ou=profiles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyProfile
+grants: mockPerm0
+roles: mockRole2
+user: akarasulu
+profileId: mockProfile2
+
+dn: profileId=mockProfile3,ou=profiles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyProfile
+grants: mockPerm7
+grants: mockPerm0
+roles: mockRole3
+user: akarasulu
+profileId: mockProfile3
+
+dn: profileId=mockProfile4,ou=profiles,appName=mockApplication,ou=applications,dc=example,dc=com
+objectClass: top
+objectClass: policyProfile
+denials: mockPerm7
+grants: mockPerm0
+roles: mockRole4
+roles: mockRole3
+user: akarasulu
+profileId: mockProfile4
+

Added: directory/trunks/triplesec/guardian-ldap/src/test/resources/server.xml
URL: http://svn.apache.org/viewvc/directory/trunks/triplesec/guardian-ldap/src/test/resources/server.xml?view=auto&rev=486187
==============================================================================
--- directory/trunks/triplesec/guardian-ldap/src/test/resources/server.xml (added)
+++ directory/trunks/triplesec/guardian-ldap/src/test/resources/server.xml Tue Dec 12 07:23:31 2006
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
+  "http://www.springframework.org/dtd/spring-beans.dtd">
+
+<beans>
+  <bean id="environment" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
+    <property name="properties">
+      <props>
+        <prop key="java.naming.security.authentication">simple</prop>
+        <prop key="java.naming.security.principal">uid=admin,ou=system</prop>
+        <prop key="java.naming.security.credentials">secret</prop>
+        <prop key="java.naming.provider.url">dc=example,dc=com</prop>
+        <prop key="java.naming.factory.state">org.safehaus.triplesec.store.ProfileStateFactory</prop>
+        <prop key="java.naming.factory.object">org.safehaus.triplesec.store.ProfileObjectFactory</prop>
+
+        <prop key="kdc.primary.realm">EXAMPLE.COM</prop>
+        <prop key="kdc.principal">krbtgt/EXAMPLE.COM@EXAMPLE.COM</prop>
+        <prop key="kdc.encryption.types">des-cbc-md5 des3-cbc-sha1 des3-cbc-md5 des-cbc-md4 des-cbc-crc</prop>
+        <prop key="kdc.entryBaseDn">ou=users,dc=example,dc=com</prop>
+        <prop key="kdc.java.naming.security.credentials">secret</prop>
+
+        <prop key="changepw.entryBaseDn">ou=users,dc=example,dc=com</prop>
+        <prop key="changepw.java.naming.security.credentials">secret</prop>
+        <prop key="changepw.principal">kadmin/changepw@EXAMPLE.COM</prop>
+
+        <!-- All times are in minutes -->
+        <prop key="kdc.allowable.clockskew">5</prop>
+        <prop key="kdc.tgs.maximum.ticket.lifetime">1440</prop>
+        <prop key="kdc.tgs.maximum.renewable.lifetime">10080</prop>
+        <prop key="kdc.pa.enc.timestamp.required">true</prop>
+        <prop key="kdc.tgs.empty.addresses.allowed">true</prop>
+        <prop key="kdc.tgs.forwardable.allowed">true</prop>
+        <prop key="kdc.tgs.proxiable.allowed">true</prop>
+        <prop key="kdc.tgs.postdate.allowed">true</prop>
+        <prop key="kdc.tgs.renewable.allowed">true</prop>
+
+        <prop key="safehaus.entry.basedn">ou=Users,dc=example,dc=com</prop>
+        <prop key="safehaus.load.testdata">true</prop>
+        <prop key="kerberos.sam.type.7">org.safehaus.triplesec.verifier.hotp.DefaultHotpSamVerifier</prop>
+      </props>
+    </property>
+  </bean>
+
+  <bean id="configuration" class="org.safehaus.triplesec.configuration.MutableTriplesecStartupConfiguration">
+    <property name="workingDirectory"><value>partitions</value></property>
+    <property name="allowAnonymousAccess"><value>false</value></property>
+    <property name="accessControlEnabled"><value>true</value></property>
+    <property name="ldapPort"><value>10389</value></property>
+    <property name="enableKerberos"><value>true</value></property>
+    <property name="enableNtp"><value>false</value></property>
+    <property name="enableChangePassword"><value>true</value></property>
+
+    <!-- Uncomment below to have the server load entries on startup!        -->
+    <!-- ldifDirectory property can point to a relative file, directory or  -->
+    <!-- can point to an absolute path to either using the URL path         -->
+    <!-- notation: i.e. file:///Users/jack/apacheds/ldifs                   -->
+
+    <!-- Entries will optionally be filtered using LdifLoadFilters in the   -->
+    <!-- order specified.  The included Krb5KdcEntryFilter will filter      -->
+    <!-- kerberos principals creating keys for them using their             -->
+    <!-- userPassword attribute if present.                                 -->
+
+    <!-- If missing the Triplesec server will use LDIF files under the conf -->
+    <!-- directory where it has been installed.                             -->
+
+    <!--
+    <property name="ldifDirectory">
+      <value>example.ldif</value>
+    </property>
+    -->
+    <property name="ldifFilters">
+      <list>
+        <bean class="org.apache.directory.server.protocol.shared.store.Krb5KdcEntryFilter"/>
+      </list>
+    </property>
+
+    <property name="activationConfiguration">
+      <bean class="org.safehaus.triplesec.configuration.ActivationConfiguration">
+        <property name="enableDecoyMidlet"><value>true</value></property>
+        <property name="otpLength"><value>6</value></property>
+        <property name="midletNameAttribute"><value>midletNameAttribute</value></property>
+      </bean>  
+    </property>    
+    
+    <property name="smsConfiguration">
+      <bean class="org.safehaus.triplesec.configuration.SmsConfiguration">
+        <property name="smsUsername"><value>hauskeys</value></property>
+        <property name="smsPassword"><value>secret</value></property>
+        <property name="smsAccountName"><value>demo</value></property>
+        <property name="smsTransportUrl"><value>http://www.nbroadcasting.com/customers/messages/Sender.asp</value></property>
+      </bean>  
+    </property>    
+    
+    <property name="smtpConfiguration">
+      <bean class="org.safehaus.triplesec.configuration.SmtpConfiguration">
+        <property name="smtpAuthenticate"><value>false</value></property>
+        <!-- uncomment and set above property if authentication is required by mail server
+             <property name="smtpUsername"><value>hauskeys</value></property>
+             <property name="smtpPassword"><value>secret</value></property>
+             -->
+             <property name="smtpHost"><value>localhost</value></property>
+             <property name="smtpSubject"><value>Triplesec Account Activated</value></property>
+             <property name="smtpFrom"><value>dev@safehaus.org</value></property>
+           </bean>  
+         </property>    
+         
+    <property name="contextPartitionConfigurations">
+      <set>
+        <ref bean="examplePartitionConfiguration"/>
+      </set>
+    </property>
+    <property name="bootstrapSchemas">
+      <set>
+        <bean class="org.apache.directory.server.core.schema.bootstrap.CorbaSchema"/>
+        <bean class="org.apache.directory.server.core.schema.bootstrap.CoreSchema"/>
+        <bean class="org.apache.directory.server.core.schema.bootstrap.CosineSchema"/>
+        <bean class="org.apache.directory.server.core.schema.bootstrap.ApacheSchema"/>
+        <bean class="org.apache.directory.server.core.schema.bootstrap.CollectiveSchema"/>
+        <bean class="org.apache.directory.server.core.schema.bootstrap.InetorgpersonSchema"/>
+        <bean class="org.apache.directory.server.core.schema.bootstrap.JavaSchema"/>
+        <bean class="org.apache.directory.server.core.schema.bootstrap.Krb5kdcSchema"/>
+        <bean class="org.apache.directory.server.core.schema.bootstrap.SystemSchema"/>
+        <bean class="org.safehaus.triplesec.store.schema.SafehausSchema"/>
+      </set>
+    </property>
+    
+    <property name="extendedOperationHandlers">
+      <list>
+        <bean class="org.apache.directory.server.ldap.support.extended.GracefulShutdownHandler"/>
+        <bean class="org.apache.directory.server.ldap.support.extended.LaunchDiagnosticUiHandler"/>
+      </list>
+    </property>  
+
+    <property name="interceptorConfigurations">
+      <list>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>normalizationService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.directory.server.core.normalization.NormalizationService" />
+          </property>
+        </bean>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>authenticationService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.directory.server.core.authn.AuthenticationService" />
+          </property>
+        </bean>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>referralService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.directory.server.core.referral.ReferralService" />
+          </property>
+        </bean>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>authorizationService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.directory.server.core.authz.AuthorizationService" />
+          </property>
+        </bean>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>defaultAuthorizationService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.directory.server.core.authz.DefaultAuthorizationService" />
+          </property>
+        </bean>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>exceptionService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.directory.server.core.exception.ExceptionService" />
+          </property>
+        </bean>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>schemaService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.directory.server.core.schema.SchemaService" />
+          </property>
+        </bean>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>subentryService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.directory.server.core.subtree.SubentryService" />
+          </property>
+        </bean>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>operationalAttributeService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.directory.server.core.operational.OperationalAttributeService" />
+          </property>
+        </bean>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>collectiveAttributeService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.directory.server.core.collective.CollectiveAttributeService" />
+          </property>
+        </bean>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>eventService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.directory.server.core.event.EventService" />
+          </property>
+        </bean>
+        <bean class="org.apache.directory.server.core.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>policyProtectionService</value></property>
+          <property name="interceptor">
+            <bean class="org.safehaus.triplesec.store.interceptor.PolicyProtectionInterceptor" />
+          </property>
+        </bean>
+      </list>
+    </property>
+  </bean>
+  
+  <bean id="examplePartitionConfiguration" class="org.apache.directory.server.core.configuration.MutablePartitionConfiguration">
+    <property name="name"><value>example</value></property>
+    <property name="suffix"><value>dc=example,dc=com</value></property>
+    <property name="indexedAttributes">
+      <set>
+        <value>objectClass</value>
+        <value>ou</value>
+        <value>dc</value>
+        <value>uid</value>
+        <value>profileId</value>
+        <value>roles</value>
+        <value>grants</value>
+        <value>denials</value>
+        <value>krb5PrincipalName</value>
+      </set>
+    </property>
+    <property name="contextEntry">
+      <value>
+        objectClass: top
+        objectClass: domain
+        objectClass: extensibleObject
+        dc: example
+        administrativeRole: accessControlSpecificArea
+        administrativeRole: collectiveAttributeSpecificArea
+      </value>
+    </property>
+  </bean>
+
+  <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
+    <property name="customEditors">
+      <map>
+        <entry key="javax.naming.directory.Attributes">
+          <bean class="org.apache.directory.server.core.configuration.AttributesPropertyEditor"/>
+        </entry>
+      </map>
+   </property>
+  </bean>
+</beans>

Added: directory/trunks/triplesec/guardian-ldif/pom.xml
URL: http://svn.apache.org/viewvc/directory/trunks/triplesec/guardian-ldif/pom.xml?view=auto&rev=486187
==============================================================================
--- directory/trunks/triplesec/guardian-ldif/pom.xml (added)
+++ directory/trunks/triplesec/guardian-ldif/pom.xml Tue Dec 12 07:23:31 2006
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  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. 
+-->
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.safehaus.triplesec</groupId>
+    <artifactId>build</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>triplesec-guardian-ldif</artifactId>
+  <name>Triplesec Guardian LDIF Driver</name>
+  <description>
+    A driver which uses an LDAP LDIF as the policy store.
+  </description>
+  <packaging>jar</packaging>  
+  <dependencies>
+    <dependency>
+      <artifactId>nlog4j</artifactId>
+      <groupId>org.slf4j</groupId>
+      <version>1.2.25</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <artifactId>shared-ldap</artifactId>
+      <groupId>org.apache.directory.shared</groupId>
+      <version>0.9.5.3-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <artifactId>triplesec-guardian-api</artifactId>
+      <groupId>${pom.groupId}</groupId>
+      <version>${pom.version}</version>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <systemProperties>
+            <property>
+              <name>ldif.url</name>
+              <value>file://${basedir}/src/test/resources/server.ldif</value>
+            </property>
+          </systemProperties>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

Added: directory/trunks/triplesec/guardian-ldif/src/main/java/org/safehaus/triplesec/guardian/ldif/LdifApplicationPolicy.java
URL: http://svn.apache.org/viewvc/directory/trunks/triplesec/guardian-ldif/src/main/java/org/safehaus/triplesec/guardian/ldif/LdifApplicationPolicy.java?view=auto&rev=486187
==============================================================================
--- directory/trunks/triplesec/guardian-ldif/src/main/java/org/safehaus/triplesec/guardian/ldif/LdifApplicationPolicy.java (added)
+++ directory/trunks/triplesec/guardian-ldif/src/main/java/org/safehaus/triplesec/guardian/ldif/LdifApplicationPolicy.java Tue Dec 12 07:23:31 2006
@@ -0,0 +1,557 @@
+/*
+ *  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.safehaus.triplesec.guardian.ldif;
+
+
+import org.apache.directory.shared.ldap.ldif.Entry;
+import org.apache.directory.shared.ldap.ldif.LdifReader;
+import org.safehaus.triplesec.guardian.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.naming.directory.*;
+import javax.naming.NamingException;
+import javax.naming.NamingEnumeration;
+
+import java.io.File;
+import java.util.*;
+
+
+/**
+ * An LDIF file backed implementation of an application policy store.
+ *
+ * @author <a href="mailto:akarasulu@safehaus.org">Alex Karasulu</a>
+ * @version $Rev$
+ */
+class LdifApplicationPolicy implements ApplicationPolicy
+{
+    /** the logger interface for this class */
+    private static Logger log = LoggerFactory.getLogger( LdifApplicationPolicy.class );
+    /** the name of the application this store is associated with */
+    private final String applicationName;
+    /** the dn of the application */
+    private final String applicationDn;
+    /** a breif description of this application */
+    private String description;
+    /** the LDIF file that was loaded for this application */
+    private final File ldifFile;
+    /** the raw entries contained within the LDIF file */
+//    private final Map entries;
+//    private Attributes application = null;
+    /** the {@link Permissions} defined for this store's application */
+    private Permissions permissions;
+    /** the {@link Roles} defined for this store's application */
+    private Roles roles;
+    /** the {@link Profile}s loaded from LDIF */
+    private Map profileMap;
+    /** map of userNames to sets of profile ids */
+    private Map userProfilesMap;
+
+    boolean isClosed = false;
+    /** the administrators super profile */
+    private Profile adminProfile;
+
+    
+    /**
+     * Creates an instance of the LDIF ApplicationPolicyStore.  Two properties are 
+     * expected in the info properties.  One is the dn of the application principal.  
+     * The other is the path to an ldif file.
+     * <table>
+     *   <tr><th>property</th><th>description</th></tr>
+     *   <tr><td>applicationPrincipalDN</td><td>the distinguished name of the application</td></tr>
+     *   <tr><td>ldifFilePath</td><td>the path to the LDIF file containing the entries to load</td></tr>
+     * </table>
+     *
+     * @param ctx the base context under which ou=applications and ou=users can be found
+     * @param info additional information needed to load the LDIF file
+     * @throws GuardianException if failures are encountered while loading objects from the backing store
+     */
+    public LdifApplicationPolicy( File ldifFile, Properties info ) throws GuardianException
+    {
+        this.userProfilesMap = new HashMap();
+        this.profileMap = new HashMap();
+        this.applicationDn = info.getProperty( "applicationPrincipalDN" );
+        // extract the applicationName from the applicationPrincipalDN
+        this.applicationName = getApplicationName( applicationDn );
+        // extract the path to the LDIF file to load 
+        this.ldifFile = ldifFile;
+        // loads the ldifs as a map of LdapNames to Attributes
+        load();
+        // create the admin profile with all permissions as grants and in all roles
+        this.adminProfile = new Profile( this, "admin", "admin", roles, permissions, 
+            new Permissions( applicationName, new Permission[0] ), false );
+    }
+
+    
+    private Map load() throws GuardianException
+    {
+        Map roleMap = new HashMap();
+        Map permissionMap = new HashMap();
+        Map profileMap = new HashMap();
+        Map entryMap = new HashMap();
+        try
+        {
+            LdifReader reader = new LdifReader();
+            List entries = reader.parseLdifFile( ldifFile.getAbsolutePath() );
+            for ( int ii = 0; ii < entries.size(); ii++ )
+            {
+                Entry entry = ( Entry ) entries.get( ii );
+                Attributes attributes = entry.getAttributes();
+                String dn = entry.getDn();
+                entryMap.put( dn, attributes );
+                
+                if ( dn.equals( applicationDn ) )
+                {
+//                    application = attributes;
+                }
+                else if ( dn.endsWith( applicationDn ) )
+                {
+                    Attribute oc = attributes.get( "objectClass" );
+                    if ( oc.contains( "policyPermission" ) )
+                    {
+                        permissionMap.put( dn, attributes );
+                    }
+                    else if ( oc.contains( "policyRole" ) )
+                    {
+                        roleMap.put( dn, attributes );
+                    }
+                    else if ( oc.contains( "policyProfile" ) )
+                    {
+                        profileMap.put( dn, attributes );
+                    }
+                }
+            }
+        }
+        catch ( Exception e )
+        {
+            String msg = "Failed to read from ldifFile '" + ldifFile + "'.";
+            log.error( msg, e );
+            throw new GuardianException( msg, e );
+        }
+        
+        loadPermissions( permissionMap );
+        loadRoles( roleMap );
+        loadProfiles( profileMap );
+        return entryMap;
+    }
+    
+
+    /**
+     * Loads the role entries extracted from the LDIF.
+     * 
+     * @throws GuardianException if there is a problem with a role 
+     */
+    private void loadRoles( Map roleMap ) throws GuardianException
+    {
+        Set roleSet = new HashSet();
+
+        try
+        {
+            Iterator keys = roleMap.keySet().iterator();
+            while ( keys.hasNext() )
+            {
+                String dn = ( String ) keys.next();
+                Attributes entry = ( Attributes ) roleMap.get( dn );
+                String roleName = ( String ) entry.get( "roleName" ).get();
+                Set permSet = new HashSet();
+                Attribute attributes = entry.get( "grants" );
+
+                if ( attributes != null )
+                {
+                    NamingEnumeration grantsEnumeration = entry.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 = entry.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() );
+                }
+
+                roleSet.add( role );
+                log.debug( "loading role '" + roleName + "' 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 );
+    }
+
+
+    /**
+     * Loads the permission entries extracted from the LDIF.
+     * 
+     * @throws GuardianException if there is a problem with a permission
+     */
+    private void loadPermissions( Map permissionMap ) throws GuardianException
+    {
+        Set permSet = new HashSet();
+
+        try
+        {
+            Iterator keys = permissionMap.keySet().iterator();
+            while ( keys.hasNext() )
+            {
+                String dn = ( String ) keys.next();
+                Attributes entry = ( Attributes ) permissionMap.get( dn );
+                String permName = ( String ) entry.get( "permName" ).get();
+                Permission perm;
+                Attribute description = entry.get( "description" );
+                if ( description != null )
+                {
+                    perm = new Permission( applicationName, permName, ( String ) description.get() );
+                }
+                else
+                {
+                    perm = new Permission( applicationName, permName );
+                }
+                log.debug( "loading permission " + permName + " for application " + applicationName );
+                permSet.add( perm );
+            }
+        }
+        catch ( NamingException e )
+        {
+            String msg = "Failed on load of 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 );
+    }
+
+
+    public String getApplicationName()
+    {
+        return this.applicationName;
+    }
+
+
+    public String getDescription()
+    {
+        return this.description;
+    }
+
+
+    public Roles getRoles()
+    {
+        return this.roles;
+    }
+
+
+    public Permissions getPermissions()
+    {
+        return permissions;
+    }
+
+    
+    private static boolean parseBoolean( String bool )
+    {
+        if ( bool.equals( "true" ) )
+        {
+            return true;
+        }
+        
+        return false;
+    }
+
+    
+    /**
+     * Loads the profile entries extracted from the LDIF.
+     * 
+     * @throws GuardianException if there is a problem with a profile 
+     */
+    private void loadProfiles( Map profileEntryMap ) throws GuardianException
+    {
+        String[] profileDns = new String[profileEntryMap.size()];
+        profileEntryMap.keySet().toArray( profileDns );
+        
+        for ( int ii = 0; ii < profileDns.length; ii++ )
+        {
+            Profile profile;
+            Permissions grants;
+            Permissions denials;
+            Roles roles;
+            String dn = profileDns[ii];
+            Attributes entry = ( Attributes ) profileEntryMap.get( dn );
+            String profileId;
+            String userName;
+            boolean disabled = false;
+            
+            Attribute disabledAttr = entry.get( "safehausDisabled" );
+            try
+            {
+                if ( disabledAttr != null )
+                {
+                    disabled = parseBoolean( ( ( String ) disabledAttr.get() ).toLowerCase() );
+                }
+            }
+            catch ( Exception e )
+            {
+                throw new GuardianException( "Failed trying to access safehausDiabled attribute: " + dn );
+            }
+            
+            try
+            {
+                profileId = ( String ) entry.get( "profileId" ).get();
+            }
+            catch ( Exception e )
+            {
+                throw new GuardianException( "Could not find profileId attribute for profile: " + dn );
+            }
+
+            try
+            {
+                userName = ( String ) entry.get( "user" ).get();
+            }
+            catch ( Exception e )
+            {
+                throw new GuardianException( "Could not find user attribute for profile: " + dn );
+            }
+
+            // -------------------------------------------------------------------------------
+            // process and assemble the profile's granted permissions
+            // -------------------------------------------------------------------------------
+
+            Attribute grantsAttribute = entry.get( "grants" );
+            if ( grantsAttribute != null )
+            {
+                Set grantsSet = new HashSet();
+                try
+                {
+                    NamingEnumeration grantsEnumeration = grantsAttribute.getAll();
+                    while ( grantsEnumeration.hasMore() )
+                    {
+                        String grantedPermName = ( String ) grantsEnumeration.next();
+                        grantsSet.add( this.permissions.get( grantedPermName ) );
+                    }
+                }
+                catch ( NamingException e )
+                {
+                    throw new GuardianException( "Failed to get grants for profile: " + dn );
+                }
+
+                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 = entry.get( "denials" );
+            if ( denialsAttribute != null )
+            {
+                Set denialsSet = new HashSet();
+                try
+                {
+                    NamingEnumeration denialsEnumeration = denialsAttribute.getAll();
+                    while ( denialsEnumeration.hasMore() )
+                    {
+                        String deniedPermName = ( String ) denialsEnumeration.next();
+                        denialsSet.add( this.permissions.get( deniedPermName ) );
+                    }
+                }
+                catch ( NamingException e )
+                {
+                    throw new GuardianException( "Failed to get denials for profile: " + dn );
+                }
+                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 = entry.get( "roles" );
+            if ( rolesAttribute != null )
+            {
+                Set rolesSet = new HashSet();
+                try
+                {
+                    NamingEnumeration rolesEnumeration = rolesAttribute.getAll();
+                    while ( rolesEnumeration.hasMore() )
+                    {
+                        String assignedRoleName = ( String ) rolesEnumeration.next();
+                        rolesSet.add( this.roles.get( assignedRoleName ) );
+                    }
+                }
+                catch ( NamingException e )
+                {
+                    throw new GuardianException( "Failed to get roles for profile: " + dn );
+                }
+                Role[] rolesArray = new Role[rolesSet.size()];
+                roles = new Roles( applicationName, ( Role[] ) rolesSet.toArray( rolesArray ) );
+            }
+            else
+            {
+                roles = new Roles( applicationName, new Role[0] );
+            }
+
+            Attribute description = entry.get( "description" );
+            if ( description == null || description.size() == 0 )
+            {
+                profile = new Profile( this, profileId, userName, roles, grants, denials, disabled );
+            }
+            else
+            {
+                String desc = "null";
+                try
+                {
+                    desc = ( String ) description.get();
+                }
+                catch ( NamingException e )
+                {
+                    throw new GuardianException( "Failed to get description for profile: " + dn );
+                }
+                profile = new Profile( this, profileId, userName, roles, grants, denials, desc, disabled );
+            }
+            
+            profileMap.put( profileId, profile );
+            
+            Set profileIdSet = ( Set ) userProfilesMap.get( userName );
+            if ( profileIdSet == null )
+            {
+                profileIdSet = new HashSet();
+                userProfilesMap.put( userName, profileIdSet );
+            }
+            profileIdSet.add( profileId );
+
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "loaded profile '" + profileId + "' in application '" + applicationName + "'" );
+            }
+        }
+    }
+    
+
+    public Profile getProfile( String userName ) throws GuardianException
+    {
+        if ( isClosed )
+        {
+            throw new IllegalStateException( "This policy object has been closed." );
+        }
+
+        if ( profileMap.containsKey( userName ) )
+        {
+            return ( Profile ) profileMap.get( userName );
+        }
+
+        return null;
+    }
+
+
+    public void close() throws GuardianException
+    {
+        isClosed = true;
+    }
+
+
+    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();
+    }
+
+
+    public boolean removePolicyListener( PolicyChangeListener listener )
+    {
+        throw new RuntimeException( "Not implemented yet!" );
+    }
+
+
+    public boolean addPolicyListener( PolicyChangeListener listener )
+    {
+        throw new RuntimeException( "Not implemented yet!" );
+    }
+
+
+    public Set getDependentProfileNames( Role role ) throws GuardianException
+    {
+        throw new RuntimeException( "Not implemented yet!" );
+    }
+
+
+    public Set getDependentProfileNames( Permission permission ) throws GuardianException
+    {
+        throw new RuntimeException( "Not implemented yet!" );
+    }
+
+
+    public Set getUserProfileIds( String userName ) throws GuardianException
+    {
+        Set profileSet = ( Set ) userProfilesMap.get( userName );
+        if ( profileSet == null )
+        {
+            return Collections.EMPTY_SET;
+        }
+        return Collections.unmodifiableSet( profileSet );
+    }
+    
+    
+    public Iterator getProfileIdIterator()
+    {
+        return profileMap.keySet().iterator();
+    }
+
+
+    public Profile getAdminProfile()
+    {
+        return adminProfile;
+    }
+}