You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by vt...@apache.org on 2004/06/15 05:05:15 UTC

svn commit: rev 21252 - in incubator/directory/janus/trunk/core: api/src/java/org/apache/janus/authentication/group impl/src/java/org/apache/janus/authentication impl/src/java/org/apache/janus/authentication/group impl/src/java/org/apache/janus/authentication/realm impl/src/java/org/apache/janus/authorization/policy impl/src/test/org/apache/janus/authentication impl/src/test/org/apache/janus/authentication/group impl/src/test/org/apache/janus/authentication/realm impl/src/test/org/apache/janus/authorization

Author: vtence
Date: Mon Jun 14 20:05:14 2004
New Revision: 21252

Added:
   incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/
   incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/DuplicateGroupException.java
   incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/GroupManager.java
   incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/MutableGroupManager.java
   incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/NoSuchGroupException.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/AbstractPrincipal.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/DefaultGroupManager.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/DefaultGroupPrincipalFactory.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/Group.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/GroupPrincipal.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/GroupPrincipalFactory.java
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/FruitCredential.java
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/group/
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/group/DefaultGroupManagerTest.java
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/realm/DummyCredential.java
Removed:
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/AbstractPrincipal.java
Modified:
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/DefaultAuthenticator.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/UsernamePrincipal.java
   incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authorization/policy/DefaultPolicyContext.java
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/DefaultAuthenticatorTest.java
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/FruitPrincipal.java
   incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authorization/SSNPrincipal.java
Log:
First cut for group of principals (DIRJANUS-22)

Added: incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/DuplicateGroupException.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/DuplicateGroupException.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,33 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication.group;
+
+/**
+ * @author <a href="mailto:vtence@apache.org">Vincent Tence</a>
+ */
+public class DuplicateGroupException extends Exception
+{
+    public DuplicateGroupException( String message )
+    {
+        super( message );
+    }
+
+    public DuplicateGroupException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}

Added: incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/GroupManager.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/GroupManager.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,27 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication.group;
+
+import java.security.Principal;
+
+/**
+ * @author <a href="mailto:vtence@apache.org">Vincent Tence</a>
+ */
+public interface GroupManager
+{
+    Principal[] getGroupsFor( Principal p );
+}

Added: incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/MutableGroupManager.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/MutableGroupManager.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,17 @@
+package org.apache.janus.authentication.group;
+
+import java.security.Principal;
+
+/**
+ * @author <a href="mailto:vtence@optimuminformatique.com">Vincent Tence</a>
+ */
+public interface MutableGroupManager extends GroupManager
+{
+    Principal[] getGroupsFor( Principal p );
+
+    void addGroup( String groupName ) throws DuplicateGroupException;
+
+    boolean addPrincipal( String groupName, Principal p ) throws NoSuchGroupException;
+
+    boolean addSubGroup( String groupName, String subGroupName ) throws NoSuchGroupException;
+}
\ No newline at end of file

Added: incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/NoSuchGroupException.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/api/src/java/org/apache/janus/authentication/group/NoSuchGroupException.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,17 @@
+package org.apache.janus.authentication.group;
+
+/**
+ * @author <a href="mailto:vtence@optimuminformatique.com">Vincent Tence</a>
+ */
+public class NoSuchGroupException extends Exception
+{
+    public NoSuchGroupException( String message )
+    {
+        super( message );
+    }
+
+    public NoSuchGroupException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+}
\ No newline at end of file

Added: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/AbstractPrincipal.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/AbstractPrincipal.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,68 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication;
+
+import java.security.Principal;
+
+/**
+ * A principal name is unique within the set
+ * of principals of the same type.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ */
+public abstract class AbstractPrincipal implements Principal
+{
+    private final String m_name;
+
+    public AbstractPrincipal( String name )
+    {
+        if ( name == null ) throw new NullPointerException( "name" );
+        if ( name.equals( "" ) )
+        {
+            throw new IllegalArgumentException( "Empty name" );
+        }
+        m_name = name;
+    }
+
+    public String getName()
+    {
+        return m_name;
+    }
+
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( !(o instanceof AbstractPrincipal) ) return false;
+
+        final AbstractPrincipal abstractPrincipal = ( AbstractPrincipal ) o;
+
+        if ( !m_name.equals( abstractPrincipal.m_name ) ) return false;
+
+        return true;
+    }
+
+    public int hashCode()
+    {
+        return m_name.hashCode();
+    }
+
+    public String toString()
+    {
+        return "name=" + m_name;
+    }
+}
+

Modified: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/DefaultAuthenticator.java
==============================================================================
--- incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/DefaultAuthenticator.java	(original)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/DefaultAuthenticator.java	Mon Jun 14 20:05:14 2004
@@ -17,9 +17,11 @@
 package org.apache.janus.authentication;
 
 import org.apache.janus.authentication.realm.Realm;
+import org.apache.janus.authentication.group.GroupManager;
 
 import javax.security.auth.Subject;
 import java.security.Principal;
+import java.util.Arrays;
 
 /**
  * An implementation of an authenticator that uses a single realm to perform authentication.
@@ -29,10 +31,12 @@
 public class DefaultAuthenticator implements Authenticator
 {
     private final Realm m_realm;
+    private final GroupManager m_groupManager;
 
-    public DefaultAuthenticator( Realm realm )
+    public DefaultAuthenticator( Realm realm, GroupManager groupManager )
     {
         m_realm = realm;
+        m_groupManager = groupManager;
     }
 
     public Subject authenticate( CredentialSet credentials )
@@ -46,6 +50,9 @@
 
         Subject subject = new Subject();
         subject.getPrincipals().add( p );
+
+        Principal[] groups = m_groupManager.getGroupsFor( p );
+        subject.getPrincipals().addAll( Arrays.asList( groups ));
 
         return subject;
     }

Added: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/DefaultGroupManager.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/DefaultGroupManager.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,89 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication.group;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:vtence@apache.org">Vincent Tence</a>
+ */
+public class DefaultGroupManager implements MutableGroupManager
+{
+    private final Map m_groups;
+    private final GroupPrincipalFactory m_principalFactory;
+
+    public DefaultGroupManager()
+    {
+        this( new DefaultGroupPrincipalFactory() );
+    }
+
+    public DefaultGroupManager( GroupPrincipalFactory principalFactory )
+    {
+        m_principalFactory = principalFactory;
+        m_groups = new HashMap();
+    }
+
+    public Principal[] getGroupsFor( Principal p )
+    {
+        final Collection groups = new ArrayList();
+        for ( Iterator it = m_groups.values().iterator(); it.hasNext(); )
+        {
+            final Group group = ( Group ) it.next();
+            if ( group.isMember( p ) ) groups.add( m_principalFactory.newGroupPrincipal( group.getName() ) );
+        }
+
+        return ( GroupPrincipal[] ) groups.toArray( new GroupPrincipal[groups.size()] );
+    }
+
+    public void addGroup( String groupName ) throws DuplicateGroupException
+    {
+        if ( containsGroup( groupName ) ) throw new DuplicateGroupException( "Group name already exists: " + groupName );
+        m_groups.put( groupName, new Group( groupName ) );
+    }
+
+    private boolean containsGroup( String groupName )
+    {
+        return m_groups.containsKey( groupName );
+    }
+
+    public boolean addPrincipal( String groupName, Principal p ) throws NoSuchGroupException
+    {
+        final Group group = getGroup( groupName );
+        if ( group == null ) throw new NoSuchGroupException( groupName );
+        return group.addMember( p );
+    }
+
+    public boolean addSubGroup( String groupName, String subGroupName ) throws NoSuchGroupException
+    {
+        final Group grandGroup = getGroup( groupName );
+        if ( grandGroup == null ) throw new NoSuchGroupException( groupName );
+        final Group subGroup = getGroup( subGroupName );
+        if ( subGroup == null ) throw new NoSuchGroupException( subGroupName );
+
+        return grandGroup.addSubGroup( subGroup );
+    }
+
+    private Group getGroup( String groupName )
+    {
+        return ( Group ) m_groups.get( groupName );
+    }
+}

Added: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/DefaultGroupPrincipalFactory.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/DefaultGroupPrincipalFactory.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,30 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication.group;
+
+import java.security.Principal;
+
+/**
+ * @author <a href="mailto:vtence@apache.org">Vincent Tence</a>
+ */
+public class DefaultGroupPrincipalFactory implements GroupPrincipalFactory
+{
+    public Principal newGroupPrincipal( String groupName )
+    {
+        return new GroupPrincipal( groupName );
+    }
+}

Added: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/Group.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/Group.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,71 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication.group;
+
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:vtence@apache.org">Vincent Tence</a>
+ */
+public class Group
+{
+    private final String m_name;
+    private final Set m_members;
+    private final Map m_subGroups;
+
+    public Group( String name )
+    {
+        m_name = name;
+        m_members = new HashSet();
+        m_subGroups = new HashMap();
+    }
+
+    public String getName()
+    {
+        return m_name;
+    }
+
+    public boolean addMember( Principal p )
+    {
+        return m_members.add( p );
+    }
+
+    public boolean isMember( Principal p )
+    {
+        if ( m_members.contains( p ) ) return true;
+
+        for ( Iterator it = m_subGroups.values().iterator(); it.hasNext(); )
+        {
+            Group subGroup = ( Group ) it.next();
+            if ( subGroup.isMember( p ) ) return true;
+        }
+
+        return false;
+    }
+
+    public boolean addSubGroup( Group subGroup )
+    {
+        if ( m_subGroups.containsKey( subGroup.getName() ) ) return false;
+        m_subGroups.put( subGroup.getName(), subGroup );
+        return true;
+    }
+}

Added: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/GroupPrincipal.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/GroupPrincipal.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,50 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication.group;
+
+import org.apache.janus.authentication.AbstractPrincipal;
+
+/**
+ * @author <a href="mailto:vtence@apache.org">Vincent Tence</a>
+ */
+public class GroupPrincipal extends AbstractPrincipal
+{
+    public GroupPrincipal( String name )
+    {
+        super( name );
+    }
+
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( !(o instanceof GroupPrincipal) ) return false;
+        if ( !super.equals( o ) ) return false;
+
+        return true;
+    }
+
+    public int hashCode()
+    {
+        return super.hashCode();
+    }
+
+    public String toString()
+    {
+        return "GroupPrincipal: " + super.toString() + "";
+    }
+
+}

Added: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/GroupPrincipalFactory.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/group/GroupPrincipalFactory.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,27 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication.group;
+
+import java.security.Principal;
+
+/**
+ * @author <a href="mailto:vtence@apache.org">Vincent Tence</a>
+ */
+public interface GroupPrincipalFactory
+{
+    Principal newGroupPrincipal( String groupName );
+}

Modified: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/UsernamePrincipal.java
==============================================================================
--- incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/UsernamePrincipal.java	(original)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authentication/realm/UsernamePrincipal.java	Mon Jun 14 20:05:14 2004
@@ -16,6 +16,8 @@
  */
 package org.apache.janus.authentication.realm;
 
+import org.apache.janus.authentication.AbstractPrincipal;
+
 /**
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
  */

Modified: incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authorization/policy/DefaultPolicyContext.java
==============================================================================
--- incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authorization/policy/DefaultPolicyContext.java	(original)
+++ incubator/directory/janus/trunk/core/impl/src/java/org/apache/janus/authorization/policy/DefaultPolicyContext.java	Mon Jun 14 20:05:14 2004
@@ -23,11 +23,9 @@
 import java.util.Map;
 
 /**
- * todo: use a map indexed on role names instead of a set
- *
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
  */
-public class DefaultPolicyContext implements PolicyContext
+public class DefaultPolicyContext implements MutablePolicyContext
 {
     private final PermissionCollection m_excludedPermissions;
     private final PermissionCollection m_uncheckedPermissions;

Modified: incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/DefaultAuthenticatorTest.java
==============================================================================
--- incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/DefaultAuthenticatorTest.java	(original)
+++ incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/DefaultAuthenticatorTest.java	Mon Jun 14 20:05:14 2004
@@ -16,12 +16,16 @@
  */
 package org.apache.janus.authentication;
 
+import org.apache.janus.authentication.group.GroupManager;
+import org.apache.janus.authentication.group.GroupPrincipal;
 import org.apache.janus.authentication.realm.Realm;
-import org.apache.janus.authentication.realm.UsernameCredential;
 import org.jmock.Mock;
 import org.jmock.MockObjectTestCase;
 
 import javax.security.auth.Subject;
+import java.security.Principal;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
@@ -30,6 +34,7 @@
 {
     private DefaultAuthenticator m_authenticator;
     private Mock m_mockRealm;
+    private Mock m_mockGroupManager;
 
     public static void main( String[] args )
     {
@@ -40,11 +45,12 @@
     {
         m_mockRealm
                 = new Mock( Realm.class );
+        m_mockGroupManager = new Mock( GroupManager.class );
         m_authenticator
-                = new DefaultAuthenticator( ( Realm ) m_mockRealm.proxy() );
+                = new DefaultAuthenticator( ( Realm ) m_mockRealm.proxy(), (GroupManager) m_mockGroupManager.proxy() );
     }
 
-    private CredentialSet banana()
+    private CredentialSet bananaCreds()
     {
         CredentialSet credentials = new CredentialSet();
         credentials.add( new FruitCredential( "banana" ) );
@@ -53,19 +59,27 @@
 
     public void testAuthentication()
     {
-        m_mockRealm.expects( once() ).method( "validateCredentials" ).with( eq( banana() ) ).will( returnValue( new FruitPrincipal( "banana" ) ) );
+        m_mockRealm.expects( once() ).method( "validateCredentials" ).with( eq( bananaCreds() ) ).will( returnValue( banana() ) );
+        m_mockGroupManager.stubs().method( "getGroupsFor" ).will( returnValue( new GroupPrincipal[] {} ) );
 
         Subject subject = null;
         try
         {
-            subject = m_authenticator.authenticate( banana() );
+            subject = m_authenticator.authenticate( bananaCreds() );
         }
         catch ( AuthenticationException e )
         {
             fail( "Login failed" );
         }
         assertTrue( "Principal was not added to subject",
-                subject.getPrincipals().contains( new FruitPrincipal( "banana" ) ) );
+                subject.getPrincipals().contains( banana() ) );
+
+        m_mockRealm.verify();
+    }
+
+    private FruitPrincipal banana()
+    {
+        return new FruitPrincipal( "banana" );
     }
 
     public void testAuthenticationFailure()
@@ -81,5 +95,38 @@
         {
             assertTrue( true );
         }
+    }
+
+    public void testPrincipalGroupsAreAddedToSubject() throws Exception
+    {
+        m_mockRealm.stubs().method( "validateCredentials" ).will( returnValue( banana() ) );
+        m_mockGroupManager.expects( once() ).method( "getGroupsFor" ).with( eq( banana() ) ).will( returnValue( bananaGroups() ) );
+
+        Subject s = m_authenticator.authenticate( bananaCreds() );
+
+        Set expected = new HashSet( );
+        expected.add( tasty() );
+        expected.add( yellow() );
+        Set actual = s.getPrincipals( GroupPrincipal.class );
+        assertEquals( expected, actual );
+
+        m_mockGroupManager.verify();
+    }
+
+    private Principal[] bananaGroups()
+    {
+        return new GroupPrincipal[]{tasty(), yellow()};
+    }
+
+    private GroupPrincipal yellow()
+    {
+        GroupPrincipal yellow = new GroupPrincipal( "yellow" );
+        return yellow;
+    }
+
+    private GroupPrincipal tasty()
+    {
+        GroupPrincipal tasty = new GroupPrincipal( "tasty" );
+        return tasty;
     }
 }

Added: incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/FruitCredential.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/FruitCredential.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,49 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication;
+
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:vtence@apache.org">Vincent Tence</a>
+ */
+public class FruitCredential implements Serializable
+{
+    private final String m_name;
+
+    public FruitCredential( String name )
+    {
+        m_name = name;
+    }
+
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( !(o instanceof FruitCredential) ) return false;
+
+        final FruitCredential fruitCredential = ( FruitCredential ) o;
+
+        if ( !m_name.equals( fruitCredential.m_name ) ) return false;
+
+        return true;
+    }
+
+    public int hashCode()
+    {
+        return m_name.hashCode();
+    }
+}

Modified: incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/FruitPrincipal.java
==============================================================================
--- incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/FruitPrincipal.java	(original)
+++ incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/FruitPrincipal.java	Mon Jun 14 20:05:14 2004
@@ -16,7 +16,7 @@
  */
 package org.apache.janus.authentication;
 
-import org.apache.janus.authentication.realm.AbstractPrincipal;
+import org.apache.janus.authentication.AbstractPrincipal;
 
 /**
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>

Added: incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/group/DefaultGroupManagerTest.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/group/DefaultGroupManagerTest.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,156 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication.group;
+
+import junit.framework.TestCase;
+import org.apache.janus.authentication.realm.UsernamePrincipal;
+
+import java.security.Principal;
+import java.util.Arrays;
+
+/**
+ * @author <a href="mailto:vtence@apache.org">Vincent Tence</a>
+ */
+public class DefaultGroupManagerTest extends TestCase
+{
+    private DefaultGroupManager m_defaultGroupManager;
+
+    public static void main( String[] args )
+    {
+        junit.textui.TestRunner.run( DefaultGroupManager.class );
+    }
+
+    protected void setUp() throws Exception
+    {
+        m_defaultGroupManager = new DefaultGroupManager();
+    }
+
+    public void testReturnsGroupsAssociatedToPrincipal() throws Exception
+    {
+        m_defaultGroupManager.addGroup( "geeks" );
+        m_defaultGroupManager.addPrincipal( "geeks", john() );
+        m_defaultGroupManager.addGroup( "men" );
+        m_defaultGroupManager.addPrincipal( "men", john() );
+
+        GroupPrincipal[] expected = new GroupPrincipal[]{geeks(), men()};
+        Principal[] actuals = m_defaultGroupManager.getGroupsFor( john() );
+
+        assertTrue( Arrays.equals( expected, actuals ) );
+    }
+
+    public void testPrincipalBelongsToNoGroupByDefault()
+    {
+        assertEquals( 0, m_defaultGroupManager.getGroupsFor( john() ).length );
+    }
+
+    public void testGroupsAreOnlyAllowedOnce() throws Exception
+    {
+        m_defaultGroupManager.addGroup( "geeks" );
+        try
+        {
+            m_defaultGroupManager.addGroup( "geeks" );
+            fail( "Same group was added twice" );
+        }
+        catch ( DuplicateGroupException e )
+        {
+            assertTrue( true );
+        }
+    }
+
+    public void testReportsDuplicatePrincipalInGroup() throws Exception
+    {
+        m_defaultGroupManager.addGroup( "geeks" );
+        assertTrue( m_defaultGroupManager.addPrincipal( "geeks", john() ) );
+        assertFalse( m_defaultGroupManager.addPrincipal( "geeks", john() ) );
+    }
+
+    public void testGroupsMustExistToAddAPrincipal()
+    {
+        try
+        {
+            m_defaultGroupManager.addPrincipal( "geeks", john() );
+            fail( "Group doesn't exist, yet principal was added" );
+        }
+        catch ( NoSuchGroupException e )
+        {
+            assertTrue( true );
+        }
+    }
+
+    public void testGroupMembershipIsInherited() throws Exception
+    {
+        m_defaultGroupManager.addGroup( "men" );
+        m_defaultGroupManager.addGroup( "geeks" );
+        m_defaultGroupManager.addSubGroup( "men", "geeks" );
+        m_defaultGroupManager.addPrincipal( "geeks", john() );
+        Principal[] groups = m_defaultGroupManager.getGroupsFor( john() );
+
+        assertTrue( Arrays.asList( groups ).contains( new GroupPrincipal( "men" ) ) );
+    }
+
+    public void testSubGroupMustBeDefined() throws Exception
+    {
+        m_defaultGroupManager.addGroup( "men" );
+        try
+        {
+            m_defaultGroupManager.addSubGroup( "men", "geeks" );
+            fail( "Sub group not defined" );
+        }
+        catch ( NoSuchGroupException e )
+        {
+            assertTrue( true );
+        }
+    }
+
+    public void testGrandGroupMustBeDefined() throws Exception
+    {
+        m_defaultGroupManager.addGroup( "geeks" );
+        try
+        {
+            m_defaultGroupManager.addSubGroup( "men", "geeks" );
+            fail( "Grand group not defined" );
+        }
+        catch ( NoSuchGroupException e )
+        {
+            assertTrue( true );
+        }
+
+    }
+
+    public void testReportsDuplicateSubGroups() throws Exception
+    {
+        m_defaultGroupManager.addGroup( "men" );
+        m_defaultGroupManager.addGroup( "geeks" );
+        assertTrue( m_defaultGroupManager.addSubGroup( "men", "geeks" ) );
+        assertFalse( m_defaultGroupManager.addSubGroup( "men", "geeks" ) );
+    }
+
+    private GroupPrincipal geeks()
+    {
+        return new GroupPrincipal( "geeks" );
+    }
+
+    private GroupPrincipal men()
+    {
+        return new GroupPrincipal( "men" );
+    }
+
+    private UsernamePrincipal john()
+    {
+        return new UsernamePrincipal( "john" );
+    }
+}

Added: incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/realm/DummyCredential.java
==============================================================================
--- (empty file)
+++ incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authentication/realm/DummyCredential.java	Mon Jun 14 20:05:14 2004
@@ -0,0 +1,49 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.janus.authentication.realm;
+
+import java.io.Serializable;
+
+/**
+ * @author <a href="mailto:vtence@apache.org">Vincent Tence</a>
+ */
+public class DummyCredential implements Serializable
+{
+    private final String m_value;
+
+    public DummyCredential( String value )
+    {
+        m_value = value;
+    }
+
+    public boolean equals( Object o )
+    {
+        if ( this == o ) return true;
+        if ( !(o instanceof DummyCredential) ) return false;
+
+        final DummyCredential dummyCredential = ( DummyCredential ) o;
+
+        if ( !m_value.equals( dummyCredential.m_value ) ) return false;
+
+        return true;
+    }
+
+    public int hashCode()
+    {
+        return m_value.hashCode();
+    }
+}

Modified: incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authorization/SSNPrincipal.java
==============================================================================
--- incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authorization/SSNPrincipal.java	(original)
+++ incubator/directory/janus/trunk/core/impl/src/test/org/apache/janus/authorization/SSNPrincipal.java	Mon Jun 14 20:05:14 2004
@@ -16,7 +16,8 @@
  */
 package org.apache.janus.authorization;
 
-import org.apache.janus.authentication.realm.AbstractPrincipal;
+import org.apache.janus.authentication.AbstractPrincipal;
+import org.apache.janus.authentication.AbstractPrincipal;
 
 /**
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>