[jboss-cvs] JBossAS SVN: r75518 - in branches/JBPAPP_4_2_0_GA_CP: server/src/resources/43specific/org/jboss/metadata and 9 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Jul 8 22:45:49 EDT 2008


Author: bstansberry at jboss.com
Date: 2008-07-08 22:45:48 -0400 (Tue, 08 Jul 2008)
New Revision: 75518

Added:
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/AttributeBasedMaxUnreplicatedIntervalTestCase.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/FieldBasedMaxUnreplicatedIntervalTestCase.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/JBossWebXmlParsingTestCase.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/SessionBasedMaxUnreplicatedIntervalTestCase.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/BasicRequestHandler.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/CacheConfigTestSetup.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockContainer.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockEngine.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockHost.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockLoader.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockRequest.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockValve.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MutableObject.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/RequestHandler.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/RequestHandlerValve.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/SetAttributesRequestHandler.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/WebSessionTestUtil.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/http-sr/
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/jboss-web-test-service.xml
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/version.jsp
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/xmlparsing/
Removed:
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockValve.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/web.xml
Modified:
   branches/JBPAPP_4_2_0_GA_CP/server/src/resources/42specific/org/jboss/metadata/WebMetaData.java
   branches/JBPAPP_4_2_0_GA_CP/server/src/resources/43specific/org/jboss/metadata/WebMetaData.java
   branches/JBPAPP_4_2_0_GA_CP/server/src/resources/dtd/jboss-web_4_2.dtd
   branches/JBPAPP_4_2_0_GA_CP/testsuite/build.xml
   branches/JBPAPP_4_2_0_GA_CP/testsuite/imports/sections/cluster.xml
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/JvmRouteValveUnitTestCase.java
   branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/SimpleTestCase.java
   branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/BatchReplicationClusteredSessionValve.java
   branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java
   branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSessionValve.java
   branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheClusteredSession.java
   branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java
   branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManagerMBean.java
   branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java
Log:
[JBPAPP-944] Default maxUnreplicatedInterval to 60 secs; make configurable

Modified: branches/JBPAPP_4_2_0_GA_CP/server/src/resources/42specific/org/jboss/metadata/WebMetaData.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/server/src/resources/42specific/org/jboss/metadata/WebMetaData.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/server/src/resources/42specific/org/jboss/metadata/WebMetaData.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -198,6 +198,10 @@
     * for pojo replication or not.
     */
    private boolean replicationFieldBatchMode = true;
+   
+   /** By default replicate clustered session metadata at least every 60 seconds */
+   public static final int DEFAULT_MAX_UNREPLICATED_INTERVAL = 60;   
+   private int maxUnreplicatedInterval = DEFAULT_MAX_UNREPLICATED_INTERVAL;
 
    /** Should the context use session cookies or use default */
    private int sessionCookies = SESSION_COOKIES_DEFAULT;
@@ -843,7 +847,22 @@
    {
       return replicationFieldBatchMode;
    }
+   
+   public void setReplicationFieldBatchMode(boolean batchMode)
+   {
+      this.replicationFieldBatchMode = batchMode;
+   }
 
+   public int getMaxUnreplicatedInterval()
+   {
+      return maxUnreplicatedInterval;
+   }
+
+   public void setMaxUnreplicatedInterval(int maxUnreplicatedInterval)
+   {
+      this.maxUnreplicatedInterval = maxUnreplicatedInterval;
+   }
+
    public void importXml(Element element) throws DeploymentException
    {
       String rootTag = element.getOwnerDocument().getDocumentElement().getTagName();
@@ -1330,7 +1349,7 @@
                      + "' (should be ['SYNC', 'ASYNC']) in jboss-web.xml");
          }
 
-         // ... then manage "replication-type".
+         // ... then manage "replication-granularity".
          //
          Element replicationGranularityElement = MetaData.getOptionalChild(sessionReplicationRootElement,
                "replication-granularity");
@@ -1355,6 +1374,22 @@
             Boolean flag = Boolean.valueOf(MetaData.getElementContent(batchModeElement));
             replicationFieldBatchMode = flag.booleanValue();
          }
+
+         Element maxUnreplicatedIntervalElement = MetaData.getOptionalChild(sessionReplicationRootElement, "max-unreplicated-interval");
+         if (maxUnreplicatedIntervalElement != null)
+         {
+            String maxUnrep =  MetaData.getElementContent(maxUnreplicatedIntervalElement);
+            try
+            {
+               Integer interval = Integer.valueOf(maxUnrep);
+               maxUnreplicatedInterval = interval.intValue();
+            }
+            catch (NumberFormatException e)
+            {
+               throw new DeploymentException("max-unreplicated-interval value set to a non-integer value: '" + maxUnrep
+                     + " in jboss-web.xml");
+            }
+         }
       }
 
       // Check for a war level class loading config

Modified: branches/JBPAPP_4_2_0_GA_CP/server/src/resources/43specific/org/jboss/metadata/WebMetaData.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/server/src/resources/43specific/org/jboss/metadata/WebMetaData.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/server/src/resources/43specific/org/jboss/metadata/WebMetaData.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -198,6 +198,10 @@
     * for pojo replication or not.
     */
    private boolean replicationFieldBatchMode = true;
+   
+   /** By default replicate clustered session metadata at least every 60 seconds */
+   public static final int DEFAULT_MAX_UNREPLICATED_INTERVAL = 60;   
+   private int maxUnreplicatedInterval = DEFAULT_MAX_UNREPLICATED_INTERVAL;
 
    /** Should the context use session cookies or use default */
    private int sessionCookies = SESSION_COOKIES_DEFAULT;
@@ -843,7 +847,22 @@
    {
       return replicationFieldBatchMode;
    }
+   
+   public void setReplicationFieldBatchMode(boolean batchMode)
+   {
+      this.replicationFieldBatchMode = batchMode;
+   }
 
+   public int getMaxUnreplicatedInterval()
+   {
+      return maxUnreplicatedInterval;
+   }
+
+   public void setMaxUnreplicatedInterval(int maxUnreplicatedInterval)
+   {
+      this.maxUnreplicatedInterval = maxUnreplicatedInterval;
+   }
+
    public void importXml(Element element) throws DeploymentException
    {
       String rootTag = element.getOwnerDocument().getDocumentElement().getTagName();
@@ -1330,7 +1349,7 @@
                      + "' (should be ['SYNC', 'ASYNC']) in jboss-web.xml");
          }
 
-         // ... then manage "replication-type".
+         // ... then manage "replication-granularity".
          //
          Element replicationGranularityElement = MetaData.getOptionalChild(sessionReplicationRootElement,
                "replication-granularity");
@@ -1355,6 +1374,22 @@
             Boolean flag = Boolean.valueOf(MetaData.getElementContent(batchModeElement));
             replicationFieldBatchMode = flag.booleanValue();
          }
+
+         Element maxUnreplicatedIntervalElement = MetaData.getOptionalChild(sessionReplicationRootElement, "max-unreplicated-interval");
+         if (maxUnreplicatedIntervalElement != null)
+         {
+            String maxUnrep =  MetaData.getElementContent(maxUnreplicatedIntervalElement);
+            try
+            {
+               Integer interval = Integer.valueOf(maxUnrep);
+               maxUnreplicatedInterval = interval.intValue();
+            }
+            catch (NumberFormatException e)
+            {
+               throw new DeploymentException("max-unreplicated-interval value set to a non-integer value: '" + maxUnrep
+                     + " in jboss-web.xml");
+            }
+         }
       }
 
       // Check for a war level class loading config

Modified: branches/JBPAPP_4_2_0_GA_CP/server/src/resources/dtd/jboss-web_4_2.dtd
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/server/src/resources/dtd/jboss-web_4_2.dtd	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/server/src/resources/dtd/jboss-web_4_2.dtd	2008-07-09 02:45:48 UTC (rev 75518)
@@ -297,7 +297,7 @@
 <!--
    HTTP Session clustering configuration (optional tags)
 -->
-<!ELEMENT replication-config (replication-trigger?, replication-granularity, replication-field-batch-mode?)>
+<!ELEMENT replication-config (replication-trigger?, replication-granularity, replication-field-batch-mode?, max-unreplicated-interval?)>
 
 <!--
    Clustering only: Determines when the container should consider that a session
@@ -372,6 +372,38 @@
          <replication-field-batch-mode>FALSE</replication-field-batch-mode>
 -->
 <!ELEMENT replication-field-batch-mode (true|false)>
+
+<!--
+   Clustering only: Determines the maximum interval between requests, in 
+   seconds, after which a request will trigger replication of the session's 
+   timestamp and other metadata regardless of whether the request has otherwise 
+   made the session dirty.  Such replication ensures that other nodes in the 
+   cluster are aware of the most recent value for the session's timestamp 
+   and won't incorrectly expire an unreplicated session upon failover. It also
+   results in correct values for HttpSession.getLastAccessedTime() calls 
+   following failover.
+
+   The cost of this metadata replication depends on the configured
+   replication-granularity. With <code>SESSION</code>, the session's 
+   attribute map is replicated along with the metadata, so it can be fairly 
+   costly.  With other granularities, the metadata object is replicated 
+   separately from the attributes and only contains a String, and a few longs, 
+   ints and booleans.
+   
+   A value of 0 means the metadata will be replicated whenever the session is
+   accessed.  A value of -1 means the metadata will be replicated only if some
+   other activity during the request (e.g. modifying an attribute) has
+   resulted in other replication work involving the session. A positive value
+   greater than the HttpSession.getMaxInactiveInterval() value will be treated 
+   as a likely misconfiguration and converted to 0 -- i.e. replicate the 
+   metadata on every request.
+    
+   Default value is 60 seconds.
+   
+   This element was added in releases 4.2.3.GA, EAP 4.2.0.CP04 and EAP 4.2.0.CP02.
+   In releases prior to those it has no effect.
+-->
+<!ELEMENT max-unreplicated-interval (#PCDATA)>
 
 <!--
 Runtime information about a web service.

Modified: branches/JBPAPP_4_2_0_GA_CP/testsuite/build.xml
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/build.xml	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/build.xml	2008-07-09 02:45:48 UTC (rev 75518)
@@ -1286,6 +1286,7 @@
     <antcall target="tests-clustering-unit">
       <param name="cluster.includes.refid" value="cluster.http.includes"/>
       <param name="jboss-junit-configuration" value="BuddyReplEnabled-${jboss-junit-configuration}"/>
+      <param name="jbosstest.cluster.web.cache.br" value="true"/>
       <param name="jbosstest.cluster.node0.config" value="cluster-${jboss-junit-configuration}-BR-0"/>
       <param name="jbosstest.cluster.node1.config" value="cluster-${jboss-junit-configuration}-BR-1"/>
     </antcall>
@@ -3048,7 +3049,21 @@
     <property name="jboss-junit-configuration" value="TCP"/>
     <antcall target="one-cluster-test" inheritRefs="true"/>
   </target>
+	 
+  <target name="one-cluster-test-nostart" if="test">
 
+    <property name="jboss-junit-configuration" value="UDP"/>
+
+    <echo message="Going to call target tests-clustering-unit for ${test}"/>
+
+    <antcall target="tests-clustering-unit">
+      <param name="cluster.includes.refid" value="one.test.includes"/>
+      <param name="jboss-junit-configuration" value="Default-${jboss-junit-configuration}"/>
+      <param name="jbosstest.cluster.node0.config" value="cluster-${jboss-junit-configuration}-0"/>
+      <param name="jbosstest.cluster.node1.config" value="cluster-${jboss-junit-configuration}-1"/>
+    </antcall>	  	
+  </target>
+
   <!-- Misc tests of the testing framework itself
   -->
   <target name="tests-apache" description="Test that apache can be started/stopped from ant">

Modified: branches/JBPAPP_4_2_0_GA_CP/testsuite/imports/sections/cluster.xml
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/imports/sections/cluster.xml	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/imports/sections/cluster.xml	2008-07-09 02:45:48 UTC (rev 75518)
@@ -43,7 +43,10 @@
 
       <!-- build httpsessionreplication.jar -->
       <war warfile="${build.lib}/http-sr.war"
-         webxml="${build.resources}/cluster/http/web.xml">
+         webxml="${build.resources}/cluster/http/http-sr/WEB-INF/web.xml">
+         <webinf dir="${build.resources}/cluster/http/http-sr/WEB-INF">
+            <include name="jboss-web.xml"/>
+         </webinf>
          <fileset dir="${build.resources}/cluster/http">
             <include name="*.jsp"/>
          </fileset>

Copied: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/AttributeBasedMaxUnreplicatedIntervalTestCase.java (from rev 75506, branches/Branch_4_2/testsuite/src/main/org/jboss/test/cluster/test/AttributeBasedMaxUnreplicatedIntervalTestCase.java)
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/AttributeBasedMaxUnreplicatedIntervalTestCase.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/AttributeBasedMaxUnreplicatedIntervalTestCase.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,143 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.test;
+
+import junit.framework.Test;
+
+import org.jboss.metadata.WebMetaData;
+import org.jboss.test.cluster.web.util.BasicRequestHandler;
+import org.jboss.test.cluster.web.util.CacheConfigTestSetup;
+import org.jboss.test.cluster.web.util.SetAttributesRequestHandler;
+import org.jboss.test.cluster.web.util.WebSessionTestUtil;
+import org.jboss.web.tomcat.service.session.JBossCacheManager;
+
+/**
+ * Tests of handling of ClusteredSession.maxUnreplicatedInterval. This version
+ * is run with ATTRIBUTE granularity.
+ * 
+ * @author Brian Stansberry
+ *
+ */
+public class AttributeBasedMaxUnreplicatedIntervalTestCase 
+   extends SessionBasedMaxUnreplicatedIntervalTestCase
+{      
+   public AttributeBasedMaxUnreplicatedIntervalTestCase(String name)
+   {
+      super(name);
+   }
+   
+   public static Test suite() throws Exception
+   {
+      return CacheConfigTestSetup.getTestSetup(AttributeBasedMaxUnreplicatedIntervalTestCase.class, pojoCaches, false, !useBuddyRepl, false);
+   }
+   
+   protected int getReplicationGranularity()
+   {
+      return WebMetaData.REPLICATION_GRANULARITY_ATTRIBUTE;
+   }  
+   
+   /**
+    * A test of the "grace period" that maxUnreplicatedInterval adds to the
+    * removal of overaged unloaded sessions in remote caches. Confirms that a
+    * session still in the "grace period" doesn't have its cache structure
+    * removed.
+    * 
+    * @throws Exception
+    */
+   public void testMaxIntervalPreventsLossOfRemoteState() throws Exception
+   {
+      log.info("++++ Starting testMaxIntervalPreventsLossOfRemoteState ++++");
+      
+      String warname = String.valueOf(++testId);
+      
+      // A war with a maxInactive of 3 secs and a maxUnreplicated of 1
+      JBossCacheManager[] mgrs = getCacheManagers(warname, 3, 1);
+      JBossCacheManager jbcm0 = mgrs[0];
+      JBossCacheManager jbcm1 = mgrs[1];
+      
+      SetAttributesRequestHandler setHandler = new SetAttributesRequestHandler(allAttributes, false);
+      WebSessionTestUtil.invokeRequest(jbcm0, setHandler, null);
+      
+      validateNewSession(setHandler);
+      
+      Thread.sleep(250);
+      
+      // Now make a request that will not trigger replication but keeps the jbcm0 session alive
+      BasicRequestHandler getHandler = new BasicRequestHandler(immutables.keySet(), false);
+      WebSessionTestUtil.invokeRequest(jbcm0, getHandler, setHandler.getSessionId());
+      
+      validateExpectedAttributes(immutables, getHandler);
+      
+      // Sleep long enough that the session will be expired on other server
+      // if it doesn't have a maxUnreplicatedInterval grace period
+      Thread.sleep(2800);
+      
+      // jbcm1 considers the session unmodified for > 3 sec maxInactiveInterval.
+      // Try to drive the session out of the jbcm1 cache      
+      jbcm1.backgroundProcess();
+      
+      // Replicate just one attribute; see if the other is still in jbcm1
+      SetAttributesRequestHandler modifyHandler = new SetAttributesRequestHandler(mutables, false);
+      WebSessionTestUtil.invokeRequest(jbcm0, modifyHandler, setHandler.getSessionId());
+      
+      // Fail over and confirm all is well. If the session was removed,
+      // the last replication of just one attribute won't restore all
+      // attributes and we'll have a failure
+      getHandler = new BasicRequestHandler(allAttributes.keySet(), false);
+      WebSessionTestUtil.invokeRequest(jbcm1, getHandler, setHandler.getSessionId());
+      
+      validateExpectedAttributes(allAttributes, getHandler);
+   } 
+   
+   public void testDisabledMaxIntervalReplicatesOnDirtyAttribute() throws Exception
+   {
+      log.info("++++ Starting testDisabledMaxIntervalReplicatesOnDirtyAttribute ++++");
+      
+      String warname = String.valueOf(++testId);
+      
+      // A war with a maxInactive of 2 secs and a maxUnreplicated of -1
+      JBossCacheManager[] mgrs = getCacheManagers(warname, 2, -1);
+      JBossCacheManager jbcm0 = mgrs[0];
+      JBossCacheManager jbcm1 = mgrs[1];
+      
+      SetAttributesRequestHandler setHandler = new SetAttributesRequestHandler(allAttributes, false);
+      WebSessionTestUtil.invokeRequest(jbcm0, setHandler, null);
+      
+      validateNewSession(setHandler);
+      
+      Thread.sleep(250);
+      
+      SetAttributesRequestHandler modifyHandler = new SetAttributesRequestHandler(mutables, false);
+      WebSessionTestUtil.invokeRequest(jbcm0, modifyHandler, setHandler.getSessionId());
+      
+      Thread.sleep(1760);
+      
+      // Fail over and confirm all is well
+      BasicRequestHandler getHandler = new BasicRequestHandler(allAttributes.keySet(), false);
+      WebSessionTestUtil.invokeRequest(jbcm1, getHandler, setHandler.getSessionId());
+      
+      validateExpectedAttributes(allAttributes, getHandler);
+      
+   }
+
+}

Copied: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/FieldBasedMaxUnreplicatedIntervalTestCase.java (from rev 75506, branches/Branch_4_2/testsuite/src/main/org/jboss/test/cluster/test/FieldBasedMaxUnreplicatedIntervalTestCase.java)
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/FieldBasedMaxUnreplicatedIntervalTestCase.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/FieldBasedMaxUnreplicatedIntervalTestCase.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,59 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.test;
+
+import junit.framework.Test;
+
+import org.jboss.metadata.WebMetaData;
+import org.jboss.test.cluster.web.util.CacheConfigTestSetup;
+
+/**
+ * Tests of handling of ClusteredSession.maxUnreplicatedInterval. This version
+ * is run with FIELD granularity.
+ * 
+ * @author Brian Stansberry
+ */
+public class FieldBasedMaxUnreplicatedIntervalTestCase 
+   extends AttributeBasedMaxUnreplicatedIntervalTestCase
+{      
+   /**
+    * Create a new MaxUnreplicatedIntervalTestCase.
+    * 
+    * @param name
+    */
+   public FieldBasedMaxUnreplicatedIntervalTestCase(String name)
+   {
+      super(name);
+   }
+   
+   public static Test suite() throws Exception
+   {
+      return CacheConfigTestSetup.getTestSetup(FieldBasedMaxUnreplicatedIntervalTestCase.class, pojoCaches, false, !useBuddyRepl, true);
+   }
+   
+   protected int getReplicationGranularity()
+   {
+      return WebMetaData.REPLICATION_GRANULARITY_FIELD;
+   }   
+
+}

Copied: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/JBossWebXmlParsingTestCase.java (from rev 75506, branches/Branch_4_2/testsuite/src/main/org/jboss/test/cluster/test/JBossWebXmlParsingTestCase.java)
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/JBossWebXmlParsingTestCase.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/JBossWebXmlParsingTestCase.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,182 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.test;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.jboss.deployment.DeploymentException;
+import org.jboss.metadata.WebMetaData;
+import org.jboss.test.JBossTestCase;
+import org.w3c.dom.Document;
+
+/**
+ * Tests parsing of the replication-config elements in a jboss-web.xml.
+ * 
+ * @author Brian Stansberry
+ */
+public class JBossWebXmlParsingTestCase extends JBossTestCase
+{
+   private static final String RESOURCE_ROOT = "cluster/http/xmlparsing/";
+   private static final String ATTRIBUTE = RESOURCE_ROOT + "jboss-web-attr.xml";
+   private static final String BATCH_FALSE = RESOURCE_ROOT + "jboss-web-batch-false.xml";
+   private static final String BOGUS = RESOURCE_ROOT + "jboss-web-bogus.xml";
+   private static final String DEFAULT = RESOURCE_ROOT + "jboss-web-default.xml";
+   private static final String EMPTY = RESOURCE_ROOT + "jboss-web-empty.xml";
+   private static final String FIELD = RESOURCE_ROOT + "jboss-web-field.xml";
+   private static final String NO_MAX = RESOURCE_ROOT + "jboss-web-no-max.xml";
+   private static final String SET = RESOURCE_ROOT + "jboss-web-set.xml";
+   private static final String SET_AND_GET = RESOURCE_ROOT + "jboss-web-set-and-get.xml";
+   
+   private static enum Element { GRAN, TRIGGER, BATCH, MAX };
+   
+   /**
+    * Create a new JBossWebXmlParsingTestCase.
+    * 
+    * @param name
+    */
+   public JBossWebXmlParsingTestCase(String name)
+   {
+      super(name);
+   }
+   
+   public void testDefault() throws Exception
+   {      
+      WebMetaData metadata = getWebMetaData(DEFAULT);
+      defaultCheck(metadata);      
+   }
+   
+   public void testEmpty() throws Exception
+   {      
+      WebMetaData metadata = getWebMetaData(EMPTY);
+      defaultCheck(metadata);      
+   }
+   
+   public void testBogus() throws Exception
+   {      
+      try
+      {
+         getWebMetaData(BOGUS);
+         fail("Bogus config did not throw DeploymentException");
+      }
+      catch (DeploymentException expected) {}
+   }
+   
+   public void testAttributeGranularity() throws Exception
+   {
+      WebMetaData metadata = getWebMetaData(ATTRIBUTE);
+      assertEquals("Granularity", WebMetaData.REPLICATION_GRANULARITY_ATTRIBUTE, metadata.getReplicationGranularity());
+      defaultCheck(metadata, Element.GRAN);
+   }
+   
+   public void testFieldGranularity() throws Exception
+   {
+      WebMetaData metadata = getWebMetaData(FIELD);
+      assertEquals("Granularity", WebMetaData.REPLICATION_GRANULARITY_FIELD, metadata.getReplicationGranularity());
+      defaultCheck(metadata, Element.GRAN);
+   }
+   
+   public void testSetTrigger() throws Exception
+   {
+      WebMetaData metadata = getWebMetaData(SET);
+      assertEquals("Trigger", WebMetaData.SESSION_INVALIDATE_SET, metadata.getInvalidateSessionPolicy());
+      defaultCheck(metadata, Element.TRIGGER);
+   }
+   
+   public void testSetAndGetTrigger() throws Exception
+   {
+      WebMetaData metadata = getWebMetaData(SET_AND_GET);
+      assertEquals("Trigger", WebMetaData.SESSION_INVALIDATE_SET_AND_GET, metadata.getInvalidateSessionPolicy());
+      defaultCheck(metadata, Element.TRIGGER);
+   }
+   
+   public void testBatchModeFalse() throws Exception
+   {
+      WebMetaData metadata = getWebMetaData(BATCH_FALSE);
+      assertFalse("Batch mode", metadata.getReplicationFieldBatchMode());
+      defaultCheck(metadata, Element.BATCH);
+   }
+   
+   public void testMaxUnreplicatedInterval() throws Exception
+   {
+      WebMetaData metadata = getWebMetaData(NO_MAX);
+      assertEquals("Max unreplicated", -1, metadata.getMaxUnreplicatedInterval());
+      defaultCheck(metadata, Element.MAX);
+   }
+   
+   private WebMetaData getWebMetaData(String resourcePath) 
+   throws Exception
+   { 
+      ClassLoader cl = Thread.currentThread().getContextClassLoader();
+      URL webxml = cl.getResource(resourcePath);
+      assertNotNull("web.xml exists?", webxml);
+      return getWebMetaData(webxml.openStream());
+   }
+   
+   private WebMetaData getWebMetaData(InputStream webxml) 
+   throws Exception
+   { 
+      WebMetaData wmd = new WebMetaData();
+      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+      Document doc = factory.newDocumentBuilder().parse(webxml); 
+      wmd.importXml(doc.getDocumentElement()); 
+      return wmd; 
+   }    
+   
+   private void defaultCheck(WebMetaData metadata)
+   {
+      Set<Element> set = new HashSet<Element>();
+      defaultCheck(metadata, set);
+   }
+   
+   private void defaultCheck(WebMetaData metadata, Element ignore)
+   {
+      Set<Element> set = new HashSet<Element>();
+      set.add(ignore);
+      defaultCheck(metadata, set);
+   }
+   
+   private void defaultCheck(WebMetaData metadata, Set<Element> ignore)
+   {
+      if (!ignore.contains(Element.GRAN))
+      {
+         assertEquals("Granularity", WebMetaData.REPLICATION_GRANULARITY_SESSION, metadata.getReplicationGranularity());
+      }
+      if (!ignore.contains(Element.TRIGGER))
+      {
+         assertEquals("Trigger", WebMetaData.SESSION_INVALIDATE_SET_AND_NON_PRIMITIVE_GET, metadata.getInvalidateSessionPolicy());
+      }
+      if (!ignore.contains(Element.BATCH))
+      {
+         assertTrue("Batch mode", metadata.getReplicationFieldBatchMode());
+      }
+      if (!ignore.contains(Element.MAX))
+      {
+         assertEquals("Max unreplicated", WebMetaData.DEFAULT_MAX_UNREPLICATED_INTERVAL, metadata.getMaxUnreplicatedInterval());
+      }
+   }
+}

Modified: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/JvmRouteValveUnitTestCase.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/JvmRouteValveUnitTestCase.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/JvmRouteValveUnitTestCase.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -29,7 +29,7 @@
 import org.jboss.logging.Logger;
 import org.jboss.test.cluster.web.jvmroute.MockJBossManager;
 import org.jboss.test.cluster.web.jvmroute.MockRequest;
-import org.jboss.test.cluster.web.jvmroute.MockValve;
+import org.jboss.test.cluster.web.util.MockValve;
 import org.jboss.web.tomcat.service.session.JvmRouteValve;
 
 /**

Copied: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/SessionBasedMaxUnreplicatedIntervalTestCase.java (from rev 75506, branches/Branch_4_2/testsuite/src/main/org/jboss/test/cluster/test/SessionBasedMaxUnreplicatedIntervalTestCase.java)
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/SessionBasedMaxUnreplicatedIntervalTestCase.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/SessionBasedMaxUnreplicatedIntervalTestCase.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,299 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.Test;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.aop.PojoCache;
+import org.jboss.logging.Logger;
+import org.jboss.metadata.WebMetaData;
+import org.jboss.test.JBossTestCase;
+import org.jboss.test.cluster.web.util.BasicRequestHandler;
+import org.jboss.test.cluster.web.util.CacheConfigTestSetup;
+import org.jboss.test.cluster.web.util.MutableObject;
+import org.jboss.test.cluster.web.util.SetAttributesRequestHandler;
+import org.jboss.test.cluster.web.util.WebSessionTestUtil;
+import org.jboss.web.tomcat.service.session.JBossCacheManager;
+import org.jboss.web.tomcat.service.session.JBossCacheService;
+
+/**
+ * Tests of handling of ClusteredSession.maxUnreplicatedInterval.  This base
+ * test is run with SESSION granularity.
+ * 
+ * @author Brian Stansberry
+ */
+public class SessionBasedMaxUnreplicatedIntervalTestCase extends JBossTestCase
+{
+   protected static PojoCache[] pojoCaches = new PojoCache[2];
+
+   protected static long testId = System.currentTimeMillis();
+   
+   protected static boolean useBuddyRepl = Boolean.valueOf(System.getProperty("jbosstest.cluster.web.cache.br")).booleanValue();
+   
+   protected Logger log = Logger.getLogger(getClass());   
+   
+   protected Set<JBossCacheManager> managers = new HashSet<JBossCacheManager>();
+   
+   protected Map<String, Object> allAttributes;
+   protected Map<String, Object> immutables;
+   protected Map<String, Object> mutables;
+   
+   public SessionBasedMaxUnreplicatedIntervalTestCase(String name)
+   {
+      super(name);
+   }
+   
+   public static Test suite() throws Exception
+   {
+      return CacheConfigTestSetup.getTestSetup(SessionBasedMaxUnreplicatedIntervalTestCase.class, pojoCaches, false, !useBuddyRepl, false);
+   }
+
+   
+   @Override
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      
+      allAttributes = new HashMap<String, Object>();
+      immutables = new HashMap<String, Object>();
+      mutables = new HashMap<String, Object>();
+      
+      allAttributes.put("IMMUTABLE", "IMMUTABLE");
+      immutables.put("IMMUTABLE", "IMMUTABLE");
+      
+      MutableObject mo = new MutableObject("MUTABLE");
+      allAttributes.put("MUTABLE", mo);
+      mutables.put("MUTABLE", mo);
+      
+      allAttributes = Collections.unmodifiableMap(allAttributes);
+      immutables = Collections.unmodifiableMap(immutables);
+      mutables = Collections.unmodifiableMap(mutables);
+   }
+
+   @Override
+   protected void tearDown() throws Exception
+   {
+      super.tearDown();
+      
+      for (JBossCacheManager manager : managers)      
+         manager.stop();
+      
+      managers.clear();
+   }
+   
+   protected int getReplicationGranularity()
+   {
+      return WebMetaData.REPLICATION_GRANULARITY_SESSION;
+   }
+   
+   protected int getReplicationTrigger()
+   {
+      return WebMetaData.SESSION_INVALIDATE_SET_AND_NON_PRIMITIVE_GET;
+   }
+   
+   public void testBasicMaxIntervalPreventsExpiration() throws Exception
+   {
+      log.info("++++ Starting testBasicMaxIntervalPreventsExpiration ++++");
+      
+      maxIntervalPreventsExpirationTest(false);
+   }
+   
+   public void testZeroMaxIntervalPreventsExpiration() throws Exception
+   {
+      log.info("++++ Starting testZeroMaxIntervalPreventsExpiration ++++");
+      
+      maxIntervalPreventsExpirationTest(false);
+   }
+   
+   private void maxIntervalPreventsExpirationTest(boolean testZero) throws Exception
+   {
+      String warname = String.valueOf(++testId);
+      
+      int maxUnrep = testZero ? 0 : 1;
+      
+      // A war with a maxInactive of 3 secs and a maxUnreplicated of 0 or 1
+      JBossCacheManager[] mgrs = getCacheManagers(warname, 3, maxUnrep);
+      JBossCacheManager jbcm0 = mgrs[0];
+      JBossCacheManager jbcm1 = mgrs[1];
+      
+      SetAttributesRequestHandler setHandler = new SetAttributesRequestHandler(allAttributes, false);
+      WebSessionTestUtil.invokeRequest(jbcm0, setHandler, null);
+      
+      validateNewSession(setHandler);
+      
+      Thread.sleep(1050);
+      
+      // Now make a request that will not trigger replication unless the interval is exceeded
+      BasicRequestHandler getHandler = new BasicRequestHandler(immutables.keySet(), false);
+      WebSessionTestUtil.invokeRequest(jbcm0, getHandler, setHandler.getSessionId());
+      
+      validateExpectedAttributes(immutables, getHandler);
+      
+      // Sleep long enough that the session will be expired on other server
+      // if previous request didn't keep it alive
+      Thread.sleep(2000);
+      
+      // Fail over and confirm all is well
+      getHandler = new BasicRequestHandler(allAttributes.keySet(), false);
+      WebSessionTestUtil.invokeRequest(jbcm1, getHandler, setHandler.getSessionId());
+      
+      validateExpectedAttributes(allAttributes, getHandler);
+   }
+   
+   public void testMaxIntervalPreventsReplication() throws Exception
+   {
+      log.info("++++ Starting testMaxIntervalPreventsReplication ++++");
+      
+      String warname = String.valueOf(++testId);
+      
+      // A war with a maxInactive of 3 secs and a maxUnreplicated of 1
+      JBossCacheManager[] mgrs = getCacheManagers(warname, 3, 1);
+      JBossCacheManager jbcm0 = mgrs[0];
+      JBossCacheManager jbcm1 = mgrs[1];
+      
+      SetAttributesRequestHandler setHandler = new SetAttributesRequestHandler(allAttributes, false);
+      WebSessionTestUtil.invokeRequest(jbcm0, setHandler, null);
+      
+      // Sleep less than the maxUnreplicated time so next request shouldn't trigger timestamp repl
+      Thread.sleep(900);
+      
+      // Now make a request that will not trigger replication unless the interval is exceeded
+      BasicRequestHandler getHandler = new BasicRequestHandler(immutables.keySet(), false);
+      WebSessionTestUtil.invokeRequest(jbcm0, getHandler, setHandler.getSessionId());
+      
+      validateExpectedAttributes(immutables, getHandler);
+      
+      // Sleep long enough that the session will be expired on other server
+      // if previous request didn't keep it alive
+      Thread.sleep(2150);
+      
+      // Fail over and confirm the session was expired
+      getHandler = new BasicRequestHandler(allAttributes.keySet(), false);
+      WebSessionTestUtil.invokeRequest(jbcm1, getHandler, setHandler.getSessionId());
+      
+      validateNewSession(getHandler);
+   }
+   
+   /**
+    * Confirms that the "grace period" that maxUnreplicatedInterval adds to the
+    * removal of overaged unloaded sessions in remote caches delays their
+    * removal.
+    * 
+    * @throws Exception
+    */
+   public void testRemoteExpirationGracePeriod() throws Exception
+   {
+      log.info("++++ Starting testRemoteExpirationGracePeriod ++++");
+      
+      String warname = String.valueOf(++testId);
+      
+      JBossCacheManager[] mgrs = getCacheManagers(warname, 3, 2);
+      JBossCacheManager jbcm0 = mgrs[0];
+      JBossCacheManager jbcm1 = mgrs[1];
+      
+      SetAttributesRequestHandler setHandler1 = new SetAttributesRequestHandler(allAttributes, false);
+      WebSessionTestUtil.invokeRequest(jbcm0, setHandler1, null);
+      
+      Fqn session1Fqn = Fqn.fromString("/JSESSION/localhost/" + warname + "/" + setHandler1.getSessionId());
+      
+      SetAttributesRequestHandler setHandler2 = new SetAttributesRequestHandler(allAttributes, false);
+      WebSessionTestUtil.invokeRequest(jbcm0, setHandler2, null);
+      
+      Fqn session2Fqn = Fqn.fromString("/JSESSION/localhost/" + warname + "/" + setHandler2.getSessionId());
+      
+      // Overage the sessions
+      Thread.sleep(3010);
+      // Try to force out the overaged sessions
+      jbcm1.backgroundProcess();
+      // Confirm they are still there
+      assertNotNull(pojoCaches[1].get(session1Fqn, JBossCacheService.VERSION_KEY));
+      assertNotNull(pojoCaches[1].get(session2Fqn, JBossCacheService.VERSION_KEY));
+      
+      // Access one to prove it gets expired once the manager can see its real timestamp
+      BasicRequestHandler getHandler = new BasicRequestHandler(allAttributes.keySet(), false);
+      WebSessionTestUtil.invokeRequest(jbcm1, getHandler, setHandler1.getSessionId());      
+      validateNewSession(getHandler);
+      
+      // Sleep past the grace period
+      Thread.sleep(2010);
+      // The get restored a new fresh session with the first id, but the 2nd 
+      // one is still there and overaged. Try to force it out
+      jbcm1.backgroundProcess();
+      assertNull(pojoCaches[1].get(session2Fqn, JBossCacheService.VERSION_KEY));
+   }
+   
+   protected JBossCacheManager[] getCacheManagers(String warname, int maxInactive, int maxUnreplicated)
+      throws Exception
+   {
+      JBossCacheManager jbcm0 = WebSessionTestUtil.createManager(warname, maxInactive, pojoCaches[0], null);
+      WebMetaData metadata = WebSessionTestUtil.getWebMetaData(getReplicationGranularity(), getReplicationTrigger(), true, maxUnreplicated);
+      jbcm0.init(warname, metadata, false, true);
+      this.managers.add(jbcm0);
+      jbcm0.start();
+      
+      JBossCacheManager jbcm1 = WebSessionTestUtil.createManager(warname, maxInactive, pojoCaches[1], null);
+      metadata = WebSessionTestUtil.getWebMetaData(getReplicationGranularity(), getReplicationTrigger(), true, maxUnreplicated);
+      jbcm1.init(warname, metadata, false, true);
+      this.managers.add(jbcm1);
+      jbcm1.start();
+      
+      return new JBossCacheManager[]{jbcm0, jbcm1};
+   }
+   
+   protected void validateExpectedAttributes(Map<String, Object> expected, BasicRequestHandler handler)
+   {
+      assertFalse(handler.isNewSession());
+      
+      if (handler.isCheckAttributeNames())
+      {
+         assertEquals(expected.size(), handler.getAttributeNames().size());
+      }
+      Map<String, Object> checked = handler.getCheckedAttributes();
+      assertEquals(expected.size(), checked.size());
+      for (Map.Entry<String, Object> entry : checked.entrySet())
+         assertEquals(entry.getKey(), expected.get(entry.getKey()), entry.getValue());
+      
+   }
+   
+   protected void validateNewSession(BasicRequestHandler handler)
+   {
+      assertTrue(handler.isNewSession());
+      assertEquals(handler.getCreationTime(), handler.getLastAccessedTime());
+      if (handler.isCheckAttributeNames())
+      {
+         assertEquals(0, handler.getAttributeNames().size());
+      }
+      Map<String, Object> checked = handler.getCheckedAttributes();
+      for (Map.Entry<String, Object> entry : checked.entrySet())
+         assertNull(entry.getKey(), entry.getValue());
+   }
+   
+
+}

Modified: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/SimpleTestCase.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/SimpleTestCase.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/test/SimpleTestCase.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -21,11 +21,9 @@
  */
 package org.jboss.test.cluster.test;
 
-import javax.management.MBeanServerConnection;
-
 import junit.framework.Test;
+
 import org.apache.commons.httpclient.HttpClient;
-import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
 import org.jboss.test.JBossClusteredTestCase;
 
 /**
@@ -110,16 +108,6 @@
       HttpClient client = new HttpClient();
       makeGet(client, baseURL0_ +setURLName);
 
-      // Create a session on server 1.
-      HttpClient client1 = new HttpClient();
-      makeGet(client1, baseURL1_ +setURLName);
-      
-      // Find out the session id and use it to build an FQN
-      String sessionID = getSessionID(client1, servers_[1]);
-      // Strip off the jvmRoute, if there is one
-      sessionID = stripJvmRoute(sessionID);
-      String sessionFqn = "/JSESSION/localhost/http-sr/" + sessionID;
-
       sleepThread(6000);
       
       // Set the server0 session to ensure replication occurs
@@ -128,7 +116,7 @@
       attr = makeGetWithState(client, baseURL0_ +getURLName);
       assertNotNull("Http session get", attr);
       
-      // Sleep 15 secs.  This plus the previous 18 secs is enough to expire
+      // Sleep 15 secs.  This plus the previous 6 secs is enough to expire
       // session0 on server1 if replication failed to keep it alive
       sleepThread(15000);
       
@@ -149,32 +137,20 @@
       attr = makeGetWithState(client, baseURL0_ +getURLName);
       assertFalse("Original session not present", attr2.equals(attr));
       
-      // sleep 45 more seconds so session 1 will expire on server0.
-      // need a total of 70 secs -- 60 to expire and 10 to ensure the 
-      // bg thread runs. 20 secs to expire is not enough as the reduced
-      // life of this session is not available to the manager w/o 
-      // deserializing the session
-      sleepThread(45000);
-      
-      // Confirm 2nd session is gone from the distributed cache on node 0
-      MBeanServerConnection[] adaptors = getAdaptors();
-      assertEquals("Session gone from distributed cache for " + sessionFqn, 
-            null,
-            SessionTestUtil.getSessionVersion(adaptors[0], sessionFqn));
-      assertEquals("Session gone from distributed cache for " + sessionFqn,
-            null,
-            SessionTestUtil.getBuddySessionVersion(adaptors[0], sessionFqn));
-      
       getLog().debug("Exit testSessionTimeout");
    }
    
+   /**
+    * Tests that a request before maxUnreplicatedInterval has passed doesn't
+    * trigger replication.
+    */
    public void testMaxUnreplicatedInterval()
    {
       getLog().debug("Enter testMaxUnreplicatedInterval");
 
       String setURLName = "/http-sr/testsessionreplication.jsp";
       String getURLName = "/http-sr/getattribute.jsp";
-      String accessURLName = "/http-sr/access.jsp";
+      String versionURLName = "/http-sr/version.jsp";
 
       // Create an instance of HttpClient.
       HttpClient client = new HttpClient();
@@ -184,18 +160,23 @@
       // Get the Attribute set by testsessionreplication.jsp
       String attr = makeGetWithState(client, baseURL0_ +getURLName);
       
-      // Sleep 90% of the maxInactiveInterval
-      sleepThread(18000);
+      // Sleep a bit, but less than the 16 sec maxUnreplicatedInterval
+      sleepThread(500);
       
       // Access the session without touching any attribute
-      makeGet(client, baseURL0_ +accessURLName);
+      String ver = makeGetWithState(client, baseURL0_ +versionURLName);
       
-      // Sleep some more, long enough for the session to expire
-      // if access didn't cause replication and for the bg thread to run
-      sleepThread(17000);
+      // Sleep some more, long enough for the session to replicate
+      // if the last request incorrectly caused replication 
+      sleepThread(2000);
       
       // Switch servers
       setCookieDomainToThisServer(client, servers_[1]);
+      
+      String ver1 = makeGetWithState(client, baseURL1_ +versionURLName);
+      
+      assertEquals("Session version count unchanged", ver, ver1);
+      
       // Get the Attribute set by testsessionreplication.jsp
       String attr1 = makeGetWithState(client, baseURL1_ +getURLName);
       

Deleted: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockValve.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockValve.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/jvmroute/MockValve.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -1,92 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.test.cluster.web.jvmroute;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-
-import org.apache.catalina.CometEvent;
-import org.apache.catalina.Valve;
-import org.apache.catalina.connector.Request;
-import org.apache.catalina.connector.Response;
-
-/**
- * @author Brian Stansberry
- *
- */
-public class MockValve implements Valve
-{
-   private Request invokedRequest;
-   private Response invokedResponse;
-   
-   /**
-    * Create a new MockValve.
-    * 
-    */
-   public MockValve()
-   {
-   }
-
-   public void backgroundProcess()
-   {
-   }
-
-   public String getInfo()
-   {
-      return "MockValve";
-   }
-
-   public Valve getNext()
-   {
-      return null;
-   }
-
-   public void invoke(Request request, Response response) throws IOException, ServletException
-   {
-      this.invokedRequest = request;
-      this.invokedResponse = response;
-   }
-
-   public void setNext(Valve valve)
-   {
-
-   }
-
-   public Request getInvokedRequest()
-   {
-      return invokedRequest;
-   }
-
-   public Response getInvokedResponse()
-   {
-      return invokedResponse;
-   }
-
-   public void event(Request request, Response response, CometEvent event) throws IOException, ServletException
-   {
-   }
-   
-   
-
-}

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/BasicRequestHandler.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/BasicRequestHandler.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/BasicRequestHandler.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,135 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class BasicRequestHandler implements RequestHandler
+{
+   private Set<String> namesToCheck = new HashSet<String>();
+   private boolean checkAttributeNames;
+   private Map<String, Object> checkedAttributes = new HashMap<String, Object>();
+   private Set<String> attributeNames = new HashSet<String>();
+   private String sessionId;
+   private long lastAccessedTime;
+   private int maxInactiveInterval;
+   private long creationTime;
+   private boolean newSession;
+   private HttpSession session;
+   
+   /**
+    * Create a new AbstractRequestHandler.
+    * 
+    */
+   public BasicRequestHandler(Set<String> toCheck, boolean checkNames)
+   {      
+      if (toCheck != null)
+         this.namesToCheck.addAll(toCheck);
+      this.checkAttributeNames = checkNames;
+   }
+
+   public void handleRequest(Request request, Response response)
+   {
+      this.session = request.getSession();
+      this.sessionId = session.getId();
+      this.lastAccessedTime = session.getLastAccessedTime();
+      this.maxInactiveInterval = session.getMaxInactiveInterval();
+      this.newSession = session.isNew();
+      this.creationTime = session.getCreationTime();
+      
+      if (this.checkAttributeNames)
+      {
+         Enumeration<String> e = session.getAttributeNames();
+         while (e.hasMoreElements())
+            attributeNames.add(e.nextElement());
+      }
+      
+      if (namesToCheck != null)
+      {
+         for (String name : namesToCheck)
+         {
+            checkedAttributes.put(name, session.getAttribute(name));
+         }
+      }
+   }
+
+   public String getSessionId()
+   {
+      return sessionId;
+   }
+
+   public long getLastAccessedTime()
+   {
+      return lastAccessedTime;
+   }
+
+   public int getMaxInactiveInterval()
+   {
+      return maxInactiveInterval;
+   }
+
+   public boolean isNewSession()
+   {
+      return newSession;
+   }
+
+   public long getCreationTime()
+   {
+      return creationTime;
+   }
+
+   public Map<String, Object> getCheckedAttributes()
+   {
+      return checkedAttributes;
+   }
+
+   public Set<String> getAttributeNames()
+   {
+      return attributeNames;
+   }
+
+   public HttpSession getSession()
+   {
+      return session;
+   }
+
+   public boolean isCheckAttributeNames()
+   {
+      return checkAttributeNames;
+   }   
+   
+   
+}

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/CacheConfigTestSetup.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/CacheConfigTestSetup.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/CacheConfigTestSetup.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,135 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import java.net.InetAddress;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.jboss.cache.aop.PojoCache;
+import org.jboss.logging.Logger;
+import org.jboss.test.JBossTestSetup;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class CacheConfigTestSetup extends JBossTestSetup
+{
+   private static final Logger log = Logger.getLogger(CacheConfigTestSetup.class);
+   
+   public static Test getTestSetup(Class clazz, final PojoCache[] caches, final boolean local, final boolean totalReplication, final boolean marshalling)
+      throws Exception
+   {
+      final TestSuite suite = new TestSuite();
+      suite.addTest(new TestSuite(clazz));
+      return new CacheConfigTestSetup(suite, caches, local, totalReplication, marshalling);
+   }
+   
+   private PojoCache[] pojoCaches;
+   private boolean local;
+   private boolean totalReplication;
+   private boolean marshalling;
+   
+   /**
+    * Create a new CacheConfigTestSetup.
+    * 
+    * @param test
+    * @throws Exception
+    */
+   public CacheConfigTestSetup(Test test, PojoCache[] caches, boolean local, boolean totalReplication, final boolean marshalling) throws Exception
+   {
+      super(test);
+      this.pojoCaches = caches;
+      this.local = local;
+      this.totalReplication = totalReplication;
+      this.marshalling = marshalling;
+   }
+   
+   protected void setUp() throws Exception
+   {
+      if (pojoCaches == null) return;
+      String bind_addr = System.getProperty("jgroups.bind_addr");
+      String mcast_addr = System.getProperty("jgroups.udp.mcast_addr");
+      String mcast_port =  System.getProperty("jgroups.udp.mcast_port");
+      
+      try
+      {
+         System.setProperty("jgroups.bind_addr", System.getProperty("jbosstest.cluster.node1", InetAddress.getLocalHost().getHostAddress()));
+         String udpGroup = System.getProperty("jbosstest.udpGroup", "233.54.54.54");
+         if (udpGroup.trim().length() ==0)
+            udpGroup = "233.54.54.54";
+         System.setProperty("jgroups.udp.mcast_addr", udpGroup);
+         System.setProperty("jgroups.udp.mcast_port", String.valueOf(54545));
+         
+         for (int i = 0; i < pojoCaches.length; i++)
+         {
+            pojoCaches[i] = WebSessionTestUtil.createCache(local, totalReplication, marshalling, null);
+         }
+      }
+      finally
+      {
+         if (bind_addr == null)
+            System.clearProperty("jgroups.bind_addr");
+         else
+            System.setProperty("jgroups.bind_addr", bind_addr);
+         if (mcast_addr == null)
+            System.clearProperty("jgroups.udp.mcast_addr");
+         else
+            System.setProperty("jgroups.udp.mcast_addr", mcast_addr);
+         if (mcast_port == null)
+            System.clearProperty("jgroups.udp.mcast_port");
+         else
+            System.setProperty("jgroups.udp.mcast_port", mcast_port);
+      }
+      
+      // wait a few seconds so that the cluster stabilize
+      synchronized (this)
+      {
+         wait(2000);
+      }
+   }
+
+   protected void tearDown() throws Exception
+   {
+      if (pojoCaches != null)
+      {
+         for (int i = 0; i < pojoCaches.length; i++)
+         {
+            try
+            {   
+               PojoCache pc = pojoCaches[i];
+               pojoCaches[i] = null;
+               pc.stop();
+               pc.destroy();
+            }
+            catch (Exception ex)
+            {
+               log.error("Failed stopping cache " + i);
+            }
+         }         
+      }
+   }
+
+}

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockContainer.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockContainer.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockContainer.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import org.apache.catalina.Loader;
+import org.apache.catalina.Pipeline;
+import org.apache.catalina.core.ContainerBase;
+import org.apache.catalina.core.StandardPipeline;
+import org.jboss.logging.Logger;
+
+/**
+ * Mock Container impl to wrap a JBossCacheManager in unit tests.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 64743 $
+ */
+public class MockContainer extends ContainerBase
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 1L;
+
+   private Loader loader;
+   
+   private Pipeline pipeline;
+
+   @Override
+   public Loader getLoader()
+   {
+      if (loader == null)
+      {
+         loader = new MockLoader();
+         loader.setContainer(this);
+      }
+      return loader;
+   }
+
+   public Pipeline getPipeline()
+   {
+      if (pipeline == null)
+      {
+         pipeline = new StandardPipeline(this);
+      }
+      return pipeline;
+   }
+
+   public void setLoader(Loader loader)
+   {
+      this.loader = loader;
+   }
+
+}

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockEngine.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockEngine.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockEngine.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import org.apache.catalina.Engine;
+import org.apache.catalina.Service;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockEngine extends MockContainer implements Engine
+{
+   private static final long serialVersionUID = 1L;
+   
+   private Service service;
+   private String defaultHost = "localhost";
+   private String jvmRoute;
+   
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Engine#getDefaultHost()
+    */
+   public String getDefaultHost()
+   {
+      return defaultHost;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Engine#getJvmRoute()
+    */
+   public String getJvmRoute()
+   {
+      return jvmRoute;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Engine#getService()
+    */
+   public Service getService()
+   {
+      return service;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Engine#setDefaultHost(java.lang.String)
+    */
+   public void setDefaultHost(String arg0)
+   {
+      this.defaultHost = arg0;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Engine#setJvmRoute(java.lang.String)
+    */
+   public void setJvmRoute(String arg0)
+   {
+      this.jvmRoute = arg0;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Engine#setService(org.apache.catalina.Service)
+    */
+   public void setService(Service arg0)
+   {
+      this.service = arg0;
+   }
+
+}


Property changes on: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockEngine.java
___________________________________________________________________
Name: svn:executable
   + *

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockHost.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockHost.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockHost.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Host;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockHost extends MockContainer implements Host
+{
+   private static final long serialVersionUID = 1L;
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#addAlias(java.lang.String)
+    */
+   public void addAlias(String arg0)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#findAliases()
+    */
+   public String[] findAliases()
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#getAppBase()
+    */
+   public String getAppBase()
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#getAutoDeploy()
+    */
+   public boolean getAutoDeploy()
+   {
+      // TODO Auto-generated method stub
+      return false;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#getConfigClass()
+    */
+   public String getConfigClass()
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#getDeployOnStartup()
+    */
+   public boolean getDeployOnStartup()
+   {
+      // TODO Auto-generated method stub
+      return false;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#getXmlNamespaceAware()
+    */
+   public boolean getXmlNamespaceAware()
+   {
+      // TODO Auto-generated method stub
+      return false;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#getXmlValidation()
+    */
+   public boolean getXmlValidation()
+   {
+      // TODO Auto-generated method stub
+      return false;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#map(java.lang.String)
+    */
+   public Context map(String arg0)
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#removeAlias(java.lang.String)
+    */
+   public void removeAlias(String arg0)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#setAppBase(java.lang.String)
+    */
+   public void setAppBase(String arg0)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#setAutoDeploy(boolean)
+    */
+   public void setAutoDeploy(boolean arg0)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#setConfigClass(java.lang.String)
+    */
+   public void setConfigClass(String arg0)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#setDeployOnStartup(boolean)
+    */
+   public void setDeployOnStartup(boolean arg0)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#setXmlNamespaceAware(boolean)
+    */
+   public void setXmlNamespaceAware(boolean arg0)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.catalina.Host#setXmlValidation(boolean)
+    */
+   public void setXmlValidation(boolean arg0)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+}


Property changes on: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockHost.java
___________________________________________________________________
Name: svn:executable
   + *

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockLoader.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockLoader.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockLoader.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import java.beans.PropertyChangeListener;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Loader;
+
+/**
+ * Mock Loader impl for use in unit tests.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 64679 $
+ */
+public class MockLoader implements Loader
+{
+   private Container container;
+   
+   public void addPropertyChangeListener(PropertyChangeListener listener)
+   {
+      // TODO Auto-generated method stub
+   }
+
+   public void addRepository(String repository)
+   {
+      // TODO Auto-generated method stub
+   }
+
+   public void backgroundProcess()
+   {
+      // TODO Auto-generated method stub
+   }
+
+   public String[] findRepositories()
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   public ClassLoader getClassLoader()
+   {      
+      return container == null ? getClass().getClassLoader() 
+                               : container.getClass().getClassLoader();
+   }
+
+   public Container getContainer()
+   {
+      return container;
+   }
+
+   public boolean getDelegate()
+   {
+      // TODO Auto-generated method stub
+      return false;
+   }
+
+   public String getInfo()
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   public boolean getReloadable()
+   {
+      // TODO Auto-generated method stub
+      return false;
+   }
+
+   public boolean modified()
+   {
+      // TODO Auto-generated method stub
+      return false;
+   }
+
+   public void removePropertyChangeListener(PropertyChangeListener listener)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   public void setContainer(Container container)
+   {
+      this.container = container;
+   }
+
+   public void setDelegate(boolean delegate)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   public void setReloadable(boolean reloadable)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+}

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockRequest.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockRequest.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockRequest.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,121 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import java.io.IOException;
+
+import org.apache.catalina.Manager;
+import org.apache.catalina.Session;
+import org.apache.catalina.connector.Request;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockRequest extends Request
+{
+   private Session session;
+   private String requestedSessionId;
+   private boolean requestedSessionIdFromURL;
+   
+   /**
+    * Create a new MockRequest.
+    * 
+    */
+   public MockRequest()
+   {      
+   }
+
+   @Override
+   public String getRequestedSessionId()
+   {
+      return requestedSessionId;
+   }
+
+   public void setRequestedSessionId(String requestedSessionId)
+   {
+      this.requestedSessionId = requestedSessionId;
+   }
+
+   
+   @Override
+   protected Session doGetSession(boolean create)
+   {
+      if (session == null)
+      {      
+         Manager manager = getContext().getManager();
+         if (requestedSessionId != null)
+         {
+            try {
+                session = manager.findSession(requestedSessionId);
+            } catch (IOException e) {
+                session = null;
+            }
+         }
+         
+         if (session == null && create)
+         {
+            session = manager.createSession(requestedSessionId);
+         }
+         
+         if (session != null)
+         {
+            session.access();
+         }
+      
+      }
+      
+      if (session != null && !session.isValid())
+      {
+         session = null;
+         doGetSession(create);
+      }
+      
+      return session;
+   }
+   
+   public void setSession(Session session)
+   {
+      this.session = session;
+   }
+
+   @Override
+   public boolean isRequestedSessionIdFromURL()
+   {
+      return requestedSessionIdFromURL;
+   }
+
+   public void setRequestedSessionIdFromURL(boolean requestedSessionIdFromURL)
+   {
+      this.requestedSessionIdFromURL = requestedSessionIdFromURL;
+   }
+
+   @Override
+   public void recycle()
+   {
+      if (session != null)
+         session.endAccess();
+   }   
+
+   
+}

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockValve.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockValve.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MockValve.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,74 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import org.apache.catalina.CometEvent;
+import org.apache.catalina.Valve;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.valves.ValveBase;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockValve extends ValveBase
+{
+   static
+   {
+      info = "MockValve";
+   }
+   
+   private Request invokedRequest;
+   private Response invokedResponse;
+   
+   /**
+    * Create a new MockValve.
+    * 
+    */
+   public MockValve()
+   {
+   }
+
+   @Override
+   public void invoke(Request request, Response response) throws IOException, ServletException
+   {
+      this.invokedRequest = request;
+      this.invokedResponse = response;
+   }
+
+   public Request getInvokedRequest()
+   {
+      return invokedRequest;
+   }
+
+   public Response getInvokedResponse()
+   {
+      return invokedResponse;
+   }
+
+}

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MutableObject.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MutableObject.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/MutableObject.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,85 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import java.io.Serializable;
+
+/**
+ * Simple wrapper around a string that will trigger replication on a get if
+ * SET_AND_NON_PRIMITIVE_GET is used.
+ * 
+ * @author Brian Stansberry
+ *
+ */
+public class MutableObject implements Serializable
+{   
+   /** The serialVersionUID */
+   private static final long serialVersionUID = -8800180646736265624L;
+ 
+   private String string;
+
+   /**
+    * Create a new MutableObject.
+    * 
+    */
+   public MutableObject(String string)
+   {
+      this.string = string;
+   }
+
+   public String getString()
+   {
+      return this.string;
+   }
+
+   public void setString(String string)
+   {
+      this.string = string;
+   }
+
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (obj instanceof MutableObject)
+      {
+         return this.string.equals(((MutableObject) obj).string);
+      }
+      return false;
+   }
+
+   @Override
+   public int hashCode()
+   {      
+      return this.string.hashCode();
+   }
+
+   @Override
+   public String toString()
+   {
+      return this.string;
+   }
+   
+   
+   
+
+}

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/RequestHandler.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/RequestHandler.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/RequestHandler.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,35 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public interface RequestHandler
+{
+   void handleRequest(Request request, Response response);
+}

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/RequestHandlerValve.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/RequestHandlerValve.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/RequestHandlerValve.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,69 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class RequestHandlerValve extends MockValve
+{
+   private RequestHandler requestHandler;
+   
+   public RequestHandlerValve(RequestHandler handler)
+   {
+      this.requestHandler = handler;
+   }
+
+   public String getInfo()
+   {
+      return "RequestHandlerValve";
+   }
+
+   public void invoke(Request request, Response response) throws IOException, ServletException
+   {
+      super.invoke(request, response);
+      requestHandler.handleRequest(request, response);
+   }
+
+   public RequestHandler getRequestHandler()
+   {
+      return requestHandler;
+   }
+
+   public void setRequestHandler(RequestHandler requestHandler)
+   {
+      this.requestHandler = requestHandler;
+   }  
+   
+   
+   
+
+}

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/SetAttributesRequestHandler.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/SetAttributesRequestHandler.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/SetAttributesRequestHandler.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,64 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.cluster.web.util;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpSession;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class SetAttributesRequestHandler extends BasicRequestHandler
+{
+   private Map<String, Object> toStore;
+   
+   /**
+    * Create a new EstablishSessionRequestHandler.
+    * 
+    */
+   public SetAttributesRequestHandler(Map<String, Object> toStore, boolean checkNames)
+   {      
+      super(toStore.keySet(), checkNames);
+      this.toStore = toStore;
+   }
+
+   public void handleRequest(Request request, Response response)
+   {
+      super.handleRequest(request, response);
+      
+      HttpSession session = getSession();
+      for (Map.Entry<String,Object> entry : toStore.entrySet())
+      {
+         session.setAttribute(entry.getKey(), entry.getValue());
+      }      
+   }
+   
+   
+
+   
+}

Added: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/WebSessionTestUtil.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/WebSessionTestUtil.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/main/org/jboss/test/cluster/web/util/WebSessionTestUtil.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,191 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.cluster.web.util;
+
+import java.io.IOException;
+import java.util.Set;
+
+import javax.servlet.ServletException;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.Manager;
+import org.apache.catalina.Pipeline;
+import org.apache.catalina.Valve;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.core.StandardContext;
+import org.jboss.cache.PropertyConfigurator;
+import org.jboss.cache.aop.PojoCache;
+import org.jboss.metadata.WebMetaData;
+import org.jboss.web.tomcat.service.session.JBossCacheManager;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * A WebSessionTestUtil.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1.1 $
+ */
+public class WebSessionTestUtil
+{
+   private static final String CONFIG_LOCATION = "cluster/http/jboss-web-test-service.xml";
+   
+   public static final String JVM_ROUTE_0 = "node0";
+   public static final String JVM_ROUTE_1 = "node1";
+   
+   public static JBossCacheManager createManager(String warName, int maxInactiveInterval,
+                                                 boolean local, boolean totalReplication, 
+                                                 boolean marshalling, String jvmRoute, 
+                                                 Set<PojoCache> allCaches)
+      throws Exception
+   {
+      PojoCache cache = createCache(local, totalReplication, marshalling, allCaches);
+      return createManager(warName, maxInactiveInterval, cache, jvmRoute);
+   }
+   
+   public static JBossCacheManager createManager(String warName, 
+                                                 int maxInactiveInterval, 
+                                                 PojoCache cache, 
+                                                 String jvmRoute)
+   {
+      JBossCacheManager jbcm = new JBossCacheManager(cache);      
+      jbcm.setSnapshotMode("instant");
+      
+      MockEngine engine = new MockEngine();
+      engine.setJvmRoute(jvmRoute);
+      MockHost host = new MockHost();
+      engine.addChild(host);
+      host.setName("localhost");
+      StandardContext container = new StandardContext();
+      container.setName(warName);
+      host.addChild(container);
+      container.setManager(jbcm);
+      
+      // Do this after assigning the manager to the container, or else
+      // the container's setting will override ours
+      // Can't just set the container as their config is per minute not per second
+      jbcm.setMaxInactiveInterval(maxInactiveInterval);
+      return jbcm;      
+   }
+   
+   public static PojoCache createCache(boolean local, boolean totalReplication, 
+         boolean marshalling, Set<PojoCache> allCaches) throws Exception
+   {
+      PojoCache cache =  new PojoCache();
+      PropertyConfigurator config = new PropertyConfigurator();
+      config.configure(cache, CONFIG_LOCATION);
+      if (local)
+         cache.setCacheMode("LOCAL");
+      if (!totalReplication)
+      {
+         Element e = cache.getBuddyReplicationConfig();
+         
+         NodeList list = e.getChildNodes();
+         for (int i = 0; i < list.getLength(); i++)
+         {
+            Node node = list.item(i);
+            if (node.getNodeName().equals("buddyReplicationEnabled"))
+            {
+               node.setNodeValue("true");
+               break;
+            }
+         }
+         cache.setBuddyReplicationConfig(e);
+      }   
+      
+      if (marshalling)
+      {
+         cache.setUseRegionBasedMarshalling(true);
+         cache.setInactiveOnStartup(true);
+      }  
+      
+      if (allCaches != null)
+         allCaches.add(cache);
+      
+      cache.start();
+      return cache;
+   }
+   
+   public static void invokeRequest(Manager manager, RequestHandler handler, String sessionId)
+      throws ServletException, IOException
+   {
+      Valve valve = setupPipeline(manager, handler);
+      MockRequest request = new MockRequest();
+      request.setRequestedSessionId(sessionId);
+      request.setContext((Context) manager.getContainer());
+      Response response = new Response();
+      request.setResponse(response);
+      valve.invoke(request, response);
+      request.recycle();
+   }
+   
+   public static Valve setupPipeline(Manager manager, RequestHandler requestHandler)
+   {
+      Pipeline pipeline = manager.getContainer().getPipeline();
+      
+      // Clean out any existing request handler
+      Valve[] valves = pipeline.getValves();
+      RequestHandlerValve mockValve = null;
+      for (Valve valve: valves)
+      {
+         if (valve instanceof RequestHandlerValve)         
+         {
+            mockValve = (RequestHandlerValve) valve;
+            break;
+         }
+      }
+      
+      if (mockValve == null)
+      {
+         mockValve = new RequestHandlerValve(requestHandler);
+         pipeline.addValve(mockValve);
+      }
+      else
+      {
+         mockValve.setRequestHandler(requestHandler);
+      }
+      
+      return pipeline.getFirst();
+   }
+   
+   public static WebMetaData getWebMetaData(int granularity, int trigger, boolean batchMode, int maxUnreplicated)
+   {
+      WebMetaData metadata = new WebMetaData();
+      metadata.setDistributable(true);
+      metadata.setReplicationGranularity(granularity);
+      metadata.setInvalidateSessionPolicy(trigger);
+      metadata.setReplicationFieldBatchMode(batchMode);
+      metadata.setMaxUnreplicatedInterval(maxUnreplicated);
+      
+      return metadata;
+   }
+
+   /**
+    * Prevent external instantiation.
+    * 
+    */
+   private WebSessionTestUtil()
+   {      
+   }
+
+}

Copied: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/http-sr (from rev 75506, branches/Branch_4_2/testsuite/src/resources/cluster/http/http-sr)

Copied: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/jboss-web-test-service.xml (from rev 75507, branches/Branch_4_2/testsuite/src/resources/cluster/http/jboss-web-test-service.xml)
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/jboss-web-test-service.xml	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/jboss-web-test-service.xml	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- Can be parsed to create a basic configuration for unit tests -->
+
+<server>
+
+    <mbean code="org.jboss.cache.aop.PojoCache"
+        name="jboss.cache:service=TomcatClusteringTestCache">
+
+        <attribute name="ClusterName">Tomcat-TestCluster</attribute>
+
+        <!-- make sure to specify BatchModeTransactionManager only! -->
+        <attribute name="TransactionManagerLookupClass">org.jboss.cache.BatchModeTransactionManagerLookup</attribute>
+
+        <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+        <attribute name="CacheMode">REPL_SYNC</attribute>
+
+        <attribute name="SyncReplTimeout">20000</attribute>
+
+        <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+        <attribute name="UseRegionBasedMarshalling">false</attribute>
+        <attribute name="InactiveOnStartup">false</attribute>
+
+        <attribute name="BuddyReplicationConfig">
+            <config>
+                <buddyReplicationEnabled>false</buddyReplicationEnabled>
+                <buddyLocatorClass>org.jboss.cache.buddyreplication.NextMemberBuddyLocator</buddyLocatorClass>
+                <buddyLocatorProperties>
+                    numBuddies = 1
+                    ignoreColocatedBuddies = true
+                </buddyLocatorProperties>
+
+                <buddyPoolName>default</buddyPoolName>
+                <buddyCommunicationTimeout>2000</buddyCommunicationTimeout>
+
+                <autoDataGravitation>false</autoDataGravitation>
+                <dataGravitationRemoveOnFind>true</dataGravitationRemoveOnFind>
+                <dataGravitationSearchBackupTrees>true</dataGravitationSearchBackupTrees>
+
+            </config>
+        </attribute>
+         
+    </mbean>
+
+</server>

Copied: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/version.jsp (from rev 75516, branches/Branch_4_2/testsuite/src/resources/cluster/http/version.jsp)
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/version.jsp	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/version.jsp	2008-07-09 02:45:48 UTC (rev 75518)
@@ -0,0 +1,13 @@
+<%@page contentType="text/html"
+   import="org.jboss.mx.util.*"
+   import="javax.management.*"
+%>
+<%
+   MBeanServer server = MBeanServerLocator.locateJBoss();
+   ObjectName on = new ObjectName("jboss.cache:service=TomcatClusteringCache");
+   String fqn = "/JSESSION/localhost" + request.getContextPath() + "/" + session.getId();
+   Object[] params = { fqn, "VERSION" };
+   String[] types = new String[] { "java.lang.String", "java.lang.Object" };
+   Object version = server.invoke(on, "get", params, types);
+%>
+<%= version %>

Deleted: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/web.xml
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/web.xml	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/web.xml	2008-07-09 02:45:48 UTC (rev 75518)
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-
-<!DOCTYPE web-app
-    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
-    "http://java.sun.com/dtd/web-app_2_3.dtd">
-
-<web-app>
-  <display-name>Welcome to JBoss</display-name>
-  <description>
-     Welcome to JBoss
-  </description>
-  <distributable/>
-
-  <!-- timeout is set to 60 seconds -->
-  <session-config>
-     <session-timeout>1</session-timeout>
-  </session-config>
-</web-app>

Copied: branches/JBPAPP_4_2_0_GA_CP/testsuite/src/resources/cluster/http/xmlparsing (from rev 75507, branches/Branch_4_2/testsuite/src/resources/cluster/http/xmlparsing)

Modified: branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/BatchReplicationClusteredSessionValve.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/BatchReplicationClusteredSessionValve.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/BatchReplicationClusteredSessionValve.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -91,7 +91,13 @@
       // situation, this will cause data gravitation, which will occur 
       // thus outside of the scope of the tx we are about to start.  
       // JBossCacheManager will ensure the gravitation is in its own tx
-      request.getSession(false);
+      String requestedId = request.getRequestedSessionId();
+      if (requestedId != null)
+      {
+         // Use the manager directly so we don't invoke access() on a session
+         // that the request otherwise doesn't use
+         manager_.findSession(requestedId);
+      }
       
       // Start a new transaction, we need transaction so all the replication are sent in batch.
       try

Modified: branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSession.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -151,10 +151,7 @@
    protected transient long lastReplicated;
 
    /**
-    * Maximum percentage of the inactive interval this session
-    * should be allowed to go unreplicated if access to the
-    * session doesn't mark it as dirty. Drives the calculation
-    * of maxUnreplicatedInterval.
+    * @deprecated Not used
     */
    protected transient int maxUnreplicatedFactor = 80;
    
@@ -163,8 +160,11 @@
     * should be allowed to go unreplicated if access to the
     * session doesn't mark it as dirty. 
     */
-   protected transient long maxUnreplicatedInterval;
+   protected transient long maxUnreplicatedInterval = 0;
    
+   /** True if maxUnreplicatedInterval is 0 or less than maxInactiveInterval */
+   protected transient boolean alwaysReplicateMetadata = true;
+   
    /**
     * Whether any of this session's attributes implement
     * HttpSessionActivationListener.
@@ -200,7 +200,7 @@
       invalidationPolicy = manager.getInvalidateSessionPolicy();
       this.useJK = useJK;
       this.firstAccess = true;
-      calcMaxUnreplicatedInterval();
+      checkAlwaysReplicateMetadata();
    }
 
    /**
@@ -342,40 +342,18 @@
    }
 
    /**
-    * Gets the maximum percentage of the <code>maxInactiveInterval</code>
-    * beyond which a session should be replicated upon access even if it 
-    * isn't dirty.  Used to ensure that even a read-only session gets 
-    * replicated before it expires, so that it isn't removed from other
-    * nodes.
-    * 
-    * @return  an int between 1 and 100, or -1 if replicating on access is
-    *          disabled
+    * @deprecated Returns a meaningless value; use {@link #setMaxUnreplicatedInterval(int)}
     */
    public int getMaxUnreplicatedFactor()
    {
-      return maxUnreplicatedFactor;
+      return 80;
    }
 
    /**
-    * Sets the maximum percentage of the <code>maxInactiveInterval</code>
-    * beyond which a session should be replicated upon access even if it 
-    * isn't dirty.  Used to ensure that even a read-only session gets 
-    * replicated before it expires, so that it isn't removed from other
-    * nodes.
-    * 
-    * @param maxUnreplicatedFactor  an int between 1 and 100, or -1 to
-    *                               disable replicating on access
-    * 
-    * @throws IllegalArgumentException if the factor isn't -1 or between
-    *                                  1 and 100
+    * @deprecated Ignored; use {@link #setMaxUnreplicatedInterval(int)}
     */
    public void setMaxUnreplicatedFactor(int factor)
-   {
-      if ((factor != -1 && factor < 1) || factor > 100)
-         throw new IllegalArgumentException("Invalid factor " + factor +
-                                   " -- must be between 1 and 100 or -1");
-      this.maxUnreplicatedFactor = factor;
-      calcMaxUnreplicatedInterval();
+   {      
    }
    
 
@@ -386,7 +364,7 @@
    public void setMaxInactiveInterval(int interval)
    {
       super.setMaxInactiveInterval(interval);
-      calcMaxUnreplicatedInterval();
+      checkAlwaysReplicateMetadata();
       sessionMetadataDirty();
    }
 
@@ -408,32 +386,74 @@
       lastReplicated = System.currentTimeMillis();
    }
 
+   /**
+    * Get the maximum interval between requests, in <strong>milliseconds</strong>, 
+    * after which a request will trigger replication of the session's metadata 
+    * regardless of whether the request has otherwise made the session dirty. 
+    * <p/>
+    * <strong>NOTE:</strong> This value is in milliseconds while the equivalent
+    * property in JBossCacheManager is in seconds.
+    * 
+    * @return the maximum interval since last replication after which a request
+    *         will trigger session metadata replication. A value of 
+    *         <code>0</code> means replicate metadata on every request; a value 
+    *         of <code>-1</code> means never replicate metadata unless the 
+    *         session is otherwise dirty.
+    */
    public long getMaxUnreplicatedInterval()
    {
       return maxUnreplicatedInterval;
    }
+
+   /**
+    * Sets the maximum interval between requests, in <strong>milliseconds</strong>, 
+    * after which a request will trigger replication of the session's metadata 
+    * regardless of whether the request has otherwise made the session dirty. 
+    * <p/>
+    * <strong>NOTE:</strong> This value is in milliseconds while the equivalent
+    * property in JBossCacheManager is in seconds.
+    * 
+    * @param  maxUnreplicatedInterval  
+    *         the maximum interval since last replication after which a request
+    *         will trigger session metadata replication. A value of 
+    *         <code>0</code> means replicate metadata on every request; a value 
+    *         of <code>-1</code> means never replicate metadata unless the 
+    *         session is otherwise dirty. A value less than <code>-1</code> is
+    *         treated as <code>-1</code>.
+    */
+   public void setMaxUnreplicatedInterval(long interval)
+   {
+      this.maxUnreplicatedInterval = Math.max(interval, -1);
+      checkAlwaysReplicateMetadata();
+   }
    
    public boolean getExceedsMaxUnreplicatedInterval()
    {
-      boolean result = false;
+      boolean exceeds = alwaysReplicateMetadata;
       
-      if (maxUnreplicatedInterval > 0) // -1 means ignore; 0 means expire now
+      if (!exceeds && maxUnreplicatedInterval > 0) // -1 means ignore
       {
-         result = ((System.currentTimeMillis() - lastReplicated) >= maxUnreplicatedInterval);
+         long unrepl = System.currentTimeMillis() - lastReplicated;
+         exceeds = (unrepl >= maxUnreplicatedInterval);
       }      
       
-      return result;
+      return exceeds;
    }
    
-   private void calcMaxUnreplicatedInterval()
+   private void checkAlwaysReplicateMetadata()
    {
-      if (maxInactiveInterval < 0 || maxUnreplicatedFactor < 0)
-         maxUnreplicatedInterval = -1;
-      else
+      boolean was = this.alwaysReplicateMetadata;
+      this.alwaysReplicateMetadata = 
+         (maxUnreplicatedInterval == 0 
+            || (maxUnreplicatedInterval > 0 && maxInactiveInterval >= 0 
+                  && maxUnreplicatedInterval > (maxInactiveInterval * 1000)));
+      
+      if (this.alwaysReplicateMetadata && !was && log.isTraceEnabled())
       {
-         // Ignoring casting would be (mII * 1000) * (mUF / 100)
-         maxUnreplicatedInterval = maxInactiveInterval * maxUnreplicatedFactor * 10;
-      }
+         log.trace(id + " will always replicate metadata; maxUnreplicatedInterval=" 
+                   + maxUnreplicatedInterval
+                   + ", maxInactiveInterval=" + maxInactiveInterval);
+      }  
    }
 
    /**
@@ -1012,8 +1032,8 @@
       version = 0;
       hasActivationListener = null;
       lastReplicated = 0;
-      maxUnreplicatedFactor = 80;
-      calcMaxUnreplicatedInterval();
+      maxUnreplicatedInterval = 0;
+      this.alwaysReplicateMetadata = true;
    }
    
    /**
@@ -1132,6 +1152,12 @@
          // access cannot be the first.
          this.firstAccess = false;
          
+         // Assume deserialization means replication and use thisAccessedTime
+         // as a proxy for when replication occurred
+         this.lastReplicated = this.thisAccessedTime;
+         
+         checkAlwaysReplicateMetadata();
+         
          // TODO uncomment when work on JBAS-1900 is completed      
 //         // Session notes -- for FORM auth apps, allow replicated session 
 //         // to be used without requiring a new login
@@ -1426,7 +1452,8 @@
    
    public boolean getReplicateSessionBody()
    {
-      return sessionMetadataDirty || getExceedsMaxUnreplicatedInterval();
+      return sessionMetadataDirty || getExceedsMaxUnreplicatedInterval()
+                || (maxUnreplicatedInterval == -1 && sessionAttributesDirty);
    }
 
    protected boolean isGetDirty(Object attribute)

Modified: branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSessionValve.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSessionValve.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/ClusteredSessionValve.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -51,13 +51,15 @@
 
    // Valve-lifecycle_ helper object
    protected LifecycleSupport support = new LifecycleSupport(this);
+   
+   protected Manager manager;
 
    /**
     * Create a new Valve.
     */
-   public ClusteredSessionValve()
+   public ClusteredSessionValve(Manager manager)
    {
-      super();
+      this.manager = manager;
    }
 
    /**
@@ -83,6 +85,14 @@
       SessionReplicationContext.enterWebapp(request, response, true);
       try
       {  
+         // Workaround to JBAS-5735. Ensure we get the session from the manager
+         // rather than a cached ref from the Request.
+         String requestedId = request.getRequestedSessionId();
+         if (requestedId != null)
+         {
+            manager.findSession(requestedId);
+         }
+         
          // let the servlet invocation go through
          getNext().invoke(request, response);
       }

Modified: branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheClusteredSession.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheClusteredSession.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheClusteredSession.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -45,6 +45,8 @@
    public JBossCacheClusteredSession(JBossCacheManager manager)
    {
       super(manager, manager.getUseJK());
+      int maxUnrep = manager.getMaxUnreplicatedInterval() * 1000;
+      setMaxUnreplicatedInterval(maxUnrep);
       establishProxy();
    }
 

Modified: branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManager.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -45,6 +45,7 @@
 import org.apache.catalina.Valve;
 import org.apache.catalina.core.ContainerBase;
 import org.jboss.cache.CacheException;
+import org.jboss.cache.aop.PojoCacheMBean;
 import org.jboss.metadata.WebMetaData;
 import org.jboss.mx.util.MBeanServerLocator;
 import org.jboss.web.tomcat.service.JBossWeb;
@@ -61,9 +62,8 @@
 public class JBossCacheManager
    extends JBossManager
    implements JBossCacheManagerMBean
-{
-
-  /**
+{  
+   /**
     * Informational name for this Catalina component
     */
    static final String info_ = "JBossCacheManager/1.0";
@@ -130,6 +130,8 @@
     * Whether we are doing trace level logging
     */
    private boolean trace;
+   
+   private int maxUnreplicatedInterval_ = WebMetaData.DEFAULT_MAX_UNREPLICATED_INTERVAL;
 
    //  ----------------------------------------------------------  Constructors
 
@@ -137,6 +139,17 @@
    {
       super();
    }
+   
+   /** 
+    * Create a new JBossCacheManager using the given cache. For use in unit testing.
+    * 
+    * @param pojoCache
+    */
+   public JBossCacheManager(PojoCacheMBean pojoCache)
+   {
+      super();
+      this.proxy_ = new JBossCacheService(pojoCache);
+   }
 
    /**
     * Initializes this Manager when running in embedded mode.
@@ -154,7 +167,10 @@
       this.replicationFieldBatchMode_ =
          webMetaData.getReplicationFieldBatchMode() ? Boolean.TRUE : Boolean.FALSE;
       
-      proxy_ = new JBossCacheService(cacheObjectNameString_);
+      this.maxUnreplicatedInterval_ = webMetaData.getMaxUnreplicatedInterval();
+      
+      if (proxy_ == null)
+         proxy_ = new JBossCacheService(cacheObjectNameString_);
 
       // Confirm our replication granularity is compatible with the cache
       // Throws ISE if not
@@ -377,6 +393,16 @@
    {
       this.useLocalCache_ = useLocalCache;
    }
+   
+   public int getMaxUnreplicatedInterval()
+   {
+      return maxUnreplicatedInterval_;
+   }
+   
+   public void setMaxUnreplicatedInterval(int maxUnreplicatedInterval)
+   {
+      this.maxUnreplicatedInterval_ = maxUnreplicatedInterval;
+   }
 
    // JBossCacheManagerMBean-methods -------------------------------------
 
@@ -1019,7 +1045,7 @@
             }
             catch (Exception exn)
             {
-               exn.printStackTrace();
+               log_.error("Problem rolling back session mgmt transaction", exn);
             }
             
             // We will need to alert Tomcat of this exception.
@@ -1248,12 +1274,18 @@
          long now = System.currentTimeMillis();
          Map unloaded = new HashMap(unloadedSessions_);
          Set entries = unloaded.entrySet();
+         // We may have not gotten replication of a timestamp for requests 
+         // that occurred w/in maxUnreplicatedInterval_ of the previous
+         // request. So we add a grace period to avoid flushing a session early
+         // and permanently losing part of its node structure in JBoss Cache.
+         long maxUnrep = maxUnreplicatedInterval_ < 0 ? 60 : maxUnreplicatedInterval_;
+         long maxUnused = maxInactiveInterval_ + maxUnrep;
          for (Iterator it = entries.iterator(); it.hasNext(); )
          {
             Map.Entry entry = (Map.Entry) it.next();
             OwnedSessionUpdate osu = (OwnedSessionUpdate) entry.getValue();
             int elapsed = (int) ((now - osu.updateTime) / 1000L);
-            if (elapsed >= maxInactiveInterval_)
+            if (elapsed >= maxUnused)
             {
                String realId = (String) entry.getKey();
                try
@@ -1699,7 +1731,7 @@
       }
 
       // Add clustered session valve
-      ClusteredSessionValve valve = new ClusteredSessionValve();
+      ClusteredSessionValve valve = new ClusteredSessionValve(this);
       installContextValve(valve);
    }
 

Modified: branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManagerMBean.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManagerMBean.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheManagerMBean.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -109,6 +109,45 @@
     * is used.
     */
    int getSnapshotInterval();
+
+   /**
+    * Get the maximum interval between requests, in seconds, after which a
+    * request will trigger replication of the session's metadata regardless
+    * of whether the request has otherwise made the session dirty. Such 
+    * replication ensures that other nodes in the cluster are aware of a 
+    * relatively recent value for the session's timestamp and won't incorrectly
+    * expire an unreplicated session upon failover.
+    * <p/>
+    * Default value is {@link #DEFAULT_MAX_UNREPLICATED_INTERVAL}.
+    * <p/>
+    * The cost of the metadata replication depends on the configured
+    * {@link #setReplicationGranularityString(String) replication granularity}.
+    * With <code>SESSION</code>, the sesssion's attribute map is replicated 
+    * along with the metadata, so it can be fairly costly.  With other 
+    * granularities, the metadata object is replicated separately from the
+    * attributes and only contains a String, and a few longs, ints and booleans.
+    * 
+    * @return the maximum interval since last replication after which a request
+    *         will trigger session metadata replication. A value of 
+    *         <code>0</code> means replicate metadata on every request; a value 
+    *         of <code>-1</code> means never replicate metadata unless the 
+    *         session is otherwise dirty.
+    */
+   public int getMaxUnreplicatedInterval();
+
+   /**
+    * Sets the maximum interval between requests, in seconds, after which a
+    * request will trigger replication of the session's metadata regardless
+    * of whether the request has otherwise made the session dirty.
+    * 
+    * @param  maxUnreplicatedInterval  
+    *         the maximum interval since last replication after which a request
+    *         will trigger session metadata replication. A value of 
+    *         <code>0</code> means replicate metadata on every request; a value 
+    *         of <code>-1</code> means never replicate metadata unless the 
+    *         session is otherwise dirty.
+    */
+   public void setMaxUnreplicatedInterval(int maxUnreplicatedInterval);
    
    /**
     * Lists all session ids known to this manager, including those in the 

Modified: branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java	2008-07-09 02:13:10 UTC (rev 75517)
+++ branches/JBPAPP_4_2_0_GA_CP/tomcat/src/main/org/jboss/web/tomcat/service/session/JBossCacheService.java	2008-07-09 02:45:48 UTC (rev 75518)
@@ -71,11 +71,10 @@
    public static final String SESSION = "JSESSION";
    public static final String ATTRIBUTE = "ATTRIBUTE";
    // Needed for cache invalidation
-   static final String VERSION_KEY = "VERSION";
+   public static final String VERSION_KEY = "VERSION";
    static final String FQN_DELIMITER = "/";
    
    private PojoCacheMBean proxy_;
-   private ObjectName cacheServiceName_;
    
    // name of webapp's virtual host(JBAS-2194). 
    // Idea is host_name + web_app_path + session id is a unique combo.
@@ -95,39 +94,46 @@
    
    private WeakHashMap typeMap = new WeakHashMap();
    
-   public JBossCacheService(String treeCacheObjectName) throws ClusteringNotSupportedException
+   /**
+    * Creates a JMX proxy PojoCacheMBean for the given object name.
+    * 
+    * @param objectName the object name
+    * @return the proxy
+    * @throws ClusteringNotSupportedException if there is a problem
+    */
+   private static PojoCacheMBean getPojoCacheMBean(String objectName)
+      throws ClusteringNotSupportedException
    {
-      // Find JBossCacheService
       try
       {
-         cacheServiceName_ = new ObjectName(treeCacheObjectName);
+         ObjectName cacheServiceName = new ObjectName(objectName);
          // Create Proxy-Object for this service
-         proxy_ = (PojoCacheMBean) MBeanProxyExt.create(PojoCacheMBean.class,
-                                                        cacheServiceName_);
+         return (PojoCacheMBean) MBeanProxyExt.create(PojoCacheMBean.class,
+                                                        cacheServiceName);
       }
       catch (Throwable t)
       {
-
          String str = "Could not access TreeCache service " + 
-                     (cacheServiceName_ == null ? "<null>" : cacheServiceName_.toString()) + 
+                     (objectName == null ? "<null>" : objectName) + 
                      " for Tomcat clustering";
          log_.debug(str);
          throw new ClusteringNotSupportedException(str, t);
-      }
-      
-      if (proxy_ == null)
-      {
-         String str = "Could not access TreeCache service " + 
-                     (cacheServiceName_ == null ? "<null>" : cacheServiceName_.toString()) + 
-                     " for Tomcat clustering";
-         log_.debug(str);
-         throw new ClusteringNotSupportedException(str);
-      }
+      }  
+   }
+   
+   public JBossCacheService(PojoCacheMBean pojoCache)
+   {
+      this.proxy_ = pojoCache;
 
       cacheWrapper_ = new JBossCacheWrapper(proxy_);
       
       useTreeCacheMarshalling_ = proxy_.getUseRegionBasedMarshalling();
    }
+   
+   public JBossCacheService(String treeCacheObjectName) throws ClusteringNotSupportedException
+   {
+      this(getPojoCacheMBean(treeCacheObjectName));
+   }
 
    public void start(ClassLoader tcl, JBossCacheManager manager)
    {
@@ -280,7 +286,7 @@
          }
          catch (Exception e)
          {
-            log_.error("loadSession(): id: " + realId + "exception occurred during serialization: " +e);
+            log_.error("loadSession(): id: " + realId + " exception occurred during deserialization", e);
             return null;
          }
          finally {




More information about the jboss-cvs-commits mailing list