[Jboss-cvs] JBossAS SVN: r56366 - in branches/JBoss_4_0_3_SP1_CP: testsuite/src/etc/serialVersionUID testsuite/src/main/org/jboss/test testsuite/src/main/org/jboss/test/web/test testsuite/src/resources/web/sso/war tomcat/src/main/org/jboss/web/tomcat/tc5/sso

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Aug 28 19:03:53 EDT 2006


Author: ryan.campbell at jboss.com
Date: 2006-08-28 19:03:51 -0400 (Mon, 28 Aug 2006)
New Revision: 56366

Added:
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/etc/serialVersionUID/402.ser
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/index.jsp
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/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/resources/web/sso/war/web-sso-expire.xml
   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
Log:
Merged JBAS-2859: Port JBAS-2429 fix to 4.0.3.SP1: Undeployment of a webapp no longer invalidates single sign-on sessions associated with the webapp.

Copied: branches/JBoss_4_0_3_SP1_CP/testsuite/src/etc/serialVersionUID/402.ser (from rev 56316, branches/Branch_4_0/testsuite/src/etc/serialVersionUID/402.ser)

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-08-28 21:02:03 UTC (rev 56365)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/JBossClusteredTestCase.java	2006-08-28 23:03:51 UTC (rev 56366)
@@ -58,11 +58,30 @@
    {
       return clusterServices.getNamingURLs();
    }
+   public String[] getHANamingURLs() throws Exception
+   {
+      return clusterServices.getHANamingURLs();
+   }
    public String[] getHttpURLs() throws Exception
    {
       return clusterServices.getHttpURLs();
    }
 
+   protected void deploy(RMIAdaptor server, String name) throws Exception
+   {
+      clusterServices.deploy(server, name);
+   }
+
+   protected void redeploy(RMIAdaptor server, String name) throws Exception
+   {
+      clusterServices.redeploy(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-08-28 21:02:03 UTC (rev 56365)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/JBossTestClusteredServices.java	2006-08-28 23:03:51 UTC (rev 56366)
@@ -27,6 +27,7 @@
    protected ArrayList adaptors = null;
    protected ArrayList servers = null;
    protected ArrayList namingURLs = null;
+   protected ArrayList namingURLsHA = null;
    protected ArrayList httpURLs = null;
    
    // Constructors --------------------------------------------------
@@ -87,6 +88,24 @@
       return server;
    }
 
+   /** Get the JNDI provider urls for the cluster nodes
+    * @return
+    * @throws Exception
+    */ 
+   String[] getHANamingURLs() throws Exception
+   {
+      init();
+      String[] tmp = new String[namingURLsHA.size()];
+      namingURLsHA.toArray(tmp);
+      return tmp;
+   }
+   String getHANamingURL(int index) throws Exception
+   {
+      init();
+      String server = (String) namingURLsHA.get(index);
+      return server;
+   }
+
    /** Get the default web container urls for the cluster nodes
     * @return
     * @throws Exception
@@ -106,6 +125,69 @@
    }
 
    /**
+    * 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;
+      }
+
+      String deployURL = getDeployURL(name);
+      log.debug("Deploying " + name + ", url=" + deployURL  + " to " + server);
+      invoke(server,
+            getDeployerName(),
+            "deploy",
+            new Object[]{deployURL},
+            new String[]{"java.lang.String"});
+   }
+   
+   public void redeploy(RMIAdaptor server, String name) throws Exception
+   {
+      if (Boolean.getBoolean("jbosstest.nodeploy") == true)
+      {
+         log.debug("Skipping redeployment of: " + name);
+         return;
+      }
+
+      String deployURL = getDeployURL(name);
+      log.debug("Deploying " + name + ", url=" + deployURL);
+      invoke(server,
+         getDeployerName(),
+         "redeploy",
+         new Object[]{deployURL},
+         new String[]{"java.lang.String"});
+   }
+
+   /**
+    * 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;
+      String deployURL = getDeployURL(name);
+      log.debug("Undeploying " + name + ", url=" + deployURL);
+      Object[] args = {deployURL};
+      String[] sig = {"java.lang.String"};
+      invoke(server, getDeployerName(), "undeploy", args, sig);
+   }
+
+   /**
     * Override to invoke the operation on all servers
     *
     * @param name
@@ -144,6 +226,7 @@
          adaptors = new ArrayList();
          servers = new ArrayList();
          namingURLs = new ArrayList();
+         namingURLsHA = new ArrayList();
          httpURLs = new ArrayList();
          String adaptorName = System.getProperty("jbosstest.server.name");
          if (adaptorName == null)
@@ -177,6 +260,13 @@
             RMIAdaptor adaptor = (RMIAdaptor) tmpCtx.lookup(adaptorName);
             adaptors.add(adaptor);
 
+            // See if there is a jbosstest.cluster.nodeN.hajndi.url
+            urlProp = prop + ".hajndi.url";
+            urlDefault = "jnp://" + host + ":1100";
+            urlValue = System.getProperty(urlProp, urlDefault);
+            log.debug("HA-JNDI Url for node=" + count + " is:" + urlValue);
+            namingURLsHA.add(urlValue);
+            
             // See if there is a jbosstest.cluster.nodeN.http.url
             urlProp = prop + ".http.url";
             urlDefault = "http://" + host + ":8080";

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-08-28 21:02:03 UTC (rev 56365)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/ClusteredSingleSignOnUnitTestCase.java	2006-08-28 23:03:51 UTC (rev 56366)
@@ -17,18 +17,25 @@
 import org.apache.commons.httpclient.HttpState;
 import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.commons.httpclient.methods.PostMethod;
-import org.apache.log4j.Category;
+
+import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
 import org.jboss.test.JBossClusteredTestCase;
 
 
 /** Tests of web app single sign-on in a clustered environment
  * 
+ * TODO general refactoring; a lot of duplicated code here
+ * 
  * @author Brian Stansberry
  * @version $Revision$
  */
 public class ClusteredSingleSignOnUnitTestCase 
       extends JBossClusteredTestCase
 {   
+   private boolean deployed0 = true;
+   private boolean deployed1 = true;
+   private RMIAdaptor[] adaptors = null;
+   
    public ClusteredSingleSignOnUnitTestCase(String name)
    {
       super(name);
@@ -43,6 +50,23 @@
       return t1;
    }
 
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      
+      adaptors = getAdaptors(); 
+      if (!deployed0)
+      {
+         deploy(adaptors[0], "web-sso.ear");
+         deployed0 = true;
+      }
+      if (!deployed1)
+      {
+         deploy(adaptors[1], "web-sso.ear");
+         deployed1 = true;
+      }
+   }
+
    /** Test single sign-on across two web apps using form based auth
     * 
     * @throws Exception
@@ -64,9 +88,6 @@
     * 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() 
@@ -81,7 +102,7 @@
       
       // Start by accessing the secured index.html of war1
       HttpClient httpConn = new HttpClient();
-      GetMethod indexGet = new GetMethod(serverA+"/war3/index.html");
+      GetMethod indexGet = new GetMethod(serverA+"/war3/index.jsp");
       int responseCode = httpConn.executeMethod(indexGet);
       String body = indexGet.getResponseBodyAsString();
       assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
@@ -121,9 +142,12 @@
       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
+      // Wait more than 65 secs to let session time out
+      // 5 secs for the session timeout, 2 * 30 secs for the processor thread
+      // TODO for some reason it takes 1 min for processExpires to run ???
+      // (not an sso issue -- a tomcat issue)
       try {
-         Thread.sleep(75000);
+         Thread.sleep(65500);
       }
       catch (InterruptedException ie)
       {
@@ -131,7 +155,7 @@
       }
       
       // Try accessing war1 again
-      war1Index = new GetMethod(serverA+"/war3/index.html");
+      war1Index = new GetMethod(serverA+"/war3/index.jsp");
       responseCode = httpConn.executeMethod(war1Index.getHostConfiguration(),
          war1Index, state);
       assertTrue("Get OK", responseCode == HttpURLConnection.HTTP_OK);
@@ -141,4 +165,132 @@
          fail("get of /war1/index.html not redirected to login page");
       
    }
+   
+   /**
+    * 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];
+      
+      // Start by accessing the secured index.html of war1
+      HttpClient httpConn = new HttpClient();
+      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();
+      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
+      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");
+      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");
+
+      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();
+            // Make an sso cookie to send to serverB
+            Cookie copy = SSOBaseCase.copyCookie(k, serverB);
+            state.addCookie(copy);
+            log.debug("Added state cookie: "+copy);
+         }
+      }
+      assertTrue("Saw JSESSIONIDSSO", ssoID != null);
+      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");
+      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");
+
+      // 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.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");
+      war1Index = new GetMethod(serverB+"/war1/index.html");
+      responseCode = httpConn.executeMethod(war1Index.getHostConfiguration(),
+         war1Index, state);
+      response = war1Index.getStatusText();
+      log.debug("responseCode="+responseCode+", response="+response);
+      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 redirected to login page");
+   }
+}

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-08-28 21:02:03 UTC (rev 56365)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/web/test/SSOBaseCase.java	2006-08-28 23:03:51 UTC (rev 56366)
@@ -97,6 +97,14 @@
       assertTrue("Saw JSESSIONIDSSO", ssoID != null);
       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");
       GetMethod war2Index = new GetMethod(serverB+"/war2/index.html");
@@ -160,7 +168,7 @@
       
    }
    
-   private static Cookie copyCookie(Cookie toCopy, String targetServer)
+   public static Cookie copyCookie(Cookie toCopy, String targetServer)
    {
       // Parse the target server down to a domain name
       int index = targetServer.indexOf("://");

Copied: branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/index.jsp (from rev 56365, branches/JBoss_4_0_3_SP1_JBAS-2859/testsuite/src/resources/web/sso/war/index.jsp)

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-08-28 21:02:03 UTC (rev 56365)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/web/sso/war/web-sso-expire.xml	2006-08-28 23:03:51 UTC (rev 56366)
@@ -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>

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-08-28 21:02:03 UTC (rev 56365)
+++ branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/ClusteredSingleSignOn.java	2006-08-28 23:03:51 UTC (rev 56366)
@@ -11,17 +11,26 @@
 
 import java.io.IOException;
 import java.security.Principal;
+import java.util.Collections;
+import java.util.HashSet;
+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;
 
 
 /**
@@ -46,6 +55,7 @@
  */
 public class ClusteredSingleSignOn
    extends org.apache.catalina.authenticator.SingleSignOn
+   implements LifecycleListener
 {
 
    // Override the superclass value
@@ -77,6 +87,8 @@
     */
    private String treeCacheName = Tomcat5.DEFAULT_CACHE_NAME;
 
+   private Set activeManagers = Collections.synchronizedSet(new HashSet());
+
    // ------------------------------------------------------------- Properties
 
    /**
@@ -292,13 +304,12 @@
       if (ssoId == null)
          return;
 
-      // Was the session destroyed as the result of a timeout?
+      // 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 ((session.getMaxInactiveInterval() > 0)
-         && (System.currentTimeMillis() - session.getLastAccessedTime() >=
-         session.getMaxInactiveInterval() * 1000))
+      if (isSessionTimedOut(session) || isManagerStopped(session))
       {
          removeSession(ssoId, session);
       }
@@ -310,7 +321,72 @@
 
    }
 
+   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 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
+         {
+            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
 
 
@@ -433,9 +509,38 @@
          reverse.put(session, ssoId);
       }
 
-      // If we made a change, notify any cluster
-      if (added && ssoClusterManager != null)
+      // If we made a change, track the manager and notify any cluster
+      if (added)
+      {
+         Manager manager = session.getManager();
+         if (manager instanceof ManagerBase)
+         {
+            // Prefer to cache an ObjectName to avoid leaking a manager
+            Object mgrName = ((ManagerBase)manager).getObjectName();
+            synchronized (activeManagers)
+            {
+               if (!activeManagers.contains(mgrName))
+               {
+                  activeManagers.add(mgrName);
+                  ((Lifecycle) manager).addLifecycleListener(this);
+               }
+            }
+         }
+         else if (manager instanceof Lifecycle)
+         {
+            synchronized (activeManagers)
+            {
+               if (!activeManagers.contains(manager))
+               {
+                  activeManagers.add(manager);
+                  ((Lifecycle) manager).addLifecycleListener(this);
+               }
+            }
+         }
+         
+         if (ssoClusterManager != null)         
          ssoClusterManager.addSession(ssoId, session);
+      }
    }
 
 

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-08-28 21:02:03 UTC (rev 56365)
+++ branches/JBoss_4_0_3_SP1_CP/tomcat/src/main/org/jboss/web/tomcat/tc5/sso/TreeCacheSSOClusterManager.java	2006-08-28 23:03:51 UTC (rev 56366)
@@ -167,6 +167,11 @@
     */
    private boolean missingCacheErrorLogged = false;
    
+   /**
+    * Our node's address in the cluster.
+    */
+   private Serializable localAddress = null;
+   
    // ----------------------------------------------------------  Constructors
 
    
@@ -242,7 +247,7 @@
       {
          // Confirm the cache has a transaction manager
          // and fail if not found
-         findTransactionManager();
+         configureFromCache();
       }
    }
    
@@ -286,7 +291,7 @@
             tm.begin();
          
          Set sessions = getSessionSet(fqn, true);
-         sessions.add(session.getId());
+         sessions.add(new SessionAddress(session.getId(), localAddress));
          putInTreeCache(fqn, sessions);
       }
       catch (Exception e)
@@ -518,7 +523,7 @@
          Set sessions = getSessionSet(fqn, false);
          if (sessions != null)
          {
-            sessions.remove(session.getId());
+            sessions.remove(new SessionAddress(session.getId(), localAddress));
             if (sessions.size() == 0)
             {
                // Add this SSO to our list of in-process local removals so
@@ -826,7 +831,7 @@
       {
          if (tm == null && isTreeCacheAvailable(true))
          {
-            findTransactionManager();
+            configureFromCache();
          }
       }
       catch (Exception e)
@@ -936,11 +941,10 @@
     * 
     * @throws Exception
     */
-   private void findTransactionManager() throws Exception
-   {
-      tm = (TransactionManager) server.invoke(getCacheObjectName(), 
-                                              "getTransactionManager", 
-                                              null, new String[] {});                  
+   private void configureFromCache() throws Exception
+   {  
+      tm = (TransactionManager) server.getAttribute(getCacheObjectName(), 
+                                                    "TransactionManager");
 
       if (tm == null) 
       {
@@ -949,6 +953,15 @@
                                          "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();
    }
    
 
@@ -1422,5 +1435,42 @@
 
    } // 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());
+      }
+      
+      
+   }
+
 } // end TreeCacheSSOClusterManager
 




More information about the jboss-cvs-commits mailing list