[hibernate-commits] Hibernate SVN: r14101 - in core/trunk/cache-jbosscache2: src/main and 29 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Oct 18 16:08:50 EDT 2007


Author: bstansberry at jboss.com
Date: 2007-10-18 16:08:50 -0400 (Thu, 18 Oct 2007)
New Revision: 14101

Added:
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiMultiplexedJBossCacheRegionFactory.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiSharedJBossCacheRegionFactory.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/MultiplexedJBossCacheRegionFactory.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/SharedJBossCacheRegionFactory.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactory.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactoryImpl.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiMultiplexingCacheInstanceManager.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiSharedCacheInstanceManager.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/SharedCacheInstanceManager.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticReadOnlyAccess.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticReadOnlyAccess.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CircumventChecksDataVersion.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/DataVersionAdapter.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/NonLockingDataVersion.java
   core/trunk/cache-jbosscache2/src/main/resources/
   core/trunk/cache-jbosscache2/src/main/resources/org/
   core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/
   core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/
   core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/jbc2/
   core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/jbc2/builder/
   core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/jbc2/builder/jbc2-configs.xml
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractEntityCollectionRegionTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractRegionImplTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheComplianceTest.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheRegionFactoryTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/CacheInstanceManagerTestBase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/MultiplexedCacheInstanceManagerTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/SharedCacheInstanceManagerTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractReadOnlyAccessTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractTransactionalAccessTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/CollectionRegionImplTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticInvalidatedTransactionalTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyExtraAPITestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReplicatedTransactionalTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticTransactionalExtraAPITestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticInvalidatedTransactionalTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyExtraAPITestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReplicatedTransactionalTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticTransactionalExtraAPITestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractReadOnlyAccessTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/EntityRegionImplTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticInvalidatedTransactionalTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyExtraAPITestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReplicatedTransactionalTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticTransactionalExtraAPITestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticInvalidatedTransactionalTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyExtraAPITestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReplicatedTransactionalTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticTransactionalExtraAPITestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractEntityCacheFunctionalTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractQueryCacheFunctionalTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/CacheTestCaseBase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.hbm.xml
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/OptimisticJBossCacheTestDisabled.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/PessimisticJBossCacheTestDisabled.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/VersionedItem.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/query/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/query/QueryRegionImplTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/timestamp/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/timestamp/TimestampsRegionImplTestCase.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyConnectionProvider.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransaction.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManager.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManagerLookup.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/BatchModeTransactionManagerLookup.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestSupport.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestUtil.java
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/optimistic-local-cache.xml
   core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/pessimistic-local-cache.xml
   core/trunk/cache-jbosscache2/src/test/resources/hibernate.cfg.xml
   core/trunk/cache-jbosscache2/src/test/resources/hibernate.properties
   core/trunk/cache-jbosscache2/src/test/resources/log4j.properties
   core/trunk/cache-jbosscache2/src/test/resources/treecache.xml
Removed:
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/InvalidationCacheInstanceManager.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheModeHelper.java
Modified:
   core/trunk/cache-jbosscache2/
   core/trunk/cache-jbosscache2/pom.xml
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/CacheInstanceManager.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/TransactionalDataRegionAdapter.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/MultiplexingCacheInstanceManager.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/ReadOnlyAccess.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/ReadOnlyAccess.java
   core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java
Log:
[HHH-2555] Reimplement Hibernate/JBC 2.0 integration


Property changes on: core/trunk/cache-jbosscache2
___________________________________________________________________
Name: svn:ignore
   - target
local
*.ipr
*.iws
*.iml
.classpath
.project
.nbattrs
*.log
*.properties
.clover

   + target
local
*.ipr
*.iws
*.iml
.classpath
.project
.nbattrs
*.log
*.properties
.clover
.settings
bin


Modified: core/trunk/cache-jbosscache2/pom.xml
===================================================================
--- core/trunk/cache-jbosscache2/pom.xml	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/pom.xml	2007-10-18 20:08:50 UTC (rev 14101)
@@ -25,16 +25,36 @@
             <version>${version}</version>
         </dependency>
         <dependency>
-            <groupId>jboss</groupId>
-            <artifactId>jboss-cache</artifactId>
+            <groupId>${groupId}</groupId>
+            <artifactId>hibernate-testing</artifactId>
+            <version>${version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.cache</groupId>
+            <artifactId>jbosscache-core</artifactId>
             <!-- I'd prefer this, at least until we get a GA...
             <version>[2.0.0.BETA2,)</version>
             -->
-            <version>2.0.0.BETA2</version>
-        </dependency>
+            <version>2.1.0.BETA1</version>
+        </dependency>
+        <!-- test dependencies -->
     </dependencies>
 
-    <build>
+    <build>
+        <testResources>
+            <testResource>
+                <filtering>false</filtering>
+                <directory>src/test/java</directory>
+                <includes>
+                    <include>**/*.xml</include>
+                </includes>
+            </testResource>
+            <testResource>
+                <filtering>true</filtering>
+                <directory>src/test/resources</directory>
+            </testResource>
+        </testResources>
+        
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
@@ -43,8 +63,72 @@
                     <source>1.5</source>
                     <target>1.5</target>
                 </configuration>
-              </plugin>
+              </plugin>
+            <plugin>
+                <groupId>org.jboss.maven.plugins</groupId>
+                <artifactId>maven-test-ext-plugin</artifactId>
+                <version>1.1.0</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>extend</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <systemProperties>
+                        <property>
+                            <name>hibernate.test.validatefailureexpected</name>
+                            <value>true</value>
+                        </property>
+                    </systemProperties>
+                </configuration>
+            </plugin>
         </plugins>
-    </build>
+    </build>
+
+    <profiles>
+        <!-- HSQLDB is the default (eventually move to H2) -->
+        <profile>
+            <id>hsqldb</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>hsqldb</groupId>
+                    <artifactId>hsqldb</artifactId>
+                    <version>1.8.0.2</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                    <version>1.4.2</version>
+                </dependency>
+                <dependency>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                    <version>1.2.14</version>
+                </dependency>
+                <dependency>
+                    <groupId>cglib</groupId>
+                    <artifactId>cglib</artifactId>
+                    <version>2.1_3</version>
+                </dependency>
+            </dependencies>
+            <properties>
+                <db.dialect>org.hibernate.dialect.HSQLDialect</db.dialect>
+                <jdbc.driver>org.hsqldb.jdbcDriver</jdbc.driver>
+                <jdbc.url>jdbc:hsqldb:target/test/db/hsqldb/hibernate</jdbc.url>
+                <jdbc.user>sa</jdbc.user>
+                <jdbc.pass/>
+                <jdbc.isolation/>
+            </properties>
+        </profile>
+     </profiles>
 
 </project>

Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -19,128 +19,307 @@
 import java.util.Map;
 import java.util.Set;
 
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
 import org.jboss.cache.Cache;
 import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.NodeSPI;
+import org.jboss.cache.config.Configuration;
 import org.jboss.cache.config.Option;
+import org.jboss.cache.config.Configuration.NodeLockingScheme;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeCreated;
+import org.jboss.cache.notifications.event.NodeCreatedEvent;
+import org.jboss.cache.optimistic.DataVersion;
 
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.Region;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cache.jbc2.util.NonLockingDataVersion;
 
 /**
- * General support for writing {@link Region} implementations for
- *
- *
+ * General support for writing {@link Region} implementations for JBoss Cache
+ * 2.x.
+ * 
+ * 
  * @author Steve Ebersole
  */
+ at CacheListener
 public abstract class BasicRegionAdapter implements Region {
-	public static final String ITEM = "item";
+    public static final String ITEM = CacheHelper.ITEM;
 
-	protected final Cache jbcCache;
-	protected final String regionName;
-	protected final Fqn regionFqn;
+    protected final Cache jbcCache;
+    protected final String regionName;
+    protected final Fqn regionFqn;
+    protected final boolean optimistic;
+    
+    protected final TransactionManager transactionManager;
 
-	public BasicRegionAdapter(Cache jbcCache, String regionName) {
-		this.jbcCache = jbcCache;
-		this.regionName = regionName;
-		this.regionFqn = Fqn.fromString( regionName.replace( '.', '/' ) );
-		activateLocalClusterNode();
-	}
+    protected SetResidentListener listener;
+    
+    public BasicRegionAdapter(Cache jbcCache, String regionName, String regionPrefix) {
+        this.jbcCache = jbcCache;
+        this.transactionManager = jbcCache.getConfiguration().getRuntimeConfig().getTransactionManager();
+        this.regionName = regionName;
+        this.regionFqn = createRegionFqn(regionName, regionPrefix);
+        optimistic = jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC;
+        activateLocalClusterNode();
+    }
 
-	private void activateLocalClusterNode() {
-		org.jboss.cache.Region jbcRegion = jbcCache.getRegion( regionFqn, true );
-		if ( jbcRegion.isActive() ) {
-			return;
-		}
-		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-		if ( classLoader == null ) {
-			classLoader = getClass().getClassLoader();
-		}
-		jbcRegion.registerContextClassLoader( classLoader );
-		jbcRegion.activate();
-	}
+    protected abstract Fqn<String> createRegionFqn(String regionName, String regionPrefix);
 
-	public String getName() {
-		return regionName;
-	}
+    protected void activateLocalClusterNode() {
+        try {
+            Configuration cfg = jbcCache.getConfiguration();
+            if (cfg.isUseRegionBasedMarshalling()) {
+                org.jboss.cache.Region jbcRegion = jbcCache.getRegion(regionFqn, true);
+                ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+                if (classLoader == null) {
+                    classLoader = getClass().getClassLoader();
+                }
+                jbcRegion.registerContextClassLoader(classLoader);
+                if (jbcRegion.isActive() == false) {
+                    jbcRegion.activate();
+                }
+            }
+            
+            // If we are using replication, we may remove the root node
+            // and then need to re-add it. In that case, the fact
+            // that it is resident will not replicate, so use a listener
+            // to set it as resident
+            if (CacheHelper.isClusteredReplication(cfg.getCacheMode())) {
+                listener = new SetResidentListener();
+                jbcCache.addCacheListener(listener);
+            }
+            
+            // Make sure the root node for the region exists and 
+            // has a DataVersion that never complains
+            Node regionRoot = jbcCache.getRoot().getChild( regionFqn );
+            if (regionRoot == null) {                
+                // Establish the region root node with a non-locking data version
+                DataVersion version = optimistic ? NonLockingDataVersion.INSTANCE : null;
+                regionRoot = CacheHelper.addNode(jbcCache, regionFqn, true, true, version);    
+            }
+            else if (optimistic && regionRoot instanceof NodeSPI) {
+                // FIXME Hacky workaround to JBCACHE-1202
+                if ((((NodeSPI) regionRoot).getVersion() instanceof NonLockingDataVersion) == false) {
+                    ((NodeSPI) regionRoot).setVersion(NonLockingDataVersion.INSTANCE);
+                }
+            }
+            // Never evict this node
+            regionRoot.setResident(true);
+        }
+        catch (Exception e) {
+            throw new CacheException(e.getMessage(), e);
+        }
+    }
 
-	public Cache getCacheInstance() {
-		return jbcCache;
-	}
+    public String getName() {
+        return regionName;
+    }
 
-	public Fqn getRegionFqn() {
-		return regionFqn;
-	}
+    public Cache getCacheInstance() {
+        return jbcCache;
+    }
 
-	public void destroy() throws CacheException {
-		try {
-			// NOTE : this is being used from the process of shutting down a
-			// SessionFactory.  Specific things to consider:
-			// 		(1) this clearing of the region should not propogate to
-			// 			other nodes on the cluster (if any); this is the
-			//			cache-mode-local option bit...
-			//		(2) really just trying a best effort to cleanup after
-			// 			ourselves; lock failures, etc are not critical here;
-			//			this is the fail-silently option bit...
-			Option option = new Option();
-			option.setCacheModeLocal( true );
-			option.setFailSilently( true );
-			jbcCache.getInvocationContext().setOptionOverrides( option );
-			jbcCache.removeNode( regionFqn );
-			deactivateLocalNode();
-		}
-		catch( Exception e ) {
-			throw new CacheException( e );
-		}
-	}
+    public Fqn getRegionFqn() {
+        return regionFqn;
+    }
 
-	private void deactivateLocalNode() {
-		org.jboss.cache.Region jbcRegion = jbcCache.getRegion( regionFqn, false );
-		if ( jbcRegion != null && jbcRegion.isActive() ) {
-			jbcRegion.deactivate();
-			jbcRegion.unregisterContextClassLoader();
-		}
-	}
+    public void destroy() throws CacheException {
+        try {
+            // NOTE : this is being used from the process of shutting down a
+            // SessionFactory. Specific things to consider:
+            // (1) this clearing of the region should not propogate to
+            // other nodes on the cluster (if any); this is the
+            // cache-mode-local option bit...
+            // (2) really just trying a best effort to cleanup after
+            // ourselves; lock failures, etc are not critical here;
+            // this is the fail-silently option bit...
+            Option option = new Option();
+            option.setCacheModeLocal(true);
+            option.setFailSilently(true);
+            if (optimistic) {
+                option.setDataVersion(NonLockingDataVersion.INSTANCE);
+            }
+            jbcCache.getInvocationContext().setOptionOverrides(option);
+            jbcCache.removeNode(regionFqn);
+            deactivateLocalNode();            
+        } catch (Exception e) {
+            throw new CacheException(e);
+        }
+        finally {
+            if (listener != null)
+                jbcCache.removeCacheListener(listener);
+        }
+    }
 
-	public long getSizeInMemory() {
-		// not supported
-		return -1;
-	}
+    protected void deactivateLocalNode() {
+        org.jboss.cache.Region jbcRegion = jbcCache.getRegion(regionFqn, false);
+        if (jbcRegion != null && jbcRegion.isActive()) {
+            jbcRegion.deactivate();
+            jbcRegion.unregisterContextClassLoader();
+        }
+    }
 
-	public long getElementCountInMemory() {
-		try {
-			Set children = jbcCache.getRoot().getChild( regionFqn ).getChildrenNames();
-			return children == null ? 0 : children.size();
-		}
-		catch ( Exception e ) {
-			throw new CacheException( e );
-		}
-	}
+    public long getSizeInMemory() {
+        // not supported
+        return -1;
+    }
 
-	public long getElementCountOnDisk() {
-		return -1;
-	}
+    public long getElementCountInMemory() {
+        try {
+            Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
+            return childrenNames.size();
+        } catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
 
-	public Map toMap() {
-		try {
-			Map result = new HashMap();
-			Set childrenNames = jbcCache.getRoot().getChild( regionFqn ).getChildrenNames();
-			if (childrenNames != null) {
-				for ( Object childName : childrenNames ) {
-					result.put( childName, jbcCache.get( new Fqn( regionFqn, childName ), ITEM ) );
-				}
-			}
-			return result;
-		}
-		catch (Exception e) {
-			throw new CacheException(e);
-		}
-	}
+    public long getElementCountOnDisk() {
+        return -1;
+    }
 
-	public long nextTimestamp() {
-		return System.currentTimeMillis() / 100;
-	}
+    public Map toMap() {
+        try {
+            Map result = new HashMap();
+            Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
+            for (Object childName : childrenNames) {
+                result.put(childName, jbcCache.get(new Fqn(regionFqn, childName), ITEM));
+            }
+            return result;
+        } catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
 
-	public int getTimeout() {
-		return 600; //60 seconds
-	}
+    public long nextTimestamp() {
+        return System.currentTimeMillis() / 100;
+    }
+
+    public int getTimeout() {
+        return 600; // 60 seconds
+    }
+
+    /**
+     * Performs a JBoss Cache <code>get(Fqn, Object)</code> after first
+     * {@link #suspend suspending any ongoing transaction}. Wraps any exception
+     * in a {@link CacheException}. Ensures any ongoing transaction is resumed.
+     * 
+     * @param key
+     * @param opt any option to add to the get invocation. May be <code>null</code>
+     * @param suppressTimeout should any TimeoutException be suppressed?
+     * @return
+     */
+    protected Object suspendAndGet(Object key, Option opt, boolean suppressTimeout) throws CacheException {
+        Transaction tx = suspend();
+        try {
+            CacheHelper.setInvocationOption(getCacheInstance(), opt);
+            if (suppressTimeout)
+                return CacheHelper.getAllowingTimeout(getCacheInstance(), getRegionFqn(), key);
+            else
+                return CacheHelper.get(getCacheInstance(), getRegionFqn(), key);
+        } finally {
+            resume(tx);
+        }
+    }
+
+    /**
+     * Tell the TransactionManager to suspend any ongoing transaction.
+     * 
+     * @return the transaction that was suspended, or <code>null</code> if
+     *         there wasn't one
+     */
+    protected Transaction suspend() {
+        Transaction tx = null;
+        try {
+            if (transactionManager != null) {
+                tx = transactionManager.suspend();
+            }
+        } catch (SystemException se) {
+            throw new CacheException("Could not suspend transaction", se);
+        }
+        return tx;
+    }
+
+    /**
+     * Tell the TransactionManager to resume the given transaction
+     * 
+     * @param tx
+     *            the transaction to suspend. May be <code>null</code>.
+     */
+    protected void resume(Transaction tx) {
+        try {
+            if (tx != null)
+                transactionManager.resume(tx);
+        } catch (Exception e) {
+            throw new CacheException("Could not resume transaction", e);
+        }
+    }
+
+    /**
+     * Get an Option with a {@link Option#getDataVersion() data version}
+     * of {@link NonLockingDataVersion}.  The data version will not be 
+     * set if the cache is not configured for optimistic locking.
+     * 
+     * @param allowNullReturn If <code>true</code>, return <code>null</code>
+     *                        if the cache is not using optimistic locking.
+     *                        If <code>false</code>, return a default
+     *                        {@link Option}.
+     *                        
+     * @return the Option, or <code>null</code>.
+     */
+    protected Option getNonLockingDataVersionOption(boolean allowNullReturn) {
+        return optimistic ? NonLockingDataVersion.getInvocationOption() 
+                          : (allowNullReturn) ? null : new Option();
+    }
+
+    public static Fqn<String> getTypeFirstRegionFqn(String regionName, String regionPrefix, String regionType) {
+        Fqn<String> base = Fqn.fromString(regionType);
+        Fqn<String> added = Fqn.fromString(escapeRegionName(regionName, regionPrefix));
+        return new Fqn<String>(base, added);
+    }
+
+    public static Fqn<String> getTypeLastRegionFqn(String regionName, String regionPrefix, String regionType) {
+        Fqn<String> base = Fqn.fromString(escapeRegionName(regionName, regionPrefix));
+        return new Fqn<String>(base, regionType);
+    }
+
+    public static String escapeRegionName(String regionName, String regionPrefix) {
+        String escaped = null;
+        int idx = -1;
+        if (regionPrefix != null) {
+            idx = regionName.indexOf(regionPrefix);
+        }
+
+        if (idx > -1) {
+            int regionEnd = idx + regionPrefix.length();
+            String prefix = regionName.substring(0, regionEnd);
+            String suffix = regionName.substring(regionEnd);
+            suffix = suffix.replace('.', '/');
+            escaped = prefix + suffix;
+        } else {
+            escaped = regionName.replace('.', '/');
+            if (regionPrefix != null && regionPrefix.length() > 0) {
+                escaped = regionPrefix + "/" + escaped;
+            }
+        }
+        return escaped;
+    }
+    
+    @CacheListener
+    public class SetResidentListener {
+        
+        @NodeCreated
+        public void nodeCreated(NodeCreatedEvent event) {
+            if (!event.isPre() && event.getFqn().equals(getRegionFqn())) {
+                Node regionRoot = jbcCache.getRoot().getChild(getRegionFqn());
+                regionRoot.setResident(true);
+            }
+        }
+        
+    }
 }

Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/CacheInstanceManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/CacheInstanceManager.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/CacheInstanceManager.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -15,48 +15,69 @@
  */
 package org.hibernate.cache.jbc2;
 
+import java.util.Properties;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cfg.Settings;
 import org.jboss.cache.Cache;
 
 /**
  * Acts as a buffer from how instances of {@link Cache} are built/obtained.
- *
+ * 
  * @author Steve Ebersole
  */
 public interface CacheInstanceManager {
-	/**
-	 * Retrieve a handle to the {@link Cache} instance to be used for storing
-	 * entity data.
-	 *
-	 * @return The entity data cache instance.
-	 */
-	public Cache getEntityCacheInstance();
+    /**
+     * Retrieve a handle to the {@link Cache} instance to be used for storing
+     * entity data.
+     * 
+     * @return The entity data cache instance.
+     */
+    public Cache getEntityCacheInstance();
 
-	/**
-	 * Retrieve a handle to the {@link Cache} instance to be used for storing
-	 * collection data.
-	 *
-	 * @return The collection data cache instance.
-	 */
-	public Cache getCollectionCacheInstance();
+    /**
+     * Retrieve a handle to the {@link Cache} instance to be used for storing
+     * collection data.
+     * 
+     * @return The collection data cache instance.
+     */
+    public Cache getCollectionCacheInstance();
 
-	/**
-	 * Retrieve a handle to the {@link Cache} instance to be used for storing
-	 * query results.
-	 *
-	 * @return The query result cache instance.
-	 */
-	public Cache getQueryCacheInstance();
+    /**
+     * Retrieve a handle to the {@link Cache} instance to be used for storing
+     * query results.
+     * 
+     * @return The query result cache instance.
+     */
+    public Cache getQueryCacheInstance();
 
-	/**
-	 * Retrieve a handle to the {@link Cache} instance to be used for storing
-	 * timestamps.
-	 * 
-	 * @return The timestamps cache instance.
-	 */
-	public Cache getTimestampsCacheInstance();
+    /**
+     * Retrieve a handle to the {@link Cache} instance to be used for storing
+     * timestamps.
+     * 
+     * @return The timestamps cache instance.
+     */
+    public Cache getTimestampsCacheInstance();
 
-	/**
-	 * Release any held resources.
-	 */
-	public void release();
+    /**
+     * Lifecycle callback to perform any necessary initialization of the
+     * CacheInstanceManager. Called exactly once during the construction of a
+     * {@link org.hibernate.impl.SessionFactoryImpl}.
+     * 
+     * @param settings
+     *            The settings in effect.
+     * @param properties
+     *            The defined cfg properties
+     * @throws CacheException
+     *             Indicates problems starting the L2 cache impl; considered as
+     *             a sign to stop {@link org.hibernate.SessionFactory} building.
+     */
+    public void start(Settings settings, Properties properties) throws CacheException;
+
+    /**
+     * Lifecycle callback to perform any necessary cleanup of the underlying
+     * CacheInstanceManager. Called exactly once during
+     * {@link org.hibernate.SessionFactory#close}.
+     */
+    public void stop();
 }

Deleted: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
- *
- * 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, v. 2.1. This program is distributed in the
- * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
- * distribution; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Red Hat Author(s): Steve Ebersole
- */
-package org.hibernate.cache.jbc2;
-
-import java.util.Properties;
-
-import org.hibernate.cache.CacheDataDescription;
-import org.hibernate.cache.CacheException;
-import org.hibernate.cache.CollectionRegion;
-import org.hibernate.cache.EntityRegion;
-import org.hibernate.cache.QueryResultsRegion;
-import org.hibernate.cache.RegionFactory;
-import org.hibernate.cache.TimestampsRegion;
-import org.hibernate.cache.jbc2.builder.InvalidationCacheInstanceManager;
-import org.hibernate.cache.jbc2.collection.CollectionRegionImpl;
-import org.hibernate.cache.jbc2.entity.EntityRegionImpl;
-import org.hibernate.cfg.Settings;
-
-/**
- * {@inheritDoc}
- *
- * @author Steve Ebersole
- */
-public class JBossCacheRegionFactory implements RegionFactory {
-	private CacheInstanceManager cacheInstanceManager;
-
-	public JBossCacheRegionFactory() {
-	}
-
-	public JBossCacheRegionFactory(CacheInstanceManager cacheInstanceManager) {
-		this.cacheInstanceManager = cacheInstanceManager;
-	}
-
-	public void start(Settings settings, Properties properties) throws CacheException {
-		if ( cacheInstanceManager == null ) {
-			cacheInstanceManager = new InvalidationCacheInstanceManager( settings, properties );
-		}
-	}
-
-	public void stop() {
-		if ( cacheInstanceManager != null ) {
-			cacheInstanceManager.release();
-		}
-	}
-
-	public boolean isMinimalPutsEnabledByDefault() {
-		return true;
-	}
-
-	public long nextTimestamp() {
-		return System.currentTimeMillis() / 100;
-	}
-
-	public EntityRegion buildEntityRegion(
-			String regionName,
-			Properties properties,
-			CacheDataDescription metadata) throws CacheException {
-		return new EntityRegionImpl( cacheInstanceManager.getEntityCacheInstance(), regionName, metadata );
-	}
-
-	public CollectionRegion buildCollectionRegion(
-			String regionName,
-			Properties properties,
-			CacheDataDescription metadata) throws CacheException {
-		return new CollectionRegionImpl( cacheInstanceManager.getCollectionCacheInstance(), regionName, metadata );
-	}
-
-	public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
-		return null;
-	}
-
-	public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
-		return null;
-	}
-
-}

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.TimestampsRegion;
+import org.hibernate.cache.jbc2.builder.JndiSharedCacheInstanceManager;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cache.jbc2.collection.CollectionRegionImpl;
+import org.hibernate.cache.jbc2.entity.EntityRegionImpl;
+import org.hibernate.cache.jbc2.query.QueryResultsRegionImpl;
+import org.hibernate.cache.jbc2.timestamp.TimestampsRegionImpl;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Settings;
+import org.hibernate.util.PropertiesHelper;
+import org.jboss.cache.DefaultCacheFactory;
+
+;
+
+/**
+ * {@link RegionFactory} that uses one or more JBoss Cache instances for 
+ * caching entities, collections, queries and timestamps. How the factory
+ * obtains a reference to the needed JBoss Cache instance(s) is determined
+ * by the injected {@link CacheInstanceManager}.
+ * <p>
+ * By default uses {@link SharedCacheInstanceManager} as its
+ * {@link #getCacheInstanceManager() CacheInstanceManager}.
+ * Basically, this uses a single shared JBoss Cache for entities, collections,
+ * queries and timestamps. The JBoss Cache instance is created by the
+ * JBC {@link DefaultCacheFactory} using the resource identified by the
+ * {@link JndiSharedCacheInstanceManager#CACHE_RESOURCE_PROP}
+ * configuration property. 
+ * </p>
+ * <p>
+ * Also exposes an overloaded constructor that allows injection of different
+ * <code>CacheInstanceManager</code> implementations.
+ * </p>
+ * 
+ * @author Steve Ebersole
+ * @author Brian Stansberry
+ */
+public class JBossCacheRegionFactory implements RegionFactory {
+    private CacheInstanceManager cacheInstanceManager;
+
+    /**
+     * FIXME Per the RegionFactory class Javadoc, this constructor version
+     * should not be necessary.
+     * 
+     * @param props
+     */
+    public JBossCacheRegionFactory(Properties props) {
+        this();
+    }
+
+    /**
+     *  Create a new JBossCacheRegionFactory.
+     */
+    public JBossCacheRegionFactory() {
+    }
+
+    /**
+     * Create a new JBossCacheRegionFactory that uses the provided
+     * {@link CacheInstanceManager}.
+     * 
+     * @param cacheInstanceManager
+     */
+    public JBossCacheRegionFactory(CacheInstanceManager cacheInstanceManager) {
+        this.cacheInstanceManager = cacheInstanceManager;
+    }
+
+    public CacheInstanceManager getCacheInstanceManager() {
+        return cacheInstanceManager;
+    }
+
+    public void start(Settings settings, Properties properties) throws CacheException {
+        if (cacheInstanceManager == null) {
+            cacheInstanceManager = new SharedCacheInstanceManager();
+        }
+
+        cacheInstanceManager.start(settings, properties);
+    }
+
+    public void stop() {
+        if (cacheInstanceManager != null) {
+            cacheInstanceManager.stop();
+        }
+    }
+
+    public boolean isMinimalPutsEnabledByDefault() {
+        return true;
+    }
+
+    public long nextTimestamp() {
+        return System.currentTimeMillis() / 100;
+    }
+
+    public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
+            throws CacheException {
+        return new EntityRegionImpl(cacheInstanceManager.getEntityCacheInstance(), regionName,
+                getRegionPrefix(properties), metadata);
+    }
+
+    public CollectionRegion buildCollectionRegion(String regionName, Properties properties,
+            CacheDataDescription metadata) throws CacheException {
+        return new CollectionRegionImpl(cacheInstanceManager.getCollectionCacheInstance(), regionName,
+                getRegionPrefix(properties), metadata);
+    }
+
+    public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
+
+        return new QueryResultsRegionImpl(cacheInstanceManager.getQueryCacheInstance(), regionName,
+                getRegionPrefix(properties), properties);
+    }
+
+    public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
+
+        return new TimestampsRegionImpl(cacheInstanceManager.getTimestampsCacheInstance(), regionName,
+                getRegionPrefix(properties), properties);
+    }
+
+    public static String getRegionPrefix(Properties properties) {
+        return PropertiesHelper.getString(Environment.CACHE_REGION_PREFIX, properties, null);
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiMultiplexedJBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiMultiplexedJBossCacheRegionFactory.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiMultiplexedJBossCacheRegionFactory.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.builder.JndiMultiplexingCacheInstanceManager;
+
+/**
+ * {@link JBossCacheRegionFactory} that uses
+ * {@link JndiMultiplexingCacheInstanceManager} as its
+ * {@link #getCacheInstanceManager() CacheInstanceManager}.
+ * <p>
+ * Supports separate JBoss Cache instances for entity, collection, query
+ * and timestamp caching, with the expectation that a single multiplexed
+ * JGroups channel will be shared between the caches. JBoss Cache instances
+ * are created from a factory.
+ * </p>
+ * <p>
+ * This version finds the factory in JNDI. See 
+ * {@link JndiMultiplexingCacheInstanceManager} for configuration details. 
+ * </p>
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class JndiMultiplexedJBossCacheRegionFactory extends JBossCacheRegionFactory {
+
+    /**
+     * FIXME Per the RegionFactory class Javadoc, this constructor version
+     * should not be necessary.
+     * 
+     * @param props
+     */
+    public JndiMultiplexedJBossCacheRegionFactory(Properties props) {
+        this();
+    }
+
+    /**
+     * Create a new MultiplexedJBossCacheRegionFactory.
+     * 
+     */
+    public JndiMultiplexedJBossCacheRegionFactory() {
+        super(new JndiMultiplexingCacheInstanceManager());
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiSharedJBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiSharedJBossCacheRegionFactory.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiSharedJBossCacheRegionFactory.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.builder.JndiSharedCacheInstanceManager;
+
+/**
+ * {@link JBossCacheRegionFactory} that uses
+ * {@link JndiSharedCacheInstanceManager} as its
+ * {@link #getCacheInstanceManager() CacheInstanceManager}.
+ * <p>
+ * Basically, uses a single shared JBoss Cache for entities, collections,
+ * queries and timestamps. The JBoss Cache instance is found in JNDI
+ * using the value of the {@link JndiSharedCacheInstanceManager#CACHE_RESOURCE_PROP}
+ * configuration property as the name to look up. 
+ * </p>
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class JndiSharedJBossCacheRegionFactory extends JBossCacheRegionFactory {
+
+    /**
+     * FIXME Per the RegionFactory class Javadoc, this constructor version
+     * should not be necessary.
+     * 
+     * @param props
+     */
+    public JndiSharedJBossCacheRegionFactory(Properties props) {
+        this();
+    }
+
+    /**
+     * Create a new MultiplexedJBossCacheRegionFactory.
+     * 
+     */
+    public JndiSharedJBossCacheRegionFactory() {
+        super(new JndiSharedCacheInstanceManager());
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/MultiplexedJBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/MultiplexedJBossCacheRegionFactory.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/MultiplexedJBossCacheRegionFactory.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+
+/**
+ * {@link JBossCacheRegionFactory} that uses
+ * {@link MultiplexingCacheInstanceManager} as its
+ * {@link #getCacheInstanceManager() CacheInstanceManager}.
+ * <p>
+ * Supports separate JBoss Cache instances for entity, collection, query
+ * and timestamp caching, with the expectation that a single multiplexed
+ * JGroups channel will be shared between the caches. JBoss Cache instances
+ * are created from a factory.
+ * </p>
+ * <p>
+ * This version instantiates the factory itself. See 
+ * {@link MultiplexingCacheInstanceManager} for configuration details. 
+ * </p>
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class MultiplexedJBossCacheRegionFactory extends JBossCacheRegionFactory {
+
+    /**
+     * FIXME Per the RegionFactory class Javadoc, this constructor version
+     * should not be necessary.
+     * 
+     * @param props
+     */
+    public MultiplexedJBossCacheRegionFactory(Properties props) {
+        this();
+    }
+
+    /**
+     * Create a new MultiplexedJBossCacheRegionFactory.
+     * 
+     */
+    public MultiplexedJBossCacheRegionFactory() {
+        super(new MultiplexingCacheInstanceManager());
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/SharedJBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/SharedJBossCacheRegionFactory.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/SharedJBossCacheRegionFactory.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.builder.JndiSharedCacheInstanceManager;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.jboss.cache.DefaultCacheFactory;
+
+/**
+ * {@link JBossCacheRegionFactory} that uses
+ * {@link SharedCacheInstanceManager} as its
+ * {@link #getCacheInstanceManager() CacheInstanceManager}.
+ * <p>
+ * Basically, uses a single shared JBoss Cache for entities, collections,
+ * queries and timestamps. The JBoss Cache instance created by the
+ * JBC {@link DefaultCacheFactory} using the resource identified by the
+ * {@link JndiSharedCacheInstanceManager#CACHE_RESOURCE_PROP}
+ * configuration property. 
+ * </p>
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class SharedJBossCacheRegionFactory extends JBossCacheRegionFactory {
+
+    /**
+     * FIXME Per the RegionFactory class Javadoc, this constructor version
+     * should not be necessary.
+     * 
+     * @param props
+     */
+    public SharedJBossCacheRegionFactory(Properties props) {
+        this();
+    }
+
+    /**
+     * Create a new MultiplexedJBossCacheRegionFactory.
+     * 
+     */
+    public SharedJBossCacheRegionFactory() {
+        super(new SharedCacheInstanceManager());
+    }
+
+}

Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/TransactionalDataRegionAdapter.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/TransactionalDataRegionAdapter.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/TransactionalDataRegionAdapter.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -15,36 +15,38 @@
  */
 package org.hibernate.cache.jbc2;
 
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.TransactionalDataRegion;
 import org.jboss.cache.Cache;
 
-import org.hibernate.cache.TransactionalDataRegion;
-import org.hibernate.cache.CacheDataDescription;
-
 /**
  * {@inheritDoc}
- *
+ * 
  * @author Steve Ebersole
  */
-public class TransactionalDataRegionAdapter extends BasicRegionAdapter implements TransactionalDataRegion {
-	protected final CacheDataDescription metadata;
+public abstract class TransactionalDataRegionAdapter extends BasicRegionAdapter implements TransactionalDataRegion {
 
-	public TransactionalDataRegionAdapter(Cache jbcCache, String regionName, CacheDataDescription metadata) {
-		super( jbcCache, regionName );
-		this.metadata = metadata;
-	}
+    protected final CacheDataDescription metadata;
 
-	/**
-	 * Here, for JBossCache, we consider the cache to be transaction aware if the underlying
-	 * cache instance has a refernece to the transaction manager.
-	 */
-	public boolean isTransactionAware() {
-		return jbcCache.getConfiguration().getRuntimeConfig().getTransactionManager() != null;
-	}
+    public TransactionalDataRegionAdapter(Cache jbcCache, String regionName, String regionPrefix,
+            CacheDataDescription metadata) {
+        super(jbcCache, regionName, regionPrefix);
+        this.metadata = metadata;
+    }
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public CacheDataDescription getCacheDataDescription() {
-		return metadata;
-	}
+    /**
+     * Here, for JBossCache, we consider the cache to be transaction aware if
+     * the underlying cache instance has a reference to the transaction manager.
+     */
+    public boolean isTransactionAware() {
+        return transactionManager != null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public CacheDataDescription getCacheDataDescription() {
+        return metadata;
+    }
+
 }

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.access;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cache.jbc2.util.DataVersionAdapter;
+import org.hibernate.cache.jbc2.util.NonLockingDataVersion;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.optimistic.DataVersion;
+
+/**
+ * Defines the strategy for transactional access to entity or collection data in
+ * an optimistic-locking JBoss Cache using its 2.x APIs.
+ * <p>
+ * The intent of this class is to encapsulate common code and serve as a
+ * delegate for {@link EntityRegionAccessStrategy} and
+ * {@link CollectionRegionAccessStrategy} implementations.
+ * </p>
+ * 
+ * @author Brian Stansberry
+ * @version $Revision: 1 $
+ */
+public class OptimisticTransactionalAccessDelegate extends TransactionalAccessDelegate {
+
+    protected final CacheDataDescription dataDescription;
+
+    public OptimisticTransactionalAccessDelegate(Cache cache, Fqn regionFqn, CacheDataDescription dataDescription) {
+        super(cache, regionFqn);
+        this.dataDescription = dataDescription;
+    }
+
+    /**
+     * Overrides the
+     * {@link TransactionalAccessDelegate#evict(Object) superclass} by adding a
+     * {@link NonLockingDataVersion} to the invocation.
+     */
+    @Override
+    public void evict(Object key) throws CacheException {
+
+        Option opt = NonLockingDataVersion.getInvocationOption();
+        CacheHelper.remove(cache, regionFqn, key, opt);
+    }
+
+    /**
+     * Overrides the {@link TransactionalAccessDelegate#evictAll() superclass}
+     * by adding a {@link NonLockingDataVersion} to the invocation.
+     */
+    @Override
+    public void evictAll() throws CacheException {
+
+        evictOrRemoveAll();
+    }
+
+    /**
+     * Overrides the
+     * {@link TransactionalAccessDelegate#insert(Object, Object, Object) superclass}
+     * by adding a {@link DataVersion} to the invocation.
+     */
+    @Override
+    public boolean insert(Object key, Object value, Object version) throws CacheException {
+
+        Option opt = getDataVersionOption(version, null);
+        CacheHelper.put(cache, regionFqn, key, value, opt);
+        return true;
+    }
+
+    @Override
+    public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+            throws CacheException {
+
+        // We ignore minimalPutOverride. JBossCache putForExternalRead is
+        // already about as minimal as we can get; it will promptly return
+        // if it discovers that the node we want to write to already exists
+        Option opt = getDataVersionOption(version, version);
+        return CacheHelper.putForExternalRead(cache, regionFqn, key, value, opt);
+    }
+
+    @Override
+    public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+
+        Option opt = getDataVersionOption(version, version);
+        return CacheHelper.putForExternalRead(cache, regionFqn, key, value, opt);
+    }
+
+    @Override
+    public void remove(Object key) throws CacheException {
+
+        Option opt = NonLockingDataVersion.getInvocationOption();
+        CacheHelper.remove(cache, regionFqn, key, opt);
+    }
+
+    @Override
+    public void removeAll() throws CacheException {
+
+        evictOrRemoveAll();  
+    }
+
+    @Override
+    public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
+            throws CacheException {
+
+        Option opt = getDataVersionOption(currentVersion, previousVersion);
+        CacheHelper.put(cache, regionFqn, key, value, opt);
+        return true;
+    }
+
+    private Option getDataVersionOption(Object currentVersion, Object previousVersion) {
+        DataVersion dv = (dataDescription != null && dataDescription.isVersioned()) ? new DataVersionAdapter(
+                currentVersion, previousVersion, dataDescription.getVersionComparator(), dataDescription.toString())
+                : NonLockingDataVersion.INSTANCE;
+        Option opt = new Option();
+        opt.setDataVersion(dv);
+        return opt;
+    }
+
+    private void evictOrRemoveAll() {
+        Option opt = NonLockingDataVersion.getInvocationOption();
+        CacheHelper.removeAll(cache, regionFqn, opt);
+        
+        // Restablish the region root node with a non-locking data version
+        CacheHelper.addNode(cache, regionFqn, false, true, NonLockingDataVersion.INSTANCE);
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.cache.jbc2.access;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+
+/**
+ * Defines the strategy for transactional access to entity or collection data in
+ * a pessimistic-locking JBoss Cache using its 2.x APIs.
+ * <p>
+ * The intent of this class is to encapsulate common code and serve as a
+ * delegate for {@link EntityRegionAccessStrategy} and
+ * {@link CollectionRegionAccessStrategy} implementations.
+ * </p>
+ * 
+ * @author Brian Stansberry
+ */
+public class TransactionalAccessDelegate {
+
+    protected final Cache cache;
+    protected final Fqn regionFqn;
+
+    public TransactionalAccessDelegate(Cache cache, Fqn regionFqn) {
+        this.cache = cache;
+        this.regionFqn = regionFqn;
+    }
+
+    public Object get(Object key, long txTimestamp) throws CacheException {
+
+        return CacheHelper.get(cache, regionFqn, key);
+    }
+
+    public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+
+        return CacheHelper.putForExternalRead(cache, regionFqn, key, value);
+    }
+
+    public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+            throws CacheException {
+
+        // We ignore minimalPutOverride. JBossCache putForExternalRead is
+        // already about as minimal as we can get; it will promptly return
+        // if it discovers that the node we want to write to already exists
+        return CacheHelper.putForExternalRead(cache, regionFqn, key, value);
+    }
+
+    public SoftLock lockItem(Object key, Object version) throws CacheException {
+        return null;
+    }
+
+    public SoftLock lockRegion() throws CacheException {
+        return null;
+    }
+
+    public void unlockItem(Object key, SoftLock lock) throws CacheException {
+    }
+
+    public void unlockRegion(SoftLock lock) throws CacheException {
+    }
+
+    public boolean insert(Object key, Object value, Object version) throws CacheException {
+
+        CacheHelper.put(cache, regionFqn, key, value);
+        return true;
+    }
+
+    public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
+        return false;
+    }
+
+    public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
+            throws CacheException {
+
+        CacheHelper.put(cache, regionFqn, key, value);
+        return true;
+    }
+
+    public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
+            throws CacheException {
+        return false;
+    }
+
+    public void remove(Object key) throws CacheException {
+
+        CacheHelper.remove(cache, regionFqn, key);
+    }
+
+    public void removeAll() throws CacheException {
+        evictOrRemoveAll();
+    }
+
+    public void evict(Object key) throws CacheException {
+        CacheHelper.remove(cache, regionFqn, key);
+    }
+
+    public void evictAll() throws CacheException {
+        evictOrRemoveAll();
+    }
+    
+    private void evictOrRemoveAll() throws CacheException {
+        CacheHelper.removeAll(cache, regionFqn);
+        // Restore the region root node
+        CacheHelper.addNode(cache, regionFqn, false, true, null);        
+    }
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java
___________________________________________________________________
Name: svn:executable
   + *

Deleted: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/InvalidationCacheInstanceManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/InvalidationCacheInstanceManager.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/InvalidationCacheInstanceManager.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
- *
- * 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, v. 2.1. This program is distributed in the
- * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
- * distribution; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Red Hat Author(s): Steve Ebersole
- */
-package org.hibernate.cache.jbc2.builder;
-
-import java.util.Properties;
-import javax.transaction.TransactionManager;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.jboss.cache.Cache;
-import org.jboss.cache.DefaultCacheFactory;
-
-import org.hibernate.cache.CacheException;
-import org.hibernate.cache.jbc2.CacheInstanceManager;
-import org.hibernate.cache.jbc2.util.CacheModeHelper;
-import org.hibernate.cfg.Settings;
-import org.hibernate.util.PropertiesHelper;
-
-/**
- * A {@link CacheInstanceManager} implementation where we use a single cache instance
- * we assume to be configured for invalidation if operating on a cluster.  Under that
- * assumption, we can store all data into the same {@link Cache} instance.
- * <p/>
- * todo : this is built on the assumption that JBC clustered invalidation is changed to keep the "cache node" around on the other "cluster nodes"
- *
- * @author Steve Ebersole
- */
-public class InvalidationCacheInstanceManager implements CacheInstanceManager {
-	public static final String CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.invalidation";
-	public static final String DEFAULT_CACHE_RESOURCE = "treecache.xml";
-
-	private static final Logger log = LoggerFactory.getLogger( InvalidationCacheInstanceManager.class );
-
-	private final Cache cache;
-
-	public InvalidationCacheInstanceManager(Settings settings, Properties properties) {
-		String configResource = PropertiesHelper.getString( CACHE_RESOURCE_PROP, properties, DEFAULT_CACHE_RESOURCE );
-		cache = DefaultCacheFactory.getInstance().createCache( configResource, false );
-		if ( settings.getTransactionManagerLookup() != null ) {
-			TransactionManager tm = settings.getTransactionManagerLookup().getTransactionManager( properties );
-			if ( tm != null ) {
-				cache.getConfiguration().getRuntimeConfig().setTransactionManager( tm );
-			}
-		}
-		cache.start();
-	}
-
-	public InvalidationCacheInstanceManager(Cache cache) {
-		this.cache = cache;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Cache getEntityCacheInstance() {
-		return cache;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Cache getCollectionCacheInstance() {
-		return cache;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Cache getQueryCacheInstance() {
-		if ( CacheModeHelper.isClusteredInvalidation( cache ) ) {
-			throw new CacheException( "Query cache not supported for clustered invalidation" );
-		}
-		return cache;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Cache getTimestampsCacheInstance() {
-		if ( CacheModeHelper.isClusteredInvalidation( cache ) ) {
-			throw new CacheException( "Query cache not supported for clustered invalidation" );
-		}
-		return cache;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public void release() {
-		if ( cache != null ) {
-			try {
-				cache.stop();
-			}
-			catch( Throwable t ) {
-				log.warn( "Unable to stop cache instance", t );
-			}
-		}
-	}
-}

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactory.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactory.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.builder;
+
+import java.util.Set;
+
+import org.jboss.cache.Cache;
+
+/**
+ * Factory and registry for JBoss Cache instances configured using
+ * named configurations.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public interface JBossCacheFactory {
+
+    /**
+     * Gets all the names of all the configurations of which this object
+     * is aware.
+     * 
+     * @return
+     */
+    Set getConfigurationNames();
+    
+    /**
+     * Get a cache configured according to the given configuration name.
+     * <p>
+     * The caller is free to invoke the {@link Cache#create()} and
+     * {@link Cache#start()} lifecycle methods on the returned cache, but
+     * the @link Cache#stop()} and {@link Cache#destroy()} methods should not
+     * be invoked, since it is quite possible other session factories are
+     * still using the cache. Use {@link #releaseCache(String)} to notify this 
+     * factory that the caller is no longer using a cache; let the factory 
+     * control stopping and destroying the underlying cache.
+     * </p>
+     * 
+     * @param configName    the name of the configuration
+     * @param create        should the cache be instantiated if it
+     *                      hasn't already been?
+     * @return              the cache, or <code>null</code> if 
+     *                      <code>create</code> is false and the cache hasn't
+     *                      been created previously.
+     *                      
+     * @throws IllegalArgumentException if this object is unaware of 
+     *                                  <code>configName</code>
+     * @throws Exception if there is a problem instantiating the cache
+     */
+    Cache getCache(String configName, boolean create) throws Exception;
+    
+    /**
+     * Notifies the factory that the caller is no longer using the given
+     * cache.  The factory may perform cleanup operations, such as 
+     * stopping and destroying the cache.
+     * 
+     * @param configName
+     */
+    void releaseCache(String configName);
+
+}
\ No newline at end of file

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactoryImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactoryImpl.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactoryImpl.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.builder;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.hibernate.cache.CacheException;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheStatus;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.ConfigurationException;
+import org.jboss.cache.xml.XmlHelper;
+import org.jgroups.ChannelFactory;
+import org.jgroups.JChannelFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSOutput;
+import org.w3c.dom.ls.LSSerializer;
+
+/**
+ * A JBossCacheConfigurationFactory. This is a basic prototype of a
+ * JBCACHE-1156 solution; only in Hibernate code base for a very short
+ * period.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class JBossCacheFactoryImpl implements JBossCacheFactory {
+    
+    private static final Logger log = LoggerFactory.getLogger(JBossCacheFactoryImpl.class);
+
+    private static final String DOCUMENT_ROOT = "cache-configs";
+    private static final String CONFIG_ROOT = "cache-config";
+    private static final String CONFIG_NAME = "name";
+
+    private static JBossCacheFactoryImpl sharedFactory;
+    private static String sharedChannelFactoryCfg;
+    
+    private XmlConfigurationParser parser;
+    private String configResource;
+    private Map configs = new HashMap();
+    private Map caches = new HashMap();
+    private Map checkouts = new HashMap();
+    private ChannelFactory channelFactory;
+    private boolean started;
+    
+    public JBossCacheFactoryImpl(String configResource, ChannelFactory factory) {
+        
+        parser = new XmlConfigurationParser();
+        this.configResource = configResource;
+        this.channelFactory = factory;
+    }
+    
+    public static synchronized JBossCacheFactory getSharedInstance(String cacheConfigResource, String channelFactoryConfigResource) {
+        
+        if (sharedFactory == null) {
+            ChannelFactory cf = new JChannelFactory();
+            try {
+                cf.setMultiplexerConfig(channelFactoryConfigResource);
+            }
+            catch (Exception e) {
+                throw new CacheException("Problem setting ChannelFactory config", e);
+            }
+            sharedFactory = new JBossCacheFactoryImpl(cacheConfigResource, cf);
+            sharedChannelFactoryCfg = channelFactoryConfigResource;
+        }
+        else {
+            // Validate that the provided resources match the existing singleton
+            if (!sharedFactory.getConfigResource().equals(cacheConfigResource)) {
+                throw new CacheException("Provided cacheConfigResource does " +
+                		"not match the existing shared factory: provided = " + 
+                		cacheConfigResource + "; existing = " + sharedFactory.getConfigResource());
+            }
+            else if (!sharedChannelFactoryCfg.equals(channelFactoryConfigResource)) {
+                throw new IllegalStateException("Provided channelFactoryConfigResource does " +
+                        "not match the existing shared factory: provided = " + 
+                        channelFactoryConfigResource + "; existing = " + sharedChannelFactoryCfg);
+                
+            }
+        }
+        
+        return sharedFactory;
+    }
+    
+    public void start() {
+        if (!started) {
+            this.configs = parser.parseConfigs(configResource);
+            started = true;
+        }
+    }
+    
+    public void stop() {
+        if (started) {
+            synchronized (caches) {
+                for (Iterator it = caches.entrySet().iterator(); it.hasNext(); ) {
+                    Map.Entry entry = (Entry) it.next();
+                    destroyCache((Cache) entry.getValue());
+                    it.remove();
+                }
+                caches.clear();
+                checkouts.clear();
+                configs.clear();
+            }
+            started = false;
+        }
+    }
+    
+    public String getConfigResource() {
+        return configResource;
+    }
+
+    public ChannelFactory getChannelFactory() {
+        return channelFactory;
+    }
+
+    public Set getConfigurationNames()
+    {
+        return new HashSet(configs.keySet());
+    }
+    
+    public Cache getCache(String configName, boolean create) throws Exception
+    {
+        Cache cache = null;
+        synchronized (caches) {
+            cache = (Cache) caches.get(configName);
+            if (cache == null && create) {
+                Configuration config = getConfiguration(configName);
+                cache = DefaultCacheFactory.getInstance().createCache(config, false);
+                registerCache(cache, configName);
+            }
+            else if (cache != null) {
+                incrementCheckout(configName);
+            }
+        }
+        
+        return cache;
+    }
+
+    private int incrementCheckout(String configName) {
+        synchronized (checkouts) {
+            Integer count = (Integer) checkouts.get(configName);
+            if (count == null)
+                count = new Integer(0);
+            Integer newVal = new Integer(count.intValue() + 1);
+            checkouts.put(configName, newVal);
+            return newVal.intValue();
+        }
+    }
+
+    private int decrementCheckout(String configName) {
+        synchronized (checkouts) {
+            Integer count = (Integer) checkouts.get(configName);
+            if (count == null || count.intValue() < 1)
+                throw new IllegalStateException("invalid count of " + count + " for " + configName);
+
+            Integer newVal = new Integer(count.intValue() - 1);
+            checkouts.put(configName, newVal);
+            return newVal.intValue();
+        }
+    }
+    
+    public void registerCache(Cache cache, String configName) {
+        synchronized (caches) {
+            if (caches.containsKey(configName))
+                throw new IllegalStateException(configName + " already registered");
+            caches.put(configName, cache);
+            incrementCheckout(configName);
+        }
+    }
+    
+    public void releaseCache(String configName) {
+
+        synchronized (caches) {
+            if (!caches.containsKey(configName))
+                throw new IllegalStateException(configName + " not registered");
+            if (decrementCheckout(configName) == 0) {
+                Cache cache = (Cache) caches.remove(configName);
+                destroyCache(cache);
+            }
+        }
+    }
+
+    private void destroyCache(Cache cache) {
+        if (cache.getCacheStatus() == CacheStatus.STARTED) {
+            cache.stop();
+        }
+        if (cache.getCacheStatus() != CacheStatus.DESTROYED
+                && cache.getCacheStatus() != CacheStatus.INSTANTIATED) {
+            cache.destroy();
+        }
+    }
+    
+    public Configuration getConfiguration(String configName) throws Exception {
+        Element element = (Element) configs.get(configName);
+        if (element == null)
+            throw new IllegalArgumentException("unknown config " + configName);
+        Configuration config = parser.parseConfig(element);
+        if (channelFactory != null && config.getMultiplexerStack() != null) {
+            config.getRuntimeConfig().setMuxChannelFactory(channelFactory);
+        }
+        return config;
+    }
+    
+    class XmlConfigurationParser extends org.jboss.cache.factories.XmlConfigurationParser {
+
+        public Map parseConfigs(String configs) {
+            InputStream is = getAsInputStreamFromClassLoader(configs);
+            if (is == null)
+            {
+               if (log.isDebugEnabled())
+                  log.debug("Unable to find configuration file " + configs + " in classpath; searching for this file on the filesystem instead.");
+               try
+               {
+                  is = new FileInputStream(configs);
+               }
+               catch (FileNotFoundException e)
+               {
+                  throw new ConfigurationException("Unable to find config file " + configs + " either in classpath or on the filesystem!", e);
+               }
+            }
+
+            return parseConfigs(is);
+        }
+        
+        public Map parseConfigs(InputStream stream) {
+            
+            // loop through all elements in XML.
+            Element root = XmlHelper.getDocumentRoot(stream);
+            NodeList list = root.getElementsByTagName(CONFIG_ROOT);
+            if (list == null || list.getLength() == 0) 
+                throw new ConfigurationException("Can't find " + CONFIG_ROOT + " tag");
+            
+            Map result = new HashMap();
+            
+            for (int i = 0; i < list.getLength(); i++)
+            {
+               org.w3c.dom.Node node = list.item(i);
+               if (node.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
+               {
+                  continue;
+               }
+               
+               Element element = (Element) node;
+               String name = element.getAttribute(CONFIG_NAME);
+               if (name == null || name.trim().length() == 0)
+                   throw new ConfigurationException("Element " + element + " has no name attribute");
+               
+               result.put(name.trim(), element);
+            }
+            
+            return result;
+        }
+        
+        public Configuration parseConfig(Element config) throws Exception {
+
+            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
+            Document doc = builder.newDocument();
+            Element root = doc.createElement(DOCUMENT_ROOT);
+            doc.appendChild(root);
+            Node imported = doc.importNode(config, true);
+            root.appendChild(imported);
+            
+            DOMImplementation domImpl = doc.getImplementation();
+
+            DOMImplementationLS impl = 
+                (DOMImplementationLS)domImpl.getFeature("LS", "3.0");
+
+            LSSerializer writer = impl.createLSSerializer();
+            LSOutput output = impl.createLSOutput();
+            output.setEncoding("UTF-8");
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            output.setByteStream(baos);
+            writer.write(doc, output);
+            
+            ByteArrayInputStream is = new ByteArrayInputStream(baos.toByteArray());            
+            return parseStream(is);
+        } 
+
+
+        @Override
+        protected Element getMBeanElement(Element root)
+        {
+           // This is following JBoss convention.
+           NodeList list = root.getElementsByTagName(CONFIG_ROOT);
+           if (list == null) throw new ConfigurationException("Can't find " + CONFIG_ROOT + " tag");
+
+           if (list.getLength() > 1) throw new ConfigurationException("Has multiple " + CONFIG_ROOT + " tag");
+
+           Node node = list.item(0);
+           Element element = null;
+           if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE)
+           {
+              element = (Element) node;
+           }
+           else
+           {
+              throw new ConfigurationException("Can't find " + CONFIG_ROOT + " element");
+           }
+           return element;
+        }
+        
+        
+    }
+    
+    public static void main(String[] args)
+    {
+        try
+        {
+            JChannelFactory cf = new JChannelFactory();
+            cf.setMultiplexerConfig("stacks.xml");
+            JBossCacheFactoryImpl factory = new JBossCacheFactoryImpl("jbc2-configs.xml", cf);
+            for (Iterator iter = factory.getConfigurationNames().iterator(); iter.hasNext(); )
+            {
+                String name = (String) iter.next();
+                Cache c = factory.getCache(name, true);
+                c.start();
+                System.out.println(name + " == " + c);
+                factory.releaseCache(name);
+                System.out.println(name + " == " + c.getCacheStatus());
+            }
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace(System.out);
+        }
+    }
+}

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiMultiplexingCacheInstanceManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiMultiplexingCacheInstanceManager.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiMultiplexingCacheInstanceManager.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.builder;
+
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cfg.Settings;
+import org.hibernate.util.NamingHelper;
+import org.hibernate.util.PropertiesHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A {@link MultiplexingCacheInstanceManager} that finds its cache factory
+ * in JNDI rather than creating one itself.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class JndiMultiplexingCacheInstanceManager extends MultiplexingCacheInstanceManager {
+    
+    private static final Logger log = LoggerFactory.getLogger(JndiMultiplexingCacheInstanceManager.class);
+    
+    /**
+     * Specifies the JNDI name under which the {@link JBossCacheFactory} to use is bound.
+     * There is no default value -- the user must specify the property.
+     */
+    public static final String CACHE_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.cachefactory";
+
+    /**
+     * Create a new JndiMultiplexingCacheInstanceManager.
+     */
+    public JndiMultiplexingCacheInstanceManager() {
+        super();
+    }
+
+    @Override
+    public void start(Settings settings, Properties properties) throws CacheException {
+        
+        String name = PropertiesHelper.getString(CACHE_FACTORY_RESOURCE_PROP, properties, null);
+        if (name == null)
+            throw new CacheException("Configuration property " + CACHE_FACTORY_RESOURCE_PROP + " not set");
+        
+        JBossCacheFactory cf = locateCacheFactory( name, NamingHelper.getJndiProperties( properties ) );
+        setCacheFactory( cf );        
+        
+        super.start(settings, properties);
+    }
+
+    private JBossCacheFactory locateCacheFactory(String jndiNamespace, Properties jndiProperties) {
+
+        Context ctx = null;
+        try {
+            ctx = new InitialContext( jndiProperties );
+            return (JBossCacheFactory) ctx.lookup( jndiNamespace );
+        }
+        catch (NamingException ne) {
+            String msg = "Unable to retreive Cache from JNDI [" + jndiNamespace + "]";
+            log.info( msg, ne );
+            throw new CacheException( msg );
+        }
+        finally {
+            if ( ctx != null ) {
+                try {
+                    ctx.close();
+                }
+                catch( NamingException ne ) {
+                    log.info( "Unable to release initial context", ne );
+                }
+            }
+        }
+    }
+
+    
+}

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiSharedCacheInstanceManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiSharedCacheInstanceManager.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiSharedCacheInstanceManager.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.builder;
+
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cfg.Settings;
+import org.hibernate.util.NamingHelper;
+import org.hibernate.util.PropertiesHelper;
+import org.jboss.cache.Cache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A {@link SharedCacheInstanceManager} that finds the shared cache in JNDI 
+ * rather than instantiating one from an XML config file.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class JndiSharedCacheInstanceManager extends SharedCacheInstanceManager {
+    
+    private static final Logger log = LoggerFactory.getLogger(JndiSharedCacheInstanceManager.class);
+
+    /**
+     * Specifies the JNDI name under which the {@link Cache} to use is bound.
+     * <p>
+     * Note that although this configuration property has the same name as that by
+     * in {@link SharedCacheInstanceManager#CACHE_RESOURCE_PROP the superclass}, 
+     * the meaning here is different. Note also that in this class' usage
+     * of the property, there is no default value -- the user must specify
+     * the property.
+     */
+    public static final String CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.shared";
+    
+    /**
+     * Create a new JndiSharedCacheInstanceManager.
+     * 
+     */
+    public JndiSharedCacheInstanceManager() {
+        super();
+    }
+
+    @Override
+    protected Cache createSharedCache(Settings settings, Properties properties) {
+        
+        String name = PropertiesHelper.getString(CACHE_RESOURCE_PROP, properties, null);
+        if (name == null)
+            throw new CacheException("Configuration property " + CACHE_RESOURCE_PROP + " not set");
+        
+        return locateCache( name, NamingHelper.getJndiProperties( properties ) );
+    }
+
+    /**
+     * No-op; we don't own the cache so we shouldn't stop it.
+     */
+    @Override
+    protected void stopSharedCache(Cache cache) {
+        // no-op. We don't own the cache so we shouldn't stop it.
+    }
+
+    private Cache locateCache(String jndiNamespace, Properties jndiProperties) {
+
+        Context ctx = null;
+        try {
+            ctx = new InitialContext( jndiProperties );
+            return (Cache) ctx.lookup( jndiNamespace );
+        }
+        catch (NamingException ne) {
+            String msg = "Unable to retreive Cache from JNDI [" + jndiNamespace + "]";
+            log.info( msg, ne );
+            throw new CacheException( msg );
+        }
+        finally {
+            if ( ctx != null ) {
+                try {
+                    ctx.close();
+                }
+                catch( NamingException ne ) {
+                    log.info( "Unable to release initial context", ne );
+                }
+            }
+        }
+    }
+
+}

Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/MultiplexingCacheInstanceManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/MultiplexingCacheInstanceManager.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/MultiplexingCacheInstanceManager.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -19,188 +19,442 @@
 import javax.transaction.TransactionManager;
 
 import org.jboss.cache.Cache;
-import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.CacheStatus;
+import org.jboss.cache.config.Configuration;
+import org.jgroups.ChannelFactory;
+import org.jgroups.JChannelFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.jbc2.CacheInstanceManager;
 import org.hibernate.cfg.Settings;
+import org.hibernate.transaction.TransactionManagerLookup;
 import org.hibernate.util.PropertiesHelper;
 
 /**
- * Here we build separate {@link Cache} instances for each type of region, but
- * using the jgroups multiplexer under the covers to re-use the same group
- * communication stack.
- * <p/>
- * todo : this can get simplified once JBC implemants their "configuration factory" (the stuff akin to channel factory) - http://jira.jboss.com/jira/browse/JBCACHE-1156
+ * Allows building separate {@link Cache} instances for each type of region, but
+ * supports using the JGroups multiplexer under the covers to re-use the same group
+ * communication stack. <p/> todo : replace the prototype cache factory with
+ * the equivalent JBoss Cache solution from
+ * http://jira.jboss.com/jira/browse/JBCACHE-1156
  * 
  * @author Steve Ebersole
+ * @author Brian Stansberry
  */
 public class MultiplexingCacheInstanceManager implements CacheInstanceManager {
-	public static final String ENTITY_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.entity";
-	public static final String COLL_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.collection";
-	public static final String TS_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.ts";
-	public static final String QUERY_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.query";
 
-	public static final String DEF_ENTITY_RESOURCE = "entity-cache.xml";
-	public static final String DEF_COLL_RESOURCE = "collection-cache.xml";
-	public static final String DEF_TS_RESOURCE = "ts-cache.xml";
-	public static final String DEF_QUERY_RESOURCE = "query-cache.xml";
+    private static final Logger log = LoggerFactory.getLogger(MultiplexingCacheInstanceManager.class);
+    
+    /** 
+     * Classpath or filesystem resource identifying containing JBoss Cache 
+     * configurations the factory should use.
+     * 
+     * @see #DEF_CACHE_FACTORY_RESOURCE
+     */
+    public static final String CACHE_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.configs";
+    /**
+     * Classpath or filesystem resource identifying containing JGroups protocol
+     * stack configurations the <code>org.jgroups.ChannelFactory</code>
+     * should use.
+     * 
+     * @see #DEF_MULTIPLEXER_RESOURCE
+     */
+    public static final String CHANNEL_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.multiplexer.stacks";
+    
+    /**
+     * Name of the configuration that should be used for entity caches.
+     * 
+     * @see #DEF_ENTITY_RESOURCE
+     */
+    public static final String ENTITY_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.entity";
+    /**
+     * Name of the configuration that should be used for collection caches.
+     * No default value, as by default we try to use the same JBoss Cache
+     * instance we use for entity caching.
+     * 
+     * @see #ENTITY_CACHE_RESOURCE_PROP
+     * @see #DEF_ENTITY_RESOURCE
+     */
+    public static final String COLLECTION_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.collection";
+    /**
+     * Name of the configuration that should be used for timestamp caches.
+     * 
+     * @see #DEF_TS_RESOURCE
+     */
+    public static final String TIMESTAMP_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.ts";
+    /**
+     * Name of the configuration that should be used for query caches.
+     * 
+     * @see #DEF_QUERY_RESOURCE
+     */
+    public static final String QUERY_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.query";
 
-	public static final String OPTIMISTIC_LOCKING_SCHEME = "OPTIMISTIC";
+    /**
+     * Default value for {@link #CACHE_FACTORY_RESOURCE_PROP}. Specifies
+     * the "jbc2-configs.xml" file in this package.
+     */
+    public static final String DEF_CACHE_FACTORY_RESOURCE = "org/hibernate/cache/jbc2/builder/jbc2-configs.xml";    
+    /**
+     * Default value for {@link #CHANNEL_FACTORY_RESOURCE_PROP}. Specifies
+     * "stacks.xml", which can be found in the root of the JGroups jar file.
+     * Thus, leaving this value at default means using the default protocol
+     * stack configs provided by JGroups.
+     */
+    public static final String DEF_MULTIPLEXER_RESOURCE = "stacks.xml";
+    /**
+     * Default value for {@link #ENTITY_CACHE_RESOURCE_PROP}.
+     */
+    public static final String DEF_ENTITY_RESOURCE = "optimistic-entity";
+    /**
+     * Default value for {@link #TIMESTAMP_CACHE_RESOURCE_PROP}.
+     */
+    public static final String DEF_TS_RESOURCE = "timestamps-cache";
+    /**
+     * Default value for {@link #ENTITY_CACHE_RESOURCE_PROP}.
+     */
+    public static final String DEF_QUERY_RESOURCE = "local-query";
 
-	private static final Logger log = LoggerFactory.getLogger( MultiplexingCacheInstanceManager.class );
+    /** Cache for entities */
+    private Cache jbcEntityCache;
+    /** Cache for collections */
+    private Cache jbcCollectionCache;
+    /** Cache for timestamps */
+    private Cache jbcTsCache;
+    /** Cache for queries */
+    private Cache jbcQueryCache;
+    /** Name of config used for entities. */
+    private String entityConfig = null;
+    /** Name of config used for collections. */
+    private String collectionConfig = null;
+    /** Name of config used for queries. */
+    private String queryConfig = null;
+    /** Name of config used for timestamps. */
+    private String tsConfig = null;
+    
+    /** Our cache factory */
+    private JBossCacheFactory jbcFactory;
+    /** Our channel factory */
+    private ChannelFactory channelFactory;
+    /** 
+     * Did we create the factory ourself and thus can assume we are not
+     * sharing it (and the caches) with other users?
+     */
+    private boolean selfCreatedFactory;
 
-	private final Cache jbcEntityCache;
-	private final Cache jbcCollectionCache;
-	private final Cache jbcTsCache;
-	private final Cache jbcQueryCache;
+    /**
+     * Create a new MultiplexingCacheInstanceManager.
+     */
+    public MultiplexingCacheInstanceManager() {
+    }
+    
+    /**
+     * Create a new MultiplexingCacheInstanceManager using the provided
+     * {@link Cache}s.
+     * <p>
+     * If this constructor is used, the {@link #start(Settings, Properties)}
+     * method will make no attempt to create a cache factory or obtain caches
+     * from it.  Only the <code>Cache</code>s passed as arguments to this
+     * constructor will be available.
+     * </p>
+     * 
+     */
+    public MultiplexingCacheInstanceManager(Cache jbcEntityCache, Cache jbcCollectionCache, 
+                                            Cache jbcTsCache, Cache jbcQueryCache) {
+        
+        this.jbcEntityCache = jbcEntityCache;
+        this.jbcCollectionCache = jbcCollectionCache;
+        this.jbcTsCache = jbcTsCache;
+        this.jbcQueryCache = jbcQueryCache;
+    }
+    
+    /**
+     * Gets the cache factory.
+     */
+    public JBossCacheFactory getCacheFactory() {
+        return jbcFactory;
+    }
 
-	public MultiplexingCacheInstanceManager(Settings settings, Properties properties) {
-		try {
-			TransactionManager tm = settings.getTransactionManagerLookup() == null
-					? null
-					: settings.getTransactionManagerLookup().getTransactionManager( properties );
-			if ( settings.isSecondLevelCacheEnabled() ) {
-				jbcEntityCache = buildEntityRegionCacheInstance( properties );
-				jbcCollectionCache = buildCollectionRegionCacheInstance( properties );
-				if ( tm != null ) {
-					jbcEntityCache.getConfiguration().getRuntimeConfig().setTransactionManager( tm );
-					jbcCollectionCache.getConfiguration().getRuntimeConfig().setTransactionManager( tm );
-				}
-			}
-			else {
-				jbcEntityCache = null;
-				jbcCollectionCache = null;
-			}
-			if ( settings.isQueryCacheEnabled() ) {
-				jbcTsCache = buildTsRegionCacheInstance( properties );
-				jbcQueryCache = buildQueryRegionCacheInstance( properties );
-			}
-			else {
-				jbcTsCache = null;
-				jbcQueryCache = null;
-			}
-		}
-		catch( CacheException ce ) {
-			throw ce;
-		}
-		catch( Throwable t ) {
-			throw new CacheException( "Unable to start region factory", t );
-		}
-	}
+    /**
+     * Sets the cache factory.
+     * @param cacheFactory the cache factory
+     */
+    public void setCacheFactory(JBossCacheFactory factory) {
+        this.jbcFactory = factory;
+    }
+    
+    /**
+     * Gets the channel factory.
+     */
+    public ChannelFactory getChannelFactory() {
+        return channelFactory;
+    }
+    
+    /**
+     * Set the channel factory.
+     * 
+     * @param factory the channel factory
+     */
+    public void setChannelFactory(ChannelFactory factory) {
+        this.channelFactory = factory;
+    }
 
-	public MultiplexingCacheInstanceManager(Cache jbcEntityCache, Cache jbcCollectionCache, Cache jbcTsCache, Cache jbcQueryCache) {
-		this.jbcEntityCache = jbcEntityCache;
-		this.jbcCollectionCache = jbcCollectionCache;
-		this.jbcTsCache = jbcTsCache;
-		this.jbcQueryCache = jbcQueryCache;
-	}
+    /**
+     * {@inheritDoc}
+     */
+    public Cache getEntityCacheInstance() {
+        return jbcEntityCache;
+    }
 
-	protected Cache buildEntityRegionCacheInstance(Properties properties) {
-		try {
-			String configResource = PropertiesHelper.getString( ENTITY_CACHE_RESOURCE_PROP, properties, DEF_ENTITY_RESOURCE );
-			return DefaultCacheFactory.getInstance().createCache( configResource );
-		}
-		catch( Throwable t ) {
-			throw new CacheException( "unable to build entity region cache instance", t );
-		}
-	}
+    /**
+     * {@inheritDoc}
+     */
+    public Cache getCollectionCacheInstance() {
+        return jbcCollectionCache;
+    }
 
-	protected Cache buildCollectionRegionCacheInstance(Properties properties) {
-		try {
-			String configResource = PropertiesHelper.getString( COLL_CACHE_RESOURCE_PROP, properties, DEF_COLL_RESOURCE );
-			return DefaultCacheFactory.getInstance().createCache( configResource );
-		}
-		catch( Throwable t ) {
-			throw new CacheException( "unable to build collection region cache instance", t );
-		}
-	}
+    /**
+     * {@inheritDoc}
+     */
+    public Cache getQueryCacheInstance() {
+        return jbcQueryCache;
+    }
 
-	protected Cache buildTsRegionCacheInstance(Properties properties) {
-		try {
-			String configResource = PropertiesHelper.getString( TS_CACHE_RESOURCE_PROP, properties, DEF_TS_RESOURCE );
-			return DefaultCacheFactory.getInstance().createCache( configResource );
-		}
-		catch( Throwable t ) {
-			throw new CacheException( "unable to build timestamps region cache instance", t );
-		}
-	}
+    /**
+     * {@inheritDoc}
+     */
+    public Cache getTimestampsCacheInstance() {
+        return jbcTsCache;
+    }
 
-	protected Cache buildQueryRegionCacheInstance(Properties properties) {
-		try {
-			String configResource = PropertiesHelper.getString( QUERY_CACHE_RESOURCE_PROP, properties, DEF_QUERY_RESOURCE );
-			return DefaultCacheFactory.getInstance().createCache( configResource );
-		}
-		catch( Throwable t ) {
-			throw new CacheException( "unable to build query region cache instance", t );
-		}
-	}
+    /**
+     * {@inheritDoc}
+     */
+    public void start(Settings settings, Properties properties) throws CacheException {
+        try {
+            // We need our tm, so get it now and avoid doing other work
+            // if there is a problem
+            TransactionManagerLookup tml = settings.getTransactionManagerLookup();
+            TransactionManager tm =  (tml == null ? null : tml.getTransactionManager(properties));
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public Cache getEntityCacheInstance() {
-		return jbcEntityCache;
-	}
+            // We only build caches if *none* were passed in.  Passing in
+            // caches counts as a clear statement of exactly what is wanted
+            boolean buildCaches = jbcEntityCache == null
+                                  && jbcCollectionCache == null
+                                  && jbcTsCache == null
+                                  && jbcQueryCache == null;
+                                  
+            // Set up the cache factory
+            if (buildCaches && jbcFactory == null) {
+                // See if the user configured a multiplexer stack
+                if (channelFactory == null) {
+                    String muxStacks = PropertiesHelper.getString(CHANNEL_FACTORY_RESOURCE_PROP, properties, DEF_MULTIPLEXER_RESOURCE);
+                    if (muxStacks != null) {
+                        channelFactory = new JChannelFactory();
+                        channelFactory.setMultiplexerConfig(muxStacks);
+                    }
+                }
+                
+                String factoryRes = PropertiesHelper.getString(CACHE_FACTORY_RESOURCE_PROP, properties, DEF_CACHE_FACTORY_RESOURCE);
+                // FIXME use an impl from JBossCache
+                jbcFactory = new JBossCacheFactoryImpl(factoryRes, channelFactory);
+                ((JBossCacheFactoryImpl) jbcFactory).start();
+                selfCreatedFactory = true;
+            }
+            
+            if (settings.isSecondLevelCacheEnabled()) {
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public Cache getCollectionCacheInstance() {
-		return jbcCollectionCache;
-	}
+                if (buildCaches) {
+                    entityConfig = PropertiesHelper
+                            .getString(ENTITY_CACHE_RESOURCE_PROP, properties, DEF_ENTITY_RESOURCE);
+                    jbcEntityCache = jbcFactory.getCache(entityConfig, true);
+                
+                    // Default to collections sharing entity cache if there is one
+                    collectionConfig = PropertiesHelper.getString(COLLECTION_CACHE_RESOURCE_PROP, properties, entityConfig);
+                    if (entityConfig.equals(collectionConfig)) {
+                        jbcCollectionCache = jbcEntityCache;
+                    }
+                    else {
+                        jbcCollectionCache = jbcFactory.getCache(collectionConfig, true);
+                    }
+                }
+                
+                if (jbcEntityCache != null) {
+                    configureTransactionManager(jbcEntityCache, tm, false);
+                    jbcEntityCache.start();
+                }
+                if (jbcCollectionCache != null) {
+                    configureTransactionManager(jbcCollectionCache, tm, false);
+                    jbcCollectionCache.start();
+                }
+                
+            } 
+            else {
+                jbcEntityCache = null;
+                jbcCollectionCache = null;
+            }
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public Cache getQueryCacheInstance() {
-		return jbcQueryCache;
-	}
+            if (settings.isQueryCacheEnabled()) {
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public Cache getTimestampsCacheInstance() {
-		return jbcTsCache;
-	}
+                if (buildCaches) {
+                    // Default to sharing the entity cache if there is one
+                    String dfltQueryResource = (entityConfig == null ? DEF_QUERY_RESOURCE : entityConfig);
+                    queryConfig = PropertiesHelper.getString(QUERY_CACHE_RESOURCE_PROP, properties, dfltQueryResource);
+                    if (queryConfig.equals(entityConfig)) {
+                        jbcQueryCache = jbcEntityCache;
+                    } else if (queryConfig.equals(collectionConfig)) {
+                        jbcQueryCache = jbcCollectionCache;
+                    } else {
+                        jbcQueryCache = jbcFactory.getCache(queryConfig, true);
+                    }
+    
+                    // For Timestamps, we default to a separate config
+                    tsConfig = PropertiesHelper.getString(TIMESTAMP_CACHE_RESOURCE_PROP, properties, DEF_TS_RESOURCE);
+                    if (tsConfig.equals(queryConfig)) {
+                        jbcTsCache = jbcQueryCache;
+                    }
+                    else if (tsConfig.equals(entityConfig)) {
+                        jbcTsCache = jbcEntityCache;
+                    } 
+                    else if (tsConfig.equals(collectionConfig)) {
+                        jbcTsCache = jbcCollectionCache;
+                    } 
+                    else {
+                        jbcTsCache = jbcFactory.getCache(tsConfig, true);
+                    }
+                }
+                
+                if (jbcQueryCache != null) {
+                    configureTransactionManager(jbcQueryCache, tm, false);
+                    jbcQueryCache.start();
+                }
+                if (jbcTsCache != null) {
+                    configureTransactionManager(jbcTsCache, tm, true);
+                    jbcTsCache.start();
+                }
+            } 
+            else {
+                jbcTsCache = null;
+                jbcQueryCache = null;
+            }
+        } 
+        catch (CacheException ce) {
+            throw ce;
+        }
+        catch (Throwable t) {
+            throw new CacheException("Unable to start region factory", t);
+        }
+    }
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public void release() {
-		if ( jbcEntityCache != null ) {
-			try {
-				jbcEntityCache.stop();
-			}
-			catch( Throwable t ) {
-				log.info( "Unable to stop entity cache instance", t );
-			}
-		}
-		if ( jbcCollectionCache != null ) {
-			try {
-				jbcCollectionCache.stop();
-			}
-			catch( Throwable t ) {
-				log.info( "Unable to stop collection cache instance", t );
-			}
-		}
-		if ( jbcTsCache != null ) {
-			try {
-				jbcTsCache.stop();
-			}
-			catch( Throwable t ) {
-				log.info( "Unable to stop timestamp cache instance", t );
-			}
-		}
-		if ( jbcQueryCache != null ) {
-			try {
-				jbcQueryCache.stop();
-			}
-			catch( Throwable t ) {
-				log.info( "Unable to stop query cache instance", t );
-			}
-		}
-	}
+    /**
+     * {@inheritDoc}
+     */
+    public void stop() {
+        releaseCaches();
+        if (selfCreatedFactory) {
+            ((JBossCacheFactoryImpl) jbcFactory).stop();
+        }
+    }
+
+    /**
+     * Injects the given TransactionManager into the cache.
+     * 
+     * @param cache    the cache. cannot be <code>null</code>
+     * @param tm        the transaction manager Hibernate recognizes
+     *                  May be <code>null</code>
+     * @param allowNull whether we accept a null transaction manager in the cache
+     *                  if <code>tm</code> is not <code>null</code>
+     * 
+     * @throws CacheException if <code>cache</code> is already started and is 
+     *                        configured with a different TransactionManager
+     *                        than the one we would inject
+     */
+    private void configureTransactionManager(Cache cache, TransactionManager tm, boolean allowNull) {
+        Configuration cacheConfig = cache.getConfiguration();
+        TransactionManager cacheTm = cacheConfig.getRuntimeConfig().getTransactionManager();
+        if (!safeEquals(tm, cacheTm)) {
+            if (cache.getCacheStatus() != CacheStatus.INSTANTIATED) {
+                // We can't change the TM on a running cache; just check
+                // if the cache has no TM and we're OK with that
+                if (!allowNull || cacheTm != null) {
+                    throw new CacheException("JBoss Cache is already started " + "with a transaction manager ("
+                            + cacheTm + ") that doesn't match our own (" + tm + ")");
+                }
+            } else {
+                // Configure the cache to use our TM
+                cacheConfig.getRuntimeConfig().setTransactionManager(tm);
+                if (tm == null) {
+                    // Make sure JBC doesn't look one up
+                    cacheConfig.setTransactionManagerLookupClass(null);
+                }
+            }
+        }
+    }
+
+    /**
+     * Notify cache factory that we are no longer using the caches.  
+     */
+    private void releaseCaches() {
+        
+        // This method should be implemented assuming it's valid to 
+        // do start/stop/start -- leave state appropriate for another start
+        
+        if (jbcEntityCache != null  && entityConfig != null) {
+            try {
+                jbcFactory.releaseCache(entityConfig);
+                jbcEntityCache = null;
+                
+                // Make sure we don't re-release the same cache
+                if (entityConfig.equals(collectionConfig))
+                    collectionConfig = null;
+                if (entityConfig.equals(queryConfig))
+                    queryConfig = null;
+                if (entityConfig.equals(tsConfig))
+                    tsConfig = null;
+                entityConfig = null;
+            } catch (Throwable t) {
+                log.info("Unable to release entity cache instance", t);
+            }
+        }
+        if (jbcCollectionCache != null && collectionConfig != null) {
+            try {
+                jbcFactory.releaseCache(collectionConfig);
+                jbcCollectionCache = null;
+                
+                if (collectionConfig.equals(queryConfig))
+                    queryConfig = null;
+                if (collectionConfig.equals(tsConfig))
+                    tsConfig = null;
+                collectionConfig = null;
+            } catch (Throwable t) {
+                log.info("Unable to stop collection cache instance", t);
+            }
+        }
+        if (jbcQueryCache != null && queryConfig != null) {
+            try {
+                jbcFactory.releaseCache(queryConfig);
+                jbcQueryCache = null;
+                
+                if (queryConfig.equals(tsConfig))
+                    tsConfig = null;
+                queryConfig = null;
+            } catch (Throwable t) {
+                log.info("Unable to stop query cache instance", t);
+            }
+        }
+        if (jbcTsCache != null && tsConfig != null) {
+            try {
+                jbcFactory.releaseCache(tsConfig);
+                jbcTsCache = null;
+                
+                tsConfig = null;
+            } catch (Throwable t) {
+                log.info("Unable to stop timestamp cache instance", t);
+            }
+        }
+    }
+
+    private boolean safeEquals(Object a, Object b) {
+        return (a == b || (a != null && a.equals(b)));
+    }
 }

Copied: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/SharedCacheInstanceManager.java (from rev 14071, core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/InvalidationCacheInstanceManager.java)
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/SharedCacheInstanceManager.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/SharedCacheInstanceManager.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.cache.jbc2.builder;
+
+import java.util.Properties;
+import javax.transaction.TransactionManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheStatus;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.config.Configuration;
+import org.jgroups.ChannelFactory;
+import org.jgroups.JChannelFactory;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cfg.Settings;
+import org.hibernate.util.PropertiesHelper;
+
+/**
+ * A {@link CacheInstanceManager} implementation where we use a single cache
+ * instance we assume to be configured for invalidation if operating on a
+ * cluster. Under that assumption, we can store all data into the same
+ * {@link Cache} instance.
+ * 
+ * @author Steve Ebersole
+ */
+public class SharedCacheInstanceManager implements CacheInstanceManager {
+    
+    private static final Logger log = LoggerFactory.getLogger(SharedCacheInstanceManager.class);
+
+    /**
+     * Classpath or filesystem resource identifying containing JBoss Cache 
+     * configuration settings the {@link Cache} should use.
+     * 
+     * @see #DEFAULT_CACHE_RESOURCE
+     */
+    public static final String CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.shared";
+    
+    /**
+     * Default name for the JBoss Cache configuration file.
+     */
+    public static final String DEFAULT_CACHE_RESOURCE = "treecache.xml";
+    /**
+     * Classpath or filesystem resource identifying containing JGroups protocol
+     * stack configurations the <code>org.jgroups.ChannelFactory</code>
+     * should use.
+     * 
+     * @see #DEF_MULTIPLEXER_RESOURCE
+     */
+    public static final String CHANNEL_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.multiplexer.stacks";
+    /**
+     * Default value for {@link #CHANNEL_FACTORY_RESOURCE_PROP}. Specifies
+     * "stacks.xml", which can be found in the root of the JGroups jar file.
+     * Thus, leaving this value at default means using the default protocol
+     * stack configs provided by JGroups.
+     */
+    public static final String DEF_MULTIPLEXER_RESOURCE = "stacks.xml";
+
+    private Cache cache;
+    private ChannelFactory channelFactory;
+    private boolean use2ndLevel;
+    private boolean useQuery;
+    
+    public SharedCacheInstanceManager() {
+    }
+
+    public SharedCacheInstanceManager(ChannelFactory channelFactory) {
+        this.channelFactory = channelFactory;
+    }
+    
+    public SharedCacheInstanceManager(Cache cache) {
+        this.cache = cache;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Cache getEntityCacheInstance() {
+        return use2ndLevel ? cache : null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Cache getCollectionCacheInstance() {
+        return use2ndLevel ? cache : null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Cache getQueryCacheInstance() {
+        
+        if (!useQuery)
+            return null;
+        
+        if (CacheHelper.isClusteredInvalidation(cache)) {
+            throw new CacheException("Query cache not supported for clustered invalidation");
+        }
+        return cache;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void start(Settings settings, Properties properties) throws CacheException {
+
+        use2ndLevel = settings.isSecondLevelCacheEnabled();
+        useQuery = settings.isQueryCacheEnabled();
+        
+        if (cache == null) {
+            
+            if (channelFactory == null) {
+                String muxStacks = PropertiesHelper.getString(CHANNEL_FACTORY_RESOURCE_PROP, properties, DEF_MULTIPLEXER_RESOURCE);
+                if (muxStacks != null) {
+                    channelFactory = new JChannelFactory();
+                    try {
+                        channelFactory.setMultiplexerConfig(muxStacks);
+                    }
+                    catch (Exception e) {
+                        throw new CacheException("Problem setting ChannelFactory config", e);
+                    }
+                }
+            }
+            cache = createSharedCache(settings, properties);
+            configureTransactionManager(cache, settings, properties);
+            if (cache.getConfiguration().getMultiplexerStack() != null
+                    && cache.getConfiguration().getRuntimeConfig().getMuxChannelFactory() == null) {
+                cache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(channelFactory);
+            }
+        }
+        cache.start();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Cache getTimestampsCacheInstance() {
+        
+        if (!useQuery)
+            return null;
+        
+        if (CacheHelper.isClusteredInvalidation(cache)) {
+            throw new CacheException("Query cache not supported for clustered invalidation");
+        }
+        return cache;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void stop() {
+        if (cache != null) {
+            stopSharedCache(cache);
+        }
+    }
+
+    /**
+     * Create a cache using the given settings and properties.
+     * 
+     * @param settings
+     * @param properties
+     * @return
+     */
+    protected Cache createSharedCache(Settings settings, Properties properties)
+    {
+        String configResource = PropertiesHelper.getString(CACHE_RESOURCE_PROP, properties, DEFAULT_CACHE_RESOURCE);
+        return DefaultCacheFactory.getInstance().createCache(configResource, false);
+    }
+    
+    /**
+     * Injects the TransactionManager found via {@link Settings#getTransactionManagerLookup()}
+     * into the cache.
+     * 
+     * @param cache
+     * @param settings
+     * @param properties
+     * 
+     * @throws CacheException if <code>cache</code> is already started and is 
+     *                        configured with a different TransactionManager
+     *                        than the one we would inject
+     */
+    protected void configureTransactionManager(Cache cache, Settings settings, Properties properties) {
+        
+        TransactionManager tm = null;
+        if (settings.getTransactionManagerLookup() != null) {
+            tm = settings.getTransactionManagerLookup().getTransactionManager(properties);
+        }
+        
+        Configuration cacheConfig = cache.getConfiguration();
+        TransactionManager cacheTm = cacheConfig.getRuntimeConfig().getTransactionManager();
+        
+        if (!safeEquals(tm, cacheTm)) {            
+            if (cache.getCacheStatus() != CacheStatus.INSTANTIATED
+                    && cache.getCacheStatus() != CacheStatus.DESTROYED) {
+                throw new CacheException("JBoss Cache is already started " + "with a transaction manager ("
+                            + cacheTm + ") that doesn't match our own (" + tm + ")");
+            } else {
+                // Configure the cache to use our TM
+                cacheConfig.getRuntimeConfig().setTransactionManager(tm);
+                if (tm == null) {
+                    // Make sure JBC doesn't look one up
+                    cacheConfig.setTransactionManagerLookupClass(null);
+                }
+            }
+        }
+    }
+
+    private boolean safeEquals(Object a, Object b) {
+        return (a == b || (a != null && a.equals(b)));
+    }
+
+    /**
+     * Stops the shared cache.
+     * @param cache the shared cache
+     */
+    protected void stopSharedCache(Cache cache) {
+        try {
+            if (cache.getCacheStatus() == CacheStatus.STARTED) {
+                cache.stop();
+            }
+            if (cache.getCacheStatus() != CacheStatus.DESTROYED
+                    && cache.getCacheStatus() != CacheStatus.INSTANTIATED) {
+                cache.destroy();
+            }
+        } catch (Throwable t) {
+            log.warn("Unable to stop cache instance", t);
+        }
+    }
+}

Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -16,6 +16,8 @@
 package org.hibernate.cache.jbc2.collection;
 
 import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Configuration.NodeLockingScheme;
 
 import org.hibernate.cache.CacheDataDescription;
 import org.hibernate.cache.CacheException;
@@ -25,25 +27,35 @@
 import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
 
 /**
- * Defines the behavior of the collection cache regions for JBossCache.
- *
+ * Defines the behavior of the collection cache regions for JBossCache 2.x.
+ * 
  * @author Steve Ebersole
  */
 public class CollectionRegionImpl extends TransactionalDataRegionAdapter implements CollectionRegion {
-	public CollectionRegionImpl(Cache jbcCache, String regionName, CacheDataDescription metadata) {
-		super( jbcCache, regionName, metadata );
-	}
 
-	public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
-		if ( AccessType.READ_ONLY.equals( accessType ) ) {
-			return new ReadOnlyAccess( this );
-		}
-		if ( AccessType.TRANSACTIONAL.equals( accessType ) ) {
-			return new TransactionalAccess( this );
-		}
+    public static final String TYPE = "COLL";
+    private boolean optimistic;
 
-		// todo : add support for READ_WRITE ( + NONSTRICT_READ_WRITE ??? )
+    public CollectionRegionImpl(Cache jbcCache, String regionName, String regionPrefix, CacheDataDescription metadata) {
+        super(jbcCache, regionName, regionPrefix, metadata);
+        optimistic = (jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC);
+    }
 
-		throw new CacheException( "unsupported access type [" + accessType.getName() + "]" );
-	}
+    public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
+        if (AccessType.READ_ONLY.equals(accessType)) {
+            return optimistic ? new OptimisticReadOnlyAccess(this) : new ReadOnlyAccess(this);
+        }
+        if (AccessType.TRANSACTIONAL.equals(accessType)) {
+            return optimistic ? new OptimisticTransactionalAccess(this) : new TransactionalAccess(this);
+        }
+
+        // todo : add support for READ_WRITE ( + NONSTRICT_READ_WRITE ??? )
+
+        throw new CacheException("unsupported access type [" + accessType.getName() + "]");
+    }
+
+    @Override
+    protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
+        return getTypeLastRegionFqn(regionName, regionPrefix, TYPE);
+    }
 }

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticReadOnlyAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticReadOnlyAccess.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticReadOnlyAccess.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.collection;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.SoftLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This defines the strategy for transactional access to collection data in an
+ * optimistic-locking JBossCache using its 2.x APIs. <p/> The read-only access
+ * to a JBossCache really is still transactional, just with the extra semantic
+ * or guarantee that we will not update data.
+ * 
+ * @author Brian Stansberry
+ */
+public class OptimisticReadOnlyAccess extends OptimisticTransactionalAccess {
+
+    private static final Logger log = LoggerFactory.getLogger(OptimisticReadOnlyAccess.class);
+
+    /**
+     * Create a new OptimisticReadOnlyAccess.
+     * 
+     * @param region
+     */
+    public OptimisticReadOnlyAccess(CollectionRegionImpl region) {
+        super(region);
+    }
+
+    @Override
+    public SoftLock lockItem(Object key, Object version) throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+    }
+
+    @Override
+    public SoftLock lockRegion() throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only region");
+    }
+
+    @Override
+    public void unlockItem(Object key, SoftLock lock) throws CacheException {
+        log.error("Illegal attempt to edit read only item");
+    }
+
+    @Override
+    public void unlockRegion(SoftLock lock) throws CacheException {
+        log.error("Illegal attempt to edit read only region");
+    }
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticReadOnlyAccess.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.collection;
+
+import org.hibernate.cache.jbc2.access.OptimisticTransactionalAccessDelegate;
+
+/**
+ * Defines the strategy for transactional access to entity data in an
+ * optimistic-locking JBoss Cache using its 2.x APIs
+ * 
+ * @author Brian Stansberry
+ * @version $Revision: 1 $
+ */
+public class OptimisticTransactionalAccess extends TransactionalAccess {
+
+    /**
+     * Create a new OptimisticTransactionalAccess.
+     * 
+     * @param region
+     */
+    public OptimisticTransactionalAccess(CollectionRegionImpl region) {
+        
+        // We use a different delegate than the non-optimistic superclass default
+        super(region, new OptimisticTransactionalAccessDelegate(region.getCacheInstance(), region.getRegionFqn(),
+                region.getCacheDataDescription()));
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java
___________________________________________________________________
Name: svn:executable
   + *

Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/ReadOnlyAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/ReadOnlyAccess.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/ReadOnlyAccess.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -22,50 +22,37 @@
 import org.hibernate.cache.CacheException;
 
 /**
- * This defines the strategy for transactional access to enity data in JBossCache using its 2.x APIs
- * <p/>
- * read-only access to a JBossCache really is still transactional, just with
- * the extra semantic or guarentee that we will not update data.
- *
+ * This defines the strategy for transactional access to collection data in a
+ * pessimistic-locking JBossCache using its 2.x APIs. <p/> The read-only access
+ * to a JBossCache really is still transactional, just with the extra semantic
+ * or guarantee that we will not update data.
+ * 
  * @author Steve Ebersole
  */
 public class ReadOnlyAccess extends TransactionalAccess {
-	private static final Logger log = LoggerFactory.getLogger( ReadOnlyAccess.class );
+    private static final Logger log = LoggerFactory.getLogger(ReadOnlyAccess.class);
 
-	public ReadOnlyAccess(CollectionRegionImpl region) {
-		super( region );
-	}
+    public ReadOnlyAccess(CollectionRegionImpl region) {
+        super(region);
+    }
 
-	public SoftLock lockItem(Object key, Object version) throws CacheException {
-		throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
-	}
+    @Override
+    public SoftLock lockItem(Object key, Object version) throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+    }
 
-	public SoftLock lockRegion() throws CacheException {
-		throw new UnsupportedOperationException( "Illegal attempt to edit read only region" );
-	}
+    @Override
+    public SoftLock lockRegion() throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only region");
+    }
 
-	public void unlockItem(Object key, SoftLock lock) throws CacheException {
-		log.error( "Illegal attempt to edit read only item" );
-	}
+    @Override
+    public void unlockItem(Object key, SoftLock lock) throws CacheException {
+        log.error("Illegal attempt to edit read only item");
+    }
 
-	public void unlockRegion(SoftLock lock) throws CacheException {
-		log.error( "Illegal attempt to edit read only region" );
-	}
-
-	public boolean update(
-			Object key,
-			Object value,
-			Object currentVersion,
-			Object previousVersion) throws CacheException {
-		throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
-	}
-
-	public boolean afterUpdate(
-			Object key,
-			Object value,
-			Object currentVersion,
-			Object previousVersion,
-			SoftLock lock) throws CacheException {
-		throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
-	}
+    @Override
+    public void unlockRegion(SoftLock lock) throws CacheException {
+        log.error("Illegal attempt to edit read only region");
+    }
 }

Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -15,68 +15,100 @@
  */
 package org.hibernate.cache.jbc2.collection;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
 import org.hibernate.cache.access.CollectionRegionAccessStrategy;
 import org.hibernate.cache.access.SoftLock;
-import org.hibernate.cache.CollectionRegion;
-import org.hibernate.cache.CacheException;
+import org.hibernate.cache.jbc2.access.TransactionalAccessDelegate;
 
 /**
- * todo : implement
- *
+ * This defines the strategy for transactional access to collection data in a
+ * pessimistic-locking JBossCache using its 2.x APIs
+ * 
  * @author Steve Ebersole
+ * @author Brian Stansberry
  */
 public class TransactionalAccess implements CollectionRegionAccessStrategy {
-	private static final Logger log = LoggerFactory.getLogger( TransactionalAccess.class );
 
-	private final CollectionRegionImpl region;
+    private final CollectionRegionImpl region;
 
-	public TransactionalAccess(CollectionRegionImpl region) {
-		this.region = region;
-	}
+    /**
+     * Most of our logic is shared between this and entity regions, so we
+     * delegate to a class that encapsulates it
+     */
+    private final TransactionalAccessDelegate delegate;
 
-	public CollectionRegion getRegion() {
-		return region;
-	}
+    /**
+     * Create a new TransactionalAccess.
+     * 
+     * @param region
+     */
+    public TransactionalAccess(CollectionRegionImpl region) {
+        this(region, new TransactionalAccessDelegate(region.getCacheInstance(), region.getRegionFqn()));
+    }
 
-	public Object get(Object key, long txTimestamp) throws CacheException {
-		return null;
-	}
+    /**
+     * Allow subclasses to define the delegate.
+     * 
+     * @param region
+     * @param delegate
+     */
+    protected TransactionalAccess(CollectionRegionImpl region, TransactionalAccessDelegate delegate) {
+        this.region = region;
+        this.delegate = delegate;
+    }
 
-	public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
-		return false;
-	}
+    public CollectionRegion getRegion() {
+        return region;
+    }
 
-	public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
-			throws CacheException {
-		return false;
-	}
+    public Object get(Object key, long txTimestamp) throws CacheException {
 
-	public SoftLock lockItem(Object key, Object version) throws CacheException {
-		return null;
-	}
+        return delegate.get(key, txTimestamp);
+    }
 
-	public SoftLock lockRegion() throws CacheException {
-		return null;
-	}
+    public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
 
-	public void unlockItem(Object key, SoftLock lock) throws CacheException {
-	}
+        return delegate.putFromLoad(key, value, txTimestamp, version);
+    }
 
-	public void unlockRegion(SoftLock lock) throws CacheException {
-	}
+    public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+            throws CacheException {
 
-	public void remove(Object key) throws CacheException {
-	}
+        return delegate.putFromLoad(key, value, txTimestamp, version, minimalPutOverride);
+    }
 
-	public void removeAll() throws CacheException {
-	}
+    public void remove(Object key) throws CacheException {
 
-	public void evict(Object key) throws CacheException {
-	}
+        delegate.remove(key);
+    }
 
-	public void evictAll() throws CacheException {
-	}
+    public void removeAll() throws CacheException {
+        delegate.removeAll();
+    }
+
+    public void evict(Object key) throws CacheException {
+        delegate.evict(key);
+    }
+
+    public void evictAll() throws CacheException {
+        delegate.evictAll();
+    }
+
+    // Following methods we don't delegate since they have so little logic
+    // it's clearer to just implement them here
+
+    public SoftLock lockItem(Object key, Object version) throws CacheException {
+        return null;
+    }
+
+    public SoftLock lockRegion() throws CacheException {
+        return null;
+    }
+
+    public void unlockItem(Object key, SoftLock lock) throws CacheException {
+    }
+
+    public void unlockRegion(SoftLock lock) throws CacheException {
+    }
 }

Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -16,6 +16,8 @@
 package org.hibernate.cache.jbc2.entity;
 
 import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Configuration.NodeLockingScheme;
 
 import org.hibernate.cache.CacheDataDescription;
 import org.hibernate.cache.CacheException;
@@ -26,28 +28,39 @@
 
 /**
  * Defines the behavior of the entity cache regions for JBossCache.
- *
+ * 
  * @author Steve Ebersole
  */
 public class EntityRegionImpl extends TransactionalDataRegionAdapter implements EntityRegion {
 
-	public EntityRegionImpl(Cache jbcCache, String regionName, CacheDataDescription metadata) {
-		super( jbcCache, regionName, metadata );
-	}
+    public static final String TYPE = "ENTITY";
+    
+    private boolean optimistic;
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
-		if ( AccessType.READ_ONLY.equals( accessType ) ) {
-			return new ReadOnlyAccess( this );
-		}
-		if ( AccessType.TRANSACTIONAL.equals( accessType ) ) {
-			return new TransactionalAccess( this );
-		}
+    public EntityRegionImpl(Cache jbcCache, String regionName, String regionPrefix, CacheDataDescription metadata) {
+        super(jbcCache, regionName, regionPrefix, metadata);
+        optimistic = (jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC);
+    }
 
-		// todo : add support for READ_WRITE ( + NONSTRICT_READ_WRITE ??? )
+    /**
+     * {@inheritDoc}
+     */
+    public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
+        if (AccessType.READ_ONLY.equals(accessType)) {
+            return optimistic ? new OptimisticReadOnlyAccess(this) : new ReadOnlyAccess(this);
+        }
+        if (AccessType.TRANSACTIONAL.equals(accessType)) {
+            return optimistic ? new OptimisticTransactionalAccess(this) : new TransactionalAccess(this);
+        }
 
-		throw new CacheException( "unsupported access type [" + accessType.getName() + "]" );
-	}
+        // todo : add support for READ_WRITE ( + NONSTRICT_READ_WRITE ??? )
+
+        throw new CacheException("unsupported access type [" + accessType.getName() + "]");
+    }
+
+    @Override
+    protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
+        return getTypeLastRegionFqn(regionName, regionPrefix, TYPE);
+    }
+
 }

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticReadOnlyAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticReadOnlyAccess.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticReadOnlyAccess.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.cache.jbc2.entity;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.CacheException;
+
+/**
+ * This defines the strategy for read-only access to enity data in an
+ * optimistic-locking JBossCache using its 2.x APIs <p/> The read-only access to
+ * a JBossCache really is still transactional, just with the extra semantic or
+ * guarantee that we will not update data.
+ * 
+ * @author Brian Stansberry
+ */
+public class OptimisticReadOnlyAccess extends OptimisticTransactionalAccess {
+    private static final Logger log = LoggerFactory.getLogger(OptimisticReadOnlyAccess.class);
+
+    public OptimisticReadOnlyAccess(EntityRegionImpl region) {
+        super(region);
+    }
+
+    @Override
+    public SoftLock lockItem(Object key, Object version) throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+    }
+
+    @Override
+    public SoftLock lockRegion() throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only region");
+    }
+
+    @Override
+    public void unlockItem(Object key, SoftLock lock) throws CacheException {
+        log.error("Illegal attempt to edit read only item");
+    }
+
+    @Override
+    public void unlockRegion(SoftLock lock) throws CacheException {
+        log.error("Illegal attempt to edit read only region");
+    }
+
+    @Override
+    public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
+            throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+    }
+
+    @Override
+    public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
+            throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+    }
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticReadOnlyAccess.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.entity;
+
+import org.hibernate.cache.jbc2.access.OptimisticTransactionalAccessDelegate;
+
+/**
+ * Defines the strategy for transactional access to entity data in an
+ * optimistic-locking JBoss Cache using its 2.x APIs
+ * 
+ * @author Brian Stansberry
+ * @version $Revision: 1 $
+ */
+public class OptimisticTransactionalAccess extends TransactionalAccess {
+
+    /**
+     * Create a new OptimisticTransactionalAccess.
+     * 
+     * @param region
+     */
+    public OptimisticTransactionalAccess(EntityRegionImpl region) {
+        super(region, new OptimisticTransactionalAccessDelegate(region.getCacheInstance(), region.getRegionFqn(),
+                region.getCacheDataDescription()));
+    }
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java
___________________________________________________________________
Name: svn:executable
   + *

Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/ReadOnlyAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/ReadOnlyAccess.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/ReadOnlyAccess.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -22,50 +22,49 @@
 import org.hibernate.cache.CacheException;
 
 /**
- * This defines the strategy for transactional access to enity data in JBossCache using its 2.x APIs
- * <p/>
- * read-only access to a JBossCache really is still transactional, just with
- * the extra semantic or guarentee that we will not update data.
- *
+ * This defines the strategy for transactional access to enity data in
+ * JBossCache using its 2.x APIs <p/> read-only access to a JBossCache really is
+ * still transactional, just with the extra semantic or guarentee that we will
+ * not update data.
+ * 
  * @author Steve Ebersole
  */
 public class ReadOnlyAccess extends TransactionalAccess {
-	private static final Logger log = LoggerFactory.getLogger( ReadOnlyAccess.class );
+    private static final Logger log = LoggerFactory.getLogger(ReadOnlyAccess.class);
 
-	public ReadOnlyAccess(EntityRegionImpl region) {
-		super( region );
-	}
+    public ReadOnlyAccess(EntityRegionImpl region) {
+        super(region);
+    }
 
-	public SoftLock lockItem(Object key, Object version) throws CacheException {
-		throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
-	}
+    @Override
+    public SoftLock lockItem(Object key, Object version) throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+    }
 
-	public SoftLock lockRegion() throws CacheException {
-		throw new UnsupportedOperationException( "Illegal attempt to edit read only region" );
-	}
+    @Override
+    public SoftLock lockRegion() throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only region");
+    }
 
-	public void unlockItem(Object key, SoftLock lock) throws CacheException {
-		log.error( "Illegal attempt to edit read only item" );
-	}
+    @Override
+    public void unlockItem(Object key, SoftLock lock) throws CacheException {
+        log.error("Illegal attempt to edit read only item");
+    }
 
-	public void unlockRegion(SoftLock lock) throws CacheException {
-		log.error( "Illegal attempt to edit read only region" );
-	}
+    @Override
+    public void unlockRegion(SoftLock lock) throws CacheException {
+        log.error("Illegal attempt to edit read only region");
+    }
 
-	public boolean update(
-			Object key,
-			Object value,
-			Object currentVersion,
-			Object previousVersion) throws CacheException {
-		throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
-	}
+    @Override
+    public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
+            throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+    }
 
-	public boolean afterUpdate(
-			Object key,
-			Object value,
-			Object currentVersion,
-			Object previousVersion,
-			SoftLock lock) throws CacheException {
-		throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
-	}
+    @Override
+    public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
+            throws CacheException {
+        throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+    }
 }

Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -15,145 +15,108 @@
  */
 package org.hibernate.cache.jbc2.entity;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.lock.TimeoutException;
-
 import org.hibernate.cache.access.EntityRegionAccessStrategy;
 import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.jbc2.access.TransactionalAccessDelegate;
 import org.hibernate.cache.EntityRegion;
 import org.hibernate.cache.CacheException;
 
 /**
- * This defines the strategy for transactional access to enity data
- * in JBossCache using its 2.x APIs
- *
+ * Defines the strategy for transactional access to entity data in a
+ * pessimistic-locking JBossCache using its 2.x APIs
+ * 
  * @author Steve Ebersole
  */
 public class TransactionalAccess implements EntityRegionAccessStrategy {
-	private static final Logger log = LoggerFactory.getLogger( TransactionalAccess.class );
 
-	private final EntityRegionImpl region;
+    protected final EntityRegionImpl region;
 
-	public TransactionalAccess(EntityRegionImpl region) {
-		this.region = region;
-	}
+    /**
+     * Most of our logic is shared between this and entity regions, so we
+     * delegate to a class that encapsulates it
+     */
+    private final TransactionalAccessDelegate delegate;
 
-	public EntityRegion getRegion() {
-		return region;
-	}
+    public TransactionalAccess(EntityRegionImpl region) {
+        this(region, new TransactionalAccessDelegate(region.getCacheInstance(), region.getRegionFqn()));
+    }
 
-	public Object get(Object key, long txTimestamp) throws CacheException {
-		try {
-			return region.getCacheInstance().get( region.getRegionFqn(), EntityRegionImpl.ITEM );
-		}
-		catch ( Exception e ) {
-			throw new CacheException( e );
-		}
-	}
+    protected TransactionalAccess(EntityRegionImpl region, TransactionalAccessDelegate delegate) {
+        this.region = region;
+        this.delegate = delegate;
+    }
 
-	public boolean putFromLoad(
-			Object key,
-			Object value,
-			long txTimestamp,
-			Object version) throws CacheException {
-		try {
-			region.getCacheInstance().putForExternalRead( new Fqn( region.getRegionFqn(), key ), EntityRegionImpl.ITEM, value );
-			return true;
-		}
-		catch ( TimeoutException te) {
-			//ignore!
-			log.debug( "ignoring write lock acquisition failure" );
-			return false;
-		}
-		catch ( Throwable t ) {
-			throw new CacheException( t );
-		}
-	}
+    public EntityRegion getRegion() {
+        return region;
+    }
 
-	public boolean putFromLoad(
-			Object key,
-			Object value,
-			long txTimestamp,
-			Object version,
-			boolean minimalPutOverride) throws CacheException {
-		if ( minimalPutOverride && get( key, txTimestamp ) != null ) {
-			if ( log.isDebugEnabled() ) {
-				log.debug( "item already cached: " + key );
-			}
-			return false;
-		}
-		return putFromLoad( key, value, txTimestamp, version );
-	}
+    public Object get(Object key, long txTimestamp) throws CacheException {
 
-	public SoftLock lockItem(Object key, Object version) throws CacheException {
-		return null;
-	}
+        return delegate.get(key, txTimestamp);
+    }
 
-	public SoftLock lockRegion() throws CacheException {
-		return null;
-	}
+    public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
 
-	public void unlockItem(Object key, SoftLock lock) throws CacheException {
-	}
+        return delegate.putFromLoad(key, value, txTimestamp, version);
+    }
 
-	public void unlockRegion(SoftLock lock) throws CacheException {
-	}
+    public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+            throws CacheException {
 
-	public boolean insert(Object key, Object value, Object version) throws CacheException {
-		try {
-			region.getCacheInstance().put( new Fqn( region.getRegionFqn(), key ), EntityRegionImpl.ITEM, value );
-		}
-		catch ( Throwable t ) {
-			throw new CacheException( t );
-		}
-		return true;
-	}
+        return delegate.putFromLoad(key, value, txTimestamp, version, minimalPutOverride);
+    }
 
-	public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
-		return false;
-	}
+    public boolean insert(Object key, Object value, Object version) throws CacheException {
 
-	public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
-			throws CacheException {
-		try {
-			region.getCacheInstance().put( new Fqn( region.getRegionFqn(), key ), EntityRegionImpl.ITEM, value );
-		}
-		catch ( Throwable t ) {
-			throw new CacheException( t );
-		}
-		return true;
-	}
+        return delegate.insert(key, value, version);
+    }
 
-	public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
-			throws CacheException {
-		return false;
-	}
+    public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
+            throws CacheException {
 
-	public void remove(Object key) throws CacheException {
-		try {
-			region.getCacheInstance().removeNode( new Fqn( region.getRegionFqn(), key ) );
-		}
-		catch ( Exception e ) {
-			throw new CacheException( e );
-		}
-	}
+        return delegate.update(key, value, currentVersion, previousVersion);
+    }
 
-	public void removeAll() throws CacheException {
-		try {
-			region.getCacheInstance().removeNode( region.getRegionFqn() );
-		}
-		catch ( Exception e ) {
-			throw new CacheException( e );
-		}
-	}
+    public void remove(Object key) throws CacheException {
 
-	public void evict(Object key) throws CacheException {
-		remove( key );
-	}
+        delegate.remove(key);
+    }
 
-	public void evictAll() throws CacheException {
-		removeAll();
-	}
+    public void removeAll() throws CacheException {
+        delegate.removeAll();
+    }
+
+    public void evict(Object key) throws CacheException {
+        delegate.evict(key);
+    }
+
+    public void evictAll() throws CacheException {
+        delegate.evictAll();
+    }
+
+    // Following methods we don't delegate since they have so little logic
+    // it's clearer to just implement them here
+
+    public SoftLock lockItem(Object key, Object version) throws CacheException {
+        return null;
+    }
+
+    public SoftLock lockRegion() throws CacheException {
+        return null;
+    }
+
+    public void unlockItem(Object key, SoftLock lock) throws CacheException {
+    }
+
+    public void unlockRegion(SoftLock lock) throws CacheException {
+    }
+
+    public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
+        return false;
+    }
+
+    public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
+            throws CacheException {
+        return false;
+    }
 }

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.query;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.util.PropertiesHelper;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Option;
+
+/**
+ * Defines the behavior of the query cache regions for JBossCache 2.x.
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class QueryResultsRegionImpl extends TransactionalDataRegionAdapter implements QueryResultsRegion {
+
+    public static final String QUERY_CACHE_LOCAL_ONLY_PROP = "hibernate.cache.region.jbc2.query.localonly";
+    
+    
+    /**
+     * Whether we should set an option to disable propagation of changes around
+     * cluster.
+     */
+    private boolean localOnly;
+
+    /**
+     * Create a new QueryResultsRegionImpl.
+     * 
+     * @param jbcCache
+     * @param regionName
+     * @param regionPrefix
+     *            TODO
+     */
+    public QueryResultsRegionImpl(Cache jbcCache, String regionName, String regionPrefix, Properties properties) {
+        super(jbcCache, regionName, regionPrefix, null);
+
+        // If JBC is using INVALIDATION, we don't want to propagate changes.
+        // We use the Timestamps cache to manage invalidation
+        localOnly = CacheHelper.isClusteredInvalidation(jbcCache);
+        if (!localOnly) {
+            // We don't want to waste effort setting an option if JBC is
+            // already in LOCAL mode. If JBC is REPL_(A)SYNC then check
+            // if they passed an config option to disable query replication
+            localOnly = CacheHelper.isClusteredReplication(jbcCache)
+                    && PropertiesHelper.getBoolean(QUERY_CACHE_LOCAL_ONLY_PROP, properties, false);
+        }
+    }
+
+    public void evict(Object key) throws CacheException {
+        Option opt = getNonLockingDataVersionOption(false);
+        if (localOnly)
+            opt.setCacheModeLocal(true);
+        CacheHelper.remove(getCacheInstance(), getRegionFqn(), key, opt);
+    }
+
+    public void evictAll() throws CacheException {
+        Option opt = getNonLockingDataVersionOption(false);
+        if (localOnly)
+            opt.setCacheModeLocal(true);
+        CacheHelper.removeAll(getCacheInstance(), getRegionFqn(), opt);
+    }
+
+    public Object get(Object key) throws CacheException {
+
+        // Don't hold the JBC node lock throughout the tx, as that
+        // prevents updates
+        // Add a zero (or low) timeout option so we don't block
+        // waiting for tx's that did a put to commit
+        Option opt = new Option();
+        opt.setLockAcquisitionTimeout(0);
+        return suspendAndGet(key, opt, true);
+    }
+
+    public void put(Object key, Object value) throws CacheException {
+
+        // Here we don't want to suspend the tx. If we do:
+        // 1) We might be caching query results that reflect uncommitted
+        // changes. No tx == no WL on cache node, so other threads
+        // can prematurely see those query results
+        // 2) No tx == immediate replication. More overhead, plus we
+        // spread issue #1 above around the cluster
+
+        // Add a zero (or quite low) timeout option so we don't block
+        // Ignore any TimeoutException. Basically we forego caching the
+        // query result in order to avoid blocking for concurrent reads.
+        // Reads are done with suspended tx, so they should not hold the
+        // lock for long.  Not caching the query result is OK, since
+        // any subsequent read will just see the old result with its
+        // out-of-date timestamp; that result will be discarded and the
+        // db query performed again.
+        Option opt = getNonLockingDataVersionOption(false);
+        opt.setLockAcquisitionTimeout(2);
+        if (localOnly)
+            opt.setCacheModeLocal(true);
+        CacheHelper.putAllowingTimeout(getCacheInstance(), getRegionFqn(), key, value, opt);
+    }
+
+    @Override
+    protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
+        return Fqn.fromString(escapeRegionName(regionName, regionPrefix));
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.timestamp;
+
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.transaction.Transaction;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.TimestampsRegion;
+import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeModified;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+
+/**
+ * Defines the behavior of the timestamps cache region for JBossCache 2.x.
+ * <p>
+ * Maintains a local (authoritative) cache of timestamps along with the
+ * distributed cache held in JBoss Cache. Listens for changes in the distributed
+ * cache and updates the local cache accordingly. Ensures that any changes in
+ * the local cache represent an increase in the timestamp. This approach allows
+ * timestamp changes to be replicated asynchronously by JBoss Cache while still
+ * preventing backward changes in timestamps.
+ * </p>
+ * 
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+ at CacheListener
+public class TimestampsRegionImpl extends TransactionalDataRegionAdapter implements TimestampsRegion {
+
+    public static final String TYPE = "TS";
+    
+    private final Map localCache = new ConcurrentHashMap();
+
+    /**
+     * Create a new TimestampsRegionImpl.
+     * 
+     * @param jbcCache
+     * @param regionName
+     * @param regionPrefix
+     *            TODO
+     * @param metadata
+     */
+    public TimestampsRegionImpl(Cache jbcCache, String regionName, String regionPrefix, Properties properties) {
+        super(jbcCache, regionName, regionPrefix, null);
+
+        jbcCache.addCacheListener(this);
+
+        populateLocalCache();
+    }
+
+    @Override
+    protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
+        return getTypeFirstRegionFqn(regionName, regionPrefix, TYPE);
+    }
+
+    public void evict(Object key) throws CacheException {
+        // TODO Is this a valid operation on a timestamps cache?
+        localCache.remove(key);
+        Option opt = getNonLockingDataVersionOption(true);
+        CacheHelper.remove(getCacheInstance(), getRegionFqn(), key, opt);
+    }
+
+    public void evictAll() throws CacheException {
+        // TODO Is this a valid operation on a timestamps cache?
+        localCache.clear();
+        Option opt = getNonLockingDataVersionOption(true);
+        CacheHelper.removeAll(getCacheInstance(), getRegionFqn(), opt);
+    }
+
+    public Object get(Object key) throws CacheException {
+
+        Object timestamp = localCache.get(key);
+        if (timestamp == null) {
+            // Check the cluster-wide cache
+            // Don't hold the cache node lock throughout the tx, as that
+            // prevents updates
+            timestamp = suspendAndGet(key, null, false);
+            updateLocalCache(key, timestamp);
+        }
+        return timestamp;
+    }
+
+    public void put(Object key, Object value) throws CacheException {
+
+        // Immediately update the local cache
+        boolean incremented = updateLocalCache(key, value);
+
+        if (incremented) {
+            // Now the cluster-wide cache
+
+            // TODO there's a race here where 2 threads can get through
+            // updateLocalCache() in proper sequence but then the earlier
+            // one updates JBC *later*. This should only affect newly
+            // joined nodes who populate their initial localCache from JBC.
+
+            // Don't hold the JBC node lock throughout the tx, as that
+            // prevents reads and other updates
+            Transaction tx = suspend();
+            try {
+                // We ensure ASYNC semantics (JBCACHE-1175)
+                Option opt = getNonLockingDataVersionOption(false);
+                opt.setForceAsynchronous(true);
+                getCacheInstance().getInvocationContext().setOptionOverrides(opt);
+                getCacheInstance().put(new Fqn(regionFqn, key), ITEM, value);
+            } catch (Exception e) {
+                throw new CacheException(e);
+            } finally {
+                resume(tx);
+            }
+        }
+    }
+
+    @Override
+    public void destroy() throws CacheException {
+
+        localCache.clear();
+        getCacheInstance().removeCacheListener(this);
+        super.destroy();
+    }
+
+    /**
+     * Monitors cache events and updates the local cache
+     * 
+     * @param event
+     */
+    @NodeModified
+    public void nodeModified(NodeModifiedEvent event) {
+        if (event.isOriginLocal() || event.isPre())
+            return;
+
+        Fqn fqn = event.getFqn();
+        Fqn regFqn = getRegionFqn();
+        if (fqn.size() == regFqn.size() + 1 && fqn.isChildOf(regFqn)) {
+            Object key = fqn.get(regFqn.size());
+            updateLocalCache(key, event.getData().get(ITEM));
+        }
+    }
+
+    private void populateLocalCache() {
+        Set children = CacheHelper.getChildrenNames(getCacheInstance(), getRegionFqn());
+        for (Object key : children) {
+            get(key);
+        }
+    }
+
+    /**
+     * Updates the local cache, ensuring that the new value represents a higher
+     * value than the old (i.e. timestamp never goes back in time).
+     * 
+     * @param key
+     * @param value
+     */
+    private boolean updateLocalCache(Object key, Object value) {
+        if (value == null)
+            return false;
+
+        boolean increase = true;
+
+        long newVal = 0;
+        try {
+            newVal = ((Long) value).longValue();
+
+            Long oldVal = (Long) localCache.get(key);
+            increase = oldVal == null || newVal > oldVal.longValue();
+            if (increase) {
+                oldVal = (Long) localCache.put(key, value);
+                // Double check that it was an increase
+                if (oldVal != null && oldVal.longValue() > newVal) {
+                    // Nope; Restore the old value
+                    increase = updateLocalCache(key, oldVal);
+                }
+            }
+        } catch (ClassCastException cce) {
+            // TODO -- this is stupid; look into changing TimestampsRegion API
+            // not using Long; just store it
+            localCache.put(key, value);
+        }
+
+        return increase;
+
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + native

Copied: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java (from rev 13968, core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheModeHelper.java)
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.cache.jbc2.util;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.hibernate.cache.CacheException;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.Node;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.lock.TimeoutException;
+import org.jboss.cache.optimistic.DataVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper for dealing with JBossCache {@link Configuration.CacheMode}.
+ * 
+ * @author Steve Ebersole
+ * @author Brian Stansberry
+ */
+public class CacheHelper {
+
+    /** Key under which items are cached */
+    public static final String ITEM = "item";
+    /** Key and value used in a hack to create region root nodes */
+    public static final String DUMMY = "dummy";
+    
+    private static final Logger log = LoggerFactory.getLogger(CacheHelper.class);
+
+    /**
+     * Disallow external instantiation of CacheHelper.
+     */
+    private CacheHelper() {
+    }
+
+    /**
+     * Is this cache participating in a cluster with invalidation?
+     * 
+     * @param cache
+     *            The cache to check.
+     * @return True if the cache is configured for synchronous/asynchronous
+     *         invalidation; false otherwise.
+     */
+    public static boolean isClusteredInvalidation(Cache cache) {
+        return isClusteredInvalidation(cache.getConfiguration().getCacheMode());
+    }
+
+    /**
+     * Does this cache mode indicate clustered invalidation?
+     * 
+     * @param cacheMode
+     *            The cache to check
+     * @return True if the cache mode is confiogured for
+     *         synchronous/asynchronous invalidation; false otherwise.
+     */
+    public static boolean isClusteredInvalidation(Configuration.CacheMode cacheMode) {
+        return cacheMode == Configuration.CacheMode.INVALIDATION_ASYNC
+                || cacheMode == Configuration.CacheMode.INVALIDATION_SYNC;
+    }
+
+    /**
+     * Is this cache participating in a cluster with replication?
+     * 
+     * @param cache
+     *            The cache to check.
+     * @return True if the cache is configured for synchronous/asynchronous
+     *         invalidation; false otherwise.
+     */
+    public static boolean isClusteredReplication(Cache cache) {
+        return isClusteredReplication(cache.getConfiguration().getCacheMode());
+    }
+
+    /**
+     * Does this cache mode indicate clustered replication?
+     * 
+     * @param cacheMode
+     *            The cache to check
+     * @return True if the cache mode is confiogured for
+     *         synchronous/asynchronous invalidation; false otherwise.
+     */
+    public static boolean isClusteredReplication(Configuration.CacheMode cacheMode) {
+        return cacheMode == Configuration.CacheMode.REPL_ASYNC || cacheMode == Configuration.CacheMode.REPL_SYNC;
+    }
+    
+    public static boolean isSynchronous(Cache cache) {
+        return isSynchronous(cache.getConfiguration().getCacheMode());
+    }
+    
+    public static boolean isSynchronous(Configuration.CacheMode cacheMode) {
+        return cacheMode == Configuration.CacheMode.REPL_SYNC || cacheMode == Configuration.CacheMode.INVALIDATION_SYNC;
+    }
+    
+    public static Set getChildrenNames(Cache cache, Fqn fqn) {
+        Node node = cache.getRoot().getChild(fqn);
+        return (node != null) ? node.getChildrenNames() : Collections.emptySet();
+    }
+
+    /**
+     * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+     * and performs a JBoss Cache <code>get(Fqn, Object)</code>, wrapping any
+     * exception in a {@link CacheException}.
+     * 
+     * @param cache
+     *            the cache to invoke on
+     * @param region
+     *            base Fqn for the cache region
+     * @param key
+     *            specific key to append to the <code>region</code> to form
+     *            the full Fqn
+     */
+    public static Object get(Cache cache, Fqn region, Object key) throws CacheException {
+        try {
+            return cache.get(new Fqn(region, key), ITEM);
+        } catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /**
+     * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+     * and performs a JBoss Cache <code>get(Fqn, Object)</code>, wrapping any
+     * exception in a {@link CacheException}.
+     * 
+     * @param cache
+     *            the cache to invoke on
+     * @param region
+     *            base Fqn for the cache region
+     * @param key
+     *            specific key to append to the <code>region</code> to form
+     *            the full Fqn
+     */
+    public static Object getAllowingTimeout(Cache cache, Fqn region, Object key) throws CacheException {
+        try {
+            return cache.get(new Fqn(region, key), ITEM);        
+        } 
+        catch (TimeoutException ignored) {
+            // ignore it
+            return null;
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /**
+     * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+     * and performs a JBoss Cache <code>put(Object, Object)</code>, wrapping
+     * any exception in a {@link CacheException}.
+     * 
+     * @param cache
+     *            the cache to invoke on
+     * @param region
+     *            base Fqn for the cache region
+     * @param key
+     *            specific key to append to the <code>region</code> to form
+     *            the full Fqn
+     * @param value
+     *            data to store in the cache node
+     */
+    public static void put(Cache cache, Fqn region, Object key, Object value) throws CacheException {
+
+        put(cache, region, key, value, null);
+    }
+
+    /**
+     * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+     * and performs a JBoss Cache <code>put(Object, Object)</code>, wrapping
+     * any exception in a {@link CacheException}.
+     * 
+     * @param cache
+     *            the cache to invoke on
+     * @param region
+     *            base Fqn for the cache region
+     * @param key
+     *            specific key to append to the <code>region</code> to form
+     *            the full Fqn
+     * @param value
+     *            data to store in the cache node
+     * @param option
+     *            invocation Option to set for this invocation. May be
+     *            <code>null</code>.
+     */
+    public static void put(Cache cache, Fqn region, Object key, Object value, Option option) throws CacheException {
+        try {
+            setInvocationOption(cache, option);
+            cache.put(new Fqn(region, key), ITEM, value);
+        } catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /**
+     * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+     * and performs a JBoss Cache <code>put(Object, Object)</code>, ignoring any
+     * {@link TimeoutException} and wrapping any other exception in a {@link CacheException}.
+     * 
+     * @param cache
+     *            the cache to invoke on
+     * @param region
+     *            base Fqn for the cache region
+     * @param key
+     *            specific key to append to the <code>region</code> to form
+     *            the full Fqn
+     * @param value
+     *            data to store in the cache node
+     * @param option
+     *            invocation Option to set for this invocation. May be
+     *            <code>null</code>.
+     */
+    public static void putAllowingTimeout(Cache cache, Fqn region, Object key, Object value, Option option) throws CacheException {
+        try {
+            setInvocationOption(cache, option);
+            cache.put(new Fqn(region, key), ITEM, value);
+        }
+        catch (TimeoutException allowed) {
+            // ignore it
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /**
+     * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+     * and performs a JBoss Cache
+     * <code>putForExternalRead(Object, Object)</code>, wrapping any
+     * exception in a {@link CacheException}. Ignores any JBoss Cache
+     * {@link TimeoutException}.
+     * 
+     * @param cache
+     *            the cache to invoke on
+     * @param region
+     *            base Fqn for the cache region
+     * @param key
+     *            specific key to append to the <code>region</code> to form
+     *            the full Fqn
+     * @param value
+     *            data to store in the cache node
+     */
+    public static boolean putForExternalRead(Cache cache, Fqn region, Object key, Object value) throws CacheException {
+
+        return putForExternalRead(cache, region, key, value, null);
+    }
+
+    /**
+     * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+     * and performs a JBoss Cache
+     * <code>putForExternalRead(Object, Object)</code>, wrapping any
+     * exception in a {@link CacheException}. Ignores any JBoss Cache
+     * {@link TimeoutException}.
+     * 
+     * @param cache
+     *            the cache to invoke on
+     * @param region
+     *            base Fqn for the cache region
+     * @param key
+     *            specific key to append to the <code>region</code> to form
+     *            the full Fqn
+     * @param value
+     *            data to store in the cache node
+     * @param option
+     *            invocation Option to set for this invocation. May be
+     *            <code>null</code>.
+     */
+    public static boolean putForExternalRead(Cache cache, Fqn region, Object key, Object value, Option option)
+            throws CacheException {
+        try {
+            setInvocationOption(cache, option);
+            cache.putForExternalRead(new Fqn(region, key), ITEM, value);
+            return true;
+        } catch (TimeoutException te) {
+            // ignore!
+            log.debug("ignoring write lock acquisition failure");
+            return false;
+        } catch (Throwable t) {
+            throw new CacheException(t);
+        }
+    }
+
+    /**
+     * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+     * and performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
+     * exception in a {@link CacheException}.
+     * 
+     * @param cache
+     *            the cache to invoke on
+     * @param region
+     *            base Fqn for the cache region
+     * @param key
+     *            specific key to append to the <code>region</code> to form
+     *            the full Fqn
+     */
+    public static void remove(Cache cache, Fqn region, Object key) throws CacheException {
+
+        remove(cache, region, key, null);
+    }
+
+    /**
+     * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+     * and performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
+     * exception in a {@link CacheException}.
+     * 
+     * @param cache
+     *            the cache to invoke on
+     * @param region
+     *            base Fqn for the cache region
+     * @param key
+     *            specific key to append to the <code>region</code> to form
+     *            the full Fqn
+     * @param option
+     *            invocation Option to set for this invocation. May be
+     *            <code>null</code>.
+     */
+    public static void remove(Cache cache, Fqn region, Object key, Option option) throws CacheException {
+        try {
+            setInvocationOption(cache, option);
+            cache.removeNode(new Fqn(region, key));
+        } catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    /**
+     * Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
+     * exception in a {@link CacheException}.
+     * 
+     * @param cache
+     *            the cache to invoke on
+     * @param region
+     *            base Fqn for the cache region
+     */
+    public static void removeAll(Cache cache, Fqn region) throws CacheException {
+
+        removeAll(cache, region, null);
+    }
+
+    /**
+     * Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
+     * exception in a {@link CacheException}.
+     * 
+     * @param cache
+     *            the cache to invoke on
+     * @param region
+     *            base Fqn for the cache region
+     * @param option
+     *            invocation Option to set for this invocation. May be
+     *            <code>null</code>.
+     */
+    public static void removeAll(Cache cache, Fqn region, Option option) throws CacheException {
+        try {
+            setInvocationOption(cache, option);
+            cache.removeNode(region);
+        } catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+    
+    public static Node addNode(Cache cache, Fqn fqn, boolean localOnly, boolean resident, DataVersion version)
+            throws CacheException {
+        try {
+            Option option = null;
+            if (localOnly || version != null) {
+                option = new Option();
+                option.setCacheModeLocal(localOnly);
+                option.setDataVersion(version);
+            }
+            
+            Node root = cache.getRoot();
+            setInvocationOption(cache, option);
+            // FIXME hack to work around fact that calling
+            // Node added = root.addChild( fqn ); doesn't 
+            // properly set the version on the node
+            Node added = null;
+            if (version == null) {
+                added = root.addChild( fqn );
+            }
+            else {
+                cache.put(fqn, DUMMY, DUMMY);
+                added = root.getChild(fqn);
+            }
+            if (resident)
+                added.setResident(true);
+            return added;
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+    
+
+    /**
+     * Assigns the given Option to the cache's {@link InvocationContext}. Does
+     * nothing if <code>option</code> is <code>null</code>.
+     * 
+     * @param cache
+     *            the cache. Cannot be <code>null</code>.
+     * @param option
+     *            the option. May be <code>null</code>.
+     * 
+     * @see {@link Cache#getInvocationContext()}
+     * @see {@link InvocationContext#setOptionOverrides(Option)}
+     */
+    public static void setInvocationOption(Cache cache, Option option) {
+        if (option != null) {
+            cache.getInvocationContext().setOptionOverrides(option);
+        }
+    }
+
+    /**
+     * Creates an {@link Option} using the given {@link DataVersion} and passes
+     * it to {@link #setInvocationOption(Cache, Option)}.
+     * 
+     * @param cache
+     *            the cache to set the Option on. Cannot be <code>null</code>.
+     * @param version
+     *            the DataVersion to set. Cannot be <code>null</code>.
+     */
+    public static void setDataVersionOption(Cache cache, DataVersion version) {
+        Option option = new Option();
+        option.setDataVersion(version);
+        setInvocationOption(cache, option);
+    }
+}

Deleted: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheModeHelper.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheModeHelper.java	2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheModeHelper.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
- *
- * 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, v. 2.1. This program is distributed in the
- * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
- * distribution; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Red Hat Author(s): Steve Ebersole
- */
-package org.hibernate.cache.jbc2.util;
-
-import org.jboss.cache.Cache;
-import org.jboss.cache.config.Configuration;
-
-/**
- * Helper for dealing with JBossCache {@link Configuration.CacheMode}.
- *
- * @author Steve Ebersole
- */
-public class CacheModeHelper {
-	/**
-	 * Disallow external instantiation of CacheModeHelper.
-	 */
-	private CacheModeHelper() {
-	}
-
-	/**
-	 * Is this cache participating in a cluster with invalidation?
-	 *
-	 * @param cache The cache to check.
-	 * @return True if the cache is configured for synchronous/asynchronous invalidation; false
-	 * otherwise.
-	 */
-	public static boolean isClusteredInvalidation(Cache cache) {
-		return isClusteredInvalidation( cache.getConfiguration().getCacheMode() );
-	}
-
-	/**
-	 * Does this cache mode indicate clustered invalidation?
-	 *
-	 * @param cacheMode The cache to check
-	 * @return True if the cache mode is confiogured for synchronous/asynchronous invalidation; false
-	 * otherwise.
-	 */
-	public static boolean isClusteredInvalidation(Configuration.CacheMode cacheMode) {
-		return cacheMode == Configuration.CacheMode.REPL_ASYNC || cacheMode == Configuration.CacheMode.REPL_SYNC;
-	}
-}

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CircumventChecksDataVersion.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CircumventChecksDataVersion.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CircumventChecksDataVersion.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.util;
+
+import org.hibernate.cache.CacheException;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.optimistic.DataVersion;
+
+/**
+ * Used to signal to a DataVersionAdapter to simply not perform any checks. This
+ * is currently needed for proper handling of remove() calls for entity cache
+ * regions (we do not know the version info...).
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class CircumventChecksDataVersion implements DataVersion {
+
+    private static final long serialVersionUID = 7996980646166032369L;
+
+    public static final DataVersion INSTANCE = new CircumventChecksDataVersion();
+
+    public static Option getInvocationOption() {
+        Option option = new Option();
+        option.setDataVersion(INSTANCE);
+        return option;
+    }
+
+    public boolean newerThan(DataVersion dataVersion) {
+        throw new CacheException("optimistic locking checks should never happen on CircumventChecksDataVersion");
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CircumventChecksDataVersion.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/DataVersionAdapter.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/DataVersionAdapter.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/DataVersionAdapter.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.util;
+
+import java.io.IOException;
+import java.util.Comparator;
+
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.hibernate.util.CalendarComparator;
+import org.hibernate.util.ComparableComparator;
+import org.jboss.cache.optimistic.DataVersion;
+import org.jboss.cache.optimistic.DefaultDataVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A DataVersionAdapter.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class DataVersionAdapter implements DataVersion {
+
+    private static final Logger log = LoggerFactory.getLogger(TransactionalAccess.class);
+
+    private static final long serialVersionUID = 5564692336076405571L;
+
+    private final Object currentVersion;
+
+    private final Object previousVersion;
+
+    /** 
+     * Comparator does not extend Serializable and the std impls don't either,
+     * so we make the field transient to allow special handling
+     */
+    private transient Comparator versionComparator;
+
+    private final String sourceIdentifer;
+
+    public DataVersionAdapter(Object currentVersion, Object previousVersion, Comparator versionComparator,
+            String sourceIdentifer) {
+        this.currentVersion = currentVersion;
+        this.previousVersion = previousVersion;
+        this.versionComparator = versionComparator;
+        this.sourceIdentifer = sourceIdentifer;
+        log.trace("created " + this);
+    }
+
+    /**
+     * newerThan() call is dispatched against the DataVersion currently
+     * associated with the node; the passed dataVersion param is the DataVersion
+     * associated with the data we are trying to put into the node. <p/> we are
+     * expected to return true in the case where we (the current node
+     * DataVersion) are newer that then incoming value. Returning true here
+     * essentially means that a optimistic lock failure has occured (because
+     * conversely, the value we are trying to put into the node is "older than"
+     * the value already there...)
+     */
+    public boolean newerThan(DataVersion dataVersion) {
+        log.trace("checking [" + this + "] against [" + dataVersion + "]");
+        if (dataVersion instanceof CircumventChecksDataVersion) {
+            log.trace("skipping lock checks...");
+            return false;
+        } else if (dataVersion instanceof NonLockingDataVersion) {
+            // can happen because of the multiple ways Cache.remove()
+            // can be invoked :(
+            log.trace("skipping lock checks...");
+            return false;
+        } else if (dataVersion instanceof DefaultDataVersion) {
+            if (((DefaultDataVersion) dataVersion).getRawVersion() == 0) {
+                // JBC put a version in the node when it created it as
+                // part of building a larger tree
+                return true;
+            } else {
+                log.error("Cannot compare to " + dataVersion);
+                return false;
+            }
+        }
+        DataVersionAdapter other = (DataVersionAdapter) dataVersion;
+        if (other.previousVersion == null) {
+            log.warn("Unexpected optimistic lock check on inserting data");
+            // work around the "feature" where tree cache is validating the
+            // inserted node during the next transaction. no idea...
+            if (this == dataVersion) {
+                log.trace("skipping lock checks due to same DV instance");
+                return false;
+            }
+        }
+
+        if (currentVersion == null) {
+            // If the workspace node has null as well, OK; if not we've
+            // been modified in a non-comparable manner, which we have to
+            // treat as us being newer
+            return (other.previousVersion != null);
+        }
+
+        return versionComparator.compare(currentVersion, other.previousVersion) >= 1;
+    }
+
+    public String toString() {
+        return super.toString() + " [current=" + currentVersion + ", previous=" + previousVersion + ", src="
+                + sourceIdentifer + "]";
+    }
+    
+    
+    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+        
+        // The standard comparator types are not Serializable but are singletons
+        if (versionComparator instanceof ComparableComparator)
+            out.writeByte(0);
+        else if (versionComparator instanceof CalendarComparator)
+            out.writeByte(1);
+        else {
+            out.writeByte(999);
+            out.writeObject(versionComparator);
+        }
+    }
+    
+    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException  {
+        
+        in.defaultReadObject();
+        byte comparatorType = in.readByte();
+        switch (comparatorType) {
+            case 0:
+                versionComparator = ComparableComparator.INSTANCE;
+                break;
+            case 1:
+                versionComparator = CalendarComparator.INSTANCE;
+                break;
+            default:
+                versionComparator = (Comparator) in.readObject();
+        }
+    }
+    
+    
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/DataVersionAdapter.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/NonLockingDataVersion.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/NonLockingDataVersion.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/NonLockingDataVersion.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.util;
+
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.optimistic.DataVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link DataVersion} used in regions where no locking should ever occur. This
+ * includes query-caches, update-timestamps caches, collection caches, and
+ * entity caches where the entity is not versioned.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class NonLockingDataVersion implements DataVersion {
+
+    private static final Logger log = LoggerFactory.getLogger(TransactionalAccess.class);
+
+    private static final long serialVersionUID = 7050722490368630553L;
+
+    public static final DataVersion INSTANCE = new NonLockingDataVersion();
+
+    public static Option getInvocationOption() {
+        Option option = new Option();
+        option.setDataVersion(INSTANCE);
+        return option;
+    }
+
+    public boolean newerThan(DataVersion dataVersion) {
+        
+//        if (dataVersion instanceof DefaultDataVersion) {
+//            log.info("unexpectedly validating against a DefaultDataVersion", new Exception("Just a stack trace"));
+//            return true;
+//        }
+//        else {
+            log.trace("non locking lock check...");
+            return false;
+//        }
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/NonLockingDataVersion.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/jbc2/builder/jbc2-configs.xml
===================================================================
(Binary files differ)


Property changes on: core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/jbc2/builder/jbc2-configs.xml
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractEntityCollectionRegionTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractEntityCollectionRegionTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractEntityCollectionRegionTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.TransactionalDataRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.test.util.CacheTestUtil;
+
+/**
+ * Base class for tests of EntityRegion and CollectionRegion implementations.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractEntityCollectionRegionTestCase extends AbstractRegionImplTestCase {
+
+    /**
+     * Create a new EntityCollectionRegionTestCaseBase.
+     * 
+     * @param name
+     */
+    public AbstractEntityCollectionRegionTestCase(String name) {
+        super(name);
+    }
+   
+    /** 
+     * Create a Region backed by an OPTIMISTIC locking JBoss Cache, and then 
+     * ensure that it handles calls to buildAccessStrategy as expected when 
+     * all the various {@link AccessType}s are passed as arguments.
+     */
+    public void testSupportedAccessTypesOptimistic() throws Exception {
+        
+        supportedAccessTypeTest(true);
+    }
+
+    /** 
+     * Creates a Region backed by an PESSIMISTIC locking JBoss Cache, and then 
+     * ensures that it handles calls to buildAccessStrategy as expected when 
+     * all the various {@link AccessType}s are passed as arguments.
+     */
+    public void testSupportedAccessTypesPessimistic() throws Exception {
+        
+        supportedAccessTypeTest(false);
+    }
+    
+    private void supportedAccessTypeTest(boolean optimistic) throws Exception {
+        
+        Configuration cfg = CacheTestUtil.buildConfiguration("test", MultiplexedJBossCacheRegionFactory.class, true, false);
+        String entityCfg = optimistic ? "optimistic-entity" : "pessimistic-entity";
+        cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, entityCfg);
+        
+        JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+        
+        supportedAccessTypeTest(regionFactory, cfg.getProperties());
+    }
+    
+    /** 
+     * Creates a Region using the given factory, and then ensure that it
+     * handles calls to buildAccessStrategy as expected when all the
+     * various {@link AccessType}s are passed as arguments.
+     */
+    protected abstract void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties);
+    
+    /**
+     * Test that the Region properly implements 
+     * {@link TransactionalDataRegion#isTransactionAware()}.
+     * 
+     * @throws Exception
+     */
+    public void testIsTransactionAware() throws Exception {
+        
+        Configuration cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, false);
+        cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
+        
+        JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+        
+        TransactionalDataRegion region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
+        
+        assertTrue("Region is transaction-aware", region.isTransactionAware());
+        
+        CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
+        
+        cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, false);
+        cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
+        // Make it non-transactional
+        cfg.getProperties().remove(Environment.TRANSACTION_MANAGER_STRATEGY);
+        
+        regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+        
+        region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
+        
+        assertFalse("Region is not transaction-aware", region.isTransactionAware());
+        
+        CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
+    }
+    
+    public void testGetCacheDataDescription() throws Exception {
+        Configuration cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, false);
+        cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
+        
+        JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+        
+        TransactionalDataRegion region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
+        
+        CacheDataDescription cdd = region.getCacheDataDescription();
+        
+        assertNotNull(cdd);
+        
+        CacheDataDescription expected = getCacheDataDescription();
+        assertEquals(expected.isMutable(), cdd.isMutable());
+        assertEquals(expected.isVersioned(), cdd.isVersioned());
+        assertEquals(expected.getVersionComparator(), cdd.getVersionComparator());
+        
+    }
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,118 @@
+package org.hibernate.test.cache.jbc2;
+
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.junit.UnitTestCase;
+import org.hibernate.test.util.CacheTestSupport;
+import org.jboss.cache.Cache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base class for all non-functional tests of JBoss Cache integration.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractJBossCacheTestCase extends UnitTestCase {
+
+    public static final String REGION_PREFIX = "test";
+    
+    private CacheTestSupport testSupport = new CacheTestSupport();
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+
+    
+    public AbstractJBossCacheTestCase(String name) {
+        super(name);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        
+        testSupport.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        
+        testSupport.tearDown();
+    }
+
+    protected void registerCache(Cache cache) {
+        testSupport.registerCache(cache);
+    }
+
+    protected void unregisterCache(Cache cache) {
+        testSupport.unregisterCache(cache);
+    }
+
+    protected void registerFactory(RegionFactory factory) {
+        testSupport.registerFactory(factory);
+    }
+
+    protected void unregisterFactory(RegionFactory factory) {
+        testSupport.unregisterFactory(factory);
+    }
+
+    protected CacheTestSupport getCacheTestSupport() {
+        return testSupport;
+    }
+    
+    protected void sleep(long ms) {
+        try {
+            Thread.sleep(ms);
+        }
+        catch (InterruptedException e) {
+            log.warn("Interrupted during sleep", e);
+        }
+    }
+
+    
+    /**
+     * Supports easy creation of a TestSuite where a subclass' "FailureExpected"
+     * version of a base test is included in the suite, while the base test
+     * is excluded.  E.g. test class FooTestCase includes method testBar(), while test
+     * class SubFooTestCase extends FooTestCase includes method testBarFailureExcluded().
+     * Passing SubFooTestCase.class to this method will return a suite that
+     * does not include testBar().
+     * 
+     * FIXME Move this to UnitTestCase
+     */
+    public static TestSuite createFailureExpectedSuite(Class testClass) {
+       
+       TestSuite allTests = new TestSuite(testClass);
+       Set failureExpected = new HashSet();
+       Enumeration tests = allTests.tests();
+       while (tests.hasMoreElements()) {
+          Test t = (Test) tests.nextElement();
+          if (t instanceof TestCase) {
+             String name = ((TestCase) t).getName();
+             if (name.endsWith("FailureExpected"))
+                failureExpected.add(name);
+          }       
+       }
+       
+       TestSuite result = new TestSuite();
+       tests = allTests.tests();
+       while (tests.hasMoreElements()) {
+          Test t = (Test) tests.nextElement();
+          if (t instanceof TestCase) {
+             String name = ((TestCase) t).getName();
+             if (!failureExpected.contains(name + "FailureExpected")) {
+                result.addTest(t);
+             }
+          }       
+       }
+       
+       return result;
+    }
+}
\ No newline at end of file

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractRegionImplTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractRegionImplTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractRegionImplTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.impl.CacheDataDescriptionImpl;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.util.CacheTestUtil;
+import org.hibernate.util.ComparableComparator;
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.config.Option;
+import org.jgroups.JChannelFactory;
+
+/**
+ * Base class for tests of Region implementations.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractRegionImplTestCase extends AbstractJBossCacheTestCase {
+
+    /**
+     * Create a new RegionImplTestCaseBase.
+     * 
+     * @param name
+     */
+    public AbstractRegionImplTestCase(String name) {
+        super(name);
+    }  
+
+    /**
+     * Tests proper handling of region initialization and destruction.
+     * 
+     * @throws Exception
+     */
+    public void testActivationDeactivation() throws Exception {
+        
+        // Set up a cache to monitor affects of starting the region
+        Cache remoteCache = DefaultCacheFactory.getInstance().createCache(SharedCacheInstanceManager.DEFAULT_CACHE_RESOURCE, false);
+        
+        // This test assumes replication; verify that's correct
+        assertEquals("Cache is REPL_SYNC", "REPL_SYNC", remoteCache.getConfiguration().getCacheModeString());
+        
+        JChannelFactory channelFactory = new JChannelFactory();
+        channelFactory.setMultiplexerConfig(SharedCacheInstanceManager.DEF_MULTIPLEXER_RESOURCE);
+        remoteCache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(channelFactory);
+        remoteCache.start();
+        
+        // Make sure we stop the remoteCache
+        registerCache(remoteCache);
+        
+        Fqn regionFqn = getRegionFqn("test/test", "test");
+        
+        assertNull("No region node", remoteCache.getRoot().getChild( regionFqn ));
+        
+        Configuration cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, true);
+        JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+        
+        Region region = createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
+        
+        Cache localCache = getJBossCache( regionFactory );
+        
+        // This test assumes replication; verify that's correct
+        assertEquals("Cache is REPL_SYNC", "REPL_SYNC", localCache.getConfiguration().getCacheModeString());
+        
+        // Region creation should not have affected remoteCache
+
+        assertNull("No region node", remoteCache.getRoot().getChild( regionFqn ));
+        Node regionRoot = localCache.getRoot().getChild( regionFqn );
+        assertTrue("Has a node at " + regionFqn, regionRoot != null );
+        assertTrue(regionFqn + " is resident", regionRoot.isResident() );
+        
+        // Confirm region destroy does not affect remote cache
+        
+        Option option = new Option();
+        option.setCacheModeLocal(true);
+        remoteCache.getInvocationContext().setOptionOverrides(option);
+        remoteCache.put(regionFqn, "test", "test");
+        
+        assertEquals("Put succeeded", "test", remoteCache.get(regionFqn, "test"));
+        assertNull("Put was local", localCache.get(regionFqn, "test"));
+        
+        region.destroy();
+        
+        assertEquals("Remote cache unchanged", "test", remoteCache.get(regionFqn, "test"));
+        assertNull("No region node", localCache.getRoot().getChild( regionFqn ));
+    }
+    
+    protected abstract Cache getJBossCache(JBossCacheRegionFactory regionFactory);
+    
+    protected abstract Fqn getRegionFqn(String regionName, String regionPrefix);
+    
+    protected abstract Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd);
+    
+    protected CacheDataDescription getCacheDataDescription() {
+       return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
+   }   
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheComplianceTest.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheComplianceTest.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheComplianceTest.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,150 @@
+package org.hibernate.test.cache.jbc2;
+
+import junit.framework.TestCase;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Settings;
+import org.hibernate.test.util.CacheTestSupport;
+import org.hibernate.test.util.CacheTestUtil;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.optimistic.DataVersion;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Tests that JBC itself functions as expected in certain areas where there
+ * may have been problems in the past.  Basically tests JBC itself, not the 
+ * Hibernate/JBC integration.
+ * 
+ * TODO if the equivalent tests are not in the JBC testsuite, add them.
+ * 
+ * @author Brian Stansberry
+ */
+public class JBossCacheComplianceTest extends TestCase {
+
+    private CacheTestSupport testSupport = new CacheTestSupport();
+    
+    
+    public JBossCacheComplianceTest(String x) {
+        super(x);
+    }
+
+    protected String getConfigResourceKey() {
+        return SharedCacheInstanceManager.CACHE_RESOURCE_PROP;
+    }
+
+    protected String getConfigResourceLocation() {
+        return "org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml";
+    }
+
+    protected Class<? extends RegionFactory> getCacheRegionFactory() {
+        return JBossCacheRegionFactory.class;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        
+        testSupport.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        
+        testSupport.tearDown();
+        
+        super.tearDown();
+    } 
+
+    @SuppressWarnings("unchecked")
+    public void testCacheLevelStaleWritesFail() throws Throwable {
+        
+        Configuration cfg = CacheTestUtil.buildConfiguration("", MultiplexedJBossCacheRegionFactory.class, true, false);
+        cfg.setProperty(getConfigResourceKey(), getConfigResourceLocation());
+        
+        Settings settings = cfg.buildSettings();
+        
+        Fqn<String> fqn = Fqn.fromString("/whatever");
+        JBossCacheRegionFactory regionFactory = (JBossCacheRegionFactory) settings.getRegionFactory();
+        regionFactory.start(settings, cfg.getProperties());
+        
+        // Make sure we clean up when done
+        testSupport.registerFactory(regionFactory);
+        
+        Cache<Object, Object> treeCache = regionFactory.getCacheInstanceManager().getEntityCacheInstance();
+
+        // Make sure this is an OPTIMISTIC cache
+        assertEquals("Cache is OPTIMISTIC", "OPTIMISTIC", treeCache.getConfiguration().getNodeLockingSchemeString());
+        
+        Long long1 = new Long(1);
+        Long long2 = new Long(2);
+
+        try {
+            System.out.println("****************************************************************");
+            BatchModeTransactionManager.getInstance().begin();
+            CacheHelper.setInvocationOption(treeCache, ManualDataVersion.gen(1));
+            treeCache.put(fqn, "ITEM", long1);
+            BatchModeTransactionManager.getInstance().commit();
+
+            System.out.println("****************************************************************");
+            BatchModeTransactionManager.getInstance().begin();
+            CacheHelper.setInvocationOption(treeCache, ManualDataVersion.gen(2));
+            treeCache.put(fqn, "ITEM", long2);
+            BatchModeTransactionManager.getInstance().commit();
+
+            try {
+                System.out.println("****************************************************************");
+                BatchModeTransactionManager.getInstance().begin();
+                CacheHelper.setInvocationOption(treeCache, ManualDataVersion.gen(1));
+                treeCache.put(fqn, "ITEM", long1);
+                BatchModeTransactionManager.getInstance().commit();
+                fail("stale write allowed");
+            } catch (Throwable ignore) {
+                // expected behavior
+                try {
+                    BatchModeTransactionManager.getInstance().rollback();
+                }
+                catch (IllegalStateException ignored) {
+                    // tx is already cleared
+                }
+            }
+
+            Long current = (Long) treeCache.get(fqn, "ITEM");
+            assertEquals("unexpected current value", 2, current.longValue());
+        } finally {
+            try {
+                treeCache.remove(fqn, "ITEM");
+            } catch (Throwable ignore) {
+            }
+        }
+    }
+
+    private static class ManualDataVersion implements DataVersion {
+
+        /** The serialVersionUID */
+        private static final long serialVersionUID = 1L;
+
+        private final int version;
+
+        public ManualDataVersion(int version) {
+            this.version = version;
+        }
+
+        public boolean newerThan(DataVersion dataVersion) {
+            return this.version > ((ManualDataVersion) dataVersion).version;
+        }
+
+        public static Option gen(int version) {
+            ManualDataVersion mdv = new ManualDataVersion(version);
+            Option option = new Option();
+            option.setDataVersion(mdv);
+            return option;
+        }
+    }
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheComplianceTest.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheRegionFactoryTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheRegionFactoryTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheRegionFactoryTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Settings;
+import org.hibernate.test.util.CacheTestUtil;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheStatus;
+
+/**
+ * A JBossCacheRegionFactoryTestCase.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class JBossCacheRegionFactoryTestCase extends AbstractJBossCacheTestCase {
+
+    /**
+     * Create a new JBossCacheRegionFactoryTestCase.
+     * 
+     * @param name
+     */
+    public JBossCacheRegionFactoryTestCase(String name) {
+        super(name);
+    }
+
+    public void testDefaultConfig() throws Exception {
+
+        Configuration cfg = CacheTestUtil.buildConfiguration("", JBossCacheRegionFactory.class, true, true);
+        
+        JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+        
+        CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
+        assertTrue("Correct default CacheInstanceManager type", mgr instanceof SharedCacheInstanceManager);
+        
+        Cache cache = mgr.getEntityCacheInstance();
+        assertTrue("entity cache exists", cache != null);
+        assertEquals("Used correct config", "TestSharedCache", cache.getConfiguration().getClusterName());
+        assertEquals("Cache started", CacheStatus.STARTED, cache.getCacheStatus());        
+        
+        CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
+        
+        assertEquals("Cache destroyed", CacheStatus.DESTROYED, cache.getCacheStatus());
+    }
+    
+    public void testInjectedCacheInstanceManager() {
+
+        Configuration cfg = CacheTestUtil.buildConfiguration("", JBossCacheRegionFactory.class, true, true);
+        
+        CacheInstanceManager cim = new MultiplexingCacheInstanceManager();
+        JBossCacheRegionFactory regionFactory = new JBossCacheRegionFactory(cim);
+        
+        Settings settings = cfg.buildSettings();
+        Properties properties = cfg.getProperties();
+        
+        regionFactory.start(settings, properties);        
+        // Ensure we clean up
+        registerFactory(regionFactory);
+        
+        assertEquals("Used injected CacheInstanceManager", cim, regionFactory.getCacheInstanceManager());
+        
+        CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/CacheInstanceManagerTestBase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/CacheInstanceManagerTestBase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/CacheInstanceManagerTestBase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.builder;
+
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractJBossCacheTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+
+/**
+ * A CacheInstanceManagerTestBase.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class CacheInstanceManagerTestBase extends AbstractJBossCacheTestCase {
+
+    /**
+     * Create a new CacheInstanceManagerTestBase.
+     * 
+     * @param name
+     */
+    public CacheInstanceManagerTestBase(String name) {
+        super(name);
+    }
+
+    protected abstract Class getRegionFactoryClass();
+    
+    public void testUse2ndLevelCache() throws Exception {
+        Configuration cfg = CacheTestUtil.buildConfiguration("", getRegionFactoryClass(), false, true);
+        
+        JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+        
+        CacheInstanceManager cim = regionFactory.getCacheInstanceManager();
+        
+        assertNull(cim.getCollectionCacheInstance());
+        assertNull(cim.getEntityCacheInstance());
+        assertNotNull(cim.getQueryCacheInstance());
+        assertNotNull(cim.getTimestampsCacheInstance());
+    }
+    
+    public void testUseQueryCache() throws Exception {
+        Configuration cfg = CacheTestUtil.buildConfiguration("", getRegionFactoryClass(), true, false);
+        
+        JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+        
+        CacheInstanceManager cim = regionFactory.getCacheInstanceManager();
+        
+        assertNotNull(cim.getCollectionCacheInstance());
+        assertNotNull(cim.getEntityCacheInstance());
+        assertNull(cim.getQueryCacheInstance());
+        assertNull(cim.getTimestampsCacheInstance());
+    }
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/MultiplexedCacheInstanceManagerTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/MultiplexedCacheInstanceManagerTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/MultiplexedCacheInstanceManagerTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.builder;
+
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+
+
+/**
+ * A SharedCacheInstanceManagerTestCase.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class MultiplexedCacheInstanceManagerTestCase extends CacheInstanceManagerTestBase {
+
+    /**
+     * Create a new SharedCacheInstanceManagerTestCase.
+     * 
+     * @param name
+     */
+    public MultiplexedCacheInstanceManagerTestCase(String name) {
+        super(name);
+    }
+
+    @Override
+    protected Class getRegionFactoryClass() {
+        return MultiplexedJBossCacheRegionFactory.class;
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/SharedCacheInstanceManagerTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/SharedCacheInstanceManagerTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/SharedCacheInstanceManagerTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.builder;
+
+import org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory;
+
+/**
+ * A SharedCacheInstanceManagerTestCase.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class SharedCacheInstanceManagerTestCase extends CacheInstanceManagerTestBase {
+
+    /**
+     * Create a new SharedCacheInstanceManagerTestCase.
+     * 
+     * @param name
+     */
+    public SharedCacheInstanceManagerTestCase(String name) {
+        super(name);
+    }
+
+    @Override
+    protected Class getRegionFactoryClass() {
+        return SharedJBossCacheRegionFactory.class;
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,539 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import java.util.Iterator;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.extensions.TestSetup;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.impl.CacheDataDescriptionImpl;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.collection.CollectionRegionImpl;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cache.jbc2.util.NonLockingDataVersion;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractJBossCacheTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+import org.hibernate.util.ComparableComparator;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.NodeSPI;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/** 
+ * Base class for tests of CollectionRegionAccessStrategy impls.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractCollectionRegionAccessStrategyTestCase extends AbstractJBossCacheTestCase {
+
+    public static final String REGION_NAME = "test/com.foo.test";
+    public static final String KEY = "KEY";
+    public static final String VALUE1 = "VALUE1";
+    public static final String VALUE2 = "VALUE2";
+    
+    protected static Configuration localCfg;
+    protected static JBossCacheRegionFactory localRegionFactory;
+    protected static Cache localCache;
+    protected static Configuration remoteCfg;
+    protected static JBossCacheRegionFactory remoteRegionFactory;
+    protected static Cache remoteCache;
+    
+    protected CollectionRegion localCollectionRegion;
+    protected CollectionRegionAccessStrategy localAccessStrategy;
+
+    protected CollectionRegion remoteCollectionRegion;
+    protected CollectionRegionAccessStrategy remoteAccessStrategy;
+    
+    protected boolean invalidation;
+    protected boolean optimistic;
+    protected boolean synchronous;
+    
+    protected Exception node1Exception;
+    protected Exception node2Exception;
+    
+    protected AssertionFailedError node1Failure;
+    protected AssertionFailedError node2Failure;
+    
+    public static Test getTestSetup(Class testClass, String configName) {
+        TestSuite suite = new TestSuite(testClass);
+        return new AccessStrategyTestSetup(suite, configName);
+    }
+    
+    public static Test getTestSetup(Test test, String configName) {
+        return new AccessStrategyTestSetup(test, configName);
+    }
+    
+    /**
+     * Create a new TransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public AbstractCollectionRegionAccessStrategyTestCase(String name) {
+        super(name);
+    }
+
+    protected abstract AccessType getAccessType();
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        
+        invalidation = CacheHelper.isClusteredInvalidation(localCache);
+        synchronous = CacheHelper.isSynchronous(localCache);
+        optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
+        localCollectionRegion = localRegionFactory.buildCollectionRegion(REGION_NAME, localCfg.getProperties(), getCacheDataDescription());
+        localAccessStrategy = localCollectionRegion.buildAccessStrategy(getAccessType());
+        
+        remoteCollectionRegion = remoteRegionFactory.buildCollectionRegion(REGION_NAME, remoteCfg.getProperties(), getCacheDataDescription());
+        remoteAccessStrategy = remoteCollectionRegion.buildAccessStrategy(getAccessType());
+        
+        node1Exception = null;
+        node2Exception = null;
+        
+        node1Failure = null;
+        node2Failure  = null;
+    }
+
+    protected void tearDown() throws Exception {
+        
+        super.tearDown();
+        
+        if (localCollectionRegion != null)
+            localCollectionRegion.destroy();
+        if (remoteCollectionRegion != null)
+            remoteCollectionRegion.destroy();
+        
+        try {
+            localCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+            localCache.removeNode(Fqn.ROOT);
+        }
+        catch (Exception e) {
+            log.error("Problem purging local cache" ,e);
+        }
+        
+        try {
+            remoteCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+            remoteCache.removeNode(Fqn.ROOT);
+        }
+        catch (Exception e) {
+            log.error("Problem purging remote cache" ,e);
+        }
+        
+        node1Exception = null;
+        node2Exception = null;
+        
+        node1Failure = null;
+        node2Failure  = null;
+    }
+    
+    protected static Configuration createConfiguration(String configName) {
+        Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
+        cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, configName);
+        return cfg;
+    }
+    
+    protected CacheDataDescription getCacheDataDescription() {
+        return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
+    }
+    
+    protected boolean isUsingOptimisticLocking() {
+        return optimistic;
+    }
+    
+    protected boolean isUsingInvalidation() {
+        return invalidation;
+    }
+    
+    protected boolean isSynchronous() {
+        return synchronous;
+    }
+    
+    protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+        return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, CollectionRegionImpl.TYPE);
+    }
+    
+    /**
+     * This is just a setup test where we assert that the cache config is
+     * as we expected.
+     */
+    public abstract void testCacheConfiguration();
+    
+    /**
+     * Test method for {@link TransactionalAccess#getRegion()}.
+     */
+    public void testGetRegion() {
+        assertEquals("Correct region", localCollectionRegion, localAccessStrategy.getRegion());
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)}.
+     */
+    public void testPutFromLoad() throws Exception {
+        putFromLoadTest(false);
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)}.
+     */
+    public void testPutFromLoadMinimal() throws Exception {
+        putFromLoadTest(true);
+    }
+    
+    /**
+     * Simulate 2 nodes, both start, tx do a get, experience a cache miss,
+     * then 'read from db.' First does a putFromLoad, then an evict (to represent a change).
+     * Second tries to do a putFromLoad with stale data (i.e. it took
+     * longer to read from the db).  Both commit their tx. Then
+     * both start a new tx and get. First should see the updated data;
+     * second should either see the updated data (isInvalidation()( == false)
+     * or null (isInvalidation() == true).
+     * 
+     * @param useMinimalAPI
+     * @throws Exception
+     */
+    private void putFromLoadTest(final boolean useMinimalAPI) throws Exception {
+        
+        final CountDownLatch writeLatch1 = new CountDownLatch(1);
+        final CountDownLatch writeLatch2 = new CountDownLatch(1);
+        final CountDownLatch completionLatch = new CountDownLatch(2);
+        
+        Thread node1 = new Thread() {          
+            
+            public void run() {
+                
+                try {       
+                    long txTimestamp = System.currentTimeMillis();
+                    BatchModeTransactionManager.getInstance().begin();
+                    
+                    assertEquals("node1 starts clean", null, localAccessStrategy.get(KEY, txTimestamp));
+                    
+                    writeLatch1.await();
+                    
+                    if (useMinimalAPI) {
+                        localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2), true);                        
+                    }
+                    else {
+                        localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2));
+                    }
+                    
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    log.error("node1 caught exception", e);
+                    node1Exception = e;
+                    rollback();
+                }
+                catch (AssertionFailedError e) {
+                    node1Failure = e;
+                    rollback();
+                }
+                finally {
+                    // Let node2 write
+                    writeLatch2.countDown();
+                    completionLatch.countDown();
+                }
+            }
+        };
+        
+        Thread node2 = new Thread() {
+          
+            public void run() { 
+                
+                try {                  
+                    long txTimestamp = System.currentTimeMillis();
+                    BatchModeTransactionManager.getInstance().begin();
+                    
+                    assertNull("node1 starts clean", remoteAccessStrategy.get(KEY, txTimestamp));
+                    
+                    // Let node1 write
+                    writeLatch1.countDown();
+                    // Wait for node1 to finish
+                    writeLatch2.await();
+                    
+                    // Let the first PFER propagate
+                    sleep(200);
+                    
+                    if (useMinimalAPI) {
+                        remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);                        
+                    }
+                    else {
+                        remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+                    }
+                    
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    log.error("node2 caught exception", e);
+                    node2Exception = e;
+                    rollback();
+                }
+                catch (AssertionFailedError e) {
+                    node2Failure = e;
+                    rollback();
+                }
+                finally {
+                    completionLatch.countDown();
+                }
+            }
+        };
+        
+        node1.setDaemon(true);
+        node2.setDaemon(true);
+        
+        node1.start();
+        node2.start();        
+        
+        assertTrue("Threads completed", completionLatch.await(2, TimeUnit.SECONDS));
+        
+        if (node1Failure != null)
+            throw node1Failure;
+        if (node2Failure != null)
+            throw node2Failure;
+        
+        assertEquals("node1 saw no exceptions", null, node1Exception);
+        assertEquals("node2 saw no exceptions", null, node2Exception);
+        
+        // let the final PFER propagate
+        sleep(100);
+        
+        long txTimestamp = System.currentTimeMillis();
+        String msg1 = "Correct node1 value";
+        String msg2 = "Correct node2 value";
+        Object expected1 = null;
+        Object expected2 = null;
+        if (isUsingInvalidation()) {
+            if (isUsingOptimisticLocking()) {
+                expected1 = null; // the initial VALUE2 DataVersion should prevent the node2 put
+                expected2 = VALUE2;
+                
+                // We know this case fails
+                msg1 = msg2 = "Known issue JBCACHE-1203";
+            }
+            else {
+                // node2 can write since there is no data version
+                // We count on db locking to prevent this case
+                expected1 = VALUE1; 
+                expected2 = null; // invalidated by node2
+                
+                // We know this case fails
+                msg1 = msg2 = "Known issue JBCACHE-1203";
+            }
+        }
+        else {
+            // the initial VALUE2 should prevent the node2 put
+            expected1 = VALUE2;
+            expected2 = VALUE2;
+        }
+        
+        assertEquals(msg1, expected1, localAccessStrategy.get(KEY, txTimestamp));        
+        assertEquals(msg2, expected2, remoteAccessStrategy.get(KEY, txTimestamp));
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#remove(java.lang.Object)}.
+     */
+    public void testRemove() {
+        evictOrRemoveTest(false);
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#removeAll()}.
+     */
+    public void testRemoveAll() {
+        evictOrRemoveAllTest(false);
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#evict(java.lang.Object)}.
+     * 
+     * FIXME add testing of the "immediately without regard for transaction
+     * isolation" bit in the CollectionRegionAccessStrategy API.
+     */
+    public void testEvict() {
+        evictOrRemoveTest(true);
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#evictAll()}.
+     * 
+     * FIXME add testing of the "immediately without regard for transaction
+     * isolation" bit in the CollectionRegionAccessStrategy API.
+     */
+    public void testEvictAll() {
+        evictOrRemoveAllTest(true);
+    }
+
+    private void evictOrRemoveTest(boolean evict) {
+        assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+        
+        localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+        assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+        assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+        
+        // Wait for async propagation
+        sleep(250);
+        
+        if (evict)
+            localAccessStrategy.evict(KEY);
+        else
+            localAccessStrategy.remove(KEY);
+        
+        assertEquals(null, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        
+        assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+    }
+
+    private void evictOrRemoveAllTest(boolean evict) {
+        
+        Fqn regionFqn = getRegionFqn(REGION_NAME, REGION_PREFIX);
+        
+        Node regionRoot = localCache.getRoot().getChild(regionFqn);
+        assertFalse(regionRoot == null);
+        assertEquals(0, regionRoot.getChildrenNames().size());
+        assertTrue(regionRoot.isResident());
+        
+        if (isUsingOptimisticLocking()) {
+            assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+        }
+
+        regionRoot = remoteCache.getRoot().getChild(regionFqn);
+        assertFalse(regionRoot == null);
+        assertEquals(0, regionRoot.getChildrenNames().size());
+        assertTrue(regionRoot.isResident());
+        
+        if (isUsingOptimisticLocking()) {
+            assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+        }
+        
+        assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+        
+        localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+        assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+        assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+        
+        // Wait for async propagation
+        sleep(250);
+        
+
+        
+        if (isUsingOptimisticLocking()) {
+            regionRoot = localCache.getRoot().getChild(regionFqn);
+            assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+            regionRoot = remoteCache.getRoot().getChild(regionFqn);
+            assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+        }
+        
+        if (evict)
+            localAccessStrategy.evictAll();
+        else
+            localAccessStrategy.removeAll();
+        
+        regionRoot = localCache.getRoot().getChild(regionFqn);
+        assertFalse(regionRoot == null);
+        assertEquals(0, regionRoot.getChildrenNames().size());
+        assertTrue(regionRoot.isResident());
+
+        regionRoot = remoteCache.getRoot().getChild(regionFqn);
+        assertFalse(regionRoot == null);
+        if (isUsingInvalidation()) {
+            // JBC seems broken: see http://www.jboss.com/index.html?module=bb&op=viewtopic&t=121408
+            // FIXME   replace with the following when JBCACHE-1199 and JBCACHE-1200 are done:
+            //assertFalse(regionRoot.isValid());
+            checkNodeIsEmpty(regionRoot);
+        }
+        else {
+            // Same assertion, just different assertion msg
+            assertEquals(0, regionRoot.getChildrenNames().size());
+        }        
+        assertTrue(regionRoot.isResident());
+        
+        assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+    }
+    
+    private void checkNodeIsEmpty(Node node) {
+        assertEquals("Known issue JBCACHE-1200. node " + node.getFqn() + " should not have keys", 0, node.getKeys().size());
+        for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
+            checkNodeIsEmpty((Node) it.next());
+        }
+    }
+    
+    private void rollback() {
+        try {
+            BatchModeTransactionManager.getInstance().rollback();
+        }
+        catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        
+    }
+    
+    private static class AccessStrategyTestSetup extends TestSetup {
+        
+        private String configName;
+        
+        public AccessStrategyTestSetup(Test test, String configName) {
+            super(test);
+            this.configName = configName;
+        }
+
+        @Override
+        protected void setUp() throws Exception {
+            super.setUp();
+            localCfg = createConfiguration(configName);
+            localRegionFactory = CacheTestUtil.startRegionFactory(localCfg);
+            localCache = localRegionFactory.getCacheInstanceManager().getCollectionCacheInstance();
+            
+            remoteCfg = createConfiguration(configName);
+            remoteRegionFactory  = CacheTestUtil.startRegionFactory(remoteCfg);
+            remoteCache = remoteRegionFactory.getCacheInstanceManager().getCollectionCacheInstance();
+        }
+
+        @Override
+        protected void tearDown() throws Exception {            
+            super.tearDown();
+            
+            if (localRegionFactory != null)
+                localRegionFactory.stop();
+            
+            if (remoteRegionFactory != null)
+                remoteRegionFactory.stop();
+        }
+        
+        
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractReadOnlyAccessTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractReadOnlyAccessTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractReadOnlyAccessTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.access.AccessType;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractReadOnlyAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase {
+
+    /**
+     * Create a new AbstractTransactionalAccessTestCase.
+     * 
+     */
+    public AbstractReadOnlyAccessTestCase(String name) {
+        super(name);
+    }
+
+    @Override
+    protected AccessType getAccessType() {
+        return AccessType.READ_ONLY;
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractTransactionalAccessTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractTransactionalAccessTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractTransactionalAccessTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.access.AccessType;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractTransactionalAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase {
+
+    /**
+     * Create a new AbstractTransactionalAccessTestCase.
+     * 
+     */
+    public AbstractTransactionalAccessTestCase(String name) {
+        super(name);
+    }
+
+    @Override
+    protected AccessType getAccessType() {
+        return AccessType.TRANSACTIONAL;
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/CollectionRegionImplTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/CollectionRegionImplTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/CollectionRegionImplTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.collection.CollectionRegionImpl;
+import org.hibernate.test.cache.jbc2.AbstractEntityCollectionRegionTestCase;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+
+/**
+ * Tests of CollectionRegionImpl.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class CollectionRegionImplTestCase extends AbstractEntityCollectionRegionTestCase {
+
+    /**
+     * Create a new EntityRegionImplTestCase.
+     * 
+     * @param name
+     */
+    public CollectionRegionImplTestCase(String name) {
+        super(name);
+    }
+    
+    protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
+        
+        CollectionRegion region = regionFactory.buildCollectionRegion("test", properties, null);
+        
+        assertNull("Got TRANSACTIONAL", region.buildAccessStrategy(AccessType.TRANSACTIONAL).lockRegion());
+        
+        try
+        {
+            region.buildAccessStrategy(AccessType.READ_ONLY).lockRegion();
+            fail("Did not get READ_ONLY");
+        }
+        catch (UnsupportedOperationException good) {}
+        
+        try
+        {
+            region.buildAccessStrategy(AccessType.NONSTRICT_READ_WRITE);
+            fail("Incorrectly got NONSTRICT_READ_WRITE");
+        }
+        catch (CacheException good) {}
+        
+        try
+        {
+            region.buildAccessStrategy(AccessType.READ_WRITE);
+            fail("Incorrectly got READ_WRITE");
+        }
+        catch (CacheException good) {}
+    }
+
+    @Override
+    protected Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
+        return regionFactory.buildCollectionRegion(regionName, properties, cdd);
+    }
+
+    @Override
+    protected Cache getJBossCache(JBossCacheRegionFactory regionFactory) {
+        CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
+        return mgr.getCollectionCacheInstance();
+    }
+
+    @Override
+    protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+        return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, CollectionRegionImpl.TYPE);
+    }
+    
+    
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticInvalidatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticInvalidatedTransactionalTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticInvalidatedTransactionalTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/** 
+ * Tests TRANSACTIONAL access when optimistic locking and invalidation are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticInvalidatedTransactionalTestCase 
+    extends AbstractTransactionalAccessTestCase {
+
+    /**
+     * Create a new TransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public OptimisticInvalidatedTransactionalTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        TestSuite suite = createFailureExpectedSuite(OptimisticInvalidatedTransactionalTestCase.class);   
+        return getTestSetup(suite, "optimistic-entity");
+    }
+    
+    @Override
+    public void testCacheConfiguration() {
+        assertTrue("Using Invalidation", isUsingInvalidation());
+        assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+        assertTrue("Synchronous mode", isSynchronous());
+    }
+    
+    // Known failures   
+
+    public void testEvictAllFailureExpected() {
+        super.testEvictAll();
+    }
+
+    public void testRemoveAllFailureExpected() {
+        super.testRemoveAll();
+    }
+
+    public void testPutFromLoadFailureExpected() throws Exception {
+        super.testPutFromLoad();
+    }
+
+    public void testPutFromLoadMinimalFailureExpected() throws Exception {
+        super.testPutFromLoadMinimal();
+    }    
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyExtraAPITestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyExtraAPITestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this
+ * version using Optimistic locking with READ_ONLY access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the 
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReadOnlyExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
+
+    private static CollectionRegionAccessStrategy localAccessStrategy;
+    
+    /**
+     * Create a new TransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public OptimisticReadOnlyExtraAPITestCase(String name) {
+        super(name);
+    }
+
+    @Override
+    protected AccessType getAccessType() {
+        return AccessType.READ_ONLY;
+    }
+    
+    @Override
+    protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
+        return localAccessStrategy;
+    }
+    
+    @Override
+    protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
+        localAccessStrategy = strategy;
+    }
+    
+    /**
+     * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+     */
+    @Override
+    public void testLockItem() {
+        try {
+            getCollectionAccessStrategy().lockItem(KEY, new Integer(1));
+            fail("Call to lockItem did not throw exception");
+        }
+        catch (UnsupportedOperationException expected) {}
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#lockRegion()}.
+     */
+    @Override
+    public void testLockRegion() {
+        try {
+            getCollectionAccessStrategy().lockRegion();
+            fail("Call to lockRegion did not throw exception");
+        }
+        catch (UnsupportedOperationException expected) {}
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests READ_ONLY access when optimistic locking and invalidation are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
+
+    /**
+     * Create a new PessimisticTransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public OptimisticReadOnlyTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        TestSuite suite = createFailureExpectedSuite(OptimisticReadOnlyTestCase.class);   
+        return getTestSetup(suite, "optimistic-entity");
+    }
+    
+    @Override
+    public void testCacheConfiguration() {
+        assertTrue("Using Invalidation", isUsingInvalidation());
+        assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+        assertTrue("Synchronous mode", isSynchronous());
+    }
+    
+    // Known failures   
+
+    public void testEvictAllFailureExpected() {
+        super.testEvictAll();
+    }
+
+    public void testRemoveAllFailureExpected() {
+        super.testRemoveAll();
+    }
+
+    public void testPutFromLoadFailureExpected() throws Exception {
+        super.testPutFromLoad();
+    }
+
+    public void testPutFromLoadMinimalFailureExpected() throws Exception {
+        super.testPutFromLoadMinimal();
+    }   
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReplicatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReplicatedTransactionalTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReplicatedTransactionalTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+
+/**
+ * Tests TRANSACTIONAL access when optimistic locking and replication are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+    /**
+     * Create a new PessimisticTransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public OptimisticReplicatedTransactionalTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        return getTestSetup(OptimisticReplicatedTransactionalTestCase.class, "optimistic-shared");
+    }
+
+    @Override
+    public void testCacheConfiguration() {
+        assertFalse("Using Invalidation", isUsingInvalidation());
+        assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+        assertTrue("Synchronous mode", isSynchronous());
+    }
+    
+    
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticTransactionalExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticTransactionalExtraAPITestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticTransactionalExtraAPITestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractJBossCacheTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+import org.jboss.cache.Cache;
+
+/**
+ * Tests for the "extra API" in CollectionRegionAccessStrategy; in this base
+ * version using Optimistic locking with TRANSACTIONAL access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the 
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticTransactionalExtraAPITestCase extends AbstractJBossCacheTestCase {
+
+    public static final String REGION_NAME = "test/com.foo.test";
+    public static final String KEY = "KEY";
+    public static final String VALUE1 = "VALUE1";
+    public static final String VALUE2 = "VALUE2";
+    
+    private static CollectionRegionAccessStrategy localAccessStrategy;
+    
+    private static boolean optimistic;
+    
+    /**
+     * Create a new TransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public OptimisticTransactionalExtraAPITestCase(String name) {
+        super(name);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        
+        if (getCollectionAccessStrategy() == null) {
+            Configuration cfg = createConfiguration();
+            JBossCacheRegionFactory rf  = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+            Cache localCache = rf.getCacheInstanceManager().getEntityCacheInstance();
+            optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
+            CollectionRegion localCollectionRegion = rf.buildCollectionRegion(REGION_NAME, cfg.getProperties(), null);
+            setCollectionAccessStrategy(localCollectionRegion.buildAccessStrategy(getAccessType()));
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        
+        super.tearDown();
+    }
+    
+    protected Configuration createConfiguration() {
+        Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
+        cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName());
+        return cfg;
+    }
+    
+    protected String getCacheConfigName() {
+        return "optimistic-entity";
+    }
+    
+    protected boolean isUsingOptimisticLocking() {
+        return optimistic;
+    }
+
+    protected AccessType getAccessType() {
+        return AccessType.TRANSACTIONAL;
+    }
+    
+    protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
+        return localAccessStrategy;
+    }
+    
+    protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
+        localAccessStrategy = strategy;
+    }
+    
+    /**
+     * This is just a setup test where we assert that the cache config is
+     * as we expected.
+     */
+    public void testCacheConfiguration() {
+        assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+    }
+    
+    /**
+     * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+     */
+    public void testLockItem() {
+        assertNull(getCollectionAccessStrategy().lockItem(KEY, new Integer(1)));
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#lockRegion()}.
+     */
+    public void testLockRegion() {
+        assertNull(getCollectionAccessStrategy().lockRegion());
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#unlockItem(java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+     */
+    public void testUnlockItem() {
+        getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock());
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#unlockRegion(org.hibernate.cache.access.SoftLock)}.
+     */
+    public void testUnlockRegion() {
+        getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock());
+    }
+    
+    public static class MockSoftLock implements SoftLock {
+        
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticInvalidatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticInvalidatedTransactionalTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticInvalidatedTransactionalTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests TRANSACTIONAL access when pessimistic locking and invalidation are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+    /**
+     * Create a new PessimisticTransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public PessimisticInvalidatedTransactionalTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        TestSuite suite = createFailureExpectedSuite(PessimisticInvalidatedTransactionalTestCase.class);   
+        return getTestSetup(suite, "pessimistic-entity");
+    }
+
+    @Override
+    public void testCacheConfiguration() {
+        assertTrue("Using Invalidation", isUsingInvalidation());
+        assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+        assertTrue("Synchronous mode", isSynchronous());
+    }
+    
+    // Known failures   
+
+    public void testEvictAllFailureExpected() {
+        super.testEvictAll();
+    }
+
+    public void testRemoveAllFailureExpected() {
+        super.testRemoveAll();
+    }
+
+    public void testPutFromLoadFailureExpected() throws Exception {
+        super.testPutFromLoad();
+    }
+
+    public void testPutFromLoadMinimalFailureExpected() throws Exception {
+        super.testPutFromLoadMinimal();
+    }    
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyExtraAPITestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyExtraAPITestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this 
+ * version using pessimistic locking with READ_ONLY access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the 
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReadOnlyExtraAPITestCase extends OptimisticReadOnlyExtraAPITestCase {
+
+    private static CollectionRegionAccessStrategy localAccessStrategy;
+    
+    /**
+     * Create a new PessimisticAccessStrategyExtraAPITestCase.
+     * 
+     * @param name
+     */
+    public PessimisticReadOnlyExtraAPITestCase(String name) {
+        super(name);
+    }
+    
+    @Override
+    protected String getCacheConfigName() {
+        return "pessimistic-entity";
+    }
+    
+    @Override
+    protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
+        return localAccessStrategy;
+    }
+    
+    @Override
+    protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
+        localAccessStrategy = strategy;
+    }
+    
+    @Override
+    public void testCacheConfiguration() {
+        assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests READ_ONLY access when pessimistic locking and invalidation are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
+
+    /**
+     * Create a new PessimisticTransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public PessimisticReadOnlyTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        TestSuite suite = createFailureExpectedSuite(PessimisticReadOnlyTestCase.class); 
+        return getTestSetup(suite, "pessimistic-entity");
+    }
+    
+    // Known failures   
+
+    public void testEvictAllFailureExpected() {
+        super.testEvictAll();
+    }
+
+    public void testRemoveAllFailureExpected() {
+        super.testRemoveAll();
+    }
+
+    public void testPutFromLoadFailureExpected() throws Exception {
+        super.testPutFromLoad();
+    }
+
+    public void testPutFromLoadMinimalFailureExpected() throws Exception {
+        super.testPutFromLoadMinimal();
+    }   
+    
+    // Overrides   
+
+    @Override
+    public void testCacheConfiguration() {
+        assertTrue("Using Invalidation", isUsingInvalidation());
+        assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReplicatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReplicatedTransactionalTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReplicatedTransactionalTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+
+/**
+ * Tests TRANSACTIONAL access when pessimistic locking and replication are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+    /**
+     * Create a new PessimisticTransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public PessimisticReplicatedTransactionalTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        return getTestSetup(PessimisticReplicatedTransactionalTestCase.class, "pessimistic-shared");
+    }
+
+    @Override
+    public void testCacheConfiguration() {
+        assertFalse("Using Invalidation", isUsingInvalidation());
+        assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+        assertTrue("Synchronous mode", isSynchronous());
+    }
+    
+    
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticTransactionalExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticTransactionalExtraAPITestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticTransactionalExtraAPITestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this base
+ * version using Optimistic locking with TRANSACTIONAL access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the 
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticTransactionalExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
+
+    private static CollectionRegionAccessStrategy localAccessStrategy;
+    
+    /**
+     * Create a new PessimisticAccessStrategyExtraAPITestCase.
+     * 
+     * @param name
+     */
+    public PessimisticTransactionalExtraAPITestCase(String name) {
+        super(name);
+    }
+    
+    @Override
+    protected String getCacheConfigName() {
+        return "pessimistic-entity";
+    }
+    
+    @Override
+    protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
+        return localAccessStrategy;
+    }
+    
+    @Override
+    protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
+        localAccessStrategy = strategy;
+    }
+    
+    @Override
+    public void testCacheConfiguration() {
+        assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import java.util.Iterator;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.extensions.TestSetup;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.impl.CacheDataDescriptionImpl;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.entity.EntityRegionImpl;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cache.jbc2.util.NonLockingDataVersion;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractJBossCacheTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+import org.hibernate.util.ComparableComparator;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.NodeSPI;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/** 
+ * Base class for tests of EntityRegionAccessStrategy impls.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractEntityRegionAccessStrategyTestCase extends AbstractJBossCacheTestCase {
+
+    public static final String REGION_NAME = "test/com.foo.test";
+    public static final String KEY = "KEY";
+    public static final String VALUE1 = "VALUE1";
+    public static final String VALUE2 = "VALUE2";
+    
+    protected static Configuration localCfg;
+    protected static JBossCacheRegionFactory localRegionFactory;
+    protected static Cache localCache;
+    protected static Configuration remoteCfg;
+    protected static JBossCacheRegionFactory remoteRegionFactory;
+    protected static Cache remoteCache;
+    
+    protected static boolean invalidation;
+    protected static boolean optimistic;
+    protected static boolean synchronous;
+    
+    protected EntityRegion localEntityRegion;
+    protected EntityRegionAccessStrategy localAccessStrategy;
+
+    protected EntityRegion remoteEntityRegion;
+    protected EntityRegionAccessStrategy remoteAccessStrategy;
+    
+    protected Exception node1Exception;
+    protected Exception node2Exception;
+    
+    protected AssertionFailedError node1Failure;
+    protected AssertionFailedError node2Failure;
+    
+    
+    public static Test getTestSetup(Class testClass, String configName) {
+        TestSuite suite = new TestSuite(testClass);
+        return new AccessStrategyTestSetup(suite, configName);
+    }
+    
+    public static Test getTestSetup(Test test, String configName) {
+        return new AccessStrategyTestSetup(test, configName);
+    }
+    
+    
+    /**
+     * Create a new TransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public AbstractEntityRegionAccessStrategyTestCase(String name) {
+        super(name);
+    }
+
+    protected abstract AccessType getAccessType();
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        
+        localEntityRegion = localRegionFactory.buildEntityRegion(REGION_NAME, localCfg.getProperties(), getCacheDataDescription());
+        localAccessStrategy = localEntityRegion.buildAccessStrategy(getAccessType());
+        
+        remoteEntityRegion = remoteRegionFactory.buildEntityRegion(REGION_NAME, remoteCfg.getProperties(), getCacheDataDescription());
+        remoteAccessStrategy = remoteEntityRegion.buildAccessStrategy(getAccessType());
+                
+        node1Exception = null;
+        node2Exception = null;
+        
+        node1Failure = null;
+        node2Failure  = null;
+    }
+
+    protected void tearDown() throws Exception {
+        
+        super.tearDown();
+        
+        if (localEntityRegion != null)
+            localEntityRegion.destroy();
+        if (remoteEntityRegion != null)
+            remoteEntityRegion.destroy();
+        
+        try {
+            localCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+            localCache.removeNode(Fqn.ROOT);
+        }
+        catch (Exception e) {
+            log.error("Problem purging local cache" ,e);
+        }
+        
+        try {
+            remoteCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+            remoteCache.removeNode(Fqn.ROOT);
+        }
+        catch (Exception e) {
+            log.error("Problem purging remote cache" ,e);
+        }
+        
+        node1Exception = null;
+        node2Exception = null;
+        
+        node1Failure = null;
+        node2Failure  = null;
+    }
+    
+    protected static Configuration createConfiguration(String configName) {
+        Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
+        cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, configName);
+        return cfg;
+    }
+    
+    protected CacheDataDescription getCacheDataDescription() {
+        return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
+    }
+    
+    protected boolean isUsingOptimisticLocking() {
+        return optimistic;
+    }
+    
+    protected boolean isUsingInvalidation() {
+        return invalidation;
+    }
+    
+    protected boolean isSynchronous() {
+        return synchronous;
+    }
+    
+    protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+        return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, EntityRegionImpl.TYPE);
+    }
+    
+    /**
+     * This is just a setup test where we assert that the cache config is
+     * as we expected.
+     */
+    public abstract void testCacheConfiguration();
+    
+    /**
+     * Test method for {@link TransactionalAccess#getRegion()}.
+     */
+    public void testGetRegion() {
+        assertEquals("Correct region", localEntityRegion, localAccessStrategy.getRegion());
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)}.
+     */
+    public void testPutFromLoad() throws Exception {
+        putFromLoadTest(false);
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)}.
+     */
+    public void testPutFromLoadMinimal() throws Exception {
+        putFromLoadTest(true);
+    }
+    
+    /**
+     * Simulate 2 nodes, both start, tx do a get, experience a cache miss,
+     * then 'read from db.' First does a putFromLoad, then an update.
+     * Second tries to do a putFromLoad with stale data (i.e. it took
+     * longer to read from the db).  Both commit their tx. Then
+     * both start a new tx and get. First should see the updated data;
+     * second should either see the updated data (isInvalidation()( == false)
+     * or null (isInvalidation() == true).
+     * 
+     * @param useMinimalAPI
+     * @throws Exception
+     */
+    private void putFromLoadTest(final boolean useMinimalAPI) throws Exception {
+        
+        final CountDownLatch writeLatch1 = new CountDownLatch(1);
+        final CountDownLatch writeLatch2 = new CountDownLatch(1);
+        final CountDownLatch completionLatch = new CountDownLatch(2);
+        
+        Thread node1 = new Thread() {          
+            
+            public void run() {
+                
+                try {       
+                    long txTimestamp = System.currentTimeMillis();
+                    BatchModeTransactionManager.getInstance().begin();
+                    
+                    assertNull("node1 starts clean", localAccessStrategy.get(KEY, txTimestamp));
+                    
+                    writeLatch1.await();
+                    
+                    if (useMinimalAPI) {
+                        localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);                        
+                    }
+                    else {
+                        localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+                    }
+                    
+                    localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+                    
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    log.error("node1 caught exception", e);
+                    node1Exception = e;
+                    rollback();
+                }
+                catch (AssertionFailedError e) {
+                    node1Failure = e;
+                    rollback();
+                }
+                finally {
+                    // Let node2 write
+                    writeLatch2.countDown();
+                    completionLatch.countDown();
+                }
+            }
+        };
+        
+        Thread node2 = new Thread() {
+          
+            public void run() { 
+                
+                try {                  
+                    long txTimestamp = System.currentTimeMillis();
+                    BatchModeTransactionManager.getInstance().begin();
+                    
+                    assertNull("node1 starts clean", remoteAccessStrategy.get(KEY, txTimestamp));
+                    
+                    // Let node1 write
+                    writeLatch1.countDown();
+                    // Wait for node1 to finish
+                    writeLatch2.await();
+                    
+                    if (useMinimalAPI) {
+                        remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);                        
+                    }
+                    else {
+                        remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+                    }
+                    
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    log.error("node2 caught exception", e);
+                    node2Exception = e;
+                    rollback();
+                }
+                catch (AssertionFailedError e) {
+                    node2Failure = e;
+                    rollback();
+                }
+                finally {
+                    completionLatch.countDown();
+                }
+            }
+        };
+        
+        node1.setDaemon(true);
+        node2.setDaemon(true);
+        
+        node1.start();
+        node2.start();        
+        
+        assertTrue("Threads completed", completionLatch.await(2, TimeUnit.SECONDS));
+        
+        if (node1Failure != null)
+            throw node1Failure;
+        if (node2Failure != null)
+            throw node2Failure;
+        
+        assertEquals("node1 saw no exceptions", null, node1Exception);
+        assertEquals("node2 saw no exceptions", null, node2Exception);
+        
+        long txTimestamp = System.currentTimeMillis();
+        assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
+        
+        if (isUsingInvalidation()) {
+            if (isUsingOptimisticLocking())
+                // The node is "deleted" but it's ghost data version prevents the stale node2 PFER 
+                assertEquals("Correct node2 value", null, remoteAccessStrategy.get(KEY, txTimestamp));
+            else {
+                // no data version to prevent the PFER; we count on db locks preventing this
+                assertEquals("Expected node2 value", VALUE1, remoteAccessStrategy.get(KEY, txTimestamp));                
+            }
+        }
+        else {
+            // The node1 update is replicated, preventing the node2 PFER
+            assertEquals("Correct node2 value", VALUE2, remoteAccessStrategy.get(KEY, txTimestamp));            
+        }
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#insert(java.lang.Object, java.lang.Object, java.lang.Object)}.
+     */
+    public void testInsert() throws Exception {
+        
+        final CountDownLatch readLatch = new CountDownLatch(1);
+        final CountDownLatch commitLatch = new CountDownLatch(1);
+        final CountDownLatch completionLatch = new CountDownLatch(2);
+        
+        Thread inserter = new Thread() {          
+            
+            public void run() {
+                
+                try {       
+                    long txTimestamp = System.currentTimeMillis();
+                    BatchModeTransactionManager.getInstance().begin();
+                    
+                    assertNull("Correct initial value", localAccessStrategy.get(KEY, txTimestamp));
+                    
+                    localAccessStrategy.insert(KEY, VALUE1, new Integer(1));
+                    
+                    readLatch.countDown();
+                    commitLatch.await();
+                    
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    log.error("node1 caught exception", e);
+                    node1Exception = e;
+                    rollback();
+                }
+                catch (AssertionFailedError e) {
+                    node1Failure = e;
+                    rollback();
+                }
+                finally {
+                    completionLatch.countDown();
+                }
+            }
+        };
+        
+        Thread reader = new Thread() {          
+            
+            public void run() {
+                
+                try {       
+                    long txTimestamp = System.currentTimeMillis();
+                    BatchModeTransactionManager.getInstance().begin();
+                    
+                    readLatch.await();
+                    Object expected = isUsingOptimisticLocking() ? null : VALUE1;
+                    
+                    assertEquals("Correct initial value", expected, localAccessStrategy.get(KEY, txTimestamp));
+                    
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    log.error("node1 caught exception", e);
+                    node1Exception = e;
+                    rollback();
+                }
+                catch (AssertionFailedError e) {
+                    node1Failure = e;
+                    rollback();
+                }
+                finally {
+                    commitLatch.countDown();
+                    completionLatch.countDown();
+                }
+            }
+        };
+        
+        inserter.setDaemon(true);
+        reader.setDaemon(true);
+        inserter.start();
+        reader.start();
+        
+        if (isUsingOptimisticLocking())
+            assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
+        else {
+            // Reader should be blocking for lock
+            assertFalse("Threads completed", completionLatch.await(250, TimeUnit.MILLISECONDS));
+            commitLatch.countDown();
+            assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
+        }
+        
+        if (node1Failure != null)
+            throw node1Failure;
+        if (node2Failure != null)
+            throw node2Failure;
+        
+        assertEquals("node1 saw no exceptions", null, node1Exception);
+        assertEquals("node2 saw no exceptions", null, node2Exception);
+        
+        long txTimestamp = System.currentTimeMillis();
+        assertEquals("Correct node1 value", VALUE1, localAccessStrategy.get(KEY, txTimestamp));
+        Object expected = isUsingInvalidation() ? null : VALUE1;
+        assertEquals("Correct node2 value", expected, remoteAccessStrategy.get(KEY, txTimestamp));
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#update(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object)}.
+     */
+    public void testUpdate() throws Exception {
+        
+        // Set up initial state
+        localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+        remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+        
+        // Let the async put propagate
+        sleep(250);
+        
+        final CountDownLatch readLatch = new CountDownLatch(1);
+        final CountDownLatch commitLatch = new CountDownLatch(1);
+        final CountDownLatch completionLatch = new CountDownLatch(2);
+        
+        Thread updater = new Thread() {          
+            
+            public void run() {
+                
+                try {       
+                    long txTimestamp = System.currentTimeMillis();
+                    BatchModeTransactionManager.getInstance().begin();
+                    
+                    assertEquals("Correct initial value", VALUE1, localAccessStrategy.get(KEY, txTimestamp));
+                    
+                    localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+                    
+                    readLatch.countDown();
+                    commitLatch.await();
+                    
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    log.error("node1 caught exception", e);
+                    node1Exception = e;
+                    rollback();
+                }
+                catch (AssertionFailedError e) {
+                    node1Failure = e;
+                    rollback();
+                }
+                finally {
+                    completionLatch.countDown();
+                }
+            }
+        };
+        
+        Thread reader = new Thread() {          
+            
+            public void run() {                
+                try {       
+                    long txTimestamp = System.currentTimeMillis();
+                    BatchModeTransactionManager.getInstance().begin();
+                    
+                    readLatch.await();
+                    
+                    // This will block w/ pessimistic locking and then
+                    // read the new value; w/ optimistic it shouldn't
+                    // block and will read the old value
+                    Object expected = isUsingOptimisticLocking() ? VALUE1 : VALUE2;
+                    assertEquals("Correct value", expected, localAccessStrategy.get(KEY, txTimestamp));
+                    
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    log.error("node1 caught exception", e);
+                    node1Exception = e;
+                    rollback();
+                }
+                catch (AssertionFailedError e) {
+                    node1Failure = e;
+                    rollback();
+                }
+                finally {
+                    commitLatch.countDown();
+                    completionLatch.countDown();
+                }                
+            }
+        };
+        
+        updater.setDaemon(true);
+        reader.setDaemon(true);
+        updater.start();
+        reader.start();
+        
+        if (isUsingOptimisticLocking())
+            // Should complete promptly
+            assertTrue(completionLatch.await(1, TimeUnit.SECONDS));
+        else {        
+            // Reader thread should be blocking
+            assertFalse(completionLatch.await(250, TimeUnit.MILLISECONDS));
+            // Let the writer commit down
+            commitLatch.countDown();
+            assertTrue(completionLatch.await(1, TimeUnit.SECONDS));
+        }
+        
+        if (node1Failure != null)
+            throw node1Failure;
+        if (node2Failure != null)
+            throw node2Failure;
+        
+        assertEquals("node1 saw no exceptions", null, node1Exception);
+        assertEquals("node2 saw no exceptions", null, node2Exception);
+        
+        long txTimestamp = System.currentTimeMillis();
+        assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
+        Object expected = isUsingInvalidation() ? null : VALUE2;
+        assertEquals("Correct node2 value", expected, remoteAccessStrategy.get(KEY, txTimestamp));
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#remove(java.lang.Object)}.
+     */
+    public void testRemove() {
+        evictOrRemoveTest(false);
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#removeAll()}.
+     */
+    public void testRemoveAll() {
+        evictOrRemoveAllTest(false);
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#evict(java.lang.Object)}.
+     * 
+     * FIXME add testing of the "immediately without regard for transaction
+     * isolation" bit in the EntityRegionAccessStrategy API.
+     */
+    public void testEvict() {
+        evictOrRemoveTest(true);
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#evictAll()}.
+     * 
+     * FIXME add testing of the "immediately without regard for transaction
+     * isolation" bit in the EntityRegionAccessStrategy API.
+     */
+    public void testEvictAll() {
+        evictOrRemoveAllTest(true);
+    }
+
+    private void evictOrRemoveTest(boolean evict) {
+        assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+        
+        localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+        assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+        assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+        
+        // Wait for async propagation
+        sleep(250);
+        
+        if (evict)
+            localAccessStrategy.evict(KEY);
+        else
+            localAccessStrategy.remove(KEY);
+        
+        assertEquals(null, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        
+//        sleep(1000);
+        
+        assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+    }
+
+    private void evictOrRemoveAllTest(boolean evict) {
+        
+        Fqn regionFqn = getRegionFqn(REGION_NAME, REGION_PREFIX);
+        
+        Node regionRoot = localCache.getRoot().getChild(regionFqn);
+        assertFalse(regionRoot == null);
+        assertEquals(0, regionRoot.getChildrenNames().size());
+        assertTrue(regionRoot.isResident());
+        
+        if (isUsingOptimisticLocking()) {
+            assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+        }
+
+        regionRoot = remoteCache.getRoot().getChild(regionFqn);
+        assertFalse(regionRoot == null);
+        assertEquals(0, regionRoot.getChildrenNames().size());
+        assertTrue(regionRoot.isResident());
+        
+        if (isUsingOptimisticLocking()) {
+            assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+        }
+        
+        assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+        
+        localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+        assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+        assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+        
+        // Wait for async propagation
+        sleep(250);
+        
+
+        
+        if (isUsingOptimisticLocking()) {
+            regionRoot = localCache.getRoot().getChild(regionFqn);
+            assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+            regionRoot = remoteCache.getRoot().getChild(regionFqn);
+            assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+        }
+        
+        if (evict)
+            localAccessStrategy.evictAll();
+        else
+            localAccessStrategy.removeAll();
+        
+        regionRoot = localCache.getRoot().getChild(regionFqn);
+        assertFalse(regionRoot == null);
+        assertEquals(0, regionRoot.getChildrenNames().size());
+        assertTrue(regionRoot.isResident());
+
+        regionRoot = remoteCache.getRoot().getChild(regionFqn);
+        assertFalse(regionRoot == null);
+        if (isUsingInvalidation()) {
+            // JBC seems broken: see http://www.jboss.com/index.html?module=bb&op=viewtopic&t=121408
+            // FIXME   replace with the following when JBCACHE-1199 and JBCACHE-1200 are done:
+            //assertFalse(regionRoot.isValid());
+            checkNodeIsEmpty(regionRoot);
+        }
+        else {
+            // Same assertion, just different assertion msg
+            assertEquals(0, regionRoot.getChildrenNames().size());
+        }        
+        assertTrue(regionRoot.isResident());
+        
+        assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+    }
+    
+    private void checkNodeIsEmpty(Node node) {
+        assertEquals("Known issue JBCACHE-1200. node " + node.getFqn() + " should not have keys", 0, node.getKeys().size());
+        for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
+            checkNodeIsEmpty((Node) it.next());
+        }
+    }
+    
+    protected void rollback() {
+        try {
+            BatchModeTransactionManager.getInstance().rollback();
+        }
+        catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        
+    }
+    
+    private static class AccessStrategyTestSetup extends TestSetup {
+        
+        private String configName;
+        
+        public AccessStrategyTestSetup(Test test, String configName) {
+            super(test);
+            this.configName = configName;
+        }
+
+        @Override
+        protected void setUp() throws Exception {
+            super.setUp();
+            localCfg = createConfiguration(configName);
+            localRegionFactory = CacheTestUtil.startRegionFactory(localCfg);
+            localCache = localRegionFactory.getCacheInstanceManager().getEntityCacheInstance();
+            
+            remoteCfg = createConfiguration(configName);
+            remoteRegionFactory  = CacheTestUtil.startRegionFactory(remoteCfg);
+            remoteCache = remoteRegionFactory.getCacheInstanceManager().getEntityCacheInstance();
+            
+            invalidation = CacheHelper.isClusteredInvalidation(localCache);
+            synchronous = CacheHelper.isSynchronous(localCache);
+            optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
+        }
+
+        @Override
+        protected void tearDown() throws Exception {            
+            super.tearDown();
+            
+            if (localRegionFactory != null)
+                localRegionFactory.stop();
+            
+            if (remoteRegionFactory != null)
+                remoteRegionFactory.stop();
+        }
+        
+        
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractReadOnlyAccessTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractReadOnlyAccessTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractReadOnlyAccessTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import org.hibernate.cache.access.AccessType;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractReadOnlyAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
+
+    /**
+     * Create a new AbstractTransactionalAccessTestCase.
+     * 
+     */
+    public AbstractReadOnlyAccessTestCase(String name) {
+        super(name);
+    }
+
+    @Override
+    protected AccessType getAccessType() {
+        return AccessType.READ_ONLY;
+    }   
+
+    @Override
+    public void testPutFromLoad() throws Exception {
+        putFromLoadTest(false);
+    }
+
+    @Override
+    public void testPutFromLoadMinimal() throws Exception {
+        putFromLoadTest(true);
+    }
+    
+    private void putFromLoadTest(boolean minimal) throws Exception {
+        long txTimestamp = System.currentTimeMillis();
+        BatchModeTransactionManager.getInstance().begin();
+        assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        if (minimal)
+            localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
+        else
+            localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+        
+        sleep(250);
+        Object expected = isUsingInvalidation() ? null : VALUE1;
+        assertEquals(expected, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+        
+        BatchModeTransactionManager.getInstance().commit();
+        assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+        assertEquals(expected, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+    }
+
+    @Override
+    public void testUpdate() throws Exception {
+        try {
+            localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+            fail("Call to update did not throw exception");
+        }
+        catch (UnsupportedOperationException good) {}
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.cache.access.AccessType;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractTransactionalAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
+
+    /**
+     * Create a new AbstractTransactionalAccessTestCase.
+     * 
+     */
+    public AbstractTransactionalAccessTestCase(String name) {
+        super(name);
+    }
+
+    @Override
+    protected AccessType getAccessType() {
+        return AccessType.TRANSACTIONAL;
+    }
+    
+    public void testContestedPutFromLoad() throws Exception {
+        
+        localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+               
+        final CountDownLatch pferLatch = new CountDownLatch(1);
+        final CountDownLatch pferCompletionLatch = new CountDownLatch(1);
+        final CountDownLatch commitLatch = new CountDownLatch(1);
+        final CountDownLatch completionLatch = new CountDownLatch(1);
+        
+        Thread blocker = new Thread() {          
+            
+            public void run() {
+                
+                try {       
+                    long txTimestamp = System.currentTimeMillis();
+                    BatchModeTransactionManager.getInstance().begin();
+                    
+                    assertEquals("Correct initial value", VALUE1, localAccessStrategy.get(KEY, txTimestamp));
+                    
+                    localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+                    
+                    pferLatch.countDown();
+                    commitLatch.await();
+                    
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    log.error("node1 caught exception", e);
+                    node1Exception = e;
+                    rollback();
+                }
+                catch (AssertionFailedError e) {
+                    node1Failure = e;
+                    rollback();
+                }
+                finally {
+                    completionLatch.countDown();
+                }
+            }
+        };
+        
+        Thread putter = new Thread() {          
+            
+            public void run() {
+                
+                try {       
+                    long txTimestamp = System.currentTimeMillis();
+                    BatchModeTransactionManager.getInstance().begin();
+                    
+                    localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+                    
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    log.error("node1 caught exception", e);
+                    node1Exception = e;
+                    rollback();
+                }
+                catch (AssertionFailedError e) {
+                    node1Failure = e;
+                    rollback();
+                }
+                finally {
+                    pferCompletionLatch.countDown();
+                }
+            }
+        };
+        
+        blocker.start();
+        assertTrue("Active tx has done an update", pferLatch.await(1, TimeUnit.SECONDS));
+        putter.start();
+        assertTrue("putFromLoadreturns promtly", pferCompletionLatch.await(10, TimeUnit.MILLISECONDS));
+        
+        commitLatch.countDown();       
+        
+        assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
+        
+        if (node1Failure != null)
+            throw node1Failure;
+        if (node2Failure != null)
+            throw node2Failure;
+        
+        assertEquals("node1 saw no exceptions", null, node1Exception);
+        assertEquals("node2 saw no exceptions", null, node2Exception);
+        
+        long txTimestamp = System.currentTimeMillis();
+        assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/EntityRegionImplTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/EntityRegionImplTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/EntityRegionImplTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.entity.EntityRegionImpl;
+import org.hibernate.test.cache.jbc2.AbstractEntityCollectionRegionTestCase;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+
+/**
+ * Tests of EntityRegionImpl.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class EntityRegionImplTestCase extends AbstractEntityCollectionRegionTestCase {
+    
+    /**
+     * Create a new EntityRegionImplTestCase.
+     * 
+     * @param name
+     */
+    public EntityRegionImplTestCase(String name) {
+        super(name);
+    } 
+    
+    protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
+        
+        EntityRegion region = regionFactory.buildEntityRegion("test", properties, null);
+        
+        assertNull("Got TRANSACTIONAL", region.buildAccessStrategy(AccessType.TRANSACTIONAL).lockRegion());
+        
+        try
+        {
+            region.buildAccessStrategy(AccessType.READ_ONLY).lockRegion();
+            fail("Did not get READ_ONLY");
+        }
+        catch (UnsupportedOperationException good) {}
+        
+        try
+        {
+            region.buildAccessStrategy(AccessType.NONSTRICT_READ_WRITE);
+            fail("Incorrectly got NONSTRICT_READ_WRITE");
+        }
+        catch (CacheException good) {}
+        
+        try
+        {
+            region.buildAccessStrategy(AccessType.READ_WRITE);
+            fail("Incorrectly got READ_WRITE");
+        }
+        catch (CacheException good) {}      
+        
+    }
+
+    @Override
+    protected Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
+        return regionFactory.buildEntityRegion(regionName, properties, cdd);
+    }
+
+    @Override
+    protected Cache getJBossCache(JBossCacheRegionFactory regionFactory) {
+        CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
+        return mgr.getEntityCacheInstance();
+    }
+
+    @Override
+    protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+        return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, EntityRegionImpl.TYPE);
+    }
+    
+    
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticInvalidatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticInvalidatedTransactionalTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticInvalidatedTransactionalTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/** 
+ * Tests TRANSACTIONAL access when optimistic locking and invalidation are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+    
+    /**
+     * Create a new OptimisticInvalidatedTransactionalTestCase.
+     * 
+     * @param name
+     */
+    public OptimisticInvalidatedTransactionalTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        TestSuite suite = createFailureExpectedSuite(OptimisticInvalidatedTransactionalTestCase.class);   
+        return getTestSetup(suite, "optimistic-entity");
+    }
+    
+    @Override
+    public void testCacheConfiguration() {
+        assertTrue("Using Invalidation", isUsingInvalidation());
+        assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+        assertTrue("Synchronous mode", isSynchronous());
+    }
+    
+    // Known failures   
+
+    public void testEvictAllFailureExpected() {
+        super.testEvictAll();
+    }
+
+    public void testRemoveAllFailureExpected() {
+        super.testRemoveAll();
+    }
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyExtraAPITestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyExtraAPITestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this
+ * version using Optimistic locking with READ_ONLY access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the 
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReadOnlyExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
+
+    private static EntityRegionAccessStrategy localAccessStrategy;
+    
+    /**
+     * Create a new TransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public OptimisticReadOnlyExtraAPITestCase(String name) {
+        super(name);
+    }
+
+    @Override
+    protected AccessType getAccessType() {
+        return AccessType.READ_ONLY;
+    }
+    
+    @Override
+    protected EntityRegionAccessStrategy getEntityAccessStrategy() {
+        return localAccessStrategy;
+    }
+    
+    @Override
+    protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
+        localAccessStrategy = strategy;
+    }
+    
+    /**
+     * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+     */
+    @Override
+    public void testLockItem() {
+        try {
+            getEntityAccessStrategy().lockItem(KEY, new Integer(1));
+            fail("Call to lockItem did not throw exception");
+        }
+        catch (UnsupportedOperationException expected) {}
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#lockRegion()}.
+     */
+    @Override
+    public void testLockRegion() {
+        try {
+            getEntityAccessStrategy().lockRegion();
+            fail("Call to lockRegion did not throw exception");
+        }
+        catch (UnsupportedOperationException expected) {}
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+     */
+    @Override
+    public void testAfterUpdate() {
+        try {
+            getEntityAccessStrategy().afterUpdate(KEY, VALUE2, new Integer(1), new Integer(2), new MockSoftLock());
+            fail("Call to afterUpdate did not throw exception");
+        }
+        catch (UnsupportedOperationException expected) {}
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests READ_ONLY access when optimistic locking and invalidation are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
+
+    /**
+     * Create a new PessimisticTransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public OptimisticReadOnlyTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        TestSuite suite = createFailureExpectedSuite(OptimisticReadOnlyTestCase.class);        
+        return getTestSetup(suite, "optimistic-entity");
+    }
+    
+    @Override
+    public void testCacheConfiguration() {
+        assertTrue("Using Invalidation", isUsingInvalidation());
+        assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+        assertTrue("Synchronous mode", isSynchronous());
+    }
+    
+    // Known failures   
+
+    public void testEvictAllFailureExpected() {
+        super.testEvictAll();
+    }
+
+    public void testRemoveAllFailureExpected() {
+        super.testRemoveAll();
+    }    
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReplicatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReplicatedTransactionalTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReplicatedTransactionalTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+
+/**
+ * Tests TRANSACTIONAL access when optimistic locking and replication are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+    /**
+     * Create a new PessimisticTransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public OptimisticReplicatedTransactionalTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        return getTestSetup(OptimisticReplicatedTransactionalTestCase.class, "optimistic-shared");
+    }
+
+    @Override
+    public void testCacheConfiguration() {
+        assertFalse("Using Invalidation", isUsingInvalidation());
+        assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+        assertTrue("Synchronous mode", isSynchronous());
+    }
+    
+    
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticTransactionalExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticTransactionalExtraAPITestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticTransactionalExtraAPITestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractJBossCacheTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+import org.jboss.cache.Cache;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this base
+ * version using Optimistic locking with TRANSACTIONAL access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the 
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticTransactionalExtraAPITestCase extends AbstractJBossCacheTestCase {
+
+    public static final String REGION_NAME = "test/com.foo.test";
+    public static final String KEY = "KEY";
+    public static final String VALUE1 = "VALUE1";
+    public static final String VALUE2 = "VALUE2";
+    
+    private static EntityRegionAccessStrategy localAccessStrategy;
+    
+    private static boolean optimistic;
+    
+    /**
+     * Create a new TransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public OptimisticTransactionalExtraAPITestCase(String name) {
+        super(name);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        
+        if (getEntityAccessStrategy() == null) {
+            Configuration cfg = createConfiguration();
+            JBossCacheRegionFactory rf  = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+            Cache localCache = rf.getCacheInstanceManager().getEntityCacheInstance();
+            optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
+            EntityRegion localEntityRegion = rf.buildEntityRegion(REGION_NAME, cfg.getProperties(), null);
+            setEntityRegionAccessStrategy(localEntityRegion.buildAccessStrategy(getAccessType()));
+        }
+    }
+
+    protected void tearDown() throws Exception {
+        
+        super.tearDown();
+    }
+    
+    protected Configuration createConfiguration() {
+        Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
+        cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName());
+        return cfg;
+    }
+    
+    protected String getCacheConfigName() {
+        return "optimistic-entity";
+    }
+    
+    protected boolean isUsingOptimisticLocking() {
+        return optimistic;
+    }
+
+    protected AccessType getAccessType() {
+        return AccessType.TRANSACTIONAL;
+    }
+    
+    protected EntityRegionAccessStrategy getEntityAccessStrategy() {
+        return localAccessStrategy;
+    }
+    
+    protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
+        localAccessStrategy = strategy;
+    }
+    
+    /**
+     * This is just a setup test where we assert that the cache config is
+     * as we expected.
+     */
+    public void testCacheConfiguration() {
+        assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+    }
+    
+    /**
+     * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+     */
+    public void testLockItem() {
+        assertNull(getEntityAccessStrategy().lockItem(KEY, new Integer(1)));
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#lockRegion()}.
+     */
+    public void testLockRegion() {
+        assertNull(getEntityAccessStrategy().lockRegion());
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#unlockItem(java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+     */
+    public void testUnlockItem() {
+        getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock());
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#unlockRegion(org.hibernate.cache.access.SoftLock)}.
+     */
+    public void testUnlockRegion() {
+        getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock());
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#afterInsert(java.lang.Object, java.lang.Object, java.lang.Object)}.
+     */
+    public void testAfterInsert() {
+        assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterInsert(KEY, VALUE1, new Integer(1)));
+    }
+
+    /**
+     * Test method for {@link TransactionalAccess#afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+     */
+    public void testAfterUpdate() {
+        assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterUpdate(KEY, VALUE2, new Integer(1), new Integer(2), new MockSoftLock()));
+    }
+    
+    public static class MockSoftLock implements SoftLock {
+        
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticInvalidatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticInvalidatedTransactionalTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticInvalidatedTransactionalTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests TRANSACTIONAL access when pessimistic locking and invalidation are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+    /**
+     * Create a new PessimisticTransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public PessimisticInvalidatedTransactionalTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        TestSuite suite = createFailureExpectedSuite(PessimisticInvalidatedTransactionalTestCase.class);
+        return getTestSetup(suite, "pessimistic-entity");
+    }
+    
+    // Known failures   
+
+    public void testEvictAllFailureExpected() {
+        super.testEvictAll();
+    }
+
+    public void testRemoveAllFailureExpected() {
+        super.testRemoveAll();
+    }
+
+    // Overrides
+    
+    @Override
+    public void testCacheConfiguration() {
+        assertTrue("Using Invalidation", isUsingInvalidation());
+        assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+        assertTrue("Synchronous mode", isSynchronous());
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyExtraAPITestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyExtraAPITestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this 
+ * version using pessimistic locking with READ_ONLY access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the 
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReadOnlyExtraAPITestCase extends OptimisticReadOnlyExtraAPITestCase {
+
+    private static EntityRegionAccessStrategy localAccessStrategy;
+    
+    /**
+     * Create a new PessimisticAccessStrategyExtraAPITestCase.
+     * 
+     * @param name
+     */
+    public PessimisticReadOnlyExtraAPITestCase(String name) {
+        super(name);
+    }
+    
+    @Override
+    protected String getCacheConfigName() {
+        return "pessimistic-entity";
+    }
+    
+    @Override
+    protected EntityRegionAccessStrategy getEntityAccessStrategy() {
+        return localAccessStrategy;
+    }
+    
+    @Override
+    protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
+        localAccessStrategy = strategy;
+    }
+    
+    @Override
+    public void testCacheConfiguration() {
+        assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.access.AccessType;
+
+/**
+ * Tests READ_ONLY access when pessimistic locking and invalidation are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
+
+    /**
+     * Create a new PessimisticTransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public PessimisticReadOnlyTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        TestSuite suite = createFailureExpectedSuite(PessimisticReadOnlyTestCase.class); 
+        return getTestSetup(suite, "pessimistic-entity");
+    }
+    
+    // Known failures   
+
+    public void testEvictAllFailureExpected() {
+        super.testEvictAll();
+    }
+
+    public void testRemoveAllFailureExpected() {
+        super.testRemoveAll();
+    }
+    
+    // Overrides   
+
+
+    @Override
+    public void testCacheConfiguration() {
+        assertTrue("Using Invalidation", isUsingInvalidation());
+        assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+    }
+    
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReplicatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReplicatedTransactionalTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReplicatedTransactionalTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+
+/**
+ * Tests TRANSACTIONAL access when pessimistic locking and replication are used.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+    /**
+     * Create a new PessimisticTransactionalAccessTestCase.
+     * 
+     * @param name
+     */
+    public PessimisticReplicatedTransactionalTestCase(String name) {
+        super(name);
+    }
+    
+    public static Test suite() throws Exception {
+        return getTestSetup(PessimisticReplicatedTransactionalTestCase.class, "pessimistic-shared");
+    }
+
+    @Override
+    public void testCacheConfiguration() {
+        assertFalse("Using Invalidation", isUsingInvalidation());
+        assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+        assertTrue("Synchronous mode", isSynchronous());
+    }
+    
+    
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticTransactionalExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticTransactionalExtraAPITestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticTransactionalExtraAPITestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this base
+ * version using Optimistic locking with TRANSACTIONAL access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the 
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticTransactionalExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
+
+    private static EntityRegionAccessStrategy localAccessStrategy;
+    
+    /**
+     * Create a new PessimisticAccessStrategyExtraAPITestCase.
+     * 
+     * @param name
+     */
+    public PessimisticTransactionalExtraAPITestCase(String name) {
+        super(name);
+    }
+    
+    @Override
+    protected String getCacheConfigName() {
+        return "pessimistic-entity";
+    }
+    
+    @Override
+    protected EntityRegionAccessStrategy getEntityAccessStrategy() {
+        return localAccessStrategy;
+    }
+    
+    @Override
+    protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
+        localAccessStrategy = strategy;
+    }
+    
+    @Override
+    public void testCacheConfiguration() {
+        assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractEntityCacheFunctionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractEntityCacheFunctionalTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractEntityCacheFunctionalTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,103 @@
+package org.hibernate.test.cache.jbc2.functional;
+
+import java.util.Map;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.cache.ReadWriteCache;
+import org.hibernate.stat.SecondLevelCacheStatistics;
+import org.hibernate.stat.Statistics;
+
+/**
+ * Common requirement entity caching testing for each
+ * {@link org.hibernate.cache.RegionFactory} impl.
+ * 
+ * @author Steve Ebersole
+ */
+public abstract class AbstractEntityCacheFunctionalTestCase extends CacheTestCaseBase {
+
+    // note that a lot of the functionality here is intended to be used
+    // in creating specific tests for each CacheProvider that would extend
+    // from a base test case (this) for common requirement testing...
+
+    public AbstractEntityCacheFunctionalTestCase(String x) {
+        super(x);
+    }
+
+    @Override
+    protected boolean getUseQueryCache() {
+        return false;
+    }
+
+    public void testEmptySecondLevelCacheEntry() throws Exception {
+        getSessions().evictEntity(Item.class.getName());
+        Statistics stats = getSessions().getStatistics();
+        stats.clear();
+        SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics(Item.class.getName());
+        Map cacheEntries = statistics.getEntries();
+        assertEquals(0, cacheEntries.size());
+    }
+
+    public void testStaleWritesLeaveCacheConsistent() {
+        Session s = openSession();
+        Transaction txn = s.beginTransaction();
+        VersionedItem item = new VersionedItem();
+        item.setName("steve");
+        item.setDescription("steve's item");
+        s.save(item);
+        txn.commit();
+        s.close();
+
+        Long initialVersion = item.getVersion();
+
+        // manually revert the version property
+        item.setVersion(new Long(item.getVersion().longValue() - 1));
+
+        try {
+            s = openSession();
+            txn = s.beginTransaction();
+            s.update(item);
+            txn.commit();
+            s.close();
+            fail("expected stale write to fail");
+        } catch (Throwable expected) {
+            // expected behavior here
+            if (txn != null) {
+                try {
+                    txn.rollback();
+                } catch (Throwable ignore) {
+                }
+            }
+        } finally {
+            if (s != null && s.isOpen()) {
+                try {
+                    s.close();
+                } catch (Throwable ignore) {
+                }
+            }
+        }
+
+        // check the version value in the cache...
+        SecondLevelCacheStatistics slcs = sfi().getStatistics().getSecondLevelCacheStatistics(
+                VersionedItem.class.getName());
+
+        Object entry = slcs.getEntries().get(item.getId());
+        Long cachedVersionValue;
+        if (entry instanceof ReadWriteCache.Lock) {
+            // FIXME don't know what to test here
+            cachedVersionValue = new Long(((ReadWriteCache.Lock) entry).getUnlockTimestamp());
+        } else {
+            cachedVersionValue = (Long) ((Map) entry).get("_version");
+            assertEquals(initialVersion.longValue(), cachedVersionValue.longValue());
+        }
+
+        // cleanup
+        s = openSession();
+        txn = s.beginTransaction();
+        item = (VersionedItem) s.load(VersionedItem.class, item.getId());
+        s.delete(item);
+        txn.commit();
+        s.close();
+
+    }
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractQueryCacheFunctionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractQueryCacheFunctionalTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractQueryCacheFunctionalTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.functional;
+
+import java.util.Map;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.cache.ReadWriteCache;
+import org.hibernate.stat.SecondLevelCacheStatistics;
+
+/**
+ * A QueryCacheEnabledCacheProviderTestCase.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractQueryCacheFunctionalTestCase extends AbstractEntityCacheFunctionalTestCase {
+
+    /**
+     * Create a new QueryCacheEnabledCacheProviderTestCase.
+     * 
+     * @param x
+     */
+    public AbstractQueryCacheFunctionalTestCase(String x) {
+        super(x);
+    }
+
+    @Override
+    protected boolean getUseQueryCache() {
+        return true;
+    }
+
+    public void testQueryCacheInvalidation() {
+        Session s = openSession();
+        Transaction t = s.beginTransaction();
+        Item i = new Item();
+        i.setName("widget");
+        i.setDescription("A really top-quality, full-featured widget.");
+        s.persist(i);
+        t.commit();
+        s.close();
+
+        SecondLevelCacheStatistics slcs = s.getSessionFactory().getStatistics().getSecondLevelCacheStatistics(
+                Item.class.getName());
+
+        assertEquals(slcs.getPutCount(), 1);
+        assertEquals(slcs.getElementCountInMemory(), 1);
+        assertEquals(slcs.getEntries().size(), 1);
+
+        s = openSession();
+        t = s.beginTransaction();
+        i = (Item) s.get(Item.class, i.getId());
+
+        assertEquals(slcs.getHitCount(), 1);
+        assertEquals(slcs.getMissCount(), 0);
+
+        i.setDescription("A bog standard item");
+
+        t.commit();
+        s.close();
+
+        assertEquals(slcs.getPutCount(), 2);
+
+        Object entry = slcs.getEntries().get(i.getId());
+        Map map;
+        if (entry instanceof ReadWriteCache.Item) {
+            map = (Map) ((ReadWriteCache.Item) entry).getValue();
+        } else {
+            map = (Map) entry;
+        }
+        assertTrue(map.get("description").equals("A bog standard item"));
+        assertTrue(map.get("name").equals("widget"));
+
+        // cleanup
+        s = openSession();
+        t = s.beginTransaction();
+        s.delete(i);
+        t.commit();
+        s.close();
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractQueryCacheFunctionalTestCase.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/CacheTestCaseBase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/CacheTestCaseBase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/CacheTestCaseBase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,81 @@
+package org.hibernate.test.cache.jbc2.functional;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.test.tm.DummyConnectionProvider;
+import org.hibernate.test.tm.DummyTransactionManagerLookup;
+
+/**
+ * Provides common configuration setups for cache testing.
+ * 
+ * @author Brian Stansberry
+ */
+public abstract class CacheTestCaseBase extends FunctionalTestCase {
+
+    // note that a lot of the functionality here is intended to be used
+    // in creating specific tests for each CacheProvider that would extend
+    // from a base test case (this) for common requirement testing...
+
+    public CacheTestCaseBase(String x) {
+        super(x);
+    }
+
+    public String[] getMappings() {
+        return new String[] { "cache/jbc2/functional/Item.hbm.xml" };
+    }
+
+    public void configure(Configuration cfg) {
+        super.configure(cfg);
+
+        cfg.setProperty(Environment.CACHE_REGION_PREFIX, "test");
+        cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true");
+        cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
+        cfg.setProperty(Environment.USE_STRUCTURED_CACHE, "true");
+        cfg.setProperty(Environment.CACHE_REGION_FACTORY, getCacheRegionFactory().getName());
+
+        cfg.setProperty(Environment.USE_QUERY_CACHE, String.valueOf(getUseQueryCache()));
+        cfg.setProperty(Environment.CONNECTION_PROVIDER, DummyConnectionProvider.class.getName());
+        cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, DummyTransactionManagerLookup.class.getName());
+
+        configureCacheFactory(cfg);
+    }
+
+    public String getCacheConcurrencyStrategy() {
+        return "transactional";
+    }
+
+    /**
+     * The cache provider to be tested.
+     * 
+     * @return The cache provider.
+     */
+    protected void configureCacheFactory(Configuration cfg) {
+        if (getConfigResourceKey() != null) {
+            cfg.setProperty(getConfigResourceKey(), getConfigResourceLocation());
+        }
+    }
+
+    protected abstract Class<? extends RegionFactory> getCacheRegionFactory();
+
+    protected abstract boolean getUseQueryCache();
+
+    /**
+     * For provider-specific configuration, the name of the property key the
+     * provider expects.
+     * 
+     * @return The provider-specific config key.
+     */
+    protected String getConfigResourceKey() {
+        return Environment.CACHE_REGION_FACTORY;
+    }
+
+    /**
+     * For provider-specific configuration, the resource location of that config
+     * resource.
+     * 
+     * @return The config resource location.
+     */
+    protected abstract String getConfigResourceLocation();
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/CacheTestCaseBase.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.hbm.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.hbm.xml	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.hbm.xml	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC 
+	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping 
+	package="org.hibernate.test.cache.jbc2.functional">
+
+	<class name="Item" table="Items">
+		<id name="id">
+			<generator class="increment"/>
+		</id>
+		<property name="name" not-null="true"/>
+		<property name="description" not-null="true"/>
+	</class>
+
+	<class name="VersionedItem" table="VersionedItems">
+		<id name="id">
+			<generator class="increment"/>
+		</id>
+        <version name="version" type="long"/>
+        <property name="name" not-null="true"/>
+		<property name="description" not-null="true"/>
+	</class>
+
+</hibernate-mapping>


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.hbm.xml
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,35 @@
+//$Id: Item.java 5686 2005-02-12 07:27:32Z steveebersole $
+package org.hibernate.test.cache.jbc2.functional;
+
+/**
+ * @author Gavin King
+ */
+public class Item {
+    private Long id;
+    private String name;
+    private String description;
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/OptimisticJBossCacheTestDisabled.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/OptimisticJBossCacheTestDisabled.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/OptimisticJBossCacheTestDisabled.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,41 @@
+package org.hibernate.test.cache.jbc2.functional;
+
+import junit.framework.Test;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * FIXME Move to hibernate-testsuite project and rename class x- "Disabled"
+ * 
+ * @author Brian Stansberry
+ */
+public class OptimisticJBossCacheTestDisabled extends AbstractQueryCacheFunctionalTestCase {
+
+    // note that a lot of the fucntionality here is intended to be used
+    // in creating specific tests for each CacheProvider that would extend
+    // from a base test case (this) for common requirement testing...
+
+    public OptimisticJBossCacheTestDisabled(String x) {
+        super(x);
+    }
+
+    public static Test suite() {
+        return new FunctionalTestClassTestSuite(OptimisticJBossCacheTestDisabled.class);
+    }
+
+    protected Class<? extends RegionFactory> getCacheRegionFactory() {
+        return JBossCacheRegionFactory.class;
+    }
+
+    protected String getConfigResourceKey() {
+        return SharedCacheInstanceManager.CACHE_RESOURCE_PROP;
+    }
+
+    protected String getConfigResourceLocation() {
+        return "org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml";
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/OptimisticJBossCacheTestDisabled.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/PessimisticJBossCacheTestDisabled.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/PessimisticJBossCacheTestDisabled.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/PessimisticJBossCacheTestDisabled.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,41 @@
+package org.hibernate.test.cache.jbc2.functional;
+
+import junit.framework.Test;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * FIXME Move to hibernate-testsuite project and rename class x- "Disabled"
+ * 
+ * @author Brian Stansberry
+ */
+public class PessimisticJBossCacheTestDisabled extends AbstractQueryCacheFunctionalTestCase {
+
+    // note that a lot of the fucntionality here is intended to be used
+    // in creating specific tests for each CacheProvider that would extend
+    // from a base test case (this) for common requirement testing...
+
+    public PessimisticJBossCacheTestDisabled(String x) {
+        super(x);
+    }
+
+    public static Test suite() {
+        return new FunctionalTestClassTestSuite(PessimisticJBossCacheTestDisabled.class);
+    }
+
+    protected Class<? extends RegionFactory> getCacheRegionFactory() {
+        return JBossCacheRegionFactory.class;
+    }
+
+    protected String getConfigResourceKey() {
+        return SharedCacheInstanceManager.CACHE_RESOURCE_PROP;
+    }
+
+    protected String getConfigResourceLocation() {
+        return "org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml";
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/PessimisticJBossCacheTestDisabled.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/VersionedItem.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/VersionedItem.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/VersionedItem.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,16 @@
+package org.hibernate.test.cache.jbc2.functional;
+
+/**
+ * @author Steve Ebersole
+ */
+public class VersionedItem extends Item {
+    private Long version;
+
+    public Long getVersion() {
+        return version;
+    }
+
+    public void setVersion(Long version) {
+        this.version = version;
+    }
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/VersionedItem.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!--                                                                       -->
+<!--  Sample JBoss Cache Service Configuration                               -->
+<!--  Recommended for use as Hibernate's 2nd Level Cache                   -->
+<!--  For use with JBossCache >= 2.0.0 ONLY!!!                             -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+
+<server>
+
+    <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
+
+
+    <!-- ==================================================================== -->
+    <!-- Defines TreeCache configuration                                      -->
+    <!-- ==================================================================== -->
+
+    <mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
+        name="jboss.cache:service=TreeCache">
+
+        <depends>jboss:service=Naming</depends>
+        <depends>jboss:service=TransactionManager</depends>
+
+        <!--
+            TransactionManager configuration not required for Hibernate!
+            Hibernate will plug in its own transaction manager integration.
+        -->
+
+
+        <!--
+            Node locking scheme:
+                OPTIMISTIC
+                PESSIMISTIC (default)
+        -->
+        <attribute name="NodeLockingScheme">OPTIMISTIC</attribute>
+
+        <!--
+            Note that this attribute is IGNORED if your NodeLockingScheme above is OPTIMISTIC.
+
+            Isolation level : SERIALIZABLE
+                              REPEATABLE_READ (default)
+                              READ_COMMITTED
+                              READ_UNCOMMITTED
+                              NONE
+        -->
+        <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+        <!--
+             Valid modes are LOCAL
+                             REPL_ASYNC
+                             REPL_SYNC
+                             INVALIDATION_ASYNC
+                             INVALIDATION_SYNC
+
+             INVALIDATION_ASYNC is highly recommended as the mode for use
+             with clustered second-level caches.
+        -->
+        <attribute name="CacheMode">REPL_SYNC</attribute>
+
+        <!-- Name of cluster. Needs to be the same for all clusters, in order
+             to find each other
+        -->
+        <attribute name="ClusterName">TreeCache-Cluster</attribute>
+
+        <attribute name="ClusterConfig">
+            <config>
+                <!-- UDP: if you have a multihomed machine,
+                set the bind_addr attribute to the appropriate NIC IP address -->
+                <!-- UDP: On Windows machines, because of the media sense feature
+                 being broken with multicast (even after disabling media sense)
+                 set the loopback attribute to true -->
+                <UDP mcast_addr="228.1.2.3" mcast_port="48866"
+                    ip_ttl="64" ip_mcast="true"
+                    mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
+                    ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
+                    loopback="false"/>
+                <PING timeout="2000" num_initial_members="3"/>
+                <MERGE2 min_interval="10000" max_interval="20000"/>
+                <FD shun="true"/>
+                <FD_SOCK/>
+                <VERIFY_SUSPECT timeout="1500"/>
+                <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"
+                    max_xmit_size="8192"/>
+                <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"/>
+                <pbcast.STABLE desired_avg_gossip="20000"/>
+                <FRAG frag_size="8192"/>
+                <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+                    shun="true" print_local_addr="true"/>
+                <pbcast.STATE_TRANSFER/>
+            </config>
+        </attribute>
+
+        <!--
+         Whether or not to fetch state on joining a cluster
+         NOTE this used to be called FetchStateOnStartup and has been renamed to be more descriptive.
+        -->
+        <attribute name="FetchInMemoryState">false</attribute>
+
+        <!--
+            Number of milliseconds to wait until all responses for a
+            synchronous call have been received.
+        -->
+        <attribute name="SyncReplTimeout">20000</attribute>
+
+        <!-- Max number of milliseconds to wait for a lock acquisition -->
+        <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+       <!--
+          Indicate whether to use marshalling or not. Set this to true if you are running under a scoped
+          class loader, e.g., inside an application server. Default is "false".
+       -->
+       <attribute name="UseRegionBasedMarshalling">true</attribute>
+       <!-- Must match the value of "useRegionBasedMarshalling" -->
+       <attribute name="InactiveOnStartup">true</attribute>
+
+      <!--  Specific eviction policy configurations. This is LRU -->
+      <attribute name="EvictionPolicyConfig">
+        <config>
+          <attribute name="wakeUpIntervalSeconds">5</attribute>
+          <!-- Name of the DEFAULT eviction policy class. -->
+          <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+          <!--  Cache wide default -->
+          <region name="/_default_">
+            <attribute name="maxNodes">5000</attribute>
+            <attribute name="timeToLiveSeconds">1000</attribute>
+          </region>
+          <!--  Don't ever evict modification timestamps -->
+          <region name="/TS">
+            <attribute name="maxNodes">0</attribute>
+            <attribute name="timeToLiveSeconds">0</attribute>
+          </region>
+        </config>
+     </attribute>
+
+    </mbean>
+</server>


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!--                                                                       -->
+<!--  Sample TreeCache Service Configuration                               -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+
+<server>
+
+    <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
+
+
+    <!-- ==================================================================== -->
+    <!-- Defines TreeCache configuration                                      -->
+    <!-- ==================================================================== -->
+
+    <mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
+        name="jboss.cache:service=TreeCache">
+
+        <depends>jboss:service=Naming</depends>
+        <depends>jboss:service=TransactionManager</depends>
+
+        <!--
+            TransactionManager configuration not required for Hibernate!
+            Hibernate will plug in its own transaction manager integration.
+        -->
+
+        <!--
+            Node isolation level : SERIALIZABLE
+                                 REPEATABLE_READ (default)
+                                 READ_COMMITTED
+                                 READ_UNCOMMITTED
+                                 NONE
+        -->
+        <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+        <!--
+             Valid modes are LOCAL
+                             REPL_ASYNC
+                             REPL_SYNC
+        -->
+        <attribute name="CacheMode">LOCAL</attribute>
+
+        <!-- Name of cluster. Needs to be the same for all clusters, in order
+             to find each other
+        -->
+        <attribute name="ClusterName">TreeCache-Cluster</attribute>
+
+        <attribute name="ClusterConfig">
+            <config>
+                <!-- UDP: if you have a multihomed machine,
+                set the bind_addr attribute to the appropriate NIC IP address -->
+                <!-- UDP: On Windows machines, because of the media sense feature
+                 being broken with multicast (even after disabling media sense)
+                 set the loopback attribute to true -->
+                <UDP mcast_addr="228.1.2.3" mcast_port="45566"
+                    ip_ttl="64" ip_mcast="true"
+                    mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
+                    ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
+                    loopback="false"/>
+                <PING timeout="2000" num_initial_members="3"/>
+                <MERGE2 min_interval="10000" max_interval="20000"/>
+                <FD shun="true"/>
+                <VERIFY_SUSPECT timeout="1500"/>
+                <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"/>
+                <pbcast.STABLE desired_avg_gossip="20000"/>
+                <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"/>
+                <FRAG frag_size="8192"/>
+                <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+                    shun="true" print_local_addr="true"/>
+                <pbcast.STATE_TRANSFER/>
+            </config>
+        </attribute>
+      
+      <!-- Must be true if any entity deployment uses a scoped classloader -->
+      <attribute name="UseRegionBasedMarshalling">true</attribute>
+      <!-- Must match the value of "useRegionBasedMarshalling" -->
+      <attribute name="InactiveOnStartup">true</attribute>
+
+        <!--
+            The max amount of time (in milliseconds) we wait until the
+            initial state (ie. the contents of the cache) are retrieved from
+            existing members in a clustered environment
+        -->
+        <attribute name="StateRetrievalTimeout">20000</attribute>
+
+        <!--
+            Number of milliseconds to wait until all responses for a
+            synchronous call have been received.
+        -->
+        <attribute name="SyncReplTimeout">20000</attribute>
+
+        <!-- Max number of milliseconds to wait for a lock acquisition -->
+        <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+      <!--  Specific eviction policy configurations. This is LRU -->
+      <attribute name="EvictionPolicyConfig">
+        <config>
+          <attribute name="wakeUpIntervalSeconds">5</attribute>
+          <!-- Name of the DEFAULT eviction policy class. -->
+          <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+          <!--  Cache wide default -->
+          <region name="/_default_">
+            <attribute name="maxNodes">5000</attribute>
+            <attribute name="timeToLiveSeconds">1000</attribute>
+          </region>
+          <!--  Don't ever evict modification timestamps -->
+          <region name="/TS">
+            <attribute name="maxNodes">0</attribute>
+            <attribute name="timeToLiveSeconds">0</attribute>
+          </region>
+        </config>
+     </attribute>
+  </mbean>
+
+
+</server>


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/query/QueryRegionImplTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/query/QueryRegionImplTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/query/QueryRegionImplTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.query;
+
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractRegionImplTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeVisited;
+import org.jboss.cache.notifications.event.NodeVisitedEvent;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Tests of QueryResultRegionImpl.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class QueryRegionImplTestCase extends AbstractRegionImplTestCase {
+    
+    private static final String KEY = "Key";
+    private static final String VALUE1 = "value1";
+    private static final String VALUE2 = "value2";
+    
+    /**
+     * Create a new EntityRegionImplTestCase.
+     * 
+     * @param name
+     */
+    public QueryRegionImplTestCase(String name) {
+        super(name);
+    } 
+
+    @Override
+    protected Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
+        return regionFactory.buildQueryResultsRegion(regionName, properties);
+    }
+
+    @Override
+    protected Cache getJBossCache(JBossCacheRegionFactory regionFactory) {
+        CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
+        return mgr.getQueryCacheInstance();
+    }
+
+    @Override
+    protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+        return Fqn.fromString(BasicRegionAdapter.escapeRegionName(regionName, regionPrefix));
+    }
+        
+    public void testPutDoesNotBlockGetOptimistic() throws Exception {
+        putDoesNotBlockGetTest("optimistic-shared");
+    }
+        
+    public void testPutDoesNotBlockGetPessimistic() throws Exception {
+        putDoesNotBlockGetTest("pessimistic-shared");
+    }
+    
+    private void putDoesNotBlockGetTest(String configName) throws Exception {
+        
+        Configuration cfg = CacheTestUtil.buildConfiguration("test", MultiplexedJBossCacheRegionFactory.class, false, true);
+        cfg.setProperty(MultiplexingCacheInstanceManager.QUERY_CACHE_RESOURCE_PROP, configName);
+        // Use the local-query config for timestamps as well to save time
+        cfg.setProperty(MultiplexingCacheInstanceManager.TIMESTAMP_CACHE_RESOURCE_PROP, configName);
+        JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+        
+        final QueryResultsRegion region = regionFactory.buildQueryResultsRegion("test/com.foo.test", cfg.getProperties());
+        
+        region.put(KEY, VALUE1);
+        assertEquals(VALUE1, region.get(KEY));
+
+        final CountDownLatch readerLatch = new CountDownLatch(1);
+        final CountDownLatch writerLatch = new CountDownLatch(1);
+        final CountDownLatch completionLatch = new CountDownLatch(1);
+        final ExceptionHolder holder = new ExceptionHolder();
+        
+        Thread reader = new Thread() {
+          
+            public void run() {
+                try {
+                    BatchModeTransactionManager.getInstance().begin();
+                    assertTrue(VALUE2.equals(region.get(KEY)) == false);
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (AssertionFailedError e) {
+                    holder.a1 = e;
+                    rollback();
+                }
+                catch (Exception e) {
+                    holder.e1 = e;
+                    rollback();
+                }
+                finally {
+                    readerLatch.countDown();
+                }
+            }
+        };
+        
+        Thread writer = new Thread() {
+          
+            public void run() {
+                try {                    
+                    BatchModeTransactionManager.getInstance().begin();
+                    region.put(KEY, VALUE2);
+                    writerLatch.await();
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    holder.e2 = e;
+                    rollback();
+                }
+                finally {
+                    completionLatch.countDown();
+                }
+            }
+        };
+        
+        reader.setDaemon(true);
+        writer.setDaemon(true);
+        
+        writer.start();        
+        assertFalse("Writer is blocking", completionLatch.await(100, TimeUnit.MILLISECONDS));
+        
+        // Start the reader
+        reader.start();
+        assertTrue("Reader finished promptly", readerLatch.await(100, TimeUnit.MILLISECONDS));
+
+        writerLatch.countDown();
+        assertTrue("Reader finished promptly", completionLatch.await(100, TimeUnit.MILLISECONDS));
+                
+        assertEquals(VALUE2, region.get(KEY));            
+        
+        if (holder.a1 != null)
+            throw holder.a1;
+        else if (holder.a2 != null)
+            throw holder.a2;
+        
+        assertEquals("writer saw no exceptions", null, holder.e1);
+        assertEquals("reader saw no exceptions", null, holder.e2);
+    }
+    
+    public void testGetDoesNotBlockPutOptimistic() throws Exception {
+        getDoesNotBlockPutTest("optimistic-shared");
+    }
+    
+    public void testGetDoesNotBlockPutPessimistic() throws Exception {
+        getDoesNotBlockPutTest("pessimistic-shared");
+    }
+    
+    private void getDoesNotBlockPutTest(String configName) throws Exception {
+        
+        Configuration cfg = CacheTestUtil.buildConfiguration("test", MultiplexedJBossCacheRegionFactory.class, false, true);
+        cfg.setProperty(MultiplexingCacheInstanceManager.QUERY_CACHE_RESOURCE_PROP, configName);
+        // Use the local-query config for timestamps as well to save time
+        cfg.setProperty(MultiplexingCacheInstanceManager.TIMESTAMP_CACHE_RESOURCE_PROP, configName);
+        JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+        
+        final QueryResultsRegion region = regionFactory.buildQueryResultsRegion("test/com.foo.test", cfg.getProperties());
+        
+        region.put(KEY, VALUE1);
+        assertEquals(VALUE1, region.get(KEY));
+        
+        final Fqn rootFqn = getRegionFqn("test/com.foo.test", "test");
+        final Cache jbc = getJBossCache(regionFactory);
+
+        final CountDownLatch blockerLatch = new CountDownLatch(1);
+        final CountDownLatch writerLatch = new CountDownLatch(1);
+        final CountDownLatch completionLatch = new CountDownLatch(1);
+        final ExceptionHolder holder = new ExceptionHolder();
+        
+        Thread blocker = new Thread() {
+          
+            public void run() {
+                Fqn toBlock = new Fqn(rootFqn, KEY);
+                GetBlocker blocker = new GetBlocker(blockerLatch,toBlock);
+                try {
+                    jbc.addCacheListener(blocker);
+                    
+                    BatchModeTransactionManager.getInstance().begin();
+                    region.get(KEY);
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    holder.e1 = e;
+                    rollback();
+                }
+                finally {
+                    jbc.removeCacheListener(blocker);
+                }
+            }
+        };
+        
+        Thread writer = new Thread() {
+          
+            public void run() {
+                try {
+                    writerLatch.await();
+                    
+                    BatchModeTransactionManager.getInstance().begin();
+                    region.put(KEY, VALUE2);
+                    BatchModeTransactionManager.getInstance().commit();
+                }
+                catch (Exception e) {
+                    holder.e2 = e;
+                    rollback();
+                }
+                finally {
+                    completionLatch.countDown();
+                }
+            }
+        };
+        
+        blocker.setDaemon(true);
+        writer.setDaemon(true);
+        
+        boolean unblocked = false;
+        try {
+            blocker.start();
+            writer.start();
+            
+            assertFalse("Blocker is blocking", completionLatch.await(100, TimeUnit.MILLISECONDS));
+            // Start the writer
+            writerLatch.countDown();
+            assertTrue("Writer finished promptly", completionLatch.await(100, TimeUnit.MILLISECONDS));
+            
+            blockerLatch.countDown();
+            unblocked = true;
+            
+            if ("PESSIMISTIC".equals(jbc.getConfiguration().getNodeLockingSchemeString())) {
+                assertEquals(VALUE1, region.get(KEY));
+            }
+            else {
+                assertEquals(VALUE2, region.get(KEY));
+            }            
+            
+            if (holder.a1 != null)
+                throw holder.a1;
+            else if (holder.a2 != null)
+                throw holder.a2;
+            
+            assertEquals("blocker saw no exceptions", null, holder.e1);
+            assertEquals("writer saw no exceptions", null, holder.e2);
+        }
+        finally {
+            if (!unblocked)
+                blockerLatch.countDown();
+        }
+    }
+    
+    private void rollback() {
+        try {
+            BatchModeTransactionManager.getInstance().rollback();
+        }
+        catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+        
+    }
+    
+    @CacheListener
+    public class GetBlocker {
+        
+        private CountDownLatch latch;
+        private Fqn fqn;
+        
+        GetBlocker(CountDownLatch latch, Fqn fqn) {
+            this.latch = latch;
+            this.fqn = fqn;
+        }
+        
+        @NodeVisited
+        public void nodeVisisted(NodeVisitedEvent event) {
+            
+            if (event.isPre() && event.getFqn().equals(fqn)) {
+                try {
+                    latch.await();
+                }
+                catch (InterruptedException e) {
+                    log.error("Interrupted waiting for latch", e);
+                }
+            }
+        }
+    }
+    
+    private class ExceptionHolder {
+        Exception e1;
+        Exception e2;
+        AssertionFailedError a1;
+        AssertionFailedError a2;
+    }
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/timestamp/TimestampsRegionImplTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/timestamp/TimestampsRegionImplTestCase.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/timestamp/TimestampsRegionImplTestCase.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.timestamp;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.timestamp.TimestampsRegionImpl;
+import org.hibernate.test.cache.jbc2.AbstractRegionImplTestCase;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+
+/**
+ * Tests of TimestampsRegionImpl.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class TimestampsRegionImplTestCase extends AbstractRegionImplTestCase {
+    
+    /**
+     * Create a new EntityRegionImplTestCase.
+     * 
+     * @param name
+     */
+    public TimestampsRegionImplTestCase(String name) {
+        super(name);
+    }
+
+    @Override
+    protected Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
+        return regionFactory.buildTimestampsRegion(regionName, properties);
+    }
+
+    @Override
+    protected Cache getJBossCache(JBossCacheRegionFactory regionFactory) {
+        CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
+        return mgr.getTimestampsCacheInstance();
+    }
+
+    @Override
+    protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+        return BasicRegionAdapter.getTypeFirstRegionFqn(regionName, regionPrefix, TimestampsRegionImpl.TYPE);
+    }
+    
+    
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyConnectionProvider.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyConnectionProvider.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyConnectionProvider.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,52 @@
+//$Id: DummyConnectionProvider.java 6501 2005-04-24 00:18:28Z oneovthafew $
+package org.hibernate.test.tm;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.hibernate.HibernateException;
+import org.hibernate.connection.ConnectionProvider;
+import org.hibernate.connection.ConnectionProviderFactory;
+
+/**
+ * FIXME Get this class into hibernate-testing so we don't have to maintain
+ * a copy here. Can't use the hibernate-testsuite version as that would
+ * lead to circular project dependencies.
+ * 
+ * @author Gavin King
+ */
+public class DummyConnectionProvider implements ConnectionProvider {
+
+    ConnectionProvider cp;
+    boolean isTransaction;
+
+    public void configure(Properties props) throws HibernateException {
+        cp = ConnectionProviderFactory.newConnectionProvider();
+    }
+
+    public Connection getConnection() throws SQLException {
+        DummyTransactionManager dtm = DummyTransactionManager.INSTANCE;
+        if (dtm != null && dtm.getCurrent() != null && dtm.getCurrent().getConnection() != null) {
+            isTransaction = true;
+            return dtm.getCurrent().getConnection();
+        } else {
+            isTransaction = false;
+            return cp.getConnection();
+        }
+    }
+
+    public void closeConnection(Connection conn) throws SQLException {
+        if (!isTransaction)
+            conn.close();
+    }
+
+    public void close() throws HibernateException {
+
+    }
+
+    public boolean supportsAggressiveRelease() {
+        return true;
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyConnectionProvider.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransaction.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransaction.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransaction.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,143 @@
+//$Id: DummyTransaction.java 8411 2005-10-14 23:29:04Z maxcsaucdk $
+package org.hibernate.test.tm;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+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;
+
+/**
+ * FIXME Get this class into hibernate-testing so we don't have to maintain
+ * a copy here. Can't use the hibernate-testsuite version as that would
+ * lead to circular project dependencies.
+ * 
+ * @author Gavin King
+ */
+public class DummyTransaction implements Transaction {
+
+    int status;
+    private Connection connection;
+    List synchronizations = new ArrayList();
+    private DummyTransactionManager transactionManager;
+
+    DummyTransaction(DummyTransactionManager transactionManager) {
+        status = Status.STATUS_NO_TRANSACTION;
+        this.transactionManager = transactionManager;
+    }
+
+    public void begin() throws SystemException {
+        try {
+            connection = transactionManager.connections.getConnection();
+        } catch (SQLException sqle) {
+
+            sqle.printStackTrace();
+            throw new SystemException(sqle.toString());
+        }
+        status = Status.STATUS_ACTIVE;
+    }
+
+    public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+            SecurityException, IllegalStateException, SystemException {
+
+        if (status == Status.STATUS_MARKED_ROLLBACK) {
+            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;
+
+            try {
+                connection.commit();
+                connection.close();
+            } catch (SQLException sqle) {
+                status = Status.STATUS_UNKNOWN;
+                throw new SystemException();
+            }
+
+            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;
+            transactionManager.endCurrent(this);
+        }
+
+    }
+
+    public boolean delistResource(XAResource arg0, int arg1) throws IllegalStateException, SystemException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public boolean enlistResource(XAResource arg0) throws RollbackException, IllegalStateException, SystemException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    public int getStatus() throws SystemException {
+        return status;
+    }
+
+    public void registerSynchronization(Synchronization sync) throws RollbackException, IllegalStateException,
+            SystemException {
+        synchronizations.add(sync);
+    }
+
+    public void rollback() throws IllegalStateException, SystemException {
+
+        status = Status.STATUS_ROLLING_BACK;
+
+        // Synch.beforeCompletion() should *not* be called for rollbacks
+        // for ( int i=0; i<synchronizations.size(); i++ ) {
+        // Synchronization s = (Synchronization) synchronizations.get(i);
+        // s.beforeCompletion();
+        // }
+
+        status = Status.STATUS_ROLLEDBACK;
+
+        try {
+            connection.rollback();
+            connection.close();
+        } catch (SQLException sqle) {
+            status = Status.STATUS_UNKNOWN;
+            throw new SystemException();
+        }
+
+        for (int i = 0; i < synchronizations.size(); i++) {
+            Synchronization s = (Synchronization) synchronizations.get(i);
+            s.afterCompletion(status);
+        }
+
+        // status = Status.STATUS_NO_TRANSACTION;
+        transactionManager.endCurrent(this);
+    }
+
+    public void setRollbackOnly() throws IllegalStateException, SystemException {
+        status = Status.STATUS_MARKED_ROLLBACK;
+    }
+
+    void setConnection(Connection connection) {
+        this.connection = connection;
+    }
+
+    public Connection getConnection() {
+        return connection;
+    }
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransaction.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManager.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManager.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,85 @@
+//$Id: DummyTransactionManager.java 7003 2005-06-03 16:09:59Z steveebersole $
+package org.hibernate.test.tm;
+
+import java.util.Properties;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.hibernate.connection.ConnectionProvider;
+import org.hibernate.connection.ConnectionProviderFactory;
+
+/**
+ * FIXME Get this class into hibernate-testing so we don't have to maintain
+ * a copy here. Can't use the hibernate-testsuite version as that would
+ * lead to circular project dependencies.
+ * 
+ * @author Gavin King
+ */
+public class DummyTransactionManager implements TransactionManager {
+
+    public static DummyTransactionManager INSTANCE;
+
+    private DummyTransaction current;
+    ConnectionProvider connections;
+
+    public DummyTransactionManager(Properties props) {
+        connections = ConnectionProviderFactory.newConnectionProvider();
+    }
+
+    public void begin() throws NotSupportedException, SystemException {
+        current = new DummyTransaction(this);
+        current.begin();
+    }
+
+    public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+            SecurityException, IllegalStateException, SystemException {
+        current.commit();
+    }
+
+    public int getStatus() throws SystemException {
+        return current.getStatus();
+    }
+
+    public Transaction getTransaction() throws SystemException {
+        return current;
+    }
+
+    public void resume(Transaction tx) throws InvalidTransactionException, IllegalStateException, SystemException {
+        current = (DummyTransaction) tx;
+    }
+
+    public void rollback() throws IllegalStateException, SecurityException, SystemException {
+        current.rollback();
+
+    }
+
+    public void setRollbackOnly() throws IllegalStateException, SystemException {
+        current.setRollbackOnly();
+    }
+
+    public void setTransactionTimeout(int t) throws SystemException {
+    }
+
+    public Transaction suspend() throws SystemException {
+        Transaction result = current;
+        current = null;
+        return result;
+    }
+
+    public DummyTransaction getCurrent() {
+        return current;
+    }
+
+    void endCurrent(DummyTransaction tx) {
+        if (current == tx)
+            current = null;
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManager.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManagerLookup.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManagerLookup.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManagerLookup.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,31 @@
+//$Id: DummyTransactionManagerLookup.java 5693 2005-02-13 01:59:07Z oneovthafew $
+package org.hibernate.test.tm;
+
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.HibernateException;
+import org.hibernate.transaction.TransactionManagerLookup;
+
+/**
+ * FIXME Get this class into hibernate-testing so we don't have to maintain
+ * a copy here. Can't use the hibernate-testsuite version as that would
+ * lead to circular project dependencies.
+ * 
+ * @author Gavin King
+ */
+public class DummyTransactionManagerLookup implements TransactionManagerLookup {
+
+    public TransactionManager getTransactionManager(Properties props) throws HibernateException {
+        if (DummyTransactionManager.INSTANCE == null) {
+            DummyTransactionManager.INSTANCE = new DummyTransactionManager(props);
+        }
+        return DummyTransactionManager.INSTANCE;
+    }
+
+    public String getUserTransactionName() {
+        throw new UnsupportedOperationException();
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManagerLookup.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/BatchModeTransactionManagerLookup.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/BatchModeTransactionManagerLookup.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/BatchModeTransactionManagerLookup.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,34 @@
+//$Id: DummyTransactionManagerLookup.java 5693 2005-02-13 01:59:07Z oneovthafew $
+package org.hibernate.test.tm.jbc2;
+
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.HibernateException;
+import org.hibernate.transaction.TransactionManagerLookup;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Uses the JBoss Cache BatchModeTransactionManager. Should not be used in
+ * any tests that simulate usage of database connections.
+ * 
+ * @author Brian Stansberry
+ */
+public class BatchModeTransactionManagerLookup
+    implements TransactionManagerLookup {
+
+    public TransactionManager getTransactionManager(Properties props) throws HibernateException {
+        try {
+            return BatchModeTransactionManager.getInstance();
+        }
+        catch (Exception e) {
+            throw new HibernateException("Failed getting BatchModeTransactionManager", e);
+        }
+    }
+
+    public String getUserTransactionName() {
+        throw new UnsupportedOperationException();
+    }
+
+}


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/BatchModeTransactionManagerLookup.java
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestSupport.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestSupport.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestSupport.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.util;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.hibernate.cache.RegionFactory;
+import org.jboss.cache.Cache;
+
+/**
+ * Support class for tracking and cleaning up objects used in tests.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class CacheTestSupport {
+    
+    private Set<Cache> caches = new HashSet();
+    private Set<RegionFactory> factories = new HashSet();
+    private Exception exception;
+ 
+    public void registerCache(Cache cache) {
+        caches.add(cache);
+    }
+    
+    public void registerFactory(RegionFactory factory) {
+        factories.add(factory);
+    }
+ 
+    public void unregisterCache(Cache cache) {
+        caches.remove(cache);
+    }
+    
+    public void unregisterFactory(RegionFactory factory) {
+        factories.remove(factory);
+    }
+    
+    public void setUp() throws Exception {        
+        cleanUp();
+        throwStoredException();
+    }
+
+    public void tearDown() throws Exception {       
+        cleanUp();
+        throwStoredException();
+    }
+
+    private void cleanUp() {
+        for (Iterator it = factories.iterator(); it.hasNext(); ) {
+            try {
+                ((RegionFactory) it.next()).stop();
+            }
+            catch (Exception e) {
+                storeException(e);
+            }
+            finally {
+                it.remove();
+            }
+        }        
+        factories.clear();
+        
+        for (Iterator it = caches.iterator(); it.hasNext(); ) {
+            try {
+                Cache cache = (Cache) it.next();
+                cache.stop();
+                cache.destroy();
+            }
+            catch (Exception e) {
+                storeException(e);
+            }
+            finally {
+                it.remove();
+            }
+        }        
+        caches.clear();
+    }
+    
+    private void storeException(Exception e) {
+        if (this.exception == null) {
+            this.exception = e;
+        }
+    }
+    
+    private void throwStoredException() throws Exception {
+        if (exception != null) {
+            Exception toThrow = exception;
+            exception = null;
+            throw toThrow;
+        }
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestUtil.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestUtil.java	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestUtil.java	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * 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, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.util;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Settings;
+import org.hibernate.test.tm.jbc2.BatchModeTransactionManagerLookup;
+
+/**
+ * Utilities for cache testing.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class CacheTestUtil {
+
+    public static String LOCAL_OPTIMISIC_CACHE;
+    public static String LOCAL_PESSIMISTIC_CACHE;
+    
+    static {
+        String pkg = CacheTestUtil.class.getPackage().getName().replace('.', '/');
+        LOCAL_OPTIMISIC_CACHE = pkg + "/optimistic-local-cache.xml";
+        LOCAL_PESSIMISTIC_CACHE = pkg + "/pessimistic-local-cache.xml";
+    }
+    
+    public static Configuration buildConfiguration(String regionPrefix, Class regionFactory, boolean use2ndLevel, boolean useQueries) {
+        
+        Configuration cfg = new Configuration();
+        cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
+        cfg.setProperty(Environment.USE_STRUCTURED_CACHE, "true");
+//        cfg.setProperty(Environment.CONNECTION_PROVIDER, DummyConnectionProvider.class.getName());
+        cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, BatchModeTransactionManagerLookup.class.getName());
+
+        cfg.setProperty(Environment.CACHE_REGION_FACTORY, regionFactory.getName());
+        cfg.setProperty(Environment.CACHE_REGION_PREFIX, regionPrefix);
+        cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, String.valueOf(use2ndLevel));
+        cfg.setProperty(Environment.USE_QUERY_CACHE, String.valueOf(useQueries));
+        
+        return cfg;
+    }
+    
+    public static Configuration buildLocalOnlyConfiguration(String regionPrefix, boolean optimistic, boolean use2ndLevel, boolean useQueries) {
+        Configuration cfg = buildConfiguration(regionPrefix, SharedJBossCacheRegionFactory.class, use2ndLevel, useQueries);
+        
+        String resource = CacheTestUtil.class.getPackage().getName().replace('.', '/') + "/";
+        resource += optimistic ? "optimistic" : "pessimistic";
+        resource += "-local-cache.xml";
+        
+        cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, resource);
+        
+        return cfg;
+    }
+    
+    public static JBossCacheRegionFactory startRegionFactory(Configuration cfg) 
+            throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+        
+        Settings settings = cfg.buildSettings();
+        Properties properties = cfg.getProperties();
+        
+        String factoryType = cfg.getProperty(Environment.CACHE_REGION_FACTORY);
+        Class factoryClass = Thread.currentThread().getContextClassLoader().loadClass(factoryType);
+        JBossCacheRegionFactory regionFactory = (JBossCacheRegionFactory) factoryClass.newInstance();
+        
+        regionFactory.start(settings, properties);
+        
+        return regionFactory;        
+    }
+    
+    public static JBossCacheRegionFactory startRegionFactory(Configuration cfg, CacheTestSupport testSupport) 
+            throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+    
+        JBossCacheRegionFactory factory = startRegionFactory(cfg);
+        testSupport.registerFactory(factory);
+        return factory;
+    }
+    
+    public static void stopRegionFactory(JBossCacheRegionFactory factory, CacheTestSupport testSupport) {
+    
+        factory.stop();
+        testSupport.unregisterFactory(factory);
+    }
+    
+    /**
+     * Prevent instantiation. 
+     */
+    private CacheTestUtil() {        
+    }
+
+}

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/optimistic-local-cache.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/optimistic-local-cache.xml	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/optimistic-local-cache.xml	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!--                                                                       -->
+<!--  Sample JBoss Cache Service Configuration                               -->
+<!--  Recommended for use as Hibernate's 2nd Level Cache                   -->
+<!--  For use with JBossCache >= 2.0.0 ONLY!!!                             -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+
+<server>
+
+    <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
+
+
+    <!-- ==================================================================== -->
+    <!-- Defines TreeCache configuration                                      -->
+    <!-- ==================================================================== -->
+
+    <mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
+        name="jboss.cache:service=TreeCache">
+
+        <depends>jboss:service=Naming</depends>
+        <depends>jboss:service=TransactionManager</depends>
+
+        <!--
+            TransactionManager configuration not required for Hibernate!
+            Hibernate will plug in its own transaction manager integration.
+        -->
+
+
+        <!--
+            Node locking scheme:
+                OPTIMISTIC
+                PESSIMISTIC (default)
+        -->
+        <attribute name="NodeLockingScheme">OPTIMISTIC</attribute>
+
+        <!--
+            Note that this attribute is IGNORED if your NodeLockingScheme above is OPTIMISTIC.
+
+            Isolation level : SERIALIZABLE
+                              REPEATABLE_READ (default)
+                              READ_COMMITTED
+                              READ_UNCOMMITTED
+                              NONE
+        -->
+        <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+        <!--
+             Valid modes are LOCAL
+                             REPL_ASYNC
+                             REPL_SYNC
+                             INVALIDATION_ASYNC
+                             INVALIDATION_SYNC
+
+             INVALIDATION_ASYNC is highly recommended as the mode for use
+             with clustered second-level caches.
+        -->
+        <attribute name="CacheMode">REPL_SYNC</attribute>
+
+        <!-- Name of cluster. Needs to be the same for all clusters, in order
+             to find each other
+        -->
+        <attribute name="ClusterName">TreeCache-Cluster</attribute>
+
+        <attribute name="ClusterConfig">
+            <config>
+                <!-- UDP: if you have a multihomed machine,
+                set the bind_addr attribute to the appropriate NIC IP address -->
+                <!-- UDP: On Windows machines, because of the media sense feature
+                 being broken with multicast (even after disabling media sense)
+                 set the loopback attribute to true -->
+                <UDP mcast_addr="228.1.2.3" mcast_port="48866"
+                    ip_ttl="64" ip_mcast="true"
+                    mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
+                    ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
+                    loopback="false"/>
+                <PING timeout="2000" num_initial_members="3"/>
+                <MERGE2 min_interval="10000" max_interval="20000"/>
+                <FD shun="true"/>
+                <FD_SOCK/>
+                <VERIFY_SUSPECT timeout="1500"/>
+                <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"
+                    max_xmit_size="8192"/>
+                <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"/>
+                <pbcast.STABLE desired_avg_gossip="20000"/>
+                <FRAG frag_size="8192"/>
+                <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+                    shun="true" print_local_addr="true"/>
+                <pbcast.STATE_TRANSFER/>
+            </config>
+        </attribute>
+
+        <!--
+         Whether or not to fetch state on joining a cluster
+         NOTE this used to be called FetchStateOnStartup and has been renamed to be more descriptive.
+        -->
+        <attribute name="FetchInMemoryState">false</attribute>
+
+        <!--
+            Number of milliseconds to wait until all responses for a
+            synchronous call have been received.
+        -->
+        <attribute name="SyncReplTimeout">20000</attribute>
+
+        <!-- Max number of milliseconds to wait for a lock acquisition -->
+        <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+       <!--
+          Indicate whether to use marshalling or not. Set this to true if you are running under a scoped
+          class loader, e.g., inside an application server. Default is "false".
+       -->
+       <attribute name="UseRegionBasedMarshalling">true</attribute>
+       <!-- Must match the value of "useRegionBasedMarshalling" -->
+       <attribute name="InactiveOnStartup">true</attribute>
+
+      <!--  Specific eviction policy configurations. This is LRU -->
+      <attribute name="EvictionPolicyConfig">
+        <config>
+          <attribute name="wakeUpIntervalSeconds">5</attribute>
+          <!-- Name of the DEFAULT eviction policy class. -->
+          <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+          <!--  Cache wide default -->
+          <region name="/_default_">
+            <attribute name="maxNodes">5000</attribute>
+            <attribute name="timeToLiveSeconds">1000</attribute>
+          </region>
+          <!--  Don't ever evict modification timestamps -->
+          <region name="/TS">
+            <attribute name="maxNodes">0</attribute>
+            <attribute name="timeToLiveSeconds">0</attribute>
+          </region>
+        </config>
+     </attribute>
+
+    </mbean>
+</server>


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/optimistic-local-cache.xml
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/pessimistic-local-cache.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/pessimistic-local-cache.xml	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/pessimistic-local-cache.xml	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!--                                                                       -->
+<!--  Sample TreeCache Service Configuration                               -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+
+<server>
+
+    <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
+
+
+    <!-- ==================================================================== -->
+    <!-- Defines TreeCache configuration                                      -->
+    <!-- ==================================================================== -->
+
+    <mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
+        name="jboss.cache:service=TreeCache">
+
+        <depends>jboss:service=Naming</depends>
+        <depends>jboss:service=TransactionManager</depends>
+
+        <!--
+            TransactionManager configuration not required for Hibernate!
+            Hibernate will plug in its own transaction manager integration.
+        -->
+
+        <!--
+            Node isolation level : SERIALIZABLE
+                                 REPEATABLE_READ (default)
+                                 READ_COMMITTED
+                                 READ_UNCOMMITTED
+                                 NONE
+        -->
+        <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+        <!--
+             Valid modes are LOCAL
+                             REPL_ASYNC
+                             REPL_SYNC
+        -->
+        <attribute name="CacheMode">LOCAL</attribute>
+
+        <!-- Name of cluster. Needs to be the same for all clusters, in order
+             to find each other
+        -->
+        <attribute name="ClusterName">TreeCache-Cluster</attribute>
+
+        <attribute name="ClusterConfig">
+            <config>
+                <!-- UDP: if you have a multihomed machine,
+                set the bind_addr attribute to the appropriate NIC IP address -->
+                <!-- UDP: On Windows machines, because of the media sense feature
+                 being broken with multicast (even after disabling media sense)
+                 set the loopback attribute to true -->
+                <UDP mcast_addr="228.1.2.3" mcast_port="45566"
+                    ip_ttl="64" ip_mcast="true"
+                    mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
+                    ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
+                    loopback="false"/>
+                <PING timeout="2000" num_initial_members="3"/>
+                <MERGE2 min_interval="10000" max_interval="20000"/>
+                <FD shun="true"/>
+                <VERIFY_SUSPECT timeout="1500"/>
+                <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"/>
+                <pbcast.STABLE desired_avg_gossip="20000"/>
+                <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"/>
+                <FRAG frag_size="8192"/>
+                <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+                    shun="true" print_local_addr="true"/>
+                <pbcast.STATE_TRANSFER/>
+            </config>
+        </attribute>
+      
+      <!-- Must be true if any entity deployment uses a scoped classloader -->
+      <attribute name="UseRegionBasedMarshalling">true</attribute>
+      <!-- Must match the value of "useRegionBasedMarshalling" -->
+      <attribute name="InactiveOnStartup">true</attribute>
+
+        <!--
+            The max amount of time (in milliseconds) we wait until the
+            initial state (ie. the contents of the cache) are retrieved from
+            existing members in a clustered environment
+        -->
+        <attribute name="StateRetrievalTimeout">20000</attribute>
+
+        <!--
+            Number of milliseconds to wait until all responses for a
+            synchronous call have been received.
+        -->
+        <attribute name="SyncReplTimeout">20000</attribute>
+
+        <!-- Max number of milliseconds to wait for a lock acquisition -->
+        <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+      <!--  Specific eviction policy configurations. This is LRU -->
+      <attribute name="EvictionPolicyConfig">
+        <config>
+          <attribute name="wakeUpIntervalSeconds">5</attribute>
+          <!-- Name of the DEFAULT eviction policy class. -->
+          <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+          <!--  Cache wide default -->
+          <region name="/_default_">
+            <attribute name="maxNodes">5000</attribute>
+            <attribute name="timeToLiveSeconds">1000</attribute>
+          </region>
+          <!--  Don't ever evict modification timestamps -->
+          <region name="/TS">
+            <attribute name="maxNodes">0</attribute>
+            <attribute name="timeToLiveSeconds">0</attribute>
+          </region>
+        </config>
+     </attribute>
+  </mbean>
+
+
+</server>


Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/pessimistic-local-cache.xml
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/resources/hibernate.cfg.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/resources/hibernate.cfg.xml	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/resources/hibernate.cfg.xml	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,8 @@
+<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+<hibernate-configuration>
+	<session-factory name="foo">
+		<property name="show_sql">true</property>
+		<mapping resource="org/hibernate/test/legacy/Simple.hbm.xml"/>
+		<class-cache class="org.hibernate.test.legacy.Simple" region="Simple" usage="read-write"/>
+	</session-factory>
+</hibernate-configuration>
\ No newline at end of file


Property changes on: core/trunk/cache-jbosscache2/src/test/resources/hibernate.cfg.xml
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/resources/hibernate.properties
===================================================================
--- core/trunk/cache-jbosscache2/src/test/resources/hibernate.properties	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/resources/hibernate.properties	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,30 @@
+################################################################################
+# Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.            #
+#                                                                              #
+# 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, v. 2.1. This program is distributed in the    #
+# hope that it will be useful, but WITHOUT A 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, v.2.1 along with this         #
+# distribution; if not, write to the Free Software Foundation, Inc.,           #
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                 #
+#                                                                              #
+# Red Hat Author(s): Steve Ebersole                                            #
+################################################################################
+hibernate.dialect org.hibernate.dialect.HSQLDialect
+hibernate.connection.driver_class org.hsqldb.jdbcDriver
+hibernate.connection.url jdbc:hsqldb:target/test/db/hsqldb/hibernate
+hibernate.connection.username sa
+hibernate.connection.password 
+hibernate.connection.isolation 
+
+hibernate.connection.pool_size 5
+
+hibernate.format_sql true
+
+hibernate.max_fetch_depth 5
+
+hibernate.cache.region_prefix hibernate.test
+hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider


Property changes on: core/trunk/cache-jbosscache2/src/test/resources/hibernate.properties
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/resources/log4j.properties
===================================================================
--- core/trunk/cache-jbosscache2/src/test/resources/log4j.properties	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/resources/log4j.properties	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,9 @@
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
+
+
+log4j.rootLogger=info, stdout
+
+log4j.logger.org.hibernate.test=info
\ No newline at end of file


Property changes on: core/trunk/cache-jbosscache2/src/test/resources/log4j.properties
___________________________________________________________________
Name: svn:executable
   + *

Added: core/trunk/cache-jbosscache2/src/test/resources/treecache.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/resources/treecache.xml	                        (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/resources/treecache.xml	2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!--                                                                       -->
+<!--  Sample TreeCache Service Configuration                               -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+
+<server>
+
+    <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
+
+
+    <!-- ==================================================================== -->
+    <!-- Defines TreeCache configuration                                      -->
+    <!-- ==================================================================== -->
+
+    <mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
+        name="jboss.cache:service=TreeCache">
+
+        <depends>jboss:service=Naming</depends>
+        <depends>jboss:service=TransactionManager</depends>
+
+        <!-- TransactionManager configuration not required for Hibernate!
+             Hibernate will plug in its own transaction manager integration. 
+        -->
+
+        <!-- Node locking scheme:
+                OPTIMISTIC
+                PESSIMISTIC (default)
+        -->
+        <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+
+        <!--
+            Isolation level : SERIALIZABLE
+                              REPEATABLE_READ (default)
+                              READ_COMMITTED
+                              READ_UNCOMMITTED
+                              NONE
+        -->
+        <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+        <!-- Valid modes are LOCAL
+                             REPL_ASYNC
+                             REPL_SYNC
+                             INVALIDATION_ASYNC
+                             INVALIDATION_SYNC
+
+             INVALIDATION_SYNC is highly recommended as the mode for use
+             with entity and collection caches.
+        -->
+        <attribute name="CacheMode">REPL_SYNC</attribute>
+
+        <!-- Name of cluster. Needs to be the same for all members, in order
+             to find each other -->
+        <attribute name="ClusterName">TestSharedCache</attribute>
+        
+        <!-- Use a UDP (multicast) based stack. Need JGroups flow control (FC)
+             because timestamp communication will not require a synchronous response.
+        -->
+        <attribute name="MultiplexerStack">udp</attribute>
+
+        <!-- Used for timestamps, so must fetch state. -->
+        <attribute name="FetchInMemoryState">true</attribute>
+
+        <!--
+          The max amount of time (in milliseconds) we wait until the
+          state (ie. the contents of the cache) are retrieved from
+          existing members at startup.
+        -->
+        <attribute name="StateRetrievalTimeout">20000</attribute>
+
+        <!--
+            Number of milliseconds to wait until all responses for a
+            synchronous call have been received.
+        -->
+        <attribute name="SyncReplTimeout">20000</attribute>
+
+        <!-- Max number of milliseconds to wait for a lock acquisition -->
+        <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+       <!--
+          Indicate whether to use marshalling or not. Set this to true if you 
+          are running under a scoped class loader, e.g., inside an application 
+          server. Default is "false".
+       -->
+       <attribute name="UseRegionBasedMarshalling">true</attribute>
+       <!-- Must match the value of "useRegionBasedMarshalling" -->
+       <attribute name="InactiveOnStartup">true</attribute>
+
+      <!--  Specific eviction policy configurations. This is LRU -->
+      <attribute name="EvictionPolicyConfig">
+        <config>
+          <attribute name="wakeUpIntervalSeconds">5</attribute>
+          <!-- Name of the DEFAULT eviction policy class. -->
+          <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+          <!--  Cache wide default -->
+          <region name="/_default_">
+            <attribute name="maxNodes">5000</attribute>
+            <attribute name="timeToLiveSeconds">1000</attribute>
+          </region>
+          <!--  Don't ever evict modification timestamps -->
+          <region name="/TS">
+            <attribute name="maxNodes">0</attribute>
+            <attribute name="timeToLiveSeconds">0</attribute>
+          </region>
+        </config>
+     </attribute>
+     
+  </mbean>
+
+
+</server>


Property changes on: core/trunk/cache-jbosscache2/src/test/resources/treecache.xml
___________________________________________________________________
Name: svn:executable
   + *




More information about the hibernate-commits mailing list