[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