You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ro...@apache.org on 2012/08/24 17:33:05 UTC

svn commit: r1376968 [5/7] - in /qpid/trunk/qpid/java: broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ broker-plugins...

Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java?rev=1376968&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java Fri Aug 24 15:33:00 2012
@@ -0,0 +1,548 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model.adapter;
+
+import java.security.AccessControlException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Group;
+import org.apache.qpid.server.model.GroupMember;
+import org.apache.qpid.server.model.GroupProvider;
+import org.apache.qpid.server.model.IllegalStateTransitionException;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.Statistics;
+import org.apache.qpid.server.model.UUIDGenerator;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.group.GroupManager;
+
+public class GroupProviderAdapter extends AbstractAdapter implements
+        GroupProvider
+{
+    private final GroupManager _groupManager;
+
+    protected GroupProviderAdapter(GroupManager groupManager)
+    {
+        super(UUIDGenerator.generateRandomUUID());
+
+        if (groupManager == null)
+        {
+            throw new IllegalArgumentException("GroupManager must not be null");
+        }
+        _groupManager = groupManager;
+    }
+
+    public static GroupProviderAdapter createGroupProviderAdapter(
+            BrokerAdapter brokerAdapter, GroupManager groupManager)
+    {
+        final GroupProviderAdapter groupProviderAdapter = new GroupProviderAdapter(
+                groupManager);
+        groupProviderAdapter.addParent(Broker.class, brokerAdapter);
+        return groupProviderAdapter;
+    }
+
+    @Override
+    public String getName()
+    {
+        return _groupManager.getClass().getSimpleName();
+    }
+
+    @Override
+    public String setName(String currentName, String desiredName)
+            throws IllegalStateException, AccessControlException
+    {
+        return null;
+    }
+
+    @Override
+    public State getActualState()
+    {
+        return null;
+    }
+
+    @Override
+    public boolean isDurable()
+    {
+        return true;
+    }
+
+    @Override
+    public void setDurable(boolean durable) throws IllegalStateException,
+            AccessControlException, IllegalArgumentException
+    {
+    }
+
+    @Override
+    public LifetimePolicy getLifetimePolicy()
+    {
+        return LifetimePolicy.PERMANENT;
+    }
+
+    @Override
+    public LifetimePolicy setLifetimePolicy(LifetimePolicy expected,
+            LifetimePolicy desired) throws IllegalStateException,
+            AccessControlException, IllegalArgumentException
+    {
+        return null;
+    }
+
+    @Override
+    public long getTimeToLive()
+    {
+        return 0;
+    }
+
+    @Override
+    public long setTimeToLive(long expected, long desired)
+            throws IllegalStateException, AccessControlException,
+            IllegalArgumentException
+    {
+        return 0;
+    }
+
+    @Override
+    public Statistics getStatistics()
+    {
+        return NoStatistics.getInstance();
+    }
+
+    @Override
+    public Collection<String> getAttributeNames()
+    {
+        return GroupProvider.AVAILABLE_ATTRIBUTES;
+    }
+
+    @Override
+    public Object getAttribute(String name)
+    {
+        if (TYPE.equals(name))
+        {
+            return getName();
+        }
+        else if (CREATED.equals(name))
+        {
+            // TODO
+        }
+        else if (DURABLE.equals(name))
+        {
+            return true;
+        }
+        else if (ID.equals(name))
+        {
+            return getId();
+        }
+        else if (LIFETIME_POLICY.equals(name))
+        {
+            return LifetimePolicy.PERMANENT;
+        }
+        else if (NAME.equals(name))
+        {
+            return getName();
+        }
+        else if (STATE.equals(name))
+        {
+            return State.ACTIVE; // TODO
+        }
+        else if (TIME_TO_LIVE.equals(name))
+        {
+            // TODO
+        }
+        else if (UPDATED.equals(name))
+        {
+            // TODO
+        }
+        return super.getAttribute(name);
+    }
+
+    @Override
+    public <C extends ConfiguredObject> C createChild(Class<C> childClass,
+            Map<String, Object> attributes, ConfiguredObject... otherParents)
+    {
+        if (childClass == Group.class)
+        {
+            String groupName = (String) attributes.get(Group.NAME);
+
+            if (getSecurityManager().authoriseGroupOperation(Operation.CREATE, groupName))
+            {
+                _groupManager.createGroup(groupName);
+                return (C) new GroupAdapter(groupName);
+            }
+            else
+            {
+                throw new AccessControlException("Do not have permission" +
+                		" to create new group");
+            }
+        }
+
+        throw new IllegalArgumentException(
+                "This group provider does not support creating children of type: "
+                        + childClass);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+    {
+        if (clazz == Group.class)
+        {
+            Set<Principal> groups = _groupManager.getGroupPrincipals();
+            Collection<Group> principals = new ArrayList<Group>(groups.size());
+            for (Principal group : groups)
+            {
+                principals.add(new GroupAdapter(group.getName()));
+            }
+            return (Collection<C>) Collections
+                    .unmodifiableCollection(principals);
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    private org.apache.qpid.server.security.SecurityManager getSecurityManager()
+    {
+        return ApplicationRegistry.getInstance().getSecurityManager();
+    }
+
+    private class GroupAdapter extends AbstractAdapter implements Group
+    {
+        private final String _group;
+
+        public GroupAdapter(String group)
+        {
+            super(UUIDGenerator.generateGroupUUID(
+                    GroupProviderAdapter.this.getName(), group));
+            _group = group;
+
+        }
+
+        @Override
+        public String getName()
+        {
+            return _group;
+        }
+
+        @Override
+        public String setName(String currentName, String desiredName)
+                throws IllegalStateException, AccessControlException
+        {
+            throw new IllegalStateException("Names cannot be updated");
+        }
+
+        @Override
+        public State getActualState()
+        {
+            return State.ACTIVE;
+        }
+
+        @Override
+        public boolean isDurable()
+        {
+            return true;
+        }
+
+        @Override
+        public void setDurable(boolean durable) throws IllegalStateException,
+                AccessControlException, IllegalArgumentException
+        {
+            throw new IllegalStateException("Durability cannot be updated");
+        }
+
+        @Override
+        public LifetimePolicy getLifetimePolicy()
+        {
+            return LifetimePolicy.PERMANENT;
+        }
+
+        @Override
+        public LifetimePolicy setLifetimePolicy(LifetimePolicy expected,
+                LifetimePolicy desired) throws IllegalStateException,
+                AccessControlException, IllegalArgumentException
+        {
+            throw new IllegalStateException("LifetimePolicy cannot be updated");
+        }
+
+        @Override
+        public long getTimeToLive()
+        {
+            return 0;
+        }
+
+        @Override
+        public long setTimeToLive(long expected, long desired)
+                throws IllegalStateException, AccessControlException,
+                IllegalArgumentException
+        {
+            throw new IllegalStateException("ttl cannot be updated");
+        }
+
+        @Override
+        public Statistics getStatistics()
+        {
+            return NoStatistics.getInstance();
+        }
+
+        @Override
+        public <C extends ConfiguredObject> Collection<C> getChildren(
+                Class<C> clazz)
+        {
+            if (clazz == GroupMember.class)
+            {
+                Set<Principal> usersInGroup = _groupManager
+                        .getUserPrincipalsForGroup(_group);
+                Collection<GroupMember> members = new ArrayList<GroupMember>();
+                for (Principal principal : usersInGroup)
+                {
+                    members.add(new GroupMemberAdapter(principal.getName()));
+                }
+                return (Collection<C>) Collections
+                        .unmodifiableCollection(members);
+            }
+            else
+            {
+                return null;
+            }
+
+        }
+
+        @Override
+        public <C extends ConfiguredObject> C createChild(Class<C> childClass,
+                Map<String, Object> attributes,
+                ConfiguredObject... otherParents)
+        {
+            if (childClass == GroupMember.class)
+            {
+                String memberName = (String) attributes.get(GroupMember.NAME);
+
+                if (getSecurityManager().authoriseGroupOperation(Operation.UPDATE, _group))
+                {
+                    _groupManager.addUserToGroup(memberName, _group);
+                    return (C) new GroupMemberAdapter(memberName);
+                }
+                else
+                {
+                    throw new AccessControlException("Do not have permission" +
+                    		" to add new group member");
+                }
+            }
+
+            throw new IllegalArgumentException(
+                    "This group provider does not support creating children of type: "
+                            + childClass);
+        }
+
+        @Override
+        public Collection<String> getAttributeNames()
+        {
+            return Group.AVAILABLE_ATTRIBUTES;
+        }
+
+        @Override
+        public Object getAttribute(String name)
+        {
+            if (ID.equals(name))
+            {
+                return getId();
+            }
+            else if (NAME.equals(name))
+            {
+                return getName();
+            }
+            return super.getAttribute(name);
+        }
+
+        @Override
+        public Object setAttribute(String name, Object expected, Object desired)
+                throws IllegalStateException, AccessControlException,
+                IllegalArgumentException
+        {
+            return super.setAttribute(name, expected, desired);
+        }
+
+        @Override
+        public State setDesiredState(State currentState, State desiredState)
+                throws IllegalStateTransitionException, AccessControlException
+        {
+            if (desiredState == State.DELETED)
+            {
+                if (getSecurityManager().authoriseGroupOperation(Operation.DELETE, _group))
+                {
+                    _groupManager.removeGroup(_group);
+                    return State.DELETED;
+                }
+                else
+                {
+                    throw new AccessControlException("Do not have permission" +
+                    " to delete group");
+                }
+            }
+
+            return super.setDesiredState(currentState, desiredState);
+        }
+
+        private class GroupMemberAdapter extends AbstractAdapter implements
+                GroupMember
+        {
+            private String _memberName;
+
+            public GroupMemberAdapter(String memberName)
+            {
+                super(UUIDGenerator
+                        .generateGroupMemberUUID(
+                                GroupProviderAdapter.this.getName(), _group,
+                                memberName));
+                _memberName = memberName;
+            }
+
+            @Override
+            public Collection<String> getAttributeNames()
+            {
+                return GroupMember.AVAILABLE_ATTRIBUTES;
+            }
+
+            @Override
+            public Object getAttribute(String name)
+            {
+                if (ID.equals(name))
+                {
+                    return getId();
+                }
+                else if (NAME.equals(name))
+                {
+                    return getName();
+                }
+                return super.getAttribute(name);
+            }
+
+            @Override
+            public String getName()
+            {
+                return _memberName;
+            }
+
+            @Override
+            public String setName(String currentName, String desiredName)
+                    throws IllegalStateException, AccessControlException
+            {
+                return null;
+            }
+
+            @Override
+            public State getActualState()
+            {
+                return null;
+            }
+
+            @Override
+            public boolean isDurable()
+            {
+                return false;
+            }
+
+            @Override
+            public void setDurable(boolean durable)
+                    throws IllegalStateException, AccessControlException,
+                    IllegalArgumentException
+            {
+            }
+
+            @Override
+            public LifetimePolicy getLifetimePolicy()
+            {
+                return null;
+            }
+
+            @Override
+            public LifetimePolicy setLifetimePolicy(LifetimePolicy expected,
+                    LifetimePolicy desired) throws IllegalStateException,
+                    AccessControlException, IllegalArgumentException
+            {
+                return null;
+            }
+
+            @Override
+            public long getTimeToLive()
+            {
+                return 0;
+            }
+
+            @Override
+            public long setTimeToLive(long expected, long desired)
+                    throws IllegalStateException, AccessControlException,
+                    IllegalArgumentException
+            {
+                return 0;
+            }
+
+            @Override
+            public Statistics getStatistics()
+            {
+                return NoStatistics.getInstance();
+            }
+
+            @Override
+            public <C extends ConfiguredObject> Collection<C> getChildren(
+                    Class<C> clazz)
+            {
+                return null;
+            }
+
+            @Override
+            public <C extends ConfiguredObject> C createChild(
+                    Class<C> childClass, Map<String, Object> attributes,
+                    ConfiguredObject... otherParents)
+            {
+                return null;
+            }
+
+            @Override
+            public State setDesiredState(State currentState, State desiredState)
+                    throws IllegalStateTransitionException,
+                    AccessControlException
+            {
+                if (desiredState == State.DELETED)
+                {
+                    if (getSecurityManager().authoriseGroupOperation(Operation.UPDATE, _group))
+                    {
+                        _groupManager.removeUserFromGroup(_memberName, _group);
+                        return State.DELETED;
+                    }
+                    else
+                    {
+                        throw new AccessControlException("Do not have permission" +
+                        " to remove group member");
+                    }
+                }
+                
+                return super.setDesiredState(currentState, desiredState);
+            }
+
+        }
+    }
+}

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java Fri Aug 24 15:33:00 2012
@@ -49,6 +49,8 @@ import org.apache.qpid.server.security.a
 import org.apache.qpid.server.security.auth.manager.KerberosAuthenticationManager;
 import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
 import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager;
+import org.apache.qpid.server.security.group.FileGroupManager;
+import org.apache.qpid.server.security.group.GroupManagerPluginFactory;
 import org.apache.qpid.server.virtualhost.plugins.SlowConsumerDetection;
 import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory;
 import org.apache.qpid.server.virtualhost.plugins.policies.TopicDeletePolicy;
@@ -90,6 +92,7 @@ public class PluginManager implements Cl
     private ServiceTracker _virtualHostTracker = null;
     private ServiceTracker _policyTracker = null;
     private ServiceTracker _authenticationManagerTracker = null;
+    private ServiceTracker _groupManagerTracker = null;
 
     private Activator _activator;
 
@@ -99,6 +102,7 @@ public class PluginManager implements Cl
     private Map<String, VirtualHostPluginFactory> _vhostPlugins = new HashMap<String, VirtualHostPluginFactory>();
     private Map<String, SlowConsumerPolicyPluginFactory> _policyPlugins = new HashMap<String, SlowConsumerPolicyPluginFactory>();
     private Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> _authenticationManagerPlugins = new HashMap<String, AuthenticationManagerPluginFactory<? extends Plugin>>();
+    private Map<String, GroupManagerPluginFactory<? extends Plugin>> _groupManagerPlugins = new HashMap<String, GroupManagerPluginFactory<? extends Plugin>>();
 
     /** The default name of the OSGI system package list. */
     private static final String DEFAULT_RESOURCE_NAME = "org/apache/qpid/server/plugins/OsgiSystemPackages.properties";
@@ -162,7 +166,8 @@ public class PluginManager implements Cl
                 AnonymousAuthenticationManager.AnonymousAuthenticationManagerConfiguration.FACTORY,
                 KerberosAuthenticationManager.KerberosAuthenticationManagerConfiguration.FACTORY,
                 SimpleLDAPAuthenticationManager.SimpleLDAPAuthenticationManagerConfiguration.FACTORY,
-                ExternalAuthenticationManager.ExternalAuthenticationManagerConfiguration.FACTORY
+                ExternalAuthenticationManager.ExternalAuthenticationManagerConfiguration.FACTORY,
+                FileGroupManager.FileGroupManagerConfiguration.FACTORY
                 ))
         {
             _configPlugins.put(configFactory.getParentPaths(), configFactory);
@@ -186,6 +191,12 @@ public class PluginManager implements Cl
             _authenticationManagerPlugins.put(pluginFactory.getPluginName(), pluginFactory);
         }
 
+        for (GroupManagerPluginFactory<? extends Plugin> pluginFactory : Arrays.asList(
+                FileGroupManager.FACTORY))
+        {
+            _groupManagerPlugins.put(pluginFactory.getPluginName(), pluginFactory);
+        }
+
         if(bundleContext == null)
         {
             // Check the plugin directory path is set and exist
@@ -283,6 +294,11 @@ public class PluginManager implements Cl
         _authenticationManagerTracker.open();
         _trackers.add(_authenticationManagerTracker);
 
+        _groupManagerTracker = new ServiceTracker(bundleContext, GroupManagerPluginFactory.class.getName(), null);
+        _groupManagerTracker.open();
+        _trackers.add(_groupManagerTracker);
+
+
         _logger.info("Opened service trackers");
     }
 
@@ -358,6 +374,11 @@ public class PluginManager implements Cl
         return getServices(_authenticationManagerTracker, _authenticationManagerPlugins);
     }
 
+    public Map<String, GroupManagerPluginFactory<? extends Plugin>> getGroupManagerPlugins()
+    {
+        return getServices(_groupManagerTracker, _groupManagerPlugins);
+    }
+
     public void close()
     {
         try

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java Fri Aug 24 15:33:00 2012
@@ -68,6 +68,7 @@ import org.apache.qpid.server.output.Pro
 import org.apache.qpid.server.output.ProtocolOutputConverterRegistry;
 import org.apache.qpid.server.queue.QueueEntry;
 import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
 import org.apache.qpid.server.state.AMQState;
 import org.apache.qpid.server.state.AMQStateManager;
 import org.apache.qpid.server.stats.StatisticsCounter;
@@ -367,7 +368,7 @@ public class AMQProtocolEngine implement
             // This sets the protocol version (and hence framing classes) for this session.
             setProtocolVersion(pv);
 
-            String mechanisms = ApplicationRegistry.getInstance().getAuthenticationManager(getLocalAddress()).getMechanisms();
+            String mechanisms = ApplicationRegistry.getInstance().getSubjectCreator(getLocalAddress()).getMechanisms();
 
             String locales = "en_US";
 
@@ -1017,7 +1018,7 @@ public class AMQProtocolEngine implement
 
     public Principal getAuthorizedPrincipal()
     {
-        return _authorizedSubject == null ? null : _authorizedSubject.getPrincipals().iterator().next();
+        return _authorizedSubject == null ? null : _authorizedSubject.getPrincipals(AuthenticatedPrincipal.class).iterator().next();
     }
 
     public SocketAddress getRemoteAddress()

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java Fri Aug 24 15:33:00 2012
@@ -302,7 +302,7 @@ public class MultiVersionProtocolEngine 
         public ServerProtocolEngine getProtocolEngine()
         {
             final ConnectionDelegate connDelegate =
-                    new org.apache.qpid.server.transport.ServerConnectionDelegate(_appRegistry, _fqdn, _appRegistry.getAuthenticationManager(getLocalAddress()));
+                    new org.apache.qpid.server.transport.ServerConnectionDelegate(_appRegistry, _fqdn, _appRegistry.getSubjectCreator(getLocalAddress()));
 
             ServerConnection conn = new ServerConnection(_id);
             conn.setConnectionDelegate(connDelegate);

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java Fri Aug 24 15:33:00 2012
@@ -43,6 +43,7 @@ import org.apache.qpid.server.configurat
 import org.apache.qpid.server.configuration.ConnectionConfigType;
 import org.apache.qpid.server.protocol.v1_0.Connection_1_0;
 import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.security.SubjectCreator;
 import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
 import org.apache.qpid.transport.Sender;
 import org.apache.qpid.transport.network.NetworkConnection;
@@ -144,7 +145,7 @@ public class ProtocolEngine_1_0_0 implem
 
         Container container = new Container(_appRegistry.getBrokerId().toString());
 
-        _conn = new ConnectionEndpoint(container, asSaslServerProvider(_appRegistry.getAuthenticationManager(
+        _conn = new ConnectionEndpoint(container, asSaslServerProvider(_appRegistry.getSubjectCreator(
                 getLocalAddress())));
         _conn.setConnectionEventListener(new Connection_1_0(_appRegistry, _conn, _connectionId));
         _conn.setFrameOutputHandler(this);
@@ -157,14 +158,14 @@ public class ProtocolEngine_1_0_0 implem
         _sender.flush();
     }
 
-    private SaslServerProvider asSaslServerProvider(final AuthenticationManager authenticationManager)
+    private SaslServerProvider asSaslServerProvider(final SubjectCreator subjectCreator)
     {
         return new SaslServerProvider()
         {
             @Override
             public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException
             {
-                return authenticationManager.createSaslServer(mechanism, fqdn, null);
+                return subjectCreator.createSaslServer(mechanism, fqdn, null);
             }
         };
     }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java Fri Aug 24 15:33:00 2012
@@ -45,7 +45,7 @@ import org.apache.qpid.server.configurat
 import org.apache.qpid.server.protocol.v1_0.Connection_1_0;
 import org.apache.qpid.server.registry.ApplicationRegistry;
 import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.security.SubjectCreator;
 import org.apache.qpid.transport.Sender;
 import org.apache.qpid.transport.network.NetworkConnection;
 
@@ -165,7 +165,7 @@ public class ProtocolEngine_1_0_0_SASL i
         Container container = new Container(_appRegistry.getBrokerId().toString());
 
         _conn = new ConnectionEndpoint(container, asSaslServerProvider(ApplicationRegistry.getInstance()
-                .getAuthenticationManager(getLocalAddress())));
+                .getSubjectCreator(getLocalAddress())));
         _conn.setConnectionEventListener(new Connection_1_0(_appRegistry, _conn, _connectionId));
         _conn.setRemoteAddress(getRemoteAddress());
 
@@ -175,8 +175,6 @@ public class ProtocolEngine_1_0_0_SASL i
 
         _conn.setOnSaslComplete(new Runnable()
         {
-
-
             public void run()
             {
                 if(_conn.isAuthenticated())
@@ -201,14 +199,14 @@ public class ProtocolEngine_1_0_0_SASL i
 
     }
 
-    private SaslServerProvider asSaslServerProvider(final AuthenticationManager authenticationManager)
+    private SaslServerProvider asSaslServerProvider(final SubjectCreator subjectCreator)
     {
         return new SaslServerProvider()
         {
             @Override
             public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException
             {
-                return authenticationManager.createSaslServer(mechanism, fqdn, null);
+                return subjectCreator.createSaslServer(mechanism, fqdn, null);
             }
         };
     }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java Fri Aug 24 15:33:00 2012
@@ -42,11 +42,17 @@ import org.apache.qpid.server.logging.me
 import org.apache.qpid.server.logging.messages.VirtualHostMessages;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.adapter.BrokerAdapter;
+import org.apache.qpid.server.plugins.Plugin;
 import org.apache.qpid.server.plugins.PluginManager;
 import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.security.SubjectCreator;
+import org.apache.qpid.server.security.SecurityManager.SecurityConfiguration;
 import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
 import org.apache.qpid.server.security.auth.manager.AuthenticationManagerRegistry;
 import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry;
+import org.apache.qpid.server.security.group.GroupManager;
+import org.apache.qpid.server.security.group.GroupManagerPluginFactory;
+import org.apache.qpid.server.security.group.GroupPrincipalAccessor;
 import org.apache.qpid.server.stats.StatisticsCounter;
 import org.apache.qpid.server.transport.QpidAcceptor;
 import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -87,7 +93,7 @@ public abstract class ApplicationRegistr
 
     private ConfigurationManager _configurationManager;
 
-    private RootMessageLogger _rootMessageLogger;
+    private volatile RootMessageLogger _rootMessageLogger;
 
     private CompositeStartupMessageLogger _startupMessageLogger;
 
@@ -115,6 +121,11 @@ public abstract class ApplicationRegistr
     private List<IAuthenticationManagerRegistry.RegistryChangeListener> _authManagerChangeListeners =
             new ArrayList<IAuthenticationManagerRegistry.RegistryChangeListener>();
 
+    private List<GroupManagerChangeListener> _groupManagerChangeListeners =
+            new ArrayList<GroupManagerChangeListener>();
+
+    private List<GroupManager> _groupManagerList = new ArrayList<GroupManager>();
+
     public Map<InetSocketAddress, QpidAcceptor> getAcceptors()
     {
         synchronized (_acceptors)
@@ -314,7 +325,25 @@ public abstract class ApplicationRegistr
 
             _securityManager = new SecurityManager(_configuration, _pluginManager);
 
-            _authenticationManagerRegistry = createAuthenticationManagerRegistry(_configuration, _pluginManager);
+            final Collection<GroupManagerPluginFactory<? extends Plugin>> factories = _pluginManager.getGroupManagerPlugins().values();
+            final SecurityConfiguration securityConfiguration = _configuration.getConfiguration(SecurityConfiguration.class.getName());
+
+            for(GroupManagerPluginFactory<? extends Plugin> factory : factories)
+            {
+                final GroupManager groupManager = factory.newInstance(securityConfiguration);
+                if(groupManager != null)
+                {
+                    _groupManagerList.add(groupManager);
+
+                    for(GroupManagerChangeListener listener : _groupManagerChangeListeners)
+                    {
+                        listener.groupManagerRegistered(groupManager);
+                    }
+                }
+            }
+            _logger.debug("Created " + _groupManagerList.size() + " group manager(s)");
+
+            _authenticationManagerRegistry = createAuthenticationManagerRegistry(_configuration, _pluginManager, new GroupPrincipalAccessor(_groupManagerList));
 
             if(!_authManagerChangeListeners.isEmpty())
             {
@@ -348,10 +377,10 @@ public abstract class ApplicationRegistr
         }
     }
 
-    protected IAuthenticationManagerRegistry createAuthenticationManagerRegistry(ServerConfiguration _configuration, PluginManager _pluginManager)
+    protected IAuthenticationManagerRegistry createAuthenticationManagerRegistry(ServerConfiguration configuration, PluginManager pluginManager, GroupPrincipalAccessor groupManagerList)
             throws ConfigurationException
     {
-        return new AuthenticationManagerRegistry(_configuration, _pluginManager);
+        return new AuthenticationManagerRegistry(configuration, pluginManager, groupManagerList);
     }
 
     protected void initialiseVirtualHosts() throws Exception
@@ -588,9 +617,9 @@ public abstract class ApplicationRegistr
     }
 
     @Override
-    public AuthenticationManager getAuthenticationManager(SocketAddress address)
+    public SubjectCreator getSubjectCreator(SocketAddress localAddress)
     {
-        return _authenticationManagerRegistry.getAuthenticationManager(address);
+        return _authenticationManagerRegistry.getSubjectCreator(localAddress);
     }
 
     @Override
@@ -599,6 +628,12 @@ public abstract class ApplicationRegistr
         return _authenticationManagerRegistry;
     }
 
+    @Override
+    public List<GroupManager> getGroupManagers()
+    {
+        return _groupManagerList;
+    }
+
     public PluginManager getPluginManager()
     {
         return _pluginManager;
@@ -758,7 +793,7 @@ public abstract class ApplicationRegistr
     }
 
     @Override
-    public void addRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener)
+    public void addAuthenticationManagerRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener)
     {
         if(_authenticationManagerRegistry == null)
         {
@@ -769,4 +804,10 @@ public abstract class ApplicationRegistr
             _authenticationManagerRegistry.addRegistryChangeListener(registryChangeListener);
         }
     }
+
+    @Override
+    public void addGroupManagerChangeListener(GroupManagerChangeListener groupManagerChangeListener)
+    {
+        _groupManagerChangeListeners.add(groupManagerChangeListener);
+    }
 }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java Fri Aug 24 15:33:00 2012
@@ -30,8 +30,10 @@ import org.apache.qpid.server.logging.Ro
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.plugins.PluginManager;
 import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.security.SubjectCreator;
 import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
 import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry;
+import org.apache.qpid.server.security.group.GroupManager;
 import org.apache.qpid.server.stats.StatisticsGatherer;
 import org.apache.qpid.server.transport.QpidAcceptor;
 import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -39,6 +41,7 @@ import org.apache.qpid.server.virtualhos
 
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
@@ -64,18 +67,16 @@ public interface IApplicationRegistry ex
     ServerConfiguration getConfiguration();
 
     /**
-     * Get the AuthenticationManager for the given socket address
-     *
-     * If no AuthenticationManager has been specifically set for the given address, then use the default
-     * AuthenticationManager
+     * Get the SubjectCreator for the given socket address.
      *
      * @param address The (listening) socket address for which the AuthenticationManager is required
-     * @return the AuthenticationManager
      */
-    AuthenticationManager getAuthenticationManager(SocketAddress address);
+    SubjectCreator getSubjectCreator(SocketAddress localAddress);
 
     IAuthenticationManagerRegistry getAuthenticationManagerRegistry();
 
+    List<GroupManager> getGroupManagers();
+
     VirtualHostRegistry getVirtualHostRegistry();
 
     SecurityManager getSecurityManager();
@@ -123,7 +124,7 @@ public interface IApplicationRegistry ex
 
     int getHTTPSManagementPort();
 
-    void addRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener);
+    void addAuthenticationManagerRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener);
 
     public interface PortBindingListener
     {
@@ -132,4 +133,11 @@ public interface IApplicationRegistry ex
 
     }
 
+    void addGroupManagerChangeListener(GroupManagerChangeListener groupManagerChangeListener);
+
+    public static interface GroupManagerChangeListener
+    {
+        void groupManagerRegistered(GroupManager groupManager);
+        void groupManagerUnregistered(GroupManager groupManager);
+    }
 }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java Fri Aug 24 15:33:00 2012
@@ -24,14 +24,14 @@ import javax.security.auth.Subject;
 import java.security.Principal;
 
 /**
- * Represents the authorization of the logged on user. 
- * 
+ * Represents the authorization of the logged on user.
+ *
  */
 public interface AuthorizationHolder
 {
-    /** 
+    /**
      * Returns the {@link Subject} of the authorized user.  This is guaranteed to
-     * contain at least one {@link org.apache.qpid.server.security.auth.sasl.UsernamePrincipal}, representing the the identity
+     * contain at least one {@link org.apache.qpid.server.security.auth.UsernamePrincipal}, representing the the identity
      * used when the user logged on to the application, and zero or more {@link org.apache.qpid.server.security.auth.sasl.GroupPrincipal}
      * representing the group(s) to which the user belongs.
      *
@@ -39,10 +39,10 @@ public interface AuthorizationHolder
      */
     Subject getAuthorizedSubject();
 
-    /** 
+    /**
      * Returns the {@link Principal} representing the the identity
      * used when the user logged on to the application.
-     * 
+     *
      * @return a Principal
      */
     Principal getAuthorizedPrincipal();

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java Fri Aug 24 15:33:00 2012
@@ -32,8 +32,10 @@ import org.apache.qpid.server.security.a
 import org.apache.qpid.server.security.access.Operation;
 
 import static org.apache.qpid.server.security.access.ObjectType.EXCHANGE;
+import static org.apache.qpid.server.security.access.ObjectType.GROUP;
 import static org.apache.qpid.server.security.access.ObjectType.METHOD;
 import static org.apache.qpid.server.security.access.ObjectType.QUEUE;
+import static org.apache.qpid.server.security.access.ObjectType.USER;
 import static org.apache.qpid.server.security.access.ObjectType.VIRTUALHOST;
 import static org.apache.qpid.server.security.access.Operation.BIND;
 import static org.apache.qpid.server.security.access.Operation.CONSUME;
@@ -387,6 +389,27 @@ public class SecurityManager
         });
     }
 
+    public boolean authoriseGroupOperation(final Operation operation, final String groupName)
+    {
+        return checkAllPlugins(new AccessCheck()
+        {
+            Result allowed(SecurityPlugin plugin)
+            {
+                return plugin.authorise(operation, GROUP, new ObjectProperties(groupName));
+            }
+        });
+    }
+
+    public boolean authoriseUserOperation(final Operation operation, final String userName)
+    {
+        return checkAllPlugins(new AccessCheck()
+        {
+            Result allowed(SecurityPlugin plugin)
+            {
+                return plugin.authorise(operation, USER, new ObjectProperties(userName));
+            }
+        });
+    }
 
     private ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>> _immediatePublishPropsCache
             = new ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>>();

Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java?rev=1376968&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java Fri Aug 24 15:33:00 2012
@@ -0,0 +1,137 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security;
+
+import java.security.Principal;
+
+import javax.security.auth.Subject;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
+import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.security.group.GroupPrincipalAccessor;
+
+/**
+ * Creates a {@link Subject} formed by the {@link Principal}'s returned from:
+ * <ol>
+ * <li>Authenticating using an {@link AuthenticationManager}</li>
+ * <li>A {@link GroupPrincipalAccessor}</li>
+ * </ol>
+ *
+ * <p>
+ * SubjectCreator is a facade to the {@link AuthenticationManager}, and is intended to be
+ * the single place that {@link Subject}'s are created in the broker.
+ * </p>
+ */
+public class SubjectCreator
+{
+    private AuthenticationManager _authenticationManager;
+    private GroupPrincipalAccessor _groupAccessor;
+
+    public SubjectCreator(AuthenticationManager authenticationManager, GroupPrincipalAccessor groupAccessor)
+    {
+        _authenticationManager = authenticationManager;
+        _groupAccessor = groupAccessor;
+    }
+
+   /**
+    * Gets the known SASL mechanisms
+    *
+    * @return SASL mechanism names, space separated.
+    */
+    public String getMechanisms()
+    {
+        return _authenticationManager.getMechanisms();
+    }
+
+    /**
+     * @see AuthenticationManager#createSaslServer(String, String, Principal)
+     */
+    public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException
+    {
+        return _authenticationManager.createSaslServer(mechanism, localFQDN, externalPrincipal);
+    }
+
+    /**
+     * Authenticates a user using SASL negotiation.
+     *
+     * @param server SASL server
+     * @param response SASL response to process
+     */
+    public SubjectAuthenticationResult authenticate(SaslServer server, byte[] response)
+    {
+        AuthenticationResult authenticationResult = _authenticationManager.authenticate(server, response);
+        if(server.isComplete())
+        {
+            String username = server.getAuthorizationID();
+
+            return createResultWithGroups(username, authenticationResult);
+        }
+        else
+        {
+            return new SubjectAuthenticationResult(authenticationResult);
+        }
+    }
+
+    /**
+     * Authenticates a user using their username and password.
+     */
+    public SubjectAuthenticationResult authenticate(String username, String password)
+    {
+        final AuthenticationResult authenticationResult = _authenticationManager.authenticate(username, password);
+
+        return createResultWithGroups(username, authenticationResult);
+    }
+
+    private SubjectAuthenticationResult createResultWithGroups(String username, final AuthenticationResult authenticationResult)
+    {
+        if(authenticationResult.getStatus() == AuthenticationStatus.SUCCESS)
+        {
+            final Subject authenticationSubject = new Subject();
+
+            authenticationSubject.getPrincipals().addAll(authenticationResult.getPrincipals());
+            authenticationSubject.getPrincipals().addAll(_groupAccessor.getGroupPrincipals(username));
+
+            authenticationSubject.setReadOnly();
+
+            return new SubjectAuthenticationResult(authenticationResult, authenticationSubject);
+        }
+        else
+        {
+            return new SubjectAuthenticationResult(authenticationResult);
+        }
+    }
+
+    public Subject createSubjectWithGroups(String username)
+    {
+        Subject authenticationSubject = new Subject();
+
+        authenticationSubject.getPrincipals().add(new AuthenticatedPrincipal(username));
+        authenticationSubject.getPrincipals().addAll(_groupAccessor.getGroupPrincipals(username));
+        authenticationSubject.setReadOnly();
+
+        return authenticationSubject;
+    }
+}

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java Fri Aug 24 15:33:00 2012
@@ -45,8 +45,10 @@ public enum ObjectType
     EXCHANGE(Operation.ALL, ACCESS, CREATE, DELETE, BIND, UNBIND, PUBLISH),
     LINK, // Not allowed in the Java broker
     ROUTE, // Not allowed in the Java broker
-    METHOD(Operation.ALL, ACCESS, UPDATE);
-    
+    METHOD(Operation.ALL, ACCESS, UPDATE),
+    USER(Operation.ALL, CREATE, DELETE, UPDATE),
+    GROUP(Operation.ALL, CREATE, DELETE, UPDATE);
+
     private EnumSet<Operation> _actions;
     
     private ObjectType()

Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipal.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipal.java?rev=1376968&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipal.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipal.java Fri Aug 24 15:33:00 2012
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.server.security.auth;
+
+import java.security.Principal;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
+
+/**
+ * A simple Principal wrapper. Exists to allow us to identify the "primary" principal
+ * by calling {@link Subject#getPrincipals(Class)}, passing in {@link AuthenticatedPrincipal}.class,
+ * e.g. when logging.
+ */
+public final class AuthenticatedPrincipal implements Principal
+{
+    private final Principal _wrappedPrincipal;
+
+    /** convenience constructor for the common case where we're wrapping a {@link UsernamePrincipal} */
+    public AuthenticatedPrincipal(String userPrincipalName)
+    {
+        this(new UsernamePrincipal(userPrincipalName));
+    }
+
+    public AuthenticatedPrincipal(Principal wrappedPrincipal)
+    {
+        if(wrappedPrincipal == null)
+        {
+            throw new IllegalArgumentException("Wrapped principal is null");
+        }
+
+        _wrappedPrincipal = wrappedPrincipal;
+    }
+
+    @Override
+    public String getName()
+    {
+        return _wrappedPrincipal.getName();
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return _wrappedPrincipal.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj)
+        {
+            return true;
+        }
+
+        if (!(obj instanceof AuthenticatedPrincipal))
+        {
+            return false;
+        }
+
+        AuthenticatedPrincipal other = (AuthenticatedPrincipal) obj;
+
+        return _wrappedPrincipal.equals(other._wrappedPrincipal);
+    }
+
+    public static AuthenticatedPrincipal getOptionalAuthenticatedPrincipalFromSubject(final Subject authSubject)
+    {
+        return getAuthenticatedPrincipalFromSubject(authSubject, true);
+    }
+
+    public static AuthenticatedPrincipal getAuthenticatedPrincipalFromSubject(final Subject authSubject)
+    {
+        return getAuthenticatedPrincipalFromSubject(authSubject, false);
+    }
+
+    private static AuthenticatedPrincipal getAuthenticatedPrincipalFromSubject(final Subject authSubject, boolean isPrincipalOptional)
+    {
+        if (authSubject == null)
+        {
+            throw new IllegalArgumentException("No authenticated subject.");
+        }
+
+        final Set<AuthenticatedPrincipal> principals = authSubject.getPrincipals(AuthenticatedPrincipal.class);
+        int numberOfAuthenticatedPrincipals = principals.size();
+
+        if(numberOfAuthenticatedPrincipals == 0 && isPrincipalOptional)
+        {
+            return null;
+        }
+        else
+        {
+            if (numberOfAuthenticatedPrincipals != 1)
+            {
+                throw new IllegalArgumentException(
+                        "Can't find single AuthenticatedPrincipal in authenticated subject. There were "
+                                + numberOfAuthenticatedPrincipals
+                                + " authenticated principals out of a total number of principals of: " + authSubject.getPrincipals());
+            }
+            return principals.iterator().next();
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return getName();
+    }
+
+}

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java Fri Aug 24 15:33:00 2012
@@ -7,9 +7,9 @@
  * 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
@@ -20,15 +20,20 @@
  */
 package org.apache.qpid.server.security.auth;
 
-import javax.security.auth.Subject;
+import java.security.Principal;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
 
 /**
- * Encapsulates the result of an attempt to authenticate.
+ * Encapsulates the result of an attempt to authenticate using an {@link AuthenticationManager}.
  * <p>
  * The authentication status describes the overall outcome.
  * <p>
  * <ol>
- *  <li>If authentication status is SUCCESS, the subject will be populated.
+ *  <li>If authentication status is SUCCESS, at least one {@link Principal} will be populated.
  *  </li>
  *  <li>If authentication status is CONTINUE, the authentication has failed because the user
  *      supplied incorrect credentials (etc).  If the authentication requires it, the next challenge
@@ -40,6 +45,8 @@ import javax.security.auth.Subject;
  *  </li>
  * </ol>
  *
+ * The main principal provided to the constructor is wrapped in an {@link AuthenticatedPrincipal}
+ * to make it easier for the rest of the application to identify it among the set of other principals.
  */
 public class AuthenticationResult
 {
@@ -56,37 +63,54 @@ public class AuthenticationResult
     private final AuthenticationStatus _status;
     private final byte[] _challenge;
     private final Exception _cause;
-    private final Subject _subject;
+    private final Set<Principal> _principals = new HashSet<Principal>();
 
     public AuthenticationResult(final AuthenticationStatus status)
     {
         this(null, status, null);
     }
 
+    public AuthenticationResult(Principal mainPrincipal)
+    {
+        this(mainPrincipal, Collections.<Principal>emptySet());
+    }
+
+    public AuthenticationResult(Principal mainPrincipal, Set<Principal> otherPrincipals)
+    {
+        AuthenticatedPrincipal specialQpidAuthenticatedPrincipal = new AuthenticatedPrincipal(mainPrincipal);
+        _principals.addAll(otherPrincipals);
+        _principals.remove(mainPrincipal);
+        _principals.add(specialQpidAuthenticatedPrincipal);
+
+        _status = AuthenticationStatus.SUCCESS;
+        _challenge = null;
+        _cause = null;
+    }
+
     public AuthenticationResult(final byte[] challenge, final AuthenticationStatus status)
     {
-        this(challenge, status, null);
+        _challenge = challenge;
+        _status = status;
+        _cause = null;
     }
 
     public AuthenticationResult(final AuthenticationStatus error, final Exception cause)
     {
-        this(null, error, cause);
+        _status = error;
+        _challenge = null;
+        _cause = cause;
     }
 
     public AuthenticationResult(final byte[] challenge, final AuthenticationStatus status, final Exception cause)
     {
+        if(status == AuthenticationStatus.SUCCESS)
+        {
+            throw new IllegalArgumentException("Successful authentication requires at least one principal");
+        }
+
         this._status = status;
         this._challenge = challenge;
         this._cause = cause;
-        this._subject = null;
-    }
-
-    public AuthenticationResult(final Subject subject)
-    {
-        this._status = AuthenticationStatus.SUCCESS;
-        this._challenge = null;
-        this._cause = null;
-        this._subject = subject;
     }
 
     public Exception getCause()
@@ -104,9 +128,8 @@ public class AuthenticationResult
         return _challenge;
     }
 
-    public Subject getSubject()
+    public Set<Principal> getPrincipals()
     {
-        return _subject;
+        return _principals;
     }
-
 }

Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/SubjectAuthenticationResult.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/SubjectAuthenticationResult.java?rev=1376968&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/SubjectAuthenticationResult.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/SubjectAuthenticationResult.java Fri Aug 24 15:33:00 2012
@@ -0,0 +1,76 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security.auth;
+
+import java.security.Principal;
+
+import javax.security.auth.Subject;
+
+import org.apache.qpid.server.security.SubjectCreator;
+
+/**
+ * Encapsulates the result of an attempt to authenticate using a {@link SubjectCreator}.
+ *
+ * <p>
+ * iff authentication was successful, {@link #getSubject()} will return a non-null value and
+ * {@link #getStatus()} will return {@link AuthenticationResult.AuthenticationStatus#SUCCESS}.
+ *
+ * In this case, the {@link Subject} will contain the user {@link Principal} and zero or more other principals
+ * representing groups.
+ * </p>
+ * @see SubjectCreator
+ */
+public class SubjectAuthenticationResult
+{
+    private final AuthenticationResult _authenticationResult;
+    private final Subject _subject;
+
+    public SubjectAuthenticationResult(AuthenticationResult authenticationResult, Subject subject)
+    {
+        _authenticationResult = authenticationResult;
+        _subject = subject;
+    }
+
+    public SubjectAuthenticationResult(AuthenticationResult unsuccessfulAuthenticationResult)
+    {
+        this(unsuccessfulAuthenticationResult, null);
+    }
+
+    public Exception getCause()
+    {
+        return _authenticationResult.getCause();
+    }
+
+    public AuthenticationResult.AuthenticationStatus getStatus()
+    {
+        return _authenticationResult.getStatus();
+    }
+
+    public byte[] getChallenge()
+    {
+        return _authenticationResult.getChallenge();
+    }
+
+    public Subject getSubject()
+    {
+        return _subject;
+    }
+}

Copied: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/UsernamePrincipal.java (from r1376735, qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java)
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/UsernamePrincipal.java?p2=qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/UsernamePrincipal.java&p1=qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java&r1=1376735&r2=1376968&rev=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/UsernamePrincipal.java Fri Aug 24 15:33:00 2012
@@ -7,9 +7,9 @@
  * 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
@@ -18,11 +18,9 @@
  * under the License.
  *
  */
-package org.apache.qpid.server.security.auth.sasl;
+package org.apache.qpid.server.security.auth;
 
-import javax.security.auth.Subject;
 import java.security.Principal;
-import java.util.Set;
 
 /** A principal that is just a wrapper for a simple username. */
 public class UsernamePrincipal implements Principal
@@ -48,9 +46,6 @@ public class UsernamePrincipal implement
         return _name;
     }
 
-    /**
-     * @see java.lang.Object#hashCode()
-     */
     @Override
     public int hashCode()
     {
@@ -58,9 +53,6 @@ public class UsernamePrincipal implement
         return prime * _name.hashCode();
     }
 
-    /**
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
     @Override
     public boolean equals(Object obj)
     {
@@ -81,19 +73,4 @@ public class UsernamePrincipal implement
             }
         }
     }
-
-    public static UsernamePrincipal getUsernamePrincipalFromSubject(final Subject authSubject)
-    {
-        if (authSubject == null)
-        {
-            throw new IllegalArgumentException("No authenticated subject.");
-        }
-
-        final Set<UsernamePrincipal> principals = authSubject.getPrincipals(UsernamePrincipal.class);
-        if (principals.size() != 1)
-        {
-            throw new IllegalArgumentException("Can't find single UsernamePrincipal in authenticated subject");
-        }
-        return principals.iterator().next();
-    }
 }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java Fri Aug 24 15:33:00 2012
@@ -21,9 +21,9 @@
 package org.apache.qpid.server.security.auth.database;
 
 import org.apache.log4j.Logger;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
 import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
 import org.apache.qpid.server.security.auth.sasl.UsernamePasswordInitialiser;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
 
 import javax.security.auth.callback.PasswordCallback;
 import javax.security.auth.login.AccountNotFoundException;

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java Fri Aug 24 15:33:00 2012
@@ -21,7 +21,7 @@
 package org.apache.qpid.server.security.auth.database;
 
 import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
 import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser;
 import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser;
 

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java Fri Aug 24 15:33:00 2012
@@ -24,7 +24,6 @@ import java.security.Principal;
 import java.util.Arrays;
 import java.util.List;
 import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
 import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
 import org.apache.commons.configuration.Configuration;
@@ -33,7 +32,7 @@ import org.apache.log4j.Logger;
 import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
 import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
 import org.apache.qpid.server.security.auth.AuthenticationResult;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
 import org.apache.qpid.server.security.auth.sasl.anonymous.AnonymousInitialiser;
 import org.apache.qpid.server.security.auth.sasl.anonymous.AnonymousSaslServer;
 
@@ -45,7 +44,9 @@ public class AnonymousAuthenticationMana
 
     private static final String ANONYMOUS = SASL_INITIALISER.getMechanismName();
 
-    private static final Principal ANONYMOUS_PRINCIPAL = new UsernamePrincipal("ANONYMOUS");
+    public static final String ANONYMOUS_USERNAME = "ANONYMOUS";
+
+    public static final Principal ANONYMOUS_PRINCIPAL = new UsernamePrincipal(ANONYMOUS_USERNAME);
 
     public static final Subject ANONYMOUS_SUBJECT = new Subject();
     static
@@ -53,10 +54,7 @@ public class AnonymousAuthenticationMana
         ANONYMOUS_SUBJECT.getPrincipals().add(ANONYMOUS_PRINCIPAL);
     }
 
-    private static final AuthenticationResult ANONYMOUS_AUTHENTICATION = new AuthenticationResult(ANONYMOUS_SUBJECT);
-
-
-    private static CallbackHandler _callbackHandler = SASL_INITIALISER.getCallbackHandler();
+    private static final AuthenticationResult ANONYMOUS_AUTHENTICATION = new AuthenticationResult(ANONYMOUS_PRINCIPAL);
 
     static final AnonymousAuthenticationManager INSTANCE = new AnonymousAuthenticationManager();
 

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java Fri Aug 24 15:33:00 2012
@@ -30,14 +30,15 @@ import org.apache.qpid.server.security.a
 /**
  * Implementations of the AuthenticationManager are responsible for determining
  * the authenticity of a user's credentials.
- *
- * If the authentication is successful, the manager is responsible for producing a populated
- * {@link javax.security.auth.Subject} containing the user's identity and zero or more principals representing
- * groups to which the user belongs.
+ * <p>
+ * If the authentication is successful, the manager is responsible for producing an
+ * {@link AuthenticationResult} containing the user's main {@link Principal} and zero or
+ * more other implementation-specific principals.
+ * </p>
  * <p>
  * The {@link #initialise()} method is responsible for registering SASL mechanisms required by
  * the manager.  The {@link #close()} method must reverse this registration.
- *
+ * </p>
  */
 public interface AuthenticationManager extends Closeable, Plugin
 {
@@ -88,5 +89,4 @@ public interface AuthenticationManager e
      * @return authentication result
      */
     AuthenticationResult authenticate(String username, String password);
-
 }

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java Fri Aug 24 15:33:00 2012
@@ -25,7 +25,6 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -35,6 +34,8 @@ import org.apache.qpid.server.configurat
 import org.apache.qpid.server.plugins.Plugin;
 import org.apache.qpid.server.plugins.PluginManager;
 import org.apache.qpid.server.security.SecurityManager.SecurityConfiguration;
+import org.apache.qpid.server.security.SubjectCreator;
+import org.apache.qpid.server.security.group.GroupPrincipalAccessor;
 
 /**
  * A concrete implementation of {@link IAuthenticationManagerRegistry} that registers all {@link AuthenticationManager}
@@ -50,12 +51,12 @@ import org.apache.qpid.server.security.S
 public class AuthenticationManagerRegistry implements Closeable, IAuthenticationManagerRegistry
 {
     private final Map<String,AuthenticationManager> _classToAuthManagerMap = new HashMap<String,AuthenticationManager>();
-    private final AuthenticationManager _defaultAuthenticationManager;
-    private final Map<Integer,AuthenticationManager> _portToAuthenticationManagerMap;
+    private final SubjectCreator _defaultSubjectCreator;
+    private final Map<Integer, SubjectCreator> _portToSubjectCreatorMap;
     private final List<RegistryChangeListener> _listeners =
             Collections.synchronizedList(new ArrayList<RegistryChangeListener>());
 
-    public AuthenticationManagerRegistry(ServerConfiguration serverConfiguration, PluginManager _pluginManager)
+    public AuthenticationManagerRegistry(ServerConfiguration serverConfiguration, PluginManager _pluginManager, GroupPrincipalAccessor groupPrincipalAccessor)
     throws ConfigurationException
     {
         final Collection<AuthenticationManagerPluginFactory<? extends Plugin>> factories = _pluginManager.getAuthenticationManagerPlugins().values();
@@ -78,9 +79,9 @@ public class AuthenticationManagerRegist
                 throw new ConfigurationException("No authentication managers configured within the configuration file.");
             }
 
-            _defaultAuthenticationManager = getDefaultAuthenticationManager(serverConfiguration);
+            _defaultSubjectCreator = createDefaultSubectCreator(serverConfiguration, groupPrincipalAccessor);
 
-            _portToAuthenticationManagerMap = getPortToAuthenticationManagerMap(serverConfiguration);
+            _portToSubjectCreatorMap = createPortToSubjectCreatorMap(serverConfiguration, groupPrincipalAccessor);
             willClose = false;
         }
         finally
@@ -95,14 +96,14 @@ public class AuthenticationManagerRegist
     }
 
     @Override
-    public AuthenticationManager getAuthenticationManager(SocketAddress address)
+    public SubjectCreator getSubjectCreator(SocketAddress address)
     {
-        AuthenticationManager authManager =
+        SubjectCreator subjectCreator =
                 address instanceof InetSocketAddress
-                        ? _portToAuthenticationManagerMap.get(((InetSocketAddress)address).getPort())
+                        ? _portToSubjectCreatorMap.get(((InetSocketAddress)address).getPort())
                         : null;
 
-        return authManager == null ? _defaultAuthenticationManager : authManager;
+        return subjectCreator == null ? _defaultSubjectCreator : subjectCreator;
     }
 
     @Override
@@ -140,8 +141,8 @@ public class AuthenticationManagerRegist
         }
     }
 
-    private AuthenticationManager getDefaultAuthenticationManager(
-            ServerConfiguration serverConfiguration)
+    private SubjectCreator createDefaultSubectCreator(
+            ServerConfiguration serverConfiguration, GroupPrincipalAccessor groupAccessor)
             throws ConfigurationException
     {
         final AuthenticationManager defaultAuthenticationManager;
@@ -164,14 +165,14 @@ public class AuthenticationManagerRegist
         {
             throw new ConfigurationException("If more than one authentication manager is configured a default MUST be specified.");
         }
-        return defaultAuthenticationManager;
+        return new SubjectCreator(defaultAuthenticationManager, groupAccessor);
     }
 
-    private Map<Integer,AuthenticationManager> getPortToAuthenticationManagerMap(
-            ServerConfiguration serverConfiguration)
+    private Map<Integer, SubjectCreator> createPortToSubjectCreatorMap(
+            ServerConfiguration serverConfiguration, GroupPrincipalAccessor groupPrincipalAccessor)
             throws ConfigurationException
     {
-        Map<Integer,AuthenticationManager> portToAuthenticationManagerMap = new HashMap<Integer, AuthenticationManager>();
+        Map<Integer,SubjectCreator> portToSubjectCreatorMap = new HashMap<Integer, SubjectCreator>();
 
         for(Map.Entry<Integer,String> portMapping : serverConfiguration.getPortAuthenticationMappings().entrySet())
         {
@@ -182,10 +183,12 @@ public class AuthenticationManagerRegist
                 throw new ConfigurationException("Unknown authentication manager class " + portMapping.getValue() +
                                                 " configured for port " + portMapping.getKey());
             }
-            portToAuthenticationManagerMap.put(portMapping.getKey(), authenticationManager);
+
+            SubjectCreator subjectCreator = new SubjectCreator(authenticationManager, groupPrincipalAccessor);
+            portToSubjectCreatorMap.put(portMapping.getKey(), subjectCreator);
         }
 
-        return portToAuthenticationManagerMap;
+        return portToSubjectCreatorMap;
     }
 
     @Override

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java Fri Aug 24 15:33:00 2012
@@ -21,7 +21,6 @@ package org.apache.qpid.server.security.
 import java.security.Principal;
 import java.util.Arrays;
 import java.util.List;
-import javax.security.auth.Subject;
 import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
 import org.apache.commons.configuration.Configuration;
@@ -137,15 +136,13 @@ public class ExternalAuthenticationManag
         // Process response from the client
         try
         {
-            byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
+            server.evaluateResponse(response != null ? response : new byte[0]);
 
             Principal principal = ((ExternalSaslServer)server).getAuthenticatedPrincipal();
 
             if(principal != null)
             {
-                final Subject subject = new Subject();
-                subject.getPrincipals().add(principal);
-                return new AuthenticationResult(subject);
+                return new AuthenticationResult(principal);
             }
             else
             {

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java Fri Aug 24 15:33:00 2012
@@ -23,13 +23,11 @@ import java.net.SocketAddress;
 
 import java.util.Map;
 import org.apache.qpid.common.Closeable;
-import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.security.SubjectCreator;
 
 /**
- * Registry for {@link AuthenticationManager} instances.
- *
- * <p>A lookup method {@link #getAuthenticationManager(SocketAddress)} allows a caller to determine
- * the AuthenticationManager associated with a particular port number.</p>
+ * Registry for {@link AuthenticationManager} instances, also exposing them wrapped in {@link SubjectCreator}'s
+ * as a convenience.
  *
  * <p>It is important to {@link #close()} the registry after use and this allows the AuthenticationManagers
  * to reverse any security registrations they have performed.</p>
@@ -37,14 +35,11 @@ import org.apache.qpid.server.virtualhos
 public interface IAuthenticationManagerRegistry extends Closeable
 {
     /**
-     * Returns the {@link AuthenticationManager} associated with a particular {@link SocketAddress}.
-     * If no authentication manager is associated with this address, a default authentication manager will be
+     * Returns the {@link SubjectCreator} associated with a particular {@link SocketAddress}.
+     * If no subject creator is associated with this address, a default will be
      * returned.  Null is never returned.
-     *
-     * @param address
-     * @return authentication manager.
      */
-    public AuthenticationManager getAuthenticationManager(SocketAddress address);
+    public SubjectCreator getSubjectCreator(SocketAddress address);
 
     Map<String, AuthenticationManager> getAvailableAuthenticationManagers();
 
@@ -55,5 +50,4 @@ public interface IAuthenticationManagerR
     }
 
     public void addRegistryChangeListener(RegistryChangeListener listener);
-
 }
\ No newline at end of file

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java Fri Aug 24 15:33:00 2012
@@ -23,7 +23,6 @@ import java.security.Principal;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
-import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.UnsupportedCallbackException;
@@ -37,7 +36,7 @@ import org.apache.log4j.Logger;
 import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
 import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
 import org.apache.qpid.server.security.auth.AuthenticationResult;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
 
 public class KerberosAuthenticationManager implements AuthenticationManager
 {
@@ -158,10 +157,7 @@ public class KerberosAuthenticationManag
 
             if (server.isComplete())
             {
-                final Subject subject = new Subject();
-                _logger.debug("Authenticated as " + server.getAuthorizationID());
-                subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID()));
-                return new AuthenticationResult(subject);
+                return new AuthenticationResult(new UsernamePrincipal(server.getAuthorizationID()));
             }
             else
             {

Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java?rev=1376968&r1=1376967&r2=1376968&view=diff
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java (original)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java Fri Aug 24 15:33:00 2012
@@ -34,9 +34,8 @@ import org.apache.qpid.server.security.a
 import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
 import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
 import org.apache.qpid.server.security.auth.sasl.JCAProvider;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
 
-import javax.security.auth.Subject;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.login.AccountNotFoundException;
 import javax.security.sasl.Sasl;
@@ -164,6 +163,7 @@ public class PrincipalDatabaseAuthentica
             return getConfig().getString("principal-database.class");
         }
 
+        @SuppressWarnings({ "unchecked", "rawtypes" })
         public Map<String,String> getPdClassAttributeMap() throws ConfigurationException
         {
             final List<String> argumentNames = (List) getConfig().getList("principal-database.attributes.attribute.name");
@@ -284,9 +284,8 @@ public class PrincipalDatabaseAuthentica
 
             if (server.isComplete())
             {
-                final Subject subject = new Subject();
-                subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID()));
-                return new AuthenticationResult(subject);
+                final String userId = server.getAuthorizationID();
+                return new AuthenticationResult(new UsernamePrincipal(userId));
             }
             else
             {
@@ -308,9 +307,7 @@ public class PrincipalDatabaseAuthentica
         {
             if (_principalDatabase.verifyPassword(username, password.toCharArray()))
             {
-                final Subject subject = new Subject();
-                subject.getPrincipals().add(new UsernamePrincipal(username));
-                return new AuthenticationResult(subject);
+                return new AuthenticationResult(new UsernamePrincipal(username));
             }
             else
             {
@@ -353,6 +350,16 @@ public class PrincipalDatabaseAuthentica
         }
     }
 
+    public PrincipalDatabase getPrincipalDatabase()
+    {
+        return _principalDatabase;
+    }
+
+    protected void setPrincipalDatabase(final PrincipalDatabase principalDatabase)
+    {
+        _principalDatabase = principalDatabase;
+    }
+
     private void configPrincipalDatabase(final PrincipalDatabase principalDatabase, final PrincipalDatabaseAuthenticationManagerConfiguration config)
             throws ConfigurationException
     {
@@ -400,11 +407,6 @@ public class PrincipalDatabaseAuthentica
         }
     }
 
-    public PrincipalDatabase getPrincipalDatabase()
-    {
-        return _principalDatabase;
-    }
-
     private String generateSetterName(String argName) throws ConfigurationException
     {
         if ((argName == null) || (argName.length() == 0))
@@ -421,8 +423,4 @@ public class PrincipalDatabaseAuthentica
         return methodName;
     }
 
-    protected void setPrincipalDatabase(final PrincipalDatabase principalDatabase)
-    {
-        _principalDatabase = principalDatabase;
-    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org