[jboss-cvs] Picketbox SVN: r226 - in trunk/security-jboss-sx/jbosssx/src: main/java/org/jboss/security/mapping/providers and 4 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Jun 15 11:31:14 EDT 2011


Author: mmoyses
Date: 2011-06-15 11:31:14 -0400 (Wed, 15 Jun 2011)
New Revision: 226

Added:
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapUsersLoginModule.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/PropertiesUsersLoginModule.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/SimpleUsersLoginModule.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/AbstractRolesMappingProvider.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/DatabaseRolesMappingProvider.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/LdapRolesMappingProvider.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/PropertiesRolesMappingProvider.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/SecurityActions.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/SimpleRolesMappingProvider.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/Util.java
Modified:
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/AbstractServerLoginModule.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/DatabaseServerLoginModule.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapExtLoginModule.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/SecurityActions.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/UsernamePasswordLoginModule.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/Util.java
   trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/plugins/TransactionManagerLocator.java
   trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/JBossSecuritySubjectFactoryUnitTestCase.java
   trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/jaas/LoginModulesUnitTestCase.java
Log:
Separate authentication from role mapping in the login modules

Modified: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/AbstractServerLoginModule.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/AbstractServerLoginModule.java	2011-05-26 18:23:11 UTC (rev 225)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/AbstractServerLoginModule.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -216,6 +216,15 @@
       Set<Principal> principals = subject.getPrincipals();
       Principal identity = getIdentity();
       principals.add(identity);
+      // add the CallerPrincipal group
+      Group callerGroup = getCallerPrincipalGroup(principals);
+      if (callerGroup == null)
+      {
+         callerGroup = new SimpleGroup(SecurityConstants.CALLER_PRINCIPAL_GROUP);
+         callerGroup.addMember(identity);
+         principals.add(callerGroup);
+      }
+      // add other role groups
       Group[] roleSets = getRoleSets();
       for(int g = 0; g < roleSets.length; g ++)
       {
@@ -263,6 +272,9 @@
       Principal identity = getIdentity();
       Set<Principal> principals = subject.getPrincipals();
       principals.remove(identity);
+      Group callerGroup = getCallerPrincipalGroup(principals);
+      if (callerGroup != null)
+         principals.remove(callerGroup);
       // Remove any added Groups...
       return true;
    }
@@ -350,4 +362,22 @@
       }
       return p;
    }
+   
+   protected Group getCallerPrincipalGroup(Set<Principal> principals)
+   {
+      Group callerGroup = null;
+      for (Principal principal : principals)
+      {
+         if (principal instanceof Group)
+         {
+            Group group = Group.class.cast(principal);
+            if (group.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP))
+            {
+               callerGroup = group;
+               break;
+            }
+         }
+      }
+      return callerGroup;
+   }
 }
\ No newline at end of file

Modified: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/DatabaseServerLoginModule.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/DatabaseServerLoginModule.java	2011-05-26 18:23:11 UTC (rev 225)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/DatabaseServerLoginModule.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -75,7 +75,7 @@
    /** The sql query to obtain the user password */
    protected String principalsQuery = "select Password from Principals where PrincipalID=?";
    /** The sql query to obtain the user roles */
-   protected String rolesQuery = "select Role, RoleGroup from Roles where PrincipalID=?";
+   protected String rolesQuery;
    /** Whether to suspend resume transactions during database operations */
    protected boolean suspendResume = true;
    
@@ -114,7 +114,8 @@
       {
          log.trace("DatabaseServerLoginModule, dsJndiName="+dsJndiName);
          log.trace("principalsQuery="+principalsQuery);
-         log.trace("rolesQuery="+rolesQuery);
+         if (rolesQuery != null)
+            log.trace("rolesQuery="+rolesQuery);
          log.trace("suspendResume="+suspendResume);
       }
       //Get the Transaction Manager JNDI Name
@@ -255,12 +256,16 @@
     */
    protected Group[] getRoleSets() throws LoginException
    {
-      String username = getUsername();
-      if (log.isTraceEnabled())
-         log.trace("getRoleSets using rolesQuery: "+rolesQuery+", username: "+username);
-      Group[] roleSets = Util.getRoleSets(username, dsJndiName, rolesQuery, this,
-         suspendResume);
-      return roleSets;
+      if (rolesQuery != null)
+      {
+         String username = getUsername();
+         if (log.isTraceEnabled())
+            log.trace("getRoleSets using rolesQuery: "+rolesQuery+", username: "+username);
+         Group[] roleSets = Util.getRoleSets(username, dsJndiName, rolesQuery, this,
+               suspendResume);
+         return roleSets;
+      }
+      return new Group[0];
    }
    
    /** A hook to allow subclasses to convert a password from the database

Modified: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapExtLoginModule.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapExtLoginModule.java	2011-05-26 18:23:11 UTC (rev 225)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapExtLoginModule.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -461,9 +461,7 @@
    {
       SearchControls constraints = new SearchControls();
       constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
-      constraints.setReturningAttributes(new String[0]);
       constraints.setTimeLimit(searchTimeLimit);
-
       String attrList[] = {distinguishedNameAttribute};
       constraints.setReturningAttributes(attrList);
 
@@ -657,6 +655,7 @@
          Properties tmp = new Properties();
          tmp.putAll(env);
          tmp.setProperty(Context.SECURITY_CREDENTIALS, "***");
+         tmp.setProperty(BIND_CREDENTIAL, "***");
          log.trace("Logging into LDAP server, env=" + tmp.toString());
       }
    }

Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapUsersLoginModule.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapUsersLoginModule.java	                        (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/LdapUsersLoginModule.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -0,0 +1,338 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.auth.spi;
+
+import java.security.acl.Group;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Map.Entry;
+
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.InitialLdapContext;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+
+import org.jboss.security.Util;
+
+/**
+ * A login module to authenticate users using a LDAP server.
+ * 
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @author Andy Oliver
+ * @author Scott.Stark at jboss.org
+ */
+public class LdapUsersLoginModule extends UsernamePasswordLoginModule
+{
+   private static final String BIND_DN = "bindDN";
+
+   private static final String BIND_CREDENTIAL = "bindCredential";
+
+   private static final String BASE_CTX_DN = "baseCtxDN";
+
+   private static final String BASE_FILTER_OPT = "baseFilter";
+
+   private static final String SEARCH_TIME_LIMIT_OPT = "searchTimeLimit";
+
+   private static final String SEARCH_SCOPE_OPT = "searchScope";
+
+   private static final String DISTINGUISHED_NAME_ATTRIBUTE_OPT = "distinguishedNameAttribute";
+
+   private static final String PARSE_USERNAME = "parseUsername";
+   
+   private static final String USERNAME_BEGIN_STRING = "usernameBeginString";
+   
+   private static final String USERNAME_END_STRING = "usernameEndString";
+   
+   private static final String ALLOW_EMPTY_PASSWORDS = "allowEmptyPasswords";
+
+   protected String bindDN;
+
+   protected String bindCredential;
+
+   protected String baseDN;
+
+   protected String baseFilter;
+
+   protected int searchTimeLimit = 10000;
+
+   protected int searchScope = SearchControls.SUBTREE_SCOPE; 
+   
+   protected String distinguishedNameAttribute;
+   
+   protected boolean parseUsername;
+   
+   protected String usernameBeginString;
+   
+   protected String usernameEndString;
+   
+   protected boolean allowEmptyPasswords;
+
+   @Override
+   protected String getUsersPassword() throws LoginException
+   {
+      return "";
+   }
+
+   @Override
+   protected Group[] getRoleSets() throws LoginException
+   {
+      return new Group[0];
+   }
+   
+   @Override
+   protected String getUsername()
+   {
+      String username = super.getUsername();
+      if (parseUsername)
+      {
+         int beginIndex = 0;
+         if (usernameBeginString != null && !usernameBeginString.equals(""))
+            beginIndex = username.indexOf(usernameBeginString) + usernameBeginString.length();
+         if (beginIndex == -1) // not allowed. reset
+            beginIndex = 0;
+         int endIndex = username.length();
+         if (usernameEndString != null && !usernameEndString.equals(""))
+            endIndex = username.substring(beginIndex).indexOf(usernameEndString);
+         if (endIndex == -1) // not allowed. reset
+            endIndex = username.length();
+         else
+            endIndex += beginIndex;
+         username = username.substring(beginIndex, endIndex);
+      }
+      return username;
+   }
+
+   @Override
+   public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+         Map<String, ?> options)
+   {
+      super.initialize(subject, callbackHandler, sharedState, options);
+      trace = log.isTraceEnabled();
+      bindDN = (String) options.get(BIND_DN);
+      bindCredential = (String) options.get(BIND_CREDENTIAL);
+      if ((bindCredential != null) && bindCredential.startsWith("{EXT}"))
+      {
+         try
+         {
+            bindCredential = new String(Util.loadPassword(bindCredential));
+         }
+         catch (Exception e)
+         {
+            throw new IllegalArgumentException("Unable to decode bindCredential", e);
+         }
+      }
+      baseDN = (String) options.get(BASE_CTX_DN);
+      baseFilter = (String) options.get(BASE_FILTER_OPT);
+      String timeLimit = (String) options.get(SEARCH_TIME_LIMIT_OPT);
+      if (timeLimit != null)
+      {
+         try
+         {
+            searchTimeLimit = Integer.parseInt(timeLimit);
+         }
+         catch (NumberFormatException e)
+         {
+            if (trace)
+               log.trace("Failed to parse: " + timeLimit + ", using searchTimeLimit=" + searchTimeLimit, e);
+         }
+      }
+      String scope = (String) options.get(SEARCH_SCOPE_OPT);
+      if ("OBJECT_SCOPE".equalsIgnoreCase(scope))
+         searchScope = SearchControls.OBJECT_SCOPE;
+      else if ("ONELEVEL_SCOPE".equalsIgnoreCase(scope))
+         searchScope = SearchControls.ONELEVEL_SCOPE;
+      if ("SUBTREE_SCOPE".equalsIgnoreCase(scope))
+         searchScope = SearchControls.SUBTREE_SCOPE;
+
+      distinguishedNameAttribute = (String) options.get(DISTINGUISHED_NAME_ATTRIBUTE_OPT);
+      if (distinguishedNameAttribute == null)
+          distinguishedNameAttribute = "distinguishedName";
+      allowEmptyPasswords = Boolean.valueOf((String) options.get(ALLOW_EMPTY_PASSWORDS));
+      
+      parseUsername = Boolean.valueOf((String) options.get(PARSE_USERNAME));
+      if (parseUsername)
+      {
+         usernameBeginString = (String) options.get(USERNAME_BEGIN_STRING);
+         usernameEndString = (String) options.get(USERNAME_END_STRING);
+      }
+   }
+
+   @Override
+   protected boolean validatePassword(String inputPassword, String expectedPassword)
+   {
+      boolean isValid = false;
+      if (inputPassword != null)
+      {
+         // See if this is an empty password that should be disallowed
+         if (inputPassword.length() == 0)
+         {
+            if (allowEmptyPasswords == false)
+            {
+               if(trace)
+                  log.trace("Rejecting empty password due to allowEmptyPasswords");
+               return false;
+            }
+         }
+
+         try
+         {
+            // Validate the password by trying to create an initial context
+            String username = getUsername();
+            isValid = createLdapInitContext(username, inputPassword);
+         }
+         catch (Throwable e)
+         {
+            super.setValidateError(e);
+         }
+      }
+      return isValid;
+   }
+   
+   /**
+    * Bind to the LDAP server for authentication
+    */
+   private boolean createLdapInitContext(String username, Object credential) throws Exception
+   {
+      // Get the admin context for searching
+      InitialLdapContext ctx = null;
+      ClassLoader currentTCCL = SecurityActions.getContextClassLoader();
+      try
+      {
+         if (currentTCCL != null)
+            SecurityActions.setContextClassLoader(null);
+         ctx = constructInitialLdapContext(bindDN, bindCredential);
+         // Validate the user by binding against the userDN
+         bindDNAuthentication(ctx, username, credential, baseDN, baseFilter);
+      }
+      finally
+      {
+         if (ctx != null)
+            ctx.close();
+         if (currentTCCL != null)
+            SecurityActions.setContextClassLoader(currentTCCL);
+      }
+      return true;
+   }
+   
+   private InitialLdapContext constructInitialLdapContext(String dn, Object credential) throws NamingException
+   {
+      Properties env = new Properties();
+      Iterator iter = options.entrySet().iterator();
+      while (iter.hasNext())
+      {
+         Entry entry = (Entry) iter.next();
+         env.put(entry.getKey(), entry.getValue());
+      }
+
+      // Set defaults for key values if they are missing
+      String factoryName = env.getProperty(Context.INITIAL_CONTEXT_FACTORY);
+      if (factoryName == null)
+      {
+         factoryName = "com.sun.jndi.ldap.LdapCtxFactory";
+         env.setProperty(Context.INITIAL_CONTEXT_FACTORY, factoryName);
+      }
+      String authType = env.getProperty(Context.SECURITY_AUTHENTICATION);
+      if (authType == null)
+         env.setProperty(Context.SECURITY_AUTHENTICATION, "simple");
+      String protocol = env.getProperty(Context.SECURITY_PROTOCOL);
+      String providerURL = (String) options.get(Context.PROVIDER_URL);
+      if (providerURL == null)
+         providerURL = "ldap://localhost:" + ((protocol != null && protocol.equals("ssl")) ? "636" : "389");
+
+      env.setProperty(Context.PROVIDER_URL, providerURL);
+      // JBAS-3555, allow anonymous login with no bindDN and bindCredential
+      if (dn != null)
+         env.setProperty(Context.SECURITY_PRINCIPAL, dn);
+      if (credential != null)
+         env.put(Context.SECURITY_CREDENTIALS, credential);
+      traceLdapEnv(env);
+      return new InitialLdapContext(env, null);
+   }
+   
+   private void traceLdapEnv(Properties env)
+   {
+      if (trace)
+      {
+         Properties tmp = new Properties();
+         tmp.putAll(env);
+         tmp.setProperty(Context.SECURITY_CREDENTIALS, "***");
+         tmp.setProperty(BIND_CREDENTIAL, "***");
+         log.trace("Logging into LDAP server, env=" + tmp.toString());
+      }
+   }
+   
+   protected String bindDNAuthentication(InitialLdapContext ctx, String user, Object credential, String baseDN,
+         String filter) throws NamingException
+   {
+      SearchControls constraints = new SearchControls();
+      constraints.setSearchScope(searchScope);
+      constraints.setTimeLimit(searchTimeLimit);
+      String attrList[] = {distinguishedNameAttribute};
+      constraints.setReturningAttributes(attrList);
+
+      NamingEnumeration<SearchResult> results = null;
+
+      Object[] filterArgs = {user};
+      results = ctx.search(baseDN, filter, filterArgs, constraints);
+      if (!results.hasMore())
+      {
+         results.close();
+         throw new NamingException("Search of baseDN(" + baseDN + ") found no matches");
+      }
+
+      SearchResult sr = results.next();
+      String name = sr.getName();
+      String userDN = null;
+      Attributes attrs = sr.getAttributes();
+      if (attrs != null)
+      {
+         Attribute dn = attrs.get(distinguishedNameAttribute);
+         if (dn != null)
+         {
+            userDN = (String) dn.get();
+         }
+      }
+      if (userDN == null)
+      {
+         if (sr.isRelative())
+            userDN = name + ("".equals(baseDN) ? "" : "," + baseDN);
+         else
+            throw new NamingException("Can't follow referal for authentication: " + name);
+      }
+
+      results.close();
+      results = null;
+      // Bind as the user dn to authenticate the user
+      InitialLdapContext userCtx = constructInitialLdapContext(userDN, credential);
+      userCtx.close();
+
+      return userDN;
+   }
+}

Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/PropertiesUsersLoginModule.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/PropertiesUsersLoginModule.java	                        (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/PropertiesUsersLoginModule.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -0,0 +1,52 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.auth.spi;
+
+import java.io.IOException;
+import java.security.acl.Group;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.security.auth.login.LoginException;
+
+/**
+ * A {@code LoginModule} that uses a properties file to store username and password for authentication.
+ * No roles are mapped.
+ * 
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ */
+public class PropertiesUsersLoginModule extends UsersRolesLoginModule
+{
+
+   @Override
+   protected Group[] getRoleSets() throws LoginException
+   {
+      return new Group[0];
+   }
+
+   @Override
+   protected Properties createRoles(Map<String, ?> options) throws IOException
+   {
+      return new Properties();
+   }
+
+}

Modified: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/SecurityActions.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/SecurityActions.java	2011-05-26 18:23:11 UTC (rev 225)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/SecurityActions.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -83,21 +83,34 @@
          }
        });
    }
-   
-   static Class<?> loadClass(final String name) throws PrivilegedActionException 
+
+   static Class<?> loadClass(final String name) throws PrivilegedActionException
    {
       return AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>()
       {
-         public Class<?> run() throws PrivilegedActionException
+         public Class<?> run() throws ClassNotFoundException
          {
-            try
+            ClassLoader[] cls = new ClassLoader[] {
+                  getContextClassLoader(), // User defined classes
+                  SecurityActions.class.getClassLoader(), // PB classes (not always on TCCL [modular env])
+                  ClassLoader.getSystemClassLoader() }; // System loader, usually has app class path
+
+            ClassNotFoundException e = null;
+            for (ClassLoader cl : cls)
             {
-               return getContextClassLoader().loadClass(name);
+               if (cl == null)
+                  continue;
+               
+               try
+               {
+                  return cl.loadClass(name);
+               }
+               catch (ClassNotFoundException ce)
+               {
+                  e = ce;
+               }
             }
-            catch ( Exception e)
-            {
-               throw new PrivilegedActionException(e);
-            } 
+            throw e != null ? e : new ClassNotFoundException(name);
          }
       });
    }

Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/SimpleUsersLoginModule.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/SimpleUsersLoginModule.java	                        (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/SimpleUsersLoginModule.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -0,0 +1,87 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.auth.spi;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.jboss.security.SecurityConstants;
+
+/**
+ * A {@code LoginModule} that stores username and password as options.
+ * 
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ */
+public class SimpleUsersLoginModule extends PropertiesUsersLoginModule
+{
+
+   protected static Set<String> invalidProperties = new HashSet<String>();
+   
+   // adding valid properties' keys from super classes
+   {
+      invalidProperties.add("usersProperties");
+      invalidProperties.add("defaultUsersProperties");
+      invalidProperties.add("rolesProperties");
+      invalidProperties.add("defaultRolesProperties");
+      invalidProperties.add("roleGroupSeperator");
+      invalidProperties.add("digestCallback");
+      invalidProperties.add("storeDigestCallback");
+      invalidProperties.add("legacyCreatePasswordHash");
+      invalidProperties.add("inputValidator");
+      invalidProperties.add("hashAlgorithm");
+      invalidProperties.add("hashEncoding");
+      invalidProperties.add("hashCharset");
+      invalidProperties.add("hashStorePassword");
+      invalidProperties.add("hashUserPassword");
+      invalidProperties.add("ignorePasswordCase");
+      invalidProperties.add("throwValidateError");
+      invalidProperties.add(SecurityConstants.SECURITY_DOMAIN_OPTION);
+      invalidProperties.add("password-stacking");
+      invalidProperties.add("principalClass");
+      invalidProperties.add("unauthenticatedIdentity");
+   }
+   
+   @Override
+   protected Properties createUsers(Map<String, ?> options) throws IOException
+   {
+      Properties properties = new Properties();
+      for (Entry<String, ?> entry : options.entrySet())
+      {
+         String key = entry.getKey();
+         Object value = entry.getValue();
+         if (value != null && isValidEntry(key))
+            properties.put(key, value);
+      }
+      
+      return properties;
+   }
+   
+   protected boolean isValidEntry(String key)
+   {
+      return !invalidProperties.contains(key);
+   }
+
+}

Modified: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/UsernamePasswordLoginModule.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/UsernamePasswordLoginModule.java	2011-05-26 18:23:11 UTC (rev 225)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/UsernamePasswordLoginModule.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -412,8 +412,7 @@
       {
          try
          {
-            ClassLoader loader = SecurityActions.getContextClassLoader();
-            Class<?> callbackClass = loader.loadClass(callbackClassName);
+            Class<?> callbackClass = SecurityActions.loadClass(callbackClassName);
             callback = (DigestCallback) callbackClass.newInstance();
             if( log.isTraceEnabled() )
                log.trace("Created DigestCallback: "+callback);

Modified: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/Util.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/Util.java	2011-05-26 18:23:11 UTC (rev 225)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/auth/spi/Util.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -268,7 +268,7 @@
          }
          else
          {
-            throw new IOException("Properties file " + propertiesName + " not avilable");
+            throw new IOException("Properties file " + propertiesName + " not available");
          }
          if (trace)
             log.trace("Loaded properties, users="+bundle.keySet());
@@ -290,33 +290,52 @@
     * @exception java.io.IOException thrown if the properties file cannot be found
     *    or loaded 
     */
-   static Properties loadProperties(String propertiesName, Logger log)
-      throws IOException
-   { 
+   static Properties loadProperties(String propertiesName, Logger log) throws IOException
+   {
       boolean trace = log.isTraceEnabled();
-      
-      ClassLoader loader = SecurityActions.getContextClassLoader(); 
+
+      Properties bundle = null;
+      ClassLoader loader = SecurityActions.getContextClassLoader();
       URL url = null;
       // First check for local visibility via a URLClassLoader.findResource
-      if( loader instanceof URLClassLoader )
+      if (loader instanceof URLClassLoader)
       {
-         URLClassLoader ucl = (URLClassLoader) loader; 
-         url = SecurityActions.findResource(ucl,propertiesName);
-         if(trace)
-            log.trace("findResource: "+url);
-      } 
-      if( url == null )
+         URLClassLoader ucl = (URLClassLoader) loader;
+         url = SecurityActions.findResource(ucl, propertiesName);
+         if (trace)
+            log.trace("findResource: " + url);
+      }
+      // Do a general resource search
+      if (url == null)
+      {
          url = loader.getResource(propertiesName);
-      if( url == null)
+         if (url == null)
+         {
+            try
+            {
+               url = new URL(propertiesName);
+            }
+            catch (MalformedURLException mue)
+            {
+               if (trace)
+                  log.trace("Failed to open properties as URL", mue);
+               File tmp = new File(propertiesName);
+               if (tmp.exists())
+                  url = tmp.toURI().toURL();
+            }
+         }
+      }
+      if (url == null)
       {
-         url = new URL(propertiesName); 
+         String msg = "No properties file: " + propertiesName + " found";
+         throw new IOException(msg);
       }
 
-      if(trace)
-         log.trace("Properties file=" + url ); 
-
-      Properties bundle = new Properties();
-      if( url != null )
+      if (trace)
+         log.trace("Properties file=" + url);
+      Properties defaults = new Properties();
+      bundle = new Properties(defaults);
+      if (url != null)
       {
          InputStream is = null;
          try
@@ -325,8 +344,8 @@
          }
          catch (PrivilegedActionException e)
          {
-            if(trace)
-               log.trace("open stream error:", e);
+            if (trace)
+               log.trace("Open stream error", e);
             throw new IOException(e.getLocalizedMessage());
          }
          if (is != null)
@@ -338,7 +357,8 @@
          {
             throw new IOException("Properties file " + propertiesName + " not available");
          }
-         log.debug("Loaded properties, users="+bundle.keySet());
+         if (trace)
+            log.trace("Loaded properties, users=" + bundle.keySet());
       }
 
       return bundle;

Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/AbstractRolesMappingProvider.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/AbstractRolesMappingProvider.java	                        (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/AbstractRolesMappingProvider.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -0,0 +1,88 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.mapping.providers.role;
+
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.SecurityConstants;
+import org.jboss.security.identity.RoleGroup;
+import org.jboss.security.mapping.MappingProvider;
+import org.jboss.security.mapping.MappingResult;
+
+/**
+ * Abstract class for Role mapping providers
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ */
+public abstract class AbstractRolesMappingProvider implements MappingProvider<RoleGroup>
+{
+   protected Logger log;
+
+   protected MappingResult<RoleGroup> result;
+   
+   @Override
+   public boolean supports(Class<?> p)
+   {
+      if (RoleGroup.class.isAssignableFrom(p))
+         return true;
+
+      return false;
+   }
+   
+   @Override
+   public void setMappingResult(MappingResult<RoleGroup> result)
+   {
+      this.result = result;
+   }
+   
+   protected Principal getCallerPrincipal(Map<String, Object> map)
+   {
+      Principal principal = (Principal) map.get(SecurityConstants.PRINCIPAL_IDENTIFIER);
+      Principal callerPrincipal = null;
+      if (principal == null)
+      {
+         @SuppressWarnings("unchecked")
+         Set<Principal> principals = (Set<Principal>) map.get(SecurityConstants.PRINCIPALS_SET_IDENTIFIER);
+         if (principals != null && !principals.isEmpty())
+         {
+            for (Principal p : principals) {
+               if (!(p instanceof Group) && principal == null) {
+                  principal = p;
+               }
+               if (p instanceof Group) {
+                  Group g = Group.class.cast(p);
+                  if (g.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP) && callerPrincipal == null) {
+                     Enumeration<? extends Principal> e = g.members();
+                     if (e.hasMoreElements())
+                        callerPrincipal = e.nextElement();
+                  }
+               }
+            }
+         }
+      }
+      return callerPrincipal == null ? principal : callerPrincipal;
+   }
+}
\ No newline at end of file

Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/DatabaseRolesMappingProvider.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/DatabaseRolesMappingProvider.java	                        (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/DatabaseRolesMappingProvider.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -0,0 +1,112 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.mapping.providers.role;
+
+import java.security.Principal;
+import java.util.Map;
+
+import javax.naming.NamingException;
+import javax.transaction.TransactionManager;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.identity.RoleGroup;
+import org.jboss.security.plugins.TransactionManagerLocator;
+
+/**
+ * A {@code MappingProvider} that reads roles from a database.
+ * 
+ * rolesQuery option should be a prepared statement equivalent to
+ * "select RoleName from Roles where User=?"
+ * 
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ */
+public class DatabaseRolesMappingProvider extends AbstractRolesMappingProvider
+{
+
+   protected String dsJndiName;
+   
+   protected String rolesQuery;
+
+   protected boolean suspendResume = true;
+
+   protected String TX_MGR_JNDI_NAME = "java:/TransactionManager";
+
+   protected TransactionManager tm = null;
+
+   @Override
+   public void init(Map<String, Object> options)
+   {
+      log = Logger.getLogger(getClass());
+
+      if (options != null)
+      {
+         dsJndiName = (String) options.get("dsJndiName");
+         if (dsJndiName == null)
+            throw new IllegalArgumentException("Datasource JNDI name can't be null");
+         rolesQuery = (String) options.get("rolesQuery");
+         if (rolesQuery == null)
+            throw new IllegalArgumentException("Prepared statement can't be null");
+         String option = (String) options.get("suspendResume");
+         if (option != null)
+            suspendResume = Boolean.valueOf(option.toString()).booleanValue();
+
+         // Get the Transaction Manager JNDI Name
+         option = (String) options.get("transactionManagerJndiName");
+         if (option != null)
+            TX_MGR_JNDI_NAME = option;
+         try
+         {
+            if (suspendResume)
+               tm = getTransactionManager();
+         }
+         catch (NamingException e)
+         {
+            throw new RuntimeException("Unable to get Transaction Manager", e);
+         }
+      }
+   }
+
+   @Override
+   public void performMapping(Map<String, Object> map, RoleGroup mappedObject)
+   {
+      if (map == null || map.isEmpty())
+         throw new IllegalArgumentException("Context Map is null or empty");
+      
+      //Obtain the principal to roles mapping
+      Principal principal = getCallerPrincipal(map);
+
+      if (principal != null && rolesQuery != null)
+      {
+         String username = principal.getName();
+         Util.addRolesToGroup(username, mappedObject, dsJndiName, rolesQuery, log, suspendResume, tm);
+         result.setMappedObject(mappedObject);
+      }
+
+   }
+
+   protected TransactionManager getTransactionManager() throws NamingException
+   {
+      TransactionManagerLocator tml = new TransactionManagerLocator();
+      return tml.getTM(this.TX_MGR_JNDI_NAME);
+   }
+
+}

Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/LdapRolesMappingProvider.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/LdapRolesMappingProvider.java	                        (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/LdapRolesMappingProvider.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -0,0 +1,396 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.mapping.providers.role;
+
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.Map.Entry;
+
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.InitialLdapContext;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.Util;
+import org.jboss.security.identity.RoleGroup;
+import org.jboss.security.identity.plugins.SimpleRole;
+
+/**
+ * A mapping provider that assigns roles to an user using a LDAP server to search for the roles. 
+ * 
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @author Andy Oliver
+ * @author Scott.Stark at jboss.org
+ */
+public class LdapRolesMappingProvider extends AbstractRolesMappingProvider
+{
+   private static final String BIND_DN = "bindDN";
+
+   private static final String BIND_CREDENTIAL = "bindCredential";
+   
+   private static final String ROLES_CTX_DN_OPT = "rolesCtxDN";
+
+   private static final String ROLE_ATTRIBUTE_ID_OPT = "roleAttributeID";
+
+   private static final String ROLE_ATTRIBUTE_IS_DN_OPT = "roleAttributeIsDN";
+
+   private static final String ROLE_NAME_ATTRIBUTE_ID_OPT = "roleNameAttributeID";
+   
+   private static final String PARSE_ROLE_NAME_FROM_DN_OPT = "parseRoleNameFromDN";
+   
+   private static final String ROLE_FILTER_OPT = "roleFilter";
+
+   private static final String ROLE_RECURSION = "roleRecursion";
+   
+   private static final String SEARCH_TIME_LIMIT_OPT = "searchTimeLimit";
+
+   private static final String SEARCH_SCOPE_OPT = "searchScope";
+   
+   protected String bindDN;
+
+   protected String bindCredential;
+   
+   protected String rolesCtxDN;
+
+   protected String roleFilter;
+
+   protected String roleAttributeID;
+
+   protected String roleNameAttributeID;
+
+   protected boolean roleAttributeIsDN;
+   
+   protected boolean parseRoleNameFromDN;
+
+   protected int recursion = 0;
+
+   protected int searchTimeLimit = 10000;
+
+   protected int searchScope = SearchControls.SUBTREE_SCOPE;
+   
+   protected Map<String, Object> options;
+   
+   protected boolean trace;
+   
+   @Override
+   public void init(Map<String, Object> options)
+   {
+      log = Logger.getLogger(getClass());
+      trace = log.isTraceEnabled();
+      
+      if (options != null)
+      {
+         this.options = options;
+         bindDN = (String) options.get(BIND_DN);
+         bindCredential = (String) options.get(BIND_CREDENTIAL);
+         if ((bindCredential != null) && bindCredential.startsWith("{EXT}"))
+         {
+            try
+            {
+               bindCredential = new String(Util.loadPassword(bindCredential));
+            }
+            catch (Exception e)
+            {
+               throw new IllegalArgumentException("Unable to decode bindCredential", e);
+            }
+         }
+         roleFilter = (String) options.get(ROLE_FILTER_OPT);
+         roleAttributeID = (String) options.get(ROLE_ATTRIBUTE_ID_OPT);
+         if (roleAttributeID == null)
+            roleAttributeID = "role";
+         // Is user's role attribute a DN or the role name
+         String roleAttributeIsDNOption = (String) options.get(ROLE_ATTRIBUTE_IS_DN_OPT);
+         roleAttributeIsDN = Boolean.valueOf(roleAttributeIsDNOption).booleanValue();
+         roleNameAttributeID = (String) options.get(ROLE_NAME_ATTRIBUTE_ID_OPT);
+         if (roleNameAttributeID == null)
+            roleNameAttributeID = "name";
+      
+         //JBAS-4619:Parse Role Name from DN
+         String parseRoleNameFromDNOption = (String) options.get(PARSE_ROLE_NAME_FROM_DN_OPT);
+         parseRoleNameFromDN = Boolean.valueOf(parseRoleNameFromDNOption).booleanValue();
+      
+         rolesCtxDN = (String) options.get(ROLES_CTX_DN_OPT);
+         String strRecursion = (String) options.get(ROLE_RECURSION);
+         try
+         {
+            recursion = Integer.parseInt(strRecursion);
+         }
+         catch (Exception e)
+         {
+            if (trace)
+               log.trace("Failed to parse: " + strRecursion + ", disabling recursion", e);
+            // its okay for this to be 0 as this just disables recursion
+            recursion = 0;
+         }
+         String timeLimit = (String) options.get(SEARCH_TIME_LIMIT_OPT);
+         if (timeLimit != null)
+         {
+            try
+            {
+               searchTimeLimit = Integer.parseInt(timeLimit);
+            }
+            catch (NumberFormatException e)
+            {
+               if (trace)
+                  log.trace("Failed to parse: " + timeLimit + ", using searchTimeLimit=" + searchTimeLimit, e);
+            }
+         }
+         String scope = (String) options.get(SEARCH_SCOPE_OPT);
+         if ("OBJECT_SCOPE".equalsIgnoreCase(scope))
+            searchScope = SearchControls.OBJECT_SCOPE;
+         else if ("ONELEVEL_SCOPE".equalsIgnoreCase(scope))
+            searchScope = SearchControls.ONELEVEL_SCOPE;
+         if ("SUBTREE_SCOPE".equalsIgnoreCase(scope))
+            searchScope = SearchControls.SUBTREE_SCOPE;
+      }
+   }
+
+   @Override
+   public void performMapping(Map<String, Object> map, RoleGroup mappedObject)
+   {
+      if (map == null || map.isEmpty())
+         throw new IllegalArgumentException("Context Map is null or empty");
+
+      //Obtain the principal to roles mapping
+      Principal principal = getCallerPrincipal(map);
+
+      if (principal != null)
+      {
+         // Get the admin context for searching
+         InitialLdapContext ctx = null;
+         ClassLoader currentTCCL = SecurityActions.getContextClassLoader();
+         try
+         {
+            if (currentTCCL != null)
+               SecurityActions.setContextClassLoader(null);
+            ctx = constructInitialLdapContext(bindDN, bindCredential);
+            
+            // Query for roles matching the role filter
+            SearchControls constraints = new SearchControls();
+            constraints.setSearchScope(searchScope);
+            constraints.setReturningAttributes(new String[0]);
+            constraints.setTimeLimit(searchTimeLimit);
+            rolesSearch(ctx, constraints, principal.getName(), recursion, 0, mappedObject);
+         }
+         catch (NamingException ne)
+         {
+            log.error("Error connecting to LDAP server", ne);
+         }
+         finally
+         {
+            if (ctx != null)
+            {
+               try
+               {
+                  ctx.close();
+               }
+               catch (NamingException ne)
+               {
+                  log.error("Error closing context", ne);
+               }
+            }
+            if (currentTCCL != null)
+               SecurityActions.setContextClassLoader(currentTCCL);
+         }
+      }
+   }
+   
+   protected InitialLdapContext constructInitialLdapContext(String dn, Object credential) throws NamingException
+   {
+      Properties env = new Properties();
+      Iterator<Entry<String, Object>> iter = options.entrySet().iterator();
+      while (iter.hasNext())
+      {
+         Entry<String, Object> entry = iter.next();
+         env.put(entry.getKey(), entry.getValue());
+      }
+
+      // Set defaults for key values if they are missing
+      String factoryName = env.getProperty(Context.INITIAL_CONTEXT_FACTORY);
+      if (factoryName == null)
+      {
+         factoryName = "com.sun.jndi.ldap.LdapCtxFactory";
+         env.setProperty(Context.INITIAL_CONTEXT_FACTORY, factoryName);
+      }
+      String authType = env.getProperty(Context.SECURITY_AUTHENTICATION);
+      if (authType == null)
+         env.setProperty(Context.SECURITY_AUTHENTICATION, "simple");
+      String protocol = env.getProperty(Context.SECURITY_PROTOCOL);
+      String providerURL = (String) options.get(Context.PROVIDER_URL);
+      if (providerURL == null)
+         providerURL = "ldap://localhost:" + ((protocol != null && protocol.equals("ssl")) ? "636" : "389");
+
+      env.setProperty(Context.PROVIDER_URL, providerURL);
+      // JBAS-3555, allow anonymous login with no bindDN and bindCredential
+      if (dn != null)
+         env.setProperty(Context.SECURITY_PRINCIPAL, dn);
+      if (credential != null)
+         env.put(Context.SECURITY_CREDENTIALS, credential);
+      traceLdapEnv(env);
+      return new InitialLdapContext(env, null);
+   }
+   
+   private void traceLdapEnv(Properties env)
+   {
+      if (trace)
+      {
+         Properties tmp = new Properties();
+         tmp.putAll(env);
+         tmp.setProperty(Context.SECURITY_CREDENTIALS, "***");
+         tmp.setProperty(BIND_CREDENTIAL, "***");
+         log.trace("Logging into LDAP server, env=" + tmp.toString());
+      }
+   }
+
+   protected void rolesSearch(InitialLdapContext ctx, SearchControls constraints, String user, int recursionMax,
+         int nesting, RoleGroup roleGroup) throws NamingException
+   {
+      Object[] filterArgs = {user};
+      NamingEnumeration<SearchResult> results = ctx.search(rolesCtxDN, roleFilter, filterArgs, constraints);
+      try
+      {
+         while (results.hasMore())
+         {
+            SearchResult sr = results.next();
+            String dn = canonicalize(sr.getName());
+
+            // Query the context for the roleDN values
+            String[] attrNames = {roleAttributeID};
+            Attributes result = ctx.getAttributes(dn, attrNames);
+            if (result != null && result.size() > 0)
+            {
+               Attribute roles = result.get(roleAttributeID);
+               for (int n = 0; n < roles.size(); n++)
+               {
+                  String roleName = (String) roles.get(n);
+                  if (roleAttributeIsDN && parseRoleNameFromDN)
+                  {
+                     parseRole(roleName, roleGroup);
+                  }
+                  else if (roleAttributeIsDN)
+                  {
+                     // Query the roleDN location for the value of roleNameAttributeID
+                     String roleDN = roleName;
+                     String[] returnAttribute = {roleNameAttributeID};
+                     if (trace)
+                        log.trace("Using roleDN: " + roleDN);
+                     try
+                     {
+                        Attributes result2 = ctx.getAttributes(roleDN, returnAttribute);
+                        Attribute roles2 = result2.get(roleNameAttributeID);
+                        if (roles2 != null)
+                        {
+                           for (int m = 0; m < roles2.size(); m++)
+                           {
+                              roleName = (String) roles2.get(m);
+                              addRole(roleName, roleGroup);
+                           }
+                        }
+                     }
+                     catch (NamingException e)
+                     {
+                        if (trace)
+                           log.trace("Failed to query roleNameAttrName", e);
+                     }
+                  }
+                  else
+                  {
+                     // The role attribute value is the role name
+                     addRole(roleName, roleGroup);
+                  }
+               }
+            }
+
+            if (nesting < recursionMax)
+            {
+               rolesSearch(ctx, constraints, user, recursionMax, nesting + 1, roleGroup);
+            }
+         }
+      }
+      finally
+      {
+         if (results != null)
+            results.close();
+      }
+   }
+   
+   //JBAS-3438 : Handle "/" correctly
+   private String canonicalize(String searchResult)
+   {
+      String result = searchResult;
+      int len = searchResult.length();
+
+      String appendRolesCtxDN = "" + ("".equals(rolesCtxDN) ? "" : "," + rolesCtxDN);
+      if (searchResult.endsWith("\""))
+      {
+         result = searchResult.substring(0, len - 1) + appendRolesCtxDN + "\"";
+      }
+      else
+      {
+         result = searchResult + appendRolesCtxDN;
+      }
+      return result;
+   }
+
+   private void addRole(String roleName, RoleGroup roleGroup)
+   {
+      if (roleName != null)
+      {
+         try
+         {
+            SimpleRole role = new SimpleRole(roleName);
+            if (trace)
+               log.trace("Assign user to role " + roleName);
+            roleGroup.addRole(role);
+         }
+         catch (Exception e)
+         {
+            if (trace)
+               log.debug("Failed to create principal: " + roleName, e);
+         }
+      }
+   }
+
+   private void parseRole(String dn, RoleGroup roleGroup)
+   {
+      StringTokenizer st = new StringTokenizer(dn, ",");
+      while (st != null && st.hasMoreTokens())
+      {
+         String keyVal = st.nextToken();
+         if (keyVal.indexOf(roleNameAttributeID) > -1)
+         {
+            StringTokenizer kst = new StringTokenizer(keyVal, "=");
+            kst.nextToken();
+            addRole(kst.nextToken(), roleGroup);
+         }
+      }
+   }
+
+}

Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/PropertiesRolesMappingProvider.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/PropertiesRolesMappingProvider.java	                        (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/PropertiesRolesMappingProvider.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -0,0 +1,96 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.mapping.providers.role;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+import java.util.Properties;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.identity.RoleGroup;
+import org.jboss.util.StringPropertyReplacer;
+
+/**
+ * A {@code MappingProvider} that reads roles from a properties file in the format
+ * 
+ * <p>
+ * username=role1,role2,...
+ * </p>
+ * 
+ * and adds those roles to the security context for authorization purposes.
+ * 
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ */
+public class PropertiesRolesMappingProvider extends AbstractRolesMappingProvider
+{
+
+   protected String rolesRsrcName = "roles.properties";
+
+   protected Properties roles;
+
+   @Override
+   public void init(Map<String, Object> options)
+   {
+      log = Logger.getLogger(getClass());
+
+      if (options != null)
+      {
+         String option = (String) options.get("rolesProperties");
+         if (option != null)
+            rolesRsrcName = StringPropertyReplacer.replaceProperties(option);
+
+         // read properties file
+         try
+         {
+            roles = loadRoles();
+         }
+         catch (IOException ioe)
+         {
+            throw new IllegalStateException("Error loading roles properties file", ioe);
+         }
+      }
+   }
+
+   @Override
+   public void performMapping(Map<String, Object> map, RoleGroup mappedObject)
+   {
+      if (map == null || map.isEmpty())
+         throw new IllegalArgumentException("Context Map is null or empty");
+
+      //Obtain the principal to roles mapping
+      Principal principal = getCallerPrincipal(map);
+
+      if (principal != null)
+      {
+         String username = principal.getName();
+         Util.addRolesToGroup(username, mappedObject, roles, log);
+         result.setMappedObject(mappedObject);
+      }
+   }
+
+   protected Properties loadRoles() throws IOException
+   {
+      return Util.loadProperties(rolesRsrcName, log);
+   }
+
+}

Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/SecurityActions.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/SecurityActions.java	                        (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/SecurityActions.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -0,0 +1,103 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2007, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.security.mapping.providers.role;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ *  Privileged Blocks
+ *  @author Anil.Saldhana at redhat.com
+ *  @since  Sep 26, 2007 
+ *  @version $Revision$
+ */
+class SecurityActions
+{
+   static ClassLoader getContextClassLoader()
+   {
+      return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>()
+      {
+         public ClassLoader run()
+         {
+            return Thread.currentThread().getContextClassLoader();
+         }
+      });
+   }
+   
+   static Void setContextClassLoader(final ClassLoader cl)
+   {
+      return AccessController.doPrivileged(new PrivilegedAction<Void>()
+      {
+         public Void run()
+         {
+            Thread.currentThread().setContextClassLoader(cl);
+            return null;
+         }
+      });
+   }
+
+   static URL findResource(final URLClassLoader cl, final String name)
+   {
+      return AccessController.doPrivileged(new PrivilegedAction<URL>()
+      {
+         public URL run()
+         {
+            return cl.findResource(name);
+         }
+      });
+   }
+
+   static InputStream openStream(final URL url) throws PrivilegedActionException
+   {
+      return AccessController.doPrivileged(new PrivilegedExceptionAction<InputStream>()
+      {
+         public InputStream run() throws IOException
+         {
+            return url.openStream();
+         }
+      });
+   }
+
+   static Class<?> loadClass(final String name) throws PrivilegedActionException
+   {
+      return AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>()
+      {
+         public Class<?> run() throws PrivilegedActionException
+         {
+            try
+            {
+               return getContextClassLoader().loadClass(name);
+            }
+            catch (Exception e)
+            {
+               throw new PrivilegedActionException(e);
+            }
+         }
+      });
+   }
+}
\ No newline at end of file

Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/SimpleRolesMappingProvider.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/SimpleRolesMappingProvider.java	                        (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/SimpleRolesMappingProvider.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -0,0 +1,90 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.mapping.providers.role;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+
+import org.jboss.logging.Logger;
+
+/**
+ * A simple {@code MappingProvider} that reads roles from the options map.
+ * The option key is the username to assign roles to and the option value is
+ * the comma separated role names to assign to the user.
+ * 
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ */
+public class SimpleRolesMappingProvider extends PropertiesRolesMappingProvider
+{
+   protected Map<String, Object> options;
+   
+   @Override
+   public void init(Map<String, Object> options)
+   {
+      log = Logger.getLogger(getClass());
+      
+      this.options = options;
+
+      if (options != null)
+      {
+         try
+         {
+            roles = loadRoles();
+         }
+         catch (IOException ioe)
+         {
+            throw new IllegalStateException("Error loading roles from options", ioe);
+         }
+      }
+   }
+   
+   /**
+    * Load roles from options map
+    */
+   @Override
+   protected Properties loadRoles() throws IOException
+   {
+      roles = new Properties();
+      for (Map.Entry<String, Object> entry : options.entrySet())
+      {
+         String key = entry.getKey();
+         if (isValidEntry(key))
+            roles.put(key, entry.getValue());
+      }
+      
+      return roles;
+   }
+
+   /**
+    * Removes entries that are valid options for super classes
+    * 
+    * @param key entry key
+    * @return true if entry is valid, false otherwise
+    */
+   protected boolean isValidEntry(String key)
+   {
+      if (key.equals("rolesProperties"))
+         return false;
+      return true;
+   }
+}

Added: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/Util.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/Util.java	                        (rev 0)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/mapping/providers/role/Util.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -0,0 +1,300 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.security.mapping.providers.role;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.PrivilegedActionException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.jboss.logging.Logger;
+import org.jboss.security.identity.RoleGroup;
+import org.jboss.security.identity.plugins.SimpleRole;
+
+/**
+ * Utility class for this package.
+ * 
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ */
+public class Util
+{
+
+   /** 
+    * Utility method which loads the given properties file and returns a
+    * Properties object containing the key,value pairs in that file.
+    * The properties files should be in the class path as this method looks
+    * to the thread context class loader (TCL) to locate the resource. If the
+    * TCL is a URLClassLoader the findResource(String) method is first tried.
+    * If this fails or the TCL is not a URLClassLoader getResource(String) is
+    * tried.
+    * @param propertiesName - the name of the properties file resource
+    * @param log - the logger used for trace level messages
+    * @return the loaded properties file if found
+    * @exception java.io.IOException thrown if the properties file cannot be found
+    *    or loaded 
+    */
+   static Properties loadProperties(String propertiesName, Logger log) throws IOException
+   {
+      boolean trace = log.isTraceEnabled();
+
+      Properties bundle = null;
+      ClassLoader loader = SecurityActions.getContextClassLoader();
+      URL url = null;
+      // First check for local visibility via a URLClassLoader.findResource
+      if (loader instanceof URLClassLoader)
+      {
+         URLClassLoader ucl = (URLClassLoader) loader;
+         url = SecurityActions.findResource(ucl, propertiesName);
+         if (log.isTraceEnabled())
+            log.trace("findResource: " + url);
+      }
+      // Do a general resource search
+      if (url == null)
+         url = loader.getResource(propertiesName);
+      if (url == null) {
+         try {
+            url = new URL(propertiesName);
+         } catch (MalformedURLException mue) {
+            if (trace)
+               log.trace("Failed to open properties as URL", mue);
+            File tmp = new File(propertiesName);
+            if (tmp.exists())
+               url = tmp.toURI().toURL();
+         }
+      }
+      if (url == null)
+      {
+         String msg = "No properties file " + propertiesName + " found";
+         throw new IOException(msg);
+      }
+
+      if (log.isTraceEnabled())
+         log.trace("Properties file=" + url);
+      Properties defaults = new Properties();
+      bundle = new Properties(defaults);
+      InputStream is = null;
+      try
+      {
+         is = SecurityActions.openStream(url);
+      }
+      catch (PrivilegedActionException e)
+      {
+         if (trace)
+            log.trace("Open stream error", e);
+         throw new IOException(e.getLocalizedMessage());
+      }
+      if (is != null)
+      {
+         bundle.load(is);
+         is.close();
+      }
+      else
+      {
+         throw new IOException("Properties file " + propertiesName + " not available");
+      }
+      if (trace)
+         log.debug("Loaded properties, keySet=" + bundle.keySet());
+
+      return bundle;
+   }
+
+   /** 
+    * Create the set of roles the user belongs to by parsing the roles.properties
+    * data for username=role1,role2,...
+    * 
+    * @param username - name of user
+    * @param roleGroup - group containing the user's roles
+    * @param roles - the Properties containing the user=roles mappings
+    * @param log - logger
+    * @return Group[] containing the sets of roles
+    */
+   static void addRolesToGroup(String username, RoleGroup roleGroup, Properties roles, Logger log)
+   {
+      boolean trace = log.isTraceEnabled();
+      String[] roleNames = null;
+      if (roles.containsKey(username))
+      {
+         String value = roles.getProperty(username);
+         if (trace)
+            log.trace("Adding to RoleGroup: " + value);
+         roleNames = parseRoles(value);
+      }
+      if (roleNames != null)
+      {
+         for (int i = 0; i < roleNames.length; i++)
+         {
+            roleGroup.addRole(new SimpleRole(roleNames[i]));
+         }
+      }
+   }
+
+   /** 
+    * Parse the comma delimited roles names given by value
+    *
+    * @param roles - the comma delimited role names.
+    */
+   static String[] parseRoles(String roles)
+   {
+      return roles.split(",");
+   }
+
+   /**
+    * Create the set of roles the user belongs to by querying a database
+    * 
+    * @param username - name of the user
+    * @param roleGroup - group containing the user's roles
+    * @param dsJndiName - JNDI name of the datasource
+    * @param rolesQuery - prepared statement to query
+    * @param log - logger
+    * @param suspendResume - flag to indicate if transactions should be suspended/resumed
+    * @param tm - transaction manager
+    */
+   static void addRolesToGroup(String username, RoleGroup roleGroup, String dsJndiName, String rolesQuery, Logger log, boolean suspendResume, TransactionManager tm)
+   {
+      boolean trace = log.isTraceEnabled();
+      Connection conn = null;
+      PreparedStatement ps = null;
+      ResultSet rs = null;
+
+      if (suspendResume)
+      {
+         if (tm == null)
+            throw new IllegalStateException("Transaction Manager is null");
+      }
+      Transaction tx = null;
+      if (suspendResume)
+      {
+         try
+         {
+            tx = tm.suspend();
+         }
+         catch (SystemException e)
+         {
+            throw new RuntimeException(e);
+         }
+         if (trace)
+            log.trace("suspendAnyTransaction");
+      }
+
+      try
+      {
+         InitialContext ctx = new InitialContext();
+         DataSource ds = (DataSource) ctx.lookup(dsJndiName);
+         conn = ds.getConnection();
+         // Get the user role names
+         if (trace)
+            log.trace("Excuting query: " + rolesQuery + ", with username: " + username);
+         ps = conn.prepareStatement(rolesQuery);
+         try
+         {
+            ps.setString(1, username);
+         }
+         catch (ArrayIndexOutOfBoundsException ignore)
+         {
+            // The query may not have any parameters so just try it
+         }
+         rs = ps.executeQuery();
+         if (!rs.next())
+         {
+            if (trace)
+               log.trace("No roles found");
+         }
+         
+         do
+         {
+            String name = rs.getString(1);
+            roleGroup.addRole(new SimpleRole(name));
+         }
+         while (rs.next());
+      }
+      catch (NamingException ex)
+      {
+         throw new IllegalArgumentException("Error looking up DataSource from: " + dsJndiName, ex);
+      }
+      catch (SQLException ex)
+      {
+         throw new IllegalArgumentException("Query failed", ex);
+      }
+      finally
+      {
+         if (rs != null)
+         {
+            try
+            {
+               rs.close();
+            }
+            catch (SQLException e)
+            {
+            }
+         }
+         if (ps != null)
+         {
+            try
+            {
+               ps.close();
+            }
+            catch (SQLException e)
+            {
+            }
+         }
+         if (conn != null)
+         {
+            try
+            {
+               conn.close();
+            }
+            catch (Exception ex)
+            {
+            }
+         }
+         if (suspendResume)
+         {
+            try
+            {
+               tm.resume(tx);
+            }
+            catch (Exception e)
+            {
+               throw new RuntimeException(e);
+            }
+            if (trace)
+               log.trace("resumeAnyTransaction");
+         }
+      }
+   }
+
+}

Modified: trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/plugins/TransactionManagerLocator.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/plugins/TransactionManagerLocator.java	2011-05-26 18:23:11 UTC (rev 225)
+++ trunk/security-jboss-sx/jbosssx/src/main/java/org/jboss/security/plugins/TransactionManagerLocator.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -40,6 +40,7 @@
 {
    private static Logger log = Logger.getLogger(TransactionManagerLocator.class);
    private boolean trace = log.isTraceEnabled();
+   private static TransactionManager transactionManager;
    
    public TransactionManagerLocator()
    {   
@@ -72,6 +73,8 @@
          { 
             if(trace)
                log.trace("Exception in getJBossTM:", ignore);
+            if (transactionManager != null)
+               tm = transactionManager;
          }
       } 
       return tm;
@@ -84,4 +87,9 @@
       Method m = clz.getMethod("locate", new Class[]{});
       return (TransactionManager) m.invoke(null, new Object[0]); 
    }
+   
+   public static void setTransactionManager(TransactionManager transactionManager)
+   {
+      TransactionManagerLocator.transactionManager = transactionManager;
+   }
 }
\ No newline at end of file

Modified: trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/JBossSecuritySubjectFactoryUnitTestCase.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/JBossSecuritySubjectFactoryUnitTestCase.java	2011-05-26 18:23:11 UTC (rev 225)
+++ trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/JBossSecuritySubjectFactoryUnitTestCase.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -22,7 +22,10 @@
 package org.jboss.test.authentication;
 
 import java.lang.reflect.Method;
+import java.security.Principal;
 import java.security.acl.Group;
+import java.util.Collections;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Set;
 
@@ -162,11 +165,30 @@
       JBossSecuritySubjectFactory subjectFactory = new JBossSecuritySubjectFactory();
       Subject subject = subjectFactory.createSubject();
       Set<Group> groups = subject.getPrincipals(Group.class);
-      assertTrue("Principals contains scott", subject.getPrincipals().contains(new SimplePrincipal("scott")));
-      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
-      Group roles = groups.iterator().next();
-      assertTrue("TestRole is a role", roles.isMember(new SimplePrincipal("TestRole")));
-      assertTrue("Role2 is a role", roles.isMember(new SimplePrincipal("Role2")));
+      Principal scott = new SimplePrincipal("scott");
+      assertTrue("Principals contains scott", subject.getPrincipals().contains(scott));
+      assertTrue("Principals contains Roles", groups.contains(new SimpleGroup("Roles")));
+      assertTrue("Principals contains CallerPrincipal", groups.contains(new SimpleGroup("CallerPrincipal")));
+      for (Group group : groups)
+      {
+         if (group.getName().equals("Roles"))
+         {
+            Enumeration<? extends Principal> roles = group.members();
+            assertEquals("Roles group has 2 entries", 2, Collections.list(roles).size());
+            assertTrue("TestRole is a role", group.isMember(new SimplePrincipal("TestRole")));
+            assertTrue("Role2 is a role", group.isMember(new SimplePrincipal("Role2")));
+         }
+         else if (group.getName().equals("CallerPrincipal"))
+         {
+            Enumeration<? extends Principal> roles = group.members();
+            assertEquals("CallerPrincipal group has 1 entry", 1, Collections.list(roles).size());
+            assertTrue("scott is the caller principal", group.isMember(scott));
+         }
+         else
+         {
+            fail("Another group was set: " + group.getName());
+         }
+      }
    }
    
    public void testSubjectCreationWithDefaultSecurityManagementImplementation() throws Exception
@@ -180,10 +202,29 @@
       JBossSecuritySubjectFactory subjectFactory = new JBossSecuritySubjectFactory();
       Subject subject = subjectFactory.createSubject("securityDomain");
       Set<Group> groups = subject.getPrincipals(Group.class);
-      assertTrue("Principals contains scott", subject.getPrincipals().contains(new SimplePrincipal("scott")));
-      assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
-      Group roles = groups.iterator().next();
-      assertTrue("Role1 is a role", roles.isMember(new SimplePrincipal("Role1")));
+      Principal scott = new SimplePrincipal("scott");
+      assertTrue("Principals contains scott", subject.getPrincipals().contains(scott));
+      assertTrue("Principals contains Roles", groups.contains(new SimpleGroup("Roles")));
+      assertTrue("Principals contains CallerPrincipal", groups.contains(new SimpleGroup("CallerPrincipal")));
+      for (Group group : groups)
+      {
+         if (group.getName().equals("Roles"))
+         {
+            Enumeration<? extends Principal> roles = group.members();
+            assertEquals("Roles group has 1 entry", 1, Collections.list(roles).size());
+            assertTrue("Role1 is a role", group.isMember(new SimplePrincipal("Role1")));
+         }
+         else if (group.getName().equals("CallerPrincipal"))
+         {
+            Enumeration<? extends Principal> roles = group.members();
+            assertEquals("CallerPrincipal group has 1 entry", 1, Collections.list(roles).size());
+            assertTrue("scott is the caller principal", group.isMember(scott));
+         }
+         else
+         {
+            fail("Another group was set: " + group.getName());
+         }
+      }
    }
 
 }

Modified: trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/jaas/LoginModulesUnitTestCase.java
===================================================================
--- trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/jaas/LoginModulesUnitTestCase.java	2011-05-26 18:23:11 UTC (rev 225)
+++ trunk/security-jboss-sx/jbosssx/src/test/java/org/jboss/test/authentication/jaas/LoginModulesUnitTestCase.java	2011-06-15 15:31:14 UTC (rev 226)
@@ -25,6 +25,8 @@
 import java.security.MessageDigest;
 import java.security.Principal;
 import java.security.acl.Group;
+import java.util.Collections;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Set;
 
@@ -361,12 +363,31 @@
      LoginContext lc = new LoginContext("testUsernamePassword", handler);
      lc.login();
      Subject subject = lc.getSubject();
-     Set groups = subject.getPrincipals(Group.class);
-     assertTrue("Principals contains scott", subject.getPrincipals().contains(new SimplePrincipal("scott")));
-     assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
-     Group roles = (Group) groups.iterator().next();
-     assertTrue("TestRole is a role", roles.isMember(new SimplePrincipal("TestRole")));
-     assertTrue("Role2 is a role", roles.isMember(new SimplePrincipal("Role2")));
+     Set<Group> groups = subject.getPrincipals(Group.class);
+     Principal scott = new SimplePrincipal("scott");
+     assertTrue("Principals contains scott", subject.getPrincipals().contains(scott));
+     assertTrue("Principals contains Roles", groups.contains(new SimpleGroup("Roles")));
+     assertTrue("Principals contains CallerPrincipal", groups.contains(new SimpleGroup("CallerPrincipal")));
+     for (Group group : groups)
+     {
+        if (group.getName().equals("Roles"))
+        {
+           Enumeration<? extends Principal> roles = group.members();
+           assertEquals("Roles group has 2 entries", 2, Collections.list(roles).size());
+           assertTrue("TestRole is a role", group.isMember(new SimplePrincipal("TestRole")));
+           assertTrue("Role2 is a role", group.isMember(new SimplePrincipal("Role2")));
+        }
+        else if (group.getName().equals("CallerPrincipal"))
+        {
+           Enumeration<? extends Principal> roles = group.members();
+           assertEquals("CallerPrincipal group has 1 entry", 1, Collections.list(roles).size());
+           assertTrue("scott is the caller principal", group.isMember(scott));
+        }
+        else
+        {
+           fail("Another group was set: " + group.getName());
+        }
+     }
 
      lc.logout();
   }
@@ -377,12 +398,31 @@
      LoginContext lc = new LoginContext("testUsernamePasswordHash", handler);
      lc.login();
      Subject subject = lc.getSubject();
-     Set groups = subject.getPrincipals(Group.class);
-     assertTrue("Principals contains scott", subject.getPrincipals().contains(new SimplePrincipal("scott")));
-     assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
-     Group roles = (Group) groups.iterator().next();
-     assertTrue("TestRole is a role", roles.isMember(new SimplePrincipal("TestRole")));
-     assertTrue("Role2 is a role", roles.isMember(new SimplePrincipal("Role2")));
+     Set<Group> groups = subject.getPrincipals(Group.class);
+     Principal scott = new SimplePrincipal("scott");
+     assertTrue("Principals contains scott", subject.getPrincipals().contains(scott));
+     assertTrue("Principals contains Roles", groups.contains(new SimpleGroup("Roles")));
+     assertTrue("Principals contains CallerPrincipal", groups.contains(new SimpleGroup("CallerPrincipal")));
+     for (Group group : groups)
+     {
+        if (group.getName().equals("Roles"))
+        {
+           Enumeration<? extends Principal> roles = group.members();
+           assertEquals("Roles group has 2 entries", 2, Collections.list(roles).size());
+           assertTrue("TestRole is a role", group.isMember(new SimplePrincipal("TestRole")));
+           assertTrue("Role2 is a role", group.isMember(new SimplePrincipal("Role2")));
+        }
+        else if (group.getName().equals("CallerPrincipal"))
+        {
+           Enumeration<? extends Principal> roles = group.members();
+           assertEquals("CallerPrincipal group has 1 entry", 1, Collections.list(roles).size());
+           assertTrue("scott is the caller principal", group.isMember(scott));
+        }
+        else
+        {
+           fail("Another group was set: " + group.getName());
+        }
+     }
 
      lc.logout();
   }
@@ -394,11 +434,28 @@
      LoginContext lc = new LoginContext("testAnon", handler);
      lc.login();
      Subject subject = lc.getSubject();
-     Set groups = subject.getPrincipals(Group.class);
-     assertTrue("Principals contains nobody", subject.getPrincipals().contains(new SimplePrincipal("nobody")));
-     assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
-     Group roles = (Group) groups.iterator().next();
-     assertTrue("Roles has no members", roles.members().hasMoreElements() == false);
+     Set<Group> groups = subject.getPrincipals(Group.class);
+     Principal nobody = new SimplePrincipal("nobody");
+     assertTrue("Principals contains nobody", subject.getPrincipals().contains(nobody));
+     assertTrue("Principals contains Roles", groups.contains(new SimpleGroup("Roles")));
+     assertTrue("Principals contains CallerPrincipal", groups.contains(new SimpleGroup("CallerPrincipal")));
+     for (Group group : groups)
+     {
+        if (group.getName().equals("Roles"))
+        {
+           assertTrue("Roles has no members", !group.members().hasMoreElements());
+        }
+        else if (group.getName().equals("CallerPrincipal"))
+        {
+           Enumeration<? extends Principal> roles = group.members();
+           assertEquals("CallerPrincipal group has 1 entry", 1, Collections.list(roles).size());
+           assertTrue("scott is the caller principal", group.isMember(nobody));
+        }
+        else
+        {
+           fail("Another group was set: " + group.getName());
+        }
+     }
 
      lc.logout();
   }
@@ -424,13 +481,32 @@
      LoginContext lc = new LoginContext("testIdentity");
      lc.login();
      Subject subject = lc.getSubject();
-     Set groups = subject.getPrincipals(Group.class);
-     assertTrue("Principals contains stark", subject.getPrincipals().contains(new SimplePrincipal("stark")));
-     assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
-     Group roles = (Group) groups.iterator().next();
-     assertTrue("Role2 is not a role", roles.isMember(new SimplePrincipal("Role2")) == false);
-     assertTrue("Role3 is a role", roles.isMember(new SimplePrincipal("Role3")));
-     assertTrue("Role4 is a role", roles.isMember(new SimplePrincipal("Role4")));
+     Set<Group> groups = subject.getPrincipals(Group.class);
+     Principal stark = new SimplePrincipal("stark");
+     assertTrue("Principals contains stark", subject.getPrincipals().contains(stark));
+     assertTrue("Principals contains Roles", groups.contains(new SimpleGroup("Roles")));
+     assertTrue("Principals contains CallerPrincipal", groups.contains(new SimpleGroup("CallerPrincipal")));
+     for (Group group : groups)
+     {
+        if (group.getName().equals("Roles"))
+        {
+           Enumeration<? extends Principal> roles = group.members();
+           assertEquals("Roles group has 2 entries", 2, Collections.list(roles).size());
+           assertTrue("Role2 is not a role", !group.isMember(new SimplePrincipal("Role2")));
+           assertTrue("Role3 is a role", group.isMember(new SimplePrincipal("Role3")));
+           assertTrue("Role4 is a role", group.isMember(new SimplePrincipal("Role4")));
+        }
+        else if (group.getName().equals("CallerPrincipal"))
+        {
+           Enumeration<? extends Principal> roles = group.members();
+           assertEquals("CallerPrincipal group has 1 entry", 1, Collections.list(roles).size());
+           assertTrue("scott is the caller principal", group.isMember(stark));
+        }
+        else
+        {
+           fail("Another group was set: " + group.getName());
+        }
+     }
 
      lc.logout();
   } 
@@ -441,12 +517,31 @@
      LoginContext lc = new LoginContext("testSimple", handler);
      lc.login();
      Subject subject = lc.getSubject();
-     Set groups = subject.getPrincipals(Group.class);
-     assertTrue("Principals contains jduke", subject.getPrincipals().contains(new SimplePrincipal("jduke")));
-     assertTrue("Principals contains Roles", groups.contains(new SimplePrincipal("Roles")));
-     Group roles = (Group) groups.iterator().next();
-     assertTrue("user is a role", roles.isMember(new SimplePrincipal("user")));
-     assertTrue("guest is a role", roles.isMember(new SimplePrincipal("guest")));
+     Set<Group> groups = subject.getPrincipals(Group.class);
+     Principal jduke = new SimplePrincipal("jduke");
+     assertTrue("Principals contains jduke", subject.getPrincipals().contains(jduke));
+     assertTrue("Principals contains Roles", groups.contains(new SimpleGroup("Roles")));
+     assertTrue("Principals contains CallerPrincipal", groups.contains(new SimpleGroup("CallerPrincipal")));
+     for (Group group : groups)
+     {
+        if (group.getName().equals("Roles"))
+        {
+           Enumeration<? extends Principal> roles = group.members();
+           assertEquals("Roles group has 2 entries", 2, Collections.list(roles).size());
+           assertTrue("user is a role", group.isMember(new SimplePrincipal("user")));
+           assertTrue("guest is a role", group.isMember(new SimplePrincipal("guest")));
+        }
+        else if (group.getName().equals("CallerPrincipal"))
+        {
+           Enumeration<? extends Principal> roles = group.members();
+           assertEquals("CallerPrincipal group has 1 entry", 1, Collections.list(roles).size());
+           assertTrue("scott is the caller principal", group.isMember(jduke));
+        }
+        else
+        {
+           fail("Another group was set: " + group.getName());
+        }
+     }
 
      lc.logout();
   }



More information about the jboss-cvs-commits mailing list