[jboss-cvs] JBossAS SVN: r106021 - in branches/JBPAPP_4_2_0_GA_CP: tomcat/src/main/org/jboss/web/tomcat/service/sso and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Jun 14 00:41:07 EDT 2010


Author: jiwils
Date: 2010-06-14 00:41:06 -0400 (Mon, 14 Jun 2010)
New Revision: 106021

Modified:
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/web/test/TreeCacheSSOClusterManagerUnitTestCase.java
   branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/sso/TreeCacheSSOClusterManager.java
Log:
Fix for JBPAPP-4473.  JBossWeb Host and Context are now taken into account when managing SSO sessions.

Modified: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/web/test/TreeCacheSSOClusterManagerUnitTestCase.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/web/test/TreeCacheSSOClusterManagerUnitTestCase.java	2010-06-14 04:38:56 UTC (rev 106020)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/web/test/TreeCacheSSOClusterManagerUnitTestCase.java	2010-06-14 04:41:06 UTC (rev 106021)
@@ -30,8 +30,10 @@
 import javax.management.ObjectName;
 import javax.transaction.TransactionManager;
 
+import org.apache.catalina.Container;
 import org.apache.catalina.Manager;
 import org.apache.catalina.Session;
+import org.apache.catalina.core.ContainerBase;
 import org.apache.catalina.session.StandardManager;
 import org.apache.catalina.session.StandardSession;
 import org.jboss.cache.AbstractTreeCacheListener;
@@ -53,19 +55,19 @@
 
 /**
  * Test of the TreeCacheSSOClusterManager class.
- * 
+ *
  * @author Brian Stansberry
  */
 public class TreeCacheSSOClusterManagerUnitTestCase extends JBossTestCase
 {
    private static IpAddress LOCAL_ADDRESS;
    private static IpAddress REMOTE_ADDRESS;
-   
+
    public TreeCacheSSOClusterManagerUnitTestCase(String name)
    {
       super(name);
    }
-   
+
    @Override
    protected void setUp() throws Exception
    {
@@ -78,19 +80,69 @@
    {
       deadMemberCleanupTest(true);
    }
-   
+
    public void testDeadMemberCleanupWithoutPool() throws Exception
    {
       deadMemberCleanupTest(false);
    }
-   
+
+   // See JBPAPP-4473.
+   public void testMultipleAppsSameSession() throws Exception
+   {
+      log.debug("+++ testMultipleAppsSameSession");
+
+      MBeanServer mbeanServer =
+         MBeanServerFactory.createMBeanServer("multipleAppsSameSessionTest");
+
+      try
+      {
+         // The following initial code is the same as for the dead member tests,
+         // and it could be factored out into various methods, but this was left
+         // as is on purpose so it is clear what is happening in this test.
+
+         // Register a cache
+         MockTreeCache cache = new MockTreeCache();
+         cache.setTransactionManagerLookup(new MockTransactionManagerLookup());
+         mbeanServer.registerMBean(cache, new ObjectName(TreeCacheSSOClusterManager.DEFAULT_GLOBAL_CACHE_NAME));
+         cache.startService();
+
+         // Build up an SSO infrastructure based on LOCAL_ADDRESS
+         TreeCacheSSOClusterManager localManager = new TreeCacheSSOClusterManager(mbeanServer);
+         localManager.setCacheName(TreeCacheSSOClusterManager.DEFAULT_GLOBAL_CACHE_NAME);
+
+         MockSSOValve localValve = new MockSSOValve();
+         localValve.setClusterManager(localManager);
+         localManager.setSingleSignOnValve(localValve);
+         localManager.start();
+
+         // Begin test specific code.
+         localManager.register("MultipleApps", "FORM", "Jimmy", "password");
+         final String sessionId = "9";
+
+         Manager localSessMgrApp1 = createSessionManager("localSessMgrApp1");
+         Session sess9 = new MockSession(localSessMgrApp1, sessionId);
+         Manager localSessMgrApp2 = createSessionManager("localSessMgrApp2");
+         Session sess9DiffApp = new MockSession(localSessMgrApp2, sessionId);
+         localManager.addSession("MultipleApps", sess9);
+         localManager.addSession("MultipleApps", sess9DiffApp);
+
+         Set sso5 = (Set) cache.get("/SSO/MultipleApps/sessions", "key");
+         assertNotNull("SSO MultipleApps exists", sso5);
+         assertEquals("SSO MultipleApps has correct number of sessions", 2, sso5.size());
+      }
+      finally
+      {
+         MBeanServerFactory.releaseMBeanServer(mbeanServer);
+      }
+   }
+
    private void deadMemberCleanupTest(boolean usePool) throws Exception
    {
       log.debug("+++ testDeadMemberCleanup()");
-      
-      MBeanServer mbeanServer = 
+
+      MBeanServer mbeanServer =
          MBeanServerFactory.createMBeanServer("deadMemberTest");
-      try 
+      try
       {
          // Register a cache
          MockTreeCache cache = new MockTreeCache();
@@ -100,82 +152,82 @@
          cache.setTransactionManagerLookup(new MockTransactionManagerLookup());
          mbeanServer.registerMBean(cache, new ObjectName(TreeCacheSSOClusterManager.DEFAULT_GLOBAL_CACHE_NAME));
          cache.startService();
-         
+
          if (usePool)
          {
             BasicThreadPool pool = new BasicThreadPool();
             mbeanServer.registerMBean(pool, new ObjectName(TreeCacheSSOClusterManager.DEFAULT_THREAD_POOL_NAME));
          }
-         
-         // Build up an SSO infrastructure based on LOCAL_ADDRESS         
+
+         // Build up an SSO infrastructure based on LOCAL_ADDRESS
          TreeCacheSSOClusterManager localManager = new TreeCacheSSOClusterManager(mbeanServer);
          localManager.setCacheName(TreeCacheSSOClusterManager.DEFAULT_GLOBAL_CACHE_NAME);
-         
+
          MockSSOValve localValve = new MockSSOValve();
          localValve.setClusterManager(localManager);
          localManager.setSingleSignOnValve(localValve);
          localManager.start();
-         
+
          assertEquals("Thread pool usage as expected", usePool, localManager.isUsingThreadPool());
-         
+
          //  Build up a second SSO infrastructure based on LOCAL_ADDRESS
          // It uses the same mock cache, but we change the cache address
          // so it thinks it's a different address when it starts
          cache.setOurAddress(REMOTE_ADDRESS);
-         
+
          TreeCacheSSOClusterManager remoteManager = new TreeCacheSSOClusterManager(mbeanServer);
          remoteManager.setCacheName(TreeCacheSSOClusterManager.DEFAULT_GLOBAL_CACHE_NAME);
-         
+
          MockSSOValve remoteValve = new MockSSOValve();
          remoteValve.setClusterManager(remoteManager);
          remoteManager.setSingleSignOnValve(localValve);
          remoteManager.start();
-         
-         
+
+
          // Create an SSO that will have sessions from both valves
          localManager.register("1", "FORM", "Brian", "password");
-         
-         Manager localSessMgr1 = new StandardManager();
+
+         Manager localSessMgr1 = createSessionManager("localSessMgr1");
          Session sess1 = new MockSession(localSessMgr1, "1");
          localManager.addSession("1", sess1);
-         
-         Manager remoteSessMgr1 = new StandardManager();
+
+         Manager remoteSessMgr1 = createSessionManager("remoteSessMgr1");
          Session sess2 = new MockSession(remoteSessMgr1, "2");
          remoteManager.addSession("1", sess2);
-         
-         
+
+
          // Create another SSO with sessions only from remote
          remoteManager.register("2", "FORM", "Brian", "password");
-         
-         Manager remoteSessMgr2 = new StandardManager();
+
+         Manager remoteSessMgr2 = createSessionManager("remoteSessMgr2");
          Session sess3 = new MockSession(remoteSessMgr2, "3");
          remoteManager.addSession("2", sess3);
-         
-         
+
+
          // Create a third SSO that will have sessions from both valves
          localManager.register("3", "FORM", "Brian", "password");
-         
-         Manager localSessMgr2 = new StandardManager();
+
+         Manager localSessMgr2 = createSessionManager("localSessMgr2");
          Session sess4 = new MockSession(localSessMgr2, "4");
          localManager.addSession("3", sess4);
-         
-         Manager remoteSessMgr3 = new StandardManager();
+
+         Manager remoteSessMgr3 = createSessionManager("remoteSessMgr3");
          Session sess5 = new MockSession(remoteSessMgr3, "5");
          remoteManager.addSession("3", sess5);
-         
-         
+
+
          // Create a fourth SSO that will have sessions from both valves
          localManager.register("4", "FORM", "Brian", "password");
-         
-         Manager localSessMgr3 = new StandardManager();
+
+         Manager localSessMgr3 = createSessionManager("localSessMgr3");
          Session sess6 = new MockSession(localSessMgr3, "6");
          localManager.addSession("4", sess6);
-         
-         Manager remoteSessMgr4 = new StandardManager();
+
+         Manager remoteSessMgr4 = createSessionManager("remoteSessMgr4");
          Session sess7 = new MockSession(remoteSessMgr4, "7");
          remoteManager.addSession("4", sess7);
-         
-         
+
+
          // Confirm that data is cached properly
          Set sso1 = (Set) cache.get("/SSO/1/sessions", "key");
          assertNotNull("SSO 1 exists", sso1);
@@ -189,14 +241,14 @@
          Set sso4 = (Set) cache.get("/SSO/4/sessions", "key");
          assertNotNull("SSO 4 exists", sso4);
          assertEquals("SSO 4 has correct number of sessions", 2, sso4.size());
-         
+
          // Put in a new view with REMOTE_ADDRESS dead
          ViewId viewId = new ViewId(LOCAL_ADDRESS, 1);
          Vector v = new Vector();
          v.add(LOCAL_ADDRESS);
          localManager.viewChange(new View(viewId, v));
-         
-         
+
+
          // Test that a regular remove call cleans up dead members
          // (BES: the cleanup thread may have dealt with this; I see no
          //  clean way to force this being done by the caller thread)
@@ -204,20 +256,20 @@
          sso3 = (Set) cache.get("/SSO/3/sessions", "key");
          assertNotNull("SSO 3 exists", sso3);
          assertEquals("SSO 3 has correct number of sessions", 0, sso3.size());
-         
+
          // Test that a regular add call cleans up dead members
          // (BES: the cleanup thread may have dealt with this; I see no
          //  clean way to force this being done by the caller thread)
-         Manager localSessMgr4 = new StandardManager();
+         Manager localSessMgr4 = createSessionManager("localSessMgr4");
          Session sess8 = new MockSession(localSessMgr4, "8");
          localManager.addSession("4", sess8);
          sso4 = (Set) cache.get("/SSO/4/sessions", "key");
          assertNotNull("SSO 4 exists", sso4);
          assertEquals("SSO 4 has correct number of sessions", 2, sso4.size());
-         
+
          // Give the cleanup thread time to finish
          Thread.sleep(300);
-         
+
          // Confirm that cached data is properly cleaned up
          sso1 = (Set) cache.get("/SSO/1/sessions", "key");
          assertNotNull("SSO 1 exists", sso1);
@@ -230,19 +282,37 @@
          assertEquals("SSO 3 has correct number of sessions", 0, sso3.size());
          sso4 = (Set) cache.get("/SSO/4/sessions", "key");
          assertNotNull("SSO 4 exists", sso4);
-         assertEquals("SSO 4 has correct number of sessions", 2, sso4.size());         
+         assertEquals("SSO 4 has correct number of sessions", 2, sso4.size());
       }
       finally
       {
          MBeanServerFactory.releaseMBeanServer(mbeanServer);
-      }      
+      }
    }
-   
-   
+
+   /**
+    * Creates a session manager with context and host container names to avoid
+    * NPEs specific to this test case.
+    */
+   private Manager createSessionManager(String name)
+   {
+      Container contextContainer = new MockContainer();
+      contextContainer.setName(name + "-context");
+
+      Container hostContainer = new MockContainer();
+      hostContainer.setName(name + "-host");
+
+      contextContainer.setParent(hostContainer);
+
+      Manager sessionManager = new StandardManager();
+      sessionManager.setContainer(contextContainer);
+      return sessionManager;
+   }
+
    static class MockTreeCache extends TreeCache
    {
       private IpAddress ourAddress = LOCAL_ADDRESS;
-      
+
       public MockTreeCache() throws Exception
       {
          super();
@@ -254,7 +324,7 @@
       {
          return ourAddress;
       }
-      
+
       void setOurAddress(IpAddress address)
       {
          ourAddress = address;
@@ -267,10 +337,10 @@
          v.add(LOCAL_ADDRESS);
          v.add(REMOTE_ADDRESS);
          return v;
-      }      
-      
+      }
+
    }
-   
+
    /**
     * Override ClusteredSingleSignOn to suppress the empty SSO callbacks
     */
@@ -286,35 +356,44 @@
       protected void notifySSONotEmpty(String ssoId)
       {
          // no-op
-      }      
+      }
    }
-   
+
+   /**
+    * Override container to provide context and host container names to avoid
+    * NPEs specific to this test case.  This class only exists because
+    * ContainerBase is abstract.
+    */
+   static class MockContainer extends ContainerBase
+   {
+   }
+
    static class MockSession extends StandardSession
    {
       private static final long serialVersionUID = 1L;
-      
+
       private String ourId;
-      
+
       MockSession(Manager manager, String id)
       {
          super(manager);
          ourId = id;
       }
-      
+
       @Override
       public String getId()
       {
          return ourId;
       }
    }
-   
+
    static class MockTransactionManagerLookup implements TransactionManagerLookup
    {
       public TransactionManager getTransactionManager() throws Exception
       {
          return new BatchModeTransactionManager();
       }
-      
+
    }
 
 }

Modified: branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/sso/TreeCacheSSOClusterManager.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/sso/TreeCacheSSOClusterManager.java	2010-06-14 04:38:56 UTC (rev 106020)
+++ branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/sso/TreeCacheSSOClusterManager.java	2010-06-14 04:41:06 UTC (rev 106021)
@@ -36,6 +36,7 @@
 import javax.transaction.Status;
 import javax.transaction.TransactionManager;
 
+import org.apache.catalina.Container;
 import org.apache.catalina.LifecycleException;
 import org.apache.catalina.LifecycleListener;
 import org.apache.catalina.Session;
@@ -112,27 +113,27 @@
     * Parameter signature used for TreeCache.put calls over JMX
     */
    private static final String[] PUT_SIGNATURE =
-      {Fqn.class.getName(), Object.class.getName(), 
+      {Fqn.class.getName(), Object.class.getName(),
        Object.class.getName(), Option.class.getName()};
 
    /**
     * Parameter signature used for TreeCache.remove calls over JMX
     */
-   private static final String[] REMOVE_SIGNATURE = 
+   private static final String[] REMOVE_SIGNATURE =
          {Fqn.class.getName(), Option.class.getName()};
-   
+
    private static final Option GRAVITATE_OPTION = new Option();
    private static final Option LOCAL_OPTION = new Option();
-   
+
    static
    {
       GRAVITATE_OPTION.setForceDataGravitation(true);
       LOCAL_OPTION.setCacheModeLocal(true);
    }
-   
-   
+
+
    // -------------------------------------------------------  Instance Fields
-   
+
    /**
     * SSO id which the thread is currently storing to the cache
     */
@@ -152,11 +153,11 @@
     * ObjectName of the TreeCache
     */
    private ObjectName cacheObjectName = null;
-   
+
    private String threadPoolName = DEFAULT_THREAD_POOL_NAME;
 
    private ThreadPool threadPool;
-   
+
    /**
     * String version of the object name to use to access the TreeCache
     */
@@ -166,7 +167,7 @@
     * Transaction Manager
     */
    private TransactionManager tm = null;
-   
+
    /**
     * The lifecycle event support for this component.
     */
@@ -206,23 +207,23 @@
     * Whether we have logged an error due to not having a valid cache
     */
    private boolean missingCacheErrorLogged = false;
-   
+
    /**
     * Our node's address in the cluster.
     */
    private Serializable localAddress = null;
-   
+
    /** The members of the last view passed to viewChange() */
    private Set currentView;
-   
+
    /** Mutex lock to ensure only one view change at a time is being processed */
    private Object cleanupMutex = new Object();
-   
+
    private boolean checkForInvalidAddresses = false;
-   
+
    // ----------------------------------------------------------  Constructors
 
-   
+
    /**
     * Creates a new TreeCacheSSOClusterManager
     */
@@ -234,7 +235,7 @@
          server = MBeanServerLocator.locate();
    }
 
-   
+
    /**
     * Creates a new TreeCacheSSOClusterManager that works with the given
     * MBeanServer.  This constructor is only intended for use in unit testing.
@@ -243,10 +244,10 @@
    {
       this.server = server;
    }
-   
-   
+
+
    // ------------------------------------------------------------  Properties
-  
+
    public String getCacheName()
    {
       return cacheName;
@@ -283,7 +284,7 @@
 
       removeAsTreeCacheListener();
       this.tm = null;
-      
+
       this.cacheObjectName = objectName;
       this.cacheName = (objectName == null
          ? null
@@ -304,7 +305,7 @@
          }
       }
    }
-   
+
    public String getThreadPoolName()
    {
       return threadPoolName;
@@ -322,12 +323,12 @@
          this.threadPoolName = threadPoolName;
       }
    }
-   
+
    public boolean isUsingThreadPool()
    {
       return threadPool != null;
    }
-   
+
    // -----------------------------------------------------  SSOClusterManager
 
 
@@ -363,18 +364,18 @@
          // failure to find will throw an IllegalStateException
          if (tm == null)
             configureFromCache();
-         
-         // Don't do anything if there is already a transaction 
+
+         // Don't do anything if there is already a transaction
          // context associated with this thread.
          if(tm.getTransaction() == null)
             doTx = true;
 
          if(doTx)
             tm.begin();
-         
+
          Set sessions = getSessionSet(fqn, true, false);
-         sessions.add(new SessionAddress(session.getId(), localAddress));
-         
+         sessions.add(new SessionAddress(getSessionAddressId(session), localAddress));
+
          if (checkForInvalidAddresses)
          {
             cleanDeadMembers(sessions, new HashSet(currentView));
@@ -441,13 +442,13 @@
       {
          return;
       }
-      
-      // Check whether we are already handling this removal 
+
+      // Check whether we are already handling this removal
       if (ssoId.equals(beingLocallyRemoved.get()))
       {
          return;
-      }         
-      
+      }
+
       // Add this SSO to our list of in-process local removals so
       // this.nodeRemoved() will ignore the removal
       beingLocallyRemoved.set(ssoId);
@@ -459,7 +460,7 @@
       }
 
       Fqn fqn = getSingleSignOnFqn(ssoId);
-      
+
       try
       {
          removeFromTreeCache(fqn);
@@ -553,19 +554,19 @@
       {
          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()))
       {
          return;
       }
-      
+
       Fqn fqn = getSessionsFqn(ssoId);
       boolean doTx = false;
 //      boolean removing = false;
@@ -576,18 +577,18 @@
          if (tm == null)
             configureFromCache();
 
-         // Don't do anything if there is already a transaction 
+         // Don't do anything if there is already a transaction
          // context associated with this thread.
          if(tm.getTransaction() == null)
             doTx = true;
 
          if(doTx)
             tm.begin();
-         
+
          Set sessions = getSessionSet(fqn, false, false);
          if (sessions != null)
          {
-            sessions.remove(new SessionAddress(session.getId(), localAddress));
+            sessions.remove(new SessionAddress(getSessionAddressId(session), localAddress));
 
             if (log.isTraceEnabled())
             {
@@ -595,8 +596,8 @@
                   " from cached session set for SSO " + ssoId + " -- " +
                   sessions.size() + " sessions remain");
             }
-            
 
+
             if (checkForInvalidAddresses)
             {
                cleanDeadMembers(sessions, new HashSet(currentView));
@@ -615,7 +616,7 @@
          catch (Exception x)
          {
          }
-         
+
          String sessId = (session == null ? "NULL" : session.getId());
          log.error("caught exception removing session " + sessId +
             " from SSO id " + ssoId, e);
@@ -655,7 +656,7 @@
       storeSSOData(ssoId, authType, username, password);
    }
 
-   
+
    // ------------------------------------------------------  TreeCacheListener
 
    /**
@@ -670,7 +671,7 @@
    public void nodeRemoved(Fqn fqn)
    {
       String ssoId = getIdFromFqn(fqn);
-      
+
       if (ssoId == null)
          return;
 
@@ -679,7 +680,7 @@
       {
          return;
       }
-      
+
       beingRemotelyRemoved.set(ssoId);
 
       try
@@ -729,7 +730,7 @@
 
 
    /**
-    *  
+    *
     * @param fqn an Fqn that points to the CREDENTIALS node of an SSO
     */
    private void handleCredentialUpdate(Fqn fqn)
@@ -782,9 +783,9 @@
          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)
@@ -792,19 +793,19 @@
       // 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      
+      try
       {
          Set sessions = (Set) getFromTreeCache(fqn, false);
          if (sessions == null)
          {
-            // don't think we'd get this event; 
+            // 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);            
+            ssoValve.notifySSOEmpty(ssoId);
          }
          else
          {
@@ -826,20 +827,20 @@
     */
    public synchronized void viewChange(View new_view)
    {
-      Set oldMembers = currentView;      
+      Set oldMembers = currentView;
       currentView = new HashSet(new_view.getMembers());
-      
+
       if (oldMembers == null)
          return;  // we must not be started yet
-      
+
       // If we're not in the view, just exit
       if (localAddress == null || !currentView.contains((Address) localAddress))
          return;
-      
-      // Remove all the current members from the old set; any left 
+
+      // Remove all the current members from the old set; any left
       // are the dead members
       oldMembers.removeAll(currentView);
-      
+
       if (oldMembers.size() > 0)
       {
          // Inform threads updating our SSOs to check for dead members so
@@ -858,9 +859,9 @@
             t.start();
          }
       }
-         
-   }   
-   
+
+   }
+
    // -------------------------------------------------------------  Lifecycle
 
 
@@ -913,7 +914,7 @@
             ("TreeCacheSSOClusterManager already Started");
       }
 
-      try 
+      try
       {
          if (isTreeCacheAvailable(true))
          {
@@ -925,9 +926,9 @@
          throw new LifecycleException("Caught exception looking up " +
                                       "TransactionManager from TreeCache", e);
       }
-      
+
       initThreadPool();
-      
+
       started = true;
 
       // Notify our interested LifecycleListeners
@@ -952,14 +953,14 @@
          throw new LifecycleException
             ("TreeCacheSSOClusterManager not Started");
       }
-      
+
       started = false;
 
       // Notify our interested LifecycleListeners
       lifecycle.fireLifecycleEvent(STOP_EVENT, null);
    }
 
-   
+
    // -------------------------------------------------------  Private Methods
 
    private Object getFromTreeCache(Fqn fqn, boolean localOnly) throws Exception
@@ -967,12 +968,12 @@
       Object[] args = new Object[]{fqn, KEY, localOnly ? LOCAL_OPTION : GRAVITATE_OPTION};
       return server.invoke(getCacheObjectName(), "get", args, GET_SIGNATURE);
    }
-   
+
    private Set getSSOIds() throws Exception
    {
       Fqn ssoRoot = new Fqn(new Object[] {SSO});
-      Set ssoIds = (Set) server.invoke(getCacheObjectName(), "getChildrenNames", 
-                                       new Object[]{ ssoRoot }, 
+      Set ssoIds = (Set) server.invoke(getCacheObjectName(), "getChildrenNames",
+                                       new Object[]{ ssoRoot },
                                        new String[]{ Fqn.class.getName() });
       return ssoIds == null ? Collections.emptySet() : ssoIds;
    }
@@ -1038,28 +1039,28 @@
          type = (String) fqn.get(2);
       return type;
    }
-   
+
    /**
     * 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(), 
+   {
+      tm = (TransactionManager) server.getAttribute(getCacheObjectName(),
                                                     "TransactionManager");
 
-      if (tm == null) 
+      if (tm == null)
       {
          throw new IllegalStateException("TreeCache does not have a " +
                                          "transaction manager; please " +
                                          "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
@@ -1068,29 +1069,29 @@
          localAddress = (Serializable) address;
       else
          localAddress = address.toString();
-      
+
       // Get the currentView
-      Vector members = (Vector) server.getAttribute(getCacheObjectName(), 
+      Vector members = (Vector) server.getAttribute(getCacheObjectName(),
                                                    "Members");
       if (members != null)
          currentView = new HashSet(members);
    }
-   
 
+
    private void endTransaction()
    {
-      try 
+      try
       {
          if(tm.getTransaction().getStatus() != Status.STATUS_MARKED_ROLLBACK)
          {
             tm.commit();
-         } 
+         }
          else
          {
             tm.rollback();
          }
-      } 
-      catch (Exception e) 
+      }
+      catch (Exception e)
       {
          log.error(e);
          throw new NestedRuntimeException("TreeCacheSSOClusterManager.endTransaction(): ", e);
@@ -1140,7 +1141,7 @@
       }
       return treeCacheAvailable;
    }
-   
+
    private boolean checkTreeCacheAvailable()
    {
       boolean avail = isTreeCacheAvailable(false);
@@ -1159,12 +1160,12 @@
    {
       // Ensure we have a transaction manager and a cluster-wide unique address
       configureFromCache();
-      
+
       // If the SSO region is inactive, activate it
       activateCacheRegion();
-      
+
       registerAsTreeCacheListener();
-      
+
       log.debug("Successfully integrated with cache service " + cacheObjectName);
    }
 
@@ -1172,7 +1173,7 @@
    /**
     * If we are sharing a cache with HttpSession replication, the SSO
     * region may not be active, so here we ensure it is.
-    * 
+    *
     * @throws Exception
     */
    private void activateCacheRegion() throws Exception
@@ -1198,7 +1199,7 @@
                catch (MBeanException e)
                {
                   Exception cause = e.getTargetException();
-                  if (cause != null 
+                  if (cause != null
                         && "org.jboss.cache.RegionNotEmptyException".equals(cause.getClass().getName()))
                   {
                      log.debug(SSO + " region already active", cause);
@@ -1253,9 +1254,9 @@
          new Object[]{fqn, GRAVITATE_OPTION},
          REMOVE_SIGNATURE);
    }
-   
+
    private void initThreadPool()
-   {      
+   {
       if (threadPoolName != null)
       {
          try
@@ -1267,14 +1268,14 @@
          }
          catch (Exception e)
          {
-            log.info("Unable to access ThreadPool at " + threadPoolName + 
+            log.info("Unable to access ThreadPool at " + threadPoolName +
                      " -- will use individual threads for cleanup work");
             log.debug("Failure to access ThreadPool due to: " + e);
          }
       }
       else
       {
-         log.debug("No ThreadPool configured -- will use individual threads for cleanup work");         
+         log.debug("No ThreadPool configured -- will use individual threads for cleanup work");
       }
    }
 
@@ -1298,11 +1299,11 @@
       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);
-      
+
       try
       {
          putInTreeCache(getCredentialsFqn(ssoId), data, false);
@@ -1347,7 +1348,28 @@
          setMissingCacheErrorLogged(true);
       }
    }
-   
+
+   /**
+    * Creates a SessionAddressId which includes the host and context in
+    * addition to the session id itself.  These fields could not be added
+    * directly to SessionAddress as that would have broken backwards
+    * compatibility.  See JBPAPP-4473 for more information.
+    */
+   private String getSessionAddressId(Session session)
+   {
+      Container context = session.getManager().getContainer();
+      String contextName = context.getName();
+      Container host = context.getParent();
+      String hostName = host.getName();
+
+      StringBuilder builder = new StringBuilder(hostName);
+      builder.append('_');
+      builder.append(contextName);
+      builder.append('_');
+      builder.append(session.getId());
+      return builder.toString();
+   }
+
    private static boolean cleanDeadMembers(Set sessionSet, Set currentMembers)
    {
       boolean changed = false;
@@ -1381,7 +1403,7 @@
    {
       /** The serialVersionUID */
       private static final long serialVersionUID = 5704877226920571663L;
-      
+
       private String authType = null;
       private String password = null;
       private String username = null;
@@ -1433,15 +1455,15 @@
       }
 
    } // 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;
@@ -1452,13 +1474,13 @@
       {
          if (this == obj)
             return true;
-         
+
          if (!(obj instanceof SessionAddress))
             return false;
-         
+
          SessionAddress other = (SessionAddress) obj;
-         
-         return (sessionId.equals(other.sessionId) 
+
+         return (sessionId.equals(other.sessionId)
                  && address.equals(other.address));
       }
 
@@ -1467,36 +1489,36 @@
          int total = (19 * 43) + sessionId.hashCode();
          return ((total * 43) + address.hashCode());
       }
-      
-      
+
+
    }
 
    /**
-    * Runnable that's run when the removal of a node from the cluster has been detected. 
+    * 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();
                // Copy off the currentView
                Set members = new HashSet(currentView);
                for (Iterator iter = ids.iterator(); iter.hasNext();)
                {
-                  cleanDeadMembersFromSSO((String) iter.next(), members);                  
+                  cleanDeadMembersFromSSO((String) iter.next(), members);
                }
-               
+
                // We've cleaned up; no need for other threads to help
                checkForInvalidAddresses = false;
             }
@@ -1506,7 +1528,7 @@
             }
          }
       }
-      
+
       private void cleanDeadMembersFromSSO(String ssoId, Set currentMembers)
       {
          Fqn fqn = getSessionsFqn(ssoId);
@@ -1519,20 +1541,20 @@
 
             if(doTx)
                tm.begin();
-            
+
             Set sessions = getSessionSet(fqn, false, true);
             if (sessions != null && sessions.size() > 0)
             {
                boolean changed = cleanDeadMembers(sessions, currentMembers);
-               
+
                if (changed)
-               {                  
+               {
                   if (sessions.size() == 0)
                   {
                      ssoValve.notifySSOEmpty(ssoId);
                   }
-                  
-                  // Don't bother with the local-onlyput; we have a lock on the node 
+
+                  // Don't bother with the local-onlyput; we have a lock on the node
                   // from the get and the cached data is a ref to the set we just changed
                   //putInTreeCache(fqn, sessions, true);
                }
@@ -1554,7 +1576,7 @@
          {
             if (doTx)
                endTransaction();
-         }         
+         }
       }
    }
 



More information about the jboss-cvs-commits mailing list