[jboss-cvs] Picketbox SVN: r180 - in trunk: picketbox-infinispan and 16 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Mar 31 10:09:00 EDT 2011


Author: mmoyses
Date: 2011-03-31 10:09:00 -0400 (Thu, 31 Mar 2011)
New Revision: 180

Added:
   trunk/picketbox-infinispan/
   trunk/picketbox-infinispan/.classpath
   trunk/picketbox-infinispan/.project
   trunk/picketbox-infinispan/.settings/
   trunk/picketbox-infinispan/.settings/org.eclipse.jdt.core.prefs
   trunk/picketbox-infinispan/.settings/org.maven.ide.eclipse.prefs
   trunk/picketbox-infinispan/pom.xml
   trunk/picketbox-infinispan/src/
   trunk/picketbox-infinispan/src/main/
   trunk/picketbox-infinispan/src/main/java/
   trunk/picketbox-infinispan/src/main/java/org/
   trunk/picketbox-infinispan/src/main/java/org/jboss/
   trunk/picketbox-infinispan/src/main/java/org/jboss/security/
   trunk/picketbox-infinispan/src/main/java/org/jboss/security/authentication/
   trunk/picketbox-infinispan/src/main/java/org/jboss/security/authentication/JBossCachedAuthenticationManager.java
   trunk/picketbox-infinispan/src/main/java/org/jboss/security/authentication/SubjectActions.java
   trunk/picketbox-infinispan/src/test/
   trunk/picketbox-infinispan/src/test/java/
   trunk/picketbox-infinispan/src/test/java/org/
   trunk/picketbox-infinispan/src/test/java/org/jboss/
   trunk/picketbox-infinispan/src/test/java/org/jboss/security/
   trunk/picketbox-infinispan/src/test/java/org/jboss/security/test/
   trunk/picketbox-infinispan/src/test/java/org/jboss/security/test/authentication/
   trunk/picketbox-infinispan/src/test/java/org/jboss/security/test/authentication/JBossCachedAuthenticationManagerUnitTestCase.java
   trunk/picketbox-infinispan/src/test/java/org/jboss/security/test/authentication/SecurityActions.java
   trunk/picketbox-infinispan/src/test/resources/
   trunk/picketbox-infinispan/src/test/resources/roles.properties
   trunk/picketbox-infinispan/src/test/resources/users.properties
Modified:
   trunk/pom.xml
Log:
SECURITY-577: new AuthenticationManager implementation using Infinispan as cache solution


Property changes on: trunk/picketbox-infinispan
___________________________________________________________________
Added: svn:ignore
   + .settings


Added: trunk/picketbox-infinispan/.classpath
===================================================================
--- trunk/picketbox-infinispan/.classpath	                        (rev 0)
+++ trunk/picketbox-infinispan/.classpath	2011-03-31 14:09:00 UTC (rev 180)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry kind="src" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

Added: trunk/picketbox-infinispan/.project
===================================================================
--- trunk/picketbox-infinispan/.project	                        (rev 0)
+++ trunk/picketbox-infinispan/.project	2011-03-31 14:09:00 UTC (rev 180)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>picketbox-infinispan</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>

Added: trunk/picketbox-infinispan/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- trunk/picketbox-infinispan/.settings/org.eclipse.jdt.core.prefs	                        (rev 0)
+++ trunk/picketbox-infinispan/.settings/org.eclipse.jdt.core.prefs	2011-03-31 14:09:00 UTC (rev 180)
@@ -0,0 +1,9 @@
+#Thu Mar 24 17:50:09 BRT 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6

Added: trunk/picketbox-infinispan/.settings/org.maven.ide.eclipse.prefs
===================================================================
--- trunk/picketbox-infinispan/.settings/org.maven.ide.eclipse.prefs	                        (rev 0)
+++ trunk/picketbox-infinispan/.settings/org.maven.ide.eclipse.prefs	2011-03-31 14:09:00 UTC (rev 180)
@@ -0,0 +1,8 @@
+#Thu Mar 24 17:49:52 BRT 2011
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1

Added: trunk/picketbox-infinispan/pom.xml
===================================================================
--- trunk/picketbox-infinispan/pom.xml	                        (rev 0)
+++ trunk/picketbox-infinispan/pom.xml	2011-03-31 14:09:00 UTC (rev 180)
@@ -0,0 +1,53 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+   <parent>
+     <groupId>org.jboss</groupId>
+     <artifactId>jboss-parent</artifactId>
+     <version>5</version>
+   </parent>
+
+   <modelVersion>4.0.0</modelVersion>
+   <groupId>org.picketbox</groupId>
+   <artifactId>picketbox-infinispan</artifactId>
+   <version>4.0.0-SNAPSHOT</version>
+   <packaging>jar</packaging>
+   <name>Picketbox Infinispan</name>
+   <url>http://jboss.org/picketbox</url>
+   <description>PicketBox Infinispan adds cluster and cache capabilities to PicktBox.</description>
+   
+   <properties>
+   	<version.org.infinispan>4.2.1.FINAL</version.org.infinispan>
+   </properties>
+
+    <dependencies>
+      <dependency>
+         <groupId>org.picketbox</groupId>
+         <artifactId>picketbox-spi-bare</artifactId>
+         <version>${project.version}</version>
+         <scope>compile</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.picketbox</groupId>
+         <artifactId>jbosssx-bare</artifactId>
+         <version>${project.version}</version>
+         <scope>compile</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.jboss.logging</groupId>
+         <artifactId>jboss-logging-spi</artifactId>
+         <version>2.1.1.GA</version>
+         <scope>compile</scope>
+      </dependency>
+      <dependency>
+         <groupId>org.infinispan</groupId>
+         <artifactId>infinispan-core</artifactId>
+         <version>${version.org.infinispan}</version>
+         <scope>compile</scope>
+      </dependency>
+      <dependency>
+         <groupId>junit</groupId>
+         <artifactId>junit</artifactId>
+         <version>4.8.1</version>
+         <scope>test</scope>
+      </dependency>
+    </dependencies>
+</project>

Added: trunk/picketbox-infinispan/src/main/java/org/jboss/security/authentication/JBossCachedAuthenticationManager.java
===================================================================
--- trunk/picketbox-infinispan/src/main/java/org/jboss/security/authentication/JBossCachedAuthenticationManager.java	                        (rev 0)
+++ trunk/picketbox-infinispan/src/main/java/org/jboss/security/authentication/JBossCachedAuthenticationManager.java	2011-03-31 14:09:00 UTC (rev 180)
@@ -0,0 +1,493 @@
+/*
+ * 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.authentication;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.infinispan.Cache;
+import org.jboss.logging.Logger;
+import org.jboss.security.AuthenticationManager;
+import org.jboss.security.CacheableManager;
+import org.jboss.security.SecurityConstants;
+import org.jboss.security.SecurityContext;
+import org.jboss.security.SecurityContextAssociation;
+import org.jboss.security.auth.callback.JBossCallbackHandler;
+import org.jboss.security.authentication.JBossCachedAuthenticationManager.DomainInfo;
+
+/**
+ * {@link AuthenticationManager} implementation that uses {@link Cache} as the cache provider.
+ * 
+ * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ * @author <a href="on at ibis.odessa.ua">Oleg Nitz</a>
+ * @author Scott.Stark at jboss.org
+ * @author Anil.Saldhana at jboss.org
+ */
+public class JBossCachedAuthenticationManager
+      implements
+         AuthenticationManager,
+         CacheableManager<Cache<Principal, DomainInfo>, Principal>
+{
+
+   private String securityDomain;
+
+   private CallbackHandler callbackHandler;
+
+   protected Logger log = Logger.getLogger(this.getClass());
+
+   protected boolean trace;
+
+   private transient Method setSecurityInfo;
+
+   protected Cache<Principal, DomainInfo> domainCache;
+
+   private boolean deepCopySubjectOption = false;
+
+   /**
+    * Create a new JBossCachedAuthenticationManager using the
+    * default security domain and {@link CallbackHandler} implementation.
+    */
+   public JBossCachedAuthenticationManager()
+   {
+      this(SecurityConstants.DEFAULT_APPLICATION_POLICY, new JBossCallbackHandler());
+   }
+
+   /**
+    * Create a new JBossCachedAuthenticationManager.
+    * 
+    * @param securityDomain name of the security domain
+    * @param callbackHandler {@link CallbackHandler} implementation
+    */
+   public JBossCachedAuthenticationManager(String securityDomain, CallbackHandler callbackHandler)
+   {
+      this.securityDomain = securityDomain;
+      this.callbackHandler = callbackHandler;
+      this.trace = log.isTraceEnabled();
+
+      // Get the setSecurityInfo(Principal principal, Object credential) method
+      Class<?>[] sig =
+      {Principal.class, Object.class};
+      try
+      {
+         setSecurityInfo = callbackHandler.getClass().getMethod("setSecurityInfo", sig);
+      }
+      catch (Exception e)
+      {
+         String msg = "Failed to find setSecurityInfo(Principal, Object) method in CallbackHandler";
+         throw new UndeclaredThrowableException(e, msg);
+      }
+      if (trace)
+         log.trace("CallbackHandler: " + callbackHandler);
+   }
+
+   @Override
+   public Subject getActiveSubject()
+   {
+      Subject subj = null;
+      SecurityContext sc = SecurityContextAssociation.getSecurityContext();
+      if (sc != null)
+      {
+         subj = sc.getUtil().getSubject();
+      }
+      return subj;
+   }
+
+   @Override
+   public Principal getTargetPrincipal(Principal anotherDomainPrincipal, Map<String, Object> contextMap)
+   {
+      throw new RuntimeException("Not implemented yet");
+   }
+
+   @Override
+   public boolean isValid(Principal principal, Object credential)
+   {
+      return isValid(principal, credential, null);
+   }
+
+   @Override
+   public boolean isValid(Principal principal, Object credential, Subject activeSubject)
+   {
+      // first check cache
+      DomainInfo cachedEntry = getCacheInfo(principal);
+      if (trace)
+         log.trace("Begin isValid, principal:" + principal + ", cache entry: " + cachedEntry);
+
+      boolean isValid = false;
+      if (cachedEntry != null)
+      {
+         isValid = validateCache(cachedEntry, credential, activeSubject);
+      }
+
+      if (!isValid)
+         isValid = authenticate(principal, credential, activeSubject);
+
+      if (trace)
+         log.trace("End isValid, " + isValid);
+
+      return isValid;
+   }
+
+   @Override
+   public String getSecurityDomain()
+   {
+      return securityDomain;
+   }
+
+   @Override
+   public void flushCache()
+   {
+      if (trace)
+         log.trace("Flushing all entried from the cache");
+      domainCache.clear();
+   }
+
+   @Override
+   public void flushCache(Principal key)
+   {
+      if (trace)
+         log.trace("Flushing " + key.getName() + " from cache");
+      domainCache.evict(key);
+   }
+
+   @Override
+   public void setCache(Cache<Principal, DomainInfo> cache)
+   {
+      this.domainCache = cache;
+   }
+   
+   @Override
+   public boolean containsKey(Principal key)
+   {
+      return domainCache.containsKey(key);
+   }
+
+   /**
+    * Flag to specify if deep copy of subject sets needs to be 
+    * enabled
+    * 
+    * @param flag
+    */
+   public void setDeepCopySubjectOption(Boolean flag)
+   {
+      if (trace)
+         log.trace("setDeepCopySubjectOption=" + flag);
+      deepCopySubjectOption = flag.booleanValue();
+   }
+
+   /**
+    * Retrieve on entry from the cache.
+    * 
+    * @param principal entry's key
+    * @return entry's value or null if not found
+    */
+   private DomainInfo getCacheInfo(Principal principal)
+   {
+      if (domainCache == null)
+         return null;
+      return domainCache.get(principal);
+   }
+
+   /**
+    * Validate the cache credential value against the provided credential
+    */
+   @SuppressWarnings({"rawtypes", "unchecked"})
+   private boolean validateCache(DomainInfo info, Object credential, Subject theSubject)
+   {
+      if (trace)
+      {
+         StringBuffer tmp = new StringBuffer("Begin validateCache, info=");
+         tmp.append(info.toString());
+         tmp.append(";credential.class=");
+         if (credential != null)
+         {
+            Class c = credential.getClass();
+            tmp.append(c.getName());
+            tmp.append('@');
+            tmp.append(System.identityHashCode(c));
+         }
+         else
+         {
+            tmp.append("null");
+         }
+         log.trace(tmp.toString());
+      }
+
+      Object subjectCredential = info.credential;
+      boolean isValid = false;
+      // Check for a null credential as can be the case for an anonymous user
+      if (credential == null || subjectCredential == null)
+      {
+         // Both credentials must be null
+         isValid = (credential == null) && (subjectCredential == null);
+      }
+      // See if the credential is assignable to the cache value
+      else if (subjectCredential.getClass().isAssignableFrom(credential.getClass()))
+      {
+         // Validate the credential by trying Comparable, char[], byte[], Object[], and finally Object.equals()
+         if (subjectCredential instanceof Comparable)
+         {
+            Comparable c = (Comparable) subjectCredential;
+            isValid = c.compareTo(credential) == 0;
+         }
+         else if (subjectCredential instanceof char[])
+         {
+            char[] a1 = (char[]) subjectCredential;
+            char[] a2 = (char[]) credential;
+            isValid = Arrays.equals(a1, a2);
+         }
+         else if (subjectCredential instanceof byte[])
+         {
+            byte[] a1 = (byte[]) subjectCredential;
+            byte[] a2 = (byte[]) credential;
+            isValid = Arrays.equals(a1, a2);
+         }
+         else if (subjectCredential.getClass().isArray())
+         {
+            Object[] a1 = (Object[]) subjectCredential;
+            Object[] a2 = (Object[]) credential;
+            isValid = Arrays.equals(a1, a2);
+         }
+         else
+         {
+            isValid = subjectCredential.equals(credential);
+         }
+      }
+      else if (subjectCredential instanceof char[] && credential instanceof String)
+      {
+         char[] a1 = (char[]) subjectCredential;
+         char[] a2 = ((String) credential).toCharArray();
+         isValid = Arrays.equals(a1, a2);
+      }
+      else if (subjectCredential instanceof String && credential instanceof char[])
+      {
+         char[] a1 = ((String) subjectCredential).toCharArray();
+         char[] a2 = (char[]) credential;
+         isValid = Arrays.equals(a1, a2);
+      }
+
+      // If the credentials match, set the thread's active Subject
+      if (isValid)
+      {
+         // Copy the current subject into theSubject
+         if (theSubject != null)
+         {
+            SubjectActions.copySubject(info.subject, theSubject, false, this.deepCopySubjectOption);
+         }
+      }
+      if (trace)
+         log.trace("End validateCache, isValid=" + isValid);
+
+      return isValid;
+   }
+   
+   /** 
+    * Currently this simply calls defaultLogin() to do a JAAS login using the
+    * security domain name as the login module configuration name.
+    *
+    * @param principal - the user id to authenticate
+    * @param credential - an opaque credential.
+    * @return false on failure, true on success.
+    */
+   private boolean authenticate(Principal principal, Object credential, Subject theSubject)
+   {
+      Subject subject = null;
+      boolean authenticated = false;
+      LoginException authException = null;
+
+      try
+      {
+         // Validate the principal using the login configuration for this domain
+         LoginContext lc = defaultLogin(principal, credential);
+         subject = lc.getSubject();
+
+         // Set the current subject if login was successful
+         if (subject != null)
+         {
+            // Copy the current subject into theSubject
+            if (theSubject != null)
+            {
+               SubjectActions.copySubject(subject, theSubject, false, this.deepCopySubjectOption);
+            }
+            else
+            {
+               theSubject = subject;
+            }
+
+            authenticated = true;
+            // Build the Subject based DomainInfo cache value
+            updateCache(lc, subject, principal, credential);
+         }
+      }
+      catch (LoginException e)
+      {
+         // Don't log anonymous user failures unless trace level logging is on
+         if (principal != null && principal.getName() != null || trace)
+            log.trace("Login failure", e);
+         authException = e;
+      }
+      // Set the security association thread context info exception
+      SubjectActions.setContextInfo("org.jboss.security.exception", authException);
+
+      return authenticated;
+   }
+   
+   /** 
+    * Pass the security info to the login modules configured for
+    * this security domain using our SecurityAssociationHandler.
+    *
+    * @return The authenticated Subject if successful.
+    * @exception LoginException throw if login fails for any reason.
+    */
+   private LoginContext defaultLogin(Principal principal, Object credential) throws LoginException
+   {
+      // We use our internal CallbackHandler to provide the security info. A
+      // copy must be made to ensure there is a unique handler per active
+      // login since there can be multiple active logins.
+      Object[] securityInfo = {principal, credential};
+      CallbackHandler theHandler = null;
+      try
+      {
+         theHandler = (CallbackHandler) callbackHandler.getClass().newInstance();
+         setSecurityInfo.invoke(theHandler, securityInfo);
+      }
+      catch (Throwable e)
+      {
+         if (trace)
+            log.trace("Failed to create/setSecurityInfo on handler", e);
+         LoginException le = new LoginException("Failed to setSecurityInfo on handler");
+         le.initCause(e);
+         throw le;
+      }
+      Subject subject = new Subject();
+      LoginContext lc = null;
+      if (trace)
+         log.trace("defaultLogin, principal=" + principal);
+      lc = SubjectActions.createLoginContext(securityDomain, subject, theHandler);
+      lc.login();
+      if (trace)
+         log.trace("defaultLogin, lc=" + lc + ", subject=" + SubjectActions.toString(subject));
+      return lc;
+   }
+
+   /**
+    * Updates the cache either by inserting a new entry or by replacing
+    * an invalid (expired) entry.
+    * 
+    * @param loginContext {@link LoginContext} of the authentication
+    * @param subject {@link Subject} resulted from JAAS login
+    * @param principal {@link Principal} representing the user's identity
+    * @param credential user's proof of identity
+    * @return authenticated {@link Subject}
+    */
+   private Subject updateCache(LoginContext loginContext, Subject subject, Principal principal, Object credential)
+   {
+      // If we don't have a cache there is nothing to update
+      if (domainCache == null)
+         return subject;
+
+      DomainInfo info = new DomainInfo();
+      info.loginContext = loginContext;
+      info.subject = new Subject();
+      SubjectActions.copySubject(subject, info.subject, true, this.deepCopySubjectOption);
+      info.credential = credential;
+
+      if (trace)
+      {
+         log.trace("updateCache, inputSubject=" + SubjectActions.toString(subject) + ", cacheSubject="
+               + SubjectActions.toString(info.subject));
+      }
+
+      // Get the Subject callerPrincipal by looking for a Group called 'CallerPrincipal'
+      Set<Group> subjectGroups = subject.getPrincipals(Group.class);
+      Iterator<Group> iter = subjectGroups.iterator();
+      while (iter.hasNext())
+      {
+         Group grp = iter.next();
+         String name = grp.getName();
+         if (name.equals("CallerPrincipal"))
+         {
+            Enumeration<? extends Principal> members = grp.members();
+            if (members.hasMoreElements())
+               info.callerPrincipal = members.nextElement();
+         }
+      }
+
+      // Handle null principals with no callerPrincipal. This is an indication
+      // of an user that has not provided any authentication info, but
+      // has been authenticated by the domain login module stack. Here we look
+      // for the first non-Group Principal and use that.
+      if (info.callerPrincipal == null)
+      {
+         Set<Principal> subjectPrincipals = subject.getPrincipals(Principal.class);
+         Iterator<? extends Principal> iterPrincipals = subjectPrincipals.iterator();
+         while (iterPrincipals.hasNext())
+         {
+            Principal p = iterPrincipals.next();
+            if (!(p instanceof Group))
+            {
+               info.callerPrincipal = p;
+               break;
+            }
+         }
+      }
+
+      // If the user already exists another login is active. Currently
+      // only one is allowed so remove the old and insert the new
+      domainCache.put(info.callerPrincipal, info);
+      if (trace)
+         log.trace("Inserted cache info: " + info);
+      return info.subject;
+   }
+
+   /**
+    * A cache value. Holds information about the authentication process.
+    * 
+    * @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+    */
+   public static class DomainInfo implements Serializable
+   {
+
+      private static final long serialVersionUID = 7402775370244483773L;
+
+      protected LoginContext loginContext;
+
+      protected Subject subject;
+
+      protected Object credential;
+
+      protected Principal callerPrincipal;
+   }
+
+}

Added: trunk/picketbox-infinispan/src/main/java/org/jboss/security/authentication/SubjectActions.java
===================================================================
--- trunk/picketbox-infinispan/src/main/java/org/jboss/security/authentication/SubjectActions.java	                        (rev 0)
+++ trunk/picketbox-infinispan/src/main/java/org/jboss/security/authentication/SubjectActions.java	2011-03-31 14:09:00 UTC (rev 180)
@@ -0,0 +1,365 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, 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.authentication;
+
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.security.jacc.PolicyContext;
+import javax.security.jacc.PolicyContextException;
+
+import org.jboss.security.SecurityAssociation;
+import org.jboss.security.SecurityConstants;
+import org.jboss.security.SecurityContext;
+import org.jboss.security.SecurityContextAssociation;
+import org.jboss.security.SecurityContextFactory;
+
+/** 
+ * Common PrivilegedAction used by classes in this package.
+ * 
+ * @author Scott.Stark at jboss.org
+ * @author Anil.Saldhana at redhat.com
+ */
+class SubjectActions
+{
+   private static class ToStringSubjectAction implements PrivilegedAction<String>
+   {
+      Subject subject;
+
+      ToStringSubjectAction(Subject subject)
+      {
+         this.subject = subject;
+      }
+
+      public String run()
+      {
+         StringBuffer tmp = new StringBuffer();
+         tmp.append("Subject(");
+         tmp.append(System.identityHashCode(subject));
+         tmp.append(").principals=");
+         Iterator<Principal> principals = subject.getPrincipals().iterator();
+         while (principals.hasNext())
+         {
+            Object p = principals.next();
+            Class<?> c = p.getClass();
+            tmp.append(c.getName());
+            tmp.append('@');
+            tmp.append(System.identityHashCode(c));
+            tmp.append('(');
+            tmp.append(p);
+            tmp.append(')');
+         }
+         return tmp.toString();
+      }
+   }
+
+   private static class GetSubjectAction implements PrivilegedExceptionAction<Subject>
+   {
+      static PrivilegedExceptionAction<Subject> ACTION = new GetSubjectAction();
+
+      public Subject run() throws PolicyContextException
+      {
+         return (Subject) PolicyContext.getContext(SecurityConstants.SUBJECT_CONTEXT_KEY);
+      }
+   }
+
+   private static class CopySubjectAction implements PrivilegedAction<Object>
+   {
+      Subject fromSubject;
+
+      Subject toSubject;
+
+      boolean setReadOnly;
+
+      boolean deepCopy;
+
+      CopySubjectAction(Subject fromSubject, Subject toSubject, boolean setReadOnly)
+      {
+         this.fromSubject = fromSubject;
+         this.toSubject = toSubject;
+         this.setReadOnly = setReadOnly;
+      }
+
+      public void setDeepCopy(boolean flag)
+      {
+         this.deepCopy = flag;
+      }
+
+      @SuppressWarnings({"rawtypes", "unchecked"})
+      public Object run()
+      {
+         Set principals = fromSubject.getPrincipals();
+         Set principals2 = toSubject.getPrincipals();
+         Iterator<Principal> iter = principals.iterator();
+         while (iter.hasNext())
+            principals2.add(getCloneIfNeeded(iter.next()));
+         Set privateCreds = fromSubject.getPrivateCredentials();
+         Set privateCreds2 = toSubject.getPrivateCredentials();
+         iter = privateCreds.iterator();
+         while (iter.hasNext())
+            privateCreds2.add(getCloneIfNeeded(iter.next()));
+         Set publicCreds = fromSubject.getPublicCredentials();
+         Set publicCreds2 = toSubject.getPublicCredentials();
+         iter = publicCreds.iterator();
+         while (iter.hasNext())
+            publicCreds2.add(getCloneIfNeeded(iter.next()));
+         if (setReadOnly == true)
+            toSubject.setReadOnly();
+         return null;
+      }
+
+      /** Check if the deepCopy flag is ON && Object implements {@link Cloneable} and return cloned object */
+      private Object getCloneIfNeeded(Object obj)
+      {
+         Object clonedObject = null;
+         if (this.deepCopy && obj instanceof Cloneable)
+         {
+            Class<?> clazz = obj.getClass();
+            try
+            {
+               Method cloneMethod = clazz.getMethod("clone", (Class[]) null);
+               clonedObject = cloneMethod.invoke(obj, (Object[]) null);
+            }
+            catch (Exception e)
+            {
+               // Ignore non-cloneable issues 
+            }
+         }
+         if (clonedObject == null)
+            clonedObject = obj;
+         return clonedObject;
+      }
+   }
+
+   private static class LoginContextAction implements PrivilegedExceptionAction<LoginContext>
+   {
+      String securityDomain;
+
+      Subject subject;
+
+      CallbackHandler handler;
+
+      LoginContextAction(String securityDomain, Subject subject, CallbackHandler handler)
+      {
+         this.securityDomain = securityDomain;
+         this.subject = subject;
+         this.handler = handler;
+      }
+
+      public LoginContext run() throws Exception
+      {
+         LoginContext lc = new LoginContext(securityDomain, subject, handler);
+         return lc;
+      }
+   }
+
+   private static class GetTCLAction implements PrivilegedAction<ClassLoader>
+   {
+      static PrivilegedAction<ClassLoader> ACTION = new GetTCLAction();
+
+      public ClassLoader run()
+      {
+         ClassLoader loader = Thread.currentThread().getContextClassLoader();
+         return loader;
+      }
+   }
+
+   private static class SetContextInfoAction implements PrivilegedAction<Object>
+   {
+      String key;
+
+      Object value;
+
+      SetContextInfoAction(String key, Object value)
+      {
+         this.key = key;
+         this.value = value;
+      }
+
+      public Object run()
+      {
+         // Set it on the current security context also
+         SecurityContext sc = SecurityContextAssociation.getSecurityContext();
+         if (sc != null)
+         {
+            sc.getData().put(key, value);
+         }
+         return SecurityAssociation.setContextInfo(key, value);
+      }
+   }
+
+   interface PrincipalInfoAction
+   {
+      PrincipalInfoAction PRIVILEGED = new PrincipalInfoAction()
+      {
+         public void push(final Principal principal, final Object credential, final Subject subject,
+               final String securityDomain)
+         {
+            AccessController.doPrivileged(new PrivilegedAction<Object>()
+            {
+               public Object run()
+               {
+                  SecurityContext sc = SecurityContextAssociation.getSecurityContext();
+                  if (sc == null)
+                  {
+                     try
+                     {
+                        sc = SecurityContextFactory.createSecurityContext(principal, credential, subject,
+                              securityDomain);
+                     }
+                     catch (Exception e)
+                     {
+                        throw new RuntimeException(e);
+                     }
+                  }
+                  SecurityContextAssociation.setSecurityContext(sc);
+                  return null;
+               }
+            });
+         }
+
+         public void pop()
+         {
+            AccessController.doPrivileged(new PrivilegedAction<Object>()
+            {
+               public Object run()
+               {
+                  SecurityContextAssociation.clearSecurityContext();
+                  return null;
+               }
+            });
+         }
+      };
+
+      PrincipalInfoAction NON_PRIVILEGED = new PrincipalInfoAction()
+      {
+         public void push(Principal principal, Object credential, Subject subject, String securityDomain)
+         {
+            SecurityContext sc = SecurityContextAssociation.getSecurityContext();
+            if (sc == null)
+            {
+               try
+               {
+                  sc = SecurityContextFactory.createSecurityContext(principal, credential, subject, securityDomain);
+               }
+               catch (Exception e)
+               {
+                  throw new RuntimeException(e);
+               }
+            }
+            else
+            {
+               sc.getUtil().createSubjectInfo(principal, credential, subject);
+            }
+            SecurityContextAssociation.setSecurityContext(sc);
+         }
+
+         public void pop()
+         {
+            SecurityContextAssociation.clearSecurityContext();
+         }
+      };
+
+      void push(Principal principal, Object credential, Subject subject, String securityDomain);
+
+      void pop();
+   }
+
+   static Subject getActiveSubject() throws PrivilegedActionException
+   {
+      Subject subject = (Subject) AccessController.doPrivileged(GetSubjectAction.ACTION);
+      return subject;
+   }
+
+   static void copySubject(Subject fromSubject, Subject toSubject)
+   {
+      copySubject(fromSubject, toSubject, false);
+   }
+
+   static void copySubject(Subject fromSubject, Subject toSubject, boolean setReadOnly)
+   {
+      CopySubjectAction action = new CopySubjectAction(fromSubject, toSubject, setReadOnly);
+      if (System.getSecurityManager() != null)
+         AccessController.doPrivileged(action);
+      else
+         action.run();
+   }
+
+   static void copySubject(Subject fromSubject, Subject toSubject, boolean setReadOnly, boolean deepCopy)
+   {
+      CopySubjectAction action = new CopySubjectAction(fromSubject, toSubject, setReadOnly);
+      action.setDeepCopy(deepCopy);
+      if (System.getSecurityManager() != null)
+         AccessController.doPrivileged(action);
+      else
+         action.run();
+   }
+
+   static LoginContext createLoginContext(String securityDomain, Subject subject, CallbackHandler handler)
+         throws LoginException
+   {
+      LoginContextAction action = new LoginContextAction(securityDomain, subject, handler);
+      try
+      {
+         LoginContext lc = (LoginContext) AccessController.doPrivileged(action);
+         return lc;
+      }
+      catch (PrivilegedActionException e)
+      {
+         Exception ex = e.getException();
+         if (ex instanceof LoginException)
+            throw (LoginException) ex;
+         else
+            throw new LoginException(ex.getMessage());
+      }
+   }
+
+   static ClassLoader getContextClassLoader()
+   {
+      ClassLoader loader = (ClassLoader) AccessController.doPrivileged(GetTCLAction.ACTION);
+      return loader;
+   }
+
+   static Object setContextInfo(String key, Object value)
+   {
+      SetContextInfoAction action = new SetContextInfoAction(key, value);
+      Object prevInfo = AccessController.doPrivileged(action);
+      return prevInfo;
+   }
+
+   static String toString(Subject subject)
+   {
+      ToStringSubjectAction action = new ToStringSubjectAction(subject);
+      String info = (String) AccessController.doPrivileged(action);
+      return info;
+   }
+}
\ No newline at end of file

Added: trunk/picketbox-infinispan/src/test/java/org/jboss/security/test/authentication/JBossCachedAuthenticationManagerUnitTestCase.java
===================================================================
--- trunk/picketbox-infinispan/src/test/java/org/jboss/security/test/authentication/JBossCachedAuthenticationManagerUnitTestCase.java	                        (rev 0)
+++ trunk/picketbox-infinispan/src/test/java/org/jboss/security/test/authentication/JBossCachedAuthenticationManagerUnitTestCase.java	2011-03-31 14:09:00 UTC (rev 180)
@@ -0,0 +1,201 @@
+/*
+ * 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.test.authentication;
+
+import java.security.Principal;
+import java.util.HashMap;
+
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
+
+import junit.framework.TestCase;
+
+import org.infinispan.Cache;
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.jboss.security.AuthenticationManager;
+import org.jboss.security.CacheableManager;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.auth.callback.AppCallbackHandler;
+import org.jboss.security.authentication.JBossCachedAuthenticationManager;
+import org.jboss.security.authentication.JBossCachedAuthenticationManager.DomainInfo;
+
+/**
+ *  Unit tests for the JBossCachedAuthenticationManager.
+ *  
+ *  @author <a href="mmoyses at redhat.com">Marcus Moyses</a>
+ *  @author Anil.Saldhana at redhat.com
+ */
+public class JBossCachedAuthenticationManagerUnitTestCase extends TestCase
+{
+   @Override
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      establishSecurityConfiguration();
+   }
+
+   public void testSecurityDomain() throws Exception
+   {
+      AuthenticationManager am = new JBossCachedAuthenticationManager("test1", new AppCallbackHandler("a",
+            "b".toCharArray()));
+      assertEquals("test1", am.getSecurityDomain());
+   }
+
+   public void testLogin() throws Exception
+   {
+      Principal p = new SimplePrincipal("jduke");
+      AppCallbackHandler acbh = new AppCallbackHandler("jduke", "theduke".toCharArray());
+      AuthenticationManager am = new JBossCachedAuthenticationManager("test", acbh);
+      assertTrue(am.isValid(p, "theduke"));
+   }
+
+   public void testUnsuccessfulLogin() throws Exception
+   {
+      Principal p = new SimplePrincipal("jduke");
+      AppCallbackHandler acbh = new AppCallbackHandler("jduke", "bad".toCharArray());
+      AuthenticationManager am = new JBossCachedAuthenticationManager("test", acbh);
+      assertFalse(am.isValid(p, "bad"));
+   }
+   
+   public void testCacheHit() throws Exception
+   {
+      Principal p = new SimplePrincipal("jduke");
+      AppCallbackHandler acbh = new AppCallbackHandler("jduke", "theduke".toCharArray());
+      AuthenticationManager am = new JBossCachedAuthenticationManager("test", acbh);
+      
+      EmbeddedCacheManager cacheManager = new DefaultCacheManager();
+      org.infinispan.config.Configuration configuration = new org.infinispan.config.Configuration();
+      configuration.setExpirationMaxIdle(2000);
+      cacheManager.defineConfiguration("test", configuration);
+      Cache<Principal, DomainInfo> cache = cacheManager.getCache("test");
+      @SuppressWarnings("unchecked")
+      CacheableManager<Cache<Principal, DomainInfo>, Principal> cm = (CacheableManager<Cache<Principal, DomainInfo>, Principal>) am;
+      cm.setCache(cache);
+      
+      assertTrue(am.isValid(p, "theduke"));
+      assertTrue(cm.containsKey(p));
+      Thread.sleep(1000);
+      assertTrue(cm.containsKey(p));
+   }
+   
+   public void testCacheIdleTimeExpiration() throws Exception
+   {
+      Principal p = new SimplePrincipal("jduke");
+      AppCallbackHandler acbh = new AppCallbackHandler("jduke", "theduke".toCharArray());
+      AuthenticationManager am = new JBossCachedAuthenticationManager("test", acbh);
+      
+      EmbeddedCacheManager cacheManager = new DefaultCacheManager();
+      org.infinispan.config.Configuration configuration = new org.infinispan.config.Configuration();
+      configuration.setExpirationMaxIdle(1000);
+      cacheManager.defineConfiguration("test", configuration);
+      Cache<Principal, DomainInfo> cache = cacheManager.getCache("test");
+      @SuppressWarnings("unchecked")
+      CacheableManager<Cache<Principal, DomainInfo>, Principal> cm = (CacheableManager<Cache<Principal, DomainInfo>, Principal>) am;
+      cm.setCache(cache);
+      
+      assertTrue(am.isValid(p, "theduke"));
+      assertTrue(cm.containsKey(p));
+      Thread.sleep(2000);
+      assertFalse(cm.containsKey(p));
+   }
+   
+   public void testCacheIdleTimeUpdate() throws Exception
+   {
+      Principal p = new SimplePrincipal("jduke");
+      AppCallbackHandler acbh = new AppCallbackHandler("jduke", "theduke".toCharArray());
+      AuthenticationManager am = new JBossCachedAuthenticationManager("test", acbh);
+      
+      EmbeddedCacheManager cacheManager = new DefaultCacheManager();
+      org.infinispan.config.Configuration configuration = new org.infinispan.config.Configuration();
+      configuration.setExpirationMaxIdle(2000);
+      cacheManager.defineConfiguration("test", configuration);
+      Cache<Principal, DomainInfo> cache = cacheManager.getCache("test");
+      @SuppressWarnings("unchecked")
+      CacheableManager<Cache<Principal, DomainInfo>, Principal> cm = (CacheableManager<Cache<Principal, DomainInfo>, Principal>) am;
+      cm.setCache(cache);
+      
+      assertTrue(am.isValid(p, "theduke"));
+      assertTrue(cm.containsKey(p));
+      Thread.sleep(1000);
+      assertTrue(cm.containsKey(p));
+      Thread.sleep(1000);
+      assertTrue(cm.containsKey(p));
+      Thread.sleep(1000);
+      assertTrue(cm.containsKey(p));
+      Thread.sleep(3000);
+      assertFalse(cm.containsKey(p));
+   }
+
+   public void testCacheLifespanExpiration() throws Exception
+   {
+      Principal p = new SimplePrincipal("jduke");
+      AppCallbackHandler acbh = new AppCallbackHandler("jduke", "theduke".toCharArray());
+      AuthenticationManager am = new JBossCachedAuthenticationManager("test", acbh);
+      
+      EmbeddedCacheManager cacheManager = new DefaultCacheManager();
+      org.infinispan.config.Configuration configuration = new org.infinispan.config.Configuration();
+      configuration.setExpirationMaxIdle(2000);
+      configuration.setExpirationLifespan(3000);
+      cacheManager.defineConfiguration("test", configuration);
+      Cache<Principal, DomainInfo> cache = cacheManager.getCache("test");
+      @SuppressWarnings("unchecked")
+      CacheableManager<Cache<Principal, DomainInfo>, Principal> cm = (CacheableManager<Cache<Principal, DomainInfo>, Principal>) am;
+      cm.setCache(cache);
+      
+      assertTrue(am.isValid(p, "theduke"));
+      assertTrue(cm.containsKey(p));
+      Thread.sleep(1000);
+      assertTrue(cm.containsKey(p));
+      Thread.sleep(1000);
+      assertTrue(cm.containsKey(p));
+      Thread.sleep(1000);
+      assertFalse(cm.containsKey(p));
+   }
+   
+   private void establishSecurityConfiguration()
+   {
+      SecurityActions.setJAASConfiguration((Configuration) new TestConfig());
+   }
+
+   public class TestConfig extends Configuration
+   {
+      @Override
+      public AppConfigurationEntry[] getAppConfigurationEntry(String name)
+      {
+         HashMap<String, Object> map = new HashMap<String, Object>();
+         map.put("usersProperties", "users.properties");
+         map.put("rolesProperties", "roles.properties");
+         String moduleName = "org.jboss.security.auth.spi.UsersRolesLoginModule";
+         AppConfigurationEntry ace = new AppConfigurationEntry(moduleName, LoginModuleControlFlag.REQUIRED, map);
+
+         return new AppConfigurationEntry[]
+         {ace};
+      }
+
+      @Override
+      public void refresh()
+      {
+      }
+   }
+}

Added: trunk/picketbox-infinispan/src/test/java/org/jboss/security/test/authentication/SecurityActions.java
===================================================================
--- trunk/picketbox-infinispan/src/test/java/org/jboss/security/test/authentication/SecurityActions.java	                        (rev 0)
+++ trunk/picketbox-infinispan/src/test/java/org/jboss/security/test/authentication/SecurityActions.java	2011-03-31 14:09:00 UTC (rev 180)
@@ -0,0 +1,77 @@
+/*
+  * 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.test.authentication;
+  
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.Configuration;
+import javax.security.jacc.PolicyContext;
+
+//$Id$
+
+/**
+ *  Privileged Blocks
+ *  @author Anil.Saldhana at redhat.com
+ *  @since  Sep 25, 2007 
+ *  @version $Revision$
+ */
+public class SecurityActions
+{
+   public static void addPrincipalToSubject(final Subject subj, final Principal p)
+   {
+      AccessController.doPrivileged(new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            subj.getPrincipals().add(p);
+            return null;
+         }
+      }); 
+   }
+   
+   public static void setJAASConfiguration(final Configuration configuration)
+   {
+      AccessController.doPrivileged(new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            Configuration.setConfiguration(configuration);
+            return null;
+         }
+      });
+   }
+   
+   public static void setPolicyContextID(final String contextID)
+   {
+      AccessController.doPrivileged(new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            PolicyContext.setContextID(contextID);
+            return null;
+         }
+      });
+   }
+}

Added: trunk/picketbox-infinispan/src/test/resources/roles.properties
===================================================================
--- trunk/picketbox-infinispan/src/test/resources/roles.properties	                        (rev 0)
+++ trunk/picketbox-infinispan/src/test/resources/roles.properties	2011-03-31 14:09:00 UTC (rev 180)
@@ -0,0 +1,12 @@
+scott=Echo
+stark=Java,Coder
+stark.CallerPrincipal=callerStark
+
+starksm.Roles=ProjectUser
+starksm.CallerPrincipal=callerStarksm
+scott.Roles=ProjectUser
+scott.CallerPrincipal=callerScott
+
+jduke=Role1,Role2
+jdukeman=Role2,Role3
+jdukeman.CallerPrincipal=callerJdukeman
\ No newline at end of file

Added: trunk/picketbox-infinispan/src/test/resources/users.properties
===================================================================
--- trunk/picketbox-infinispan/src/test/resources/users.properties	                        (rev 0)
+++ trunk/picketbox-infinispan/src/test/resources/users.properties	2011-03-31 14:09:00 UTC (rev 180)
@@ -0,0 +1,4 @@
+scott=echoman
+stark=javaman
+jduke=theduke
+jdukeman=anotherduke
\ No newline at end of file

Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml	2011-03-31 13:49:41 UTC (rev 179)
+++ trunk/pom.xml	2011-03-31 14:09:00 UTC (rev 180)
@@ -18,6 +18,7 @@
      <module>security-spi</module>
      <module>security-jboss-sx</module>
      <module>picketbox</module>
+     <module>picketbox-infinispan</module>
      <module>assembly</module>
    </modules>
 </project>



More information about the jboss-cvs-commits mailing list