[jboss-cvs] JBossAS SVN: r58921 - in branches/JBoss_4_0_3_SP1_CP: testsuite/imports testsuite/src/main/org/jboss/test testsuite/src/main/org/jboss/test/web/test testsuite/src/resources/test-configs/tomcat-sso/deploy/jbossweb-tomcat55.sar testsuite/src/resources/test-configs/tomcat-sso-cluster/deploy/jbossweb-tomcat55.sar testsuite/src/resources/web/sso/war tomcat/src/main/org/jboss/web/tomcat/tc5/session tomcat/src/main/org/jboss/web/tomcat/tc5/sso

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Dec 7 22:07:41 EST 2006


Author: vivekl at redhat.com
Date: 2006-12-07 22:07:36 -0500 (Thu, 07 Dec 2006)
New Revision: 58921

Removed:
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso-cluster/deploy/jbossweb-tomcat55.sar/context.xml
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso/deploy/jbossweb-tomcat55.sar/context.xml
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/index.jsp
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/isValid.jsp
Modified:
   branches/JBoss_4_0_3_SP1_CP/testsuite/imports/test-jars.xml
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/JBossClusteredTestCase.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/JBossTestClusteredServices.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/ClusteredSingleSignOnUnitTestCase.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/SSOBaseCase.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/SingleSignOnUnitTestCase.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso-cluster/deploy/jbossweb-tomcat55.sar/server.xml
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/web-sso-expire.xml
   branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossManager.java
   branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/ClusteredSingleSignOn.java
   branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/TreeCacheSSOClusterManager.java
   branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/mbeans-descriptors.xml
Log:
ASPATCH129: JBAS-3808: Port JBAS-3096 Fix to 4.0.3.SP1
Revision 58722 reverted since this is not meant for a CP release.



Modified: branches/JBoss_4_0_3_SP1_CP/testsuite/imports/test-jars.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/imports/test-jars.xml	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/imports/test-jars.xml	2006-12-08 03:07:36 UTC (rev 58921)
@@ -5086,7 +5086,6 @@
       </classes>
       <fileset dir="${build.resources}/web/sso/war">
         <include name="**/*.html"/>
-        <include name="**/*.jsp"/>
       </fileset>
     </war>
     <war destfile="${build.lib}/sso-expire.war"
@@ -5100,7 +5099,6 @@
       </classes>
       <fileset dir="${build.resources}/web/sso/war">
         <include name="**/*.html"/>
-        <include name="**/*.jsp"/>
       </fileset>
     </war>
     <zip destfile="${build.lib}/web-sso.ear">

Modified: branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/JBossClusteredTestCase.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/JBossClusteredTestCase.java	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/JBossClusteredTestCase.java	2006-12-08 03:07:36 UTC (rev 58921)
@@ -63,16 +63,6 @@
       return clusterServices.getHttpURLs();
    }
 
-   protected void deploy(RMIAdaptor server, String name) throws Exception
-   {
-      clusterServices.deploy(server, name);
-   }
-
-   protected void undeploy(RMIAdaptor server, String name) throws Exception
-   {
-      clusterServices.undeploy(server, name);
-   }
-
    public static Test getDeploySetup(final Test test, final String jarName)
       throws Exception
    {

Modified: branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/JBossTestClusteredServices.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/JBossTestClusteredServices.java	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/JBossTestClusteredServices.java	2006-12-08 03:07:36 UTC (rev 58921)
@@ -6,7 +6,6 @@
  */
 package org.jboss.test;
 
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.Hashtable;
 
@@ -134,53 +133,6 @@
 
    }
 
-   /**
-    * Deploy a package on the given server with the main deployer. The supplied 
-    * name is interpreted as a url, or as a filename in jbosstest.deploy.lib or 
-    * ../lib.
-    *
-    * @param server         server on which the package should be deployed
-    * @param name           filename/url of package to deploy.
-    * @exception Exception  Description of Exception
-    */
-   public void deploy(RMIAdaptor server, String name) throws Exception
-   {
-      if (Boolean.getBoolean("jbosstest.nodeploy") == true)
-      {
-         log.debug("Skipping deployment of: " + name);
-         return;
-      }
-
-      URL deployURL = new URL(getDeployURL(name));
-      log.debug("Deploying " + name + ", url=" + deployURL  + " to " + server);
-      invoke(server,
-            getDeployerName(),
-            "deploy",
-            new Object[]{deployURL},
-            new String[]{"java.net.URL"});
-   }
-
-   /**
-    * Undeploy a package from the given server with the main deployer. 
-    * The supplied name is interpreted as a url, or as a filename in 
-    * jbosstest.deploy.lib or ../lib.
-    *
-    * @param server         server on which the package should be deployed
-    * @param name           filename/url of package to undeploy.
-    * @exception Exception  Description of Exception
-    */
-   public void undeploy(RMIAdaptor server, String name) throws Exception
-   {
-      if (Boolean.getBoolean("jbosstest.nodeploy") == true)
-         return;
-
-      URL deployURL = new URL(getDeployURL(name));
-      log.debug("Undeploying " + name + ", url=" + deployURL);
-      Object[] args = {deployURL};
-      String[] sig = {"java.net.URL"};
-      invoke(server, getDeployerName(), "undeploy", args, sig);
-   }
-
    public void init() throws Exception
    {
       if (initialContext == null)

Modified: branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/ClusteredSingleSignOnUnitTestCase.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/ClusteredSingleSignOnUnitTestCase.java	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/ClusteredSingleSignOnUnitTestCase.java	2006-12-08 03:07:36 UTC (rev 58921)
@@ -1,37 +1,23 @@
 /*
-* JBoss, a division of Red Hat
-* Copyright 2006, Red Hat Middleware, LLC, 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.
-*/
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
 package org.jboss.test.web.test;
 
-import java.util.Set;
+import java.net.HttpURLConnection;
 
-import javax.management.ObjectName;
-
 import junit.framework.Test;
-import junit.framework.TestSuite;
 
+import org.apache.commons.httpclient.Cookie;
+import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpState;
-import org.jboss.cache.Fqn;
-import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.log4j.Category;
 import org.jboss.test.JBossClusteredTestCase;
 
 
@@ -43,13 +29,6 @@
 public class ClusteredSingleSignOnUnitTestCase 
       extends JBossClusteredTestCase
 {   
-   // NOTE: these variables must be static as apparently a separate instance
-   // of this class is created for each test
-   private static boolean deployed0 = true;
-   private static boolean deployed1 = true;
-   
-   private RMIAdaptor[] adaptors = null;
-   
    public ClusteredSingleSignOnUnitTestCase(String name)
    {
       super(name);
@@ -59,119 +38,11 @@
     */
    public static Test suite() throws Exception
    {
-      // Have to build the suite in detail, as testSessionExpiration must come first
-      TestSuite suite = new TestSuite();
-      suite.addTest(new ClusteredSingleSignOnUnitTestCase("testSessionExpiration"));
-      suite.addTest(new ClusteredSingleSignOnUnitTestCase("testFormAuthSingleSignOn"));
-      suite.addTest(new ClusteredSingleSignOnUnitTestCase("testWebappUndeploy"));
-      
-//      return JBossClusteredTestCase.getDeploySetup(suite, "web-sso-clustered.ear");
-      
-      return JBossClusteredTestCase.getDeploySetup(suite, "web-sso.ear");
+      Test t1 = JBossClusteredTestCase.getDeploySetup(ClusteredSingleSignOnUnitTestCase.class,
+            "web-sso.ear");
+      return t1;
    }
 
-   protected void setUp() throws Exception
-   {
-      super.setUp();
-      
-      log.debug("deployed0 = " + deployed0);
-      log.debug("deployed1 = " + deployed1);
-      
-      adaptors = getAdaptors(); 
-      if (!deployed0)
-      {
-//         deploy(adaptors[0], "web-sso-clustered.ear");
-         deploy(adaptors[0], "web-sso.ear");
-         deployed0 = true;
-      }
-      if (!deployed1)
-      {
-//         deploy(adaptors[1], "web-sso-clustered.ear");
-         deploy(adaptors[1], "web-sso.ear");
-         deployed1 = true;
-      }
-   }
-   
-   protected void tearDown() throws Exception
-   {
-      super.tearDown();
-      
-      log.debug("deployed0 = " + deployed0);
-      log.debug("deployed1 = " + deployed1);
-   }
-   
-   /**
-    * Tests that undeploying a webapp on one server doesn't kill an sso
-    * that also has a session from another webapp associated with it.
-    * See JBAS-2429.
-    * 
-    * TODO create an independently deployable war so we can test this in
-    *      a non-clustered environment as well; this isn't a clustering issue 
-    *
-    * @throws Exception
-    */
-   public void testWebappUndeploy() throws Exception
-   {
-      log.info("+++ testWebappUndeploy");
-      
-      String[] httpURLs  = super.getHttpURLs();
-
-      String serverA = httpURLs[0];
-      String serverB = httpURLs[1];
-      
-      String warA1 = serverA + "/war1/";
-      String warB1 = serverB + "/war1/";
-      String warB2 = serverB + "/war2/";
-      
-      // Start by accessing the secured index.html of war1
-      HttpClient httpConn = new HttpClient();
-      SSOBaseCase.checkAccessDenied(httpConn,  warA1 + "index.html");
-
-      HttpState state = httpConn.getState();
-      
-      String sessionID = SSOBaseCase.getSessionIdFromState(state);
-      log.debug("Saw JSESSIONID="+sessionID);
-      
-      // Submit the login form
-      SSOBaseCase.executeFormLogin(httpConn, warA1);
-
-      String ssoID = SSOBaseCase.processSSOCookie(state, serverA, serverB);
-      log.debug("Saw JSESSIONIDSSO="+ssoID);
-
-      // Pause a moment before switching wars to better simulate real life
-      // use cases.  Otherwise, the test case can "outrun" the async
-      // replication in the TreeCache used by the clustered SSO
-      // 500 ms is a long time, but this isn't a test of replication speed
-      // and we don't want spurious failures.
-      if (!serverA.equals(serverB))
-         Thread.sleep(500);
-
-      // Now try getting the war2 index using the JSESSIONIDSSO cookie 
-      log.debug("Prepare /war2/index.html get");
-      SSOBaseCase.checkAccessAllowed(httpConn, warB2 + "index.html");
-
-      // Sleep some more to allow the updated sso to propagate back to serverA
-      if (!serverA.equals(serverB))
-         Thread.sleep(500);
-      
-      // We now have a clustered sso context, plus a war1 session on
-      // serverA and a war2 session on serverB. No war1 session on serverB,
-      // so the only way to access war1 on B without a login is through sso.
-      
-      //Undeploy the ear from serverA and confirm that it doesn't kill the sso
-//      undeploy(adaptors[0], "web-sso-clustered.ear");
-      undeploy(adaptors[0], "web-sso.ear");
-      deployed0 = false;
-
-      // Sleep some more to allow the updated sso to propagate back to serverB
-      if (!serverA.equals(serverB))
-         Thread.sleep(500);
-      
-      // Now try getting the war1 index using the JSESSIONIDSSO cookie 
-      log.debug("Prepare /war1/index.html get");
-      SSOBaseCase.checkAccessAllowed(httpConn, warB1 + "index.html");
-   }
-
    /** Test single sign-on across two web apps using form based auth
     * 
     * @throws Exception
@@ -193,83 +64,81 @@
     * Tests that use of transactions in ClusteredSSO does not interfere 
     * with session expiration thread.  See JBAS-2212.
     * 
+    * TODO  this is a quick-and-dirty test to get JBoss 4.0.3 out;
+    *       clearly needs to be refactored
+    * 
     * @throws Exception
     */ 
    public void testSessionExpiration() 
          throws Exception
    {
-      log.info("+++ testSessionExpiration");
+      log.info("+++ testFormAuthSingleSignOn");
       String[] httpURLs  = super.getHttpURLs();
 
       String serverA = httpURLs[0];
-      String serverB = httpURLs[1];
       log.info(System.getProperties());
       log.info("serverA: "+serverA);
-      log.info("serverB: "+serverB);
       
-      String warA3 = serverA + "/war3/";
-      String warB3 = serverB + "/war3/";
-      
-      // First create an SSO that we won't use again -- we later test that it
-      // gets cleaned up from the cache
-      HttpClient httpConn1 = new HttpClient();
-      SSOBaseCase.checkAccessDenied(httpConn1, warA3 + "index.jsp");
-      SSOBaseCase.executeFormLogin(httpConn1, warA3);
-      
-      // Now the standard SSO tests
+      // Start by accessing the secured index.html of war1
       HttpClient httpConn = new HttpClient();
-      SSOBaseCase.checkAccessDenied(httpConn, warA3 + "index.jsp");
-      HttpState state = httpConn.getState();      
-      String sessionID = SSOBaseCase.getSessionIdFromState(state);
-      log.debug("Saw JSESSIONID="+sessionID);
-      SSOBaseCase.executeFormLogin(httpConn, warA3);
-      String ssoID = SSOBaseCase.processSSOCookie(state, serverA, serverB);
-      log.debug("Saw JSESSIONIDSSO="+ssoID);
+      GetMethod indexGet = new GetMethod(serverA+"/war3/index.html");
+      int responseCode = httpConn.executeMethod(indexGet);
+      String body = indexGet.getResponseBodyAsString();
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      assertTrue("Redirected to login page", body.indexOf("j_security_check") > 0 );
 
-      // Wait more than 15 secs to let session time out
-      // It's life is 5 secs and the processor runs every 10
-      try {
-         Thread.sleep(15500);
-      }
-      catch (InterruptedException ie)
+      HttpState state = httpConn.getState();
+      Cookie[] cookies = state.getCookies();
+      String sessionID = null;
+      for(int c = 0; c < cookies.length; c ++)
       {
-         log.debug("Interrupted while waiting for session expiration");
+         Cookie k = cookies[c];
+         if( k.getName().equalsIgnoreCase("JSESSIONID") )
+            sessionID = k.getValue();
       }
-      
-      // Try accessing war3 again on both nodes -- should succeed
-      SSOBaseCase.checkAccessAllowed(httpConn, warA3 + "index.jsp");
-      SSOBaseCase.checkAccessAllowed(httpConn, warB3 + "index.jsp");
+      log.debug("Saw JSESSIONID="+sessionID);
 
-      // Wait more than 30 secs to let SSO time out -- 15 for the sessions
-      // (as above) and 15 for the SSOs maxEmptyLife
+      // Submit the login form
+      PostMethod formPost = new PostMethod(serverA+"/war3/j_security_check");
+      formPost.addRequestHeader("Referer", serverA+"/war3/login.html");
+      formPost.addParameter("j_username", "jduke");
+      formPost.addParameter("j_password", "theduke");
+      responseCode = httpConn.executeMethod(formPost.getHostConfiguration(),
+         formPost, state);
+      String response = formPost.getStatusText();
+      log.debug("responseCode="+responseCode+", response="+response);
+      assertTrue("Saw HTTP_MOVED_TEMP("+responseCode+")",
+         responseCode == HttpURLConnection.HTTP_MOVED_TEMP);
+
+      //  Follow the redirect to the index.html page
+      Header location = formPost.getResponseHeader("Location");
+      String indexURI = location.getValue();
+      GetMethod war1Index = new GetMethod(indexURI);
+      responseCode = httpConn.executeMethod(war1Index.getHostConfiguration(),
+         war1Index, state);
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      body = war1Index.getResponseBodyAsString();
+      if( body.indexOf("j_security_check") > 0 )
+         fail("get of "+indexURI+" redirected to login page");
+
+      // Wait more than 1 minute to let session time out
       try {
-         Thread.sleep(30500);
+         Thread.sleep(75000);
       }
       catch (InterruptedException ie)
       {
-         log.debug("Interrupted while waiting for SSO expiration");
+         log.debug("Interrupted while waiting for session expiration");
       }
       
-      // Try accessing war3 again on both nodes -- should fail
-      SSOBaseCase.checkAccessDenied(httpConn, warA3 + "index.jsp");
-      SSOBaseCase.checkAccessDenied(httpConn, warB3 + "index.jsp");
+      // Try accessing war1 again
+      war1Index = new GetMethod(serverA+"/war3/index.html");
+      responseCode = httpConn.executeMethod(war1Index.getHostConfiguration(),
+         war1Index, state);
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      body = war1Index.getResponseBodyAsString();
+      log.debug("body: " + body);
+      if( body.indexOf("j_security_check") < 0 )
+         fail("get of /war1/index.html not redirected to login page");
       
-      // Confirm that the SSO we created at the start was removed from
-      // the cache
-      Set ssoIds = getSSOIds(adaptors[0]);
-      log.info("node0 sso ids are " + ssoIds);
-      assertEquals("node0 cache has no SSOs", 0, ssoIds.size());
-      ssoIds = getSSOIds(adaptors[1]);
-      log.info("node1 sso ids are " + ssoIds);
-      assertEquals("node1 cache has no SSOs", 0, ssoIds.size());
    }
-   
-   private Set getSSOIds(RMIAdaptor adaptor) throws Exception
- {
-    Fqn ssoRoot = new Fqn(new Object[] {"SSO"});
-    ObjectName oname = new ObjectName("jboss.cache:service=TomcatClusteringCache");
-    return (Set) adaptor.invoke(oname, "getChildrenNames", 
-                               new Object[]{ ssoRoot }, 
-                               new String[]{ Fqn.class.getName() });
- }
 }

Modified: branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/SSOBaseCase.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/SSOBaseCase.java	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/SSOBaseCase.java	2006-12-08 03:07:36 UTC (rev 58921)
@@ -1,34 +1,18 @@
 /*
-* JBoss, a division of Red Hat
-* Copyright 2006, Red Hat Middleware, LLC, 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.
-*/
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
 package org.jboss.test.web.test;
 
-import java.io.IOException;
 import java.net.HttpURLConnection;
 
 import junit.framework.TestCase;
 import org.apache.commons.httpclient.Cookie;
 import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.HttpState;
 import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.commons.httpclient.methods.PostMethod;
@@ -51,137 +35,132 @@
                                                   Category log) 
          throws Exception
    {
-      String warA1 = serverA + "/war1/";
-      String warB2 = serverB + "/war2/";
-      
       // Start by accessing the secured index.html of war1
       HttpClient httpConn = new HttpClient();
-      
-      checkAccessDenied(httpConn, warA1 + "index.html");
+      GetMethod indexGet = new GetMethod(serverA+"/war1/index.html");
+      int responseCode = httpConn.executeMethod(indexGet);
+      String body = indexGet.getResponseBodyAsString();
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      assertTrue("Redirected to login page", body.indexOf("j_security_check") > 0 );
 
       HttpState state = httpConn.getState();
-      
-      String sessionID = getSessionIdFromState(state);
+      Cookie[] cookies = state.getCookies();
+      String sessionID = null;
+      for(int c = 0; c < cookies.length; c ++)
+      {
+         Cookie k = cookies[c];
+         if( k.getName().equalsIgnoreCase("JSESSIONID") )
+            sessionID = k.getValue();
+      }
       log.debug("Saw JSESSIONID="+sessionID);
 
       // Submit the login form
-      executeFormLogin(httpConn, warA1);
-
-      String ssoID = processSSOCookie(state, serverA, serverB);
-      log.debug("Saw JSESSIONIDSSO="+ssoID);
-
-      // Pause a moment before switching wars to better simulate real life
-      // use cases.  Otherwise, the test case can "outrun" the async
-      // replication in the TreeCache used by the clustered SSO
-      // 500 ms is a long time, but this isn't a test of replication speed
-      // and we don't want spurious failures.
-      if (!serverA.equals(serverB))
-         Thread.sleep(500);
-
-      // Now try getting the war2 index using the JSESSIONIDSSO cookie 
-      log.debug("Prepare /war2/index.html get");
-      checkAccessAllowed(httpConn, warB2 + "index.html");
-
-      /* Access a secured servlet that calls a secured ejb in war2 to test
-      propagation of the SSO identity to the ejb container. */
-      checkAccessAllowed(httpConn, warB2 + "EJBServlet");
-
-      // Now try logging out of war2 
-      executeLogout(httpConn, warB2);
-      
-      // Again, pause before switching wars
-      if (!serverA.equals(serverB))
-         Thread.sleep(500);
-      
-      // Try accessing war1 again      
-      checkAccessDenied(httpConn, warA1 + "index.html");
-      
-      // Try accessing war2 again      
-      checkAccessDenied(httpConn, warB2 + "index.html");      
-      
-   }
-
-   public static void executeLogout(HttpClient httpConn, String warURL) throws IOException, HttpException
-   {
-      GetMethod logout = new GetMethod(warURL + "Logout");
-      logout.setFollowRedirects(false);
-      int responseCode = httpConn.executeMethod(logout.getHostConfiguration(),
-         logout, httpConn.getState());
-      assertTrue("Logout: Saw HTTP_MOVED_TEMP("+responseCode+")",
-         responseCode == HttpURLConnection.HTTP_MOVED_TEMP);
-      Header location = logout.getResponseHeader("Location");
-      String indexURI = location.getValue();
-      if( indexURI.indexOf("index.html") < 0 )
-         fail("get of " + warURL + "Logout not redirected to login page");
-   }
-
-   public static void checkAccessAllowed(HttpClient httpConn, String url) throws IOException, HttpException
-   {
-      GetMethod war2Index = new GetMethod(url);
-      int responseCode = httpConn.executeMethod(war2Index.getHostConfiguration(),
-         war2Index, httpConn.getState());
-      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
-      String body = war2Index.getResponseBodyAsString();
-      if( body.indexOf("j_security_check") > 0 )
-         fail("get of " + url + " redirected to login page");
-   }
-
-   public static void executeFormLogin(HttpClient httpConn, String warURL) throws IOException, HttpException
-   {      
-      PostMethod formPost = new PostMethod(warURL + "j_security_check");
-      formPost.addRequestHeader("Referer", warURL + "login.html");
+      PostMethod formPost = new PostMethod(serverA+"/war1/j_security_check");
+      formPost.addRequestHeader("Referer", serverA+"/war1/login.html");
       formPost.addParameter("j_username", "jduke");
       formPost.addParameter("j_password", "theduke");
-      int responseCode = httpConn.executeMethod(formPost.getHostConfiguration(),
-         formPost, httpConn.getState());
+      responseCode = httpConn.executeMethod(formPost.getHostConfiguration(),
+         formPost, state);
+      String response = formPost.getStatusText();
+      log.debug("responseCode="+responseCode+", response="+response);
       assertTrue("Saw HTTP_MOVED_TEMP("+responseCode+")",
          responseCode == HttpURLConnection.HTTP_MOVED_TEMP);
 
       //  Follow the redirect to the index.html page
       Header location = formPost.getResponseHeader("Location");
       String indexURI = location.getValue();
-      GetMethod warIndex = new GetMethod(indexURI);
-      responseCode = httpConn.executeMethod(warIndex.getHostConfiguration(),
-         warIndex, httpConn.getState());
+      GetMethod war1Index = new GetMethod(indexURI);
+      responseCode = httpConn.executeMethod(war1Index.getHostConfiguration(),
+         war1Index, state);
       assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
-      String body = warIndex.getResponseBodyAsString();
+      body = war1Index.getResponseBodyAsString();
       if( body.indexOf("j_security_check") > 0 )
          fail("get of "+indexURI+" redirected to login page");
-   }
 
-   public static void checkAccessDenied(HttpClient httpConn, String url) throws IOException, HttpException
-   {
-      GetMethod indexGet = new GetMethod(url);
-      int responseCode = httpConn.executeMethod(indexGet);
-      String body = indexGet.getResponseBodyAsString();
-      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
-      assertTrue("Redirected to login page", body.indexOf("j_security_check") > 0 );
-   }
-
-   public static String processSSOCookie(HttpState state, String serverA, String serverB)
-   {
-      Cookie[] cookies = state.getCookies();
+      cookies = state.getCookies();
       String ssoID = null;
       for(int c = 0; c < cookies.length; c ++)
       {
-         if( "JSESSIONIDSSO".equalsIgnoreCase(cookies[c].getName()) )
+         Cookie k = cookies[c];
+         if( k.getName().equalsIgnoreCase("JSESSIONIDSSO") )
          {
-            ssoID = cookies[c].getValue();
+            ssoID = k.getValue();
             if (serverA.equals(serverB) == false) 
             {
                // Make an sso cookie to send to serverB
-               Cookie copy = copyCookie(cookies[c], serverB);
+               Cookie copy = copyCookie(k, serverB);
                state.addCookie(copy);
+               log.debug("Added state cookie: "+copy);
             }
          }
       }
+      assertTrue("Saw JSESSIONIDSSO", ssoID != null);
+      log.debug("Saw JSESSIONIDSSO="+ssoID);
+
+      // Now try getting the war2 index using the JSESSIONIDSSO cookie 
+      log.debug("Prepare /war2/index.html get");
+      GetMethod war2Index = new GetMethod(serverB+"/war2/index.html");
+      responseCode = httpConn.executeMethod(war2Index.getHostConfiguration(),
+         war2Index, state);
+      response = war2Index.getStatusText();
+      log.debug("responseCode="+responseCode+", response="+response);
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      body = war2Index.getResponseBodyAsString();
+      log.debug("body: "+body);
+      if( body.indexOf("j_security_check") > 0 )
+         fail("get of /war2/index.html redirected to login page");
+
+      /* Access a secured servlet that calls a secured ejb in war2 to test
+      propagation of the SSO identity to the ejb container.
+      */
+      GetMethod war2Servlet = new GetMethod(serverB+"/war2/EJBServlet");
+      responseCode = httpConn.executeMethod(war2Servlet.getHostConfiguration(),
+         war2Servlet, state);
+      response = war2Servlet.getStatusText();
+      log.debug("responseCode="+responseCode+", response="+response);
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      body = war2Servlet.getResponseBodyAsString();
+      log.debug("body: "+body);
+      if( body.indexOf("j_security_check") > 0 )
+         fail("get of /war2/EJBServlet redirected to login page");
+
+      // Now try logging out of war2 
+      GetMethod war2Logout = new GetMethod(serverB+"/war2/Logout");
+      war2Logout.setFollowRedirects(false);
+      responseCode = httpConn.executeMethod(war2Logout.getHostConfiguration(),
+         war2Logout, state);
+      response = war2Logout.getStatusText();
+      log.debug("responseCode="+responseCode+", response="+response);
+      assertTrue("Logout: Saw HTTP_MOVED_TEMP("+responseCode+")",
+         responseCode == HttpURLConnection.HTTP_MOVED_TEMP);
+      location = war2Logout.getResponseHeader("Location");
+      indexURI = location.getValue();
+      if( indexURI.indexOf("index.html") < 0 )
+         fail("get of /war2/Logout not redirected to login page");
       
-      assertNotNull("Saw JSESSIONIDSSO", ssoID);
+      // Try accessing war1 again
+      war1Index = new GetMethod(serverA+"/war1/index.html");
+      responseCode = httpConn.executeMethod(war1Index.getHostConfiguration(),
+         war1Index, state);
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      body = war1Index.getResponseBodyAsString();
+      log.debug("body: " + body);
+      if( body.indexOf("j_security_check") < 0 )
+         fail("get of /war1/index.html not redirected to login page");
       
-      return ssoID;
+      // Try accessing war2 again
+      war2Index = new GetMethod(serverB+"/war2/index.html");
+      responseCode = httpConn.executeMethod(war2Index.getHostConfiguration(),
+         war2Index, state);
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      body = war2Index.getResponseBodyAsString();
+      log.debug("body: " + body);
+      if( body.indexOf("j_security_check") < 0 )
+         fail("get of /war2/index.html not redirected to login page");      
+      
    }
    
-   public static Cookie copyCookie(Cookie toCopy, String targetServer)
+   private static Cookie copyCookie(Cookie toCopy, String targetServer)
    {
       // Parse the target server down to a domain name
       int index = targetServer.indexOf("://");
@@ -208,17 +187,4 @@
                                false);
       return copy;
    }
-   
-   public static String getSessionIdFromState(HttpState state)
-   {
-      Cookie[] cookies = state.getCookies();
-      String sessionID = null;
-      for(int c = 0; c < cookies.length; c ++)
-      {
-         if( "JSESSIONID".equalsIgnoreCase(cookies[c].getName()) )
-            sessionID = cookies[c].getName();
-      }
-      return sessionID;
-      
-   }
 }

Modified: branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/SingleSignOnUnitTestCase.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/SingleSignOnUnitTestCase.java	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/SingleSignOnUnitTestCase.java	2006-12-08 03:07:36 UTC (rev 58921)
@@ -1,26 +1,20 @@
 /*
-* JBoss, a division of Red Hat
-* Copyright 2006, Red Hat Middleware, LLC, 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.
-*/
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
 package org.jboss.test.web.test;
 
+import java.net.HttpURLConnection;
+
+import org.apache.commons.httpclient.Cookie;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpState;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
 import org.jboss.test.JBossTestCase;
 import org.jboss.test.JBossTestSetup;
 import junit.framework.Test;
@@ -33,7 +27,7 @@
  */
 public class SingleSignOnUnitTestCase extends JBossTestCase
 {
-   private String baseURLNoAuth = "http://" + getServerHost() + ":" + Integer.getInteger("web.port", 8080); 
+   private String baseURLNoAuth = "http://" + getServerHost() + ":" + Integer.getInteger("web.port", 8080) + "/"; 
 
    public SingleSignOnUnitTestCase(String name)
    {
@@ -46,12 +40,86 @@
     */ 
    public void testFormAuthSingleSignOn() throws Exception
    {
-      log.info("+++ testFormAuthSingleSignOn");
+      // Start by accessing the secured index.html of war1
+      HttpClient httpConn = new HttpClient();
+      GetMethod indexGet = new GetMethod(baseURLNoAuth+"war1/index.html");
+      int responseCode = httpConn.executeMethod(indexGet);
+      String body = indexGet.getResponseBodyAsString();
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      assertTrue("Redirected to login page", body.indexOf("j_security_check") > 0 );
 
-      SSOBaseCase.executeFormAuthSingleSignOnTest(baseURLNoAuth, baseURLNoAuth, getLog());
+      HttpState state = httpConn.getState();
+      Cookie[] cookies = state.getCookies();
+      String sessionID = null;
+      for(int c = 0; c < cookies.length; c ++)
+      {
+         Cookie k = cookies[c];
+         if( k.getName().equalsIgnoreCase("JSESSIONID") )
+            sessionID = k.getValue();
+      }
+      getLog().debug("Saw JSESSIONID="+sessionID);
 
+      // Submit the login form
+      PostMethod formPost = new PostMethod(baseURLNoAuth+"war1/j_security_check");
+      formPost.addRequestHeader("Referer", baseURLNoAuth+"war1/login.html");
+      formPost.addParameter("j_username", "jduke");
+      formPost.addParameter("j_password", "theduke");
+      responseCode = httpConn.executeMethod(formPost.getHostConfiguration(),
+         formPost, state);
+      String response = formPost.getStatusText();
+      getLog().debug("responseCode="+responseCode+", response="+response);
+      assertTrue("Saw HTTP_MOVED_TEMP("+responseCode+")",
+         responseCode == HttpURLConnection.HTTP_MOVED_TEMP);
+
+      //  Follow the redirect to the index.html page
+      Header location = formPost.getResponseHeader("Location");
+      String indexURI = location.getValue();
+      GetMethod war1Index = new GetMethod(indexURI);
+      responseCode = httpConn.executeMethod(war1Index.getHostConfiguration(),
+         war1Index, state);
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      body = war1Index.getResponseBodyAsString();
+      if( body.indexOf("j_security_check") > 0 )
+         fail("get of "+indexURI+" redirected to login page");
+
+      cookies = state.getCookies();
+      String ssoID = null;
+      for(int c = 0; c < cookies.length; c ++)
+      {
+         Cookie k = cookies[c];
+         if( k.getName().equalsIgnoreCase("JSESSIONIDSSO") )
+            ssoID = k.getValue();
       }
+      assertTrue("Saw JSESSIONIDSSO", ssoID != null);
+      getLog().debug("Saw JSESSIONIDSSO="+ssoID);
 
+      // Now try getting the war2 index using the JSESSIONIDSSO cookie 
+      GetMethod war2Index = new GetMethod(baseURLNoAuth+"war2/index.html");
+      responseCode = httpConn.executeMethod(war2Index.getHostConfiguration(),
+         war2Index, state);
+      response = war2Index.getStatusText();
+      getLog().debug("responseCode="+responseCode+", response="+response);
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      body = war2Index.getResponseBodyAsString();
+      getLog().debug("body: "+body);
+      if( body.indexOf("j_security_check") > 0 )
+         fail("get of /war2/index.html redirected to login page");
+
+      /* Access a secured servlet that calls a secured ejb in war2 to test
+      propagation of the SSO identity to the ejb container.
+      */
+      GetMethod war2Servlet = new GetMethod(baseURLNoAuth+"war2/EJBServlet");
+      responseCode = httpConn.executeMethod(war2Servlet.getHostConfiguration(),
+         war2Servlet, state);
+      response = war2Servlet.getStatusText();
+      getLog().debug("responseCode="+responseCode+", response="+response);
+      assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
+      body = war2Servlet.getResponseBodyAsString();
+      getLog().debug("body: "+body);
+      if( body.indexOf("j_security_check") > 0 )
+         fail("get of /war2/EJBServlet redirected to login page");
+   }
+
    /** One time setup for all SingleSignOnUnitTestCase unit tests
     */
    public static Test suite() throws Exception

Deleted: branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso/deploy/jbossweb-tomcat55.sar/context.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso/deploy/jbossweb-tomcat55.sar/context.xml	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso/deploy/jbossweb-tomcat55.sar/context.xml	2006-12-08 03:07:36 UTC (rev 58921)
@@ -1,13 +0,0 @@
-<!-- The contents of this file will be loaded for each web application -->
-<Context cookies="true" crossContext="true">
-   
-   <!-- We want a low processExpiresFrequency so we can have 
-        fast turnaround of expiration tests -->
-   <Manager pathname="" processExpiresFrequency="1"/>
-
-   <!-- Install an InstanceListener to handle the establishment of the run-as
-   role for servlet init/destroy events.
-   -->
-   <InstanceListener>org.jboss.web.tomcat.security.RunAsListener</InstanceListener>
-   
-</Context>

Deleted: branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso-cluster/deploy/jbossweb-tomcat55.sar/context.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso-cluster/deploy/jbossweb-tomcat55.sar/context.xml	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso-cluster/deploy/jbossweb-tomcat55.sar/context.xml	2006-12-08 03:07:36 UTC (rev 58921)
@@ -1,13 +0,0 @@
-<!-- The contents of this file will be loaded for each web application -->
-<Context cookies="true" crossContext="true">
-   
-   <!-- We want a low processExpiresFrequency so we can have 
-        fast turnaround of expiration tests -->
-   <Manager pathname="" processExpiresFrequency="1"/>
-
-   <!-- Install an InstanceListener to handle the establishment of the run-as
-   role for servlet init/destroy events.
-   -->
-   <InstanceListener>org.jboss.web.tomcat.security.RunAsListener</InstanceListener>
-   
-</Context>

Modified: branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso-cluster/deploy/jbossweb-tomcat55.sar/server.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso-cluster/deploy/jbossweb-tomcat55.sar/server.xml	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/test-configs/tomcat-sso-cluster/deploy/jbossweb-tomcat55.sar/server.xml	2006-12-08 03:07:36 UTC (rev 58921)
@@ -14,7 +14,7 @@
          enableLookups="false" redirectPort="8443" acceptCount="100"
          connectionTimeout="20000" disableUploadTimeout="true"/>
 
-      <Engine name="jboss.web" defaultHost="localhost" backgroundProcessorDelay="10">
+      <Engine name="jboss.web" defaultHost="localhost">
 
          <!-- The JAAS based authentication and authorization realm implementation
             - certificatePrincipal : the class name of the
@@ -32,7 +32,7 @@
                deployed to this host. Provides SSO across a cluster.
             -->
             <Valve className="org.jboss.web.tomcat.tc5.sso.ClusteredSingleSignOn"
-               debug="2" maxEmptyLife="11" processExpiresInterval="5"/>
+               debug="2" />
          
             <!-- Default context parameters -->
             <DefaultContext cookies="true" crossContext="true" override="true"/>

Deleted: branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/index.jsp
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/index.jsp	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/index.jsp	2006-12-08 03:07:36 UTC (rev 58921)
@@ -1,15 +0,0 @@
-<%
-   // Give the session a quick timeout so the timeout test can be short
-	session.setMaxInactiveInterval(5);
-%>
-
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-<html>
-<head>
-   <title>A Secure Web App</title>
-</head>
-
-<body>
-<h1>A Secure Web App</h1>
-</body>
-</html>

Deleted: branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/isValid.jsp
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/isValid.jsp	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/isValid.jsp	2006-12-08 03:07:36 UTC (rev 58921)
@@ -1 +0,0 @@
-<% response.setHeader("X-SessionValid", session.isValid()); %>
\ No newline at end of file

Modified: branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/web-sso-expire.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/web-sso-expire.xml	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/web-sso-expire.xml	2006-12-08 03:07:36 UTC (rev 58921)
@@ -5,7 +5,7 @@
 
 <web-app>
    <description>WebApp Integration Tests</description>
-	<!--distributable/-->
+	<distributable/>
    <servlet>
       <servlet-name>LogoutServlet</servlet-name>
       <servlet-class>org.jboss.test.web.servlets.LogoutServlet</servlet-class>
@@ -16,10 +16,6 @@
       <url-pattern>/Logout</url-pattern>
    </servlet-mapping>
 
-   <session-config>
-      <session-timeout>1</session-timeout>
-   </session-config>
-
    <security-constraint>
       <web-resource-collection>
          <web-resource-name>Restricted</web-resource-name>
@@ -32,6 +28,10 @@
       </auth-constraint>
    </security-constraint>
 
+   <session-config>
+      <session-timeout>1</session-timeout>
+   </session-config>
+
    <login-config>
       <auth-method>FORM</auth-method>
       <form-login-config>

Modified: branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossManager.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossManager.java	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/session/JBossManager.java	2006-12-08 03:07:36 UTC (rev 58921)
@@ -208,15 +208,6 @@
       return sessionIDGenerator_.getSessionId();
    }
 
-   /**
-    * Gets the JMX <code>ObjectName</code> under
-    * which our <code>TreeCache</code> is registered. 
-    */
-   public ObjectName getObjectName()
-   {
-      return objectName_;
-   }
-
    public boolean isUseLocalCache()
    {
       return useLocalCache_;

Modified: branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/ClusteredSingleSignOn.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/ClusteredSingleSignOn.java	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/ClusteredSingleSignOn.java	2006-12-08 03:07:36 UTC (rev 58921)
@@ -8,36 +8,22 @@
 
 
 import org.jboss.web.tomcat.tc5.Tomcat5;
-import org.jboss.web.tomcat.tc5.session.JBossManager;
 
 import java.io.IOException;
 import java.security.Principal;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
 
-import javax.management.ObjectName;
 import javax.servlet.ServletException;
 import javax.servlet.http.Cookie;
 
-import org.apache.catalina.Lifecycle;
-import org.apache.catalina.LifecycleEvent;
 import org.apache.catalina.LifecycleException;
-import org.apache.catalina.LifecycleListener;
-import org.apache.catalina.Manager;
 import org.apache.catalina.Session;
 import org.apache.catalina.Realm;
 import org.apache.catalina.SessionEvent;
 import org.apache.catalina.authenticator.Constants;
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.connector.Response;
-import org.apache.catalina.session.ManagerBase;
 
-import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
 
-
 /**
  * A <strong>Valve</strong> that supports a "single sign on" user experience,
  * where the security identity of a user who successfully authenticates to one
@@ -60,13 +46,8 @@
  */
 public class ClusteredSingleSignOn
    extends org.apache.catalina.authenticator.SingleSignOn
-   implements LifecycleListener
 {
-   /** By default we process expired SSOs no more often than once per minute */
-   public static final int DEFAULT_PROCESS_EXPIRES_INTERVAL = 60;
-   /** By default we let SSOs without active sessions live for 30 mins */
-   public static final int DEFAULT_MAX_EMPTY_LIFE = 1800;
-   
+
    // Override the superclass value
    static
    {
@@ -96,30 +77,6 @@
     */
    private String treeCacheName = Tomcat5.DEFAULT_CACHE_NAME;
 
-   /** Currently started Managers that have associated as session with an SSO */
-   private Set activeManagers = Collections.synchronizedSet(new HashSet());
-   
-   /** Max number of ms an SSO with no active sessions will be usable by a request */
-   private int maxEmptyLife = DEFAULT_MAX_EMPTY_LIFE * 1000;
-   
-   /** 
-    * Minimum number of ms since the last processExpires() run 
-    * before a new run is allowed.
-    */
-   private int processExpiresInterval = DEFAULT_PROCESS_EXPIRES_INTERVAL * 1000;
-   
-   /** Timestamp of the last processExpires() run */
-   private long lastProcessExpires = System.currentTimeMillis();
-   
-   /** 
-    * Map<String, Long> containing the ids of SSOs with no active sessions
-    * and the time at which they entered that state
-    */
-   private Map emptySSOs = new ConcurrentHashMap();
-   
-   /** Used for sync locking of processExpires runs */
-   private final Object mutex = new Object();
-
    // ------------------------------------------------------------- Properties
 
    /**
@@ -238,105 +195,7 @@
       }
    }
 
-   /**
-    * Gets the max number of seconds an SSO with no active sessions will be 
-    * usable by a request.
-    * 
-    * @return a non-negative number
-    * 
-    * @see #DEFAULT_MAX_EMPTY_LIFE    * 
-    * @see #setMaxEmptyLife() 
-    */
-   public int getMaxEmptyLife()
-   {
-      return (maxEmptyLife / 1000);
-   }
 
-
-   /**
-    * Sets the maximum number of seconds an SSO with no active sessions will be 
-    * usable by a request.
-    * <p>
-    * A positive value for this property allows a user to continue to use an SSO
-    * even after all the sessions associated with it have been expired. It does not
-    * keep an SSO alive if a session associated with it has been invalidated due to 
-    * an <code>HttpSession.invalidate()</code> call.
-    * </p>
-    * <p>
-    * The primary purpose of this property is to avoid the situation where a server
-    * on which all of an SSO's sessions lives is shutdown, thus expiring all the
-    * sessions and causing the invalidation of the SSO. A positive value for this
-    * property would give the user an opportunity to fail over to another server
-    * and maintain the SSO.
-    * </p>
-    * 
-    * @param maxEmptyLife a non-negative number
-    * 
-    * @throws IllegalArgumentException if <code>maxEmptyLife < 0</code>
-    */
-   public void setMaxEmptyLife(int maxEmptyLife)
-   {
-      if (maxEmptyLife < 0)
-         throw new IllegalArgumentException("maxEmptyLife must be >= 0");
-      
-      this.maxEmptyLife = maxEmptyLife * 1000;
-   }
-
-
-   /**
-    * Gets the minimum number of seconds since the start of the last check for overaged
-    * SSO's with no active sessions before a new run is allowed.
-    * 
-    * @return a positive number
-    * 
-    * @see #DEFAULT_PROCESS_EXPIRES_INTERVAL
-    * @see #setMaxEmptyLife() 
-    * @see #setProcessExpiresInterval(int)
-    */
-   public int getProcessExpiresInterval()
-   {
-      return processExpiresInterval / 1000;
-   }
-
-   /**
-    * Sets the minimum number of seconds since the start of the last check for overaged
-    * SSO's with no active sessions before a new run is allowed.  During this check,
-    * any such overaged SSOs will be invalidated. 
-    * <p>
-    * Note that setting this value does not imply that a check will be performed
-    * every <code>processExpiresInterval</code> seconds, only that it will not
-    * be performed more often than that.
-    * </p>
-    * 
-    * @param processExpiresInterval a non-negative number. <code>0</code> means
-    *                               the overage check can be performed whenever
-    *                               the container wishes to.
-    *                               
-    * @throws IllegalArgumentException if <code>processExpiresInterval < 1</code>
-    * 
-    * @see #setMaxEmptyLife()
-    */
-   public void setProcessExpiresInterval(int processExpiresInterval)
-   {
-      if (processExpiresInterval < 0)
-         throw new IllegalArgumentException("processExpiresInterval must be >= 0");
-      
-      this.processExpiresInterval = processExpiresInterval * 1000;
-   }
-
-
-   /**
-    * Gets the timestamp of the start of the last check for overaged
-    * SSO's with no active sessions.
-    * 
-    * @see #setProcessExpiresInterval(int)
-    */
-   public long getLastProcessExpires()
-   {
-      return lastProcessExpires;
-   }
-
-
    // ------------------------------------------------------ Lifecycle Methods
 
 
@@ -433,112 +292,25 @@
       if (ssoId == null)
          return;
 
-      try
+      // Was the session destroyed as the result of a timeout?
+      // If so, we'll just remove the expired session from the
+      // SSO.  If the session was logged out, we'll log out
+      // of all sessions associated with the SSO.
+      if ((session.getMaxInactiveInterval() > 0)
+         && (System.currentTimeMillis() - session.getLastAccessedTime() >=
+         session.getMaxInactiveInterval() * 1000))
       {
-         // Was the session destroyed as the result of a timeout or
-         // the undeployment of the containing webapp?
-         // If so, we'll just remove the expired session from the
-         // SSO.  If the session was logged out, we'll log out
-         // of all sessions associated with the SSO.
-         if (isSessionTimedOut(session) || isManagerStopped(session))
-         {
-            removeSession(ssoId, session);
-
-            // Quite poor.  We hijack the caller thread (the Tomcat background thread)
-            // to do our cleanup of expired sessions
-            processExpires();
-         }
-         else
-         {
-            // The session was logged out.
-            logout(ssoId);
-         }
+         removeSession(ssoId, session);
       }
-      catch (Exception e)
+      else
       {
-         // Don't propagate back to the webapp; we don't want to disrupt
-         // the session expiration process
-         getContainer().getLogger().error("Caught exception updating SSO " + ssoId +
-                                          " following destruction of session " +
-                                          session.getId(), e);
+         // The session was logged out.
+         logout(ssoId);
       }
-   }
 
-   private boolean isSessionTimedOut(Session session)
-   {
-      return (session.getMaxInactiveInterval() > 0)
-               && (System.currentTimeMillis() - session.getLastAccessedTime() >=
-                  session.getMaxInactiveInterval() * 1000);
    }
 
-   private boolean isManagerStopped(Session session)
-   {
-      boolean stopped = false;
-      
-      Manager manager = session.getManager();
-      
-      if (manager instanceof ManagerBase)
-      {
-         ObjectName mgrName = ((ManagerBase)manager).getObjectName();
-         stopped = (!activeManagers.contains(mgrName));
-      }
-      else if (manager instanceof JBossManager)
-      {
-         ObjectName mgrName = ((JBossManager)manager).getObjectName();
-         stopped = (!activeManagers.contains(mgrName));
-      }
-      else if (manager instanceof Lifecycle)
-      {
-         stopped = (!activeManagers.contains(manager));
-      }
-      // else we have no way to tell, so assume not
-      
-      return stopped;
-   }
 
-   // ----------------------------------------------  LifecycleListener Methods
-
-
-   public void lifecycleEvent(LifecycleEvent event)
-   {
-      String type = event.getType();
-      if (Lifecycle.BEFORE_STOP_EVENT.equals(type) 
-            || Lifecycle.STOP_EVENT.equals(type) 
-            || Lifecycle.AFTER_STOP_EVENT.equals(type))
-      {
-         Lifecycle source = event.getLifecycle();
-         boolean removed;
-         if (source instanceof ManagerBase)
-         {
-            removed = activeManagers.remove(((ManagerBase)source).getObjectName());
-         }
-         else if (source instanceof JBossManager)
-         {
-            removed = activeManagers.remove(((JBossManager)source).getObjectName());
-         }
-         else
-         {
-            removed = activeManagers.remove(source);
-         }
-         
-         if (removed)
-         {
-            source.removeLifecycleListener(this);
-            
-            if (getContainer().getLogger().isDebugEnabled())
-            {
-                getContainer().getLogger().debug("ClusteredSSO: removed " +
-                        "stopped manager " + source.toString());
-            }
-         }
-         
-         // TODO consider getting the sessions and removing any from our sso's
-         // Idea is to cleanup after managers that don't destroy sessions
-         
-      }      
-   }
-   
-
    // ---------------------------------------------------------- Valve Methods
 
 
@@ -596,11 +368,10 @@
       }
 
       // Look up the cached Principal associated with this cookie value
-      String ssoId = cookie.getValue();
       if (getContainer().getLogger().isDebugEnabled())
-          getContainer().getLogger().debug(" Checking for cached principal for " + ssoId);
+          getContainer().getLogger().debug(" Checking for cached principal for " + cookie.getValue());
       SingleSignOnEntry entry = getSingleSignOnEntry(cookie.getValue());
-      if (entry != null && isValid(ssoId, entry))
+      if (entry != null)
       {
          Principal ssoPrinc = entry.getPrincipal();
          // have to deal with the fact that the entry may not have an
@@ -662,48 +433,9 @@
          reverse.put(session, ssoId);
       }
 
-      // If we made a change, track the manager and notify any cluster
-      if (added)
-      {
-         Manager manager = session.getManager();
-         
-         // Prefer to cache an ObjectName to avoid risk of leaking a manager,
-         // so if the manager exposes one, use it
-         Object mgrKey = null;
-         if (manager instanceof ManagerBase)
-         {            
-            mgrKey = ((ManagerBase)manager).getObjectName();
-         }
-         else if (manager instanceof JBossManager)
-         {
-            mgrKey = ((JBossManager)manager).getObjectName();
-         }
-         else if (manager instanceof Lifecycle)
-         {
-            mgrKey = manager;
-         }
-         else {
-            getContainer().getLogger().warn("Manager for session " + 
-                      session.getId() +
-                      " does not implement Lifecycle; web app shutdown may " +
-                      " lead to incorrect SSO invalidations");
-         }
-         
-         if (mgrKey != null)
-         {
-            synchronized (activeManagers)
-            {
-               if (!activeManagers.contains(mgrKey))
-               {
-                  activeManagers.add(mgrKey);
-                  ((Lifecycle) manager).addLifecycleListener(this);
-               }
-            }
-         }
-         
-         if (ssoClusterManager != null)         
-            ssoClusterManager.addSession(ssoId, session);
-      }
+      // If we made a change, notify any cluster
+      if (added && ssoClusterManager != null)
+         ssoClusterManager.addSession(ssoId, session);
    }
 
 
@@ -758,11 +490,6 @@
       if (getContainer().getLogger().isDebugEnabled())
           getContainer().getLogger().debug("Deregistering sso id '" + ssoId + "'");
 
-      
-      // It's possible we don't have the SSO locally but it's in
-      // the emptySSOs map; if so remove it
-      emptySSOs.remove(ssoId);
-      
       // Look up and remove the corresponding SingleSignOnEntry
       SingleSignOnEntry sso = null;
       synchronized (cache)
@@ -777,8 +504,8 @@
       Session sessions[] = sso.findSessions();
       for (int i = 0; i < sessions.length; i++)
       {
-         if (getContainer().getLogger().isDebugEnabled())
-             getContainer().getLogger().debug(" Invalidating session " + sessions[i]);
+         if (getContainer().getLogger().isTraceEnabled())
+             getContainer().getLogger().trace(" Invalidating session " + sessions[i]);
          // Remove from reverse cache first to avoid recursion
          synchronized (reverse)
          {
@@ -950,12 +677,12 @@
          reverse.remove(session);
       }
 
-//      // If there are no sessions left in the SingleSignOnEntry,
-//      // deregister the entry.
-//      if (entry.getSessionCount() == 0)
-//      {
-//         deregister(ssoId);
-//      }
+      // If there are no sessions left in the SingleSignOnEntry,
+      // deregister the entry.
+      if (entry.getSessionCount() == 0)
+      {
+         deregister(ssoId);
+      }
    }
 
 
@@ -1119,35 +846,6 @@
       }
 
    }
-   
-   /**
-    * Callback from the SSOManager when it detects an SSO without
-    * any active sessions across the cluster
-    */
-   void notifySSOEmpty(String ssoId)
-   {
-      Object obj = emptySSOs.put(ssoId, new Long(System.currentTimeMillis()));
-      
-      if (obj == null && getContainer().getLogger().isDebugEnabled())
-      {
-         getContainer().getLogger().debug("Notified that SSO " + ssoId + " is empty");
-      }
-   }
-   
-   /**
-    * Callback from the SSOManager when it detects an SSO that
-    * has active sessions across the cluster
-    */
-   void notifySSONotEmpty(String ssoId)
-   {
-      Object obj = emptySSOs.remove(ssoId);
-      
-      if (obj != null && getContainer().getLogger().isDebugEnabled())
-      {
-         getContainer().getLogger().debug("Notified that SSO " + ssoId + 
-                                          " is no longer empty");
-      }
-   }
 
    
    // -------------------------------------------------------  Private Methods
@@ -1203,66 +901,5 @@
          }
       }
    }
-   
-   
-   private void processExpires()
-   {
-      long now = 0L;
-      synchronized (mutex)
-      {
-         now = System.currentTimeMillis();
-      
-         if (now - lastProcessExpires > processExpiresInterval)
-         {
-            lastProcessExpires = now;
-         }
-         else
-         {
-             return;
-         }
-      }
-      
-      clearExpiredSSOs(now);
-   }
-   
-   private synchronized void clearExpiredSSOs(long now)
-   {      
-      for (Iterator iter = emptySSOs.entrySet().iterator(); iter.hasNext();)
-      {
-         Map.Entry entry = (Map.Entry) iter.next();
-         if ( (now - ((Long) entry.getValue()).longValue()) > maxEmptyLife)
-         {
-            String ssoId = (String) entry.getKey();
-            if (getContainer().getLogger().isDebugEnabled())
-            {
-               getContainer().getLogger().debug("Invalidating expired SSO " + ssoId);
-            }
-            logout(ssoId);
-         }
-      }      
-   }
-   
-   private boolean isValid(String ssoId, SingleSignOnEntry entry)
-   {
-      boolean valid = true;
-      if (entry.getSessionCount() == 0)
-      {
-         Long expired = (Long) emptySSOs.get(ssoId);
-         if (expired != null 
-               && (System.currentTimeMillis() - expired.longValue()) > maxEmptyLife)
-         {
-            valid = false;
-            
-            if (getContainer().getLogger().isDebugEnabled())
-            {
-               getContainer().getLogger().debug("Invalidating expired SSO " + ssoId);
-            }
-            
-            logout(ssoId);
-         }
-      }
-      
-      return valid;
-   }
 
 }
\ No newline at end of file

Modified: branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/TreeCacheSSOClusterManager.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/TreeCacheSSOClusterManager.java	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/TreeCacheSSOClusterManager.java	2006-12-08 03:07:36 UTC (rev 58921)
@@ -1,29 +1,15 @@
 /*
- * JBoss, Home of Professional Open Source.
- * Copyright 2006, 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.
+ * JBoss, the OpenSource WebOS
  *
- * 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.
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
  */
 package org.jboss.web.tomcat.tc5.sso;
 
 import java.io.Serializable;
 import java.security.Principal;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.Set;
 
 import javax.management.MBeanServer;
@@ -105,19 +91,20 @@
    // -------------------------------------------------------  Instance Fields
    
    /**
-    * SSO id which the thread is currently storing to the cache
+    * List of SSO ids which this object is currently storing to the cache
     */
-   private ThreadLocal beingLocallyAdded = new ThreadLocal();
+   private LinkedList beingLocallyAdded = new LinkedList();
 
    /**
-    * SSO id which a thread is currently removing from the cache
+    * List of SSO ids which this object is currently removing from the cache
     */
-   private ThreadLocal beingLocallyRemoved = new ThreadLocal();
+   private LinkedList beingLocallyRemoved = new LinkedList();
 
    /**
-    * SSO id which the thread is deregistering due to removal on another node
+    * List of SSO ids which are being deregistered due to removal on another
+    * node
     */
-   private ThreadLocal beingRemotelyRemoved = new ThreadLocal();
+   private LinkedList beingRemotelyRemoved = new LinkedList();
 
    /**
     * ObjectName of the TreeCache
@@ -130,6 +117,12 @@
    private String cacheName = null;
 
    /**
+    * CredentialUpdater used to allow asynchronous updates of
+    * SSO credentials
+    */
+   private CredentialUpdater credentialUpdater = null;
+
+   /**
     * Transaction Manager
     */
    private TransactionManager tm = null;
@@ -174,11 +167,6 @@
     */
    private boolean missingCacheErrorLogged = false;
    
-   /**
-    * Our node's address in the cluster.
-    */
-   private Serializable localAddress = null;
-   
    // ----------------------------------------------------------  Constructors
 
    
@@ -189,21 +177,9 @@
    {
       // Find our MBeanServer
       server = MBeanServerLocator.locateJBoss();
-      if (server == null)
-         server = MBeanServerLocator.locate();
    }
-
    
-   /**
-    * Creates a new TreeCacheSSOClusterManager that works with the given
-    * MBeanServer.  This constructor is only intended for use in unit testing.
-    */
-   public TreeCacheSSOClusterManager(MBeanServer server)
-   {
-      this.server = server;
-   }
    
-   
    // ------------------------------------------------------------  Properties
   
    public String getCacheName()
@@ -240,7 +216,7 @@
          return;
       }
 
-      removeAsTreeCacheListener();
+      removeAsTreeCacheListener(cacheObjectName);
       this.tm = null;
       
       this.cacheObjectName = objectName;
@@ -262,11 +238,16 @@
                "before ClusteredSingleSignOn can handle requests");
          }
       }
+      else if (started)
+      {
+         // Confirm the cache has a transaction manager
+         // and fail if not found
+         findTransactionManager();
+      }
    }
    
    // -----------------------------------------------------  SSOClusterManager
 
-
    /**
     * Notify the cluster of the addition of a Session to an SSO session.
     *
@@ -280,8 +261,9 @@
          return;
       }
 
-      if (!checkTreeCacheAvailable())
+      if (false == isTreeCacheAvailable(false))
       {
+         logMissingCacheError();
          return;
       }
 
@@ -295,11 +277,6 @@
       boolean doTx = false;
       try
       {
-         // Confirm we have a transaction manager; if not get it from TreeCache
-         // failure to find will throw an IllegalStateException
-         if (tm == null)
-            configureFromCache();
-         
          // Don't do anything if there is already a transaction 
          // context associated with this thread.
          if(tm.getTransaction() == null)
@@ -309,7 +286,7 @@
             tm.begin();
          
          Set sessions = getSessionSet(fqn, true);
-         sessions.add(new SessionAddress(session.getId(), localAddress));
+         sessions.add(session.getId());
          putInTreeCache(fqn, sessions);
       }
       catch (Exception e)
@@ -319,7 +296,7 @@
             if(doTx)
                tm.setRollbackOnly();
          }
-         catch (Exception ignored)
+         catch (Exception x)
          {
          }
          String sessId = (session == null ? "NULL" : session.getId());
@@ -368,20 +345,23 @@
     */
    public void logout(String ssoId)
    {
-      if (!checkTreeCacheAvailable())
+      if (false == isTreeCacheAvailable(false))
       {
+         logMissingCacheError();
          return;
       }
       
       // Check whether we are already handling this removal 
-      if (ssoId.equals(beingLocallyRemoved.get()))
+      //synchronized (beingLocallyRemoved)
       {
-         return;
-      }         
-      
-      // Add this SSO to our list of in-process local removals so
-      // this.nodeRemoved() will ignore the removal
-      beingLocallyRemoved.set(ssoId);
+         if (beingLocallyRemoved.contains(ssoId))
+         {
+            return;
+         }         
+         // Add this SSO to our list of in-process local removals so
+         // this.nodeRemoved() will ignore the removal
+         beingLocallyRemoved.add(ssoId);
+      }
 
       if (log.isTraceEnabled())
       {
@@ -402,7 +382,10 @@
       }
       finally
       {
-         beingLocallyRemoved.set(null);
+         //synchronized (beingLocallyRemoved)
+         {
+            beingLocallyRemoved.remove(ssoId);
+         }
       }
    }
 
@@ -418,16 +401,20 @@
     */
    public SingleSignOnEntry lookup(String ssoId)
    {
-      if (!checkTreeCacheAvailable())
+      if (false == isTreeCacheAvailable(false))
       {
+         logMissingCacheError();
          return null;
       }
 
       SingleSignOnEntry entry = null;
       // Find the latest credential info from the cluster
       Fqn fqn = getCredentialsFqn(ssoId);
+      //UserTransaction tx = null;
       try
       {
+         //tx = getNewTransaction();
+         //tx.begin();
          SSOCredentials data = (SSOCredentials) getFromTreeCache(fqn);
          if (data != null)
          {
@@ -436,9 +423,20 @@
                data.getUsername(),
                data.getPassword());
          }
+         //tx.commit();
       }
       catch (Exception e)
       {
+         /*
+         if (tx != null)
+         {
+            try
+            {
+               tx.rollback();
+            }
+            catch (Exception x) {}
+         }
+         */
          log.error("caught exception looking up SSOCredentials for SSO id " +
             ssoId, e);
       }
@@ -458,8 +456,9 @@
    public void register(String ssoId, String authType,
       String username, String password)
    {
-      if (!checkTreeCacheAvailable())
+      if (false == isTreeCacheAvailable(false))
       {
+         logMissingCacheError();
          return;
       }
 
@@ -480,32 +479,33 @@
     */
    public void removeSession(String ssoId, Session session)
    {
-      if (ssoId == null || session == null)
+      if (false == isTreeCacheAvailable(false))
       {
+         logMissingCacheError();
          return;
       }
       
-      if (!checkTreeCacheAvailable())
-      {
-         return;
-      }
-      
       // Check that this session removal is not due to our own deregistration
       // of an SSO following receipt of a nodeRemoved() call
-      if (ssoId.equals(beingRemotelyRemoved.get()))
+      //synchronized(beingRemotelyRemoved)
       {
-         return;
+         if (beingRemotelyRemoved.contains(ssoId))
+         {
+            return;
+         }
       }
-      
+
+      if (log.isTraceEnabled())
+      {
+         log.trace("removeSession(): removing Session " + session.getId() +
+            " from cached session set for SSO " + ssoId);
+      }
+
       Fqn fqn = getSessionsFqn(ssoId);
       boolean doTx = false;
-//      boolean removing = false;
+      boolean removing = false;
       try
       {
-         // Confirm we have a transaction manager; if not get it from TreeCache
-         // failure to find will throw an IllegalStateException
-         if (tm == null)
-            configureFromCache();
 
          // Don't do anything if there is already a transaction 
          // context associated with this thread.
@@ -518,29 +518,23 @@
          Set sessions = getSessionSet(fqn, false);
          if (sessions != null)
          {
-            sessions.remove(new SessionAddress(session.getId(), localAddress));
-
-            if (log.isTraceEnabled())
+            sessions.remove(session.getId());
+            if (sessions.size() == 0)
             {
-               log.trace("removed session " + session.getId() +
-                  " from cached session set for SSO " + ssoId + " -- " +
-                  sessions.size() + " sessions remain");
+               // Add this SSO to our list of in-process local removals so
+               // this.nodeRemoved() will ignore the removal
+               //synchronized (beingLocallyRemoved)
+               {
+                  beingLocallyRemoved.add(ssoId);
+               }
+               removing = true;
+               // No sessions left; remove node
+               removeFromTreeCache(getSingleSignOnFqn(ssoId));
             }
-            
-//            if (sessions.size() == 0)
-//            {               
-//               // No sessions left; remove node
-//               
-//               // Add this SSO to our list of in-process local removals so
-//               // this.nodeRemoved() will ignore the removal
-//               removing = true;
-//               beingLocallyRemoved.set(ssoId);
-//               removeFromTreeCache(getSingleSignOnFqn(ssoId));
-//            }
-//            else
-//            {
+            else
+            {
                putInTreeCache(fqn, sessions);
-//            }
+            }
          }
       }
       catch (Exception e)
@@ -560,18 +554,21 @@
       }
       finally
       {
-//         try
-//         {
-//            if (removing)
-//            {
-//               beingLocallyRemoved.set(null);
-//            }
-//         }
-//         finally
-//         {
+         try
+         {
+            if (removing)
+            {
+               //synchronized (beingLocallyRemoved)
+               {
+                  beingLocallyRemoved.remove(ssoId);
+               }
+            }
+         }
+         finally
+         {
             if (doTx)
                endTransaction();
-//         }
+         }
       }
    }
 
@@ -589,8 +586,9 @@
    public void updateCredentials(String ssoId, String authType,
       String username, String password)
    {
-      if (!checkTreeCacheAvailable())
+      if (false == isTreeCacheAvailable(false))
       {
+         logMissingCacheError();
          return;
       }
 
@@ -662,17 +660,20 @@
    public void nodeRemoved(Fqn fqn)
    {
       String ssoId = getIdFromFqn(fqn);
-      
-      if (ssoId == null)
-         return;
 
       // Ignore messages generated by our own activity
-      if (ssoId.equals(beingLocallyRemoved.get()))
+      //synchronized(beingLocallyRemoved)
       {
-         return;
+         if (beingLocallyRemoved.contains(ssoId))
+         {
+            return;
+         }
       }
       
-      beingRemotelyRemoved.set(ssoId);
+      //synchronized (beingRemotelyRemoved)
+      {
+         beingRemotelyRemoved.add(ssoId);
+      }
 
       try
       {
@@ -685,7 +686,10 @@
       }
       finally
       {
-         beingRemotelyRemoved.set(null);
+         //synchronized(beingRemotelyRemoved)
+         {
+            beingRemotelyRemoved.remove(ssoId);
+         }
       }
 
    }
@@ -708,30 +712,21 @@
     */
    public void nodeModified(Fqn fqn)
    {
-      String type = getTypeFromFqn(fqn);
-      if (CREDENTIALS.equals(type))
+      // We are only interested in changes to the CREDENTIALS node
+      if (CREDENTIALS.equals(getTypeFromFqn(fqn)) == false)
       {
-         handleCredentialUpdate(fqn);
+         return;
       }
-      else if (SESSIONS.equals(type))
-      {
-         handleSessionSetChange(fqn);
-      }
-   }
 
+      String ssoId = getIdFromFqn(fqn);
 
-   /**
-    *  
-    * @param fqn an Fqn that points to the CREDENTIALS node of an SSO
-    */
-   private void handleCredentialUpdate(Fqn fqn)
-   {
-      String ssoId = getIdFromFqn(fqn); // won't be null per the API contract
-
       // Ignore invocations that come as a result of our additions
-      if (ssoId.equals(beingLocallyAdded.get()))
+      //synchronized(beingLocallyAdded)
       {
-         return;
+         if (beingLocallyAdded.contains(ssoId))
+         {
+            return;
+         }
       }
 
       SingleSignOnEntry sso = ssoValve.localLookup(ssoId);
@@ -747,72 +742,11 @@
       }
 
       // Put this SSO in the queue of those to be updated
-//      credentialUpdater.enqueue(sso, ssoId);
-      try
-      {
-         SSOCredentials data = (SSOCredentials) getFromTreeCache(fqn);
-         if (data != null)
-         {
-            // We want to release our read lock quickly, so get the needed
-            // data from the cache, commit the tx, and then use the data
-            String authType = data.getAuthType();
-            String username = data.getUsername();
-            String password = data.getPassword();
+      credentialUpdater.enqueue(sso, ssoId);
+   }
 
-            if (log.isTraceEnabled())
-            {
-               log.trace("CredentialUpdater: Updating credentials for SSO " + sso);
-            }
 
-            synchronized (sso)
-            {
-               // Use the existing principal
-               Principal p = sso.getPrincipal();
-               sso.updateCredentials(p, authType, username, password);
-            }
-         }
-      }
-      catch (Exception e)
-      {
-         log.error("failed to update credentials for SSO " + ssoId, e);
-      }
-   }
-   
    /**
-    *  
-    * @param fqn an Fqn that points to the SESSIONS node of an SSO
-    */
-   private void handleSessionSetChange(Fqn fqn)
-   {
-      // Here we *want* to handle local activity as well as remote,
-      // as the distributed cache set of sessions is the only
-      // complete representation
-      
-      String ssoId = getIdFromFqn(fqn);
-      try      
-      {
-         Set sessions = (Set) getFromTreeCache(fqn);
-         if (sessions == null)
-         {
-            // don't think we'd get this event; 
-            // in any case we don't deal with this
-         }
-         else if (sessions.size() == 0)
-         {
-            ssoValve.notifySSOEmpty(ssoId);            
-         }
-         else
-         {
-            ssoValve.notifySSONotEmpty(ssoId);
-         }
-      }
-      catch (Exception e)
-      {
-         log.error("failed in check for empty SSO " + ssoId, e);
-      }
-   }
-
-   /**
     * Does nothing
     */
    public void viewChange(View new_view)
@@ -884,12 +818,15 @@
          throw new LifecycleException
             ("TreeCacheSSOClusterManager already Started");
       }
+      
+      // Start the thread we use to clear nodeModified events
+      credentialUpdater = new CredentialUpdater();
 
       try 
       {
-         if (isTreeCacheAvailable(true))
+         if (tm == null && isTreeCacheAvailable(true))
          {
-            integrateWithCache();
+            findTransactionManager();
          }
       }
       catch (Exception e)
@@ -922,7 +859,9 @@
          throw new LifecycleException
             ("TreeCacheSSOClusterManager not Started");
       }
-      
+
+      credentialUpdater.stop();
+
       started = false;
 
       // Notify our interested LifecycleListeners
@@ -964,12 +903,7 @@
     */
    private String getIdFromFqn(Fqn fqn)
    {
-      String id = null;
-      if (fqn.size() > 1 && SSO.equals(fqn.get(0)))
-      {
-         id = (String) fqn.get(1);
-      }
-      return id;
+      return (String) fqn.get(1);
    }
 
    private Set getSessionSet(Fqn fqn, boolean create)
@@ -988,30 +922,25 @@
     * object.
     *
     * @param fqn the Fully Qualified Name used by TreeCache
-    * @return the 3rd in the Fqn -- either
-    *         {@link #CREDENTIALS CREDENTIALS} or {@link #SESSIONS SESSIONS},
-    *         or <code>null</code> if <code>fqn</code> is not for an SSO.
+    * @return the last element in the Fqn -- either
+    *         {@link #CREDENTIALS CREDENTIALS} or {@link #SESSIONS SESSIONS}.
     */
    private String getTypeFromFqn(Fqn fqn)
    {
-      String type = null;
-      if (fqn.size() > 2 && SSO.equals(fqn.get(0)))
-         type = (String) fqn.get(2);
-      return type;
+      return (String) fqn.get(fqn.size() - 1);
    }
    
    /**
-    * Obtains needed configuration information from the tree cache.
     * Invokes "getTransactionManager" on the tree cache, caching the
     * result or throwing an IllegalStateException if one is not found.
-    * Also get our cluster-wide unique local address from the cache.
     * 
     * @throws Exception
     */
-   private void configureFromCache() throws Exception
-   {  
-      tm = (TransactionManager) server.getAttribute(getCacheObjectName(), 
-                                                    "TransactionManager");
+   private void findTransactionManager() throws Exception
+   {
+      tm = (TransactionManager) server.invoke(getCacheObjectName(), 
+                                              "getTransactionManager", 
+                                              null, new String[] {});                  
 
       if (tm == null) 
       {
@@ -1020,15 +949,6 @@
                                          "configure a valid " +
                                          "TransactionManagerLookupClass");
       }
-      
-      // Find out our address
-      Object address = server.getAttribute(cacheObjectName, "LocalAddress");
-      // In reality this is a JGroups IpAddress, but the API says
-      // "Object" so we have to be sure its Serializable
-      if (address instanceof Serializable)
-         localAddress = (Serializable) address;
-      else
-         localAddress = address.toString();
    }
    
 
@@ -1074,19 +994,13 @@
             {
                try
                {
-                  // If Tomcat5 overrides the default cache name, it will do so
-                  // after we are started. So we need to configure ourself here
-                  // and throw an exception if there is a problem. Having this
-                  // here also allows us to recover if our cache is started
-                  // after we are
-                  if (started)
-                     integrateWithCache();
+                  registerAsTreeCacheListener(cacheObjectName);
                   setMissingCacheErrorLogged(false);
                }
                catch (Exception e)
                {
-                  log.error("Caught exception configuring from cache " +
-                            cacheObjectName, e);
+                  log.error("Caught exception registering as listener to " +
+                     cacheObjectName, e);
                   available = false;
                }
             }
@@ -1095,14 +1009,6 @@
       }
       return treeCacheAvailable;
    }
-   
-   private boolean checkTreeCacheAvailable()
-   {
-      boolean avail = isTreeCacheAvailable(false);
-      if (!avail)
-         logMissingCacheError();
-      return avail;
-   }
 
    private void putInTreeCache(Fqn fqn, Object data) throws Exception
    {
@@ -1110,26 +1016,16 @@
       server.invoke(getCacheObjectName(), "put", args, PUT_SIGNATURE);
    }
 
-   private void integrateWithCache() throws Exception
-   {
-      // Ensure we have a transaction manager and a cluster-wide unique address
-      configureFromCache();
-      
-      registerAsTreeCacheListener();
-      
-      log.debug("Successfully integrated with cache service " + cacheObjectName);
-   }
-
-
    /**
     * Invokes an operation on the JMX server to register ourself as a
     * listener on the TreeCache service.
     *
     * @throws Exception
     */
-   private void registerAsTreeCacheListener() throws Exception
+   private void registerAsTreeCacheListener(ObjectName listenTo)
+      throws Exception
    {
-      server.invoke(cacheObjectName, "addTreeCacheListener",
+      server.invoke(listenTo, "addTreeCacheListener",
          new Object[]{this},
          new String[]{TreeCacheListener.class.getName()});
       registeredAsListener = true;
@@ -1142,11 +1038,12 @@
     *
     * @throws Exception
     */
-   private void removeAsTreeCacheListener() throws Exception
+   private void removeAsTreeCacheListener(ObjectName removeFrom)
+      throws Exception
    {
-      if (registeredAsListener && cacheObjectName != null)
+      if (registeredAsListener && removeFrom != null)
       {
-         server.invoke(cacheObjectName, "removeTreeCacheListener",
+         server.invoke(removeFrom, "removeTreeCacheListener",
             new Object[]{this},
             new String[]{TreeCacheListener.class.getName()});
       }
@@ -1179,23 +1076,41 @@
       String password)
    {
       SSOCredentials data = new SSOCredentials(authType, username, password);
-      
       // Add this SSO to our list of in-process local adds so
       // this.nodeModified() will ignore the addition
-      beingLocallyAdded.set(ssoId);
-      
+      //synchronized (beingLocallyAdded)
+      {
+         beingLocallyAdded.add(ssoId);
+      }
+      //UserTransaction tx = null;
       try
       {
+         //tx = getNewTransaction();
+         //tx.begin();
          putInTreeCache(getCredentialsFqn(ssoId), data);
+         //tx.commit();
       }
       catch (Exception e)
       {
+         /*
+         if (tx != null)
+         {
+            try
+            {
+               tx.rollback();
+            }
+            catch (Exception x) {}
+         }
+         */
          log.error("Exception attempting to add TreeCache nodes for SSO " +
             ssoId, e);
       }
       finally
       {
-         beingLocallyAdded.set(null);
+         //synchronized (beingLocallyAdded)
+         {
+            beingLocallyAdded.remove(ssoId);
+         }
       }
    }
 
@@ -1229,6 +1144,219 @@
       }
    }
 
+   // ---------------------------------------------------------  Inner Classes
+
+   /**
+    * Spawns a thread to handle updates of credentials
+    * 
+    * TODO  This was added in the early days of JBossCache when invoking
+    *       a get() on a node in the middle of a TreeCacheListener 
+    *       notification would cause a deadlock.  Should not be necessary now.
+    */
+   private class CredentialUpdater
+      implements Runnable
+   {
+      private HashSet awaitingUpdate = new HashSet();
+      private Thread updateThread;
+      private boolean updateThreadSleeping = false;
+      private boolean queueEmpty = true;
+      private boolean stopped = false;
+
+      private CredentialUpdater()
+      {
+         updateThread =
+            new Thread(this, "SSOClusterManager.CredentialUpdater");
+         updateThread.setDaemon(true);
+         updateThread.start();
+      }
+
+      // ------------------------------------------------------  Runnable
+
+      public void run()
+      {
+         while (!stopped)
+         {
+            // Ensure that no runtime exceptions kill this thread
+            try
+            {
+               updateThreadSleeping = false;
+               // Get the current list of ids awaiting processing
+               SSOWrapper[] ssos = null;
+               synchronized (awaitingUpdate)
+               {
+                  ssos = new SSOWrapper[awaitingUpdate.size()];
+                  ssos = (SSOWrapper[]) awaitingUpdate.toArray(ssos);
+                  awaitingUpdate.clear();
+                  queueEmpty = true;
+               }
+
+               // Handle the credential update
+               for (int i = 0; i < ssos.length; i++)
+               {
+                  processUpdate(ssos[i]);
+               }
+
+               // Wait for another invocation of enqueue().  But,
+               // first have to check in case it was invoked while we
+               // were processing the previous bunch
+               if (queueEmpty)
+               {
+                  try
+                  {
+                     // There is a slight possibility here of a race condition
+                     // between the above check for queueEmpty and another 
+                     // thread accessing enqueue()'s check of 
+                     // updateThreadSleeping.  If this happens, the update
+                     // will not be processed by the local node until the
+                     // updateThread wakes up (30 secs) or is interrupted by 
+                     // another update.  This situation is quite unlikely,
+                     // as updates only happen 1) in odd configurations where
+                     // CLIENT-CERT authentication is used for some apps and 
+                     // FORM or BASIC are used for others and 2) the user has
+                     // first logged in to a CLIENT-CERT app and later logs in
+                     // to a FORM/BASIC app.  If such a race condition were to 
+                     // occur, the only downside would be that if the user 
+                     // accessed a FORM/BASIC app on this node before the local
+                     // update is processed, they would have to log in again.
+                     updateThreadSleeping = true;
+                     updateThread.sleep(30000);
+                  }
+                  catch (InterruptedException e)
+                  {
+                     if (log.isTraceEnabled())
+                     {
+                        log.trace("CredentialUpdater: interrupted");
+                     }
+                     // process the next bunch
+                  }
+               }
+               else if (log.isTraceEnabled())
+               {
+                  log.trace("CredentialUpdater: more updates added while " +
+                     "handling existing updates");
+               }
+            }
+            catch (Exception e)
+            {
+               log.error("CredentialUpdater thread caught an exception", e);
+            }
+         }
+      }
+
+      // -------------------------------------------------  Private Methods
+
+      /**
+       * Adds an SSO id to the set of those awaiting credential updating, and
+       * interrupts the update handler thread to notify it of the addition.
+       *
+       * @param sso the id of the SSO session whose local credentials
+       *            are to be updated
+       */
+      private void enqueue(SingleSignOnEntry sso, String ssoId)
+      {
+         synchronized (awaitingUpdate)
+         {
+            awaitingUpdate.add(new SSOWrapper(sso, ssoId));
+            queueEmpty = false;
+         }
+         // Interrupt the update thread so it wakes up to process
+         // the enqueued update.  Only do this if its "sleeping" flag
+         // is set so we don't inadvertently interrupt it while its
+         // blocked waiting for a TreeCache lock to clear
+         if (updateThreadSleeping)
+         {
+            updateThread.interrupt();
+         }
+      }
+
+      private void processUpdate(SSOWrapper wrapper)
+      {
+         if (wrapper.sso.getCanReauthenticate())
+         {
+            // No need to update
+            return;
+         }
+
+         Fqn fqn = getCredentialsFqn(wrapper.id);
+         //UserTransaction tx = null;
+         try
+         {
+            //tx = getNewTransaction();
+            //tx.begin();
+            SSOCredentials data = (SSOCredentials) getFromTreeCache(fqn);
+            if (data != null)
+            {
+               // We want to release our read lock quickly, so get the needed
+               // data from the cache, commit the tx, and then use the data
+               String authType = data.getAuthType();
+               String username = data.getUsername();
+               String password = data.getPassword();
+               //tx.commit();
+
+               if (log.isTraceEnabled())
+               {
+                  log.trace("CredentialUpdater: Updating credentials for SSO " +
+                     wrapper.sso);
+               }
+
+               synchronized (wrapper.sso)
+               {
+                  // Use the existing principal
+                  Principal p = wrapper.sso.getPrincipal();
+                  wrapper.sso.updateCredentials(p, authType, username, password);
+               }
+            }
+            /*
+            else
+            {
+               tx.commit();
+            }
+            */
+
+         }
+         catch (Exception e)
+         {
+            /*
+            if (tx != null)
+            {
+               try
+               {
+                  tx.rollback();
+               }
+               catch (Exception x) {}
+            }
+            */
+            log.error("Exception attempting to get SSOCredentials from " +
+               "TreeCache node " + fqn.toString(), e);
+         }
+      }
+
+      /**
+       * Stops the update handler thread.
+       */
+      private void stop()
+      {
+         stopped = true;
+      }
+
+   }  // end CredentialUpdater
+
+
+   /**
+    * Wrapper class that holds a SingleSignOnEntry and its id
+    */
+   private class SSOWrapper
+   {
+      private SingleSignOnEntry sso = null;
+      private String id = null;
+
+      private SSOWrapper(SingleSignOnEntry entry, String ssoId)
+      {
+         this.sso = entry;
+         this.id = ssoId;
+      }
+   }
+
    // ---------------------------------------------------------  Outer Classes
 
    /**
@@ -1293,135 +1421,6 @@
       }
 
    } // end SSOCredentials
-   
-   static class SessionAddress implements Serializable
-   {
-      /** The serialVersionUID */
-      private static final long serialVersionUID = -3702932999380140004L;
-      
-      Serializable address;
-      String sessionId;
-      
-      SessionAddress(String sessionId, Serializable address)
-      {
-         this.sessionId = sessionId;
-         this.address   = address;
-      }
 
-      public boolean equals(Object obj)
-      {
-         if (this == obj)
-            return true;
-         
-         if (!(obj instanceof SessionAddress))
-            return false;
-         
-         SessionAddress other = (SessionAddress) obj;
-         
-         return (sessionId.equals(other.sessionId) 
-                 && address.equals(other.address));
-      }
-
-      public int hashCode()
-      {
-         int total = (19 * 43) + sessionId.hashCode();
-         return ((total * 43) + address.hashCode());
-      }
-      
-      
-   }
-
-// DISABLED UNTIL 4.0.6.CR1
-//   /**
-//    * Runnable that's run when the removal of a node from the cluster has been detected. 
-//    * Removes any SessionAddress objects associated with dead members from the
-//    * session set of each SSO.  Operates locally only so each node can independently clean
-//    * its SSOs without concern about replication lock conflicts.
-//    */
-//   private class DeadMemberCleaner implements Runnable
-//   {    
-//      public void run()
-//      {
-//         synchronized (cleanupMutex)
-//         {
-//            try
-//            {      
-//               // Ensure we have a TransactionManager
-//               if (tm == null)
-//                  configureFromCache();
-//               
-//               Set ids = getSSOIds();
-//               
-//               for (Iterator iter = ids.iterator(); iter.hasNext();)
-//               {
-//                  cleanDeadMembersFromSSO((String) iter.next());
-//                  
-//               }
-//            }
-//            catch (Exception e)
-//            {
-//               log.error("Caught exception cleaning sessions from dead cluster members from SSOs ", e);
-//            }
-//         }
-//      }
-//      
-//      private void cleanDeadMembersFromSSO(String ssoId)
-//      {
-//         Fqn fqn = getSessionsFqn(ssoId);
-//         boolean doTx = false;
-//         try
-//         {
-//            // Don't start tx if there is already one associated with this thread.
-//            if(tm.getTransaction() == null)
-//               doTx = true;
-//
-//            if(doTx)
-//               tm.begin();
-//            
-//            Set sessions = getSessionSet(fqn, false, true);
-//            if (sessions != null && sessions.size() > 0)
-//            {
-//               boolean changed = false;
-//               for (Iterator iter = sessions.iterator(); iter.hasNext();)
-//               {
-//                  SessionAddress session = (SessionAddress) iter.next();
-//                  if (!currentView.containsMember((Address) session.address))
-//                  {
-//                     iter.remove();
-//                     changed = true;
-//                  }
-//               }
-//               
-//               if (changed)
-//               {                  
-//                  if (sessions.size() == 0)
-//                  {
-//                     ssoValve.notifySSOEmpty(ssoId);
-//                  }
-//                  
-//                  putInTreeCache(fqn, sessions, true);
-//               }
-//            }
-//         }
-//         catch (Exception e)
-//         {
-//            try
-//            {
-//               if(doTx)
-//                  tm.setRollbackOnly();
-//            }
-//            catch (Exception ignored)
-//            {
-//            }
-//            log.error("caught exception cleaning dead members from SSO " + ssoId, e);
-//         }
-//         finally
-//         {
-//            if (doTx)
-//               endTransaction();
-//         }         
-//      }
-//   }
-
 } // end TreeCacheSSOClusterManager
 

Modified: branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/mbeans-descriptors.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/mbeans-descriptors.xml	2006-12-08 01:43:14 UTC (rev 58920)
+++ branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/mbeans-descriptors.xml	2006-12-08 03:07:36 UTC (rev 58921)
@@ -20,19 +20,6 @@
          description="Should we attempt to reauthenticate each request against the security Realm?"
          type="boolean"/>
 
-      <attribute name="maxEmptyLife"
-         description="The maximum number of seconds an SSO with no active sessions will be usable by a request"
-         type="int"/>
-
-      <attribute name="processExpiresInterval"
-         description="The maximum number of seconds an SSO with no active sessions will be usable by a request"
-         type="int"/>
-
-      <attribute name="lastProcessExpires"
-         writeable="false"
-         description="The timestamp of the start of the last check for overaged SSO's with no active sessions."
-         type="long"/>
-
       <attribute name="clusterManager"
          description="SSOClusterManager to use for cluster support"
          type="org.jboss.web.tomcat.tc5.sso.SSOClusterManager"/>




More information about the jboss-cvs-commits mailing list