You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by sh...@apache.org on 2011/10/20 20:43:26 UTC

svn commit: r1186990 [24/43] - in /qpid/branches/QPID-2519: ./ bin/ cpp/ cpp/bindings/ cpp/bindings/qmf/python/ cpp/bindings/qmf/ruby/ cpp/bindings/qmf/tests/ cpp/bindings/qmf2/ cpp/bindings/qmf2/examples/cpp/ cpp/bindings/qmf2/python/ cpp/bindings/qmf...

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java Thu Oct 20 18:42:46 2011
@@ -20,19 +20,9 @@
  */
 package org.apache.qpid.server.security.auth.management;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.security.AccessControlContext;
-import java.security.AccessController;
 import java.security.Principal;
-import java.util.Enumeration;
 import java.util.List;
-import java.util.Properties;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.locks.ReentrantLock;
 
 import javax.management.JMException;
 import javax.management.openmbean.CompositeData;
@@ -44,17 +34,13 @@ import javax.management.openmbean.Simple
 import javax.management.openmbean.TabularData;
 import javax.management.openmbean.TabularDataSupport;
 import javax.management.openmbean.TabularType;
-import javax.management.remote.JMXPrincipal;
-import javax.security.auth.Subject;
 import javax.security.auth.login.AccountNotFoundException;
 
-import org.apache.commons.configuration.ConfigurationException;
 import org.apache.log4j.Logger;
 import org.apache.qpid.management.common.mbeans.UserManagement;
 import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription;
 import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation;
 import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.management.MBeanInvocationHandlerImpl;
 import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
 import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
 
@@ -65,22 +51,18 @@ public class AMQUserManagementMBean exte
     private static final Logger _logger = Logger.getLogger(AMQUserManagementMBean.class);
 
     private PrincipalDatabase _principalDatabase;
-    private Properties _accessRights;
-    private File _accessFile;
-
-    private ReentrantLock _accessRightsUpdate = new ReentrantLock();
 
     // Setup for the TabularType
-    static TabularType _userlistDataType; // Datatype for representing User Lists
-    static CompositeType _userDataType; // Composite type for representing User
+    private static final TabularType _userlistDataType; // Datatype for representing User Lists
+    private static final CompositeType _userDataType; // Composite type for representing User
 
     static
     {
         OpenType[] userItemTypes = new OpenType[4]; // User item types.
         userItemTypes[0] = SimpleType.STRING;  // For Username
-        userItemTypes[1] = SimpleType.BOOLEAN; // For Rights - Read
-        userItemTypes[2] = SimpleType.BOOLEAN; // For Rights - Write
-        userItemTypes[3] = SimpleType.BOOLEAN; // For Rights - Admin
+        userItemTypes[1] = SimpleType.BOOLEAN; // For Rights - Read - No longer in use
+        userItemTypes[2] = SimpleType.BOOLEAN; // For Rights - Write - No longer in use
+        userItemTypes[3] = SimpleType.BOOLEAN; // For Rights - Admin - No longer is use
 
         try
         {
@@ -92,12 +74,11 @@ public class AMQUserManagementMBean exte
         }
         catch (OpenDataException e)
         {
-            _logger.error("Tabular data setup for viewing users incorrect.");
-            _userlistDataType = null;
+            _logger.error("Tabular data setup for viewing users incorrect.", e);
+            throw new ExceptionInInitializerError("Tabular data setup for viewing users incorrect");
         }
     }
 
-
     public AMQUserManagementMBean() throws JMException
     {
         super(UserManagement.class, UserManagement.TYPE);
@@ -110,121 +91,23 @@ public class AMQUserManagementMBean exte
 
     public boolean setPassword(String username, String password)
     {
-        return setPassword(username, password.toCharArray());
-    }
-    
-    public boolean setPassword(String username, char[] password)
-    {
         try
         {
             //delegate password changes to the Principal Database
-            return _principalDatabase.updatePassword(new UsernamePrincipal(username), password);
+            return _principalDatabase.updatePassword(new UsernamePrincipal(username), password.toCharArray());
         }
         catch (AccountNotFoundException e)
         {
-            _logger.warn("Attempt to set password of non-existant user'" + username + "'");
+            _logger.warn("Attempt to set password of non-existent user'" + username + "'");
             return false;
         }
     }
 
-    public boolean setRights(String username, boolean read, boolean write, boolean admin)
+    public boolean createUser(String username, String password)
     {
-
-        Object oldRights = null;
-        if ((oldRights =_accessRights.get(username)) == null)
-        {
-            // If the user doesn't exist in the access rights file check that they at least have an account.
-            if (_principalDatabase.getUser(username) == null)
-            {
-                return false;
-            }
-        }
-
-        try
+        if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password.toCharArray()))
         {
-            _accessRightsUpdate.lock();
-
-            // Update the access rights
-            if (admin)
-            {
-                _accessRights.put(username, MBeanInvocationHandlerImpl.ADMIN);
-            }
-            else
-            {
-                if (read | write)
-                {
-                    if (read)
-                    {
-                        _accessRights.put(username, MBeanInvocationHandlerImpl.READONLY);
-                    }
-                    if (write)
-                    {
-                        _accessRights.put(username, MBeanInvocationHandlerImpl.READWRITE);
-                    }
-                }
-                else
-                {
-                    _accessRights.remove(username);
-                }
-            }
-            
-            //save the rights file
-            try
-            {
-                saveAccessFile();
-            }
-            catch (IOException e)
-            {
-                _logger.warn("Problem occured saving '" + _accessFile + "', the access right changes will not be preserved: " + e);
-
-                //the rights file was not successfully saved, restore user rights to previous value
-                _logger.warn("Reverting attempted rights update for user'" + username + "'");
-                if (oldRights != null)
-                {
-                    _accessRights.put(username, oldRights);
-                }
-                else
-                {
-                    _accessRights.remove(username);
-                }
-
-                return false;
-            }
-        }
-        finally
-        {
-            _accessRightsUpdate.unlock();
-        }
-
-        return true;
-    }
-    
-    public boolean createUser(String username, String password, boolean read, boolean write, boolean admin)
-    {
-        return createUser(username, password.toCharArray(), read, write, admin);
-    }
-
-    public boolean createUser(String username, char[] password, boolean read, boolean write, boolean admin)
-    {
-        if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password))
-        {
-            if (!setRights(username, read, write, admin))
-            {
-                //unable to set rights for user, remove account
-                try
-                {
-                    _principalDatabase.deletePrincipal(new UsernamePrincipal(username));
-                }
-                catch (AccountNotFoundException e)
-                {
-                    //ignore
-                }
-                return false;
-            }
-            else
-            {
-                return true;
-            }
+            return true;
         }
 
         return false;
@@ -234,29 +117,7 @@ public class AMQUserManagementMBean exte
     {
         try
         {
-            if (_principalDatabase.deletePrincipal(new UsernamePrincipal(username)))
-            {
-                try
-                {
-                    _accessRightsUpdate.lock();
-
-                    _accessRights.remove(username);
-                    
-                    try
-                    {
-                        saveAccessFile();
-                    }
-                    catch (IOException e)
-                    {
-                        _logger.warn("Problem occured saving '" + _accessFile + "', the access right changes will not be preserved: " + e);
-                        return false;
-                    }
-                }
-                finally
-                {
-                    _accessRightsUpdate.unlock();
-                }
-            }
+            _principalDatabase.deletePrincipal(new UsernamePrincipal(username));
         }
         catch (AccountNotFoundException e)
         {
@@ -269,38 +130,23 @@ public class AMQUserManagementMBean exte
 
     public boolean reloadData()
     {
-            try
-            {
-                loadAccessFile();
-                _principalDatabase.reload();
-            }
-            catch (ConfigurationException e)
-            {
-                _logger.warn("Reload failed due to:" + e);
-                return false;
-            }
-            catch (IOException e)
-            {
-                _logger.warn("Reload failed due to:" + e);
-                return false;
-            }
-            // Reload successful
-            return true;
+        try
+        {
+            _principalDatabase.reload();
+        }
+        catch (IOException e)
+        {
+            _logger.warn("Reload failed due to:", e);
+            return false;
+        }
+        // Reload successful
+        return true;
     }
 
 
-    @MBeanOperation(name = "viewUsers", description = "All users with access rights to the system.")
+    @MBeanOperation(name = "viewUsers", description = "All users that are currently available to the system.")
     public TabularData viewUsers()
     {
-        // Table of users
-        // Username(string), Access rights Read,Write,Admin(bool,bool,bool)
-
-        if (_userlistDataType == null)
-        {
-            _logger.warn("TabluarData not setup correctly");
-            return null;
-        }
-
         List<Principal> users = _principalDatabase.getUsers();
 
         TabularDataSupport userList = new TabularDataSupport(_userlistDataType);
@@ -311,29 +157,15 @@ public class AMQUserManagementMBean exte
             for (Principal user : users)
             {
                 // Create header attributes list
-
-                String rights = (String) _accessRights.get(user.getName());
-
-                Boolean read = false;
-                Boolean write = false;
-                Boolean admin = false;
-
-                if (rights != null)
-                {
-                    read = rights.equals(MBeanInvocationHandlerImpl.READONLY)
-                           || rights.equals(MBeanInvocationHandlerImpl.READWRITE);
-                    write = rights.equals(MBeanInvocationHandlerImpl.READWRITE);
-                    admin = rights.equals(MBeanInvocationHandlerImpl.ADMIN);
-                }
-
-                Object[] itemData = {user.getName(), read, write, admin};
+                // Read,Write,Admin items are depcreated and we return always false.
+                Object[] itemData = {user.getName(), false, false, false};
                 CompositeData messageData = new CompositeDataSupport(_userDataType, COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData);
                 userList.put(messageData);
             }
         }
         catch (OpenDataException e)
         {
-            _logger.warn("Unable to create user list due to :" + e);
+            _logger.warn("Unable to create user list due to :", e);
             return null;
         }
 
@@ -351,187 +183,4 @@ public class AMQUserManagementMBean exte
     {
         _principalDatabase = database;
     }
-
-    /**
-     * setAccessFile
-     *
-     * @param accessFile the file to use for updating.
-     *
-     * @throws java.io.IOException If the file cannot be accessed
-     * @throws org.apache.commons.configuration.ConfigurationException
-     *                             if checks on the file fail.
-     */
-    public void setAccessFile(String accessFile) throws IOException, ConfigurationException
-    {
-        if (accessFile != null)
-        {
-            _accessFile = new File(accessFile);
-            if (!_accessFile.exists())
-            {
-                throw new ConfigurationException("'" + _accessFile + "' does not exist");
-            }
-
-            if (!_accessFile.canRead())
-            {
-                throw new ConfigurationException("Cannot read '" + _accessFile + "'.");
-            }
-
-            if (!_accessFile.canWrite())
-            {
-                _logger.warn("Unable to write to access rights file '" + _accessFile + "', changes will not be preserved.");
-            }
-
-            loadAccessFile();
-        }
-        else
-        {
-            _logger.warn("Access rights file specified is null. Access rights not changed.");
-        }
-    }
-
-    private void loadAccessFile() throws IOException, ConfigurationException
-    {
-        if(_accessFile == null)
-        {
-            _logger.error("No jmx access rights file has been specified.");
-            return;
-        }
-        
-        if(_accessFile.exists())
-        {
-            try
-            {
-                _accessRightsUpdate.lock();
-
-                Properties accessRights = new Properties();
-                FileInputStream inStream = new FileInputStream(_accessFile);
-                try
-                {
-                    accessRights.load(inStream);
-                }
-                finally
-                {
-                    inStream.close();
-                }
-
-                checkAccessRights(accessRights);
-                setAccessRights(accessRights);
-            }
-            finally
-            {
-                _accessRightsUpdate.unlock();
-            }
-        }
-        else
-        {
-            _logger.error("Specified jmxaccess rights file '" + _accessFile + "' does not exist.");
-        }
-    }
-
-    private void checkAccessRights(Properties accessRights)
-    {
-        Enumeration values = accessRights.propertyNames();
-
-        while (values.hasMoreElements())
-        {
-            String user = (String) values.nextElement();
-
-            if (_principalDatabase.getUser(user) == null)
-            {
-                _logger.warn("Access rights contains user '" + user + "' but there is no authentication data for that user");
-            }
-        }
-    }
-
-    private void saveAccessFile() throws IOException
-    {
-        try
-        {
-            _accessRightsUpdate.lock();
-
-            // Create temporary file
-            Random r = new Random();
-            File tmp;
-            do
-            {
-                tmp = new File(_accessFile.getPath() + r.nextInt() + ".tmp");
-            }
-            while(tmp.exists());
-            
-            tmp.deleteOnExit();
-
-            FileOutputStream output = new FileOutputStream(tmp);
-            _accessRights.store(output, "Generated by AMQUserManagementMBean Console : Last edited by user:" + getCurrentJMXUser());
-            output.close();
-
-            // Swap temp file to main rights file.
-            File old = new File(_accessFile.getAbsoluteFile() + ".old");
-            if (old.exists())
-            {
-                old.delete();
-            }
-            
-            if(!_accessFile.renameTo(old))
-            {
-                //unable to rename the existing file to the backup name 
-                _logger.error("Could not backup the existing management rights file");
-                throw new IOException("Could not backup the existing management rights file");
-            }
-
-            if(!tmp.renameTo(_accessFile))
-            {
-                //failed to rename the new file to the required filename
-                
-                if(!old.renameTo(_accessFile))
-                {
-                    //unable to return the backup to required filename
-                    _logger.error("Could not rename the new management rights file into place, and unable to restore original file");
-                    throw new IOException("Could not rename the new management rights file into place, and unable to restore original file");
-                }
-                
-                _logger.error("Could not rename the new management rights file into place");
-                throw new IOException("Could not rename the new management rights file into place");
-            }
-        }
-        finally
-        {
-            _accessRightsUpdate.unlock();
-        }
-        
-    }
-
-    private String getCurrentJMXUser()
-    {
-        AccessControlContext acc = AccessController.getContext();
-        
-        Subject subject = Subject.getSubject(acc);
-        if (subject == null)
-        {
-            return "Unknown user, authentication Subject was null";
-        }
-
-        // Retrieve JMXPrincipal from Subject
-        Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
-        if (principals == null || principals.isEmpty())
-        {
-            return "Unknown user principals were null";
-        }
-
-        Principal principal = principals.iterator().next();
-        return principal.getName();
-    }
-
-    /**
-     * user=read user=write user=readwrite user=admin
-     *
-     * @param accessRights The properties list of access rights to process
-     */
-    private void setAccessRights(Properties accessRights)
-    {
-        _logger.debug("Setting Access Rights:" + accessRights);
-        _accessRights = accessRights;
-		
-		// TODO check where this is used
-        // MBeanInvocationHandlerImpl.setAccessRights(_accessRights);
-    }
 }

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java Thu Oct 20 18:42:46 2011
@@ -20,17 +20,73 @@
  */
 package org.apache.qpid.server.security.auth.manager;
 
+import javax.security.auth.Subject;
 import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
 
 import org.apache.qpid.common.Closeable;
+import org.apache.qpid.server.plugins.Plugin;
 import org.apache.qpid.server.security.auth.AuthenticationResult;
 
-public interface AuthenticationManager extends Closeable
+/**
+ * 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 Subject} containing the user's identity and zero or more principals representing
+ * groups to which the user belongs.
+ * <p>
+ * The {@link #initialise()} method is responsible for registering SASL mechanisms required by
+ * the manager.  The {@link #close()} method must reverse this registration.
+ * 
+ */
+public interface AuthenticationManager extends Closeable, Plugin
 {
+    /** The name for the required SASL Server mechanisms */
+    public static final String PROVIDER_NAME= "AMQSASLProvider-Server";
+
+    /**
+     * Initialise the authentication plugin.
+     *
+     */
+    void initialise();
+
+   /**
+    * Gets the SASL mechanisms known to this manager.
+    *
+    * @return SASL mechanism names, space separated.
+    */
     String getMechanisms();
 
+    /**
+     * Creates a SASL server for the specified mechanism name for the given
+     * fully qualified domain name.
+     *
+     * @param mechanism mechanism name
+     * @param localFQDN domain name
+     *
+     * @return SASL server
+     * @throws SaslException
+     */
     SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException;
 
+    /**
+     * Authenticates a user using SASL negotiation.
+     *
+     * @param server SASL server
+     * @param response SASL response to process
+     *
+     * @return authentication result
+     */
     AuthenticationResult authenticate(SaslServer server, byte[] response);
+
+    /**
+     * Authenticates a user using their username and password.
+     *
+     * @param username username
+     * @param password password
+     *
+     * @return authentication result
+     */
+    AuthenticationResult authenticate(String username, String password);
 }

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java Thu Oct 20 18:42:46 2011
@@ -20,27 +20,65 @@
  */
 package org.apache.qpid.server.security.auth.manager;
 
-import org.apache.log4j.Logger;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.AccountNotFoundException;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import javax.security.sasl.SaslServerFactory;
+
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.configuration.ConfigurationException;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.log4j.Logger;
+import org.apache.qpid.configuration.PropertyException;
+import org.apache.qpid.configuration.PropertyUtils;
+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.AuthenticationResult.AuthenticationStatus;
 import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.server.security.auth.sasl.JCAProvider;
+import org.apache.qpid.server.security.auth.management.AMQUserManagementMBean;
 import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
-import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.sasl.JCAProvider;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
 
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.sasl.SaslServerFactory;
-import javax.security.sasl.SaslServer;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.Sasl;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.TreeMap;
-import java.security.Security;
 
+/**
+ * Concrete implementation of the AuthenticationManager that determines if supplied
+ * user credentials match those appearing in a PrincipalDatabase.   The implementation
+ * of the PrincipalDatabase is determined from the configuration.
+ * 
+ * This implementation also registers the JMX UserManagemement MBean.
+ * 
+ * This plugin expects configuration such as:
+ *
+ * <pre>
+ * &lt;pd-auth-manager&gt;
+ *   &lt;principal-database&gt;
+ *      &lt;class&gt;org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase&lt;/class&gt;
+ *      &lt;attributes&gt;
+ *         &lt;attribute&gt;
+ *              &lt;name>passwordFile&lt;/name&gt;
+ *              &lt;value>${conf}/passwd&lt;/value&gt;
+ *          &lt;/attribute&gt;
+ *      &lt;/attributes&gt;
+ *   &lt;/principal-database&gt;
+ * &lt;/pd-auth-manager&gt;
+ * </pre>
+ */
 public class PrincipalDatabaseAuthenticationManager implements AuthenticationManager
 {
     private static final Logger _logger = Logger.getLogger(PrincipalDatabaseAuthenticationManager.class);
@@ -49,55 +87,109 @@ public class PrincipalDatabaseAuthentica
     private String _mechanisms;
 
     /** Maps from the mechanism to the callback handler to use for handling those requests */
-    private Map<String, CallbackHandler> _callbackHandlerMap = new HashMap<String, CallbackHandler>();
+    private final Map<String, CallbackHandler> _callbackHandlerMap = new HashMap<String, CallbackHandler>();
 
     /**
      * Maps from the mechanism to the properties used to initialise the server. See the method Sasl.createSaslServer for
      * details of the use of these properties. This map is populated during initialisation of each provider.
      */
-    private Map<String, Map<String, ?>> _serverCreationProperties = new HashMap<String, Map<String, ?>>();
+    private final Map<String, Map<String, ?>> _serverCreationProperties = new HashMap<String, Map<String, ?>>();
 
-    private AuthenticationManager _default = null;
-    /** The name for the required SASL Server mechanisms */
-    public static final String PROVIDER_NAME= "AMQSASLProvider-Server";
+    protected PrincipalDatabase _principalDatabase = null;
 
-    public PrincipalDatabaseAuthenticationManager(String name, VirtualHostConfiguration hostConfig) throws Exception
-    {
-        _logger.info("Initialising " + (name == null ? "Default" : "'" + name + "'")
-                     + " PrincipalDatabase authentication manager.");
+    protected AMQUserManagementMBean _mbean = null;
 
-        // Fixme This should be done per Vhost but allowing global hack isn't right but ...
-        // required as authentication is done before Vhost selection
+    public static final AuthenticationManagerPluginFactory<PrincipalDatabaseAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<PrincipalDatabaseAuthenticationManager>()
+    {
+        public PrincipalDatabaseAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException
+        {
+            final PrincipalDatabaseAuthenticationManagerConfiguration configuration = config.getConfiguration(PrincipalDatabaseAuthenticationManagerConfiguration.class.getName());
 
-        Map<String, Class<? extends SaslServerFactory>> providerMap = new TreeMap<String, Class<? extends SaslServerFactory>>();
+            // If there is no configuration for this plugin then don't load it.
+            if (configuration == null)
+            {
+                _logger.info("No authentication-manager configuration found for PrincipalDatabaseAuthenticationManager");
+                return null;
+            }
 
+            final PrincipalDatabaseAuthenticationManager pdam = new PrincipalDatabaseAuthenticationManager();
+            pdam.configure(configuration);
+            pdam.initialise();
+            return pdam;
+        }
 
-        if (name == null || hostConfig == null)
+        public Class<PrincipalDatabaseAuthenticationManager> getPluginClass()
         {
-            initialiseAuthenticationMechanisms(providerMap, ApplicationRegistry.getInstance().getDatabaseManager().getDatabases());
+            return PrincipalDatabaseAuthenticationManager.class;
         }
-        else
+
+        public String getPluginName()
         {
-            String databaseName = hostConfig.getAuthenticationDatabase();
+            return PrincipalDatabaseAuthenticationManager.class.getName();
+        }
+    };
 
-            if (databaseName == null)
+    public static class PrincipalDatabaseAuthenticationManagerConfiguration extends ConfigurationPlugin {
+ 
+        public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
+        {
+            public List<String> getParentPaths()
             {
-
-                _default = ApplicationRegistry.getInstance().getAuthenticationManager();
-                return;
+                return Arrays.asList("security.pd-auth-manager");
             }
-            else
+
+            public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException
             {
-                PrincipalDatabase database = ApplicationRegistry.getInstance().getDatabaseManager().getDatabases().get(databaseName);
+                final ConfigurationPlugin instance = new PrincipalDatabaseAuthenticationManagerConfiguration();
+                
+                instance.setConfiguration(path, config);
+                return instance;
+            }
+        };
 
-                if (database == null)
-                {
-                    throw new ConfigurationException("Requested database:" + databaseName + " was not found");
-                }
+        public String[] getElementsProcessed()
+        {
+            return new String[] {"principal-database.class",
+                                 "principal-database.attributes.attribute.name",
+                                 "principal-database.attributes.attribute.value"};
+        }
 
-                initialiseAuthenticationMechanisms(providerMap, database);
+        public void validateConfiguration() throws ConfigurationException
+        {
+        }
+  
+        public String getPrincipalDatabaseClass()
+        {
+            return _configuration.getString("principal-database.class");
+        }
+  
+        public Map<String,String> getPdClassAttributeMap() throws ConfigurationException
+        {
+            final List<String> argumentNames = _configuration.getList("principal-database.attributes.attribute.name");
+            final List<String> argumentValues = _configuration.getList("principal-database.attributes.attribute.value");
+            final Map<String,String> attributes = new HashMap<String,String>(argumentNames.size());
+
+            for (int i = 0; i < argumentNames.size(); i++)
+            {
+                final String argName = argumentNames.get(i);
+                final String argValue = argumentValues.get(i);
+
+                attributes.put(argName, argValue);
             }
+
+            return Collections.unmodifiableMap(attributes);
         }
+    }
+
+    protected PrincipalDatabaseAuthenticationManager()  
+    {
+    }
+
+    public void initialise()
+    {
+        final Map<String, Class<? extends SaslServerFactory>> providerMap = new TreeMap<String, Class<? extends SaslServerFactory>>();
+
+        initialiseAuthenticationMechanisms(providerMap, _principalDatabase);
 
         if (providerMap.size() > 0)
         {
@@ -110,33 +202,16 @@ public class PrincipalDatabaseAuthentica
             {
                 _logger.info("Additional SASL providers successfully registered.");
             }
-
         }
         else
         {
             _logger.warn("No additional SASL providers registered.");
         }
 
+        registerManagement();
     }
 
-
-    private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, Map<String, PrincipalDatabase> databases) throws Exception
-    {
-        if (databases.size() > 1)
-        {
-            _logger.warn("More than one principle database provided currently authentication mechanism will override each other.");
-        }
-
-        for (Map.Entry<String, PrincipalDatabase> entry : databases.entrySet())
-        {
-            // fixme As the database now provide the mechanisms they support, they will ...
-            // overwrite each other in the map. There should only be one database per vhost.
-            // But currently we must have authentication before vhost definition.
-            initialiseAuthenticationMechanisms(providerMap, entry.getValue());
-        }
-    }
-
-    private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database) throws Exception
+    private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database) 
     {
         if (database == null || database.getMechanisms().size() == 0)
         {
@@ -152,7 +227,6 @@ public class PrincipalDatabaseAuthentica
 
     private void initialiseAuthenticationMechanism(String mechanism, AuthenticationProviderInitialiser initialiser,
                                                    Map<String, Class<? extends SaslServerFactory>> providerMap)
-            throws Exception
     {
         if (_mechanisms == null)
         {
@@ -173,43 +247,37 @@ public class PrincipalDatabaseAuthentica
         _logger.info("Initialised " + mechanism + " SASL provider successfully");
     }
 
+    /**
+     * @see org.apache.qpid.server.plugins.Plugin#configure(org.apache.qpid.server.configuration.plugins.ConfigurationPlugin)
+     */
+    public void configure(final ConfigurationPlugin config) throws ConfigurationException
+    {
+        final PrincipalDatabaseAuthenticationManagerConfiguration pdamConfig = (PrincipalDatabaseAuthenticationManagerConfiguration) config;
+        final String pdClazz = pdamConfig.getPrincipalDatabaseClass();
+
+        _logger.info("PrincipalDatabase concrete implementation : " + pdClazz);
+
+        _principalDatabase = createPrincipalDatabaseImpl(pdClazz);
+
+        configPrincipalDatabase(_principalDatabase, pdamConfig);        
+    }
+
     public String getMechanisms()
     {
-        if (_default != null)
-        {
-            // Use the default AuthenticationManager if present
-            return _default.getMechanisms();
-        }
-        else
-        {
-            return _mechanisms;
-        }
+        return _mechanisms;
     }
 
     public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
     {
-        if (_default != null)
-        {
-            // Use the default AuthenticationManager if present
-            return _default.createSaslServer(mechanism, localFQDN);
-        }
-        else
-        {
-            return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, _serverCreationProperties.get(mechanism),
-                                         _callbackHandlerMap.get(mechanism));
-        }
-
+        return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, _serverCreationProperties.get(mechanism),
+                                     _callbackHandlerMap.get(mechanism));
     }
 
+    /**
+     * @see org.apache.qpid.server.security.auth.manager.AuthenticationManager#authenticate(SaslServer, byte[])
+     */
     public AuthenticationResult authenticate(SaslServer server, byte[] response)
     {
-        // Use the default AuthenticationManager if present
-        if (_default != null)
-        {
-            return _default.authenticate(server, response);
-        }
-
-
         try
         {
             // Process response from the client
@@ -217,7 +285,9 @@ public class PrincipalDatabaseAuthentica
 
             if (server.isComplete())
             {
-                return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.SUCCESS);
+                final Subject subject = new Subject();
+                subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID()));
+                return new AuthenticationResult(subject);
             }
             else
             {
@@ -230,8 +300,164 @@ public class PrincipalDatabaseAuthentica
         }
     }
 
+    /**
+     * @see org.apache.qpid.server.security.auth.manager.AuthenticationManager#authenticate(String, String)
+     */
+    public AuthenticationResult authenticate(final String username, final String password)
+    {
+        try
+        {
+            if (_principalDatabase.verifyPassword(username, password.toCharArray()))
+            {
+                final Subject subject = new Subject();
+                subject.getPrincipals().add(new UsernamePrincipal(username));
+                return new AuthenticationResult(subject);
+            }
+            else
+            {
+                return new AuthenticationResult(AuthenticationStatus.CONTINUE);
+            }
+        }
+        catch (AccountNotFoundException e)
+        {
+            return new AuthenticationResult(AuthenticationStatus.CONTINUE);
+        }
+    }
+
     public void close()
     {
+        _mechanisms = null;
         Security.removeProvider(PROVIDER_NAME);
+
+        unregisterManagement();
+    }
+
+    private PrincipalDatabase createPrincipalDatabaseImpl(final String pdClazz) throws ConfigurationException
+    {
+        try
+        {
+            return (PrincipalDatabase) Class.forName(pdClazz).newInstance();
+        }
+        catch (InstantiationException ie)
+        {
+            throw new ConfigurationException("Cannot instantiate " + pdClazz, ie);
+        }
+        catch (IllegalAccessException iae)
+        {
+            throw new ConfigurationException("Cannot access " + pdClazz, iae);
+        }
+        catch (ClassNotFoundException cnfe)
+        {
+            throw new ConfigurationException("Cannot load " + pdClazz + " implementation", cnfe);
+        }
+        catch (ClassCastException cce)
+        {
+            throw new ConfigurationException("Expecting a " + PrincipalDatabase.class + " implementation", cce);
+        }
+    }
+
+    private void configPrincipalDatabase(final PrincipalDatabase principalDatabase, final PrincipalDatabaseAuthenticationManagerConfiguration config)
+            throws ConfigurationException
+    {
+
+        final Map<String,String> attributes = config.getPdClassAttributeMap();
+
+        for (Iterator<Entry<String, String>> iterator = attributes.entrySet().iterator(); iterator.hasNext();)
+        {
+            final Entry<String, String> nameValuePair = iterator.next();
+            final String methodName = generateSetterName(nameValuePair.getKey());
+            final Method method;
+            try
+            {
+                method = principalDatabase.getClass().getMethod(methodName, String.class);
+            }
+            catch (Exception e)
+            {
+                throw new ConfigurationException("No method " + methodName + " found in class "
+                        + principalDatabase.getClass()
+                        + " hence unable to configure principal database. The method must be public and "
+                        + "have a single String argument with a void return type", e);
+            }
+            try
+            {
+                method.invoke(principalDatabase, PropertyUtils.replaceProperties(nameValuePair.getValue()));
+            }
+            catch (IllegalArgumentException e)
+            {
+                throw new ConfigurationException(e.getMessage(), e);
+            }
+            catch (PropertyException e)
+            {
+                throw new ConfigurationException(e.getMessage(), e);
+            }
+            catch (IllegalAccessException e)
+            {
+                throw new ConfigurationException(e.getMessage(), e);
+            }
+            catch (InvocationTargetException e)
+            {
+                // QPID-1347..  InvocationTargetException wraps the checked exception thrown from the reflective
+                // method call.  Pull out the underlying message and cause to make these more apparent to the user.
+                throw new ConfigurationException(e.getCause().getMessage(), e.getCause());
+            }
+        }
+    }
+
+    private String generateSetterName(String argName) throws ConfigurationException
+    {
+        if ((argName == null) || (argName.length() == 0))
+        {
+            throw new ConfigurationException("Argument names must have length >= 1 character");
+        }
+
+        if (Character.isLowerCase(argName.charAt(0)))
+        {
+            argName = Character.toUpperCase(argName.charAt(0)) + argName.substring(1);
+        }
+
+        final String methodName = "set" + argName;
+        return methodName;
+    }
+
+    protected void setPrincipalDatabase(final PrincipalDatabase principalDatabase)
+    {
+        _principalDatabase = principalDatabase;
+    }
+
+    protected void registerManagement()
+    {
+        try
+        {
+            _logger.info("Registering UserManagementMBean");
+
+            _mbean = new AMQUserManagementMBean();
+            _mbean.setPrincipalDatabase(_principalDatabase);
+            _mbean.register();
+        }
+        catch (Exception e)
+        {
+            _logger.warn("User management disabled as unable to create MBean:", e);
+            _mbean = null;
+        }
+    }
+
+    protected void unregisterManagement()
+    {
+        try
+        {
+            if (_mbean != null)
+            {
+                _logger.info("Unregistering UserManagementMBean");
+                _mbean.unregister();
+            }
+        }
+        catch (Exception e)
+        {
+            _logger.warn("Failed to unregister User management MBean:", e);
+        }
+        finally
+        {
+            _mbean = null;
+        }
     }
 }

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java Thu Oct 20 18:42:46 2011
@@ -20,14 +20,13 @@
  */
 package org.apache.qpid.server.security.auth.rmi;
 
-import java.util.Collections;
-
 import javax.management.remote.JMXAuthenticator;
 import javax.management.remote.JMXPrincipal;
 import javax.security.auth.Subject;
-import javax.security.auth.login.AccountNotFoundException;
 
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
 
 public class RMIPasswordAuthenticator implements JMXAuthenticator
 {
@@ -39,15 +38,15 @@ public class RMIPasswordAuthenticator im
     static final String CREDENTIALS_REQUIRED = "User details are required. " +
     		            "Please ensure you are using an up to date management console to connect.";
     
-    private PrincipalDatabase _db = null;
+    private AuthenticationManager _authenticationManager = null;
 
     public RMIPasswordAuthenticator()
     {
     }
-    
-    public void setPrincipalDatabase(PrincipalDatabase pd)
+
+    public void setAuthenticationManager(final AuthenticationManager authenticationManager)
     {
-        this._db = pd;
+        _authenticationManager = authenticationManager;
     }
 
     public Subject authenticate(Object credentials) throws SecurityException
@@ -65,50 +64,39 @@ public class RMIPasswordAuthenticator im
             }
         }
 
-        // Verify that required number of credential's.
+        // Verify that required number of credentials.
         final String[] userCredentials = (String[]) credentials;
         if (userCredentials.length != 2)
         {
             throw new SecurityException(SHOULD_HAVE_2_ELEMENTS);
         }
 
-        String username = (String) userCredentials[0];
-        String password = (String) userCredentials[1];
+        final String username = (String) userCredentials[0];
+        final String password = (String) userCredentials[1];
 
-        // Verify that all required credential's are actually present.
+        // Verify that all required credentials are actually present.
         if (username == null || password == null)
         {
             throw new SecurityException(SHOULD_BE_NON_NULL);
         }
         
-        // Verify that a PD has been set.
-        if (_db == null)
+        // Verify that an AuthenticationManager has been set.
+        if (_authenticationManager == null)
         {
             throw new SecurityException(UNABLE_TO_LOOKUP);
         }
-        
-        boolean authenticated = false;
+        final AuthenticationResult result = _authenticationManager.authenticate(username, password);
 
-        // Perform authentication
-        try
+        if (AuthenticationStatus.ERROR.equals(result.getStatus()))
         {
-            if (_db.verifyPassword(username, password.toCharArray()))
-            {            
-                authenticated = true;
-            }
-        }
-        catch (AccountNotFoundException e)
-        {
-            throw new SecurityException(INVALID_CREDENTIALS); // XXX
+            throw new SecurityException("Authentication manager failed", result.getCause());
         }
-
-        if (authenticated)
+        else if (AuthenticationStatus.SUCCESS.equals(result.getStatus()))
         {
-            //credential's check out, return the appropriate JAAS Subject
-            return new Subject(true,
-                    Collections.singleton(new JMXPrincipal(username)),
-                    Collections.EMPTY_SET,
-                    Collections.EMPTY_SET);
+            final Subject subject = result.getSubject();
+            subject.getPrincipals().add(new JMXPrincipal(username));
+            subject.setReadOnly();
+            return subject;
         }
         else
         {

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java Thu Oct 20 18:42:46 2011
@@ -25,9 +25,6 @@ import java.util.Map;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.sasl.SaslServerFactory;
 
-import org.apache.commons.configuration.Configuration;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-
 public interface AuthenticationProviderInitialiser
 {
     /**
@@ -37,24 +34,6 @@ public interface AuthenticationProviderI
     String getMechanismName();
 
     /**
-     * Initialise the authentication provider.
-     * @param baseConfigPath the path in the config file that points to any config options for this provider. Each
-     * provider can have its own set of configuration options
-     * @param configuration the Apache Commons Configuration instance used to configure this provider
-     * @param principalDatabases the set of principal databases that are available
-     * @throws Exception needs refined Exception is too broad.
-     */
-    void initialise(String baseConfigPath, Configuration configuration,
-                    Map<String, PrincipalDatabase> principalDatabases) throws Exception;
-
-    /**
-     * Initialise the authentication provider.     
-     * @param db The principal database to initialise with
-     */
-    void initialise(PrincipalDatabase db);
-
-
-    /**
      * @return the callback handler that should be used to process authentication requests for this mechanism. This will
      * be called after initialise and will be stored by the authentication manager. The callback handler <b>must</b> be
      * fully threadsafe.

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java Thu Oct 20 18:42:46 2011
@@ -21,12 +21,11 @@
 package org.apache.qpid.server.security.auth.sasl;
 
 import java.security.Provider;
-import java.security.Security;
 import java.util.Map;
 
 import javax.security.sasl.SaslServerFactory;
 
-public final class JCAProvider extends Provider
+public class JCAProvider extends Provider
 {
     public JCAProvider(String name, Map<String, Class<? extends SaslServerFactory>> providerMap)
     {

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java Thu Oct 20 18:42:46 2011
@@ -21,14 +21,21 @@
 package org.apache.qpid.server.security.auth.sasl;
 
 import java.security.Principal;
+import java.util.Set;
+
+import javax.security.auth.Subject;
 
 /** A principal that is just a wrapper for a simple username. */
 public class UsernamePrincipal implements Principal
 {
-    private String _name;
+    private final String _name;
 
     public UsernamePrincipal(String name)
     {
+        if (name == null)
+        {
+            throw new IllegalArgumentException("name cannot be null");
+        }
         _name = name;
     }
 
@@ -41,4 +48,53 @@ public class UsernamePrincipal implement
     {
         return _name;
     }
+
+    /**
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        return prime * _name.hashCode();
+    }
+
+    /**
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj)
+        {
+            return true;
+        }
+        else
+        {
+            if (obj instanceof UsernamePrincipal)
+            {
+                UsernamePrincipal other = (UsernamePrincipal) obj;
+                return _name.equals(other._name);
+            }
+            else
+            {
+                return false;
+            }
+        }
+    }
+
+    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/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java Thu Oct 20 18:42:46 2011
@@ -20,6 +20,8 @@
  */
 package org.apache.qpid.server.security.auth.sasl.amqplain;
 
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
 import java.io.IOException;
 
 import javax.security.auth.callback.Callback;
@@ -31,7 +33,6 @@ import javax.security.sasl.AuthorizeCall
 import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
 
-import org.apache.mina.common.ByteBuffer;
 import org.apache.qpid.framing.AMQFrameDecodingException;
 import org.apache.qpid.framing.FieldTable;
 import org.apache.qpid.framing.FieldTableFactory;
@@ -60,7 +61,7 @@ public class AmqPlainSaslServer implemen
     {
         try
         {
-            final FieldTable ft = FieldTableFactory.newFieldTable(ByteBuffer.wrap(response), response.length);
+            final FieldTable ft = FieldTableFactory.newFieldTable(new DataInputStream(new ByteArrayInputStream(response)), response.length);
             String username = (String) ft.getString("LOGIN");
             // we do not care about the prompt but it throws if null
             NameCallback nameCb = new NameCallback("prompt", username);

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java Thu Oct 20 18:42:46 2011
@@ -45,9 +45,10 @@ public class AmqPlainSaslServerFactory i
 
     public String[] getMechanismNames(Map props)
     {
-        if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
-            props.containsKey(Sasl.POLICY_NODICTIONARY) ||
-            props.containsKey(Sasl.POLICY_NOACTIVE))
+        if (props != null &&
+            (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+             props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+             props.containsKey(Sasl.POLICY_NOACTIVE)))
         {
             // returned array must be non null according to interface documentation
             return new String[0];

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java Thu Oct 20 18:42:46 2011
@@ -20,21 +20,9 @@
  */
 package org.apache.qpid.server.security.auth.sasl.anonymous;
 
-import java.io.IOException;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.sasl.AuthorizeCallback;
 import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
 
-import org.apache.mina.common.ByteBuffer;
-import org.apache.qpid.framing.AMQFrameDecodingException;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.FieldTableFactory;
 
 public class AnonymousSaslServer implements SaslServer
 {

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java Thu Oct 20 18:42:46 2011
@@ -47,10 +47,11 @@ public class AnonymousSaslServerFactory 
 
     public String[] getMechanismNames(Map props)
     {
-        if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
-            props.containsKey(Sasl.POLICY_NODICTIONARY) ||
-            props.containsKey(Sasl.POLICY_NOACTIVE) ||
-            props.containsKey(Sasl.POLICY_NOANONYMOUS))
+        if (props != null &&
+            (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+             props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+             props.containsKey(Sasl.POLICY_NOACTIVE) ||
+             props.containsKey(Sasl.POLICY_NOANONYMOUS)))
         {
             // returned array must be non null according to interface documentation
             return new String[0];

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java Thu Oct 20 18:42:46 2011
@@ -70,7 +70,7 @@ public class CRAMMD5HexInitialiser exten
             for (char c : password)
             {
                 //toHexString does not prepend 0 so we have to
-                if (((byte) c > -1) && (byte) c < 10)
+                if (((byte) c > -1) && (byte) c < 0x10 )
                 {
                     sb.append(0);
                 }

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java Thu Oct 20 18:42:46 2011
@@ -45,9 +45,10 @@ public class PlainSaslServerFactory impl
 
     public String[] getMechanismNames(Map props)
     {
-        if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
-            props.containsKey(Sasl.POLICY_NODICTIONARY) ||
-            props.containsKey(Sasl.POLICY_NOACTIVE))
+        if (props != null &&
+            (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+             props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+             props.containsKey(Sasl.POLICY_NOACTIVE)))
         {
             // returned array must be non null according to interface documentation
             return new String[0];

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java Thu Oct 20 18:42:46 2011
@@ -259,7 +259,7 @@ public class AMQStateManager implements 
 
     public AMQProtocolSession getProtocolSession()
     {
-        SecurityManager.setThreadPrincipal(_protocolSession.getPrincipal());
+        SecurityManager.setThreadSubject(_protocolSession.getAuthorizedSubject());
         return _protocolSession;
     }
 }

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java Thu Oct 20 18:42:46 2011
@@ -21,6 +21,7 @@
 package org.apache.qpid.server.store;
 
 import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.lang.ref.SoftReference;
@@ -479,9 +480,15 @@ public class DerbyMessageStore implement
                         FieldTable arguments;
                         if(dataAsBytes.length > 0)
                         {
-                            org.apache.mina.common.ByteBuffer buffer = org.apache.mina.common.ByteBuffer.wrap(dataAsBytes);
 
-                            arguments = new FieldTable(buffer,buffer.limit());
+                            try
+                            {
+                                arguments = new FieldTable(new DataInputStream(new ByteArrayInputStream(dataAsBytes)),dataAsBytes.length);
+                            }
+                            catch (IOException e)
+                            {
+                                throw new RuntimeException("IO Exception should not be thrown",e);
+                            }
                         }
                         else
                         {

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java Thu Oct 20 18:42:46 2011
@@ -20,13 +20,21 @@
  */
 package org.apache.qpid.server.subscription;
 
+import java.util.Map;
+
 import org.apache.qpid.AMQException;
 import org.apache.qpid.framing.AMQShortString;
 import org.apache.qpid.framing.FieldTable;
 import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.filter.FilterManager;
 import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.flow.FlowCreditManager_0_10;
 import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.transport.ServerSession;
 import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
+import org.apache.qpid.transport.MessageFlowMode;
 
 /**
  * Allows the customisation of the creation of a subscription. This is typically done within an AMQQueue. This factory
@@ -56,4 +64,23 @@ public interface SubscriptionFactory
                                             RecordDeliveryMethod recordMethod
     )
             throws AMQException;
+
+
+    SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(AMQChannel channel,
+                                                                          AMQProtocolSession session,
+                                                                          AMQShortString consumerTag,
+                                                                          FieldTable filters,
+                                                                          boolean noLocal,
+                                                                          FlowCreditManager creditManager,
+                                                                          ClientDeliveryMethod deliveryMethod,
+                                                                          RecordDeliveryMethod recordMethod) throws AMQException;
+
+    Subscription_0_10 createSubscription(final ServerSession session,
+                                         final String destination,
+                                         final MessageAcceptMode acceptMode,
+                                         final MessageAcquireMode acquireMode,
+                                         final MessageFlowMode flowMode,
+                                         final FlowCreditManager_0_10 creditManager,
+                                         final FilterManager filterManager,
+                                         final Map<String,Object> arguments);
 }

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java Thu Oct 20 18:42:46 2011
@@ -20,17 +20,28 @@
  */
 package org.apache.qpid.server.subscription;
 
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
 import org.apache.qpid.AMQException;
 import org.apache.qpid.common.AMQPFilterTypes;
 import org.apache.qpid.framing.AMQShortString;
 import org.apache.qpid.framing.FieldTable;
 import org.apache.qpid.protocol.AMQConstant;
 import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.filter.FilterManager;
 import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.flow.FlowCreditManager_0_10;
 import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.transport.ServerSession;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
+import org.apache.qpid.transport.MessageFlowMode;
 
 public class SubscriptionFactoryImpl implements SubscriptionFactory
 {
+    private static final AtomicLong SUB_ID_GENERATOR = new AtomicLong(0);
+
     public Subscription createSubscription(int channelId, AMQProtocolSession protocolSession,
                                            AMQShortString consumerTag, boolean acks, FieldTable filters,
                                            boolean noLocal, FlowCreditManager creditManager) throws AMQException
@@ -78,18 +89,47 @@ public class SubscriptionFactoryImpl imp
 
         if(isBrowser)
         {
-            return new SubscriptionImpl.BrowserSubscription(channel, protocolSession, consumerTag,  filters, noLocal, creditManager, clientMethod, recordMethod);
+            return new SubscriptionImpl.BrowserSubscription(channel, protocolSession, consumerTag,  filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId());
         }
         else if(acks)
         {
-            return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag,  filters, noLocal, creditManager, clientMethod, recordMethod);
+            return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag,  filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId());
         }
         else
         {
-            return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag,  filters, noLocal, creditManager, clientMethod, recordMethod);
+            return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag,  filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId());
         }
     }
 
+    public SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(final AMQChannel channel,
+                                                                                 final AMQProtocolSession session,
+                                                                                 final AMQShortString consumerTag,
+                                                                                 final FieldTable filters,
+                                                                                 final boolean noLocal,
+                                                                                 final FlowCreditManager creditManager,
+                                                                                 final ClientDeliveryMethod deliveryMethod,
+                                                                                 final RecordDeliveryMethod recordMethod) throws AMQException
+    {
+        return new SubscriptionImpl.GetNoAckSubscription(channel, session, null, null, false, creditManager, deliveryMethod, recordMethod, getNextSubscriptionId());
+    }
+
+    public Subscription_0_10 createSubscription(final ServerSession session,
+                                                final String destination,
+                                                final MessageAcceptMode acceptMode,
+                                                final MessageAcquireMode acquireMode,
+                                                final MessageFlowMode flowMode,
+                                                final FlowCreditManager_0_10 creditManager,
+                                                final FilterManager filterManager,
+                                                final Map<String,Object> arguments)
+    {
+        return new Subscription_0_10(session, destination, acceptMode, acquireMode,
+                                flowMode, creditManager, filterManager, arguments, getNextSubscriptionId());
+    }
 
     public static final SubscriptionFactoryImpl INSTANCE = new SubscriptionFactoryImpl();
+
+    private static long getNextSubscriptionId()
+    {
+        return SUB_ID_GENERATOR.getAndIncrement();
+    }
 }

Modified: qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
URL: http://svn.apache.org/viewvc/qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java?rev=1186990&r1=1186989&r2=1186990&view=diff
==============================================================================
--- qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java (original)
+++ qpid/branches/QPID-2519/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java Thu Oct 20 18:42:46 2011
@@ -88,9 +88,7 @@ public abstract class SubscriptionImpl i
 
     private final Lock _stateChangeLock;
 
-    private static final AtomicLong idGenerator = new AtomicLong(0);
-    // Create a simple ID that increments for ever new Subscription
-    private final long _subscriptionID = idGenerator.getAndIncrement();
+    private final long _subscriptionID;
     private LogSubject _logSubject;
     private LogActor _logActor;
     private UUID _id;
@@ -104,10 +102,11 @@ public abstract class SubscriptionImpl i
                                    AMQShortString consumerTag, FieldTable filters,
                                    boolean noLocal, FlowCreditManager creditManager,
                                    ClientDeliveryMethod deliveryMethod,
-                                   RecordDeliveryMethod recordMethod)
+                                   RecordDeliveryMethod recordMethod,
+                                   long subscriptionID)
             throws AMQException
         {
-            super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
+            super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
         }
 
 
@@ -151,10 +150,11 @@ public abstract class SubscriptionImpl i
                                  AMQShortString consumerTag, FieldTable filters,
                                  boolean noLocal, FlowCreditManager creditManager,
                                    ClientDeliveryMethod deliveryMethod,
-                                   RecordDeliveryMethod recordMethod)
+                                   RecordDeliveryMethod recordMethod,
+                                   long subscriptionID)
             throws AMQException
         {
-            super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
+            super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
         }
 
 
@@ -211,16 +211,45 @@ public abstract class SubscriptionImpl i
 
     }
 
+    /**
+     * NoAck Subscription for use with BasicGet method.
+     */
+    public static final class GetNoAckSubscription extends SubscriptionImpl.NoAckSubscription
+    {
+        public GetNoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
+                               AMQShortString consumerTag, FieldTable filters,
+                               boolean noLocal, FlowCreditManager creditManager,
+                                   ClientDeliveryMethod deliveryMethod,
+                                   RecordDeliveryMethod recordMethod,
+                                   long subscriptionID)
+            throws AMQException
+        {
+            super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
+        }
+
+        public boolean isTransient()
+        {
+            return true;
+        }
+
+        public boolean wouldSuspend(QueueEntry msg)
+        {
+            return !getCreditManager().useCreditForMessage(msg.getMessage());
+        }
+
+    }
+
     static final class AckSubscription extends SubscriptionImpl
     {
         public AckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
                                AMQShortString consumerTag, FieldTable filters,
                                boolean noLocal, FlowCreditManager creditManager,
                                    ClientDeliveryMethod deliveryMethod,
-                                   RecordDeliveryMethod recordMethod)
+                                   RecordDeliveryMethod recordMethod,
+                                   long subscriptionID)
             throws AMQException
         {
-            super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
+            super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
         }
 
 
@@ -296,10 +325,11 @@ public abstract class SubscriptionImpl i
                             AMQShortString consumerTag, FieldTable arguments,
                             boolean noLocal, FlowCreditManager creditManager,
                             ClientDeliveryMethod deliveryMethod,
-                            RecordDeliveryMethod recordMethod)
+                            RecordDeliveryMethod recordMethod,
+                            long subscriptionID)
             throws AMQException
     {
-
+        _subscriptionID = subscriptionID;
         _channel = channel;
         _consumerTag = consumerTag;
 
@@ -445,7 +475,7 @@ public abstract class SubscriptionImpl i
 
 
         //check that the message hasn't been rejected
-        if (entry.isRejectedBy(this))
+        if (entry.isRejectedBy(getSubscriptionID()))
         {
             if (_logger.isDebugEnabled())
             {



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscribe@qpid.apache.org