[jboss-cvs] JBossAS SVN: r70720 - in projects/ejb3/branches/cluster-dev/ejb3-cache: src/main/java/org/jboss/ejb3/cache and 14 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Mar 11 00:27:49 EDT 2008


Author: bstansberry at jboss.com
Date: 2008-03-11 00:27:49 -0400 (Tue, 11 Mar 2008)
New Revision: 70720

Added:
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/CacheFactoryNotRegisteredException.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/CacheItem.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/SerializationGroup.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulCacheFactory.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulCacheFactoryRegistry.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupAwareTransactionalCache.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/TransactionalCache.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/GroupAwareBackingCacheImpl.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/NonPassivatingBackingCacheEntry.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/NonPassivatingBackingCacheImpl.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/PassivatingBackingCacheImpl.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SerializationGroupContainer.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SerializationGroupMemberContainer.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SimplePassivatingIntegratedObjectStore.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/GroupAwareCacheFactory.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/NonClusteredIntegratedObjectStoreSource.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/NonPassivatingCacheFactory.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/PassivationExpirationCoordinatorImpl.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/BackingCache.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/BackingCacheEntry.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/GroupAwareBackingCache.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/GroupIncompatibilityException.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/IntegratedObjectStore.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/IntegratedObjectStoreSource.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/ObjectStore.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivatingBackingCache.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivatingIntegratedObjectStore.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivationExpirationCoordinator.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivationExpirationProcessor.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractBackingCacheEntry.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractStatefulCacheFactory.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractTimerTask.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/CacheableTimestamp.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/FileObjectStore.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/PassivationExpirationRunner.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/SerializationGroupImpl.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/SerializationGroupMember.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/impl/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/impl/backing/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/impl/backing/PassivatingBackingCacheImplUnitTestCase.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/Ejb3CacheTestCaseBase.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/GroupAwareTransactionalCacheUnitTestCase.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/TransactionalCacheUnitTestCase.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/CacheType.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockBeanContainer.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockBeanContext.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockCacheConfig.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockCacheItem.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockEjb3System.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockEntity.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockIdentifiable.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockPassivationManager.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockRegistry.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockStatefulObjectFactory.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockXPC.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/tm/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/tm/MockTransaction.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/tm/MockTransactionManager.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockCluster.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockClusterMember.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockIntegratedObjectStoreSource.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/UnmarshallingMap.java
Removed:
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/Cacheable.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/IntegratedObjectStore.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/ObjectStore.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivatingCache.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivatingIntegratedObjectStore.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/grouped/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/CacheableTimestamp.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/EntryStateCache.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/FileObjectStore.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupedPassivatingCacheImpl.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupedPassivatingCacheImpl2.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupContainer.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupImpl.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupMemberImpl.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimpleCache.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimpleIntegratedObjectStore.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimplePassivatingCache.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimplePassivatingCache2.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/cache/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockBeanContainer.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockBeanContext.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/grouped/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/integrated/
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/passivation/
Modified:
   projects/ejb3/branches/cluster-dev/ejb3-cache/.classpath
   projects/ejb3/branches/cluster-dev/ejb3-cache/pom.xml
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/Cache.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivationManager.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulObjectFactory.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/GroupedPassivatingUnitTestCase.java
   projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockJBCIntegratedObjectStore.java
Log:
[EJBTHREE-1026] check into sandbox redesigned API concepts, impls, test fixtures

Modified: projects/ejb3/branches/cluster-dev/ejb3-cache/.classpath
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/.classpath	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/.classpath	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,22 +1,23 @@
 <classpath>
   <classpathentry kind="src" path="src/main/java"/>
-  <classpathentry kind="src" path="src/test/java" output="target/test-classes"/>
-  <classpathentry kind="src" path="src/test/resources" output="target/test-classes" excluding="**/*.java"/>
+  <classpathentry kind="src" path="src/test/java" output="target/tests-classes"/>
+  <classpathentry kind="src" path="src/test/resources" output="target/tests-classes" excluding="**/*.java"/>
   <classpathentry kind="output" path="target/classes"/>
   <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+  <classpathentry kind="var" path="M2_REPO/jboss/jboss-common-logging-log4j/2.0.4.GA/jboss-common-logging-log4j-2.0.4.GA.jar"/>
+  <classpathentry kind="var" path="M2_REPO/jboss/jboss-common-logging-spi/2.0.4.GA/jboss-common-logging-spi-2.0.4.GA.jar"/>
+  <classpathentry kind="var" path="M2_REPO/jboss/jboss-common-core/2.0.4.GA/jboss-common-core-2.0.4.GA.jar"/>
+  <classpathentry kind="var" path="M2_REPO/apache-xerces/xml-apis/2.7.1/xml-apis-2.7.1.jar"/>
+  <classpathentry kind="var" path="M2_REPO/apache-httpclient/commons-httpclient/2.0.2/commons-httpclient-2.0.2.jar"/>
   <classpathentry kind="var" path="M2_REPO/oswego-concurrent/concurrent/1.3.4/concurrent-1.3.4.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/jboss/javaee/jboss-ejb-api/3.0.0.20070913080910/jboss-ejb-api-3.0.0.20070913080910.jar"/>
-  <classpathentry kind="var" path="M2_REPO/apache-xerces/xml-apis/2.7.1/xml-apis-2.7.1.jar"/>
-  <classpathentry kind="var" path="M2_REPO/jboss/jboss-common-core/2.0.4.GA/jboss-common-core-2.0.4.GA.jar"/>
-  <classpathentry kind="var" path="M2_REPO/jboss/jboss-common-logging-spi/2.0.4.GA/jboss-common-logging-spi-2.0.4.GA.jar"/>
   <classpathentry kind="var" path="M2_REPO/apache-slide/webdavlib/2.0/webdavlib-2.0.jar"/>
+  <classpathentry kind="var" path="M2_REPO/log4j/log4j/1.2.14/log4j-1.2.14.jar"/>
   <classpathentry kind="var" path="M2_REPO/jboss/jboss-serialization/1.0.3.GA/jboss-serialization-1.0.3.GA.jar"/>
-  <classpathentry kind="var" path="M2_REPO/log4j/log4j/1.2.14/log4j-1.2.14.jar"/>
+  <classpathentry kind="var" path="M2_REPO/junit/junit/4.4/junit-4.4.jar"/>
   <classpathentry kind="var" path="M2_REPO/org/jboss/jboss-common-core/2.2.1.GA/jboss-common-core-2.2.1.GA.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/jboss/javaee/jboss-transaction-api/1.0.1.20070913080910/jboss-transaction-api-1.0.1.20070913080910.jar"/>
-  <classpathentry kind="var" path="M2_REPO/trove/trove/2.1.1/trove-2.1.1.jar"/>
-  <classpathentry kind="var" path="M2_REPO/junit/junit/3.8.1/junit-3.8.1.jar"/>
-  <classpathentry kind="var" path="M2_REPO/jboss/jboss-common-logging-log4j/2.0.4.GA/jboss-common-logging-log4j-2.0.4.GA.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/jboss/ejb3/jboss-ejb3-ext-api/0.3-SNAPSHOT/jboss-ejb3-ext-api-0.3-SNAPSHOT.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/jboss/javaee/jboss-ejb-api/3.0.0.Beta3Update1/jboss-ejb-api-3.0.0.Beta3Update1.jar"/>
+  <classpathentry kind="var" path="M2_REPO/org/jboss/javaee/jboss-transaction-api/1.0.1.Beta3Update1/jboss-transaction-api-1.0.1.Beta3Update1.jar"/>
   <classpathentry kind="var" path="M2_REPO/jboss/jbossws/jboss-jaxrpc/1.0.4.GA/jboss-jaxrpc-1.0.4.GA.jar"/>
-  <classpathentry kind="var" path="M2_REPO/apache-httpclient/commons-httpclient/2.0.2/commons-httpclient-2.0.2.jar"/>
+  <classpathentry kind="var" path="M2_REPO/trove/trove/1.0.2/trove-1.0.2.jar"/>
 </classpath>
\ No newline at end of file

Modified: projects/ejb3/branches/cluster-dev/ejb3-cache/pom.xml
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/pom.xml	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/pom.xml	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,96 +1,79 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  vi:ts=2:sw=2:expandtab:
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <!-- Define Parent -->
   <parent>
-    <groupId>org.jboss</groupId>
-    <!--
-    <artifactId>jboss-ejb3</artifactId>
-    <version>0.11.0-SNAPSHOT</version>
+    <groupId>org.jboss.ejb3</groupId>
+    <artifactId>jboss-ejb3-build</artifactId>
+    <version>0.13.0-SNAPSHOT</version>
     <relativePath>../build/pom.xml</relativePath>
-    -->
-    <artifactId>jboss-parent</artifactId>
-    <version>3</version>
   </parent>
+
+  <!-- Maven POM Model Version -->
   <modelVersion>4.0.0</modelVersion>
-  <groupId>org.jboss</groupId>
+
+  <!-- Artifact Information -->
+  <groupId>org.jboss.ejb3</groupId>
   <artifactId>jboss-ejb3-cache</artifactId>
-  <version>0.11-SNAPSHOT</version>
+  <version>0.14.0-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>JBoss EJB 3.0 Cache</name>
-  <url>http://www.jboss.org</url>
+  <url>http://labs.jboss.com/jbossejb3/</url>
   <description>The Java EJB 3.0 Cache classes</description>
-  <scm>
-    <connection>scm:svn:http://anonsvn.jboss.org/repos/jbossas/projects/ejb3/trunk/</connection>
-    <developerConnection>scm:svn:https://svn.jboss.org/repos/jbossas/projects/ejb/trunk/</developerConnection>
-    <url>http://viewvc.jboss.org/cgi-bin/viewvc.cgi/jbossas/projects/ejb3/trunk/</url>
-  </scm>
-  <build>
-    <plugins>
-      <!-- Normally defined in the parent -->
-      <plugin>
-        <groupId>org.jboss.maven.plugins</groupId>
-        <artifactId>maven-jboss-deploy-plugin</artifactId>
-        <version>1.4</version>
-        <executions>
-          <execution>
-            <goals>
-              <goal>jboss-deploy</goal>
-            </goals>
-          </execution>
-        </executions>
-        <configuration>
-          <jbossDeployRoot>${jboss.repository.root}</jbossDeployRoot>
-          <groupId>jboss</groupId>
-        </configuration>
-        <inherited>true</inherited>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-release-plugin</artifactId>
-        <configuration>
-          <tagBase>https://svn.jboss.org/repos/jbossas/projects/ejb3/tags</tagBase>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
+
+
   <dependencies>
+
+    <!-- EJB3 API -->
     <dependency>
-      <groupId>org.jboss</groupId>
-      <artifactId>jboss-common-core</artifactId>
-      <version>2.2.1.GA</version>
+      <groupId>org.jboss.javaee</groupId>
+      <artifactId>jboss-ejb-api</artifactId>
     </dependency>
+    
+    <!-- EJB3 External API -->
     <dependency>
-      <groupId>jboss</groupId>
-      <artifactId>jboss-common-logging-spi</artifactId>
-      <version>2.0.4.GA</version>
+      <groupId>org.jboss.ejb3</groupId>
+      <artifactId>jboss-ejb3-ext-api</artifactId>
     </dependency>
+
+    <!-- GNU Trove -->
     <dependency>
-      <groupId>jboss</groupId>
-      <artifactId>jboss-common-logging-log4j</artifactId>
-      <version>2.0.4.GA</version>
-      <scope>test</scope>
+      <groupId>trove</groupId>
+      <artifactId>trove</artifactId>
+      <scope>runtime</scope>
     </dependency>
+
+    <!-- JBoss Common Core -->
     <dependency>
-      <groupId>org.jboss.javaee</groupId>
-      <artifactId>jboss-ejb-api</artifactId>
-      <version>3.0.0.20070913080910</version>
+      <groupId>org.jboss</groupId>
+      <artifactId>jboss-common-core</artifactId>
     </dependency>
+
+    <!-- JBoss Common Logging -->
     <dependency>
       <groupId>jboss</groupId>
+      <artifactId>jboss-common-logging-log4j</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+
+    <!-- JBoss Serialization -->
+    <dependency>
+      <groupId>jboss</groupId>
       <artifactId>jboss-serialization</artifactId>
-      <version>1.0.3.GA</version>
     </dependency>
+
+    <!-- JUnit -->
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>3.8.1</version>
       <scope>test</scope>
     </dependency>
-    
-    <!-- For jboss serialization -->
-    <dependency>
-      <groupId>trove</groupId>
-      <artifactId>trove</artifactId>
-      <version>2.1.1</version>
-      <scope>runtime</scope>
-    </dependency>
+
   </dependencies>
+
 </project>

Modified: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/Cache.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/Cache.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/Cache.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -23,6 +23,7 @@
 
 import javax.ejb.NoSuchEJBException;
 
+
 /**
  * Cache a stateful object and make sure any life cycle callbacks are
  * called at the appropriate time.
@@ -31,19 +32,27 @@
  * scope.
  *
  * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
+ * @author Brian Stansberry
+ * 
  * @version $Revision: $
  */
-public interface Cache<T extends Identifiable>
+public interface Cache<T extends CacheItem>
 {
    /**
-    * Create a new object.
+    * Creates and caches a new instance of <code>T</code>. The new
+    * <code>T</code> *is* returned, but is not regarded as being "in use".
+    * Callers *must not* attempt to use the new <code>T</code> without
+    * first calling {@link #get(Object)}. 
     * 
-    * @param initTypes
-    * @param initValues
-    * @return
+    * @param initTypes   the types of any <code>initValues</code>. 
+    *                    May be <code>null</code>.
+    * @param initValues  any paramaters to pass to <code>T</code>'s constructor.
+    *                    May be null, in which case a default constructor will
+    *                    be used.
+    * @return the new <code>T</code> 
     */
    T create(Class<?> initTypes[], Object initValues[]);
-   
+
    /**
     * Get the specified object from cache. This will mark
     * the object as being in use.
@@ -51,26 +60,27 @@
     * @param key    the identifier of the object
     * @return       the object
     * @throws NoSuchEJBException    if the object does not exist
+    * @throws IllegalStateException if the object is already in use by another
+    *                               transaction or if {@link #finished(CacheItem)}
+    *                               has not been invoked since the last time
+    *                               the object was gotten.
     */
    T get(Object key) throws NoSuchEJBException;
    
    /**
-    * Peek at an object which might be in use.
+    * Signal the finish of the current operation on the object.
+    * If the object was {@link #get(Object) gotten from the cache} in the 
+    * course of an ongoing transaction, the object will still be regarded as in 
+    * use, but <code>get()</code> can safely be invoked again by that same 
+    * transaction. If there was no transaction in effect when the object was 
+    * gotten from the cache, invoking this method marks the object as no
+    * longer being in use.
     * 
-    * @param key    the identifier of the object
-    * @return       the object
-    * @throws NoSuchEJBException    if the object does not exist
+    * @param obj object previously gotten via {@link #get(Object)}
     */
-   T peek(Object key) throws NoSuchEJBException;
-   
+   void finished(T obj);
+
    /**
-    * Release the object from use.
-    * 
-    * @param obj    the object
-    */
-   void release(T obj);
-   
-   /**
     * Remove the specified object from cache.
     * 
     * @param key    the identifier of the object
@@ -78,31 +88,27 @@
    void remove(Object key);
    
    /**
-    * Gets whether this cache supports clustering functionality.
+    * Gets whether this cache supports {@link SerializationGroup} management.
     * 
-    * @return <code>true</code> if clustering is supported, <code>false</code>
-    *         otherwise
+    * @return <code>true</code> if group management is supported;
+    *         <code>false</code> otherwise
     */
-   boolean isClustered();
-   
+   boolean isGroupAware();
+
    /**
-    * Replicate the object. The object must not be in use.
+    * Gets the group to which the given object belongs.
     * 
-    * @param key    the identifier of the object
-    * 
-    * @throws IllegalStateException if the object, or another object in the 
-    *                            same {@link SerializationGroup} as the object, 
-    *                            is in use. 
-    * @throws UnsupportedOperationException if {@link #isClustered()} returns
-    *                                       <code>false</code>
+    * @param obj the object
+    * @return the group, or <code>null</code> if the object is not a member
+    *         of a group
     */
-   void replicate(Object key);
-   
+   SerializationGroup<T> getGroup(T obj);
+
    /**
     * Start the cache.
     */
    void start();
-   
+
    /**
     * Stop the cache.
     */

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/CacheFactoryNotRegisteredException.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/CacheFactoryNotRegisteredException.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/CacheFactoryNotRegisteredException.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,49 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007, 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.ejb3.cache;
+
+/**
+ * Thrown when attempting to retrieve a cache factory with an
+ * unrecognized name from the {@link StatefulCacheFactoryRegistry}.
+ * 
+ * @author <a href="mailto:andrew.rubinger at redhat.com">ALR</a>
+ * @version $Revision: $
+ */
+public class CacheFactoryNotRegisteredException extends Exception
+{
+
+   // Class Members
+   private static final long serialVersionUID = -881723607135494483L;
+
+   // Constructors
+
+   public CacheFactoryNotRegisteredException()
+   {
+      super();
+   }
+
+   public CacheFactoryNotRegisteredException(String message)
+   {
+      super(message);
+   }
+
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/CacheItem.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/CacheItem.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/CacheItem.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,49 @@
+/*
+ * 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.ejb3.cache;
+
+import java.io.Serializable;
+
+/**
+ * An item that can be stored in a {@link Cache}.
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public interface CacheItem extends Identifiable, Serializable
+{ 
+   /**
+    * Gets whether this object's internal state has been modified since
+    * the last request to this method.
+    * <p>
+    * Implementations must be aggressive about returning <code>true</code> if
+    * they are uncertain about whether they have been modified; <code>false</code>
+    * should only be returned if the implementing object is certain its
+    * internal state has not been modified.
+    * </p>
+    * 
+    * @return <code>true</code> if the state has been modified or the
+    *         implementing object does not know; <code>false</code> otherwise.
+    */
+   boolean isModified();   
+}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/Cacheable.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/Cacheable.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/Cacheable.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,91 +0,0 @@
-/*
- * 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.ejb3.cache;
-
-
-/**
- * An object that can be cached.
- * 
- * @author Brian Stansberry
- * @version $Revision$
- */
-public interface Cacheable extends Identifiable
-{
-   /** Possible states of the entry.  See elements for details. */
-//   public static enum State { 
-//      /**
-//       * A reference to the entry's {@link CacheEntry#getObject container object} 
-//       * has *not* been handed out to a caller and there is no need to
-//       * invoke any @PostActivate callback before handing out a reference.
-//       */
-//      READY,
-//      /** 
-//       * A reference to the entry's {@link CacheEntry#getObject container object} 
-//       * has been handed out to a caller and has not yet been released.
-//       * 
-//       * @see Cache#get(Object)
-//       * @see Cache#peek(Object)
-//       * @see Cache#release(Identifiable)
-//       */
-//      IN_USE,
-//      /**
-//       * A reference to the entry's {@link CacheEntry#getObject container object} 
-//       * has *not* been handed out to a caller, but any @PostActivate callback 
-//       * should be invoked before handing out a reference.
-//       */
-//      PASSIVATED 
-//   };
-//   
-//   State getCacheState();
-//   
-//   void setCacheState(State state);
-   
-//   void setLastUsed(long lastUsed);
-   
-   /**
-    * Gets whether this object is in use by a caller.
-    */
-   boolean isInUse();
-   
-   /**
-    * Sets whether this object is in use by a caller.
-    * 
-    * @param inUse
-    */
-   void setInUse(boolean inUse);
-   
-   /**
-    * Gets the timestamp of the last time this object was in use.
-    * 
-    * @return
-    */
-   long getLastUsed();
-   
-   /**
-    * Gets whether this object's internal state has been modified since
-    * the last request to this method.
-    * 
-    * @return
-    */
-   boolean isModified();   
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/IntegratedObjectStore.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/IntegratedObjectStore.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/IntegratedObjectStore.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,109 +0,0 @@
-/*
- * 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.ejb3.cache;
-
-/**
- * An in-memory store for identifiable objects that integrates a persistent store. 
- * Note that this class does NOT call any callbacks.
- * 
- * @author Brian Stansberry
- * @version $Revision$
- */
-public interface IntegratedObjectStore<T extends Cacheable>
-{
-   /**
-    * Put a new entry into the store. This operation should only be
-    * performed once per entry.
-    * 
-    * @param entry the object to store. Cannot be <code>null</code>.
-    * 
-    * @throws IllegalStateException if the store is already managing an entry
-    *                               with the same {@link Identifiable#getId() id}.
-    *                               It is not a requirement that the store throw
-    *                               this exception in this case, but it is
-    *                               permissible. This basically puts the onus on
-    *                               callers to ensure this operation is only
-    *                               performed once per entry.
-    */
-   void insert(T entry);
-   
-   /**
-    * Gets the entry with the given id from the store.
-    * 
-    * @param key {@link Identifiable#getId() id} of the entry.
-    *           Cannot be <code>null</code>.
-    * @return the object store under <code>id</code>. May return <code>null</code>.
-    */
-   T get(Object key);
-   
-   /**
-    * Update an already cached item.
-    * 
-    * @param  entry the entry to update
-    * 
-    * @throws IllegalStateException if the store isn't already managing an entry
-    *                               with the same {@link Identifiable#getId() id}.
-    *                               It is not a requirement that the store throw
-    *                               this exception in this case, but it is
-    *                               permissible. This basically puts the onus on
-    *                               callers to ensure {@link #insert(Cacheable)}
-    *                               is invoked before the first replication.
-    */
-   void update(T entry);
-   
-   /**
-    * Remove the object with the given key from the store.
-    * 
-    * @param key {@link Identifiable#getId() id} of the entry.
-    *           Cannot be <code>null</code>.
-    *           
-    * @return the object that was cached under <code>key</code>
-    */
-   T remove(Object key);
-   
-   /**
-    * Remove the entry with the given key from any in-memory store
-    * while retaining it in the persistent store.
-    * 
-    * @param entry the entry to passivate
-    */
-   void passivate(T entry);
-   
-   /**
-    * Gets whether this store supports clustering functionality.
-    * 
-    * @return <code>true</code> if clustering is supported, <code>false</code>
-    *         otherwise
-    */
-   boolean isClustered();
-   
-   /**
-    * Perform any initialization work.
-    */
-   void start();
-   
-   /**
-    * Perform any shutdown work.
-    */
-   void stop();
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/ObjectStore.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/ObjectStore.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/ObjectStore.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,49 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2007, 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.ejb3.cache;
-
-/**
- * Stores an indentifiable object on a persistence store. Note that the object store
- * does NOT call any callbacks.
- * 
- * It is assumed the key represents something meaning full to the object store.
- *
- * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
- * @version $Revision: $
- */
-public interface ObjectStore<T extends Identifiable>
-{
-   /**
-    * Load the object from storage.
-    * 
-    * @param key    the object identifier
-    * @return       the object or null if not found
-    */
-   T load(Object key);
-   
-   /**
-    * Store the object into storage.
-    * 
-    * @param obj    the object
-    */
-   void store(T obj);
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivatingCache.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivatingCache.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivatingCache.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,46 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.cache;
-
-/**
- * A cache which passivates unused objects.
- * 
- * A PassivatingCache is linked to an ObjectStore to store the
- * passivated object and a PassivationManager to managed lifecycle
- * callbacks on the object.
- *
- * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
- * @version $Revision$
- */
-public interface PassivatingCache<T extends Identifiable> extends Cache<T>
-{
-   /**
-    * Force passivation of an object. The object must not be in use.
-    * 
-    * @param key    the identifier of the object
-    * 
-    * @throws IllegalStateException if the object, or another object in the 
-    *                            same {@link SerializationGroup} as the object, 
-    *                            is in use. 
-    */
-   void passivate(Object key);
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivatingIntegratedObjectStore.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivatingIntegratedObjectStore.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivatingIntegratedObjectStore.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,90 +0,0 @@
-/*
- * 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.ejb3.cache;
-
-/**
- * An {@link IntegratedObjectStore} that is able to use its knowledge of
- * when objects are accessed to coordinate the passivation and removal of 
- * cached objects.
- * 
- * @author Brian Stansberry
- * @version $Revision$
- */
-public interface PassivatingIntegratedObjectStore<T extends Cacheable>
-   extends IntegratedObjectStore<T>
-{
-   /**
-    * Gets how often, in seconds, this object should process 
-    * {@link #runPassivation() passivations} and
-    * {@link #runExpiration() expirations}.
-    * 
-    * @return  interval, in seconds, at which passivations and expirations
-    *          are processed. A value of less than 1 means this object will 
-    *          not itself initiate processing, depending instead on an external 
-    *          caller to do so.
-    */
-   int getInterval();
-   
-   /**
-    * Sets how often, in seconds, this object should process 
-    * {@link #runPassivation() passivations} and
-    * {@link #runExpiration() expirations}.
-    * 
-    * @param seconds  interval, in seconds, at which passivations and
-    *                 expirations should be processed. A value of less than 1 
-    *                 means this object will not itself initiate processing, 
-    *                 depending instead on an external caller to do so.
-    */
-   void setInterval(int seconds);
-   
-   /**
-    * Determine what cached objects need to be passivated and 
-    * {@link PassivatingCache#passivate(Object) tell the cache to passivate them}.
-    *
-    */
-   void runPassivation();
-   
-   /**
-    * Check what cached objects need to be removed and 
-    * {@link Cache#remove(Object) tell the cache to remove them}.
-    *
-    */
-   void runExpiration();
-   
-   /**
-    * Handback provided by the controlling {@link PassivatingCache} to
-    * allow the actual {@link PassivatingCache#passivate(Object) passivate}
-    * and {@link Cache#remove(Object) remove} calls.
-    * 
-    * @param cache
-    */
-   void setPassivatingCache(PassivatingCache<T> cache);
-   
-   // TODO determine what the standard configurations are
-   
-//   int getPassivationTimeout();
-//   void setPassivationTimeout(int timeout);
-//   
-//   int getRemovalTimeout();   
-//   void setRemovalTimeout(int timeout);
-}

Modified: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivationManager.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivationManager.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivationManager.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -23,13 +23,15 @@
 
 import java.io.Serializable;
 
+import org.jboss.ejb3.cache.SerializationGroup;
+
 /**
- * Manage passivation and replication lifecycle callbacks on an object.
+ * Manages passivation and replication lifecycle callbacks on an object.
  *
  * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
  * @version $Revision$
  */
-public interface PassivationManager<T extends Serializable>
+public interface PassivationManager<T extends CacheItem & Serializable>
 {
    /**
     * This method is called after an object has been retrieved
@@ -55,21 +57,10 @@
    void prePassivate(T obj);
    
    /**
-    * Gets whether this PassivationManager supports clustering functionality.
-    * 
-    * @return <code>true</code> if clustering is supported, <code>false</code>
-    *         otherwise
-    */
-   boolean isClustered();
-   
-   /**
     * This method is called after a previously replicated object has been 
     * retrieved from a clustered cache.
     * 
-    * @param obj    the object. 
-    * 
-    * @throws UnsupportedOperationException if {@link #isClustered()} returns
-    *                                       <code>false</code>
+    * @param obj    the object.
     */
    void postReplicate(T obj);
    
@@ -80,14 +71,11 @@
     * @param obj    the object
     * 
     * @throws IllegalStateException if <code>obj</code>, or another object in the 
-    *                            same {@link SerializationGroup} as 
+    *                            same {@link SerializationGroupImpl} as 
     *                            <code>obj</code>, is in use. Checking if
     *                            an object is in use and throwing this
     *                            exception is not required, so callers should
     *                            not assume it will be thrown.
-    *                             
-    * @throws UnsupportedOperationException if {@link #isClustered()} returns
-    *                                       <code>false</code>
     */
    void preReplicate(T obj);
 }

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/SerializationGroup.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/SerializationGroup.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/SerializationGroup.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,49 @@
+/*
+ * 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.ejb3.cache;
+
+import java.util.Iterator;
+
+/**
+ * Defines a group of cache items which must always be serialized in one 
+ * unit of work.
+ *
+ * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
+ * @author Brian Stansberry
+ * @version $Revision: $
+ */
+public interface SerializationGroup<T extends CacheItem> 
+  extends CacheItem
+{   
+   /**
+    * Gets the number of group members.
+    */
+   int size();
+   
+   /**
+    * Returns an iterator over the group members. The iterator does not
+    * support the {@link Iterator#remove()} operation.
+    * 
+    * @return the iterator
+    */
+   Iterator<T> iterator();   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulCacheFactory.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulCacheFactory.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulCacheFactory.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,59 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007, 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.ejb3.cache;
+
+import org.jboss.ejb3.annotation.CacheConfig;
+
+/**
+ * Defines the contract for an EJB3 Stateful Cache Factory
+ * 
+ * @author <a href="mailto:andrew.rubinger at redhat.com">ALR</a>
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public interface StatefulCacheFactory<T extends CacheItem>
+{
+   /**
+    * Creates a cache for a container.
+    * 
+    * @param containerName fully qualified name of the container. Must be
+    *                      unique across all possibly co-existent containers
+    *                      in the system. Should be as concise as possible,
+    *                      as this name may be replicated around a cluster
+    *                      in numerous messages. Should not contain characters
+    *                      that are illegal to include in an element of a 
+    *                      filesystem path. An example containerName
+    *                      for an EJBContainer might be 
+    *                      "ear=foo.ear,jar=foo.jar,name=Bar".
+    * @param factory factory for creating objects managed by the cache
+    * @param passivationManager manager for invoking pre and post passivation
+    *                           and replication callbacks on the cached objects
+    * @param config configuration details for the cache
+    * 
+    * @return the cache
+    */
+   Cache<T> createCache(String containerName, 
+                        StatefulObjectFactory<T> factory, 
+                        PassivationManager<T> passivationManager, 
+                        CacheConfig config);
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulCacheFactoryRegistry.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulCacheFactoryRegistry.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulCacheFactoryRegistry.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,87 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007, 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.ejb3.cache;
+
+import java.util.Map;
+
+/**
+ * Registry for all configured Stateful Cache Factory implementations
+ * 
+ * TODO Does this belong in ejb3-core? That would allow all of the
+ * StatefulCacheFactory<? extends CacheItem> usage to be replaced with
+ * StatefulCacheFactory<StatefulBeanContext> without leaking the
+ * StatefulBeanContext class to ejb3-cache.
+ * 
+ * @author <a href="mailto:andrew.rubinger at redhat.com">ALR</a>
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public class StatefulCacheFactoryRegistry<T extends CacheItem>
+{
+   // Instance Members
+   private Map<String, StatefulCacheFactory<T>> factories;
+
+   // Accessors / Mutators
+
+   public Map<String, StatefulCacheFactory<T>> getFactories()
+   {
+      return factories;
+   }
+
+   public void setFactories(Map<String, StatefulCacheFactory<T>> factories)
+   {
+      this.factories = factories;
+   }
+   
+   public void addCacheFactory(String name, StatefulCacheFactory<T> factory)
+   {
+      this.factories.put(name, factory);
+   }
+   
+   public void removeCacheFactory(String name)
+   {
+      this.factories.remove(name);
+   }
+
+   // Functional Methods
+
+   /**
+    * Obtains the Cache Factory with the specified registered name
+    * 
+    * @param name The registered name of the cache factory to retrieve
+    * @return The Cache Factory
+    */
+   public StatefulCacheFactory<T> getCacheFactory(String name) throws CacheFactoryNotRegisteredException
+   {
+      // Obtain cache factory
+      StatefulCacheFactory<T> cacheFactory = this.factories.get(name);
+
+      // Ensure registered
+      if (cacheFactory == null)
+      {
+         throw new CacheFactoryNotRegisteredException("Cache Factory with name " + name + " is not registered.");
+      }
+
+      return cacheFactory;
+   }
+}

Modified: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulObjectFactory.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulObjectFactory.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/StatefulObjectFactory.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -31,7 +31,7 @@
  * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
  * @version $Revision: $
  */
-public interface StatefulObjectFactory<T>
+public interface StatefulObjectFactory<T extends CacheItem>
 {
    /**
     * Creates a new stateful object by calling it's empty constructor,

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/CacheableTimestamp.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/CacheableTimestamp.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/CacheableTimestamp.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,100 +0,0 @@
-/*
- * 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.ejb3.cache.impl;
-
-import org.jboss.ejb3.cache.Cacheable;
-import org.jboss.ejb3.cache.Identifiable;
-import org.jboss.ejb3.cache.IntegratedObjectStore;
-
-/**
- * Encapsulation of the {@link Identifiable#getId() id} and
- * {@link Cacheable#getLastUsed() last used timestamp} of
- * a cached {@link Cacheable}.
- * <p>
- * Implements <code>Comparable</code> to make it easy to sort
- * for LRU comparisons.
- * </p>
- * 
- * @see IntegratedObjectStore#getInMemoryEntries()
- * @see IntegratedObjectStore#getPassivatedEntries()
- * 
- * @author Brian Stansberry
- * @version $Revision$
- */
-public class CacheableTimestamp 
-   implements Identifiable, Comparable<CacheableTimestamp>
-{
-   private Object id;
-   private long lastUsed;
-   
-   public CacheableTimestamp(Object id, long lastUsed)
-   {
-      assert id != null : "id cannot be null";
-      assert lastUsed > 0 : "lastUsed must be positive";
-      
-      this.id = id;
-      this.lastUsed = lastUsed;
-   }
-   
-   public Object getId()
-   {
-      return id;
-   }
-   
-   public long getLastUsed()
-   {
-      return lastUsed;
-   }
-
-   /**
-    * Compares based on {@link #getLastUsed() last used}, returning
-    * -1 for earlier timestamps.
-    */
-   public int compareTo(CacheableTimestamp o)
-   {
-      if (this.lastUsed < o.lastUsed)
-         return -1;
-      else if (this.lastUsed > o.lastUsed)
-         return 1;
-      return 0;
-   }
-
-   @Override
-   public boolean equals(Object obj)
-   {
-      if (this == obj)
-         return true;
-      
-      if (obj instanceof CacheableTimestamp)
-      {
-         return this.id.equals(((CacheableTimestamp) obj).id);
-      }
-      return false;
-   }
-
-   @Override
-   public int hashCode()
-   {
-      return id.hashCode();
-   }   
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/EntryStateCache.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/EntryStateCache.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/EntryStateCache.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,155 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.cache.impl;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.ejb.NoSuchEJBException;
-
-import org.jboss.ejb3.cache.Cache;
-import org.jboss.ejb3.cache.Identifiable;
-import org.jboss.ejb3.cache.StatefulObjectFactory;
-
-/**
- * Comment
- *
- * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
- * @version $Revision$
- */
-public class EntryStateCache<T extends Identifiable> implements Cache<T>
-{
-   private StatefulObjectFactory<T> factory;
-   private Map<Object, Entry> cache;
-   
-   private static enum State { READY, IN_USE };
-   
-   private class Entry
-   {
-      long lastUsed;
-      T obj;
-      State state;
-      
-      Entry(T obj)
-      {
-         assert obj != null : "obj is null";
-         
-         this.lastUsed = System.currentTimeMillis();
-         this.obj = obj;
-         this.state = State.IN_USE;
-      }
-   }
-   
-   public EntryStateCache(StatefulObjectFactory<T> factory)
-   {
-      assert factory != null : "factory is null";
-      
-      this.factory = factory;
-      this.cache = new HashMap<Object, Entry>();
-   }
-   
-   public T create(Class<?>[] initTypes, Object[] initValues)
-   {
-      T obj = factory.create(initTypes, initValues);
-      Entry entry = new Entry(obj);
-      synchronized (cache)
-      {
-         cache.put(obj.getId(), entry);
-      }
-      return obj;
-   }
-
-   public T get(Object key) throws NoSuchEJBException
-   {
-      synchronized (cache)
-      {
-         Entry entry = cache.get(key);
-         if(entry == null)
-            throw new NoSuchEJBException(String.valueOf(key));
-         if(entry.state != State.READY)
-            throw new IllegalStateException("entry " + entry + " is not ready");
-         entry.state = State.IN_USE;
-         entry.lastUsed = System.currentTimeMillis();
-         return entry.obj;
-      }
-   }
-
-   public T peek(Object key) throws NoSuchEJBException
-   {
-      synchronized (cache)
-      {
-         Entry entry = cache.get(key);
-         if(entry == null)
-            throw new NoSuchEJBException(String.valueOf(key));
-         return entry.obj;
-      }
-   }
-
-   public void release(T obj)
-   {
-      synchronized (cache)
-      {
-         Entry entry = cache.get(obj.getId());
-         if(entry.state != State.IN_USE)
-            throw new IllegalStateException("entry " + entry + " is not in use");
-         entry.state = State.READY;
-         entry.lastUsed = System.currentTimeMillis();
-      }
-   }
-
-   public void remove(Object key)
-   {
-      Entry entry;
-      synchronized (cache)
-      {
-         entry = cache.remove(key);
-         if(entry.state != State.READY)
-            throw new IllegalStateException("entry " + entry + " is not ready");
-      }
-      if(entry != null)
-         factory.destroy(entry.obj);
-   }
-
-   public void start()
-   {
-      // TODO Auto-generated method stub
-
-   }
-
-   public void stop()
-   {
-      // TODO Auto-generated method stub
-
-   }
-   
-   public boolean isClustered()
-   {
-      return false;
-   }
-   
-   public void replicate(Object key)
-   {
-      throw new UnsupportedOperationException("Clustering is not supported by " + 
-                                              getClass().getName());      
-   }
-
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/FileObjectStore.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/FileObjectStore.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/FileObjectStore.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,244 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.cache.impl;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-import org.jboss.ejb3.cache.Identifiable;
-import org.jboss.ejb3.cache.ObjectStore;
-import org.jboss.logging.Logger;
-import org.jboss.serial.io.JBossObjectInputStream;
-import org.jboss.serial.io.JBossObjectOutputStream;
-
-/**
- * Stores objects in a directory via serialization.
- *
- * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
- * @version $Revision: $
- */
-public class FileObjectStore<T extends Identifiable> implements ObjectStore<T>
-{
-   private static final Logger log = Logger.getLogger(FileObjectStore.class);
-   
-   private File storageDirectory;
-   
-   private static class DeleteFileAction implements PrivilegedAction<Boolean>
-   {
-      File file;
-
-      DeleteFileAction(File file)
-      {
-         this.file = file;
-      }
-
-      public Boolean run()
-      {
-         return file.delete();
-      }
-
-      static boolean delete(File file)
-      {
-         DeleteFileAction action = new DeleteFileAction(file);
-         return AccessController.doPrivileged(action);
-      }
-   }
-
-   private static class FISAction implements PrivilegedExceptionAction<FileInputStream>
-   {
-      File file;
-
-      FISAction(File file)
-      {
-         this.file = file;
-      }
-
-      public FileInputStream run() throws FileNotFoundException
-      {
-         FileInputStream fis = new FileInputStream(file);
-         return fis;
-      }
-
-      static FileInputStream open(File file) throws FileNotFoundException
-      {
-         FISAction action = new FISAction(file);
-         FileInputStream fis = null;
-         try
-         {
-            fis = AccessController.doPrivileged(action);
-         }
-         catch (PrivilegedActionException e)
-         {
-            throw (FileNotFoundException) e.getException();
-         }
-         return fis;
-      }
-   }
-
-   private static class FOSAction implements PrivilegedExceptionAction<FileOutputStream>
-   {
-      File file;
-
-      FOSAction(File file)
-      {
-         this.file = file;
-      }
-
-      public FileOutputStream run() throws FileNotFoundException
-      {
-         FileOutputStream fis = new FileOutputStream(file);
-         return fis;
-      }
-
-      static FileOutputStream open(File file) throws FileNotFoundException
-      {
-         FOSAction action = new FOSAction(file);
-         FileOutputStream fos = null;
-         try
-         {
-            fos = AccessController.doPrivileged(action);
-         }
-         catch (PrivilegedActionException e)
-         {
-            throw (FileNotFoundException) e.getException();
-         }
-         return fos;
-      }
-   }
-
-   private static class MkdirsFileAction implements PrivilegedAction<Boolean>
-   {
-      File file;
-
-      MkdirsFileAction(File file)
-      {
-         this.file = file;
-      }
-
-      public Boolean run()
-      {
-         return file.mkdirs();
-      }
-
-      static boolean mkdirs(File file)
-      {
-         MkdirsFileAction action = new MkdirsFileAction(file);
-         return AccessController.doPrivileged(action);
-      }
-   }
-
-   protected File getFile(Object key)
-   {
-      return new File(storageDirectory, String.valueOf(key) + ".ser");
-   }
-   
-   @SuppressWarnings("unchecked")
-   public T load(Object key)
-   {
-      File file = getFile(key);
-      if(!file.exists())
-         return null;
-      
-      log.debug("loading state from " + file);
-      try
-      {
-         FileInputStream fis = FISAction.open(file);
-         ObjectInputStream in = new JBossObjectInputStream(fis);
-         try
-         {
-            return (T) in.readObject();
-         }
-         finally
-         {
-            in.close();
-            DeleteFileAction.delete(file);
-         }
-      }
-      catch(ClassNotFoundException e)
-      {
-         throw new RuntimeException("failed to load object " + key, e);
-      }
-      catch(IOException e)
-      {
-         throw new RuntimeException("failed to load object " + key, e);
-      }
-   }
-
-   public void setStorageDirectory(String dirName)
-   {
-      storageDirectory = new File(dirName);
-   }
-   
-   public void start()
-   {
-      assert storageDirectory != null : "storageDirectory is null";
-      
-      if(!storageDirectory.exists())
-      {
-         if(!MkdirsFileAction.mkdirs(storageDirectory))
-            throw new RuntimeException("Unable to create storage directory " + storageDirectory);
-         storageDirectory.deleteOnExit();
-      }
-      
-      if(!storageDirectory.isDirectory())
-         throw new RuntimeException("Storage directory " + storageDirectory + " is not a directory");
-   }
-   
-   public void stop()
-   {
-      // TODO: implement
-   }
-   
-   public void store(T obj)
-   {
-      File file = getFile(obj.getId());
-      file.deleteOnExit();
-      log.debug("saving state to " + file);
-      try
-      {
-         FileOutputStream fos = FOSAction.open(file);
-         ObjectOutputStream out = new JBossObjectOutputStream(fos);
-         try
-         {
-            out.writeObject(obj);
-            out.flush();
-         }
-         finally
-         {
-            out.close();
-         }
-      }
-      catch(IOException e)
-      {
-         throw new RuntimeException("failed to store object " + obj.getId(), e);
-      }
-   }
-}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupAwareTransactionalCache.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupAwareTransactionalCache.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupAwareTransactionalCache.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,166 @@
+/*
+ * 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.ejb3.cache.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.ejb3.cache.Cache;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.SerializationGroup;
+import org.jboss.ejb3.cache.spi.BackingCacheEntry;
+import org.jboss.ejb3.cache.spi.GroupAwareBackingCache;
+import org.jboss.ejb3.cache.spi.GroupIncompatibilityException;
+
+/**
+ * {@link Cache#isGroupAware Group-aware} version of {@link TransactionalCache}.
+ * 
+ * @author Brian Stansberry
+ */
+public class GroupAwareTransactionalCache<C extends CacheItem, T extends BackingCacheEntry<C>> 
+   extends TransactionalCache<C, T>
+{
+   @SuppressWarnings("unchecked")
+   private static final ThreadLocal groupCreationContext = new ThreadLocal();
+   
+   /** 
+    * Another ref to super.delegate. Just saves having to do casts all the time. 
+    */
+   private final GroupAwareBackingCache<C, T> groupedCache;
+   
+   /**
+    * Create a new GroupAwareTransactionalCacheImpl.
+    * 
+    * @param delegate the backing cache
+    * @param tm       the transaction manager
+    */
+   public GroupAwareTransactionalCache(GroupAwareBackingCache<C, T> delegate, 
+                                       TransactionManager tm)
+   {
+      super(delegate, tm);
+      this.groupedCache = delegate;
+   }
+
+   @Override
+   @SuppressWarnings("unchecked")
+   public C create(Class<?>[] initTypes, Object[] initValues)
+   {
+      boolean outer = false;
+      List<ItemCachePair> contextPairs = (List<ItemCachePair>) groupCreationContext.get();
+      if (contextPairs == null)
+      {
+         contextPairs = new ArrayList<ItemCachePair>();
+         groupCreationContext.set(contextPairs);
+         outer = true;
+      }
+      
+      C cacheItem = super.create(initTypes, initValues);
+      
+      contextPairs.add(new ItemCachePair(cacheItem, this));
+            
+      if (outer)
+      {
+         groupCreationContext.set(null);
+         if (contextPairs.size() > 1)
+         {
+            SerializationGroup<C> group = null;
+            try
+            {
+               boolean skipped = false;
+               boolean added = false;
+               for (ItemCachePair pair : contextPairs)
+               {
+                  if (pair.cache.isGroupAware())
+                  {
+                     if (skipped)
+                        throw new GroupIncompatibilityException("Some caches in nested bean hierarchy are group-aware, some are not");
+                     
+                     if (group == null)
+                     {
+                        group = pair.cache.createGroup();
+                     }
+                     pair.cache.setGroup(pair.item, group);
+                     added = true;
+                  }
+                  else if (added)
+                  {
+                     throw new GroupIncompatibilityException("Some caches in nested bean hierarchy are group-aware, some are not");
+                  }
+                  else 
+                  {
+                     skipped = true;
+                  }
+               }
+            }
+            catch (GroupIncompatibilityException e)
+            {
+               // Clean up
+               for (ItemCachePair pair : contextPairs)
+               {
+                  pair.cache.remove(pair.item.getId());
+               }
+               throw new RuntimeException("Failed to create SerializationGroup for nested bean hierarchy", e);
+            }
+         }
+      }
+      
+      return cacheItem;
+   }
+
+   @Override
+   public boolean isGroupAware()
+   {
+      return true;
+   }
+
+   private void setGroup(C obj, SerializationGroup<C> group) throws GroupIncompatibilityException
+   {
+      groupedCache.setGroup(obj, group);
+   }
+   
+   private SerializationGroup<C> createGroup() throws GroupIncompatibilityException
+   {
+      return groupedCache.createGroup();
+   }
+
+   @Override
+   public SerializationGroup<C> getGroup(C obj)
+   {
+      return groupedCache.getGroup(obj);
+   }
+   
+   private class ItemCachePair
+   {
+      private final C item;
+      private final GroupAwareTransactionalCache<C, T> cache;
+      
+      ItemCachePair(C item, GroupAwareTransactionalCache<C, T> cache)
+      {
+         this.item = item;
+         this.cache = cache;
+      }
+   }
+
+}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupedPassivatingCacheImpl.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupedPassivatingCacheImpl.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupedPassivatingCacheImpl.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,297 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.cache.impl;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.ejb.NoSuchEJBException;
-
-import org.jboss.ejb3.cache.Identifiable;
-import org.jboss.ejb3.cache.ObjectStore;
-import org.jboss.ejb3.cache.PassivatingCache;
-import org.jboss.ejb3.cache.PassivationManager;
-import org.jboss.ejb3.cache.StatefulObjectFactory;
-import org.jboss.ejb3.cache.grouped.GroupedPassivatingCache;
-import org.jboss.ejb3.cache.grouped.SerializationGroup;
-import org.jboss.ejb3.cache.grouped.SerializationGroupMember;
-import org.jboss.logging.Logger;
-
-/**
- * Comment
- *
- * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
- * @version $Revision$
- */
-public class GroupedPassivatingCacheImpl<T extends Identifiable & Serializable> implements GroupedPassivatingCache<T>
-{
-   private static final Logger log = Logger.getLogger(GroupedPassivatingCacheImpl.class);
-   
-   private PassivatingCache<SerializationGroup> groupCache;
-   
-   private SimplePassivatingCache<Entry<T>> delegate;
-   private Map<Object, Entry<T>> storage = new HashMap<Object, Entry<T>>();
-   
-   protected class Entry<C extends Identifiable & Serializable> 
-      implements SerializationGroupMember, Serializable
-   {
-      private static final long serialVersionUID = 1L;
-      
-      Object id;
-      C obj;
-      SerializationGroup group;
-      Object groupId;
-      
-      Entry(C obj)
-      {
-         assert obj != null : "obj is null";
-         
-         this.obj = obj;
-         this.id = obj.getId();
-      }
-      
-      public Object getId()
-      {
-         return id;
-      }
-      
-      public C getSerializableObject()
-      {
-         return obj;
-      }
-      
-      public void prePassivate()
-      {
-         // make sure we don't passivate the group twice
-         group = null;
-         
-         delegate.passivate(this.id);
-         
-         obj = null;
-      }
-      
-      public void preReplicate()
-      {
-         throw new UnsupportedOperationException("Clustering is not supported by " + 
-                                                 GroupedPassivatingCacheImpl.this.getClass().getName());
-      }
-      
-      public boolean isClustered()
-      {
-         return false;
-      }
-      
-      @Override
-      public String toString()
-      {
-         return super.toString() + "{id=" + id + ",obj=" + obj + ",groupId=" + groupId + ",group=" + group + "}";
-      }
-   }
-   
-   private class EntryContainer implements StatefulObjectFactory<Entry<T>>, PassivationManager<Entry<T>>, ObjectStore<Entry<T>>
-   {
-      private StatefulObjectFactory<T> factory;
-      private PassivationManager<T> passivationManager;
-      private ObjectStore<T> store;
-      
-      EntryContainer(StatefulObjectFactory<T> factory, PassivationManager<T> passivationManager, ObjectStore<T> store)
-      {
-         this.factory = factory;
-         this.passivationManager = passivationManager;
-         this.store = store;
-      }
-      
-      public Entry<T> create(Class<?>[] initTypes, Object[] initValues)
-      {
-         return new Entry<T>(factory.create(initTypes, initValues));
-      }
-
-      public void destroy(Entry<T> entry)
-      {
-         factory.destroy(entry.getSerializableObject());
-      }
-      
-      public Entry<T> load(Object key)
-      {
-         Entry<T> entry = storage.get(key);
-         if(entry != null)
-         {
-            log.trace("entry = " + entry);
-            return entry;
-         }
-         // This only happens when there is no group
-         T obj = store.load(key);
-         if(obj == null)
-            return null;
-         return new Entry<T>(obj);
-      }
-      
-      @SuppressWarnings("unchecked")
-      public void postActivate(Entry<T> entry)
-      {
-         log.trace("post activate " + entry);
-         if(entry.getSerializableObject() == null)
-         {
-            if(entry.group == null)
-            {
-               // TODO: peek or get?
-               entry.group = groupCache.peek(entry.groupId);
-            }
-            entry.obj = (T) entry.group.getMemberObject(entry.id);
-            entry.group.addActive(entry);
-         }
-         passivationManager.postActivate(entry.obj);
-      }
-      
-      public void prePassivate(Entry<T> entry)
-      {
-         log.trace("pre passivate " + entry);
-         passivationManager.prePassivate(entry.obj);
-         // Am I being called recursively
-         if(entry.group != null)
-         {
-            entry.group.removeActive(entry.id);
-            entry.group.prePassivate();
-            groupCache.passivate(entry.groupId);
-            // Why clear? Because entry is removed from active, and thus passivate is never called.
-            entry.group = null;
-            entry.obj = null;
-         }
-      }
-      
-      public boolean isClustered()
-      {
-         return false;
-      }
-      
-      public void preReplicate(Entry<T> entry)
-      {
-         throw new UnsupportedOperationException("Clustering is not supported by " + 
-                                                 getClass().getName());
-      }
-      
-      public void postReplicate(Entry<T> entry)
-      {
-         throw new UnsupportedOperationException("Clustering is not supported by " + 
-                                                 getClass().getName());
-      }
-      
-      public void store(Entry<T> entry)
-      {
-         log.trace("store " + entry);
-         if(entry.groupId == null)
-            store.store(entry.obj);
-         else
-            storage.put(entry.id, entry);
-      }
-   }
-   
-   public GroupedPassivatingCacheImpl(StatefulObjectFactory<T> factory, PassivationManager<T> passivationManager, ObjectStore<T> store, PassivatingCache<SerializationGroup> groupCache)
-   {
-      assert groupCache != null : "groupCache is null";
-      assert passivationManager != null : "passivationManager is null";
-      assert groupCache.isClustered() == false : "groupCache should not be clustered";
-      
-      this.groupCache = groupCache;
-      EntryContainer container = new EntryContainer(factory, passivationManager, store);
-      this.delegate = new SimplePassivatingCache<Entry<T>>(container, container, container);
-   }
-   
-   public boolean isClustered()
-   {
-      return false;
-   }
-   
-   public void replicate(Object key)
-   {
-      throw new UnsupportedOperationException("Clustering is not supported by " + 
-                                              getClass().getName());      
-   }
-   
-   public void passivate(Object key)
-   {
-      delegate.passivate(key);
-   }
-
-   public T create(Class<?>[] initTypes, Object[] initValues)
-   {
-      return delegate.create(initTypes, initValues).obj;
-   }
-
-   public T get(Object key) throws NoSuchEJBException
-   {
-      return delegate.get(key).obj;
-   }
-
-   public T peek(Object key) throws NoSuchEJBException
-   {
-      return delegate.peek(key).obj;
-   }
-
-   public void release(T obj)
-   {
-      delegate.releaseByKey(obj.getId());
-   }
-
-   public void remove(Object key)
-   {
-      delegate.remove(key);
-   }
-
-   
-   public void setGroup(T obj, SerializationGroup group)
-   {
-      if (group.isClustered())
-      {
-         throw new IllegalArgumentException(group + " is clustered; this cache does not support clustering");
-      }
-      Object key = obj.getId();
-      Entry<T>entry = delegate.peek(key);
-      if(entry.group != null)
-         throw new IllegalStateException("object " + key + " already associated with a passivation group");
-      entry.group = group;
-      entry.groupId = group.getId();
-      // TODO: remove member at the appropriate time
-      entry.group.addMember(entry);
-   }
-
-   public void setName(String name)
-   {
-      delegate.setName(name + "-delegate");
-   }
-   
-   public void setSessionTimeout(int sessionTimeout)
-   {
-      delegate.setSessionTimeout(sessionTimeout);
-   }
-   
-   public void start()
-   {
-      delegate.start();
-   }
-
-   public void stop()
-   {
-      delegate.stop();
-   }
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupedPassivatingCacheImpl2.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupedPassivatingCacheImpl2.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/GroupedPassivatingCacheImpl2.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,376 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.cache.impl;
-
-import java.io.Serializable;
-
-import javax.ejb.NoSuchEJBException;
-
-import org.jboss.ejb3.cache.Cacheable;
-import org.jboss.ejb3.cache.IntegratedObjectStore;
-import org.jboss.ejb3.cache.PassivatingCache;
-import org.jboss.ejb3.cache.PassivatingIntegratedObjectStore;
-import org.jboss.ejb3.cache.PassivationManager;
-import org.jboss.ejb3.cache.StatefulObjectFactory;
-import org.jboss.ejb3.cache.grouped.GroupedPassivatingCache;
-import org.jboss.ejb3.cache.grouped.SerializationGroup;
-import org.jboss.logging.Logger;
-
-/**
- * {@link GroupedPassivatingCache} that uses an {@link IntegratedObjectStore}
- * to manage data.
- *
- * @author Brian Stansberry
- * @version $Revision$
- */
-public class GroupedPassivatingCacheImpl2<T extends Cacheable & Serializable> implements GroupedPassivatingCache<T>
-{
-   private static final Logger log = Logger.getLogger(GroupedPassivatingCacheImpl2.class);
-   
-   /**
-    * Cache that's managing the PassivationGroup
-    */
-   private PassivatingCache<SerializationGroup> groupCache;
-   
-   /**
-    *  Delegate that handles the usual details; ends up calling into
-    *  our EntryContainer for StatefulObjectFactory, PassivationManager
-    *  and IntegratedObjectStore functions.
-    */
-   private SimplePassivatingCache2<SerializationGroupMemberImpl<T>> delegate;
-   
-   /** 
-    * Do we support clustering? This field is really just a minor
-    * optimization to avoid calling through to the underlying 
-    * IntegratedObjectStore all the time.
-    */
-   private boolean clustered;
-   
-   private EntryContainer entryContainer;
-   
-   private class EntryContainer   
-      implements StatefulObjectFactory<SerializationGroupMemberImpl<T>>, PassivationManager<SerializationGroupMemberImpl<T>>, IntegratedObjectStore<SerializationGroupMemberImpl<T>>
-   {
-      private StatefulObjectFactory<T> factory;
-      private PassivationManager<T> passivationManager;
-      private IntegratedObjectStore<SerializationGroupMemberImpl<T>> store;
-      
-      EntryContainer(StatefulObjectFactory<T> factory, PassivationManager<T> passivationManager, IntegratedObjectStore<SerializationGroupMemberImpl<T>> store)
-      {
-         this.factory = factory;
-         this.passivationManager = passivationManager;
-         this.store = store;
-      }
-      
-      public SerializationGroupMemberImpl<T> create(Class<?>[] initTypes, Object[] initValues)
-      {
-         return new SerializationGroupMemberImpl<T>(factory.create(initTypes, initValues), 
-                             delegate);
-      }
-
-      public void destroy(SerializationGroupMemberImpl<T> entry)
-      {
-         factory.destroy(entry.getSerializableObject());
-         if (entry.getGroup() != null) 
-         {
-            entry.getGroup().removeMember(entry.getId());
-            if (entry.getGroup().size() == 0)
-            {
-               groupCache.remove(entry.getGroupId());
-            }
-         }
-      }
-      
-      @SuppressWarnings("unchecked")
-      public void postActivate(SerializationGroupMemberImpl<T> entry)
-      {
-         log.trace("post activate " + entry);
-         
-         // Restore the entry's ref to the group and object
-         if(entry.getGroup() == null)
-         {
-            // TODO: peek or get?
-            // BES 2007/10/06 I think peek is better; no
-            // sense marking the group as in-use and then having
-            // to release it or something
-            entry.setGroup(groupCache.peek(entry.getGroupId()));
-         }
-         
-         if(entry.getGroup() != null)
-         {
-            entry.setSerializableObject((T) entry.getGroup().getMemberObject(entry.getId()));
-            
-            // Notify the group that this entry is active
-            entry.getGroup().addActive(entry);
-         }
-         
-         // Invoke callbacks on the underlying object
-         passivationManager.postActivate(entry.getSerializableObject());
-      }
-      
-      public void prePassivate(SerializationGroupMemberImpl<T> entry)
-      {
-         log.trace("pre-passivate " + entry);
-         
-         // entry.obj may or may not get serialized (depends on if group
-         // is in use) but it's ok to invoke callbacks now. If a caller
-         // requests this entry again and the obj hadn't been serialized with
-         // the group, we'll just call postActivate on it then, which is OK.
-         // By always invoking the callbacks here, we avoid possible bugs
-         // where they sometimes don't get called.
-         passivationManager.prePassivate(entry.getSerializableObject());
-         
-         // If this call is coming via delegate.passivate(), entry.group will
-         // *not* be null.  In that case we are the controller for the
-         // group passivation. If the call is coming via Entry.prePassivate(), 
-         // entry.group *will* be null. In that case we are not the controller 
-         // of the passivation and can just return.
-         if(entry.getGroup() != null)
-         {
-            // Remove ourself from group's active list so we don't get
-            // called again via Entry.prePassivate()            
-            entry.getGroup().removeActive(entry.getId());
-            
-            // Only tell the group to passivate if no members are in use
-            if (!entry.getGroup().isInUse())
-            {
-               // Tell group to prePassivate other active members
-               entry.getGroup().prePassivate();
-               // Go ahead and do the real passivation
-               groupCache.passivate(entry.getGroupId());
-            }
-            // else {
-            // this turns into a pretty meaningless exercise of just
-            // passivating an empty Entry. TODO consider throwing 
-            // ItemInUseException here, thus aborting everything.  Need to
-            // be sure that doesn't lead to problems as the exception propagates
-            // }
-            
-            // This call didn't come through Entry.prePassivate() (which nulls
-            // group and obj) so we have to do it ourselves. Otherwise
-            // when this call returns, delegate will serialize the entry
-            // with a ref to group and obj.            
-            entry.setGroup(null);
-            entry.setSerializableObject(null);
-         }
-      }
-      
-      public void preReplicate(SerializationGroupMemberImpl<T> entry)
-      {         
-         // This method follows the same conceptual logic as prePassivate.
-         // See the detailed comments in that method.
-         
-         log.trace("pre-replicate " + entry);
-         
-         passivationManager.preReplicate(entry.getSerializableObject());
-         
-         if(entry.getGroup() != null)
-         {
-            entry.getGroup().removeActive(entry.getId());
-            
-            try
-            {
-               if (!entry.getGroup().isInUse())
-               {
-                  entry.getGroup().preReplicate();
-                  groupCache.replicate(entry.getGroupId());
-               }
-            }
-            finally
-            {
-               // Here we differ from prePassivate!!
-               // Restore the entry as "active" so it can get
-               // passivation callbacks
-               entry.getGroup().addActive(entry);
-            }
-            
-            entry.setGroup(null);
-            entry.setSerializableObject(null);
-         }
-      }
-      
-      @SuppressWarnings("unchecked")
-      public void postReplicate(SerializationGroupMemberImpl<T> entry)
-      {
-         log.trace("postreplicate " + entry);
-         
-         // Restore the entry's ref to the group and object
-         if(entry.getGroup() == null)
-         {
-            // TODO: peek or get?
-            // BES 2007/10/06 I think peek is better; no
-            // sense marking the group as in-use and then having
-            // to release it or something
-            entry.setGroup(groupCache.peek(entry.getGroupId()));
-         }
-         
-         if(entry.getGroup() != null)
-         {
-            entry.setSerializableObject((T) entry.getGroup().getMemberObject(entry.getId()));
-            
-            // Notify the group that this entry is active
-            entry.getGroup().addActive(entry);
-         }
-         
-         // Invoke callbacks on the underlying object
-         passivationManager.postReplicate(entry.getSerializableObject());
-      }
-
-      public void update(SerializationGroupMemberImpl<T> entry)
-      {
-         store.update(entry);
-      }
-
-      public boolean isClustered()
-      {
-         // Use value from containing cache; containing cache c'tor ensures
-         // the underlying store matches this
-         return clustered;
-      }
-      
-      public SerializationGroupMemberImpl<T> get(Object key)
-      {
-         SerializationGroupMemberImpl<T> entry = store.get(key);
-         // In case it was deserialized, make sure it has a ref to us
-         entry.setPassivatingCache(delegate);
-         return entry;
-      }
-
-      public void passivate(SerializationGroupMemberImpl<T> entry)
-      {
-         store.passivate(entry);         
-      }
-
-      public void insert(SerializationGroupMemberImpl<T> entry)
-      {
-         store.insert(entry);         
-      }
-
-      public SerializationGroupMemberImpl<T> remove(Object key)
-      {
-         return store.remove(key);
-      }
-
-      public void start()
-      {         
-         store.start();
-      }
-
-      public void stop()
-      {
-         store.stop();
-      }      
-   }
-   
-   public GroupedPassivatingCacheImpl2(StatefulObjectFactory<T> factory, PassivationManager<T> passivationManager, IntegratedObjectStore<SerializationGroupMemberImpl<T>> store, PassivatingCache<SerializationGroup> groupCache)
-   {
-      assert groupCache != null : "groupCache is null";
-      assert passivationManager != null : "passivationManager is null";
-      assert store != null : "store is null";
-      assert groupCache.isClustered() == store.isClustered(): "incompatible clustering support between groupCache and store";
-      assert groupCache.isClustered() == passivationManager.isClustered(): "incompatible clustering support between groupCache and passivationManager";
-
-      this.clustered = store.isClustered();
-      this.groupCache = groupCache;
-      entryContainer = new EntryContainer(factory, passivationManager, store);
-      this.delegate = new SimplePassivatingCache2<SerializationGroupMemberImpl<T>>(entryContainer, entryContainer, entryContainer);
-      
-      // We pass 'entryContainer' to the delegate, and that's not a PassivatingIntegratedObjectStore
-      // so delegate won't provide the real store with a ref. So we do it here.
-      if (store instanceof PassivatingIntegratedObjectStore)
-      {
-         ((PassivatingIntegratedObjectStore<SerializationGroupMemberImpl<T>>) store).setPassivatingCache(delegate);
-      }
-   }
-   
-   public boolean isClustered()
-   {
-      return clustered;
-   }
-   
-   public void replicate(Object key)
-   {
-      delegate.replicate(key);
-   }
-   
-   public void passivate(Object key)
-   {
-      delegate.passivate(key);
-   }
-
-   public T create(Class<?>[] initTypes, Object[] initValues)
-   {
-      return delegate.create(initTypes, initValues).getSerializableObject();
-   }
-
-   public T get(Object key) throws NoSuchEJBException
-   {
-      SerializationGroupMemberImpl<T> entry = delegate.get(key);
-      if (entry.getGroup() != null)
-      {
-         entry.getGroup().addInUse(key);
-      }
-      return entry.getSerializableObject();
-   }
-
-   public T peek(Object key) throws NoSuchEJBException
-   {
-      return delegate.peek(key).getSerializableObject();
-   }
-
-   public void release(T obj)
-   {
-      Object key = obj.getId();
-      SerializationGroupMemberImpl<T> entry = delegate.releaseByKey(key);
-      if (entry.getGroup() != null)
-      {
-         entry.getGroup().removeInUse(key);
-      }      
-   }
-
-   public void remove(Object key)
-   {
-      delegate.remove(key);
-   }
-   
-   public void setGroup(T obj, SerializationGroup group)
-   {
-      SerializationGroupMemberImpl<T> entry;
-      Object key = obj.getId();
-      entry = delegate.peek(key);
-      if(entry.getGroup() != null)
-         throw new IllegalStateException("object " + key + " already associated with a passivation group");
-      entry.setGroup(group);
-      entry.setGroupId(group.getId());
-      entry.getGroup().addMember(entry);
-   }
-   
-   public void start()
-   {
-      delegate.start();
-   }
-
-   public void stop()
-   {
-      delegate.stop();
-   }
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupContainer.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupContainer.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupContainer.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,97 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.cache.impl;
-
-import org.jboss.ejb3.cache.PassivationManager;
-import org.jboss.ejb3.cache.StatefulObjectFactory;
-import org.jboss.ejb3.cache.grouped.SerializationGroup;
-import org.jboss.logging.Logger;
-
-/**
- * Comment
- *  
- *  FIXME determine whether SerializationGroup clustering support should
- *  be controlled by a property of this container or via a param passed
- *  to create(). 
- *
- * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
- * @version $Revision: $
- */
-public class SerializationGroupContainer implements StatefulObjectFactory<SerializationGroup>, PassivationManager<SerializationGroup>
-{
-   private static final Logger log = Logger.getLogger(SerializationGroupContainer.class);
-   
-   private boolean clustered;
-   
-   public boolean isClustered()
-   {
-      return clustered;
-   }
-   
-   public void setClustered(boolean clustered)
-   {
-      this.clustered = clustered;
-   }
-
-   public SerializationGroup create(Class<?>[] initTypes, Object[] initValues)
-   {
-      SerializationGroup group = new SerializationGroupImpl();
-      // TODO should this be controlled via one of the initValues?
-      group.setClustered(clustered);
-      return group;
-   }
-
-   public void destroy(SerializationGroup obj)
-   {
-      // TODO: nothing?
-   }
-
-   public void postActivate(SerializationGroup obj)
-   {
-      log.trace("post activate " + obj);
-      obj.postActivate();
-   }
-
-   public void prePassivate(SerializationGroup obj)
-   {
-      log.trace("pre passivate " + obj);
-      obj.prePassivate();
-   }
-
-   public void postReplicate(SerializationGroup obj)
-   {
-      if (!clustered)
-         throw new UnsupportedOperationException("Clustering not supported");
-      log.trace("post replicate " + obj);
-      obj.postReplicate();
-   }
-
-   public void preReplicate(SerializationGroup obj)
-   {
-      if (!clustered)
-         throw new UnsupportedOperationException("Clustering not supported");
-      log.trace("pre replicate " + obj);
-      obj.preReplicate();
-   }
-
-   
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupImpl.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupImpl.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupImpl.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,205 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.cache.impl;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.jboss.ejb3.cache.grouped.SerializationGroup;
-import org.jboss.ejb3.cache.grouped.SerializationGroupMember;
-import org.jboss.logging.Logger;
-import org.jboss.util.id.GUID;
-
-/**
- * Default implementation of {@link SerializationGroup}.
- *
- * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
- * @author Brian Stansberry
- * @version $Revision: $
- */
-public class SerializationGroupImpl implements SerializationGroup
-{
-   private static final Logger log = Logger.getLogger(SerializationGroupImpl.class);
-   private static final long serialVersionUID = 1L;
-
-   private Object id = new GUID();
-   /** 
-    * The actual underlying objects passed in via addMember(). We store them 
-    * here so they aren't lost when they are cleared from the values
-    * stored in the "members" map.
-    */
-   private Map<Object, Object> memberObjects = new HashMap<Object, Object>();
-   /** 
-    * The active group members.  We don't serialized these. Rather, it is
-    * the responsibility of members to reassociate themselves with the 
-    * group upon deserialization (via addActive())
-    */
-   private transient Map<Object, SerializationGroupMember> active = 
-         new HashMap<Object, SerializationGroupMember>();
-   /**
-    * Set of keys passed to {@link #addInUse(Object)}
-    */
-   private transient Set<Object> inUseKeys = new HashSet<Object>();
-   
-   private boolean clustered;
-   
-   private long lastUsed;
-   
-   public Object getId()
-   {
-      return id;
-   }
-   
-   public boolean isClustered()
-   {
-      return clustered;
-   }
-   
-   public void setClustered(boolean clustered)
-   {
-      this.clustered = clustered;
-   }
-   
-   public void addMember(SerializationGroupMember member)
-   {
-      Object key = member.getId();
-      if (memberObjects.containsKey(key))
-         throw new IllegalStateException(member + " is already a member");
-      log.trace("add member " + key + ", " + member);
-      memberObjects.put(key, member.getSerializableObject());
-      active.put(key, member);
-   }
-   
-   public void removeMember(Object key)
-   {
-      removeActive(key);
-      memberObjects.remove(key);
-   }
-   
-   public int size()
-   {
-      return memberObjects.size();
-   }
-   
-   public Object getMemberObject(Object key)
-   {
-      return memberObjects.get(key);
-   }
-   
-   public void postActivate()
-   {
-      // do nothing
-   }
-   
-   public void prePassivate()
-   {
-      for(SerializationGroupMember member : active.values())
-      {
-         member.prePassivate();
-      }
-      active.clear();
-   }
-   
-   public void postReplicate()
-   {
-      // do nothing
-   }
-   
-   public void preReplicate()
-   {
-      for(SerializationGroupMember member : active.values())
-      {
-         member.preReplicate();
-      }
-      active.clear();
-   }
-   
-   public void addActive(SerializationGroupMember member)
-   {
-      Object key = member.getId();
-      if (!memberObjects.containsKey(key))
-         throw new IllegalStateException(member + " is not a member of " + this);
-      active.put(key, member);
-   }
-   
-   public void removeActive(Object key)
-   {
-      active.remove(key);
-   }
-
-   public void addInUse(Object key)
-   {
-      if (!memberObjects.containsKey(key))
-         throw new IllegalStateException(key + " is not a member of " + this);
-      inUseKeys.add(key);
-      lastUsed = System.currentTimeMillis();
-   }
-
-   public void removeInUse(Object key)
-   {
-      if (inUseKeys.remove(key))
-      {
-         lastUsed = System.currentTimeMillis();
-      }
-      else if (!memberObjects.containsKey(key))
-      {
-            throw new IllegalStateException(key + " is not a member of " + this);
-      }      
-   }
-
-   public long getLastUsed()
-   {
-      return lastUsed;
-   }
-
-   public boolean isInUse()
-   {
-      return inUseKeys.size() > 0;
-   }
-
-   public void setInUse(boolean inUse)
-   {
-      lastUsed = System.currentTimeMillis();
-   }
-   
-   /**
-    * Always returns <code>true</code>.
-    */
-   public boolean isModified()
-   {
-      return true;
-   }
-
-   private void readObject(java.io.ObjectInputStream in)
-         throws IOException, ClassNotFoundException
-   {
-      in.defaultReadObject();
-      active = new HashMap<Object, SerializationGroupMember>();
-      inUseKeys = new HashSet<Object>();
-   }
-   
-   
-   
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupMemberImpl.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupMemberImpl.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupMemberImpl.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,166 +0,0 @@
-package org.jboss.ejb3.cache.impl;
-
-import java.io.Serializable;
-
-import org.jboss.ejb3.cache.Cacheable;
-import org.jboss.ejb3.cache.PassivatingCache;
-import org.jboss.ejb3.cache.grouped.SerializationGroup;
-import org.jboss.ejb3.cache.grouped.SerializationGroupMember;
-
-/**
- * Default implementation of {@link SerializationGroupMember}.
- * 
- * @author Brian Stansberry
- * @version $Revision$
- */
-public class SerializationGroupMemberImpl<T extends Cacheable & Serializable> 
- implements Cacheable, SerializationGroupMember, Serializable
-{
-   private static final long serialVersionUID = 1L;
-   
-   private Object id;
-   /**
-    * The underlying object (e.g. bean context).
-    * Preferably, this field would be transient. It isn't now because it is 
-    * possible this entry will never be assigned to a PassivationGroup,
-    * in which case we need to serialize obj.
-    * TODO Relying on nulling this field is fragile. Can we make this
-    * field transient by ensuring we only use this cache class with bean 
-    * classes that are sure to be part of a group?
-    */
-   private T obj;
-   /**
-    * Hack. We hold two refs to our object; one we clear in prePassivate,
-    * one we keep, but it's transient.  getSerializableObject() returns
-    * whichever is available, making it available for passivation callbacks.
-    */
-   private transient T transientObj;
-   /** The group. Never serialize the group; only the groupCache does that */
-   private transient SerializationGroup group;
-   private Object groupId;
-   private long lastUsed;
-   /** The cache that's handling us */
-   private transient PassivatingCache<SerializationGroupMemberImpl<T>> delegate;
-   
-   SerializationGroupMemberImpl(T obj, PassivatingCache<SerializationGroupMemberImpl<T>> delegate)
-   {
-      assert obj != null : "obj is null";
-      assert delegate != null : "delegate is null";
-      
-      this.obj = transientObj = obj;
-      this.id = obj.getId();
-      this.delegate = delegate;
-   }
-   
-   public Object getId()
-   {
-      return id;
-   }
-   
-   public boolean isClustered()
-   {
-      // Value from the containing cache
-      return delegate.isClustered();
-   }
-   
-   @SuppressWarnings("unchecked")
-   public T getSerializableObject()
-   {      
-      return obj == null ? transientObj : obj;
-   }
-   
-   public void setSerializableObject(T obj)
-   {
-      this.obj = transientObj = obj;
-   }
-   
-   public SerializationGroup getGroup()
-   {
-      return group;
-   }
-
-   public void setGroup(SerializationGroup group)
-   {
-      this.group = group;
-   }
-
-   public Object getGroupId()
-   {
-      return groupId;
-   }
-
-   public void setGroupId(Object groupId)
-   {
-      this.groupId = groupId;
-   }
-
-   // Called by PassivationGroup prior to its passivating
-   public void prePassivate()
-   {
-      // make sure we don't passivate the group twice
-      group = null;
-      
-      // null out obj so when delegate passivates this entry
-      // we don't serialize it. It serializes with the PassivationGroup only  
-      // We still have a ref to transientObj, so it can be retrieved
-      // for passivation callbacks
-      obj = null;
-      
-      delegate.passivate(this.id);
-   }
-   
-   // Called by PassivationGroup prior to its replicating
-   public void preReplicate()
-   {
-      // make sure we don't replicate the group twice
-      group = null;
-      // null out obj so when delegate passivates this entry
-      // we don't serialize it. It serializes with the PassivationGroup only
-      obj = null;
-      
-      delegate.replicate(this.id);
-   }
-   
-   public long getLastUsed()
-   {
-      return obj == null ? lastUsed : obj.getLastUsed();
-   }
-
-   public boolean isInUse()
-   {
-      return obj == null ? false : obj.isInUse();
-   }
-
-   public void setInUse(boolean inUse)
-   {
-      if (obj != null)
-      {
-         obj.setInUse(inUse);
-         lastUsed = obj.getLastUsed();
-      }
-   }
-   
-   /**
-    * Allows our controlling {@link PassivatingCache} to provide
-    * us a reference after deserialization.
-    * 
-    * @param delegate
-    */
-   public void setPassivatingCache(PassivatingCache<SerializationGroupMemberImpl<T>> delegate)
-   {
-      assert delegate != null : "delegate is null";
-      
-      this.delegate = delegate;
-   }
-   
-   public boolean isModified()
-   {
-      return (obj != null && obj.isModified());
-   }
-
-   @Override
-   public String toString()
-   {
-      return super.toString() + "{id=" + id + ",obj=" + obj + ",groupId=" + groupId + ",group=" + group + "}";
-   }
-}
\ No newline at end of file

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimpleCache.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimpleCache.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimpleCache.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,115 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2007, 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.ejb3.cache.impl;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.ejb.NoSuchEJBException;
-
-import org.jboss.ejb3.cache.Cache;
-import org.jboss.ejb3.cache.Identifiable;
-import org.jboss.ejb3.cache.StatefulObjectFactory;
-
-/**
- * Comment
- *
- * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
- * @version $Revision: $
- */
-public class SimpleCache<T extends Identifiable> implements Cache<T>
-{
-   private StatefulObjectFactory<T> factory;
-   private Map<Object, T> cache;
-   
-   public SimpleCache(StatefulObjectFactory<T> factory)
-   {
-      assert factory != null;
-      
-      this.factory = factory;
-      this.cache = new HashMap<Object, T>();
-   }
-   
-   public T create(Class<?>[] initTypes, Object[] initValues)
-   {
-      T obj = factory.create(initTypes, initValues);
-      synchronized(cache)
-      {
-         cache.put(obj.getId(), obj);
-      }
-      return obj;
-   }
-
-   public T get(Object key) throws NoSuchEJBException
-   {
-      T obj;
-      synchronized (cache)
-      {
-         obj = cache.get(key);
-      }
-      if(obj == null)
-         throw new NoSuchEJBException(String.valueOf(key));
-      return obj;
-   }
-
-   public T peek(Object key) throws NoSuchEJBException
-   {
-      return get(key);
-   }
-   
-   public void release(T obj)
-   {
-      // release does nothing
-   }
-   
-   public void remove(Object key)
-   {
-      T obj;
-      synchronized (cache)
-      {
-         obj = cache.remove(key);
-      }
-      if(obj != null)
-         factory.destroy(obj);
-   } 
-   
-   public boolean isClustered()
-   {
-      return false;
-   }  
-   
-   public void replicate(Object key)
-   {
-      throw new UnsupportedOperationException("Clustering is not supported by " + 
-            getClass().getName());      
-   }
-   
-   public void start()
-   {
-      // do nothing
-   }
-   
-   public void stop()
-   {
-      // do nothing
-   }
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimpleIntegratedObjectStore.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimpleIntegratedObjectStore.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimpleIntegratedObjectStore.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,366 +0,0 @@
-/*
- * 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.ejb3.cache.impl;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import org.jboss.ejb3.cache.Cacheable;
-import org.jboss.ejb3.cache.IntegratedObjectStore;
-import org.jboss.ejb3.cache.ObjectStore;
-import org.jboss.ejb3.cache.PassivatingCache;
-import org.jboss.ejb3.cache.PassivatingIntegratedObjectStore;
-import org.jboss.logging.Logger;
-
-/**
- * A {@link IntegratedObjectStore} that delegates to a provided
- * {@link ObjectStore} for persistence.
- * 
- * @author Brian Stansberry
- * @version $Revision$
- */
-public class SimpleIntegratedObjectStore<T extends Cacheable & Serializable> 
-      implements PassivatingIntegratedObjectStore<T>
-{
-   private static final Logger log = Logger.getLogger(SimpleIntegratedObjectStore.class);
-   
-   private final ObjectStore<T> store;
-   private Map<Object, T> cache;
-   private Map<Object, Long> passivatedEntries;
-   
-   /**
-    * Support callbacks when our SessionTimeoutThread decides to
-    * evict an entry.
-    */
-   private PassivatingCache<T> owningCache;   
-   private int interval;
-   private int idleTimeSeconds;
-   private int expirationTimeSeconds;   
-   private SessionTimeoutRunner sessionTimeoutRunner;
-   private String name;
-   
-   /**
-    * Create a new SimpleIntegratedObjectStore.
-    * 
-    */
-   public SimpleIntegratedObjectStore(ObjectStore<T> store)
-   {
-      this.store = store;
-      this.cache = new HashMap<Object, T>();
-      this.passivatedEntries = new HashMap<Object, Long>();
-   }
-   
-   public boolean isClustered()
-   {
-      return false;
-   }
-
-   public T get(Object key)
-   {
-      synchronized (cache)
-      {
-         T entry = cache.get(key);
-         if(entry == null)
-         {
-            entry = store.load(key);
-            if(entry != null)
-            {
-               cache.put(key, entry);
-               passivatedEntries.remove(key);
-            }
-         }
-         return entry;
-      }
-   }
-
-   public void insert(T entry)
-   {
-      Object key = entry.getId();
-      synchronized (cache)
-      {
-         if (cache.containsKey(key) || passivatedEntries.containsKey(key))
-         {
-            throw new IllegalStateException(key + " is already in store");
-         }
-         cache.put(key, entry);
-      }
-   }
-   
-   public void update(T entry)
-   {
-      Object key = entry.getId();
-      synchronized (cache)
-      {
-         if (!cache.containsKey(key) && !passivatedEntries.containsKey(key))
-         {
-            throw new IllegalStateException(key + " is not managed by this store");
-         }
-         
-         // Otherwise we do nothing; we already have a ref to the entry
-      }
-   }
-
-   public void passivate(T entry)
-   {
-      synchronized (cache)
-      {
-         Object key = entry.getId();
-         store.store(entry);  
-         passivatedEntries.put(key, new Long(entry.getLastUsed()));
-         cache.remove(key);
-      }
-   }
-
-   public T remove(Object id)
-   {
-      synchronized (cache)
-      {
-         T entry = get(id);
-         if (entry != null)
-         {
-            cache.remove(id);
-         }
-         return entry;
-      }
-   } 
-
-   public void start()
-   {
-      if (interval > 0)
-      {
-         if (sessionTimeoutRunner == null)
-         {
-            assert name != null : "name has not been set";
-            assert owningCache != null;
-            
-            sessionTimeoutRunner = new SessionTimeoutRunner();
-         }
-         sessionTimeoutRunner.start();
-      }     
-      
-      log.debug("Started " + name);
-   }
-
-   public void stop()
-   {
-      if (sessionTimeoutRunner != null)
-      {
-         sessionTimeoutRunner.stop();
-      }      
-      
-      log.debug("Stopped " + name);
-   }
-
-   // ---------------------------------------  PassivatingIntegratedObjectStore
-
-
-   public void setPassivatingCache(PassivatingCache<T> cache)
-   {
-      this.owningCache = cache;      
-   }
-   
-   public int getInterval()
-   {
-      return interval;
-   }
-
-   public void setInterval(int seconds)
-   {
-      this.interval = seconds;      
-   }
-   
-   public void runExpiration()
-   {
-      if (expirationTimeSeconds > 0)
-      {
-         long now = System.currentTimeMillis();
-         long minRemovalUse = now - (expirationTimeSeconds * 1000);                     
-         for (CacheableTimestamp ts : getPassivatedEntries())
-         {
-            try
-            {
-               if (minRemovalUse >= ts.getLastUsed())
-               {
-                  remove(ts.getId());
-               }
-            }
-            catch (IllegalStateException ise)
-            {
-               // Not so great; we're assuming it's 'cause item's in use
-               log.trace("skipping in-use entry " + ts.getId(), ise);
-            }
-         }    
-      }      
-   }
-
-   public void runPassivation()
-   {
-      if (idleTimeSeconds > 0)
-      {
-         long now = System.currentTimeMillis();
-         long minPassUse = now - (idleTimeSeconds * 1000);
-         
-         // Scan the in-memory entries for passivation or removal
-         for (CacheableTimestamp ts : getInMemoryEntries())
-         {
-            try
-            {
-               long lastUsed = ts.getLastUsed();
-               if (minPassUse >= lastUsed)
-               {
-                  owningCache.passivate(ts.getId());
-               }
-            }
-            catch (IllegalStateException ise)
-            {
-               // Not so great; we're assuming it's 'cause item's in use
-               log.trace("skipping in-use entry " + ts.getId(), ise);
-            }
-         }
-      }
-      
-   }   
-   
-   public int getIdleTimeSeconds()
-   {
-      return idleTimeSeconds;
-   }
-
-   public void setIdleTimeSeconds(int idleTimeSeconds)
-   {
-      this.idleTimeSeconds = idleTimeSeconds;
-   }
-
-   public int getExpirationTimeSeconds()
-   {
-      return expirationTimeSeconds;
-   }
-   
-   public void setExpirationTimeSeconds(int timeout)
-   {
-      this.expirationTimeSeconds = timeout;
-   } 
-
-   private SortedSet<CacheableTimestamp> getInMemoryEntries()
-   {      
-      SortedSet<CacheableTimestamp> set = new TreeSet<CacheableTimestamp>();
-      for (Map.Entry<Object, T> entry : cache.entrySet())
-      {
-         set.add(new CacheableTimestamp(entry.getKey(), entry.getValue().getLastUsed()));
-      }
-      return set;
-   }
-
-   private SortedSet<CacheableTimestamp> getPassivatedEntries()
-   {
-      SortedSet<CacheableTimestamp> set = new TreeSet<CacheableTimestamp>();
-      for (Map.Entry<Object, Long> entry : passivatedEntries.entrySet())
-      {
-         set.add(new CacheableTimestamp(entry.getKey(), entry.getValue().longValue()));
-      }
-      return set;
-   }
-
-   public void setName(String name)
-   {
-      this.name = name;
-   }
-   
-
-   private class SessionTimeoutRunner implements Runnable
-   {
-      private boolean stopped = true;
-      private Thread thread;
-      
-      public void run()
-      {
-         while (!stopped)
-         {
-            try
-            {
-               runPassivation();               
-            }
-            catch (Exception e)
-            {
-               log.error("Caught exception processing passivations", e);
-            }
-            
-            if (!stopped)
-            {
-               try
-               {
-                  runExpiration();               
-               }
-               catch (Exception e)
-               {
-                  log.error("Caught exception processing expirations", e);
-               }               
-            }
-            
-            if (!stopped)
-            {
-               try
-               {
-                  Thread.sleep(interval * 1000);
-               }
-               catch (InterruptedException ignored) {}
-            }
-         }
-      }
-      
-      void start()
-      {
-         if (stopped)
-         {
-            thread = new Thread(this, "SessionTimeoutRunner-" + name);
-            thread.setDaemon(true);
-            stopped = false;
-            thread.start();
-         }
-      }
-      
-      void stop()
-      {
-         stopped = true;
-         if (thread != null && thread.isAlive())
-         {
-            try
-            {
-               thread.join(1000);
-            }
-            catch (InterruptedException ignored) {}
-            
-            if (thread.isAlive())
-            {
-               thread.interrupt();
-            }
-            
-         }
-      }
-      
-   }
-
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimplePassivatingCache.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimplePassivatingCache.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimplePassivatingCache.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,309 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.cache.impl;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import javax.ejb.NoSuchEJBException;
-
-import org.jboss.ejb3.cache.Identifiable;
-import org.jboss.ejb3.cache.ObjectStore;
-import org.jboss.ejb3.cache.PassivatingCache;
-import org.jboss.ejb3.cache.PassivationManager;
-import org.jboss.ejb3.cache.StatefulObjectFactory;
-import org.jboss.logging.Logger;
-
-/**
- * Comment
- *
- * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
- * @version $Revision$
- */
-public class SimplePassivatingCache<T extends Identifiable & Serializable> implements PassivatingCache<T>
-{
-   private static final Logger log = Logger.getLogger(SimplePassivatingCache.class);
-   
-   private StatefulObjectFactory<T> factory;
-   private PassivationManager<T> passivationManager;
-   private ObjectStore<T> store;
-   
-   private Map<Object, Entry> cache;
-   
-   private int sessionTimeout = -1;
-   private String name;
-   
-   private Thread sessionTimeoutTask;
-   
-   private static enum EntryState { READY, IN_USE };
-   
-   private class Entry
-   {
-      long lastUsed;
-      T obj;
-      EntryState state;
-      
-      Entry(T obj)
-      {
-         assert obj != null : "obj is null";
-         
-         this.lastUsed = System.currentTimeMillis();
-         this.obj = obj;
-         this.state = EntryState.IN_USE;
-      }
-   }
-   
-   private class SessionTimeoutThread extends Thread
-   {
-      public SessionTimeoutThread(String name)
-      {
-         super(name);
-         setDaemon(true);
-      }
-      
-      @Override
-      public void run()
-      {
-         try
-         {
-            while(!Thread.currentThread().isInterrupted())
-            {
-               Thread.sleep(1000);
-               
-               synchronized (cache)
-               {
-                  if(Thread.currentThread().isInterrupted())
-                     return;
-                  
-                  long then = System.currentTimeMillis() - sessionTimeout * 1000;
-                  Iterator<Entry> it = cache.values().iterator();
-                  while(it.hasNext())
-                  {
-                     Entry entry = it.next();
-                     if(then >= entry.lastUsed && entry.state != EntryState.IN_USE)
-                     {
-                        // TODO: can passivate?
-                        try
-                        {
-                           passivationManager.prePassivate(entry.obj);
-                        }
-                        catch(Throwable t)
-                        {
-                           log.warn("pre passivate failed for " + entry.obj, t);
-                        }
-                        
-                        store.store(entry.obj);
-                        
-                        it.remove();
-                     }
-                  }
-               }
-            }
-         }
-         catch(InterruptedException e)
-         {
-            // do nothing
-         }
-      }
-   }
-   
-   public SimplePassivatingCache(StatefulObjectFactory<T> factory, PassivationManager<T> passivationManager, ObjectStore<T> store)
-   {
-      assert factory != null : "factory is null";
-      assert passivationManager != null : "passivationManager is null";
-      assert store != null : "store is null";
-      
-      this.factory = factory;
-      this.passivationManager = passivationManager;
-      this.store = store;
-      this.cache = new HashMap<Object, Entry>();
-   }
-   
-   public boolean isClustered()
-   {
-      return false;
-   }
-   
-   public void replicate(Object key)
-   {
-      throw new UnsupportedOperationException("Clustering is not supported by " + 
-                                              getClass().getName());      
-   }
-   
-   public T create(Class<?>[] initTypes, Object[] initValues)
-   {
-      T obj = factory.create(initTypes, initValues);
-      Entry entry = new Entry(obj);
-      synchronized (cache)
-      {
-         cache.put(obj.getId(), entry);
-      }
-      return obj;
-   }
-
-   public T get(Object key) throws NoSuchEJBException
-   {
-      synchronized (cache)
-      {
-         Entry entry = cache.get(key);
-         if(entry == null)
-         {
-            T obj = store.load(key);
-            if(obj != null)
-            {
-               passivationManager.postActivate(obj);
-               
-               entry = new Entry(obj);
-               cache.put(key, entry);
-               return entry.obj;
-            }
-         }
-         if(entry == null)
-            throw new NoSuchEJBException(String.valueOf(key));
-         if(entry.state != EntryState.READY)
-            throw new IllegalStateException("entry " + key + " is not ready");
-         entry.state = EntryState.IN_USE;
-         entry.lastUsed = System.currentTimeMillis();
-         return entry.obj;
-      }
-   }
-
-   public void passivate(Object key)
-   {
-      log.trace("passivate " + key);
-      synchronized (cache)
-      {
-         Entry entry = cache.get(key);
-         
-         if(entry == null)
-            throw new IllegalArgumentException("entry " + key + " not found in cache " + this);
-         
-         if(entry.state == EntryState.IN_USE)
-            throw new IllegalStateException("entry " + entry + " is in use");
-         
-         passivationManager.prePassivate(entry.obj);
-         
-         store.store(entry.obj);
-         
-         cache.remove(key);
-      }
-   }
-   
-   public T peek(Object key) throws NoSuchEJBException
-   {
-      synchronized (cache)
-      {
-         Entry entry = cache.get(key);
-         if(entry == null)
-         {
-            T obj = store.load(key);
-            if(obj != null)
-            {
-               passivationManager.postActivate(obj);
-               
-               entry = new Entry(obj);
-               cache.put(key, entry);
-               entry.state = EntryState.READY;
-            }
-         }
-         if(entry == null)
-            throw new NoSuchEJBException(String.valueOf(key));
-         return entry.obj;
-      }
-   }
-
-   public void release(T obj)
-   {
-      releaseByKey(obj.getId());
-   }
-
-   protected void releaseByKey(Object key)
-   {
-      synchronized (cache)
-      {
-         Entry entry = cache.get(key);
-         if(entry == null)
-            throw new IllegalStateException("object " + key + " not from this cache");
-         if(entry.state != EntryState.IN_USE)
-            throw new IllegalStateException("entry " + entry + " is not in use");
-         entry.state = EntryState.READY;
-         entry.lastUsed = System.currentTimeMillis();
-      }
-   }
-   
-   public void remove(Object key)
-   {
-      Entry entry;
-      synchronized (cache)
-      {
-         entry = cache.remove(key);
-         if(entry.state != EntryState.READY)
-            throw new IllegalStateException("entry " + entry + " is not ready");
-      }
-      if(entry != null)
-         factory.destroy(entry.obj);
-   }
-
-   public void setName(String name)
-   {
-      this.name = name;
-   }
-   
-   public void setSessionTimeout(int sessionTimeout)
-   {
-      assert sessionTimeout >= 0 : "sessionTimeout must be >= 0";
-      this.sessionTimeout = sessionTimeout;
-   }
-   
-   public void start()
-   {
-      assert name != null : "name has not been set";
-      assert sessionTimeout != -1 : "sessionTimeout has not been set";
-      
-      if(sessionTimeout > 0)
-      {
-         sessionTimeoutTask = new SessionTimeoutThread("Passivation Thread - " + name);
-         sessionTimeoutTask.start();
-      }
-   }
-
-   public void stop()
-   {
-      if(sessionTimeoutTask != null)
-      {
-         sessionTimeoutTask.interrupt();
-         try
-         {
-            sessionTimeoutTask.join(5000);
-         }
-         catch (InterruptedException e)
-         {
-            // ignore
-         }
-         if(sessionTimeoutTask.isAlive())
-            log.warn("Failed to stop " + sessionTimeoutTask);
-      }
-   }
-
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimplePassivatingCache2.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimplePassivatingCache2.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SimplePassivatingCache2.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,220 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.cache.impl;
-
-import java.io.Serializable;
-
-import javax.ejb.NoSuchEJBException;
-
-import org.jboss.ejb3.cache.Cacheable;
-import org.jboss.ejb3.cache.IntegratedObjectStore;
-import org.jboss.ejb3.cache.PassivatingCache;
-import org.jboss.ejb3.cache.PassivatingIntegratedObjectStore;
-import org.jboss.ejb3.cache.PassivationManager;
-import org.jboss.ejb3.cache.StatefulObjectFactory;
-import org.jboss.logging.Logger;
-
-/**
- * Non group-aware {@link PassivatingCache} that uses an {@link IntegratedObjectStore}
- * to manage data.
- *
- * @author Brian Stansberry
- * @version $Revision: 65339 $
- */
-public class SimplePassivatingCache2<T extends Cacheable & Serializable> implements PassivatingCache<T>
-{
-   private static final Logger log = Logger.getLogger(SimplePassivatingCache2.class);
-   
-   private StatefulObjectFactory<T> factory;
-   private PassivationManager<T> passivationManager;
-   private IntegratedObjectStore<T> store;
-   
-   public SimplePassivatingCache2(StatefulObjectFactory<T> factory, PassivationManager<T> passivationManager, IntegratedObjectStore<T> store)
-   {
-      assert factory != null : "factory is null";
-      assert passivationManager != null : "passivationManager is null";
-      assert store != null : "store is null";
-      
-      this.factory = factory;
-      this.passivationManager = passivationManager;
-      this.store = store;
-      if (store instanceof PassivatingIntegratedObjectStore)
-      {
-         ((PassivatingIntegratedObjectStore<T>) store).setPassivatingCache(this);
-      }
-   }
-   
-   public boolean isClustered()
-   {
-      return store.isClustered();
-   }
-   
-   public void replicate(Object key)
-   {
-      if (!isClustered())
-      {
-         throw new UnsupportedOperationException("Clustering is not supported by " + 
-                                                 store.getClass().getName());
-      }
-      
-      log.trace("replicate " + key);
-      synchronized (store)
-      {
-         T entry = store.get(key);
-         
-         if(entry == null)
-            throw new IllegalArgumentException("entry " + key + " not found in cache " + this);
-         
-         if(entry.isInUse())
-         {
-            throw new IllegalStateException("entry " + entry + " is in use");
-         }
-         
-         passivationManager.preReplicate(entry);
-         
-         store.update(entry);
-      }
-   }
-   
-   public T create(Class<?>[] initTypes, Object[] initValues)
-   {
-      T obj = factory.create(initTypes, initValues);
-      obj.setInUse(true);
-      synchronized (store)
-      {
-         store.insert(obj);
-      }
-      return obj;
-   }
-
-   public T get(Object key) throws NoSuchEJBException
-   {
-      synchronized (store)
-      {
-         T entry = store.get(key);
-         if(entry == null)
-            throw new NoSuchEJBException(String.valueOf(key));
-         
-         if (isClustered())
-         {
-            passivationManager.postReplicate(entry);
-         }
-         
-         passivationManager.postActivate(entry);
-         
-//         if(entry.getCacheState() != Cacheable.State.READY)
-//         {
-//            throw new IllegalStateException("entry " + key + " is not ready");
-//         }
-         entry.setInUse(true);
-         return entry;
-      }
-   }
-
-   public void passivate(Object key)
-   {
-      log.trace("passivate " + key);
-      synchronized (store)
-      {
-         T entry = store.get(key);
-         
-         if(entry == null)
-            throw new IllegalArgumentException("entry " + key + " not found in cache " + this);
-         
-         if(entry.isInUse())
-         {
-            throw new IllegalStateException("entry " + entry + " is in use");
-         }
-
-         passivationManager.prePassivate(entry);
-         
-         store.passivate(entry);
-      }
-   }
-   
-   public T peek(Object key) throws NoSuchEJBException
-   {
-      synchronized (store)
-      {
-         T entry = store.get(key);
-         if(entry == null)
-            throw new NoSuchEJBException(String.valueOf(key));
-         
-         // TODO why call these in peek?  We should *always* call
-         // them in get() and let the PassivationManager sort out
-         // whether they really need to be called
-         
-//         if (isClustered())
-//         {
-//            passivationManager.postReplicate(entry);
-//         }
-//         
-//         passivationManager.postActivate(entry);
-         
-         return entry;
-      }
-   }
-
-   public void release(T obj)
-   {
-      releaseByKey(obj.getId());
-   }
-
-   protected T releaseByKey(Object key)
-   {
-      synchronized (store)
-      {
-         T entry = store.get(key);
-         if(entry == null)
-            throw new IllegalStateException("object " + key + " not from this cache");
-         if(!entry.isInUse())
-            throw new IllegalStateException("entry " + entry + " is not in use");
-         entry.setInUse(false);
-         store.update(entry);
-         return entry;
-      }
-   }
-   
-   public void remove(Object key)
-   {
-      T entry;
-      synchronized (store)
-      {
-         entry = store.remove(key);
-         if(entry.isInUse())
-            throw new IllegalStateException("entry " + entry + " is in use");
-      }
-      if(entry != null)
-         factory.destroy(entry);
-   }
-   
-   public void start()
-   {
-      store.start();
-   }
-
-   public void stop()
-   {
-      store.stop();
-   }
-
-}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/TransactionalCache.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/TransactionalCache.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/TransactionalCache.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,324 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007, 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.ejb3.cache.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.ejb.NoSuchEJBException;
+import javax.transaction.RollbackException;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.jboss.ejb3.cache.Cache;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.SerializationGroup;
+import org.jboss.ejb3.cache.spi.BackingCache;
+import org.jboss.ejb3.cache.spi.BackingCacheEntry;
+import org.jboss.ejb3.cache.spi.IntegratedObjectStore;
+
+/**
+ * {@link Cache#isGroupAware() Non-group-aware} <code>Cache</code> implementation 
+ * that applies transactional access and release semantics. Specifically: 
+ * <ol>
+ * <li>monitors the transactional status of threads that invoke create() and get()</li>
+ * <li>ensures that until the first transaction that accesses a given CacheItem 
+ * has completed, any other transaction that attempts to access the item will
+ * receive an IllegalStateException</li>
+ * <li>Only releases the CacheItem to the underlying {@link IntegratedObjectStore}
+ * when the transaction commits or rolls back.</li>
+ * </ol>
+ * <p>
+ * Delegates many functions to a backing {@link BackingCache}.
+ * </p>
+ * 
+ * @author Brian Stansberry
+ * @version $Revision: 69058 $
+ */
+public class TransactionalCache<C extends CacheItem, T extends BackingCacheEntry<C>> implements Cache<C>
+{
+   /** BackingCache that handles passivation, groups, etc */
+   private final BackingCache<C, T> delegate;
+   
+   /** Cache of items that are in use by a tx or non-transactional invocation */
+   private final Map<Object, Entry> inUseCache;
+   /** Map of Synchronizations to release items in use by a tx*/
+   private final ConcurrentMap<Object, CacheReleaseSynchronization<C, T>> synchronizations;
+   /** Our transaction manager */
+   private final TransactionManager tm;
+   
+   private enum State { INITIALIZED, IN_USE, FINISHED };
+   private class Entry
+   {
+      long lastUsed;
+      C obj;
+      State state;
+      
+      Entry()
+      {
+         this.lastUsed = System.currentTimeMillis();
+         this.state = State.INITIALIZED;
+      }
+   }
+   
+   private static class CacheReleaseSynchronization<C extends CacheItem, T extends BackingCacheEntry<C>> 
+      implements Synchronization
+   {
+      private TransactionalCache<C, T> cache;
+      private C cacheItem;
+      private Transaction tx;
+      
+      private CacheReleaseSynchronization(TransactionalCache<C, T> cache,
+                                          C cacheItem, Transaction tx)
+      {
+         assert cache != null : "cache is null";
+         assert cacheItem != null : "cacheItem is null";
+         assert tx != null : "tx is null";
+         
+         this.cache = cache;
+         this.cacheItem = cacheItem;
+         this.tx = tx;
+      }
+      
+      public Transaction getTransaction()
+      {
+         return tx;
+      }
+      
+      public void beforeCompletion()
+      {
+         cache.release(cacheItem);         
+      }
+      
+      public void afterCompletion(int arg0)
+      {
+         cache.releaseSynchronization(cacheItem);
+         cache = null;
+         cacheItem = null;
+         tx = null;         
+      }      
+   }
+   
+   public TransactionalCache(BackingCache<C, T> delegate, TransactionManager tm)
+   {
+      assert delegate != null : "delegate is null";
+      assert tm != null : "tm is null";
+      
+      this.delegate = delegate;
+      this.tm = tm;
+      
+      this.inUseCache = new HashMap<Object, Entry>();
+      this.synchronizations = new ConcurrentHashMap<Object, CacheReleaseSynchronization<C, T>>();
+   }
+
+   public C create(Class<?>[] initTypes, Object[] initValues)
+   {
+      T backingEntry = delegate.create(initTypes, initValues);
+      C obj = backingEntry.getUnderlyingItem();
+      synchronized (inUseCache)
+      {
+         // Create an entry, but do not store a ref to obj in the entry.
+         // This will ensure get() goes to the backingCache to get the
+         // missing obj, giving the backingCache an opportunity to mark
+         // the BackingCacheEntry as being in use
+         registerEntry(obj, false);
+      }
+      return obj;
+   }
+
+   private Entry registerEntry(C obj, boolean storeRef)
+   {
+      Entry entry = new Entry(); 
+      if (storeRef)
+         entry.obj = obj;
+      inUseCache.put(obj.getId(), entry);      
+      registerSynchronization(obj);
+      return entry;
+   }
+   
+   public C get(Object key) throws NoSuchEJBException
+   {
+      Entry entry = null;
+      
+      // Yuck. This is a bottleneck
+      synchronized (inUseCache)
+      {
+         entry = inUseCache.get(key);
+         if(entry == null)
+         {
+            T backingEntry = delegate.get(key);
+            C obj = backingEntry.getUnderlyingItem();
+            entry = registerEntry(obj, true); 
+         }
+      }
+      
+      if (entry.obj == null)
+         entry.obj = delegate.get(key).getUnderlyingItem();
+      
+      validateTransaction(entry.obj);
+      if(entry.state == State.IN_USE)
+         throw new IllegalStateException("entry " + key + " is already in use");
+      entry.state = State.IN_USE;
+      entry.lastUsed = System.currentTimeMillis();
+      return entry.obj;
+   }
+   
+   public void finished(C obj)
+   {
+      Entry entry = null;
+      synchronized (inUseCache)
+      {
+         entry = inUseCache.get(obj.getId());
+      }
+      if (entry == null)
+         throw new IllegalStateException("No entry for " + obj.getId());
+      if(entry.state != State.IN_USE)
+         throw new IllegalStateException("entry " + obj.getId() + " is not in operation");
+      entry.state = State.FINISHED;
+      entry.lastUsed = System.currentTimeMillis();
+      
+      // If there is no tx associated with this object, we can release it
+      if (synchronizations.get(obj.getId()) == null)
+      {
+         release(obj);
+      }
+      
+   }
+
+   public void remove(Object key)
+   {
+      // Note that the object is not in my cache at this point.
+      // FIXME BES 2008/03/10 -- above comment not true!
+      delegate.remove(key);
+      inUseCache.remove(key);
+   }
+
+   public void start()
+   {
+      delegate.start();
+   }
+
+   public void stop()
+   {
+      delegate.stop();
+   }
+
+   public boolean isGroupAware()
+   {
+      return false;
+   }
+
+   public SerializationGroup<C> getGroup(C obj)
+   {
+      return null;
+   }
+   
+   public BackingCache<C, T> getBackingCache()
+   {
+      return delegate;
+   }
+
+   /**
+    * Actually release the object from our delegate 
+    * @param obj
+    */
+   private void release(C obj)
+   {
+      Object key = obj.getId();
+      synchronized (inUseCache)
+      {
+         Entry entry = inUseCache.get(key);
+         if (entry == null)
+         {
+            // FIXME is this correct?
+            return;
+         }
+         if(entry.state == State.IN_USE)
+            throw new IllegalStateException("entry " + key + " is not finished");
+         inUseCache.remove(key);
+      }
+      delegate.release(obj.getId());
+   }
+   
+   private void registerSynchronization(C cacheItem)
+   {
+      Transaction tx = getCurrentTransaction();
+      if (tx != null)
+      {
+         CacheReleaseSynchronization<C, T> sync = new CacheReleaseSynchronization<C, T>(this, cacheItem, tx);
+         try
+         {
+            tx.registerSynchronization(sync);
+         }
+         catch (RollbackException e)
+         {
+            throw new RuntimeException("Failed registering synchronization for " + cacheItem, e);
+         }
+         catch (SystemException e)
+         {
+            throw new RuntimeException("Failed registering synchronization for " + cacheItem, e);
+         }
+         synchronizations.put(cacheItem.getId(), sync);
+      }
+   }
+   
+   private Transaction getCurrentTransaction()
+   {
+      try
+      {
+         return tm == null ? null : tm.getTransaction();
+      }
+      catch (SystemException e)
+      {
+         throw new RuntimeException("Failed getting current transaction from " + tm, e);
+      }
+   }
+   
+   private void releaseSynchronization(C cacheItem)
+   {
+      synchronizations.remove(cacheItem.getId());      
+   }
+   
+   private void validateTransaction(C cacheItem)
+   {
+      CacheReleaseSynchronization<C, T> sync = synchronizations.get(cacheItem.getId());
+      
+      if (sync != null)
+      {         
+         Transaction syncTx = sync.getTransaction();
+         if (syncTx != null) // may be null if sync has just completed
+         {
+            Transaction threadTx = getCurrentTransaction();
+            if(!syncTx.equals(threadTx))
+            {
+               throw new IllegalStateException("Illegal concurrent access to " + cacheItem +
+                                               " by two transactions: " + syncTx + " and " + threadTx);
+            }
+         }
+               
+      }
+   }   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/GroupAwareBackingCacheImpl.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/GroupAwareBackingCacheImpl.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/GroupAwareBackingCacheImpl.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,102 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.cache.impl.backing;
+
+import javax.ejb.NoSuchEJBException;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.SerializationGroup;
+import org.jboss.ejb3.cache.spi.GroupAwareBackingCache;
+import org.jboss.ejb3.cache.spi.GroupIncompatibilityException;
+import org.jboss.ejb3.cache.spi.PassivatingBackingCache;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupImpl;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupMember;
+
+/**
+ * Group-aware  version of {@link PassivatingBackingCacheImpl}.
+ *
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class GroupAwareBackingCacheImpl<C extends CacheItem>
+   extends PassivatingBackingCacheImpl<C, SerializationGroupMember<C>>
+   implements GroupAwareBackingCache<C, SerializationGroupMember<C>>
+{
+   /**
+    * Cache that's managing the SerializationGroup
+    */
+   private PassivatingBackingCache<C, SerializationGroupImpl<C>> groupCache;
+   
+   /**
+    * Creates a new GroupAwareCacheImpl.
+    * 
+    * @param memberContainer  the factory for the underlying CacheItems
+    * @param groupCache  cache for the group
+    */
+   public GroupAwareBackingCacheImpl(SerializationGroupMemberContainer<C> memberContainer, 
+                                     PassivatingBackingCache<C, SerializationGroupImpl<C>> groupCache)
+   {
+      super(memberContainer, memberContainer, memberContainer);
+      assert groupCache != null : "groupCache is null";
+      assert groupCache.isClustered() == memberContainer.isClustered(): "incompatible clustering support between groupCache and passivationManager";
+
+      this.groupCache = groupCache;
+   }
+   
+   public SerializationGroupImpl<C> createGroup()
+   {
+      return groupCache.create(null, null);
+   }
+
+   public void setGroup(C obj, SerializationGroup<C> group) throws GroupIncompatibilityException
+   {     
+      Object key = obj.getId();
+      SerializationGroupMember<C> entry = peek(key);
+      if(entry.getGroup() != null)
+         throw new IllegalStateException("object " + key + " is already associated with passivation group " + entry.getGroup());
+      
+      // Validate we share a common groupCache with the group
+      SerializationGroupImpl<C> groupImpl = (SerializationGroupImpl<C>) group;
+      if (groupCache != groupImpl.getGroupCache())
+         throw new GroupIncompatibilityException(obj + " and " + groupImpl + " use different group caches");
+      
+      entry.setGroup(groupImpl);
+      entry.getGroup().addMember(entry);
+   }
+
+   public SerializationGroup<C> getGroup(C obj)
+   {
+      Object key = obj.getId();
+      try
+      {
+         SerializationGroupMember<C> entry = peek(key);
+         return entry.getGroup();
+      }
+      catch (NoSuchEJBException nsee)
+      {
+         return null;
+      }
+   }  
+   
+   
+   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/NonPassivatingBackingCacheEntry.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/NonPassivatingBackingCacheEntry.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/NonPassivatingBackingCacheEntry.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,72 @@
+/*
+ * 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.ejb3.cache.impl.backing;
+
+import java.io.Serializable;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.spi.BackingCacheEntry;
+import org.jboss.ejb3.cache.spi.impl.AbstractBackingCacheEntry;
+
+/**
+ * Basic {@link BasicCacheEntry} implementation for use with a non-passivating
+ * {@link BackingCache}.  A wrapper for the {@link CacheItem} to allow it to 
+ * be managed by the backing cache .
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class NonPassivatingBackingCacheEntry<T extends CacheItem> extends AbstractBackingCacheEntry<T> 
+   implements BackingCacheEntry<T>, Serializable
+{   
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 1325918596862109742L;
+   
+   private T wrapped;
+   
+   /**
+    * Create a new SimpleBackingCacheEntry.
+    * 
+    * @param wrapped the item to wrap
+    */
+   public NonPassivatingBackingCacheEntry(T wrapped)
+   {
+      this.wrapped = wrapped;
+   }
+   
+   // -------------------------------------------------------- BackingCacheEntry
+
+   public T getUnderlyingItem()
+   {
+      return wrapped;
+   }
+   
+   public boolean isModified()
+   {      
+      return wrapped.isModified();
+   }
+
+   public Object getId()
+   {
+      return wrapped.getId();
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/NonPassivatingBackingCacheImpl.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/NonPassivatingBackingCacheImpl.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/NonPassivatingBackingCacheImpl.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,215 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007, 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.ejb3.cache.impl.backing;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.ejb.NoSuchEJBException;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.StatefulObjectFactory;
+import org.jboss.ejb3.cache.spi.BackingCache;
+import org.jboss.ejb3.cache.spi.PassivationExpirationProcessor;
+import org.jboss.ejb3.cache.spi.impl.PassivationExpirationRunner;
+import org.jboss.logging.Logger;
+
+/**
+ * Simple {@link BackingCache} that doesn't handle passivation (although
+ * it does handle expiration).  Pure in-VM memory cache. Not group-aware,
+ * as there is no point in managing groups if there is no serialization.
+ *
+ * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
+ * @author Brian Stansberry
+ * 
+ * @version $Revision: $
+ */
+public class NonPassivatingBackingCacheImpl<C extends CacheItem> 
+   implements BackingCache<C, NonPassivatingBackingCacheEntry<C>>, PassivationExpirationProcessor
+{
+   private static final Logger log = Logger.getLogger(NonPassivatingBackingCacheImpl.class);
+   
+   private StatefulObjectFactory<C> factory;
+   private Map<Object, NonPassivatingBackingCacheEntry<C>> cache;
+   private String name;
+   private long interval;
+   private int expirationTimeSeconds;   
+   private PassivationExpirationRunner sessionTimeoutRunner;
+   private boolean stopped = true;
+   
+   public NonPassivatingBackingCacheImpl(StatefulObjectFactory<C> factory)
+   {
+      assert factory != null;
+      
+      this.factory = factory;
+      this.cache = new ConcurrentHashMap<Object, NonPassivatingBackingCacheEntry<C>>();
+   }
+   
+   public NonPassivatingBackingCacheEntry<C> create(Class<?>[] initTypes, Object[] initValues)
+   {
+      C obj = factory.create(initTypes, initValues);
+      NonPassivatingBackingCacheEntry<C> entry = new NonPassivatingBackingCacheEntry<C>(obj);
+      cache.put(obj.getId(), entry);      
+      return entry;
+   }
+
+   public NonPassivatingBackingCacheEntry<C> get(Object key) throws NoSuchEJBException
+   {
+      NonPassivatingBackingCacheEntry<C> entry = cache.get(key);
+      if(entry == null)
+         throw new NoSuchEJBException(String.valueOf(key));
+      if(entry.isInUse())
+         throw new IllegalStateException("entry " + entry + " is already in use");
+      entry.setInUse(true);
+      return entry;
+   }
+
+   public NonPassivatingBackingCacheEntry<C> peek(Object key) throws NoSuchEJBException
+   {
+      NonPassivatingBackingCacheEntry<C> entry = cache.get(key);
+      if(entry == null)
+         throw new NoSuchEJBException(String.valueOf(key));
+      return entry;
+   }
+   
+   public NonPassivatingBackingCacheEntry<C> release(Object key)
+   {
+      NonPassivatingBackingCacheEntry<C> entry = cache.get(key);
+      if(entry == null)
+         throw new NoSuchEJBException(String.valueOf(key));
+      if(!entry.isInUse())
+         throw new IllegalStateException("entry " + key + " is not in use");
+      entry.setInUse(false);
+      return entry;
+   }
+   
+   public void remove(Object key)
+   {
+      NonPassivatingBackingCacheEntry<C> entry = cache.remove(key);
+      if(entry != null && entry.isInUse())
+         entry.setInUse(false);  
+      if(entry != null)
+         factory.destroy(entry.getUnderlyingItem());
+   } 
+   
+   public boolean isClustered()
+   {
+      return false;
+   }
+
+   public void start()
+   {
+      if (interval > 0)
+      {
+         if (sessionTimeoutRunner == null)
+         {
+            assert name != null : "name has not been set";
+            String timerName = "PassivationExpirationTimer-" + name;
+            sessionTimeoutRunner = new PassivationExpirationRunner(this, timerName, interval);
+         }
+         sessionTimeoutRunner.start();
+      }     
+      
+      stopped = false;
+      
+      log.debug("Started " + name);
+   }
+
+   public void stop()
+   {
+      if (sessionTimeoutRunner != null)
+      {
+         sessionTimeoutRunner.stop();
+      }      
+      
+      stopped = true;
+      
+      log.debug("Stopped " + name);
+   }
+
+   public long getInterval()
+   {
+      return interval;
+   }
+
+   public void setInterval(long interval)
+   {
+      this.interval = interval;
+   }
+
+   public String getName()
+   {
+      return name;
+   }
+
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+
+   public int getExpirationTimeSeconds()
+   {
+      return expirationTimeSeconds;
+   }
+
+   public void setExpirationTimeSeconds(int expirationTimeSeconds)
+   {
+      this.expirationTimeSeconds = expirationTimeSeconds;
+   }
+
+   public boolean isPassivationExpirationSelfManaged()
+   {
+      return interval > 0;
+   }
+
+   public void processPassivationExpiration()
+   {
+      if (!stopped && expirationTimeSeconds > 0)
+      {
+         // FIXME -- this is totally brute force
+         
+         long now = System.currentTimeMillis();
+         long minRemovalUse = now - (expirationTimeSeconds * 1000); 
+         Set<NonPassivatingBackingCacheEntry<C>> entries = new HashSet<NonPassivatingBackingCacheEntry<C>>(cache.values());
+         
+         for (NonPassivatingBackingCacheEntry<C> entry : entries)
+         {
+            if (!entry.isInUse() && minRemovalUse >= entry.getLastUsed())
+            {
+               try
+               {
+                  remove(entry.getId());               
+               }
+               catch (IllegalStateException ise)
+               {
+                  // Not so great; we're assuming it's 'cause item's in use
+                  log.trace("skipping in-use entry " + entry.getId(), ise);
+               }
+            }
+         }    
+      }      
+   }
+   
+   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/PassivatingBackingCacheImpl.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/PassivatingBackingCacheImpl.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/PassivatingBackingCacheImpl.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,183 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.cache.impl.backing;
+
+import javax.ejb.NoSuchEJBException;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.PassivationManager;
+import org.jboss.ejb3.cache.StatefulObjectFactory;
+import org.jboss.ejb3.cache.spi.BackingCacheEntry;
+import org.jboss.ejb3.cache.spi.PassivatingBackingCache;
+import org.jboss.ejb3.cache.spi.PassivatingIntegratedObjectStore;
+import org.jboss.logging.Logger;
+
+/**
+ * Non group-aware {@link PassivatingBackingCache} that uses a 
+ * {@link PassivatingIntegratedObjectStore} to manage data.
+ *
+ * @author Brian Stansberry
+ * @version $Revision: 65339 $
+ */
+public class PassivatingBackingCacheImpl<C extends CacheItem, T extends BackingCacheEntry<C>>
+   implements PassivatingBackingCache<C, T>
+{
+   private static final Logger log = Logger.getLogger(PassivatingBackingCacheImpl.class);
+   
+   private StatefulObjectFactory<T> factory;
+   private PassivationManager<T> passivationManager;
+   private PassivatingIntegratedObjectStore<C, T> store;
+   
+   public PassivatingBackingCacheImpl(StatefulObjectFactory<T> factory, 
+                                     PassivationManager<T> passivationManager, 
+                                     PassivatingIntegratedObjectStore<C, T> store)
+   {
+      assert factory != null : "factory is null";
+      assert passivationManager != null : "passivationManager is null";
+      assert store != null : "store is null";
+      
+      this.factory = factory;
+      this.passivationManager = passivationManager;
+      this.store = store;
+      this.store.setPassivatingCache(this);
+   }
+   
+   public boolean isClustered()
+   {
+      return store.isClustered();
+   }
+   
+   public T create(Class<?>[] initTypes, Object[] initValues)
+   {
+      T obj = factory.create(initTypes, initValues);
+//      obj.setInUse(true);
+      synchronized (store)
+      {
+         store.insert(obj);
+      }
+      return obj;
+   }
+
+   public T get(Object key) throws NoSuchEJBException
+   {
+      synchronized (store)
+      {
+         T entry = store.get(key);
+         if(entry == null)
+            throw new NoSuchEJBException(String.valueOf(key));
+         
+         if(entry.isInUse())
+         {
+            throw new IllegalStateException("entry " + entry + " is in use");
+         }
+         
+         if (isClustered())
+         {
+            passivationManager.postReplicate(entry);
+         }
+         
+         passivationManager.postActivate(entry);
+         
+         entry.setInUse(true);
+         return entry;
+      }
+   }
+
+   public void passivate(Object key)
+   {
+      log.trace("passivate " + key);
+      synchronized (store)
+      {
+         T entry = store.get(key);
+         
+         if(entry == null)
+            throw new IllegalArgumentException("entry " + key + " not found in cache " + this);
+         
+         if(entry.isInUse())
+         {
+            throw new IllegalStateException("entry " + entry + " is in use");
+         }
+
+         passivationManager.prePassivate(entry);
+         
+         store.passivate(entry);
+      }
+   }
+   
+   public T peek(Object key) throws NoSuchEJBException
+   {
+      synchronized (store)
+      {
+         T entry = store.get(key);
+         if(entry == null)
+            throw new NoSuchEJBException(String.valueOf(key));         
+         return entry;
+      }
+   }
+
+   public T release(Object key)
+   {      
+      synchronized (store)
+      {
+         T entry = store.get(key);
+         if(entry == null)
+            throw new IllegalStateException("object " + key + " not from this cache");
+         if(!entry.isInUse())
+            throw new IllegalStateException("entry " + entry + " is not in use");
+         entry.setInUse(false);
+         
+         if (entry.isModified())
+         {
+            if (isClustered())
+            {
+               passivationManager.preReplicate(entry);
+            }
+            store.update(entry);
+         }
+         
+         return entry;
+      }
+   }
+   
+   public void remove(Object key)
+   {
+      T entry;
+      synchronized (store)
+      {
+         entry = store.remove(key);
+         if(entry != null && entry.isInUse())
+            entry.setInUse(false);
+      }
+      if(entry != null)
+         factory.destroy(entry);
+   }
+   
+   public void start()
+   {
+      store.start();
+   }
+
+   public void stop()
+   {
+      store.stop();
+   }
+}

Copied: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SerializationGroupContainer.java (from rev 70283, projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupContainer.java)
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SerializationGroupContainer.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SerializationGroupContainer.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,112 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.cache.impl.backing;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.PassivationManager;
+import org.jboss.ejb3.cache.StatefulObjectFactory;
+import org.jboss.ejb3.cache.spi.PassivatingBackingCache;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupImpl;
+import org.jboss.logging.Logger;
+
+/**
+ * Comment
+ *  
+ *  FIXME determine whether SerializationGroup clustering support should
+ *  be controlled by a property of this container or via a param passed
+ *  to create(). 
+ *
+ * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
+ * @author Brian Stansberry
+ * @version $Revision: $
+ */
+public class SerializationGroupContainer<T extends CacheItem> 
+   implements StatefulObjectFactory<SerializationGroupImpl<T>>, PassivationManager<SerializationGroupImpl<T>>
+{
+   private static final Logger log = Logger.getLogger(SerializationGroupContainer.class);
+   
+   private PassivatingBackingCache<T, SerializationGroupImpl<T>> groupCache;
+   
+   private boolean clustered;
+   
+   public boolean isClustered()
+   {
+      return clustered;
+   }
+   
+   public void setClustered(boolean clustered)
+   {
+      this.clustered = clustered;
+   }
+
+   public SerializationGroupImpl<T> create(Class<?>[] initTypes, Object[] initValues)
+   {
+      SerializationGroupImpl<T> group = new SerializationGroupImpl<T>();
+      group.setClustered(clustered);
+      group.setGroupCache(groupCache);
+      return group;
+   }
+
+   public void destroy(SerializationGroupImpl<T> group)
+   {
+      // TODO: nothing?
+   }
+
+   public void postActivate(SerializationGroupImpl<T> group)
+   {
+      log.trace("post activate " + group);
+      // Restore ref to the groupCache in case it was lost during serialization
+      group.setGroupCache(groupCache);
+      group.postActivate();
+   }
+
+   public void prePassivate(SerializationGroupImpl<T> group)
+   {
+      log.trace("pre passivate " + group);
+      group.prePassivate();
+   }
+
+   public void postReplicate(SerializationGroupImpl<T> group)
+   {
+      log.trace("post replicate " + group);
+      // Restore ref to the groupCache in case it was lost during serialization
+      group.setGroupCache(groupCache);
+      group.postReplicate();
+   }
+
+   public void preReplicate(SerializationGroupImpl<T> group)
+   {
+      log.trace("pre replicate " + group);
+      group.preReplicate();
+   }
+
+   public PassivatingBackingCache<T, SerializationGroupImpl<T>> getGroupCache()
+   {
+      return groupCache;
+   }
+
+   public void setGroupCache(PassivatingBackingCache<T, SerializationGroupImpl<T>> groupCache)
+   {
+      this.groupCache = groupCache;
+   }
+   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SerializationGroupMemberContainer.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SerializationGroupMemberContainer.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SerializationGroupMemberContainer.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,323 @@
+/*
+ * 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.ejb3.cache.impl.backing;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.PassivationManager;
+import org.jboss.ejb3.cache.StatefulObjectFactory;
+import org.jboss.ejb3.cache.spi.PassivatingBackingCache;
+import org.jboss.ejb3.cache.spi.PassivatingIntegratedObjectStore;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupImpl;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupMember;
+import org.jboss.logging.Logger;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class SerializationGroupMemberContainer<C extends CacheItem>
+   implements StatefulObjectFactory<SerializationGroupMember<C>>, 
+              PassivationManager<SerializationGroupMember<C>>, 
+              PassivatingIntegratedObjectStore<C, SerializationGroupMember<C>>
+{
+   private static final Logger log = Logger.getLogger(SerializationGroupMemberContainer.class);
+   
+   private StatefulObjectFactory<C> factory;
+   private PassivationManager<C> passivationManager;
+   private PassivatingIntegratedObjectStore<C, SerializationGroupMember<C>> store;
+   private PassivatingBackingCache<C, SerializationGroupMember<C>> delegate;
+   
+   /**
+    * Cache that's managing the PassivationGroup
+    */
+   private PassivatingBackingCache<C, SerializationGroupImpl<C>> groupCache;
+   
+   
+   public SerializationGroupMemberContainer(StatefulObjectFactory<C> factory, 
+                                            PassivationManager<C> passivationManager, 
+                                            PassivatingIntegratedObjectStore<C, SerializationGroupMember<C>> store,
+                                            PassivatingBackingCache<C, SerializationGroupImpl<C>> groupCache)
+   {
+      assert factory != null : "factory is null";
+      assert passivationManager != null : "passivationManager is null";
+      assert store != null : "store is null";
+      assert groupCache != null : "groupCache is null";
+      
+      this.factory = factory;
+      this.passivationManager = passivationManager;
+      this.store = store;
+      this.groupCache = groupCache;
+   }
+   
+   public SerializationGroupMember<C> create(Class<?>[] initTypes, Object[] initValues)
+   {
+      SerializationGroupMember<C> member = 
+         new SerializationGroupMember<C>(factory.create(initTypes, initValues), 
+                                         delegate);
+      return member;
+   }
+
+   public void destroy(SerializationGroupMember<C> entry)
+   {
+      factory.destroy(entry.getUnderlyingItem());
+      SerializationGroupImpl<C> group = entry.getGroup();
+      if (group != null) 
+      {
+         group.removeMember(entry.getId());
+         if (group.size() == 0)
+         {
+            groupCache.remove(group.getId());
+         }
+      }
+   }
+   
+   public void postActivate(SerializationGroupMember<C> entry)
+   {
+      log.trace("post activate " + entry);
+      
+      // Restore the entry's ref to the group and object
+      SerializationGroupImpl<C> group = entry.getGroup();
+      if(group == null && entry.getGroupId() != null)
+      {
+         // TODO: peek or get?
+         // BES 2007/10/06 I think peek is better; no
+         // sense marking the group as in-use and then having
+         // to release it or something
+         group = groupCache.peek(entry.getGroupId());
+         entry.setGroup(group);
+      }
+      
+      if(group != null)
+      {
+         entry.setUnderlyingItem(group.getMemberObject(entry.getId()));
+         
+         // Notify the group that this entry is active
+         group.addActive(entry);
+      }
+      
+      // Invoke callbacks on the underlying object
+      if (entry.isPrePassivated())
+      {
+         passivationManager.postActivate(entry.getUnderlyingItem());
+         entry.setPrePassivated(false);
+      }
+   }
+   
+   public void prePassivate(SerializationGroupMember<C> entry)
+   {
+      log.trace("pre-passivate " + entry);
+      
+      // entry.obj may or may not get serialized (depends on if group
+      // is in use) but it's ok to invoke callbacks now. If a caller
+      // requests this entry again and the obj hadn't been serialized with
+      // the group, we'll just call postActivate on it then, which is OK.
+      if (!entry.isPrePassivated())
+      {
+         passivationManager.prePassivate(entry.getUnderlyingItem());
+         entry.setPrePassivated(true);
+      }
+      
+      // If this call is coming via PassivatingBackingCache.passivate(), 
+      // entry.group will *not* be null.  In that case we are the controller 
+      // for the group passivation. If the call is coming via entry.prePassivate(), 
+      // entry.group *will* be null. In that case we are not the controller 
+      // of the passivation and can just return.
+      SerializationGroupImpl<C> group = entry.getGroup();
+      if(group != null)
+      {
+         synchronized (group)
+         {
+            if (!group.isInvalid())
+            {
+               // Remove ourself from group's active list so we don't get
+               // called again via entry.prePassivate()            
+               group.removeActive(entry.getId());
+               
+               // Only tell the group to passivate if no members are in use
+               if (group.getInUseCount() == 0)
+               {
+                  // Go ahead and do the real passivation.
+                  groupCache.passivate(group.getId());
+                  group.setInvalid(true);
+               }         
+               // else {
+               // this turns into a pretty meaningless exercise of just
+               // passivating an empty entry. TODO consider throwing 
+               // ItemInUseException here, thus aborting everything.  Need to
+               // be sure that doesn't lead to problems as the exception propagates
+               // }
+               
+               // This call didn't come through entry.prePassivate() (which nulls
+               // group and obj) so we have to do it ourselves. Otherwise
+               // when this call returns, delegate will serialize the entry
+               // with a ref to group and obj.            
+               entry.setGroup(null);
+               entry.setUnderlyingItem(null);
+            }
+         }
+      }
+   }
+   
+   public void preReplicate(SerializationGroupMember<C> entry)
+   {         
+      // This method follows the same conceptual logic as prePassivate.
+      // See the detailed comments in that method.
+      
+      log.trace("pre-replicate " + entry);
+      
+      if (!entry.isPreReplicated())
+      {
+         passivationManager.preReplicate(entry.getUnderlyingItem());      
+         entry.setPreReplicated(true);
+      }
+      
+      SerializationGroupImpl<C> group = entry.getGroup();
+      if(group != null)
+      {
+         // Remove ourself from group's active list so we don't get
+         // called again via entry.prePassivate()            
+         group.removeActive(entry.getId());
+         
+         try
+         {
+            if (group.getInUseCount() == 0)
+            {
+//               group.preReplicate();
+               groupCache.release(group);
+            }
+         }
+         finally
+         {
+            // Here we differ from prePassivate!!
+            // Restore the entry as "active" so it can get
+            // passivation callbacks
+            group.addActive(entry);
+         }
+         
+//         entry.setGroup(null);
+//         entry.setUnderlyingItem(null);
+      }
+   }
+   
+   public void postReplicate(SerializationGroupMember<C> entry)
+   {
+      log.trace("postreplicate " + entry);
+      
+      // Restore the entry's ref to the group and object
+      SerializationGroupImpl<C> group = entry.getGroup();
+      if(group == null && entry.getGroupId() != null)
+      {
+         // TODO: peek or get?
+         // BES 2007/10/06 peek is better; you'll get multiple calls to
+         // this as different members are accessed, and the cache
+         // will throw an ISE if we use get() since we're already in use
+         group = groupCache.peek(entry.getGroupId());
+         entry.setGroup(group);
+      }
+      
+      if(group != null)
+      {
+         entry.setUnderlyingItem(group.getMemberObject(entry.getId()));
+         
+         // Notify the group that this entry is active
+         group.addActive(entry);
+      }
+      
+      // Invoke callbacks on the underlying object
+      if (entry.isPreReplicated())
+      {
+         passivationManager.postReplicate(entry.getUnderlyingItem());      
+         entry.setPreReplicated(false);
+      }
+   }
+
+   public void update(SerializationGroupMember<C> entry)
+   {
+      store.update(entry);
+   }
+
+   public boolean isClustered()
+   {
+      return groupCache.isClustered();
+   }
+   
+   public SerializationGroupMember<C> get(Object key)
+   {
+      SerializationGroupMember<C> entry = store.get(key);
+      // In case it was deserialized, make sure it has a ref to us
+      if (entry != null)
+         entry.setPassivatingCache(delegate);
+      return entry;
+   }
+
+   public void passivate(SerializationGroupMember<C> entry)
+   {
+      store.passivate(entry);         
+   }
+
+   public void insert(SerializationGroupMember<C> entry)
+   {
+      store.insert(entry);         
+   }
+
+   public SerializationGroupMember<C> remove(Object key)
+   {
+      return store.remove(key);
+   }
+
+   public void start()
+   {         
+      store.start();
+   }
+
+   public void stop()
+   {
+      store.stop();
+   }
+
+   public int getInterval()
+   {
+      return store.getInterval();
+   }
+
+   public void setInterval(int seconds)
+   {
+      store.setInterval(seconds);    
+   }
+
+   public void setPassivatingCache(PassivatingBackingCache<C, SerializationGroupMember<C>> cache)
+   {
+      this.delegate= cache;
+      this.store.setPassivatingCache(delegate);
+   }
+
+   public boolean isPassivationExpirationSelfManaged()
+   {
+      return store.isPassivationExpirationSelfManaged();
+   }
+
+   public void processPassivationExpiration()
+   {         
+      store.processPassivationExpiration();
+   }      
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SimplePassivatingIntegratedObjectStore.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SimplePassivatingIntegratedObjectStore.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/backing/SimplePassivatingIntegratedObjectStore.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,354 @@
+/*
+ * 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.ejb3.cache.impl.backing;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.jboss.ejb3.annotation.CacheConfig;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.spi.BackingCacheEntry;
+import org.jboss.ejb3.cache.spi.ObjectStore;
+import org.jboss.ejb3.cache.spi.PassivatingBackingCache;
+import org.jboss.ejb3.cache.spi.PassivatingIntegratedObjectStore;
+import org.jboss.ejb3.cache.spi.impl.CacheableTimestamp;
+import org.jboss.ejb3.cache.spi.impl.PassivationExpirationRunner;
+import org.jboss.logging.Logger;
+
+/**
+ * A {@link PassivatingIntegratedObjectStore} that stores in a simple
+ * <code>Map</code> and delegates to a provided {@link ObjectStore} for 
+ * persistence.
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class SimplePassivatingIntegratedObjectStore<C extends CacheItem, T extends BackingCacheEntry<C>>
+      implements PassivatingIntegratedObjectStore<C, T>
+{
+   private static final Logger log = Logger.getLogger(SimplePassivatingIntegratedObjectStore.class);
+   
+   private final ObjectStore<T> store;
+   private Map<Object, T> cache;
+   private Map<Object, Long> passivatedEntries;
+   
+   /**
+    * Support callbacks when our SessionTimeoutThread decides to
+    * evict an entry.
+    */
+   private PassivatingBackingCache<C, T> owningCache;   
+   private int interval;
+   private int maxSize;
+   private long idleTimeSeconds;
+   private long expirationTimeSeconds;   
+   private PassivationExpirationRunner sessionTimeoutRunner;
+   private String name;
+   private boolean stopped = true;
+   
+   /**
+    * Create a new SimpleIntegratedObjectStore.
+    */
+   public SimplePassivatingIntegratedObjectStore(ObjectStore<T> store, 
+                                                 CacheConfig config,
+                                                 String name)
+   {
+      assert store != null : "store is null";
+      assert config != null : "config is null";
+      assert name != null : "name is null";
+      
+      this.store = store;
+      this.cache = new HashMap<Object, T>();
+      this.passivatedEntries = new HashMap<Object, Long>();
+      this.idleTimeSeconds = config.idleTimeoutSeconds();
+      this.expirationTimeSeconds = config.removalTimeoutSeconds();
+      this.maxSize = config.maxSize();
+      this.name = name;
+   }
+   
+   public boolean isClustered()
+   {
+      return false;
+   }
+
+   public T get(Object key)
+   {
+      synchronized (cache)
+      {
+         T entry = cache.get(key);
+         if(entry == null)
+         {
+            entry = store.load(key);
+            if(entry != null)
+            {
+               cache.put(key, entry);
+               passivatedEntries.remove(key);
+            }
+         }
+         return entry;
+      }
+   }
+
+   public void insert(T entry)
+   {
+      Object key = entry.getId();
+      synchronized (cache)
+      {
+         if (cache.containsKey(key) || passivatedEntries.containsKey(key))
+         {
+            throw new IllegalStateException(key + " is already in store");
+         }
+         cache.put(key, entry);
+      }
+   }
+   
+   public void update(T entry)
+   {
+      Object key = entry.getId();
+      synchronized (cache)
+      {
+         if (!cache.containsKey(key) && !passivatedEntries.containsKey(key))
+         {
+            throw new IllegalStateException(key + " is not managed by this store");
+         }
+         
+         // Otherwise we do nothing; we already have a ref to the entry
+      }
+   }
+
+   public void passivate(T entry)
+   {
+      synchronized (cache)
+      {
+         Object key = entry.getId();
+         store.store(entry);  
+         passivatedEntries.put(key, new Long(entry.getLastUsed()));
+         cache.remove(key);
+      }
+   }
+
+   public T remove(Object id)
+   {
+      synchronized (cache)
+      {
+         T entry = get(id);
+         if (entry != null)
+         {
+            cache.remove(id);
+         }
+         return entry;
+      }
+   } 
+
+   public void start()
+   {
+      store.start();
+      
+      if (interval > 0)
+      {
+         if (sessionTimeoutRunner == null)
+         {
+            assert name != null : "name has not been set";
+            assert owningCache != null;
+            String timerName = "PassivationExpirationTimer-" + name;
+            sessionTimeoutRunner = new PassivationExpirationRunner(this, timerName, interval);
+         }
+         sessionTimeoutRunner.start();
+      }     
+      
+      stopped = false;
+      
+      log.debug("Started " + name);
+   }
+
+   public void stop()
+   {      
+      store.stop();
+      
+      if (sessionTimeoutRunner != null)
+      {
+         sessionTimeoutRunner.stop();
+      }      
+      
+      stopped = true;
+      
+      log.debug("Stopped " + name);
+   }
+
+   // ---------------------------------------  PassivatingIntegratedObjectStore
+
+
+   public void setPassivatingCache(PassivatingBackingCache<C, T> cache)
+   {
+      this.owningCache = cache;      
+   }
+   
+   public int getInterval()
+   {
+      return interval;
+   }
+
+   public void setInterval(int seconds)
+   {
+      this.interval = seconds;      
+   }
+   
+   public void processPassivationExpiration()
+   {
+      if (!stopped)
+      {
+         try
+         {
+            runPassivation();               
+         }
+         catch (Exception e)
+         {
+            log.error("Caught exception processing passivations", e);
+         }
+      }
+      if (!stopped)
+      {
+         try
+         {
+            runExpiration();               
+         }
+         catch (Exception e)
+         {
+            log.error("Caught exception processing expirations", e);
+         }               
+      }
+   }
+   
+   public boolean isPassivationExpirationSelfManaged()
+   {
+      return interval > 0;
+   }
+   
+   private void runExpiration()
+   {
+      if (expirationTimeSeconds > 0)
+      {
+         long now = System.currentTimeMillis();
+         long minRemovalUse = now - (expirationTimeSeconds * 1000);                     
+         for (CacheableTimestamp ts : getPassivatedEntries())
+         {
+            try
+            {
+               if (minRemovalUse >= ts.getLastUsed())
+               {
+                  remove(ts.getId());
+               }
+            }
+            catch (IllegalStateException ise)
+            {
+               // Not so great; we're assuming it's 'cause item's in use
+               log.trace("skipping in-use entry " + ts.getId(), ise);
+            }
+         }    
+      }      
+   }
+
+   private void runPassivation()
+   {
+      if (idleTimeSeconds > 0)
+      {
+         long now = System.currentTimeMillis();
+         long minPassUse = now - (idleTimeSeconds * 1000);
+         
+         // Scan the in-memory entries for passivation or removal
+         SortedSet<CacheableTimestamp> timestamps = getInMemoryEntries();
+         int overCount = timestamps.size() - maxSize;
+         for (CacheableTimestamp ts : timestamps)
+         {
+            try
+            {
+               long lastUsed = ts.getLastUsed();
+               if (overCount > 0 || minPassUse >= lastUsed)
+               {
+                  synchronized (cache)               
+                  {
+                     T entry = cache.get(ts.getId());
+                     if (entry == null || entry.isInUse())
+                        continue;
+                  }
+                  owningCache.passivate(ts.getId());
+                  overCount--;
+               }
+            }
+            catch (IllegalStateException ise)
+            {
+               // Not so great; we're assuming it's 'cause item's in use
+               log.trace("skipping in-use entry " + ts.getId(), ise);
+            }
+         }
+      }
+      
+   }   
+   
+   public int getMaxSize()
+   {
+      return maxSize;
+   }
+   
+   public long getIdleTimeSeconds()
+   {
+      return idleTimeSeconds;
+   }
+
+   public void setIdleTimeSeconds(long idleTimeSeconds)
+   {
+      this.idleTimeSeconds = idleTimeSeconds;
+   }
+
+   public long getExpirationTimeSeconds()
+   {
+      return expirationTimeSeconds;
+   }
+   
+   public void setExpirationTimeSeconds(long timeout)
+   {
+      this.expirationTimeSeconds = timeout;
+   } 
+
+   private SortedSet<CacheableTimestamp> getInMemoryEntries()
+   {      
+      SortedSet<CacheableTimestamp> set = new TreeSet<CacheableTimestamp>();
+      for (Map.Entry<Object, T> entry : cache.entrySet())
+      {
+         set.add(new CacheableTimestamp(entry.getKey(), entry.getValue().getLastUsed()));
+      }
+      return set;
+   }
+
+   private SortedSet<CacheableTimestamp> getPassivatedEntries()
+   {
+      SortedSet<CacheableTimestamp> set = new TreeSet<CacheableTimestamp>();
+      for (Map.Entry<Object, Long> entry : passivatedEntries.entrySet())
+      {
+         set.add(new CacheableTimestamp(entry.getKey(), entry.getValue().longValue()));
+      }
+      return set;
+   }
+
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/GroupAwareCacheFactory.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/GroupAwareCacheFactory.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/GroupAwareCacheFactory.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,138 @@
+/*
+ * 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.ejb3.cache.impl.factory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.ejb3.annotation.CacheConfig;
+import org.jboss.ejb3.cache.Cache;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.PassivationManager;
+import org.jboss.ejb3.cache.StatefulCacheFactory;
+import org.jboss.ejb3.cache.StatefulObjectFactory;
+import org.jboss.ejb3.cache.impl.GroupAwareTransactionalCache;
+import org.jboss.ejb3.cache.impl.backing.GroupAwareBackingCacheImpl;
+import org.jboss.ejb3.cache.impl.backing.PassivatingBackingCacheImpl;
+import org.jboss.ejb3.cache.impl.backing.SerializationGroupContainer;
+import org.jboss.ejb3.cache.impl.backing.SerializationGroupMemberContainer;
+import org.jboss.ejb3.cache.spi.GroupAwareBackingCache;
+import org.jboss.ejb3.cache.spi.IntegratedObjectStoreSource;
+import org.jboss.ejb3.cache.spi.PassivatingBackingCache;
+import org.jboss.ejb3.cache.spi.PassivatingIntegratedObjectStore;
+import org.jboss.ejb3.cache.spi.impl.AbstractStatefulCacheFactory;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupImpl;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupMember;
+
+/**
+ * {@link StatefulCacheFactory} implementation that can return a group-aware 
+ * cache.  How the cache functions depends on the behavior of the 
+ * {@link PassivatingIntegratedObjectStore} implementations returned by
+ * the injected {@link IntegratedObjectStoreSource}.
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class GroupAwareCacheFactory<T extends CacheItem> 
+   extends AbstractStatefulCacheFactory<T>
+{
+   private final Map<String, PassivatingBackingCache<T, SerializationGroupImpl<T>>> groupCaches;
+   private final IntegratedObjectStoreSource<T> storeSource;
+   
+   /**
+    * Creates a new GroupAwareCacheFactory that gets its object stores from
+    * the provided source.
+    */
+   public GroupAwareCacheFactory(IntegratedObjectStoreSource<T> storeSource)
+   {
+      assert storeSource != null : "storeSource is null";
+      
+      this.storeSource = storeSource;
+      this.groupCaches = new HashMap<String, PassivatingBackingCache<T, SerializationGroupImpl<T>>>();
+   }
+
+   // --------------------------------------------------- StatefulCacheFactory
+   
+   public Cache<T> createCache(String containerName, 
+                               StatefulObjectFactory<T> factory, 
+                               PassivationManager<T> passivationManager, CacheConfig cacheConfig)
+   {
+      String configName = getCacheConfigName(cacheConfig);
+      
+      PassivatingBackingCache<T, SerializationGroupImpl<T>> groupCache = groupCaches.get(configName);
+      if (groupCache == null)
+      {
+         groupCache = createGroupCache(containerName, configName, cacheConfig);
+         groupCaches.put(configName, groupCache);
+      }
+      
+      PassivatingIntegratedObjectStore<T, SerializationGroupMember<T>> store = 
+         storeSource.createIntegratedObjectStore(containerName, configName, cacheConfig, getTransactionManager());
+      
+      // Make sure passivation/expiration occurs periodically
+      if (store.getInterval() < 1)
+      {
+         if (getPassivationExpirationCoordinator() != null)
+         {
+            // Let our coordinator manage this
+            getPassivationExpirationCoordinator().addPassivationExpirationProcessor(store);
+         }
+         else 
+         {
+            // Tell the store to manage this itself, using our default interval
+            store.setInterval(getDefaultPassivationExpirationInterval());
+         }
+      }
+      // else the store is configured to manage processing itself
+      
+      SerializationGroupMemberContainer<T> memberContainer = 
+         new SerializationGroupMemberContainer<T>(factory, passivationManager, store, groupCache);
+      
+      GroupAwareBackingCache<T, SerializationGroupMember<T>> backingCache =
+         new GroupAwareBackingCacheImpl<T>(memberContainer, groupCache);
+      
+      return new GroupAwareTransactionalCache<T, SerializationGroupMember<T>>(backingCache, getTransactionManager());
+   }
+
+   private PassivatingBackingCache<T, SerializationGroupImpl<T>> createGroupCache(String name, String configName, CacheConfig cacheConfig)
+   {
+      SerializationGroupContainer<T> container = new SerializationGroupContainer<T>();
+      StatefulObjectFactory<SerializationGroupImpl<T>> factory = container;
+      PassivationManager<SerializationGroupImpl<T>> passivationManager = container;
+      PassivatingIntegratedObjectStore<T, SerializationGroupImpl<T>> store = 
+         storeSource.createGroupIntegratedObjectStore(name, configName, cacheConfig, getTransactionManager());
+    
+      // The group cache store should not passivate/expire -- that's a 
+      // function of the caches for the members
+      store.setInterval(0);
+      
+      PassivatingBackingCache<T, SerializationGroupImpl<T>> groupCache =
+         new PassivatingBackingCacheImpl<T, SerializationGroupImpl<T>>(factory, passivationManager, store);
+      
+      container.setGroupCache(groupCache);
+      
+      groupCache.start();
+      
+      return groupCache;
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/NonClusteredIntegratedObjectStoreSource.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/NonClusteredIntegratedObjectStoreSource.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/NonClusteredIntegratedObjectStoreSource.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,189 @@
+/*
+ * 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.ejb3.cache.impl.factory;
+
+import java.io.File;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.ejb3.annotation.CacheConfig;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.impl.backing.SimplePassivatingIntegratedObjectStore;
+import org.jboss.ejb3.cache.spi.IntegratedObjectStoreSource;
+import org.jboss.ejb3.cache.spi.PassivatingIntegratedObjectStore;
+import org.jboss.ejb3.cache.spi.impl.FileObjectStore;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupImpl;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupMember;
+
+/**
+ * {@link IntegratedObjectStoreSource} for a non-clustered cache. Uses
+ * a {@link FileObjectStore} store for persistence.
+ * 
+ * @author Brian Stansberry
+ */
+public class NonClusteredIntegratedObjectStoreSource<T extends CacheItem> 
+   implements IntegratedObjectStoreSource<T>
+{
+   /**
+    * The default session store directory name ("<tt>ejb3/sessions</tt>").
+    */
+   String DEFAULT_SESSION_DIRECTORY_NAME = "ejb3" + File.separatorChar + "sessions";
+   
+   /**
+    * The default session group store directory name ("<tt>ejb3/sfsbgroups</tt>").
+    */
+   String DEFAULT_GROUP_DIRECTORY_NAME = "ejb3" + File.separatorChar + "sfsbgroups";
+   
+   public static final int DEFAULT_SUBDIRECTORY_COUNT = 100;
+   
+   private String sessionDirectoryName = DEFAULT_SESSION_DIRECTORY_NAME;
+   private String groupDirectoryName = DEFAULT_GROUP_DIRECTORY_NAME;
+   private String baseDirectoryName;
+   private int subdirectoryCount = DEFAULT_SUBDIRECTORY_COUNT;
+   
+   public PassivatingIntegratedObjectStore<T, SerializationGroupImpl<T>> createGroupIntegratedObjectStore(String containerName, String cacheConfigName,
+         CacheConfig cacheConfig, TransactionManager transactionManager)
+   {
+      FileObjectStore<SerializationGroupImpl<T>> objectStore = new FileObjectStore<SerializationGroupImpl<T>>();
+      objectStore.setStorageDirectory(getFullGroupDirectoryName(containerName));
+      objectStore.setSubdirectoryCount(subdirectoryCount);
+      
+      String storeName = "StdGroupStore-"+cacheConfig.name();
+      SimplePassivatingIntegratedObjectStore<T, SerializationGroupImpl<T>> store = 
+         new SimplePassivatingIntegratedObjectStore<T, SerializationGroupImpl<T>>(objectStore, cacheConfig, storeName);
+      
+      return store;
+   }
+
+   public PassivatingIntegratedObjectStore<T, SerializationGroupMember<T>> createIntegratedObjectStore(String containerName, String cacheConfigName,
+         CacheConfig cacheConfig, TransactionManager transactionManager)
+   {
+      FileObjectStore<SerializationGroupMember<T>> objectStore = new FileObjectStore<SerializationGroupMember<T>>();
+      objectStore.setStorageDirectory(getFullSessionDirectoryName(containerName));
+      objectStore.setSubdirectoryCount(subdirectoryCount);
+      
+      SimplePassivatingIntegratedObjectStore<T, SerializationGroupMember<T>> store = 
+         new SimplePassivatingIntegratedObjectStore<T, SerializationGroupMember<T>>(objectStore, cacheConfig, containerName);
+      
+      return store;
+   }
+   
+   protected String getFullSessionDirectoryName(String containerName)
+   {
+      File base = new File(getBaseDirectoryName());
+      File child = new File(base, getSessionDirectoryName());
+      File full = new File(child, containerName);
+      return full.getAbsolutePath();
+   }
+   
+   protected String getFullGroupDirectoryName(String containerName)
+   {
+      File base = new File(getBaseDirectoryName());
+      File child = new File(base, getGroupDirectoryName());
+      File full = new File(child, containerName);
+      return full.getAbsolutePath();      
+   }
+
+   /**
+    * Gets the name of the base directory under which sessions and 
+    * groups should be stored. Default is the java.io.tmpdir.
+    */
+   public synchronized String getBaseDirectoryName()
+   {
+      if (baseDirectoryName == null)
+      {
+         setBaseDirectoryName(System.getProperty("java.io.tmpdir"));
+      }
+      return baseDirectoryName;
+   }
+
+   /**
+    * Sets the name of the base directory under which sessions and 
+    * groups should be stored.
+    */
+   public void setBaseDirectoryName(String baseDirectoryName)
+   {
+      this.baseDirectoryName = baseDirectoryName;
+   }
+
+   /**
+    * Gets the name of the subdirectory under the 
+    * {@link #getBaseDirectoryName() base directory} under which sessions 
+    * should be stored. Default is {@link #DEFAULT_SESSION_DIRECTORY_NAME}.
+    */
+   public String getSessionDirectoryName()
+   {
+      return sessionDirectoryName;
+   }
+
+   /**
+    * Sets the name of the subdirectory under the 
+    * {@link #getBaseDirectoryName() base directory} under which sessions 
+    * should be stored.
+    */
+   public void setSessionDirectoryName(String directoryName)
+   {
+      this.sessionDirectoryName = directoryName;
+   }
+
+   /**
+    * Gets the name of the subdirectory under the 
+    * {@link #getBaseDirectoryName() base directory} under which session groups 
+    * should be stored. Default is {@link #DEFAULT_GROUP_DIRECTORY_NAME}.
+    */
+   public String getGroupDirectoryName()
+   {
+      return groupDirectoryName;
+   }
+
+   /**
+    * Sets the name of the subdirectory under the 
+    * {@link #getBaseDirectoryName() base directory} under which session groups 
+    * should be stored.
+    */
+   public void setGroupDirectoryName(String groupDirectoryName)
+   {
+      this.groupDirectoryName = groupDirectoryName;
+   }
+
+   /**
+    * Gets the number of subdirectories under the session directory or the
+    * group directory into which the sessions/groups should be divided. Using
+    * subdirectories helps overcome filesystem limits on the number of items
+    * that can be stored. Default is {@link #DEFAULT_SUBDIRECTORY_COUNT}.
+    */
+   public int getSubdirectoryCount()
+   {
+      return subdirectoryCount;
+   }
+
+   /**
+    * Sets the number of subdirectories under the session directory or the
+    * group directory into which the sessions/groups should be divided.
+    */
+   public void setSubdirectoryCount(int subdirectoryCount)
+   {
+      this.subdirectoryCount = subdirectoryCount;
+   }
+   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/NonPassivatingCacheFactory.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/NonPassivatingCacheFactory.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/NonPassivatingCacheFactory.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,70 @@
+/*
+ * 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.ejb3.cache.impl.factory;
+
+import org.jboss.ejb3.annotation.CacheConfig;
+import org.jboss.ejb3.cache.Cache;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.PassivationManager;
+import org.jboss.ejb3.cache.StatefulCacheFactory;
+import org.jboss.ejb3.cache.StatefulObjectFactory;
+import org.jboss.ejb3.cache.impl.TransactionalCache;
+import org.jboss.ejb3.cache.impl.backing.NonPassivatingBackingCacheEntry;
+import org.jboss.ejb3.cache.impl.backing.NonPassivatingBackingCacheImpl;
+import org.jboss.ejb3.cache.spi.impl.AbstractStatefulCacheFactory;
+
+/**
+ * {@link StatefulCacheFactory} implementation that will return a 
+ * {@link Cache#isGroupAware() non-group-aware} cache that doesn't support
+ * passivation.
+ * 
+ * @author Brian Stansberry
+ */
+public class NonPassivatingCacheFactory<T extends CacheItem> 
+   extends AbstractStatefulCacheFactory<T>
+{
+
+   public Cache<T> createCache(String containerName, 
+                               StatefulObjectFactory<T> factory, 
+                               PassivationManager<T> passivationManager,
+                               CacheConfig config)
+   {
+      NonPassivatingBackingCacheImpl<T> backingCache = new NonPassivatingBackingCacheImpl<T>(factory);
+      backingCache.setName(containerName);
+      
+      // Make sure passivation/expiration occurs periodically
+      if (getPassivationExpirationCoordinator() != null)
+      {
+         // Let our coordinator manage this
+         getPassivationExpirationCoordinator().addPassivationExpirationProcessor(backingCache);
+      }
+      else 
+      {
+         // Tell the store to manage this itself, using our default interval
+         backingCache.setInterval(getDefaultPassivationExpirationInterval());
+      }
+      
+      return new TransactionalCache<T, NonPassivatingBackingCacheEntry<T>>(backingCache, getTransactionManager());
+   }
+
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/PassivationExpirationCoordinatorImpl.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/PassivationExpirationCoordinatorImpl.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/factory/PassivationExpirationCoordinatorImpl.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,220 @@
+/*
+ * 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.ejb3.cache.impl.factory;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Semaphore;
+
+import org.jboss.ejb3.cache.spi.PassivationExpirationCoordinator;
+import org.jboss.ejb3.cache.spi.PassivationExpirationProcessor;
+import org.jboss.ejb3.cache.spi.impl.AbstractTimerTask;
+import org.jboss.util.threadpool.BasicThreadPool;
+
+/**
+ * {@link PassivationExpirationCoordinator} implementation that runs as a  
+ * background TimerTask which when executed takes threads from a thread
+ * pool and uses them to process passivation and expiration.
+ * <p>
+ * If no thread pool is provided, the passivation/expiration will be handled
+ * by the timer thread itself.
+ * </p>
+ * 
+ * @author Brian Stansberry
+ */
+public class PassivationExpirationCoordinatorImpl
+   extends AbstractTimerTask
+   implements PassivationExpirationCoordinator
+{
+   public static final long DEFAULT_INTERVAL = 10000L;
+   public static final String TIMER_NAME = "EJB3SFSBPassivationExpirationCoordinator";
+   
+   private BasicThreadPool threadPool;
+   private int maxPoolThreads;
+   private Set<PassivationExpirationProcessor> processors = new HashSet<PassivationExpirationProcessor>();
+   private Semaphore threadLimit;
+   
+   public PassivationExpirationCoordinatorImpl()
+   {
+      super(TIMER_NAME, DEFAULT_INTERVAL);
+   }
+   
+   // -------------------------------------------------------------- Properties
+   
+   /**
+    * Gets the thread pool used to get threads for concurrently processing
+    * passivation/expiration on different caches.
+    * 
+    * @return the pool. May be <code>null</code>
+    */
+   public BasicThreadPool getThreadPool()
+   {
+      return threadPool;
+   }
+
+   /**
+    * Sets the thread pool to use to get threads for concurrently processing
+    * passivation/expiration on different caches.
+    * 
+    * @param threadPool the pool. May be <code>null</code>
+    */
+   public void setThreadPool(BasicThreadPool threadPool)
+   {
+      this.threadPool = threadPool;
+   }
+
+   /**
+    * Gets the maximum number of threads that can be concurrently taken from the
+    * {@link #getThreadPool() thread pool} in order to process
+    * passivation/expiration on different caches.
+    * 
+    * @return the maximum number of threads. A value less than 1 means
+    *         the thread pool will not be used.
+    */
+   public int getMaxPoolThreads()
+   {
+      return maxPoolThreads;
+   }
+
+   /**
+    * Sets the maximum number of threads to concurrently take from the
+    * {@link #getThreadPool() thread pool} in order to process
+    * passivation/expiration on different caches.
+    * 
+    * @param numThreads the maximum number of threads. A value less than
+    *                   1 disables use of the thread pool.
+    */
+   public void setMaxPoolThreads(int numThreads)
+   {
+      this.maxPoolThreads = numThreads;
+   }
+
+   // ---------------------------------------- PassivationExpirationCoordinator
+   
+   public void addPassivationExpirationProcessor(PassivationExpirationProcessor processor)
+   {
+      synchronized (processors)
+      {
+         processors.add(processor);
+      }
+   }
+
+   public void removePassivationExpirationProcessor(PassivationExpirationProcessor processor)
+   {
+      synchronized (processors)
+      {
+         processors.remove(processor);
+      }
+   }
+
+   // -------------------------------------------------------------- TimerTask
+   
+   @Override
+   public void run()
+   {
+      while (!isStopped())
+      {
+         Set<PassivationExpirationProcessor> toProcess = new HashSet<PassivationExpirationProcessor>();
+         synchronized (processors)
+         {
+            toProcess.addAll(processors);
+         }
+         
+         for (PassivationExpirationProcessor cache : toProcess)
+         {            
+            if (cache.isPassivationExpirationSelfManaged())
+               continue;
+            
+            PassivationExpirationTask task = new PassivationExpirationTask(cache, threadLimit);
+            if (threadLimit != null)
+            {
+               // Limit the number of concurrent threads
+               try
+               {
+                  threadLimit.acquire();
+               }
+               catch (InterruptedException ignore)
+               {
+               }
+               
+               if (isStopped())
+                  break;
+               
+               threadPool.run(task);
+            }
+            else
+            {
+               // We run it our self
+               task.run();
+            }
+            
+            
+            if (isStopped())
+               break;
+         }
+      }
+   }
+   
+   @Override
+   public void start()
+   {
+      if (isStopped())
+      {
+         if (threadPool != null && getMaxPoolThreads() > 0)
+         {
+            threadLimit = new Semaphore(getMaxPoolThreads());
+         }
+      }
+      super.start();      
+   }
+   
+   /**
+    * Task executed by the thread pool thread.
+    */
+   private class PassivationExpirationTask implements Runnable
+   {
+      private final PassivationExpirationProcessor cache;
+      private final Semaphore semaphore;
+      
+      PassivationExpirationTask(PassivationExpirationProcessor cache, Semaphore semaphore)
+      {
+         assert cache != null : "cache is null";
+         assert semaphore != null : "semaphore is null";
+         
+         this.cache = cache;
+         this.semaphore = semaphore;
+      }
+      
+      public void run()
+      {
+         try
+         {
+            cache.processPassivationExpiration();
+         }
+         finally
+         {
+            semaphore.release();            
+         }
+      }
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/BackingCache.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/BackingCache.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/BackingCache.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,115 @@
+/*
+ * 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.ejb3.cache.spi;
+
+import javax.ejb.NoSuchEJBException;
+
+import org.jboss.ejb3.cache.Cache;
+import org.jboss.ejb3.cache.CacheItem;
+
+/**
+ * An internal cache to which an external-facing {@link Cache} delegates, either
+ * directly or indirectly.
+ * <p>
+ * The key distinction between a BackingCache and the external-facing Cache is
+ * that a Cache directly handles external classes that implement the
+ * limited {@link CacheItem} interface. CacheItem is deliberately limited to
+ * avoid placing a implementation burden on external classes. A BackingCache 
+ * works with instances of the more expressive internal interface 
+ * {@link BackingCacheEntry}, and thus can directly implement more complex 
+ * functionality.
+ * </p>
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public interface BackingCache<C extends CacheItem, T extends BackingCacheEntry<C>> 
+{
+   /**
+    * Creates and caches a new instance of <code>T</code>. The new
+    * <code>T</code> *is* returned, but is not regarded as being "in use".
+    * Callers *must not* attempt to use the underlying <code>C</code> without
+    * first calling {@link #get(Object)}. 
+    * 
+    * @param initTypes   the types of any <code>initValues</code>. 
+    *                    May be <code>null</code>.
+    * @param initValues  any paramaters to pass to <code>T</code>'s constructor.
+    *                    May be null, in which case a default constructor will
+    *                    be used.
+    * @return the new <code>T</code> 
+    */
+   T create(Class<?> initTypes[], Object initValues[]);
+
+   /**
+    * Get the specified object from cache. This will mark
+    * the object as being in use.
+    * 
+    * @param key    the identifier of the object
+    * @return       the object
+    * @throws NoSuchEJBException    if the object does not exist
+    */
+   T get(Object key) throws NoSuchEJBException;
+   
+   /**
+    * Peek at an object which might be in use.
+    * 
+    * @param key    the identifier of the object
+    * @return       the object
+    * @throws NoSuchEJBException    if the object does not exist
+    */
+   T peek(Object key) throws NoSuchEJBException;
+   
+   /**
+    * Release the object from use.
+    * 
+    * @param key  the identifier of the object
+    * 
+    * @return the entry that was released
+    */
+   T release(Object key);
+
+   /**
+    * Remove the specified object from cache.
+    * 
+    * @param key    the identifier of the object
+    */
+   void remove(Object key);
+
+   /**
+    * Start the cache.
+    */
+   void start();
+
+   /**
+    * Stop the cache.
+    */
+   void stop();
+   
+   /**
+    * Gets whether this cache supports clustering functionality.
+    * 
+    * @return <code>true</code> if clustering is supported, <code>false</code>
+    *         otherwise
+    */
+   boolean isClustered();
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/BackingCacheEntry.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/BackingCacheEntry.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/BackingCacheEntry.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,63 @@
+/*
+ * 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.ejb3.cache.spi;
+
+import org.jboss.ejb3.cache.CacheItem;
+
+
+/**
+ * An object that can be managed by a {@link BackingCache}.
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public interface BackingCacheEntry<T extends CacheItem> 
+   extends CacheItem
+{  
+   /**
+    * Gets the underlying object that should be serialized as part of 
+    * serialization of the group.
+    * 
+    * @return
+    */
+   T getUnderlyingItem();
+   
+   /**
+    * Gets whether this object is in use by a caller.
+    */
+   boolean isInUse();
+   
+   /**
+    * Sets whether this object is in use by a caller.
+    * 
+    * @param inUse
+    */
+   void setInUse(boolean inUse);
+   
+   /**
+    * Gets the timestamp of the last time this object was in use.
+    * 
+    * @return
+    */
+   long getLastUsed();
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/GroupAwareBackingCache.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/GroupAwareBackingCache.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/GroupAwareBackingCache.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,67 @@
+/*
+ * 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.ejb3.cache.spi;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.SerializationGroup;
+
+/**
+ * A {@link BackingCache} that can manage the relationship of its 
+ * underlying entries to any {@link SerializationGroup}.
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public interface GroupAwareBackingCache<C extends CacheItem, T extends BackingCacheEntry<C>>
+   extends PassivatingBackingCache<C, T>
+{
+   /**
+    * Create a {@link SerializationGroup} to contain objects cached by
+    * this object.
+    * 
+    * @return a {@link SerializationGroup} 
+    */
+   SerializationGroup<C> createGroup();
+
+   /**
+    * Assign the given object to the given group.  The group will be
+    * of the {@link SerializationGroup} implementation type returned
+    * by {@link #createGroup()}.
+    * 
+    * @param obj
+    * @param group
+    * 
+    * @throws GroupIncompatibilityException if the group's cache is incompatible
+    *                                       with ourself.
+    */
+   void setGroup(C obj, SerializationGroup<C> group) throws GroupIncompatibilityException;
+
+   /**
+    * Gets the group the given object is a member of
+    * 
+    * @param obj the object
+    * @return the group, or <code>null</code> if the object is not a member
+    *         of a group
+    */
+   SerializationGroup<C> getGroup(C obj);
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/GroupIncompatibilityException.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/GroupIncompatibilityException.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/GroupIncompatibilityException.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,45 @@
+/*
+ * 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.ejb3.cache.spi;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class GroupIncompatibilityException extends Exception
+{
+
+    /** The serialVersionUID */
+   private static final long serialVersionUID = 8202720497027287887L;
+
+   /**
+    * Create a new IncompatibleGroupException.
+    * 
+    * @param message
+    */
+   public GroupIncompatibilityException(String message)
+   {
+      super(message);
+   }
+
+}

Copied: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/IntegratedObjectStore.java (from rev 70283, projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/IntegratedObjectStore.java)
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/IntegratedObjectStore.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/IntegratedObjectStore.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,112 @@
+/*
+ * 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.ejb3.cache.spi;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.Identifiable;
+
+/**
+ * An in-memory store for identifiable objects that integrates a persistent store. 
+ * Note that this class does NOT call any callbacks.
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public interface IntegratedObjectStore<T extends CacheItem>
+{
+   /**
+    * Put a new entry into the store. This operation should only be
+    * performed once per entry.
+    * 
+    * @param entry the object to store. Cannot be <code>null</code>.
+    * 
+    * @throws IllegalStateException if the store is already managing an entry
+    *                               with the same {@link Identifiable#getId() id}.
+    *                               It is not a requirement that the store throw
+    *                               this exception in this case, but it is
+    *                               permissible. This basically puts the onus on
+    *                               callers to ensure this operation is only
+    *                               performed once per entry.
+    */
+   void insert(T entry);
+   
+   /**
+    * Gets the entry with the given id from the store.
+    * 
+    * @param key {@link Identifiable#getId() id} of the entry.
+    *           Cannot be <code>null</code>.
+    * @return the object store under <code>id</code>. May return <code>null</code>.
+    */
+   T get(Object key);
+   
+   /**
+    * Update an already cached item.
+    * 
+    * @param  entry the entry to update
+    * 
+    * @throws IllegalStateException if the store isn't already managing an entry
+    *                               with the same {@link Identifiable#getId() id}.
+    *                               It is not a requirement that the store throw
+    *                               this exception in this case, but it is
+    *                               permissible. This basically puts the onus on
+    *                               callers to ensure {@link #insert(Cacheable)}
+    *                               is invoked before the first replication.
+    */
+   void update(T entry);
+   
+   /**
+    * Remove the object with the given key from the store.
+    * 
+    * @param key {@link Identifiable#getId() id} of the entry.
+    *           Cannot be <code>null</code>.
+    *           
+    * @return the object that was cached under <code>key</code>
+    */
+   T remove(Object key);
+   
+   /**
+    * Remove the entry with the given key from any in-memory store
+    * while retaining it in the persistent store.
+    * 
+    * @param entry the entry to passivate
+    */
+   void passivate(T entry);
+   
+   /**
+    * Gets whether this store supports clustering functionality.
+    * 
+    * @return <code>true</code> if clustering is supported, <code>false</code>
+    *         otherwise
+    */
+   boolean isClustered();
+   
+   /**
+    * Perform any initialization work.
+    */
+   void start();
+   
+   /**
+    * Perform any shutdown work.
+    */
+   void stop();
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/IntegratedObjectStoreSource.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/IntegratedObjectStoreSource.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/IntegratedObjectStoreSource.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,76 @@
+/*
+ * 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.ejb3.cache.spi;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.ejb3.annotation.CacheConfig;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.StatefulCacheFactory;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupImpl;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupMember;
+
+/**
+ * Provides {@link PassivatingIntegratedObjectStore} instances to a 
+ * {@link StatefulCacheFactory} that needs to create a 
+ * {@link GroupAwareBackingCache}.
+ * 
+ * @author Brian Stansberry
+ */
+public interface IntegratedObjectStoreSource<T extends CacheItem>
+{
+   /**
+    * Provide a {@link PassivatingIntegratedObjectStore} for storage
+    * of serialization groups.
+    * 
+    * @param containerName name of the container using this store's cache
+    * @param cacheConfigName potentially aliased name of the cache configuration. 
+    *                        Implementations should use this value in place
+    *                        of {@link CacheConfig#name()}
+    * @param config configuration details of the cache
+    * @param transactionManager TransactionManager the store should use if
+    *                           it needs to monitor transactions
+    * @return the store
+    */
+   PassivatingIntegratedObjectStore<T, SerializationGroupImpl<T>> 
+         createGroupIntegratedObjectStore(String containerName, 
+                                          String cacheConfigName, 
+                                          CacheConfig config, 
+                                          TransactionManager transactionManager);
+   
+   /**
+    * Provide a {@link PassivatingIntegratedObjectStore} for storage
+    * of serialization group members.
+    * 
+    * @param containerName name of the container using this store's cache
+    * @param cacheConfigName TODO
+    * @param transactionManager TransactionManager the store should use if
+    *                           it needs to monitor transactions
+    * @param config configuration details of the cache
+    * @return the store
+    */
+   PassivatingIntegratedObjectStore<T, SerializationGroupMember<T>> 
+         createIntegratedObjectStore(String containerName, 
+                                     String cacheConfigName, 
+                                     CacheConfig cacheConfig, TransactionManager transactionManager);
+}

Copied: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/ObjectStore.java (from rev 70283, projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/ObjectStore.java)
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/ObjectStore.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/ObjectStore.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007, 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.ejb3.cache.spi;
+
+import org.jboss.ejb3.cache.CacheItem;
+
+
+/**
+ * Stores an indentifiable object in a persistent store. Note that the object store
+ * does NOT call any callbacks.
+ * 
+ * It is assumed the key represents something meaning full to the object store.
+ *
+ * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
+ * @version $Revision: $
+ */
+public interface ObjectStore<T extends CacheItem>
+{
+   /**
+    * Load the object from storage.
+    * 
+    * @param key    the object identifier
+    * @return       the object or null if not found
+    */
+   T load(Object key);
+   
+   /**
+    * Store the object into storage.
+    * 
+    * @param obj    the object
+    */
+   void store(T obj);
+   
+   /**
+    * Perform any initialization work.
+    */
+   void start();
+   
+   /**
+    * Perform any shutdown work.
+    */
+   void stop();
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivatingBackingCache.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivatingBackingCache.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivatingBackingCache.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.cache.spi;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupImpl;
+
+
+/**
+ * A {@link BackingCache} which passivates unused objects.
+ * 
+ * A PassivatingCache is linked to an ObjectStore to store the
+ * passivated object and a PassivationManager to manage lifecycle
+ * callbacks on the object.
+ *
+ * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
+ * @version $Revision: 65977 $
+ */
+public interface PassivatingBackingCache<C extends CacheItem, T extends BackingCacheEntry<C>>
+   extends BackingCache<C, T>
+{
+   /**
+    * Force passivation of an object. The object must not be in use.
+    * 
+    * @param key    the identifier of the object
+    * 
+    * @throws IllegalStateException if the object, or another object in the 
+    *                            same {@link SerializationGroupImpl} as the object, 
+    *                            is in use. 
+    */
+   void passivate(Object key);
+}

Copied: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivatingIntegratedObjectStore.java (from rev 70283, projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/PassivatingIntegratedObjectStore.java)
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivatingIntegratedObjectStore.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivatingIntegratedObjectStore.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,79 @@
+/*
+ * 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.ejb3.cache.spi;
+
+import org.jboss.ejb3.cache.Cache;
+import org.jboss.ejb3.cache.CacheItem;
+
+/**
+ * An {@link IntegratedObjectStore} that is able to use its knowledge of
+ * when objects are accessed to coordinate the passivation and removal of 
+ * cached objects.
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public interface PassivatingIntegratedObjectStore<C extends CacheItem, T extends BackingCacheEntry<C>>
+   extends IntegratedObjectStore<T>, PassivationExpirationProcessor
+{
+   /**
+    * Gets how often, in seconds, this object should process 
+    * {@link #runPassivation() passivations} and
+    * {@link #runExpiration() expirations}.
+    * 
+    * @return  interval, in seconds, at which passivations and expirations
+    *          are processed. A value of less than 1 means this object will 
+    *          not itself initiate processing, depending instead on an external 
+    *          caller to do so.
+    */
+   int getInterval();
+   
+   /**
+    * Sets how often, in seconds, this object should process 
+    * {@link #runPassivation() passivations} and
+    * {@link #runExpiration() expirations}.
+    * 
+    * @param seconds  interval, in seconds, at which passivations and
+    *                 expirations should be processed. A value of less than 1 
+    *                 means this object will not itself initiate processing, 
+    *                 depending instead on an external caller to do so.
+    */
+   void setInterval(int seconds);
+   
+   /**
+    * Handback provided by the controlling {@link PassivatingBackingCache} to
+    * allow the actual {@link PassivatingBackingCache#passivate(Object) passivate}
+    * and {@link Cache#remove(Object) remove} calls.
+    * 
+    * @param cache
+    */
+   void setPassivatingCache(PassivatingBackingCache<C, T> cache);
+   
+   // TODO determine what the standard configurations are
+   
+//   int getPassivationTimeout();
+//   void setPassivationTimeout(int timeout);
+//   
+//   int getRemovalTimeout();   
+//   void setRemovalTimeout(int timeout);
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivationExpirationCoordinator.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivationExpirationCoordinator.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivationExpirationCoordinator.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,48 @@
+/*
+ * 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.ejb3.cache.spi;
+
+/**
+ * Object that coordinates the execution of the 
+ * {@link PassivationExpirationProcessor#processPassivationExpiration() passivation and expiration process}
+ * for a set of {@link PassivationExpirationProcessor} instances.
+ * 
+ * @author Brian Stansberry
+ *
+ */
+public interface PassivationExpirationCoordinator
+{
+   /**
+    * Add a processor to the set managed by this coordinator.
+    * 
+    * @param processor the processor. Cannot be <code>null</code>.
+    */
+   void addPassivationExpirationProcessor(PassivationExpirationProcessor processor);
+   
+   /**
+    * Remove a processor from the set managed by this coordinator.
+    * 
+    * @param processor the processor. Cannot be <code>null</code>.
+    */
+   void removePassivationExpirationProcessor(PassivationExpirationProcessor processor);
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivationExpirationProcessor.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivationExpirationProcessor.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/PassivationExpirationProcessor.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,51 @@
+/*
+ * 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.ejb3.cache.spi;
+
+/**
+ * An object that can process passivation and expiration of cache entries.
+ * 
+ * @author Brian Stansberry
+ */
+public interface PassivationExpirationProcessor
+{
+   /**
+    * Tells the processor to analyze its current content, passivating or expiring
+    * any items that meet its rules for passivation or expiration.  This method
+    * provides a hook for an external background cleanup thread to trigger
+    * passivation and expiration.  This method should not be invoked if 
+    * {@link #isPassivationExpirationSelfManaged() the cache is managing its
+    * own background process} for this.
+    */
+   void processPassivationExpiration();
+   
+   /**
+    * Gets whether this cache is running its own background process to trigger
+    * passivation and expiration.
+    * 
+    * @return <code>true</code> if the cache is managing its own background
+    *         process; <code>false</code> otherwise.
+    */
+   boolean isPassivationExpirationSelfManaged();
+
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractBackingCacheEntry.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractBackingCacheEntry.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractBackingCacheEntry.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -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.ejb3.cache.spi.impl;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.spi.BackingCacheEntry;
+
+/**
+ * Abstract superclass for {@link BackingCacheEntry} implementations.
+ * 
+ * @author Brian Stansberry
+ *
+ * @param <T>
+ */
+public abstract class AbstractBackingCacheEntry<T extends CacheItem>
+   implements BackingCacheEntry<T>
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 4562025672441864736L;
+   
+   private long lastUsed;
+   private transient boolean inUse;
+
+   public long getLastUsed()
+   {
+      return lastUsed;
+   }
+
+   public boolean isInUse()
+   {
+      return inUse;
+   }
+
+   public void setInUse(boolean inUse)
+   {
+      this.inUse = inUse;
+      setLastUsed(System.currentTimeMillis());
+   }
+
+   protected void setLastUsed(long lastUsed)
+   {
+      this.lastUsed = lastUsed;
+   }
+
+}
\ No newline at end of file

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractStatefulCacheFactory.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractStatefulCacheFactory.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractStatefulCacheFactory.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,171 @@
+/*
+ * 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.ejb3.cache.spi.impl;
+
+import java.util.Map;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.ejb3.annotation.CacheConfig;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.StatefulCacheFactory;
+import org.jboss.ejb3.cache.spi.PassivationExpirationCoordinator;
+
+/**
+ * Abstract superclass of {@link StatefulCacheFactory} implementations.
+ * 
+ * @author Brian Stansberry
+ */
+public abstract class AbstractStatefulCacheFactory<T extends CacheItem>
+   implements StatefulCacheFactory<T>
+{
+   public static final int DEFAULT_PASSIVATION_EXPIRATION_INTERVAL = 10;
+   
+   private TransactionManager transactionManager;
+   private PassivationExpirationCoordinator passivationExpirationCoordinator;
+   private int defaultPassivationExpirationInterval = DEFAULT_PASSIVATION_EXPIRATION_INTERVAL;
+   private String defaultCacheConfigName;
+   private Map<String, String> cacheConfigAliases;
+   
+   // -------------------------------------------------------------  Properties
+   
+   /**
+    * Gets the transaction manager to be used by the caches.
+    */
+   public TransactionManager getTransactionManager()
+   {
+      return transactionManager;
+   }
+   
+   /**
+    * Sets the transaction manager to be used by the caches. Must be
+    * set for caching to work.
+    */
+   public void setTransactionManager(TransactionManager transactionManager)
+   {
+      this.transactionManager = transactionManager;
+   }
+   
+   /**
+    * Gets the coordinator of passivation/expiration processes. If 
+    * <code>null</code>, each cache will manager passivation/expiration
+    * with their own thread.
+    * 
+    * @return the coordinator. May be <code>null</code>.
+    */
+   public PassivationExpirationCoordinator getPassivationExpirationCoordinator()
+   {
+      return passivationExpirationCoordinator;
+   }
+   
+   /**
+    * Sets the coordinator of passivation/expiration processes.
+    */
+   public void setPassivationExpirationCoordinator(PassivationExpirationCoordinator coordinator)
+   {
+      this.passivationExpirationCoordinator = coordinator;
+   }
+
+   /**
+    * Gets the interval at which passivation/expiration tasks will execute
+    * if no {@link PassivationExpirationCoordinator} is provided.
+    * 
+    * @return the interval, in seconds
+    */
+   public int getDefaultPassivationExpirationInterval()
+   {
+      return defaultPassivationExpirationInterval;
+   }
+
+   /**
+    * Sets the interval at which passivation/expiration tasks will execute
+    * if no {@link PassivationExpirationCoordinator} is provided.
+    * 
+    * @param interval the interval, in seconds
+    */
+   public void setDefaultPassivationExpirationInterval(int interval)
+   {
+      this.defaultPassivationExpirationInterval = interval;
+   }
+
+   /**
+    * Gets the value to internally substitute for {@link CacheConfig#name()} 
+    * if that attribute returns an empty string.
+    * 
+    * @return the substitute value. May be <code>null</code>
+    */
+   public String getDefaultCacheConfigName()
+   {
+      return defaultCacheConfigName;
+   }
+
+   /**
+    * Sets the value to internally substitute for {@link CacheConfig#name()} 
+    * if that attribute returns an empty string.
+    */
+   public void setDefaultCacheConfigName(String defaultCacheConfigName)
+   {
+      this.defaultCacheConfigName = defaultCacheConfigName;
+   }
+
+   /**
+    * Gets a map of substitute (alias) values for {@link CacheConfig#name()}
+    * values.  Map key is the {@link CacheConfig#name()}, value is the substitute
+    * name to use instead.
+    * 
+    * @return the aliases. May be <code>null</code>.
+    */
+   public Map<String, String> getCacheConfigAliases()
+   {
+      return cacheConfigAliases;
+   }
+
+   /**
+    * Sets a map of substitute (alias) values for {@link CacheConfig#name()}
+    * values.  Map key is the {@link CacheConfig#name()}, value is the substitute
+    * name to use instead.
+    */
+   public void setCacheConfigAliases(Map<String, String> cacheConfigAliases)
+   {
+      this.cacheConfigAliases = cacheConfigAliases;
+   }
+   
+   // -----------------------------------------------------------------  Public
+   
+   public String getCacheConfigName(CacheConfig cacheConfig)
+   {
+      String name = cacheConfig.name();
+      String substitute = null;
+      if (cacheConfigAliases != null)
+      {
+         substitute = cacheConfigAliases.get(name);
+      }
+      if (substitute == null && name.length() == 0)
+      {
+         substitute = defaultCacheConfigName;
+      }
+      
+      return substitute == null ? name : substitute;
+   }
+
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractTimerTask.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractTimerTask.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/AbstractTimerTask.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,115 @@
+/*
+ * 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.ejb3.cache.spi.impl;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * Abstract superclass of various TimerTask implementations.
+ * 
+ * @author Brian Stansberry
+ */
+public abstract class AbstractTimerTask 
+   extends TimerTask
+{
+   private boolean stopped = true;
+   private Timer timer;
+   private String timerName;
+   private long interval;
+   
+   /**
+    * Create a new PassivationExpirationRunner.
+    * 
+    */
+   protected AbstractTimerTask(String timerName, long interval)
+   {      
+      setTimerName(timerName);
+      setInterval(interval);
+   }
+   
+   protected AbstractTimerTask() {}
+   
+   public boolean isStopped()
+   {
+      return stopped;
+   }
+
+   public Timer getTimer()
+   {
+      return timer;
+   }
+
+   public String getTimerName()
+   {
+      return timerName;
+   }
+   
+   public void setTimerName(String name)
+   {
+      assert name != null : "name is null";
+      this.timerName = name;
+   }
+
+   /**
+    * Gets the interval, in milliseconds, with which this task should
+    * be {@link Timer#schedule(TimerTask, long) scheduled with the timer}.
+    * 
+    * @return the interval
+    */
+   public long getInterval()
+   {
+      return interval;
+   }
+
+   /**
+    * Sets the interval, in milliseconds, with which this task should
+    * be {@link Timer#schedule(TimerTask, long) scheduled with the timer}.
+    * 
+    * @param interval the interval
+    */
+   public void setInterval(long interval)
+   {
+      assert interval > 0 : "interval is < 1";
+      this.interval = interval;
+   }
+
+   public void start()
+   {
+      if (stopped)
+      {
+         timer = new Timer(getTimerName(), true);
+         stopped = false;
+         long period = getInterval() * 1000;
+         timer.schedule(this, period, period);
+      }
+   }
+   
+   public void stop()
+   {
+      stopped = true;
+      cancel();
+      timer.cancel();
+   }
+
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/CacheableTimestamp.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/CacheableTimestamp.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/CacheableTimestamp.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,100 @@
+/*
+ * 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.ejb3.cache.spi.impl;
+
+import org.jboss.ejb3.cache.Identifiable;
+import org.jboss.ejb3.cache.spi.BackingCacheEntry;
+import org.jboss.ejb3.cache.spi.IntegratedObjectStore;
+
+/**
+ * Encapsulation of the {@link Identifiable#getId() id} and
+ * {@link BackingCacheEntry#getLastUsed() last used timestamp} of
+ * a cached {@link BackingCacheEntry}.
+ * <p>
+ * Implements <code>Comparable</code> to make it easy to sort
+ * for LRU comparisons.
+ * </p>
+ * 
+ * @see IntegratedObjectStore#getInMemoryEntries()
+ * @see IntegratedObjectStore#getPassivatedEntries()
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class CacheableTimestamp 
+   implements Identifiable, Comparable<CacheableTimestamp>
+{
+   private Object id;
+   private long lastUsed;
+   
+   public CacheableTimestamp(Object id, long lastUsed)
+   {
+      assert id != null : "id cannot be null";
+      assert lastUsed > 0 : "lastUsed must be positive";
+      
+      this.id = id;
+      this.lastUsed = lastUsed;
+   }
+   
+   public Object getId()
+   {
+      return id;
+   }
+   
+   public long getLastUsed()
+   {
+      return lastUsed;
+   }
+
+   /**
+    * Compares based on {@link #getLastUsed() last used}, returning
+    * -1 for earlier timestamps.
+    */
+   public int compareTo(CacheableTimestamp o)
+   {
+      if (this.lastUsed < o.lastUsed)
+         return -1;
+      else if (this.lastUsed > o.lastUsed)
+         return 1;
+      return 0;
+   }
+
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (this == obj)
+         return true;
+      
+      if (obj instanceof CacheableTimestamp)
+      {
+         return this.id.equals(((CacheableTimestamp) obj).id);
+      }
+      return false;
+   }
+
+   @Override
+   public int hashCode()
+   {
+      return id.hashCode();
+   }   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/FileObjectStore.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/FileObjectStore.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/FileObjectStore.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,283 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.cache.spi.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.spi.ObjectStore;
+import org.jboss.logging.Logger;
+import org.jboss.serial.io.JBossObjectInputStream;
+import org.jboss.serial.io.JBossObjectOutputStream;
+
+/**
+ * Stores objects in a directory via serialization.
+ *
+ * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
+ * @version $Revision: 65339 $
+ */
+public class FileObjectStore<T extends CacheItem> 
+   implements ObjectStore<T>
+{
+   private static final Logger log = Logger.getLogger(FileObjectStore.class);
+   
+   private int subdirectoryCount;   
+   private File baseDirectory;
+   private File[] storageDirectories;
+   
+   private static class DeleteFileAction implements PrivilegedAction<Boolean>
+   {
+      File file;
+
+      DeleteFileAction(File file)
+      {
+         this.file = file;
+      }
+
+      public Boolean run()
+      {
+         return file.delete();
+      }
+
+      static boolean delete(File file)
+      {
+         DeleteFileAction action = new DeleteFileAction(file);
+         return AccessController.doPrivileged(action);
+      }
+   }
+
+   private static class FISAction implements PrivilegedExceptionAction<FileInputStream>
+   {
+      File file;
+
+      FISAction(File file)
+      {
+         this.file = file;
+      }
+
+      public FileInputStream run() throws FileNotFoundException
+      {
+         FileInputStream fis = new FileInputStream(file);
+         return fis;
+      }
+
+      static FileInputStream open(File file) throws FileNotFoundException
+      {
+         FISAction action = new FISAction(file);
+         FileInputStream fis = null;
+         try
+         {
+            fis = AccessController.doPrivileged(action);
+         }
+         catch (PrivilegedActionException e)
+         {
+            throw (FileNotFoundException) e.getException();
+         }
+         return fis;
+      }
+   }
+
+   private static class FOSAction implements PrivilegedExceptionAction<FileOutputStream>
+   {
+      File file;
+
+      FOSAction(File file)
+      {
+         this.file = file;
+      }
+
+      public FileOutputStream run() throws FileNotFoundException
+      {
+         FileOutputStream fis = new FileOutputStream(file);
+         return fis;
+      }
+
+      static FileOutputStream open(File file) throws FileNotFoundException
+      {
+         FOSAction action = new FOSAction(file);
+         FileOutputStream fos = null;
+         try
+         {
+            fos = AccessController.doPrivileged(action);
+         }
+         catch (PrivilegedActionException e)
+         {
+            throw (FileNotFoundException) e.getException();
+         }
+         return fos;
+      }
+   }
+
+   private static class MkdirsFileAction implements PrivilegedAction<Boolean>
+   {
+      File file;
+
+      MkdirsFileAction(File file)
+      {
+         this.file = file;
+      }
+
+      public Boolean run()
+      {
+         return file.mkdirs();
+      }
+
+      static boolean mkdirs(File file)
+      {
+         MkdirsFileAction action = new MkdirsFileAction(file);
+         return AccessController.doPrivileged(action);
+      }
+   }
+
+   protected File getFile(Object key)
+   {
+      File base = null;
+      if (storageDirectories != null)
+      {
+         int hash = Math.abs(key.hashCode()) % storageDirectories.length;
+         base = storageDirectories[hash];
+      }
+      else
+      {
+         base = baseDirectory;
+      }
+      return new File(base, String.valueOf(key) + ".ser");
+      
+   }
+   
+   @SuppressWarnings("unchecked")
+   public T load(Object key)
+   {
+      File file = getFile(key);
+      if(!file.exists())
+         return null;
+      
+      log.debug("loading state from " + file);
+      try
+      {
+         FileInputStream fis = FISAction.open(file);
+         ObjectInputStream in = new JBossObjectInputStream(fis);
+//         ObjectInputStream in = new ObjectInputStream(fis);
+         try
+         {
+            return (T) in.readObject();
+         }
+         finally
+         {
+            in.close();
+            DeleteFileAction.delete(file);
+         }
+      }
+      catch(ClassNotFoundException e)
+      {
+         throw new RuntimeException("failed to load object " + key, e);
+      }
+      catch(IOException e)
+      {
+         throw new RuntimeException("failed to load object " + key, e);
+      }
+   }
+
+   public void setStorageDirectory(String dirName)
+   {
+      baseDirectory = new File(dirName);
+   }   
+   
+   public void setSubdirectoryCount(int subdirectoryCount)
+   {
+      this.subdirectoryCount = subdirectoryCount;
+   }
+
+   public void start()
+   {
+      assert baseDirectory != null : "baseDirectory is null";
+      assert subdirectoryCount > 0 : "subdirectoryCount is < 1";
+      
+      establishDirectory(baseDirectory);
+      
+      if (subdirectoryCount > 1)
+      {
+         storageDirectories = new File[subdirectoryCount];
+         for (int i = 0; i < storageDirectories.length; i++)
+         {
+            File f = new File(baseDirectory, String.valueOf(i));
+            establishDirectory(f);
+            storageDirectories[i] = f;
+         }
+      }
+   }
+   
+   private void establishDirectory(File dir)
+   {      
+      if(!dir.exists())
+      {
+         if(!MkdirsFileAction.mkdirs(dir))
+            throw new RuntimeException("Unable to create storage directory " + dir);
+         dir.deleteOnExit();
+      }
+      
+      if(!dir.isDirectory())
+         throw new RuntimeException("Storage directory " + dir + " is not a directory");
+      
+   }
+   
+   public void stop()
+   {
+      // TODO: implement
+   }
+   
+   public void store(T obj)
+   {
+      File file = getFile(obj.getId());
+      file.deleteOnExit();
+      log.debug("saving state to " + file);
+      try
+      {
+         FileOutputStream fos = FOSAction.open(file);
+         ObjectOutputStream out = new JBossObjectOutputStream(fos);
+//         ObjectOutputStream out = new ObjectOutputStream(fos);
+         try
+         {
+            out.writeObject(obj);
+            out.flush();
+         }
+         finally
+         {
+            out.close();
+         }
+      }
+      catch(IOException e)
+      {
+         throw new RuntimeException("failed to store object " + obj.getId(), e);
+      }
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/PassivationExpirationRunner.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/PassivationExpirationRunner.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/PassivationExpirationRunner.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,57 @@
+/*
+ * 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.ejb3.cache.spi.impl;
+
+import org.jboss.ejb3.cache.spi.PassivationExpirationProcessor;
+
+/**
+ * TimerTask that will periodically invoke 
+ * {@link PassivationExpirationProcessor#processPassivationExpiration()}
+ * on a single processor.
+ * 
+ * @author Brian Stansberry
+ */
+public class PassivationExpirationRunner 
+   extends AbstractTimerTask
+{
+   private PassivationExpirationProcessor processor;
+   
+   /**
+    * Create a new PassivationExpirationRunner.
+    * 
+    */
+   public PassivationExpirationRunner(PassivationExpirationProcessor processor, 
+                                      String timerName, long interval)
+   {
+      super(timerName, interval);
+      
+      assert processor != null : "processor is null";
+      this.processor = processor;
+   }
+
+   public void run()
+   {
+      processor.processPassivationExpiration();
+   }
+
+}

Copied: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/SerializationGroupImpl.java (from rev 70283, projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/impl/SerializationGroupImpl.java)
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/SerializationGroupImpl.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/SerializationGroupImpl.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,384 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.cache.spi.impl;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.Identifiable;
+import org.jboss.ejb3.cache.SerializationGroup;
+import org.jboss.ejb3.cache.spi.BackingCacheEntry;
+import org.jboss.ejb3.cache.spi.PassivatingBackingCache;
+import org.jboss.logging.Logger;
+import org.jboss.util.id.GUID;
+
+/**
+ * Defines a group of serializable objects which must be serialized in
+ * one unit of work.
+ *
+ * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
+ * @author Brian Stansberry
+ * @version $Revision: $
+ */
+public class SerializationGroupImpl<T extends CacheItem>  
+   extends AbstractBackingCacheEntry<T>
+   implements SerializationGroup<T>, BackingCacheEntry<T>
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = -6181048392582344057L;
+
+   private static final Logger log = Logger.getLogger(SerializationGroupImpl.class);
+
+   private Object id = new GUID();
+   
+   /** 
+    * The actual underlying objects passed in via addMember(). We store them 
+    * here so they aren't lost when they are cleared from the values
+    * stored in the "members" map.
+    */
+   private Map<Object, T> memberObjects = new ConcurrentHashMap<Object, T>();
+   
+   /** 
+    * The active group members.  We don't serialize these. Rather, it is
+    * the responsibility of members to reassociate themselves with the 
+    * group upon deserialization (via addActive())
+    */
+   private transient Map<Object, SerializationGroupMember<T>> active = 
+         new HashMap<Object, SerializationGroupMember<T>>();
+   
+   /**
+    * Set of keys passed to {@link #addInUse(Object)}
+    */
+   private transient Set<Object> inUseKeys = new HashSet<Object>();
+   
+   /** Transient ref to our group cache; used to validate compatibility */
+   private transient PassivatingBackingCache<T, SerializationGroupImpl<T>> groupCache;
+   
+   /** Is this object used in a clustered cache? */
+   private boolean clustered;
+
+   private transient boolean invalid;
+   
+   public Object getId()
+   {
+      return id;
+   }
+   
+   /**
+    * Gets whether this groups supports (and requires) clustering functionality
+    * from its members.
+    * 
+    * @return <code>true</code> if clustering is supported, <code>false</code>
+    *         otherwise
+    */
+   public boolean isClustered()
+   {
+      return clustered;
+   }
+   
+   /**
+    * Sets whether this groups supports (and requires) clustering functionality
+    * from its members.
+    * 
+    * @return
+    */
+   public void setClustered(boolean clustered)
+   {
+      this.clustered = clustered;
+   }
+   
+   /**
+    * Initially associates a new member with the group. Also
+    * {@link #addActive(SerializationGroupMember) marks the member as
+    * active}.
+    * 
+    * @param member
+    * 
+    * @throws IllegalStateException if <code>member</code> was previously
+    *                               added to the group
+    * @throws IllegalArgumentException if the 
+    *   {@link SerializationGroupMember#isClustered() member's support for clustering}
+    *   does not match {@link #isClustered() our own}.
+    */
+   public void addMember(SerializationGroupMember<T> member)
+   {
+      Object key = member.getId();
+      if (memberObjects.containsKey(key))
+         throw new IllegalStateException(member + " is already a member");
+      log.trace("add member " + key + ", " + member);
+      memberObjects.put(key, member.getUnderlyingItem());
+      active.put(key, member);
+   }
+   
+   /**
+    * Remove the specified member from the group.
+    * 
+    * @param key the {@link Identifiable#getId() id} of the member
+    */
+   public void removeMember(Object key)
+   {
+      removeActive(key);
+      memberObjects.remove(key);
+   }
+   
+   /**
+    * Gets the number of group members.
+    */
+   public int size()
+   {
+      return memberObjects.size();
+   }
+   
+   /**
+    * Returns the {@link SerializationGroupMember#getUnderlyingItem() member object}
+    * associated with the member whose {@link Identifiable#getId() id}
+    * matches <code>key</code>.
+    * 
+    * @param key the {@link Identifiable#getId() id} of the member
+    * 
+    * @return the object associated with the member, or <code>null</code> if
+    *         <code>key</code> does not identify a member.
+    */
+   public T getMemberObject(Object key)
+   {
+      return memberObjects.get(key);
+   }
+   
+   public Iterator<T> iterator()
+   {
+      return new UnmodifiableIterator<T>(memberObjects.values().iterator());
+   }
+   
+   /**
+    * Prepare members for passivation.
+    */
+   public void prePassivate()
+   {
+      for(SerializationGroupMember<T> member : active.values())
+      {
+         member.prePassivate();
+      }
+      active.clear();
+   }
+   
+   /**
+    * Notification that the group has been activated from a passivated state.
+    */
+   public void postActivate()
+   {
+      invalid = false;
+   }
+   
+   /**
+    * Prepare members for replication.
+    */
+   public void preReplicate()
+   {
+      for(SerializationGroupMember<T> member : active.values())
+      {
+         member.preReplicate();
+      }
+      active.clear();
+   }
+   
+   /**
+    * Notification that the previously replicated group has been retrieved from 
+    * a clustered cache.
+    */
+   public void postReplicate()
+   {
+      invalid = false;
+   }
+   
+   /**
+    * Records that the given member is "active"; i.e. needs to have
+    * @PrePassivate callbacks invoked before serialization.
+    * 
+    * @param member the member
+    * 
+    * @throws IllegalStateException if <code>member</code> wasn't previously
+    *                               added to the group via
+    *                               {@link #addMember(SerializationGroupMember)}
+    */
+   public void addActive(SerializationGroupMember<T> member)
+   {
+      Object key = member.getId();
+      if (!memberObjects.containsKey(key))
+         throw new IllegalStateException(member + " is not a member of " + this);
+      active.put(key, member);
+   }
+   
+   /**
+    * Records that the given member is no longer "active"; i.e. does not need
+    * to have @PrePassivate callbacks invoked before serialization.
+    * 
+    * @param key the {@link Identifiable#getId() id} of the member
+    * 
+    * @throws IllegalStateException if <code>member</code> wasn't previously
+    *                               added to the group via
+    *                               {@link #addMember(SerializationGroupMember)}
+    */
+   public void removeActive(Object key)
+   {
+      active.remove(key);
+   }
+
+   /**
+    * Notification that the given member is "in use", and therefore the
+    * group should not be serialized.
+    * 
+    * @param key the {@link Identifiable#getId() id} of the member
+    * 
+    * @throws IllegalStateException if <code>member</code> wasn't previously
+    *                               added to the group via
+    *                               {@link #addMember(SerializationGroupMember)}
+    */
+   public void addInUse(Object key)
+   {
+      if (!memberObjects.containsKey(key))
+         throw new IllegalStateException(key + " is not a member of " + this);
+      inUseKeys.add(key);
+      setInUse(true);
+   }
+
+   /**
+    * Notification that the given member is no longer "in use", and therefore 
+    * should not prevent the group being serialized.
+    * 
+    * @param key the {@link Identifiable#getId() id} of the member
+    * 
+    * @throws IllegalStateException if <code>member</code> wasn't previously
+    *                               added to the group via
+    *                               {@link #addMember(SerializationGroupMember)}
+    */
+   public void removeInUse(Object key)
+   {
+      if (inUseKeys.remove(key))
+      {
+         setLastUsed(System.currentTimeMillis());
+      }
+      else if (!memberObjects.containsKey(key))
+      {
+            throw new IllegalStateException(key + " is not a member of " + this);
+      }      
+   }
+   
+   /**
+    * Gets the number of members currently in use.
+    */
+   public int getInUseCount()
+   {
+      return inUseKeys.size();
+   }
+   
+   /**
+    * Always returns <code>true</code>.
+    */
+   public boolean isModified()
+   {
+      return true;
+   }
+   
+   /**
+    * Returns true if this object has been passivated (meaning whoever
+    * holds a ref to it is holding an out-of-date object)
+    * 
+    * @return
+    */
+   public boolean isInvalid()
+   {
+      return invalid;
+   }
+   
+   public void setInvalid(boolean invalid)
+   {
+      this.invalid = invalid;
+   }
+   
+   /**
+    * FIXME -- returns null; what should it do?
+    */
+   public T getUnderlyingItem()
+   {
+      return null;
+   }
+
+   public PassivatingBackingCache<T, SerializationGroupImpl<T>> getGroupCache()
+   {
+      return groupCache;
+   }
+
+   @Override
+   public String toString()
+   {
+      return super.toString() + "{id=" + id + "}";
+   }
+
+   public void setGroupCache(PassivatingBackingCache<T, SerializationGroupImpl<T>> groupCache)
+   {
+      this.groupCache = groupCache;
+   }
+
+   private void readObject(java.io.ObjectInputStream in)
+         throws IOException, ClassNotFoundException
+   {
+      in.defaultReadObject();
+      active = new HashMap<Object, SerializationGroupMember<T>>();
+      inUseKeys = new HashSet<Object>();
+   }   
+   
+   private class UnmodifiableIterator<C extends CacheItem & Serializable> implements Iterator<C>
+   {
+      private Iterator<C> backingIterator;
+      
+      public UnmodifiableIterator(Iterator<C> backingIterator)
+      {
+         assert backingIterator != null : "backingIterator is null";
+         
+         this.backingIterator = backingIterator;
+      }
+
+      public boolean hasNext()
+      {
+         return backingIterator.hasNext();
+      }
+
+      public C next()
+      {
+         return backingIterator.next();
+      }
+
+      public void remove()
+      {
+         throw new UnsupportedOperationException("remove is not supported");         
+      }
+   }
+   
+   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/SerializationGroupMember.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/SerializationGroupMember.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/main/java/org/jboss/ejb3/cache/spi/impl/SerializationGroupMember.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,282 @@
+/*
+ * 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.ejb3.cache.spi.impl;
+
+import java.io.IOException;
+
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.spi.PassivatingBackingCache;
+
+/**
+ * A member of a {@link SerializationGroupImpl}.
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class SerializationGroupMember<T extends CacheItem> 
+   extends AbstractBackingCacheEntry<T>
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 7268142730501106252L;
+
+   /**
+    * Identifier for our underlying object
+    */
+   private Object id;
+   
+   /**
+    * The underlying object (e.g. bean context).
+    * Preferably, this field would be transient. It isn't now because it is 
+    * possible this entry will never be assigned to a PassivationGroup,
+    * in which case we need to serialize obj.
+    */
+   private T obj;
+   
+   /**
+    * Hack. We hold two refs to our object; one we clear in prePassivate,
+    * one we keep, but it's transient.  getUnderlyingItem() returns
+    * whichever is available, making it available for passivation callbacks.
+    */
+   private transient T transientObj;
+   
+   /** The group. Never serialize the group; only the groupCache does that */
+   private transient SerializationGroupImpl<T> group;
+   
+   /**
+    * Id for our group; serialize this so we can find our group again
+    * after deserialization on a remote node.
+    */
+   private Object groupId;
+   
+   private boolean clustered;
+   
+   private boolean preReplicated;
+   private boolean prePassivated;
+   
+   /** The cache that's handling us */
+   private transient PassivatingBackingCache<T, SerializationGroupMember<T>> cache;
+   
+   public SerializationGroupMember(T obj, PassivatingBackingCache<T, SerializationGroupMember<T>> cache)
+   {
+      assert obj != null : "obj is null";
+      assert cache != null : "cache is null";
+      
+      this.obj = transientObj = obj;
+      this.id = obj.getId();
+      this.cache = cache;
+      this.clustered = cache.isClustered();
+   }
+   
+   public Object getId()
+   {
+      return id;
+   }
+   
+   public boolean isModified()
+   {
+      return (obj != null && obj.isModified());
+   }
+   
+   /**
+    * Gets whether this member supports clustering functionality.
+    * 
+    * @return <code>true</code> if clustering is supported, <code>false</code>
+    *         otherwise
+    */
+   public boolean isClustered()
+   {
+      return clustered;
+   }
+   
+   @SuppressWarnings("unchecked")
+   public T getUnderlyingItem()
+   {      
+      return obj == null ? transientObj : obj;
+   }
+   
+   /**
+    * Sets the underlying {@link CacheItem} associated with this group member.
+    * 
+    * @param item the cache item
+    */
+   public void setUnderlyingItem(T obj)
+   {
+      this.obj = transientObj = obj;
+   }
+   
+   /**
+    * Gets the {@link SerializationGroupImpl} of which this object is a member.
+    * 
+    * @return the group. May return <code>null</code>
+    */
+   public SerializationGroupImpl<T> getGroup()
+   {
+      return (group == null || group.isInvalid()) ? null : group;
+   }
+
+   /**
+    * Sets the {@link SerializationGroupImpl} of which this object is a member.
+    * 
+    * @param the group. May be <code>null</code>
+    */
+   public void setGroup(SerializationGroupImpl<T> group)
+   {
+      this.group = group;
+      if (group != null)
+         this.groupId = group.getId();
+   }
+
+   /**
+    * Gets the id for the group
+    * 
+    * @return
+    */
+   public Object getGroupId()
+   {
+      return groupId;
+   }
+
+   /**
+    * Prepare the group member for passivation. Ensure any @PrePassivate 
+    * callback is invoked on the underlying object.  If we are a member of a 
+    * group, ensure any reference to the 
+    * {@link #getUnderlyingItem() underlying object} or to the 
+    * {@link #getGroup()} is nulled.
+    */
+   public void prePassivate()
+   {
+      // make sure we don't passivate the group twice
+      group = null;
+      
+      // null out obj so when delegate passivates this entry
+      // we don't serialize it. It serializes with the PassivationGroup only  
+      // We still have a ref to transientObj, so it can be retrieved
+      // for passivation callbacks
+      obj = null;
+      
+      cache.passivate(this.id);
+   }
+   
+   public boolean isPrePassivated()
+   {
+      return prePassivated;
+   }
+   
+   public void setPrePassivated(boolean prePassivated)
+   {
+      this.prePassivated = prePassivated;
+   }
+   
+   /**
+    * Notification that the group has been activated from a passivated state.
+    */
+   public void postActivate()
+   {
+      // no-op
+   }
+   
+   /**
+    * Prepare the group member for replication. Ensure any required callback
+    * (e.g. @PreReplicaate) is invoked on the underlying object. If we are a 
+    * member of a group, ensure any reference to the 
+    * {@link #getUnderlyingItem() underlying object} or to the 
+    * {@link #getGroup()} is nulled.
+    * 
+    * @throws UnsupportedOperationException if {@link #isClustered()} returns
+    *                                       <code>false</code>
+    */
+   public void preReplicate()
+   {
+      // make sure we don't replicate the group twice
+      group = null;
+      // null out obj so when delegate serializes this entry
+      // we don't serialize it. It serializes with the PassivationGroup only
+      obj = null;
+      
+      // FIXME -- what does this do for us?
+      // Nothing -- it will fail
+//      cache.release(this);
+   }
+   
+   public boolean isPreReplicated()
+   {
+      return preReplicated;
+   }
+   
+   public void setPreReplicated(boolean preReplicated)
+   {
+      this.preReplicated = preReplicated;
+   }
+   
+   /**
+    * Notification that the previously replicated group has been retrieved from 
+    * a clustered cache.
+    */
+   public void postReplicate()
+   {
+      // no-op
+   }
+
+   public void setInUse(boolean inUse)
+   {
+      super.setInUse(inUse);
+      
+      // Tell our group about it
+      if (group != null)
+      {
+         if (inUse)
+            group.addActive(this);
+         else
+            group.removeActive(id);
+      }         
+   }
+   
+   /**
+    * Allows our controlling {@link PassivatingBackingCache} to provide
+    * us a reference after deserialization.
+    * 
+    * @param delegate
+    */
+   public void setPassivatingCache(PassivatingBackingCache<T, SerializationGroupMember<T>> delegate)
+   {
+      assert delegate != null : "delegate is null";
+      
+      this.cache = delegate;
+   }
+
+   @Override
+   public String toString()
+   {
+      return super.toString() + "{id=" + id + ",obj=" + obj + ",groupId=" + groupId + ",group=" + group + "}";
+   }
+   
+   private void writeObject(java.io.ObjectOutputStream out) throws IOException
+   {
+      if (groupId != null)
+      {
+         group = null;
+         obj = null;
+      }
+      out.defaultWriteObject();
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/impl/backing/PassivatingBackingCacheImplUnitTestCase.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/impl/backing/PassivatingBackingCacheImplUnitTestCase.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/impl/backing/PassivatingBackingCacheImplUnitTestCase.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,79 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.test.cache.impl.backing;
+
+import junit.framework.TestCase;
+
+import org.jboss.ejb3.cache.impl.TransactionalCache;
+import org.jboss.ejb3.cache.impl.backing.PassivatingBackingCacheImpl;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupMember;
+import org.jboss.ejb3.test.cache.mock.CacheType;
+import org.jboss.ejb3.test.cache.mock.MockBeanContainer;
+import org.jboss.ejb3.test.cache.mock.MockBeanContext;
+import org.jboss.ejb3.test.cache.mock.MockCacheConfig;
+import org.jboss.ejb3.test.cache.mock.MockEjb3System;
+import org.jboss.ejb3.test.cache.mock.MockXPC;
+
+/**
+ * Comment
+ *
+ * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
+ * @version $Revision: 65339 $
+ */
+public class PassivatingBackingCacheImplUnitTestCase extends TestCase
+{
+   
+   /**
+    * Peek of an active object should not change it state.
+    */
+   @SuppressWarnings("unchecked")
+   public void testPeekActive() throws Exception
+   {
+      MockEjb3System system = new MockEjb3System(false, CacheType.SIMPLE);
+      MockXPC sharedXPC = new MockXPC();
+      MockCacheConfig config = new MockCacheConfig();
+      config.setIdleTimeoutSeconds(4);
+      MockBeanContainer container = system.deployBeanContainer("MockBeanContainer1", null, CacheType.SIMPLE, config, sharedXPC);
+      TransactionalCache cache = (TransactionalCache) container.getCache();
+      PassivatingBackingCacheImpl<MockBeanContext, SerializationGroupMember<MockBeanContext>> backingCache = (PassivatingBackingCacheImpl<MockBeanContext, SerializationGroupMember<MockBeanContext>>) cache.getBackingCache();
+      SerializationGroupMember<MockBeanContext> obj = backingCache.create(null, null);
+      Object key = obj.getId();
+      
+      backingCache.peek(key);
+      
+      try
+      {
+         backingCache.release(key);
+         fail("Should not be able to release entry that has not been gotten");
+      }
+      catch (IllegalStateException good)
+      {
+         backingCache.get(key);
+         backingCache.release(key);      
+      }
+      finally
+      {
+         backingCache.remove(key);
+      }
+         
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/Ejb3CacheTestCaseBase.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/Ejb3CacheTestCaseBase.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/Ejb3CacheTestCaseBase.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,90 @@
+/*
+ * 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.ejb3.test.cache.integrated;
+
+import org.jboss.ejb3.test.cache.mock.MockRegistry;
+import org.jboss.ejb3.test.cache.mock.tm.MockTransactionManager;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class Ejb3CacheTestCaseBase extends TestCase
+{
+
+   /**
+    * Create a new Ejb3CacheTestCaseBase.
+    * 
+    */
+   public Ejb3CacheTestCaseBase()
+   {
+      // TODO Auto-generated constructor stub
+   }
+
+   /**
+    * Create a new Ejb3CacheTestCaseBase.
+    * 
+    * @param name
+    */
+   public Ejb3CacheTestCaseBase(String name)
+   {
+      super(name);
+   }
+
+   @Override
+   protected void tearDown() throws Exception
+   {
+      cleanSystem();
+      super.tearDown();
+   }
+   
+   protected void cleanSystem()
+   {
+      MockRegistry.clear();
+      MockTransactionManager.cleanupTransactions();
+      MockTransactionManager.cleanupTransactionManagers();
+   }
+   
+   protected static void wait(Object obj) throws InterruptedException
+   {
+      synchronized (obj)
+      {
+         obj.wait(5000);
+      }
+   }
+   
+   protected static void sleep(long micros)
+   {
+      try
+      {
+         Thread.sleep(micros);
+      }
+      catch (InterruptedException e)
+      {
+         // ignore
+      }
+   }
+
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/GroupAwareTransactionalCacheUnitTestCase.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/GroupAwareTransactionalCacheUnitTestCase.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/GroupAwareTransactionalCacheUnitTestCase.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,167 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.test.cache.integrated;
+
+import org.jboss.ejb3.cache.Cache;
+import org.jboss.ejb3.test.cache.mock.CacheType;
+import org.jboss.ejb3.test.cache.mock.MockBeanContainer;
+import org.jboss.ejb3.test.cache.mock.MockBeanContext;
+import org.jboss.ejb3.test.cache.mock.MockCacheConfig;
+import org.jboss.ejb3.test.cache.mock.MockEjb3System;
+import org.jboss.ejb3.test.cache.mock.MockPassivationManager;
+import org.jboss.ejb3.test.cache.mock.MockXPC;
+import org.jboss.logging.Logger;
+
+/**
+ * Comment
+ *
+ * @author Brian Stansberry
+ * @version $Revision: 65920 $
+ */
+public class GroupAwareTransactionalCacheUnitTestCase extends TransactionalCacheUnitTestCase
+{
+   private static final Logger log = Logger.getLogger(GroupAwareTransactionalCacheUnitTestCase.class);
+   
+   @Override
+   protected Cache<MockBeanContext> createCache() throws Exception
+   {
+      MockEjb3System system = new MockEjb3System(false, CacheType.SIMPLE);
+      MockBeanContainer ejb = system.deployBeanContainer("test", null, CacheType.SIMPLE);
+      return ejb.getCache();
+   }
+   
+   public void testNonGroupedPassivation() throws Exception
+   {
+      MockEjb3System system = new MockEjb3System(false, CacheType.SIMPLE);
+      MockXPC sharedXPC = new MockXPC();
+      MockCacheConfig config = new MockCacheConfig();
+      config.setIdleTimeoutSeconds(4);
+      MockBeanContainer container = system.deployBeanContainer("MockBeanContainer1", null, CacheType.SIMPLE, config, sharedXPC);
+      Cache<MockBeanContext> cache = container.getCache();
+      
+      Object key = cache.create(null, null).getId();
+      MockBeanContext obj = cache.get(key);
+      
+      cache.finished(obj);
+      obj = null;
+      
+      wait(container);
+      
+      MockPassivationManager pass = (MockPassivationManager) container.getPassivationManager();
+      
+      assertEquals("MockBeanContext should have been passivated", 1, pass.getPrePassivateCount());
+      
+      obj = cache.get(key);
+      assertNotNull(obj);
+      
+      assertEquals("MockBeanContext should have been activated", 1, pass.getPostActivateCount());
+      
+      sleep(3000);
+      
+      assertEquals("MockBeanContext should not have been passivated", 1, pass.getPrePassivateCount());
+      
+      cache.finished(obj);
+      obj = null;
+      
+      wait(container);
+      
+      assertEquals("MockBeanContext should have been passivated", 2, pass.getPrePassivateCount());
+   }
+
+
+
+   public void testSimpleGroupPassivation() throws Exception
+   {    
+      MockEjb3System system = new MockEjb3System(false, CacheType.SIMPLE);
+      MockXPC sharedXPC = new MockXPC();
+      MockCacheConfig config = new MockCacheConfig();
+      config.setIdleTimeoutSeconds(1);
+      MockBeanContainer container1 = system.deployBeanContainer("MockBeanContainer1", null, CacheType.SIMPLE, config, sharedXPC);
+      MockBeanContainer container2 = system.deployBeanContainer("MockBeanContainer2", "MockBeanContainer1", CacheType.SIMPLE, config, sharedXPC);
+      
+      log.info("Containers deployed");
+      
+      assertTrue(container1.hasChild(container2));
+      
+      try
+      {
+         Object key1 = container1.getCache().create(null, null).getId();
+         MockBeanContext firstCtx1;
+         MockBeanContext ctx1 = firstCtx1 = container1.getCache().get(key1);
+         
+         assertEquals(sharedXPC, ctx1.getXPC());
+         Object key2 = ctx1.getChild(container2.getName());
+         MockBeanContext ctx2 = container2.getCache().get(key2);
+         assertNotNull(ctx2);
+         assertEquals(sharedXPC, ctx2.getXPC());
+
+         container2.getCache().finished(ctx2);
+         container1.getCache().finished(ctx1);
+         
+         log.info("Finished with contexts");
+         
+         sleep(2100);
+         
+         MockPassivationManager pass1 = (MockPassivationManager) container1.getPassivationManager();
+         MockPassivationManager pass2 = (MockPassivationManager) container2.getPassivationManager();
+         
+         
+         assertEquals("ctx1 should have been passivated", 1, pass1.getPrePassivateCount());
+         assertEquals("ctx2 should have been passivated", 1, pass2.getPrePassivateCount());
+         
+         log.info("Restoring ctx2");
+         
+         ctx2 = container2.getCache().get(key2);
+         
+         log.info("ctx2 = " + ctx2);
+         assertNotNull(ctx2);
+         
+         log.info("Restoring ctx1");
+         
+         ctx1 = container1.getCache().get(key1);
+         
+         log.info("ctx1 = " + ctx1);
+         
+         assertTrue("ctx1 must be different than firstCtx1 (else no passivation has taken place)", ctx1 != firstCtx1);
+         
+         assertNotNull(ctx1.getXPC());
+         assertEquals(ctx1.getXPC(), ctx2.getXPC());
+         
+         container1.getCache().finished(ctx1);         
+         container2.getCache().finished(ctx2);
+         
+      }
+      finally
+      {
+         container1.stop();
+         container2.stop();
+      }
+   }
+   
+   /**
+    * Test call to bean1 that calls into bean2 that calls back into bean1
+    */
+   public void testRecursiveCalls()
+   {
+      // FIXME implement testRecursiveCalls() -- which will fail :(
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/TransactionalCacheUnitTestCase.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/TransactionalCacheUnitTestCase.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/integrated/TransactionalCacheUnitTestCase.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,132 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007, 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.ejb3.test.cache.integrated;
+
+import javax.ejb.NoSuchEJBException;
+
+import org.jboss.ejb3.cache.Cache;
+import org.jboss.ejb3.test.cache.mock.CacheType;
+import org.jboss.ejb3.test.cache.mock.MockBeanContainer;
+import org.jboss.ejb3.test.cache.mock.MockBeanContext;
+import org.jboss.ejb3.test.cache.mock.MockEjb3System;
+
+/**
+ * Comment
+ *
+ * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
+ * @author Brian Stansberry
+ * @version $Revision: $
+ */
+public class TransactionalCacheUnitTestCase extends Ejb3CacheTestCaseBase
+{   
+   protected Cache<MockBeanContext> createCache() throws Exception
+   {
+      MockEjb3System system = new MockEjb3System(false, CacheType.NON_PASSIVATING);
+      MockBeanContainer ejb = system.deployBeanContainer("test", null, CacheType.NON_PASSIVATING);
+      return ejb.getCache();
+   }
+   
+   public void testNonExistingGet() throws Exception
+   {      
+      Cache<MockBeanContext> cache = createCache();
+      
+      try
+      {
+         cache.get(1);
+         fail("Object 1 should not be in cache");
+      }
+      catch(NoSuchEJBException e)
+      {
+         // good
+      }
+   }
+   
+   public void testSimpleLifeCycle() throws Exception
+   {
+      Cache<MockBeanContext> cache = createCache();
+      
+      Object key = cache.create(null, null).getId();
+      MockBeanContext object = cache.get(key);
+      
+      assertNotNull(object);
+      
+      cache.remove(key);
+      
+      try
+      {
+         cache.get(key);
+         fail("Object should not be in cache");
+      }
+      catch(NoSuchEJBException e)
+      {
+         // good
+      }
+   }
+   
+   public void testSequentialGetCalls() throws Exception
+   {
+      Cache<MockBeanContext> cache = createCache();
+      
+      Object key = cache.create(null, null).getId();
+      MockBeanContext object = cache.get(key);
+      
+      assertNotNull(object);
+      
+      try
+      {
+         cache.get(key);
+         fail("Two sequential get calls should throw ISE");
+      }
+      catch(IllegalStateException e)
+      {
+         // good
+      }
+      finally {
+         cache.remove(key);
+      }
+   }
+   
+   public void testSequentialFinishedCalls() throws Exception
+   {
+      Cache<MockBeanContext> cache = createCache();
+      
+      Object key = cache.create(null, null).getId();
+      MockBeanContext object = cache.get(key);
+      
+      assertNotNull(object);
+      
+      cache.finished(object);
+      
+      try
+      {
+         cache.finished(object);
+         fail("Two sequential finished calls should throw ISE");
+      }
+      catch(IllegalStateException e)
+      {
+         // good
+      }
+      finally {
+         cache.remove(key);
+      }
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/CacheType.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/CacheType.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/CacheType.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,47 @@
+/*
+ * 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.ejb3.test.cache.mock;
+
+/**
+ * Enumeration of the types of caches we'll test
+ * 
+ * @author Brian Stansberry
+ */
+public enum CacheType {
+
+   NON_PASSIVATING("NonPassivatingCache"),
+   SIMPLE("SimpleStatefulCache"),
+   DISTRIBUTED("StatefulTreeCache");
+   
+   private String mapKey;
+   
+   private CacheType(String mapKey)
+   {
+      this.mapKey = mapKey;
+   }
+   
+   public String mapKey()
+   {
+      return mapKey;
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockBeanContainer.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockBeanContainer.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockBeanContainer.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,127 @@
+/*
+ * 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.ejb3.test.cache.mock;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.jboss.ejb3.cache.Cache;
+import org.jboss.ejb3.cache.PassivationManager;
+import org.jboss.ejb3.cache.StatefulCacheFactory;
+import org.jboss.ejb3.cache.StatefulCacheFactoryRegistry;
+import org.jboss.ejb3.cache.StatefulObjectFactory;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockBeanContainer
+{
+   private final String containerName;
+   private final String cacheFactoryName;
+   private final StatefulCacheFactoryRegistry<MockBeanContext> cacheFactoryRegistry;
+   private final MockCacheConfig cacheConfig;
+   private final MockStatefulObjectFactory objectFactory;
+   private final MockPassivationManager passivationManager;
+   
+   private Cache<MockBeanContext> cache;
+   private Set<MockBeanContainer> children;
+   
+   private MockXPC xpc;
+   
+   public MockBeanContainer(String containerName, String cacheFactoryName,
+         StatefulCacheFactoryRegistry<MockBeanContext> cacheFactoryRegistry,
+         MockCacheConfig cacheConfig)
+   {
+      this.containerName = containerName;
+      this.cacheFactoryName = cacheFactoryName;
+      this.cacheFactoryRegistry = cacheFactoryRegistry;
+      this.cacheConfig = cacheConfig;
+      
+      this.objectFactory = new MockStatefulObjectFactory(this);
+      this.passivationManager = new MockPassivationManager();
+      this.children = new HashSet<MockBeanContainer>();
+      
+      MockRegistry.put(this.containerName, this);
+   }
+   
+   public void start() throws Exception
+   {
+      StatefulCacheFactory<MockBeanContext> cacheFactory = cacheFactoryRegistry.getCacheFactory(cacheFactoryName);
+      cache = cacheFactory.createCache(containerName, objectFactory, passivationManager, cacheConfig);
+      cache.start();
+   }
+   
+   public void stop()
+   {
+      cache.stop();
+      MockRegistry.remove(containerName);
+   }
+   
+   public String getName()
+   {
+      return containerName;
+   }
+   
+   public Cache<MockBeanContext> getCache()
+   {
+      return cache;
+   }
+   
+   public Set<MockBeanContainer> getChildren()
+   {
+      return children;
+   }
+   
+   public void addChild(MockBeanContainer child)
+   {
+      children.add(child);
+   }
+   
+   public boolean hasChild(MockBeanContainer child)
+   {
+      return children.contains(child);
+   }
+   
+   public MockXPC getXPC()
+   {
+      return xpc;
+   }
+
+   public void setXPC(MockXPC xpc)
+   {
+      this.xpc = xpc;
+   }
+
+   public StatefulObjectFactory<MockBeanContext> getStatefulObjectFactory()
+   {
+      return objectFactory;
+   }
+
+   public PassivationManager<MockBeanContext> getPassivationManager()
+   {
+      return passivationManager;
+   }
+   
+   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockBeanContext.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockBeanContext.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockBeanContext.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,208 @@
+/*
+ * 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.ejb3.test.cache.mock;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.jboss.ejb3.cache.Cache;
+import org.jboss.ejb3.cache.SerializationGroup;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockBeanContext extends MockCacheItem
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 3209950231614290498L;
+
+   private final String containerName;
+   
+   private MockXPC xpc;
+   private MockEntity entity;
+   
+   private int preReplicateCount;
+   private int prePassivateCount;
+   private int postReplicateCount;
+   private int postActivateCount;
+   private Map<String, Object> children;
+   
+   public MockBeanContext(String containerName)
+   {
+      super(createId());
+      this.containerName = containerName;
+      this.children = new HashMap<String, Object>();
+   }
+   
+   public MockBeanContainer getContainer()
+   {
+      return (MockBeanContainer) MockRegistry.get(containerName);
+   }
+   
+   public void addChild(MockBeanContext child)
+   {
+      // Just store the id; tests get the id from getChild() and
+      // then call get(id) on the child container's cache.
+      // This simulates how an internal call via a nested bean's 
+      // proxy would work
+      children.put(child.containerName, child.getId());
+   }
+   
+   public Object getChild(String containerName)
+   {
+      return children.get(containerName);
+   }
+   
+   public void remove()
+   {
+      if (xpc != null)
+      {
+         boolean closeIt = true;
+         Cache<MockBeanContext> cache = getContainer().getCache();
+         if (cache.isGroupAware())
+         {
+            SerializationGroup<MockBeanContext> group = cache.getGroup(this);
+            if (group != null)
+            {
+               for(Iterator<MockBeanContext> it = group.iterator(); it.hasNext();)
+               {
+                  MockBeanContext ctx = it.next();
+                  if (ctx != this)
+                  {
+                     if (xpc.equals(ctx.getXPC()))
+                     {
+                        closeIt = false;
+                        break;
+                     }
+                  }
+               }
+            }
+            
+            if (closeIt)
+               xpc.close();
+         }
+      }
+   }
+   
+   public int getPreReplicateCount()
+   {
+      return preReplicateCount;
+   }
+   public int getPrePassivateCount()
+   {
+      return prePassivateCount;
+   }
+   public int getPostReplicateCount()
+   {
+      return postReplicateCount;
+   }
+   public int getPostActivateCount()
+   {
+      return postActivateCount;
+   }
+
+   public MockXPC getXPC()
+   {
+      return xpc;
+   }
+
+   public void setXPC(MockXPC sharedObject)
+   {
+      this.xpc = sharedObject;
+   }
+   
+   public void preReplicate()
+   {
+      preReplicateCount++;
+      synchronized(this)
+      {
+         notifyAll();
+      }
+   }
+   
+   public void postReplicate()
+   {
+      postReplicateCount++;
+      synchronized(this)
+      {
+         notifyAll();
+      }
+   }
+   
+   public void prePassivate()
+   {
+      prePassivateCount++;
+      synchronized(this)
+      {
+         notifyAll();
+      }
+   }
+   
+   public void postActivate()
+   {
+      postActivateCount++;
+      synchronized(this)
+      {
+         notifyAll();
+      }
+   }
+   
+   // -- Underlying bean operations
+   
+   public void createEntity()
+   {
+      entity = xpc.createEntity();
+      setModified(true);
+   }
+   
+   public MockEntity getEntity()
+   {
+      MockEntity was = entity;
+      entity = xpc.getEntity();
+      if (was != entity)
+         setModified(true);
+      return entity;
+   }
+   
+   public void removeEntity()
+   {
+      xpc.removeEntity();
+      if (entity != null)
+      {
+         entity = null;
+         setModified(true);
+      }
+   }
+   
+   public void invokeNonModifying()
+   {
+      // no-op
+   }
+   
+   public void invokeModifying()
+   {
+       setModified(true);
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockCacheConfig.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockCacheConfig.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockCacheConfig.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,110 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007, 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.ejb3.test.cache.mock;
+
+import java.lang.annotation.Annotation;
+
+import org.jboss.ejb3.annotation.CacheConfig;
+
+/**
+ * Implementation of CacheConfig Annotation
+ * 
+ * @author Brian Stansberry
+ * @version $Revision: $
+ */
+public class MockCacheConfig implements CacheConfig
+{
+   // Instance Members
+
+   private String name = "";
+
+   private int maxSize = CacheConfig.DEFAULT_NONCLUSTERED_MAX_SIZE;
+
+   private long idleTimeoutSeconds = CacheConfig.DEFAULT_IDLE_TIMEOUT_SECONDS;
+
+   private long removalTimeoutSeconds = CacheConfig.DEFAULT_REMOVAL_TIMEOUT_SECONDS;
+
+   private boolean replicationIsPassivation = CacheConfig.DEFAULT_REPL_IS_PASV;
+
+   // Constructor
+
+   public MockCacheConfig()
+   {
+   }
+
+   // Accessors / Mutators
+
+   public String name()
+   {
+      return name;
+   }
+
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+
+   public int maxSize()
+   {
+      return maxSize;
+   }
+
+   public void setMaxSize(int maxSize)
+   {
+      this.maxSize = maxSize;
+   }
+
+   public long idleTimeoutSeconds()
+   {
+      return idleTimeoutSeconds;
+   }
+
+   public void setIdleTimeoutSeconds(long idleTimeoutSeconds)
+   {
+      this.idleTimeoutSeconds = idleTimeoutSeconds;
+   }
+
+   public long removalTimeoutSeconds()
+   {
+      return removalTimeoutSeconds;
+   }
+
+   public void setRemovalTimeoutSeconds(long removalTimeoutSeconds)
+   {
+      this.removalTimeoutSeconds = removalTimeoutSeconds;
+   }
+
+   public boolean replicationIsPassivation()
+   {
+      return replicationIsPassivation;
+   }
+
+   public void setReplicationIsPassivation(boolean replicationIsPassivation)
+   {
+      this.replicationIsPassivation = replicationIsPassivation;
+   }
+
+   public Class<? extends Annotation> annotationType()
+   {
+      return CacheConfig.class;
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockCacheItem.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockCacheItem.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockCacheItem.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,56 @@
+/*
+ * 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.ejb3.test.cache.mock;
+
+import org.jboss.ejb3.cache.CacheItem;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockCacheItem 
+   extends MockIdentifiable
+   implements CacheItem
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 7660507283782503571L;
+   
+   private boolean modified;
+
+   public MockCacheItem(long id)
+   {
+      super(id);
+   }
+   
+   public boolean isModified()
+   {
+      boolean result = modified;
+      modified = false;
+      return result;
+   }
+
+   public void setModified(boolean modified)
+   {
+      this.modified = modified;
+   }   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockEjb3System.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockEjb3System.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockEjb3System.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,187 @@
+/*
+ * 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.ejb3.test.cache.mock;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.ejb3.cache.StatefulCacheFactory;
+import org.jboss.ejb3.cache.StatefulCacheFactoryRegistry;
+import org.jboss.ejb3.cache.impl.factory.GroupAwareCacheFactory;
+import org.jboss.ejb3.cache.impl.factory.NonClusteredIntegratedObjectStoreSource;
+import org.jboss.ejb3.cache.impl.factory.NonPassivatingCacheFactory;
+import org.jboss.ejb3.cache.impl.factory.PassivationExpirationCoordinatorImpl;
+import org.jboss.ejb3.cache.spi.IntegratedObjectStoreSource;
+import org.jboss.ejb3.cache.spi.PassivationExpirationCoordinator;
+import org.jboss.ejb3.cache.spi.impl.AbstractStatefulCacheFactory;
+import org.jboss.ejb3.test.cache.mock.tm.MockTransactionManager;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockEjb3System
+{
+   private StatefulCacheFactoryRegistry<MockBeanContext> cacheFactoryRegistry;
+   private TransactionManager tm;
+   private PassivationExpirationCoordinator coordinator;
+   
+   public MockEjb3System(boolean useCoordinator, CacheType cacheType)
+   {
+      this(MockTransactionManager.getInstance(), useCoordinator, cacheType);
+   }
+   
+   public MockEjb3System(TransactionManager tm, 
+                         boolean useCoordinator,
+                         CacheType cacheType)
+   {
+      this(tm, useCoordinator, new CacheType[] { cacheType });
+   }
+   
+   public MockEjb3System(TransactionManager tm, 
+                         boolean useCoordinator,
+                         CacheType[] availableTypes)
+   {
+      this.tm = tm;
+      if (useCoordinator)
+         coordinator = new PassivationExpirationCoordinatorImpl();
+      
+      cacheFactoryRegistry = new StatefulCacheFactoryRegistry<MockBeanContext>();
+      if (availableTypes != null)
+      {
+         Map<String, StatefulCacheFactory<MockBeanContext>> factories = 
+            new HashMap<String, StatefulCacheFactory<MockBeanContext>>();
+         for (CacheType type : availableTypes)
+         {
+            factories.put(type.mapKey(), buildCacheFactory(type));
+         }
+         cacheFactoryRegistry.setFactories(factories);
+      }
+   }
+
+   public StatefulCacheFactoryRegistry<MockBeanContext> getCacheFactoryRegistry()
+   {
+      return cacheFactoryRegistry;
+   }
+
+   public TransactionManager getTransactionManager()
+   {
+      return tm;
+   }
+
+   public PassivationExpirationCoordinator getCoordinator()
+   {
+      return coordinator;
+   }
+   
+   public MockBeanContainer getMockBeanContainer(String containerName)
+   {
+      MockBeanContainer container = (MockBeanContainer) MockRegistry.get(containerName);
+      if (container == null)
+         throw new IllegalArgumentException("Container " + containerName + " not found");
+      return container;
+   }
+   
+   public MockBeanContainer deployBeanContainer(String containerName,
+                                                String parentContainerName,
+                                                CacheType cacheType) throws Exception
+   {
+      return deployBeanContainer(containerName, parentContainerName, cacheType, new MockCacheConfig(), null, true);
+   }
+   
+   public MockBeanContainer deployBeanContainer(String containerName,
+                                                String parentContainerName,
+                                                CacheType cacheType,
+                                                MockCacheConfig cacheConfig,
+                                                MockXPC xpc) throws Exception
+   {
+      return deployBeanContainer(containerName, parentContainerName, cacheType, cacheConfig, xpc, true);
+   }
+   
+   public MockBeanContainer deployBeanContainer(String containerName,
+                                                String parentContainerName,
+                                                CacheType cacheType,
+                                                MockCacheConfig cacheConfig,
+                                                MockXPC xpc,
+                                                boolean start) throws Exception
+   {
+      MockBeanContainer parent = (parentContainerName == null) ? null : getMockBeanContainer(parentContainerName);
+      MockBeanContainer container = new MockBeanContainer(containerName, cacheType.mapKey(), cacheFactoryRegistry, cacheConfig);
+      container.setXPC(xpc);
+      if (parent != null)
+         parent.addChild(container);
+      if (start)
+         container.start();
+      return container;
+   }
+   
+   protected StatefulCacheFactory<MockBeanContext> buildCacheFactory(CacheType type)
+   {
+      AbstractStatefulCacheFactory<MockBeanContext> factory = null;
+      switch(type) {
+         case NON_PASSIVATING:
+            factory = buildNonPassivatingCacheFactory();
+            break;
+         case SIMPLE:
+            factory = buildSimpleCacheFactory();
+            break;
+         case DISTRIBUTED:
+            factory = buildDistributedCacheFactory();
+            break;
+         default:
+            throw new IllegalArgumentException("Unknown type " + type);
+      }
+      
+      factory.setTransactionManager(tm);
+      factory.setPassivationExpirationCoordinator(coordinator);
+      // Process passivation/expiration as quickly as possible so tests run fast
+      factory.setDefaultPassivationExpirationInterval(1);
+      
+      return factory;
+   }
+   
+   private AbstractStatefulCacheFactory<MockBeanContext> buildNonPassivatingCacheFactory()
+   {
+      return new NonPassivatingCacheFactory<MockBeanContext>();
+   }
+   
+   private AbstractStatefulCacheFactory<MockBeanContext> buildSimpleCacheFactory()
+   {
+      NonClusteredIntegratedObjectStoreSource<MockBeanContext> source = 
+         new NonClusteredIntegratedObjectStoreSource<MockBeanContext>();
+      return new GroupAwareCacheFactory<MockBeanContext>(source);
+   }
+   
+   private AbstractStatefulCacheFactory<MockBeanContext> buildDistributedCacheFactory()
+   {
+     return new GroupAwareCacheFactory<MockBeanContext>(getDistributedStoreSource());
+   }
+   
+   protected IntegratedObjectStoreSource<MockBeanContext> getDistributedStoreSource()
+   {
+      throw new UnsupportedOperationException("Distributed caching not supported");
+   }
+   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockEntity.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockEntity.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockEntity.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,36 @@
+/*
+ * 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.ejb3.test.cache.mock;
+
+import java.io.Serializable;
+
+/**
+ * A SharedObject.
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class MockEntity implements Serializable
+{
+   private static final long serialVersionUID = 1L;
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockIdentifiable.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockIdentifiable.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockIdentifiable.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2007, 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.ejb3.test.cache.mock;
+
+import java.io.Serializable;
+
+import org.jboss.ejb3.cache.Identifiable;
+
+/**
+ * Comment
+ *
+ * @author <a href="mailto:carlo.dewolf at jboss.com">Carlo de Wolf</a>
+ * @version $Revision: $
+ */
+public class MockIdentifiable implements Identifiable, Serializable
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 828205583403324513L;
+   
+   private static volatile long currentId = 0;
+   
+   public static long createId()
+   {
+      return ++currentId;
+   }
+   
+   private long id;
+   
+   public MockIdentifiable(long id)
+   {
+      this.id = id;
+   }
+   
+   public Object getId()
+   {
+      return id;
+   }
+
+   @Override
+   public String toString()
+   {
+      return super.toString() + "{id=" + id + "}";
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockPassivationManager.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockPassivationManager.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockPassivationManager.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,83 @@
+/*
+ * 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.ejb3.test.cache.mock;
+
+import org.jboss.ejb3.cache.PassivationManager;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockPassivationManager 
+   implements PassivationManager<MockBeanContext>
+{
+   private int preReplicateCount;
+   private int prePassivateCount;
+   private int postReplicateCount;
+   private int postActivateCount;
+   
+   public void postActivate(MockBeanContext ctx)
+   {
+      ctx.postActivate();
+      postActivateCount++;
+   }
+
+   public void postReplicate(MockBeanContext ctx)
+   {
+      ctx.postReplicate();
+      postReplicateCount++;
+   }
+
+   public void prePassivate(MockBeanContext ctx)
+   {
+      ctx.prePassivate();
+      prePassivateCount++;
+   }
+
+   public void preReplicate(MockBeanContext ctx)
+   {
+      ctx.preReplicate();
+      preReplicateCount++;
+   }
+
+   public int getPreReplicateCount()
+   {
+      return preReplicateCount;
+   }
+
+   public int getPrePassivateCount()
+   {
+      return prePassivateCount;
+   }
+
+   public int getPostReplicateCount()
+   {
+      return postReplicateCount;
+   }
+
+   public int getPostActivateCount()
+   {
+      return postActivateCount;
+   }
+
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockRegistry.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockRegistry.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockRegistry.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,91 @@
+/*
+ * 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.ejb3.test.cache.mock;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author Brian Stansberry
+ */
+public class MockRegistry
+{
+   private static final Map<Object, Object> registry = new ConcurrentHashMap<Object, Object>();
+   
+   public static Object put(Object key, Object value)
+   {
+      return registry.put(new RegistryKey(key), value);
+   }
+   
+   public static Object get(Object key)
+   {
+      return registry.get(new RegistryKey(key));
+   }
+   
+   public static Object remove(Object key)
+   {
+      return registry.remove(new RegistryKey(key));
+   }
+   
+   public static void clear()
+   {
+      registry.clear();
+   }
+   
+   private static class RegistryKey
+   {
+      private ClassLoader cl;
+      private Object key;
+      
+      RegistryKey(Object key)
+      {
+         this.key = key;
+         this.cl = Thread.currentThread().getContextClassLoader();
+      }
+
+      @Override
+      public boolean equals(Object obj)
+      {
+         if (this == obj)
+            return true;
+         
+         if (obj instanceof RegistryKey)
+         {
+            RegistryKey other = (RegistryKey) obj;
+            return (cl.equals(other.cl) && key.equals(other.key));
+         }
+         return false;
+      }
+
+      @Override
+      public int hashCode()
+      {
+         int result = 19;
+         result = 51 * result + cl.hashCode();
+         result = 51 * result + key.hashCode();
+         return result;
+      }
+      
+      
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockStatefulObjectFactory.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockStatefulObjectFactory.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockStatefulObjectFactory.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,88 @@
+/*
+ * 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.ejb3.test.cache.mock;
+
+import org.jboss.ejb3.cache.StatefulObjectFactory;
+
+
+/**
+ * @author Brian Stansberry
+ */
+public class MockStatefulObjectFactory 
+   implements StatefulObjectFactory<MockBeanContext>
+{
+   private final MockBeanContainer container;
+   
+   private int creationCount;
+   private int groupCreationCount;
+   private int destroyCount;
+   
+   public MockStatefulObjectFactory(MockBeanContainer container)
+   {
+      this.container = container;
+   }
+   
+   public MockBeanContext create(Class[] initTypes, Object[] initValues)
+   {
+      MockBeanContext ctx = new MockBeanContext(container.getName());
+      ctx.setXPC(container.getXPC());
+      
+      // Here we mock creating nested beans
+      for (MockBeanContainer childContainer : container.getChildren())
+      {
+         ctx.addChild(childContainer.getCache().create(null, null));
+      }
+      
+      creationCount++;
+      return ctx;
+   }
+
+   public void destroy(MockBeanContext ctx)
+   {
+      ctx.remove();
+      destroyCount++;
+   }
+
+
+
+   public MockBeanContainer getContainer()
+   {
+      return container;
+   }
+
+   public int getCreationCount()
+   {
+      return creationCount;
+   }
+
+   public int getGroupCreationCount()
+   {
+      return groupCreationCount;
+   }
+
+   public int getDestroyCount()
+   {
+      return destroyCount;
+   }
+   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockXPC.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockXPC.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/MockXPC.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,70 @@
+/*
+ * 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.ejb3.test.cache.mock;
+
+import java.io.Serializable;
+
+/**
+ * A mock extended PersistenceContext.
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class MockXPC implements Serializable
+{
+   private static final long serialVersionUID = 1L;
+   
+   private boolean closed = false;
+   private MockEntity entity;
+   
+   public MockEntity createEntity()
+   {
+      if (entity != null)
+         throw new IllegalStateException("entity already created");
+      entity = new MockEntity();
+      return entity;
+   }
+   
+   public MockEntity getEntity()
+   {
+      return entity;
+   }
+   
+   public void removeEntity()
+   {
+      if (entity == null)
+         throw new IllegalStateException("no entity to remove");
+      entity = null;
+   }
+   
+   public boolean isClosed()
+   {
+      return closed;
+   }
+   
+   public void close()
+   {
+      closed = true;
+      entity = null;
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/tm/MockTransaction.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/tm/MockTransaction.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/tm/MockTransaction.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,142 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.jboss.ejb3.test.cache.mock.tm;
+
+import java.util.LinkedList;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.xa.XAResource;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Mock Transaction implementation that works with DualNodeTransactionManagerImpl.
+ *
+ * @author Brian Stansberry
+ */
+public class MockTransaction implements Transaction
+{
+   private static final Logger log = Logger.getLogger(MockTransaction.class);
+
+   private int status;
+
+   private LinkedList<Synchronization> synchronizations;
+
+   private final MockTransactionManager jtaTransactionManager;
+
+   public MockTransaction(MockTransactionManager jtaTransactionManager)
+   {
+      this.jtaTransactionManager = jtaTransactionManager;
+      this.status = Status.STATUS_ACTIVE;
+   }
+
+   public int getStatus()
+   {
+      return status;
+   }
+
+   public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+         IllegalStateException, SystemException
+   {
+
+      if (status == Status.STATUS_MARKED_ROLLBACK)
+      {
+         log.trace("on commit, status was marked for rollback-only");
+         rollback();
+      }
+      else
+      {
+         status = Status.STATUS_PREPARING;
+
+         for (int i = 0; i < synchronizations.size(); i++)
+         {
+            Synchronization s = (Synchronization) synchronizations.get(i);
+            s.beforeCompletion();
+         }
+
+         status = Status.STATUS_COMMITTING;
+
+         status = Status.STATUS_COMMITTED;
+
+         for (int i = 0; i < synchronizations.size(); i++)
+         {
+            Synchronization s = (Synchronization) synchronizations.get(i);
+            s.afterCompletion(status);
+         }
+
+         //status = Status.STATUS_NO_TRANSACTION;
+         jtaTransactionManager.endCurrent(this);
+      }
+   }
+
+   public void rollback() throws IllegalStateException, SystemException
+   {
+      status = Status.STATUS_ROLLEDBACK;
+
+      if (synchronizations != null)
+      {
+         for (int i = 0; i < synchronizations.size(); i++)
+         {
+            Synchronization s = (Synchronization) synchronizations.get(i);
+            s.afterCompletion(status);
+         }
+      }
+
+      //status = Status.STATUS_NO_TRANSACTION;
+      jtaTransactionManager.endCurrent(this);
+   }
+
+   public void setRollbackOnly() throws IllegalStateException, SystemException
+   {
+      status = Status.STATUS_MARKED_ROLLBACK;
+   }
+
+   public void registerSynchronization(Synchronization synchronization) throws RollbackException,
+         IllegalStateException, SystemException
+   {
+      // todo : find the spec-allowable statuses during which synch can be registered...
+      if (synchronizations == null)
+      {
+         synchronizations = new LinkedList<Synchronization>();
+      }
+      synchronizations.add(synchronization);
+   }
+
+   public boolean enlistResource(XAResource xaResource) throws RollbackException, IllegalStateException,
+         SystemException
+   {
+      return false;
+   }
+
+   public boolean delistResource(XAResource xaResource, int i) throws IllegalStateException, SystemException
+   {
+      return false;
+   }
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/tm/MockTransactionManager.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/tm/MockTransactionManager.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/cache/mock/tm/MockTransactionManager.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,183 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program 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 distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.jboss.ejb3.test.cache.mock.tm;
+
+import java.util.Hashtable;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Variant of SimpleJtaTransactionManagerImpl that doesn't use a VM-singleton,
+ * but rather a set of impls keyed by a node id.
+ *
+ * @author Brian Stansberry
+ */
+public class MockTransactionManager implements TransactionManager 
+{
+   public static final String DEFAULT = "default";
+   
+   private static final Logger log = Logger.getLogger(MockTransactionManager.class);
+   
+   private static final Hashtable<String, MockTransactionManager> INSTANCES = new Hashtable<String, MockTransactionManager>();
+
+   private ThreadLocal<MockTransaction> currentTransaction = new ThreadLocal<MockTransaction>();
+   private String nodeId;
+
+   public synchronized static MockTransactionManager getInstance()
+   {
+      return getInstance(DEFAULT);
+   }
+   
+   public synchronized static MockTransactionManager getInstance(String nodeId)
+   {
+      MockTransactionManager tm = (MockTransactionManager) INSTANCES.get(nodeId);
+      if (tm == null)
+      {
+         tm = new MockTransactionManager(nodeId);
+         INSTANCES.put(nodeId, tm);
+      }
+      return tm;
+   }
+
+   public synchronized static void cleanupTransactions()
+   {
+      for (MockTransactionManager tm : INSTANCES.values())
+      {
+         try
+         {
+            tm.currentTransaction.remove();
+         }
+         catch (Exception e)
+         {
+            log.error("Exception cleaning up TransactionManager " + tm);
+         }
+      }
+   }
+
+   public synchronized static void cleanupTransactionManagers()
+   {
+      INSTANCES.clear();
+   }
+
+   private MockTransactionManager(String nodeId)
+   {
+      this.nodeId = nodeId;
+   }
+
+   public int getStatus() throws SystemException
+   {
+      return currentTransaction.get() == null ? Status.STATUS_NO_TRANSACTION : currentTransaction.get().getStatus();
+   }
+
+   public Transaction getTransaction() throws SystemException
+   {
+      return currentTransaction.get();
+   }
+
+   public MockTransaction getCurrentTransaction()
+   {
+      return currentTransaction.get();
+   }
+
+   public void begin() throws NotSupportedException, SystemException
+   {
+      currentTransaction.set(new MockTransaction(this));
+   }
+
+   public Transaction suspend() throws SystemException
+   {
+      log
+            .trace(nodeId + ": Suspending " + currentTransaction.get() + " for thread "
+                  + Thread.currentThread().getName());
+      MockTransaction suspended = currentTransaction.get();
+      currentTransaction.set(null);
+      return suspended;
+   }
+
+   public void resume(Transaction transaction) throws InvalidTransactionException, IllegalStateException,
+         SystemException
+   {
+      currentTransaction.set((MockTransaction) transaction);
+      log.trace(nodeId + ": Resumed " + transaction + " for thread " + Thread.currentThread().getName());
+   }
+
+   public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+         SecurityException, IllegalStateException, SystemException
+   {
+      if (currentTransaction.get() == null)
+      {
+         throw new IllegalStateException("no current transaction to commit");
+      }
+      currentTransaction.get().commit();
+   }
+
+   public void rollback() throws IllegalStateException, SecurityException, SystemException
+   {
+      if (currentTransaction.get() == null)
+      {
+         throw new IllegalStateException("no current transaction");
+      }
+      currentTransaction.get().rollback();
+   }
+
+   public void setRollbackOnly() throws IllegalStateException, SystemException
+   {
+      if (currentTransaction.get() == null)
+      {
+         throw new IllegalStateException("no current transaction");
+      }
+      currentTransaction.get().setRollbackOnly();
+   }
+
+   public void setTransactionTimeout(int i) throws SystemException
+   {
+   }
+
+   void endCurrent(MockTransaction transaction)
+   {
+      if (transaction == currentTransaction.get())
+      {
+         currentTransaction.set(null);
+      }
+   }
+
+   public String toString()
+   {
+      StringBuffer sb = new StringBuffer(getClass().getName());
+      sb.append("[nodeId=");
+      sb.append(nodeId);
+      sb.append("]");
+      return sb.toString();
+   }
+}

Modified: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/GroupedPassivatingUnitTestCase.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/GroupedPassivatingUnitTestCase.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/GroupedPassivatingUnitTestCase.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -21,17 +21,14 @@
  */
 package org.jboss.ejb3.test.distributed;
 
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-
 import junit.framework.TestCase;
 
-import org.jboss.ejb3.cache.PassivationManager;
-import org.jboss.ejb3.cache.StatefulObjectFactory;
-import org.jboss.ejb3.cache.grouped.SerializationGroup;
-import org.jboss.ejb3.cache.impl.SerializationGroupContainer;
-import org.jboss.ejb3.cache.impl.SimplePassivatingCache2;
+import org.jboss.ejb3.test.cache.mock.CacheType;
+import org.jboss.ejb3.test.cache.mock.MockBeanContainer;
+import org.jboss.ejb3.test.cache.mock.MockBeanContext;
+import org.jboss.ejb3.test.cache.mock.MockCacheConfig;
+import org.jboss.ejb3.test.cache.mock.MockPassivationManager;
+import org.jboss.ejb3.test.cache.mock.MockXPC;
 import org.jboss.logging.Logger;
 
 /**
@@ -56,76 +53,72 @@
       }
    }
    
-   public void test1()
+   public void testSimpleGroupPassivation() throws Exception
    {      
-      Map<Object, Object> localJBC = new HashMap<Object, Object>();
-      Map<Object, Object> remoteJBC = new HashMap<Object, Object>();
-      SerializationGroupContainer container = new SerializationGroupContainer();
-      StatefulObjectFactory<SerializationGroup> factory = container;
-      PassivationManager<SerializationGroup> passivationManager = container;
-      MockJBCIntegratedObjectStore<SerializationGroup> store = new MockJBCIntegratedObjectStore<SerializationGroup>(localJBC, remoteJBC);
-      SimplePassivatingCache2<SerializationGroup> groupCache = new SimplePassivatingCache2<SerializationGroup>(factory, passivationManager, store);
-      MockBeanContainer container1 = new MockBeanContainer("MockBeanContainer1", 1, groupCache, localJBC, remoteJBC);
-      MockBeanContainer container2 = new MockBeanContainer("MockBeanContainer2", 10, groupCache, localJBC, remoteJBC);
+      MockCluster cluster = new MockCluster(false);
+      MockClusterMember node0 = cluster.getNode0();
+      MockCacheConfig cacheConfig = new MockCacheConfig();
+      cacheConfig.setIdleTimeoutSeconds(1);
+      MockXPC sharedXPC = new MockXPC();
+      MockBeanContainer container1 = node0.deployBeanContainer("MockBeanContainer1", null, CacheType.DISTRIBUTED, cacheConfig, sharedXPC);
+      MockBeanContainer container2 = node0.deployBeanContainer("MockBeanContainer2", "MockBeanContainer1", CacheType.DISTRIBUTED, cacheConfig, sharedXPC);
       
+      cluster.getNode0().setTCCL();
       try
       {
-         groupCache.start();
-         container1.start();
-         container2.start();
-         
-         Object shared = new SharedObject();
+         Object key1 = container1.getCache().create(null, null).getId();
          MockBeanContext firstCtx1;
-         MockBeanContext ctx1 = firstCtx1 = container1.getCache().create(null, null);
-         Object key1 = ctx1.getId();
-         // We assign the shared object here as if it were an XPC injected 
-         // during SFSB creation
-         ctx1.shared = shared;
-         MockBeanContext ctx2 = container2.getCache().create(null, null);
-         Object key2 = ctx2.getId();
-         ctx2.shared = shared;
+         MockBeanContext ctx1 = firstCtx1 = container1.getCache().get(key1);
          
-         // TODO: how will passivation groups be created?
-         SerializationGroup group = groupCache.create(null, null);
-         container1.getCache().setGroup(ctx1, group);
-         container2.getCache().setGroup(ctx2, group);
-         // TODO: currently we need to release the group
-         // BES -- not any more
-   //      groupCache.release(group);
+         Object key2 = ctx1.getChild(container2.getName());
+         MockBeanContext ctx2 = container2.getCache().get(key2);
          
-         container1.getCache().release(ctx1);
-         container2.getCache().release(ctx2);
+         assertNotNull(ctx1.getXPC());
+         assertEquals(ctx1.getXPC(), ctx2.getXPC());
          
-         sleep(4000);
+         container2.getCache().finished(ctx2);
+         container1.getCache().finished(ctx1);
          
-         assertEquals("ctx1 should have been passivated", 1, container1.passivations);
-         assertEquals("ctx2 should have been passivated", 1, container2.passivations);
+         sleep(2100);
          
+         MockPassivationManager pass1 = (MockPassivationManager) container1.getPassivationManager();
+         MockPassivationManager pass2 = (MockPassivationManager) container2.getPassivationManager();
+         
+         assertEquals("ctx1 should have been passivated", 1, pass1.getPrePassivateCount());
+         assertEquals("ctx2 should have been passivated", 1, pass2.getPrePassivateCount());
+         
          ctx2 = container2.getCache().get(key2);
          
          log.info("ctx2 = " + ctx2);
          assertNotNull(ctx2);
          
-         assertEquals("ctx2 should have been postReplicated", 1, container2.postReplications);        
-         assertEquals("ctx2 should have been activated", 1, container2.activations);
+         assertEquals("ctx2 should not have been postReplicated", 0, pass2.getPostReplicateCount());        
+         assertEquals("ctx2 should have been activated", 1, pass2.getPostActivateCount());
          
          ctx1 = container1.getCache().get(key1);
          
          log.info("ctx1 = " + ctx1);
          assertNotNull(ctx1);
          
-         assertEquals("ctx1 should have been postReplicated", 1, container1.postReplications);        
-         assertEquals("ctx1 should have been activated", 1, container1.activations);
+         assertEquals("ctx1 should not have been postReplicated", 0, pass1.getPostReplicateCount());        
+         assertEquals("ctx1 should have been activated", 1, pass1.getPostActivateCount());
          
          assertTrue("ctx1 must be different than firstCtx1 (else no passivation has taken place)", ctx1 != firstCtx1);
          
-         assertEquals(ctx1.shared, ctx2.shared);
+         assertNotNull(ctx1.getXPC());
+         assertEquals(ctx1.getXPC(), ctx2.getXPC());
       }
       finally
       {
-         container1.stop();
-         container2.stop();
-         groupCache.stop();
+         try
+         {
+            container1.stop();
+            container2.stop();
+         }
+         finally
+         {
+            cluster.getNode0().restoreTCCL();
+         }
       }
    }
 }

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockBeanContainer.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockBeanContainer.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockBeanContainer.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,137 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.test.distributed;
-
-import java.util.Map;
-
-import org.jboss.ejb3.cache.PassivatingCache;
-import org.jboss.ejb3.cache.PassivationManager;
-import org.jboss.ejb3.cache.StatefulObjectFactory;
-import org.jboss.ejb3.cache.grouped.GroupedPassivatingCache;
-import org.jboss.ejb3.cache.grouped.SerializationGroup;
-import org.jboss.ejb3.cache.impl.GroupedPassivatingCacheImpl2;
-import org.jboss.ejb3.cache.impl.SerializationGroupMemberImpl;
-import org.jboss.logging.Logger;
-
-/**
- * Comment
- *
- * @author Brian Stansberry
- * @version $Revision: 65920 $
- */
-public class MockBeanContainer implements StatefulObjectFactory<MockBeanContext>, PassivationManager<MockBeanContext>
-{
-   private static final Logger log = Logger.getLogger(MockBeanContainer.class);
-   
-   protected int activations = 0;
-   protected int passivations = 0;
-   protected int preReplications  = 0;
-   protected int postReplications = 0;
-   
-   private GroupedPassivatingCache<MockBeanContext> cache;
-   
-   public MockBeanContainer(String name, int sessionTimeout, PassivatingCache<SerializationGroup> groupCache, Map<Object, Object> localJBC, Map<Object, Object> remoteJBC)
-   {
-      MockJBCIntegratedObjectStore<SerializationGroupMemberImpl<MockBeanContext>> store = new MockJBCIntegratedObjectStore<SerializationGroupMemberImpl<MockBeanContext>>(localJBC, remoteJBC);
-      store.setIdleTimeSeconds(sessionTimeout);
-      store.setInterval(1);
-      this.cache = new GroupedPassivatingCacheImpl2<MockBeanContext>(this, this, store, groupCache);
-   }
-   
-   public MockBeanContext create(Class<?>[] initTypes, Object[] initValues)
-   {
-      return new MockBeanContext();
-   }
-   
-   public GroupedPassivatingCache<MockBeanContext> getCache()
-   {
-      return cache;
-   }
-   
-   public void destroy(MockBeanContext obj)
-   {
-   }
-
-   public void postActivate(MockBeanContext obj)
-   {
-      if(obj == null) throw new IllegalArgumentException("obj is null");
-      
-      log.info("postActivate " + obj);
-      activations++;
-      synchronized(this)
-      {
-         notifyAll();
-      }
-   }
-
-   public void prePassivate(MockBeanContext obj)
-   {
-      if(obj == null) throw new IllegalArgumentException("obj is null");
-      
-      log.info("prePassivate " + obj);
-      passivations++;
-      synchronized(this)
-      {
-         notifyAll();
-      }
-   }
-   
-   public boolean isClustered()
-   {
-      return true;
-   }
-   
-   public void postReplicate(MockBeanContext obj)
-   {
-      if(obj == null) throw new IllegalArgumentException("obj is null");
-      
-      log.info("postReplicate " + obj);
-      postReplications++;
-      synchronized(this)
-      {
-         notifyAll();
-      } 
-   }
-
-   public void preReplicate(MockBeanContext obj)
-   {
-      if(obj == null) throw new IllegalArgumentException("obj is null");
-      
-      log.info("preReplicate " + obj);
-      preReplications++;
-      synchronized(this)
-      {
-         notifyAll();
-      }
-   }
-   
-   public void start()
-   {
-      cache.start();
-   }
-   
-   public void stop()
-   {
-      cache.stop();
-   }
-   
-}

Deleted: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockBeanContext.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockBeanContext.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockBeanContext.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -1,79 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2007, Red Hat Middleware LLC, and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.test.distributed;
-
-import java.io.Serializable;
-
-import org.jboss.ejb3.cache.Cacheable;
-
-/**
- * Comment
- *
- * @author Brian Stansberry
- * @version $Revision: 65339 $
- */
-public class MockBeanContext implements Cacheable, Serializable
-{
-   private static final long serialVersionUID = 1L;
-
-   private static volatile long currentId = 100000;
-   
-   private long id;
-   
-   private boolean inUse;
-   private long lastUsed;
-   
-   public Object shared;
-   
-   public MockBeanContext()
-   {
-      this.id = ++currentId;
-   }
-   
-   public Object getId()
-   {
-      return id;
-   }
-
-   public boolean isInUse()
-   {
-      return inUse;
-   }
-
-   public void setInUse(boolean inUse)
-   {
-      this.inUse = inUse;
-      lastUsed = System.currentTimeMillis();
-   }
-
-   public long getLastUsed()
-   {
-      return lastUsed;
-   }
-
-   @Override
-   public String toString()
-   {
-      return super.toString() + "{id=" + id + "}";
-   }
-
-}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockCluster.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockCluster.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockCluster.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,117 @@
+/*
+ * 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.ejb3.test.distributed;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.ejb3.test.cache.mock.CacheType;
+import org.jboss.ejb3.test.cache.mock.MockBeanContainer;
+import org.jboss.ejb3.test.cache.mock.MockCacheConfig;
+import org.jboss.ejb3.test.cache.mock.MockXPC;
+import org.jboss.ejb3.test.cache.mock.tm.MockTransactionManager;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockCluster
+{
+   private TransactionManager tm0;
+   private TransactionManager tm1;
+   private UnmarshallingMap map0;
+   private UnmarshallingMap map1;
+   private MockClusterMember node0;
+   private MockClusterMember node1;
+   
+   public MockCluster(boolean useCoordinator)
+   {
+      this(MockTransactionManager.getInstance("node0"),
+           MockTransactionManager.getInstance("node1"), 
+           useCoordinator, CacheType.DISTRIBUTED);
+   }
+   
+   public MockCluster(TransactionManager tm0, TransactionManager tm1, boolean useCoordinator, CacheType cacheType)
+   {
+      this(tm0, tm1, useCoordinator, new CacheType[] { cacheType});
+   }
+   
+   public MockCluster(TransactionManager tm0, TransactionManager tm1, boolean useCoordinator, CacheType[] availableTypes)
+   {
+      this.tm0 = tm0;
+      this.tm1 = tm1;
+      
+      map0 = new UnmarshallingMap();
+      map1 = new UnmarshallingMap();
+      
+      node0 = new MockClusterMember(tm0, useCoordinator, availableTypes, map0, map1);
+      node1 = new MockClusterMember(tm1, useCoordinator, availableTypes, map1, map0);
+   }
+
+   public TransactionManager getTm0()
+   {
+      return tm0;
+   }
+
+   public TransactionManager getTm1()
+   {
+      return tm1;
+   }
+
+   public UnmarshallingMap getMap0()
+   {
+      return map0;
+   }
+
+   public UnmarshallingMap getMap1()
+   {
+      return map1;
+   }
+
+   public MockClusterMember getNode0()
+   {
+      return node0;
+   }
+
+   public MockClusterMember getNode1()
+   {
+      return node1;
+   }
+   
+   public MockBeanContainer[] deployBeanContainer(String containerName, String parentContainerName,
+         CacheType cacheType, MockCacheConfig cacheConfig, boolean useXPC) throws Exception
+   {
+      MockXPC xpc0 = useXPC ? new MockXPC() : null;
+      MockXPC xpc1 = useXPC ? new MockXPC() : null;
+      return deployBeanContainer(containerName, parentContainerName, cacheType, cacheConfig, xpc0, xpc1);
+   }
+   
+   public MockBeanContainer[] deployBeanContainer(String containerName, String parentContainerName,
+         CacheType cacheType, MockCacheConfig cacheConfig, MockXPC xpc0, MockXPC xpc1) throws Exception
+   {
+      MockBeanContainer[] result = new MockBeanContainer[2];
+      result[0] = node0.deployBeanContainer(containerName, parentContainerName, cacheType, cacheConfig, xpc0);
+      result[1] = node1.deployBeanContainer(containerName, parentContainerName, cacheType, cacheConfig, xpc1);
+      return result;
+   }
+   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockClusterMember.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockClusterMember.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockClusterMember.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,152 @@
+/*
+ * 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.ejb3.test.distributed;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.ejb3.cache.spi.IntegratedObjectStoreSource;
+import org.jboss.ejb3.test.cache.mock.CacheType;
+import org.jboss.ejb3.test.cache.mock.MockBeanContainer;
+import org.jboss.ejb3.test.cache.mock.MockBeanContext;
+import org.jboss.ejb3.test.cache.mock.MockCacheConfig;
+import org.jboss.ejb3.test.cache.mock.MockEjb3System;
+import org.jboss.ejb3.test.cache.mock.MockXPC;
+
+/**
+ * @author Brian Stansberry
+ */
+public class MockClusterMember extends MockEjb3System
+{
+   private UnmarshallingMap localDistributedCacheMember;
+   private UnmarshallingMap remoteDistributedCacheMember;
+   private ClassLoader localClassLoader;
+   
+   public MockClusterMember(TransactionManager tm, 
+                            boolean useCoordinator, 
+                            CacheType cacheType,
+                            UnmarshallingMap local,
+                            UnmarshallingMap remote)
+   {
+      this(tm, useCoordinator, new CacheType[] {cacheType}, local, remote);
+   }
+
+   public MockClusterMember(TransactionManager tm, 
+         boolean useCoordinator, 
+         CacheType[] availableTypes,
+         UnmarshallingMap local,
+         UnmarshallingMap remote)
+   {
+      super(tm, useCoordinator, availableTypes);
+      this.localDistributedCacheMember = local;
+      this.remoteDistributedCacheMember =remote;
+      
+      ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+      localClassLoader = new ClassLoader(tccl) {};
+      
+      // Kluge. Rebuild the distributed factory, as the superclass
+      // didn't have the maps available when it did it
+      for (CacheType type : availableTypes)
+      {
+         if (type == CacheType.DISTRIBUTED)
+            getCacheFactoryRegistry().addCacheFactory(type.mapKey(), buildCacheFactory(type));
+      }
+   }
+
+   public UnmarshallingMap getLocalDistributedCacheMember()
+   {
+      return localDistributedCacheMember;
+   }
+
+   public UnmarshallingMap getRemoteDistributedCacheMember()
+   {
+      return remoteDistributedCacheMember;
+   }
+
+   public ClassLoader getLocalClassLoader()
+   {
+      return localClassLoader;
+   }   
+   
+   public boolean setTCCL()
+   {
+      if (localClassLoader == Thread.currentThread().getContextClassLoader())
+         return false;
+      Thread.currentThread().setContextClassLoader(localClassLoader);
+      return true;
+   }
+   
+   public void restoreTCCL()
+   {
+      ClassLoader current = Thread.currentThread().getContextClassLoader();
+      if (current == localClassLoader)
+      {
+         Thread.currentThread().setContextClassLoader(localClassLoader.getParent());
+      }
+      else if (current != localClassLoader.getParent())
+      {
+         throw new IllegalStateException("Current TCCL is neither localClassLoader nor its parent");
+      }
+   }
+
+   @Override
+   protected IntegratedObjectStoreSource<MockBeanContext> getDistributedStoreSource()
+   {
+      return new MockIntegratedObjectStoreSource<MockBeanContext>(localDistributedCacheMember, 
+                                                                  remoteDistributedCacheMember);
+   }
+
+   @Override
+   public MockBeanContainer deployBeanContainer(String containerName, String parentContainerName,
+         CacheType cacheType, MockCacheConfig cacheConfig, MockXPC xpc) throws Exception
+   {
+      boolean tcclSet = setTCCL();
+      try
+      {
+         return super.deployBeanContainer(containerName, parentContainerName, cacheType, cacheConfig, xpc);
+      }
+      finally
+      {
+         if (tcclSet)
+            restoreTCCL();
+      }
+   }
+
+   @Override
+   public MockBeanContainer getMockBeanContainer(String containerName)
+   {
+      boolean tcclSet = setTCCL();
+      try
+      {
+         return super.getMockBeanContainer(containerName);
+      }
+      finally
+      {
+         if (tcclSet)
+            restoreTCCL();
+      }
+   }
+   
+   
+   
+   
+}

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockIntegratedObjectStoreSource.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockIntegratedObjectStoreSource.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockIntegratedObjectStoreSource.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,63 @@
+/*
+ * 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.ejb3.test.distributed;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.ejb3.annotation.CacheConfig;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.spi.IntegratedObjectStoreSource;
+import org.jboss.ejb3.cache.spi.PassivatingIntegratedObjectStore;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupImpl;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupMember;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockIntegratedObjectStoreSource<T extends CacheItem> 
+   implements IntegratedObjectStoreSource<T>
+{
+   private UnmarshallingMap localMap;
+   private UnmarshallingMap remoteMap;
+   
+   public MockIntegratedObjectStoreSource(UnmarshallingMap localMap, UnmarshallingMap remoteMap)
+   {
+      this.localMap = localMap;
+      this.remoteMap = remoteMap;
+   }
+   
+   public PassivatingIntegratedObjectStore<T, SerializationGroupImpl<T>>  createGroupIntegratedObjectStore(String containerName,
+         String cacheConfigName, CacheConfig cacheConfig, TransactionManager transactionManager)
+   {
+      String keyBase = "GroupCache-" + containerName;
+      return new MockJBCIntegratedObjectStore<T, SerializationGroupImpl<T>>(localMap, remoteMap, cacheConfig, keyBase, keyBase);
+   }
+
+   public PassivatingIntegratedObjectStore<T, SerializationGroupMember<T>>  createIntegratedObjectStore(String containerName, String cacheConfigName,
+         CacheConfig cacheConfig, TransactionManager transactionManager)
+   {
+      return new MockJBCIntegratedObjectStore<T, SerializationGroupMember<T>>(localMap, remoteMap, cacheConfig, containerName, containerName);
+   }
+
+}

Modified: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockJBCIntegratedObjectStore.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockJBCIntegratedObjectStore.java	2008-03-11 04:27:06 UTC (rev 70719)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/MockJBCIntegratedObjectStore.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -22,12 +22,9 @@
 
 package org.jboss.ejb3.test.distributed;
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.io.Serializable;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -36,12 +33,14 @@
 import java.util.SortedSet;
 import java.util.TreeSet;
 
-import org.jboss.ejb3.cache.Cacheable;
-import org.jboss.ejb3.cache.IntegratedObjectStore;
-import org.jboss.ejb3.cache.ItemInUseException;
-import org.jboss.ejb3.cache.PassivatingCache;
-import org.jboss.ejb3.cache.PassivatingIntegratedObjectStore;
-import org.jboss.ejb3.cache.impl.CacheableTimestamp;
+import org.jboss.ejb3.annotation.CacheConfig;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.spi.BackingCacheEntry;
+import org.jboss.ejb3.cache.spi.IntegratedObjectStore;
+import org.jboss.ejb3.cache.spi.PassivatingBackingCache;
+import org.jboss.ejb3.cache.spi.PassivatingIntegratedObjectStore;
+import org.jboss.ejb3.cache.spi.impl.CacheableTimestamp;
+import org.jboss.ejb3.cache.spi.impl.PassivationExpirationRunner;
 import org.jboss.logging.Logger;
 
 /**
@@ -51,54 +50,69 @@
  * @author Brian Stansberry
  * @version $Revision$
  */
-public class MockJBCIntegratedObjectStore<T extends Cacheable & Serializable> 
-     implements PassivatingIntegratedObjectStore<T>
+public class MockJBCIntegratedObjectStore<C extends CacheItem, T extends BackingCacheEntry<C>> 
+     implements PassivatingIntegratedObjectStore<C, T>
 {
    private static final Logger log = Logger.getLogger(MockJBCIntegratedObjectStore.class);
 
+   /**
+    * Qualifier used to scope our keys in the maps
+    */
+   private final Object keyBase;
+   
    /** 
     * Our in-VM "JBoss Cache" instance.
     */
-   private Map<Object, Object> localJBC;
+   private final UnmarshallingMap localJBC;
    /** 
     * A remote "JBoss Cache" instance. We only store byte[] values,
     * mocking the effect of replication.
     */
-   private Map<Object, Object> remoteJBC;
+   private final UnmarshallingMap remoteJBC;
    
    /**
     * Those keys in the mockJBC map that haven't been "passivated"
     */
-   private Set<Object> inMemory;
+   private final Set<Object> inMemory;
    
    /**
     * Those keys that have been updated locally but not copied to remoteJBC.
     */
    private Set<Object> dirty;
    
-   private Map<Object, Long> timestamps;
+   private final Map<Object, Long> timestamps;
 
    /** A mock transaction manager */
-   private ThreadLocal<Boolean> tm = new ThreadLocal<Boolean>();
+   private final ThreadLocal<Boolean> tm = new ThreadLocal<Boolean>();
    
    /**
     * Support callbacks when our MockEvictionRunner decides to
     * evict an entry.
     */
-   private PassivatingCache<T> owningCache;   
+   private PassivatingBackingCache<C, T> owningCache;   
    private int interval;
-   private int idleTimeSeconds;
-   private int expirationTimeSeconds;
+   private long idleTimeSeconds;
+   private long expirationTimeSeconds;
+   private int maxSize;
+   private PassivationExpirationRunner sessionTimeoutRunner;
+   private final String name;
+   private boolean stopped = true;
    
-   private SessionTimeoutRunner sessionTimeoutRunner;
-   
-   public MockJBCIntegratedObjectStore(Map<Object, Object> localCache, 
-                                       Map<Object, Object> remoteCache)
+   public MockJBCIntegratedObjectStore(UnmarshallingMap localCache, 
+                                       UnmarshallingMap remoteCache,
+                                       CacheConfig cacheConfig,
+                                       Object keyBase,
+                                       String name)
    {      
       this.localJBC = localCache;
       this.remoteJBC = remoteCache;
+      this.keyBase = keyBase;
       inMemory = new HashSet<Object>();
       timestamps = new HashMap<Object, Long>();
+      this.idleTimeSeconds = cacheConfig.idleTimeoutSeconds();
+      this.expirationTimeSeconds = cacheConfig.removalTimeoutSeconds();
+      this.maxSize = cacheConfig.maxSize();
+      this.name = name;
    }
 
    // --------------------------------------------------  IntegratedObjectStore
@@ -109,9 +123,10 @@
    }
    
    public T get(Object key)
-   {
-      T entry = unmarshall(key, localJBC.get(key));
-      timestamps.put(key, new Long(System.currentTimeMillis()));
+   {      
+      T entry = unmarshall(key, localJBC.get(getScopedKey(key)));
+      if (entry != null)
+         timestamps.put(key, new Long(System.currentTimeMillis()));
       return entry;
    }
 
@@ -122,7 +137,10 @@
    
    public void update(T entry)
    {
-      putInCache(entry.getId(), entry);
+      if (entry.isModified())
+      {
+         putInCache(entry.getId(), entry);
+      }
    }
 
    @SuppressWarnings("unchecked")
@@ -132,7 +150,8 @@
       if (inMemory.contains(key))
       {
          log.trace("converting " + key + " to passivated state");
-         localJBC.put(key, marshall((T) localJBC.get(key)));
+         ScopedKey skey = getScopedKey(key);
+         localJBC.put(skey, marshall((T) localJBC.get(skey)));
          inMemory.remove(key);
       }
    }
@@ -159,7 +178,7 @@
          for (Iterator<Object> iter = dirty.iterator(); iter.hasNext();)
          {
             Object key = iter.next();
-            replicate(key, unmarshall(key, localJBC.get(key)));
+            replicate(key, unmarshall(key, localJBC.get(getScopedKey(key))));
             iter.remove();
          }
       }
@@ -172,39 +191,30 @@
    @SuppressWarnings("unchecked")
    private T unmarshall(Object key, Object obj)
    {
-      if (obj == null)
-         return null;
-      else if (!(obj instanceof byte[]))
+      if (!(obj instanceof byte[]))
          return (T) obj;
       
       log.trace("unmarshalling " + key);
-      ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) obj);
-      try
-      {
-         ObjectInputStream ois = new ObjectInputStream(bais);
-         T entry = (T) ois.readObject();
-         localJBC.put(key, entry);
-         inMemory.add(key);
-         return entry;
-      }
-      catch (Exception e)
-      {
-         throw new RuntimeException(e);
-      }
+      ScopedKey skey = getScopedKey(key);
+      T entry = (T) localJBC.unmarshall(skey);
+      localJBC.put(skey, entry);
+      inMemory.add(key);
+      return entry;
    }
    
    private Object putInCache(Object key, T value)
    {
+      ScopedKey skey = getScopedKey(key);
       Object existing = null;
       if (value != null)
       {
-         existing = localJBC.put(key, value);
+         existing = localJBC.put(skey, value);
          inMemory.add(key);
          timestamps.put(key, new Long(System.currentTimeMillis()));
       }
       else
       {
-         existing = localJBC.remove(key);
+         existing = localJBC.remove(skey);
          inMemory.remove(key);
          timestamps.remove(key);
       }
@@ -223,10 +233,11 @@
    
    private void replicate(Object key, T value)
    {
+      ScopedKey skey = getScopedKey(key);
       if (value != null)
-         remoteJBC.put(key, marshall(value));
+         remoteJBC.put(skey, marshall(value));
       else
-         remoteJBC.remove(key);
+         remoteJBC.remove(skey);
    }
    
    private byte[] marshall(T value)
@@ -273,9 +284,10 @@
                   remove(ts.getId());
                }
             }
-            catch (ItemInUseException ignored)
+            catch (IllegalStateException ise)
             {
-               log.trace("skipping in-use entry " + ts.getId());
+               // Not so great; we're assuming it's 'cause item's in use
+               log.trace("skipping in-use entry " + ts.getId(), ise);
             }
          }    
       }      
@@ -288,27 +300,31 @@
          long now = System.currentTimeMillis();
          long minPassUse = now - (idleTimeSeconds * 1000);
          
-         // Scan the in-memory entries for passivation or removal
-         for (CacheableTimestamp ts : getInMemoryEntries())
+         SortedSet<CacheableTimestamp> timestamps = getInMemoryEntries();
+         int overCount = timestamps.size() - maxSize;
+         for (CacheableTimestamp ts : timestamps)
          {
             try
             {
                long lastUsed = ts.getLastUsed();
-               if (minPassUse >= lastUsed)
+               if (overCount > 0 || minPassUse >= lastUsed)
                {
+                  log.trace("attempting to passivate " + ts.getId());
                   owningCache.passivate(ts.getId());
+                  overCount--;
                }
             }
-            catch (ItemInUseException ignored)
+            catch (IllegalStateException ise)
             {
-               log.trace("skipping in-use entry " + ts.getId());
+               // Not so great; we're assuming it's 'cause item's in use
+               log.trace("skipping in-use entry " + ts.getId(), ise);
             }
          }
       }
       
    }
 
-   public void setPassivatingCache(PassivatingCache<T> cache)
+   public void setPassivatingCache(PassivatingBackingCache<C, T> cache)
    {
       this.owningCache = cache;      
    }
@@ -319,10 +335,17 @@
       {
          if (sessionTimeoutRunner == null)
          {
-            sessionTimeoutRunner = new SessionTimeoutRunner();
+            assert name != null : "name has not been set";
+            assert owningCache != null;
+            String timerName = "PassivationExpirationTimer-" + name;
+            sessionTimeoutRunner = new PassivationExpirationRunner(this, timerName, interval);
          }
          sessionTimeoutRunner.start();
-      }
+      }      
+      
+      stopped = false;
+      
+      log.debug("Started " + name);
    }
 
    public void stop()
@@ -330,25 +353,29 @@
       if (sessionTimeoutRunner != null)
       {
          sessionTimeoutRunner.stop();
-      }      
+      }          
+      
+      stopped = true;
+      
+      log.debug("Stopped " + name);
    }
    
-   public int getIdleTimeSeconds()
+   public long getIdleTimeSeconds()
    {
       return idleTimeSeconds;
    }
 
-   public void setIdleTimeSeconds(int idleTimeSeconds)
+   public void setIdleTimeSeconds(long idleTimeSeconds)
    {
       this.idleTimeSeconds = idleTimeSeconds;
    }
 
-   public int getExpirationTimeSeconds()
+   public long getExpirationTimeSeconds()
    {
       return expirationTimeSeconds;
    }
    
-   public void setExpirationTimeSeconds(int timeout)
+   public void setExpirationTimeSeconds(long timeout)
    {
       this.expirationTimeSeconds = timeout;
    } 
@@ -376,77 +403,73 @@
       return set;
       
    }
-
-   private class SessionTimeoutRunner implements Runnable
+   
+   public boolean isPassivationExpirationSelfManaged()
    {
-      private boolean stopped = true;
-      private Thread thread;
-      
-      public void run()
+      return interval > 0;
+   }
+   
+   public void processPassivationExpiration()
+   {
+      try
       {
-         while (!stopped)
-         {
-            try
-            {
-               runPassivation();               
-            }
-            catch (Exception e)
-            {
-               log.error("Caught exception processing passivations", e);
-            }
-            
-            if (!stopped)
-            {
-               try
-               {
-                  runExpiration();               
-               }
-               catch (Exception e)
-               {
-                  log.error("Caught exception processing expirations", e);
-               }               
-            }
-            
-            if (!stopped)
-            {
-               try
-               {
-                  Thread.sleep(interval * 1000);
-               }
-               catch (InterruptedException ignored) {}
-            }
-         }
+         runPassivation();               
       }
+      catch (Exception e)
+      {
+         log.error("Caught exception processing passivations", e);
+      }
       
-      void start()
+      if (!stopped)
       {
-         if (stopped)
+         try
          {
-            thread = new Thread(this, "MockEvictionThread");
-            thread.setDaemon(true);
-            stopped = false;
-            thread.start();
+            runExpiration();               
          }
+         catch (Exception e)
+         {
+            log.error("Caught exception processing expirations", e);
+         }               
       }
+   }
+   
+   private ScopedKey getScopedKey(Object unscoped)
+   {
+      return new ScopedKey(unscoped, keyBase);
+   }
+   
+   private static class ScopedKey
+   {
+      private Object unscoped;
+      private Object keyBase;
+      ScopedKey(Object unscoped, Object keyBase)
+      {
+         this.unscoped = unscoped;
+         this.keyBase = keyBase;
+      }
       
-      void stop()
+      @Override
+      public int hashCode()
       {
-         stopped = true;
-         if (thread != null && thread.isAlive())
+         int result = 17;
+         result += 31 * unscoped.hashCode();
+         result += 31 * keyBase.hashCode();
+         return result;
+      }
+
+      @Override
+      public boolean equals(Object obj)
+      {
+         if (this == obj)
+            return true;
+         
+         if (obj instanceof ScopedKey)
          {
-            try
-            {
-               thread.join(1000);
-            }
-            catch (InterruptedException ignored) {}
-            
-            if (thread.isAlive())
-            {
-               thread.interrupt();
-            }
-            
+            ScopedKey other = (ScopedKey) obj;
+            return (this.unscoped.equals(other.unscoped) 
+                      && keyBase.equals(other.keyBase));
          }
+         return false;
       }
-      
    }
 }

Added: projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/UnmarshallingMap.java
===================================================================
--- projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/UnmarshallingMap.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/ejb3-cache/src/test/java/org/jboss/ejb3/test/distributed/UnmarshallingMap.java	2008-03-11 04:27:49 UTC (rev 70720)
@@ -0,0 +1,98 @@
+/*
+ * 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.ejb3.test.distributed;
+
+import java.io.ByteArrayInputStream;
+import java.io.ObjectInputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Brian Stansberry
+ */
+public class UnmarshallingMap extends HashMap<Object, Object>
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = -5305256519983822837L;
+
+   /**
+    * Create a new UnmarshallingMap.
+    * 
+    */
+   public UnmarshallingMap()
+   {
+      super();
+   }
+
+   /**
+    * Create a new UnmarshallingMap.
+    * 
+    * @param initialCapacity
+    */
+   public UnmarshallingMap(int initialCapacity)
+   {
+      super(initialCapacity);
+   }
+
+   /**
+    * Create a new UnmarshallingMap.
+    * 
+    * @param m
+    */
+   public UnmarshallingMap(Map<Object, Object> m)
+   {
+      super(m);
+   }
+
+   /**
+    * Create a new UnmarshallingMap.
+    * 
+    * @param initialCapacity
+    * @param loadFactor
+    */
+   public UnmarshallingMap(int initialCapacity, float loadFactor)
+   {
+      super(initialCapacity, loadFactor);
+   }
+   
+   public Object unmarshall(Object key)
+   {
+      Object value = get(key);
+      if (value instanceof byte[])
+      {      
+         ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) value);
+         try
+         {
+            ObjectInputStream ois = new ObjectInputStream(bais);
+            value = ois.readObject();
+         }
+         catch (Exception e)
+         {
+            throw new RuntimeException(e);
+         }
+      }
+      
+      return value;
+   }
+
+}




More information about the jboss-cvs-commits mailing list