[hibernate-commits] Hibernate SVN: r11398 - in trunk/Hibernate3: src/org/hibernate/cache and 17 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Apr 10 10:54:07 EDT 2007


Author: steve.ebersole at jboss.com
Date: 2007-04-10 10:54:07 -0400 (Tue, 10 Apr 2007)
New Revision: 11398

Added:
   trunk/Hibernate3/src/org/hibernate/cache/CacheDataDescription.java
   trunk/Hibernate3/src/org/hibernate/cache/CollectionRegion.java
   trunk/Hibernate3/src/org/hibernate/cache/EntityRegion.java
   trunk/Hibernate3/src/org/hibernate/cache/GeneralDataRegion.java
   trunk/Hibernate3/src/org/hibernate/cache/QueryResultsRegion.java
   trunk/Hibernate3/src/org/hibernate/cache/Region.java
   trunk/Hibernate3/src/org/hibernate/cache/RegionFactory.java
   trunk/Hibernate3/src/org/hibernate/cache/TimestampsRegion.java
   trunk/Hibernate3/src/org/hibernate/cache/TransactionalDataRegion.java
   trunk/Hibernate3/src/org/hibernate/cache/access/
   trunk/Hibernate3/src/org/hibernate/cache/access/AccessType.java
   trunk/Hibernate3/src/org/hibernate/cache/access/CollectionRegionAccessStrategy.java
   trunk/Hibernate3/src/org/hibernate/cache/access/EntityRegionAccessStrategy.java
   trunk/Hibernate3/src/org/hibernate/cache/access/SoftLock.java
   trunk/Hibernate3/src/org/hibernate/cache/access/package.html
   trunk/Hibernate3/src/org/hibernate/cache/impl/
   trunk/Hibernate3/src/org/hibernate/cache/impl/CacheDataDescriptionImpl.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/NoCachingRegionFactory.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseGeneralDataRegionAdapter.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseRegionAdapter.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseTransactionalDataRegionAdapter.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/CollectionAccessStrategyAdapter.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/CollectionRegionAdapter.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/EntityAccessStrategyAdapter.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/EntityRegionAdapter.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/OptimisticCacheSourceAdapter.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/QueryResultsRegionAdapter.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/RegionFactoryCacheProviderBridge.java
   trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/TimestampsRegionAdapter.java
Removed:
   trunk/Hibernate3/src/org/hibernate/cache/CacheFactory.java
Modified:
   trunk/Hibernate3/src/org/hibernate/action/CollectionAction.java
   trunk/Hibernate3/src/org/hibernate/action/EntityDeleteAction.java
   trunk/Hibernate3/src/org/hibernate/action/EntityInsertAction.java
   trunk/Hibernate3/src/org/hibernate/action/EntityUpdateAction.java
   trunk/Hibernate3/src/org/hibernate/cache/Cache.java
   trunk/Hibernate3/src/org/hibernate/cache/CacheConcurrencyStrategy.java
   trunk/Hibernate3/src/org/hibernate/cache/CacheProvider.java
   trunk/Hibernate3/src/org/hibernate/cache/NonstrictReadWriteCache.java
   trunk/Hibernate3/src/org/hibernate/cache/OptimisticCacheSource.java
   trunk/Hibernate3/src/org/hibernate/cache/QueryCache.java
   trunk/Hibernate3/src/org/hibernate/cache/ReadOnlyCache.java
   trunk/Hibernate3/src/org/hibernate/cache/ReadWriteCache.java
   trunk/Hibernate3/src/org/hibernate/cache/StandardQueryCache.java
   trunk/Hibernate3/src/org/hibernate/cache/TransactionalCache.java
   trunk/Hibernate3/src/org/hibernate/cache/TreeCacheProvider.java
   trunk/Hibernate3/src/org/hibernate/cache/UpdateTimestampsCache.java
   trunk/Hibernate3/src/org/hibernate/cache/package.html
   trunk/Hibernate3/src/org/hibernate/cfg/Environment.java
   trunk/Hibernate3/src/org/hibernate/cfg/Settings.java
   trunk/Hibernate3/src/org/hibernate/cfg/SettingsFactory.java
   trunk/Hibernate3/src/org/hibernate/engine/BatchFetchQueue.java
   trunk/Hibernate3/src/org/hibernate/engine/Mapping.java
   trunk/Hibernate3/src/org/hibernate/engine/SessionFactoryImplementor.java
   trunk/Hibernate3/src/org/hibernate/engine/TwoPhaseLoad.java
   trunk/Hibernate3/src/org/hibernate/engine/loading/CollectionLoadContext.java
   trunk/Hibernate3/src/org/hibernate/event/def/AbstractLockUpgradeEventListener.java
   trunk/Hibernate3/src/org/hibernate/event/def/DefaultInitializeCollectionEventListener.java
   trunk/Hibernate3/src/org/hibernate/event/def/DefaultLoadEventListener.java
   trunk/Hibernate3/src/org/hibernate/event/def/DefaultRefreshEventListener.java
   trunk/Hibernate3/src/org/hibernate/impl/SessionFactoryImpl.java
   trunk/Hibernate3/src/org/hibernate/impl/StatelessSessionImpl.java
   trunk/Hibernate3/src/org/hibernate/loader/Loader.java
   trunk/Hibernate3/src/org/hibernate/persister/PersisterFactory.java
   trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java
   trunk/Hibernate3/src/org/hibernate/persister/collection/BasicCollectionPersister.java
   trunk/Hibernate3/src/org/hibernate/persister/collection/CollectionPersister.java
   trunk/Hibernate3/src/org/hibernate/persister/collection/OneToManyPersister.java
   trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java
   trunk/Hibernate3/src/org/hibernate/persister/entity/EntityPersister.java
   trunk/Hibernate3/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java
   trunk/Hibernate3/src/org/hibernate/persister/entity/SingleTableEntityPersister.java
   trunk/Hibernate3/src/org/hibernate/persister/entity/UnionSubclassEntityPersister.java
   trunk/Hibernate3/src/org/hibernate/stat/SecondLevelCacheStatistics.java
   trunk/Hibernate3/src/org/hibernate/stat/StatisticsImpl.java
   trunk/Hibernate3/test/org/hibernate/test/cache/BaseCacheProviderTestCase.java
   trunk/Hibernate3/test/org/hibernate/test/cache/treecache/optimistic/OptimisticTreeCacheTest.java
   trunk/Hibernate3/test/org/hibernate/test/filter/DynamicFilterTest.java
   trunk/Hibernate3/test/org/hibernate/test/legacy/CacheTest.java
   trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.java
Log:
HHH-2533: cache redesign

Modified: trunk/Hibernate3/src/org/hibernate/action/CollectionAction.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/action/CollectionAction.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/action/CollectionAction.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -1,7 +1,7 @@
 //$Id$
 package org.hibernate.action;
 
-import org.hibernate.cache.CacheConcurrencyStrategy.SoftLock;
+import org.hibernate.cache.access.SoftLock;
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.CacheKey;
 import org.hibernate.collection.PersistentCollection;
@@ -32,8 +32,7 @@
 			final CollectionPersister persister, 
 			final PersistentCollection collection, 
 			final Serializable key, 
-			final SessionImplementor session)
-	throws CacheException {
+			final SessionImplementor session) throws CacheException {
 		this.persister = persister;
 		this.session = session;
 		this.key = key;
@@ -59,7 +58,7 @@
 					session.getEntityMode(), 
 					session.getFactory() 
 				);
-			persister.getCache().release(ck, lock);
+			persister.getCacheAccessStrategy().unlockItem( ck, lock );
 		}
 	}
 
@@ -106,8 +105,8 @@
 					persister.getRole(), 
 					session.getEntityMode(), 
 					session.getFactory() 
-				);
-			lock = persister.getCache().lock(ck, null);
+			);
+			lock = persister.getCacheAccessStrategy().lockItem( ck, null );
 		}
 	}
 
@@ -120,7 +119,7 @@
 					session.getEntityMode(), 
 					session.getFactory() 
 				);
-			persister.getCache().evict(ck);
+			persister.getCacheAccessStrategy().remove( ck );
 		}
 	}
 

Modified: trunk/Hibernate3/src/org/hibernate/action/EntityDeleteAction.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/action/EntityDeleteAction.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/action/EntityDeleteAction.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -6,7 +6,7 @@
 import org.hibernate.AssertionFailure;
 import org.hibernate.HibernateException;
 import org.hibernate.cache.CacheKey;
-import org.hibernate.cache.CacheConcurrencyStrategy.SoftLock;
+import org.hibernate.cache.access.SoftLock;
 import org.hibernate.engine.EntityEntry;
 import org.hibernate.engine.EntityKey;
 import org.hibernate.engine.PersistenceContext;
@@ -64,7 +64,7 @@
 					session.getEntityMode(), 
 					session.getFactory() 
 				);
-			lock = persister.getCache().lock(ck, version);
+			lock = persister.getCacheAccessStrategy().lockItem( ck, version );
 		}
 		else {
 			ck = null;
@@ -89,7 +89,7 @@
 		persistenceContext.removeEntity(key);
 		persistenceContext.removeProxy(key);
 		
-		if ( persister.hasCache() ) persister.getCache().evict(ck);
+		if ( persister.hasCache() ) persister.getCacheAccessStrategy().remove( ck );
 
 		postDelete();
 
@@ -155,7 +155,7 @@
 					getSession().getEntityMode(), 
 					getSession().getFactory()
 				);
-			getPersister().getCache().release(ck, lock);
+			getPersister().getCacheAccessStrategy().unlockItem( ck, lock );
 		}
 		postCommitDelete();
 	}

Modified: trunk/Hibernate3/src/org/hibernate/action/EntityInsertAction.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/action/EntityInsertAction.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/action/EntityInsertAction.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -90,11 +90,10 @@
 					session.getFactory() 
 				);
 //			boolean put = persister.getCache().insert(ck, cacheEntry);
-			boolean put = persister.getCache().insert( ck, cacheEntry, version );
+			boolean put = persister.getCacheAccessStrategy().insert( ck, cacheEntry, version );
 			
 			if ( put && factory.getStatistics().isStatisticsEnabled() ) {
-				factory.getStatisticsImplementor()
-						.secondLevelCachePut( getPersister().getCache().getRegionName() );
+				factory.getStatisticsImplementor().secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() );
 			}
 			
 		}
@@ -166,11 +165,11 @@
 					getSession().getEntityMode(), 
 					getSession().getFactory() 
 				);
-			boolean put = persister.getCache().afterInsert(ck, cacheEntry, version );
+			boolean put = persister.getCacheAccessStrategy().afterInsert( ck, cacheEntry, version );
 			
 			if ( put && getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
 				getSession().getFactory().getStatisticsImplementor()
-						.secondLevelCachePut( getPersister().getCache().getRegionName() );
+						.secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() );
 			}
 		}
 		postCommitInsert();

Modified: trunk/Hibernate3/src/org/hibernate/action/EntityUpdateAction.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/action/EntityUpdateAction.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/action/EntityUpdateAction.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -7,7 +7,7 @@
 import org.hibernate.HibernateException;
 import org.hibernate.cache.CacheException;
 import org.hibernate.cache.CacheKey;
-import org.hibernate.cache.CacheConcurrencyStrategy.SoftLock;
+import org.hibernate.cache.access.SoftLock;
 import org.hibernate.cache.entry.CacheEntry;
 import org.hibernate.engine.EntityEntry;
 import org.hibernate.engine.SessionFactoryImplementor;
@@ -82,7 +82,7 @@
 					session.getEntityMode(), 
 					session.getFactory() 
 			);
-			lock = persister.getCache().lock(ck, previousVersion);
+			lock = persister.getCacheAccessStrategy().lockItem( ck, previousVersion );
 		}
 		else {
 			ck = null;
@@ -133,7 +133,7 @@
 
 		if ( persister.hasCache() ) {
 			if ( persister.isCacheInvalidationRequired() || entry.getStatus()!=Status.MANAGED ) {
-				persister.getCache().evict(ck);
+				persister.getCacheAccessStrategy().remove( ck );
 			}
 			else {
 				//TODO: inefficient if that cache is just going to ignore the updated state!
@@ -146,10 +146,9 @@
 						instance
 				);
 				cacheEntry = persister.getCacheEntryStructure().structure( ce );
-				boolean put = persister.getCache().update( ck, cacheEntry, nextVersion, previousVersion );
+				boolean put = persister.getCacheAccessStrategy().update( ck, cacheEntry, nextVersion, previousVersion );
 				if ( put && factory.getStatistics().isStatisticsEnabled() ) {
-					factory.getStatisticsImplementor()
-							.secondLevelCachePut( getPersister().getCache().getRegionName() );
+					factory.getStatisticsImplementor().secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() );
 				}
 			}
 		}
@@ -231,15 +230,14 @@
 				);
 			
 			if ( success && cacheEntry!=null /*!persister.isCacheInvalidationRequired()*/ ) {
-				boolean put = persister.getCache().afterUpdate(ck, cacheEntry, nextVersion, lock );
+				boolean put = persister.getCacheAccessStrategy().afterUpdate( ck, cacheEntry, nextVersion, previousVersion, lock );
 				
 				if ( put && getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
-					getSession().getFactory().getStatisticsImplementor()
-							.secondLevelCachePut( getPersister().getCache().getRegionName() );
+					getSession().getFactory().getStatisticsImplementor().secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() );
 				}
 			}
 			else {
-				persister.getCache().release(ck, lock );
+				persister.getCacheAccessStrategy().unlockItem( ck, lock );
 			}
 		}
 		postCommitUpdate();

Modified: trunk/Hibernate3/src/org/hibernate/cache/Cache.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/Cache.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/Cache.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -6,6 +6,8 @@
 /**
  * Implementors define a caching algorithm. All implementors
  * <b>must</b> be threadsafe.
+ *
+ * @deprecated As of 3.3; see <a href="package.html"/> for details.
  */
 public interface Cache {
 	/**

Modified: trunk/Hibernate3/src/org/hibernate/cache/CacheConcurrencyStrategy.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/CacheConcurrencyStrategy.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/CacheConcurrencyStrategy.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -3,6 +3,8 @@
 
 import java.util.Comparator;
 
+import org.hibernate.cache.access.SoftLock;
+
 /**
  * Implementors manage transactional access to cached data. Transactions
  * pass in a timestamp indicating transaction start time. Two different
@@ -36,6 +38,8 @@
  * <p/>
  * Note that query result caching does not go through a concurrency strategy; they
  * are managed directly against the underlying {@link Cache cache regions}.
+ *
+ * @deprecated As of 3.3; see <a href="package.html"/> for details.
  */
 public interface CacheConcurrencyStrategy {
 
@@ -119,7 +123,7 @@
 	 * instead of calling release().
 	 * This method is used by "asynchronous" concurrency strategies.
 	 */
-	public boolean afterUpdate(Object key, Object value, Object version, SoftLock lock) 
+	public boolean afterUpdate(Object key, Object value, Object version, SoftLock lock)
 	throws CacheException;
 	/**
 	 * Called after an item has been inserted (after the transaction completes),
@@ -151,13 +155,6 @@
 	 * @param cache
 	 */
 	public void setCache(Cache cache);
-	
-	/**
-	 * Marker interface, denoting a client-visible "soft lock"
-	 * on a cached item.
-	 * @author Gavin King
-	 */
-	public static interface SoftLock {}
 		
 	/**
 	 * Get the cache region name

Added: trunk/Hibernate3/src/org/hibernate/cache/CacheDataDescription.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/CacheDataDescription.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/CacheDataDescription.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,35 @@
+package org.hibernate.cache;
+
+import java.util.Comparator;
+
+/**
+ * Describes attributes regarding the type of data to be cached.
+ *
+ * @author Steve Ebersole
+ */
+public interface CacheDataDescription {
+	/**
+	 * Is the data marked as being mutable?
+	 *
+	 * @return True if the data is mutable; false otherwise.
+	 */
+	public boolean isMutable();
+
+	/**
+	 * Is the data to be cached considered versioned?
+	 * <p/>
+	 * If true, it is illegal for {@link #getVersionComparator} to return
+	 * null.
+	 *
+	 * @return True if the data is versioned; false otherwise.
+	 */
+	public boolean isVersioned();
+
+	/**
+	 * Get the comparator used to compare two different version values.
+	 * <p/>
+	 * May return null <b>if</b> {@link #isVersioned()} returns false.
+	 * @return
+	 */
+	public Comparator getVersionComparator();
+}

Deleted: trunk/Hibernate3/src/org/hibernate/cache/CacheFactory.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/CacheFactory.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/CacheFactory.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -1,71 +0,0 @@
-//$Id$
-package org.hibernate.cache;
-
-import java.util.Properties;
-
-import org.hibernate.HibernateException;
-import org.hibernate.MappingException;
-import org.hibernate.cfg.Settings;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * @author Gavin King
- */
-public final class CacheFactory {
-	
-	private static final Log log = LogFactory.getLog(CacheFactory.class);
-	
-	private CacheFactory() {}
-	
-	public static final String READ_ONLY = "read-only";
-	public static final String READ_WRITE = "read-write";
-	public static final String NONSTRICT_READ_WRITE = "nonstrict-read-write";
-	public static final String TRANSACTIONAL = "transactional";
-	
-	public static CacheConcurrencyStrategy createCache(
-		final String concurrencyStrategy, 
-		String regionName, 
-		final boolean mutable, 
-		final Settings settings,
-		final Properties properties) 
-	throws HibernateException {
-		
-		if ( concurrencyStrategy==null || !settings.isSecondLevelCacheEnabled() ) return null; //no cache
-		
-		String prefix = settings.getCacheRegionPrefix();
-		if ( prefix!=null ) regionName = prefix + '.' + regionName;
-		
-		if ( log.isDebugEnabled() ) log.debug("instantiating cache region: " + regionName + " usage strategy: " + concurrencyStrategy);
-		
-		final CacheConcurrencyStrategy ccs;
-		if ( concurrencyStrategy.equals(READ_ONLY) ) {
-			if (mutable) log.warn( "read-only cache configured for mutable class: " + regionName );
-			ccs = new ReadOnlyCache();
-		}
-		else if ( concurrencyStrategy.equals(READ_WRITE) ) {
-			ccs = new ReadWriteCache();
-		}
-		else if ( concurrencyStrategy.equals(NONSTRICT_READ_WRITE) ) {
-			ccs = new NonstrictReadWriteCache();
-		}
-		else if ( concurrencyStrategy.equals(TRANSACTIONAL) ) {
-			ccs = new TransactionalCache();
-		}
-		else {
-			throw new MappingException("cache usage attribute should be read-write, read-only, nonstrict-read-write or transactional");
-		}
-		
-		final Cache impl;
-		try {
-			impl = settings.getCacheProvider().buildCache(regionName, properties);
-		}
-		catch (CacheException e) {
-			throw new HibernateException( "Could not instantiate cache implementation", e );
-		}
-		ccs.setCache(impl);
-		
-		return ccs;
-	}
-		
-}

Modified: trunk/Hibernate3/src/org/hibernate/cache/CacheProvider.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/CacheProvider.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/CacheProvider.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -7,6 +7,7 @@
  * Support for pluggable caches.
  *
  * @author Gavin King
+ * @deprecated As of 3.3; see <a href="package.html"/> for details.
  */
 public interface CacheProvider {
 

Added: trunk/Hibernate3/src/org/hibernate/cache/CollectionRegion.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/CollectionRegion.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/CollectionRegion.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,28 @@
+package org.hibernate.cache;
+
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.AccessType;
+
+/**
+ * Defines the contract for a cache region which will specifically be used to
+ * store collection data.
+ * <p/>
+ * Impl note: Hibernate always deals with changes to collections which
+ * (potentially) has its data in the L2 cache by removing that collection
+ * data; in other words it never tries to update the cached state, thereby
+ * allowing it to avoid a bunch of concurrency problems.
+ *
+ * @author Steve Ebersole
+ */
+public interface CollectionRegion extends TransactionalDataRegion {
+
+	/**
+	 * Build an access strategy for the requested access type.
+	 *
+	 * @param accessType The type of access strategy to build; never null.
+	 * @return The appropriate strategy contract for accessing this region
+	 * for the requested type of access.
+	 * @throws CacheException Usually indicates mis-configuration.
+	 */
+	public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException;
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/EntityRegion.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/EntityRegion.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/EntityRegion.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,23 @@
+package org.hibernate.cache;
+
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.AccessType;
+
+/**
+ * Defines the contract for a cache region which will specifically be used to
+ * store entity data.
+ *
+ * @author Steve Ebersole
+ */
+public interface EntityRegion extends TransactionalDataRegion {
+
+	/**
+	 * Build an access strategy for the requested access type.
+	 *
+	 * @param accessType The type of access strategy to build; never null.
+	 * @return The appropriate strategy contract for accessing this region
+	 * for the requested type of access.
+	 * @throws CacheException Usually indicates mis-configuration.
+	 */
+	public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException;
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/GeneralDataRegion.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/GeneralDataRegion.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/GeneralDataRegion.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,44 @@
+package org.hibernate.cache;
+
+/**
+ * Contract for general-purpose cache regions.
+ *
+ * @author Steve Ebersole
+ */
+public interface GeneralDataRegion extends Region {
+
+	/**
+	 * Get an item from the cache.
+	 *
+	 * @param key The key of the item to be retrieved.
+	 * @return the cached object or <tt>null</tt>
+	 * @throws CacheException Indicates a problem accessing the item or region.
+	 */
+	public Object get(Object key) throws CacheException;
+
+	/**
+	 * Put an item into the cache.
+	 *
+	 * @param key The key under which to cache the item.
+	 * @param value The item to cache.
+	 * @throws CacheException Indicates a problem accessing the region.
+	 */
+	public void put(Object key, Object value) throws CacheException;
+
+	/**
+	 * Evict an item from the cache immediately (without regard for transaction
+	 * isolation).
+	 *
+	 * @param key The key of the item to remove
+	 * @throws CacheException Indicates a problem accessing the item or region.
+	 */
+	public void evict(Object key) throws CacheException;
+
+	/**
+	 * Evict all contents of this particular cache region (without regard for transaction
+	 * isolation).
+	 *
+	 * @throws CacheException Indicates problem accessing the region.
+	 */
+	public void evictAll() throws CacheException;
+}

Modified: trunk/Hibernate3/src/org/hibernate/cache/NonstrictReadWriteCache.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/NonstrictReadWriteCache.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/NonstrictReadWriteCache.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -6,6 +6,8 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.hibernate.cache.access.SoftLock;
+
 /**
  * Caches data that is sometimes updated without ever locking the cache.
  * If concurrent access to an item is possible, this concurrency strategy

Modified: trunk/Hibernate3/src/org/hibernate/cache/OptimisticCacheSource.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/OptimisticCacheSource.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/OptimisticCacheSource.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -13,17 +13,20 @@
  */
 public interface OptimisticCacheSource {
 	/**
-	 * Does this source represent versioned (i.e., and thus optimistically
-	 * lockable) data?
+	 * Is the data to be cached considered versioned?
+	 * <p/>
+	 * If true, it is illegal for {@link #getVersionComparator} to return
+	 * null.
 	 *
-	 * @return True if this source represents versioned data; false otherwise.
+	 * @return True if the data is versioned; false otherwise.
 	 */
 	public boolean isVersioned();
 
 	/**
-	 * Get the comparator used to compare two different version values together.
-	 *
-	 * @return An appropriate comparator.
+	 * Get the comparator used to compare two different version values.
+	 * <p/>
+	 * May return null <b>if</b> {@link #isVersioned()} returns false.
+	 * @return
 	 */
 	public Comparator getVersionComparator();
 }

Modified: trunk/Hibernate3/src/org/hibernate/cache/QueryCache.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/QueryCache.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/QueryCache.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -22,12 +22,10 @@
 	
 	public boolean put(QueryKey key, Type[] returnTypes, List result, boolean isNaturalKeyLookup, SessionImplementor session) throws HibernateException;
 
-	public List get(QueryKey key, Type[] returnTypes, boolean isNaturalKeyLookup, Set spaces, SessionImplementor session) 
-	throws HibernateException;
+	public List get(QueryKey key, Type[] returnTypes, boolean isNaturalKeyLookup, Set spaces, SessionImplementor session) throws HibernateException;
 
 	public void destroy();
 
-	public Cache getCache();
+	public QueryResultsRegion getRegion();
 
-	public String getRegionName();
 }

Added: trunk/Hibernate3/src/org/hibernate/cache/QueryResultsRegion.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/QueryResultsRegion.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/QueryResultsRegion.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,10 @@
+package org.hibernate.cache;
+
+/**
+ * Defines the contract for a cache region which will specifically be used to
+ * store query results.
+ *
+ * @author Steve Ebersole
+ */
+public interface QueryResultsRegion extends GeneralDataRegion {
+}

Modified: trunk/Hibernate3/src/org/hibernate/cache/ReadOnlyCache.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/ReadOnlyCache.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/ReadOnlyCache.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -6,6 +6,8 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.hibernate.cache.access.SoftLock;
+
 /**
  * Caches data that is never updated.
  * @see CacheConcurrencyStrategy

Modified: trunk/Hibernate3/src/org/hibernate/cache/ReadWriteCache.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/ReadWriteCache.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/ReadWriteCache.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -7,6 +7,8 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.hibernate.cache.access.SoftLock;
+
 /**
  * Caches data that is sometimes updated while maintaining the semantics of
  * "read committed" isolation level. If the database is set to "repeatable

Added: trunk/Hibernate3/src/org/hibernate/cache/Region.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/Region.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/Region.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,62 @@
+package org.hibernate.cache;
+
+import java.util.Map;
+
+/**
+ * Defines a contract for accessing a particular named region within the 
+ * underlying cache implementation.
+ *
+ * @author Steve Ebersole
+ */
+public interface Region {
+	/**
+	 * Retrieve the name of this region.
+	 *
+	 * @return The region name
+	 */
+	public String getName();
+
+	/**
+	 * The "end state" contract of the region's lifecycle.  Called
+	 * during {@link org.hibernate.SessionFactory#close()} to give
+	 * the region a chance to cleanup.
+	 *
+	 * @throws CacheException Indicates problem shutting down
+	 */
+	public void destroy() throws CacheException;
+
+	/**
+	 * The number of bytes is this cache region currently consuming in memory.
+	 *
+	 * @return The number of bytes consumed by this region; -1 if unknown or
+	 * unsupported.
+	 */
+	public long getSizeInMemory();
+
+	/**
+	 * The count of entries currently contained in the regions in-memory store.
+	 *
+	 * @return The count of entries in memory; -1 if unknown or unsupported.
+	 */
+	public long getElementCountInMemory();
+
+	/**
+	 * The count of entries currently contained in the regions disk store.
+	 *
+	 * @return The count of entries on disk; -1 if unknown or unsupported.
+	 */
+	public long getElementCountOnDisk();
+
+	/**
+	 * Get the contents of this region as a map.
+	 * <p/>
+	 * Implementors which do not support this notion
+	 * should simply return an empty map.
+	 *
+	 * @return The content map.
+	 */
+	public Map toMap();
+
+	public long nextTimestamp();
+	public int getTimeout();
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/RegionFactory.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/RegionFactory.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/RegionFactory.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,106 @@
+package org.hibernate.cache;
+
+import java.util.Properties;
+
+import org.hibernate.cfg.Settings;
+
+/**
+ * Contract for building second level cache regions.
+ * <p/>
+ * Implementors should define a constructor in one of two forms:<ul>
+ * <li>MyRegionFactoryImpl({@link java.util.Properties})</li>
+ * <li>MyRegionFactoryImpl()</li>
+ * </ul>
+ * Use the first when we need to read config properties prior to
+ * {@link #start} being called.  For an example, have a look at
+ * {@link org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge}
+ * where we need the properties in order to determine which legacy 
+ * {@link CacheProvider} to use so that we can answer the
+ * {@link #isMinimalPutsEnabledByDefault()} question for the
+ * {@link org.hibernate.cfg.SettingsFactory}.
+ *
+ * @author Steve Ebersole
+ */
+public interface RegionFactory {
+
+	/**
+	 * Lifecycle callback to perform any necessary initialization of the
+	 * underlying cache implementation(s).  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
+	 * cache implementation(s).  Called exactly once during
+	 * {@link org.hibernate.SessionFactory#close}.
+	 */
+	public void stop();
+
+	/**
+	 * By default should we perform "minimal puts" when using this second
+	 * level cache implementation?
+	 *
+	 * @return True if "minimal puts" should be performed by default; false
+	 * otherwise.
+	 */
+	public boolean isMinimalPutsEnabledByDefault();
+
+	/**
+	 * Generate a timestamp.
+	 * <p/>
+	 * This is generally used for cache content locking/unlocking purposes
+	 * depending upon the access-strategy being used.
+	 *
+	 * @return The generated timestamp.
+	 */
+	public long nextTimestamp();
+
+	/**
+	 * Build a cache region specialized for storing entity data.
+	 *
+	 * @param regionName The name of the region.
+	 * @param properties Configuration properties.
+	 * @param metadata Information regarding the type of data to be cached
+	 * @return The built region
+	 * @throws CacheException Indicates problems building the region.
+	 */
+	public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException;
+
+	/**
+	 * Build a cache region specialized for storing collection data.
+	 *
+	 * @param regionName The name of the region.
+	 * @param properties Configuration properties.
+	 * @param metadata Information regarding the type of data to be cached
+	 * @return The built region
+	 * @throws CacheException Indicates problems building the region.
+	 */
+	public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException;
+
+	/**
+	 * Build a cache region specialized for storing query results
+	 *
+	 * @param regionName The name of the region.
+	 * @param properties Configuration properties.
+	 * @return The built region
+	 * @throws CacheException Indicates problems building the region.
+	 */
+	public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException;
+
+	/**
+	 * Build a cache region specialized for storing update-timestamps data.
+	 *
+	 * @param regionName The name of the region.
+	 * @param properties Configuration properties.
+	 * @return The built region
+	 * @throws CacheException Indicates problems building the region.
+	 */
+	public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException;
+}

Modified: trunk/Hibernate3/src/org/hibernate/cache/StandardQueryCache.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/StandardQueryCache.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/StandardQueryCache.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -24,23 +24,23 @@
  * results.
  *
  * @author Gavin King
+ * @author Steve Ebersole
  */
 public class StandardQueryCache implements QueryCache {
 
 	private static final Log log = LogFactory.getLog( StandardQueryCache.class );
 
-	private Cache queryCache;
+	private QueryResultsRegion cacheRegion;
 	private UpdateTimestampsCache updateTimestampsCache;
-	private final String regionName;
 
 	public void clear() throws CacheException {
-		queryCache.clear();
+		cacheRegion.evictAll();
 	}
 
 	public StandardQueryCache(
-			final Settings settings, 
-			final Properties props, 
-			final UpdateTimestampsCache updateTimestampsCache, 
+			final Settings settings,
+			final Properties props,
+			final UpdateTimestampsCache updateTimestampsCache,
 			String regionName) throws HibernateException {
 		if ( regionName == null ) {
 			regionName = StandardQueryCache.class.getName();
@@ -51,9 +51,8 @@
 		}
 		log.info( "starting query cache at region: " + regionName );
 
-		this.queryCache = settings.getCacheProvider().buildCache(regionName, props);
+		this.cacheRegion = settings.getRegionFactory().buildQueryResultsRegion( regionName, props );
 		this.updateTimestampsCache = updateTimestampsCache;
-		this.regionName = regionName;
 	}
 
 	public boolean put(
@@ -62,32 +61,35 @@
 			List result,
 			boolean isNaturalKeyLookup,
 			SessionImplementor session) throws HibernateException {
-		
-		if ( isNaturalKeyLookup && result.size()==0 ) {
+		if ( isNaturalKeyLookup && result.size() == 0 ) {
 			return false;
 		}
 		else {
 			Long ts = new Long( session.getTimestamp() );
 
 			if ( log.isDebugEnabled() ) {
-				log.debug( "caching query results in region: " + regionName + "; timestamp=" + ts );
+				log.debug( "caching query results in region: " + cacheRegion.getName() + "; timestamp=" + ts );
 			}
-			
-			List cacheable = new ArrayList( result.size()+1 );
+
+			List cacheable = new ArrayList( result.size() + 1 );
 			cacheable.add( ts );
-			for ( int i=0; i<result.size(); i++ ) {
-				if ( returnTypes.length==1 ) {
-					cacheable.add( returnTypes[0].disassemble( result.get(i), session, null ) );
+			for ( int i = 0; i < result.size(); i++ ) {
+				if ( returnTypes.length == 1 ) {
+					cacheable.add( returnTypes[0].disassemble( result.get( i ), session, null ) );
 				}
 				else {
-					cacheable.add( TypeFactory.disassemble( (Object[]) result.get(i), returnTypes, null, session, null ) );
+					cacheable.add(
+							TypeFactory.disassemble(
+									( Object[] ) result.get( i ), returnTypes, null, session, null
+							)
+					);
 				}
 			}
-			
-			queryCache.put(key, cacheable);
-			
+
+			cacheRegion.put( key, cacheable );
+
 			return true;
-			
+
 		}
 
 	}
@@ -99,48 +101,52 @@
 			Set spaces,
 			SessionImplementor session) throws HibernateException {
 		if ( log.isDebugEnabled() ) {
-			log.debug("checking cached query results in region: " + regionName);
+			log.debug( "checking cached query results in region: " + cacheRegion.getName() );
 		}
 
-		List cacheable = (List) queryCache.get(key);
-		if (cacheable==null) {
-			log.debug("query results were not found in cache");
+		List cacheable = ( List ) cacheRegion.get( key );
+		if ( cacheable == null ) {
+			log.debug( "query results were not found in cache" );
 			return null;
 		}
 
-		Long timestamp = (Long) cacheable.get(0);
-		if ( !isNaturalKeyLookup && !isUpToDate(spaces, timestamp) ) {
-			log.debug("cached query results were not up to date");
+		Long timestamp = ( Long ) cacheable.get( 0 );
+		if ( !isNaturalKeyLookup && !isUpToDate( spaces, timestamp ) ) {
+			log.debug( "cached query results were not up to date" );
 			return null;
 		}
 
-		log.debug("returning cached query results");
-		for ( int i=1; i<cacheable.size(); i++ ) {
-			if ( returnTypes.length==1 ) {
-				returnTypes[0].beforeAssemble( (Serializable) cacheable.get(i), session );
+		log.debug( "returning cached query results" );
+		for ( int i = 1; i < cacheable.size(); i++ ) {
+			if ( returnTypes.length == 1 ) {
+				returnTypes[0].beforeAssemble( ( Serializable ) cacheable.get( i ), session );
 			}
 			else {
-				TypeFactory.beforeAssemble( (Serializable[]) cacheable.get(i), returnTypes, session );
+				TypeFactory.beforeAssemble( ( Serializable[] ) cacheable.get( i ), returnTypes, session );
 			}
 		}
-		List result = new ArrayList( cacheable.size()-1 );
-		for ( int i=1; i<cacheable.size(); i++ ) {
+		List result = new ArrayList( cacheable.size() - 1 );
+		for ( int i = 1; i < cacheable.size(); i++ ) {
 			try {
-				if ( returnTypes.length==1 ) {
-					result.add( returnTypes[0].assemble( (Serializable) cacheable.get(i), session, null ) );
+				if ( returnTypes.length == 1 ) {
+					result.add( returnTypes[0].assemble( ( Serializable ) cacheable.get( i ), session, null ) );
 				}
 				else {
-					result.add( TypeFactory.assemble( (Serializable[]) cacheable.get(i), returnTypes, session, null ) );
+					result.add(
+							TypeFactory.assemble(
+									( Serializable[] ) cacheable.get( i ), returnTypes, session, null
+							)
+					);
 				}
 			}
-			catch (UnresolvableObjectException uoe) {
-				if (isNaturalKeyLookup) {
+			catch ( UnresolvableObjectException uoe ) {
+				if ( isNaturalKeyLookup ) {
 					//TODO: not really completely correct, since
 					//      the uoe could occur while resolving
 					//      associations, leaving the PC in an
 					//      inconsistent state
-					log.debug("could not reassemble cached result set");
-					queryCache.remove(key);
+					log.debug( "could not reassemble cached result set" );
+					cacheRegion.evict( key );
 					return null;
 				}
 				else {
@@ -153,30 +159,26 @@
 
 	protected boolean isUpToDate(Set spaces, Long timestamp) {
 		if ( log.isDebugEnabled() ) {
-			log.debug("Checking query spaces for up-to-dateness: " + spaces);
+			log.debug( "Checking query spaces for up-to-dateness: " + spaces );
 		}
-		return updateTimestampsCache.isUpToDate(spaces, timestamp);
+		return updateTimestampsCache.isUpToDate( spaces, timestamp );
 	}
 
 	public void destroy() {
 		try {
-			queryCache.destroy();
+			cacheRegion.destroy();
 		}
-		catch (Exception e) {
-			log.warn("could not destroy query cache: " + regionName, e);
+		catch ( Exception e ) {
+			log.warn( "could not destroy query cache: " + cacheRegion.getName(), e );
 		}
 	}
-	
-	public Cache getCache() {
-		return queryCache;
+
+	public QueryResultsRegion getRegion() {
+		return cacheRegion;
 	}
-	
-	public String getRegionName() {
-		return regionName;
-	}
-	
+
 	public String toString() {
-		return "StandardQueryCache(" + regionName + ')';
+		return "StandardQueryCache(" + cacheRegion.getName() + ')';
 	}
 
 }

Added: trunk/Hibernate3/src/org/hibernate/cache/TimestampsRegion.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/TimestampsRegion.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/TimestampsRegion.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,10 @@
+package org.hibernate.cache;
+
+/**
+ * Defines the contract for a cache region which will specifically be used to
+ * store entity "update timestamps".
+ *
+ * @author Steve Ebersole
+ */
+public interface TimestampsRegion extends GeneralDataRegion {
+}

Modified: trunk/Hibernate3/src/org/hibernate/cache/TransactionalCache.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/TransactionalCache.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/TransactionalCache.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -6,6 +6,8 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.hibernate.cache.access.SoftLock;
+
 /**
  * Support for fully transactional cache implementations like
  * JBoss TreeCache. Note that this might be a less scalable

Added: trunk/Hibernate3/src/org/hibernate/cache/TransactionalDataRegion.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/TransactionalDataRegion.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/TransactionalDataRegion.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,31 @@
+package org.hibernate.cache;
+
+/**
+ * Defines contract for regions which hold transactionally-managed data.
+ * <p/>
+ * The data is not transactionally managed within the region; merely it is
+ * transactionally-managed in relation to its association with a particular
+ * {@link org.hibernate.Session}.
+ *
+ * @author Steve Ebersole
+ */
+public interface TransactionalDataRegion extends Region {
+	/**
+	 * Is the underlying cache implementation aware of (and "participating in")
+	 * ongoing JTA transactions?
+	 * <p/>
+	 * Regions which report that they are transaction-aware are considered
+	 * "synchronous", in that we assume we can immediately (i.e. synchronously)
+	 * write the changes to the cache and that the cache will properly manage
+	 * application of the written changes within the bounds of ongoing JTA
+	 * transactions.  Conversely, regions reporting false are considered
+	 * "asynchronous", where it is assumed that changes must be manually
+	 * delayed by Hibernate until we are certain that the current transaction
+	 * is successful (i.e. maintaining READ_COMMITTED isolation).
+	 *
+	 * @return True if transaction aware; false otherwise.
+	 */
+	public boolean isTransactionAware();
+
+	public CacheDataDescription getCacheDataDescription();
+}

Modified: trunk/Hibernate3/src/org/hibernate/cache/TreeCacheProvider.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/TreeCacheProvider.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/TreeCacheProvider.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -20,7 +20,7 @@
 public class TreeCacheProvider implements CacheProvider {
 
 	/**
-	 * @deprecated use {@link org.hibernate.cfg.Environment.CACHE_PROVIDER_CONFIG}
+	 * @deprecated use {@link org.hibernate.cfg.Environment#CACHE_PROVIDER_CONFIG}
 	 */
 	public static final String CONFIG_RESOURCE = "hibernate.cache.tree_cache.config";
 	public static final String DEFAULT_CONFIG = "treecache.xml";

Modified: trunk/Hibernate3/src/org/hibernate/cache/UpdateTimestampsCache.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/UpdateTimestampsCache.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/UpdateTimestampsCache.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -23,42 +23,35 @@
  * @author Mikheil Kapanadze
  */
 public class UpdateTimestampsCache {
-
 	public static final String REGION_NAME = UpdateTimestampsCache.class.getName();
+	private static final Log log = LogFactory.getLog( UpdateTimestampsCache.class );
 
-	private static final Log log = LogFactory.getLog(UpdateTimestampsCache.class);
+	private final TimestampsRegion region;
 
-	private Cache updateTimestamps;
-	private final String regionName;
-
-	public void clear() throws CacheException {
-		updateTimestamps.clear();
-	}
-
 	public UpdateTimestampsCache(Settings settings, Properties props) throws HibernateException {
 		String prefix = settings.getCacheRegionPrefix();
-		regionName = prefix == null ? REGION_NAME : prefix + '.' + REGION_NAME;
+		String regionName = prefix == null ? REGION_NAME : prefix + '.' + REGION_NAME;
 		log.info( "starting update timestamps cache at region: " + regionName );
-		this.updateTimestamps = settings.getCacheProvider().buildCache( regionName, props );
+		this.region = settings.getRegionFactory().buildTimestampsRegion( regionName, props );
 	}
 
 	public synchronized void preinvalidate(Serializable[] spaces) throws CacheException {
 		//TODO: to handle concurrent writes correctly, this should return a Lock to the client
-		Long ts = new Long( updateTimestamps.nextTimestamp() + updateTimestamps.getTimeout() );
+		Long ts = new Long( region.nextTimestamp() + region.getTimeout() );
 		for ( int i=0; i<spaces.length; i++ ) {
 			if ( log.isDebugEnabled() ) {
 				log.debug( "Pre-invalidating space [" + spaces[i] + "]" );
 			}
 			//put() has nowait semantics, is this really appropriate?
 			//note that it needs to be async replication, never local or sync
-			updateTimestamps.put( spaces[i], ts );
+			region.put( spaces[i], ts );
 		}
 		//TODO: return new Lock(ts);
 	}
 
 	 public synchronized void invalidate(Serializable[] spaces) throws CacheException {
 	 	//TODO: to handle concurrent writes correctly, the client should pass in a Lock
-		Long ts = new Long( updateTimestamps.nextTimestamp() );
+		Long ts = new Long( region.nextTimestamp() );
 		//TODO: if lock.getTimestamp().equals(ts)
 		for ( int i=0; i<spaces.length; i++ ) {
 			if ( log.isDebugEnabled() ) {
@@ -66,7 +59,7 @@
 			}
 			//put() has nowait semantics, is this really appropriate?
 			//note that it needs to be async replication, never local or sync
-			updateTimestamps.put( spaces[i], ts );
+			region.put( spaces[i], ts );
 		}
 	}
 
@@ -74,7 +67,7 @@
 		Iterator iter = spaces.iterator();
 		while ( iter.hasNext() ) {
 			Serializable space = (Serializable) iter.next();
-			Long lastUpdate = (Long) updateTimestamps.get(space);
+			Long lastUpdate = (Long) region.get(space);
 			if ( lastUpdate==null ) {
 				//the last update timestamp was lost from the cache
 				//(or there were no updates since startup!)
@@ -93,23 +86,23 @@
 		return true;
 	}
 
+	public void clear() throws CacheException {
+		region.evictAll();
+	}
+
 	public void destroy() {
 		try {
-			updateTimestamps.destroy();
+			region.destroy();
 		}
 		catch (Exception e) {
 			log.warn("could not destroy UpdateTimestamps cache", e);
 		}
 	}
 
-	public Cache getCache() {
-		return updateTimestamps;
+	public TimestampsRegion getRegion() {
+		return region;
 	}
 	
-	public String getRegionName() {
-		return regionName;
-	}
-	
 	public String toString() {
 		return "UpdateTimestampeCache";
 	}

Added: trunk/Hibernate3/src/org/hibernate/cache/access/AccessType.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/access/AccessType.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/access/AccessType.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,62 @@
+package org.hibernate.cache.access;
+
+import java.io.Serializable;
+
+/**
+ * The types of access strategies available.
+ *
+ * @author Steve Ebersole
+ */
+public class AccessType implements Serializable {
+	public static final AccessType READ_ONLY = new AccessType( "read-only" );
+	public static final AccessType READ_WRITE = new AccessType( "read-write" );
+	public static final AccessType NONSTRICT_READ_WRITE = new AccessType( "nonstrict-read-write" );
+	public static final AccessType TRANSACTIONAL = new AccessType( "transactional" );
+
+	private final String name;
+
+	private AccessType(String name) {
+		this.name = name;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public String toString() {
+		return "AccessType[" + name + "]";
+	}
+
+	private static AccessType resolve(String name) {
+		if ( READ_ONLY.name.equals( name ) ) {
+			return READ_ONLY;
+		}
+		else if ( READ_WRITE.name.equals( name ) ) {
+			return READ_WRITE;
+		}
+		else if ( NONSTRICT_READ_WRITE.name.equals( name ) ) {
+			return NONSTRICT_READ_WRITE;
+		}
+		else if ( TRANSACTIONAL.name.equals( name ) ) {
+			return TRANSACTIONAL;
+		}
+		else {
+			return null;
+		}
+	}
+
+	public static AccessType parse(String name) {
+		return resolve( name );
+	}
+
+	private Object readResolve() {
+		return resolve( name );
+	}
+
+	public static String getValidUsageString() {
+		return "cache usage attribute should be " + READ_ONLY.name +
+				", " + READ_WRITE.name +
+				", " + NONSTRICT_READ_WRITE.name +
+				", or " + TRANSACTIONAL.name;
+	}
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/access/CollectionRegionAccessStrategy.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/access/CollectionRegionAccessStrategy.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/access/CollectionRegionAccessStrategy.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,156 @@
+package org.hibernate.cache.access;
+
+import java.util.Comparator;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+
+/**
+ * Contract for managing transactional and concurrent access to cached collection
+ * data.  For cached collection data, all modification actions actually just
+ * invalidate the entry(s).  The call sequence here is:
+ * {@link #lockItem} -> {@link #remove} -> {@link #unlockItem}
+ * <p/>
+ * There is another usage pattern that is used to invalidate entries
+ * after performing "bulk" HQL/SQL operations:
+ * {@link #lockRegion} -> {@link #removeAll} -> {@link #unlockRegion}
+ *
+ * @author Gavin King
+ * @author Steve Ebersole
+ */
+public interface CollectionRegionAccessStrategy {
+
+	/**
+	 * Get the wrapped collection cache region
+	 *
+	 * @return The underlying region
+	 */
+	public CollectionRegion getRegion();
+
+	/**
+	 * Attempt to retrieve an object from the cache. Mainly used in attempting
+	 * to resolve entities/collections from the second level cache.
+	 *
+	 * @param key The key of the item to be retrieved.
+	 * @param txTimestamp a timestamp prior to the transaction start time
+	 * @return the cached object or <tt>null</tt>
+	 * @throws org.hibernate.cache.CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public Object get(Object key, long txTimestamp) throws CacheException;
+
+	/**
+	 * Attempt to cache an object, after loading from the database.
+	 *
+	 * @param key The item key
+	 * @param value The item
+	 * @param txTimestamp a timestamp prior to the transaction start time
+	 * @param version the item version number
+	 * @return <tt>true</tt> if the object was successfully cached
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public boolean putFromLoad(
+			Object key,
+			Object value,
+			long txTimestamp,
+			Object version) throws CacheException;
+
+	/**
+	 * Attempt to cache an object, after loading from the database, explicitly
+	 * specifying the minimalPut behavior.
+	 *
+	 * @param key The item key
+	 * @param value The item
+	 * @param txTimestamp a timestamp prior to the transaction start time
+	 * @param version the item version number
+	 * @param minimalPutOverride Explicit minimalPut flag
+	 * @return <tt>true</tt> if the object was successfully cached
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public boolean putFromLoad(
+			Object key,
+			Object value,
+			long txTimestamp,
+			Object version,
+			boolean minimalPutOverride) throws CacheException;
+
+	/**
+	 * We are going to attempt to update/delete the keyed object. This
+	 * method is used by "asynchronous" concurrency strategies.
+	 * <p/>
+	 * The returned object must be passed back to release(), to release the
+	 * lock. Concurrency strategies which do not support client-visible
+	 * locks may silently return null.
+	 *
+	 * @param key The key of the item to lock
+	 * @param version The item's current version value
+	 * @return A representation of our lock on the item; or null.
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public SoftLock lockItem(Object key, Object version) throws CacheException;
+
+	/**
+	 * Lock the entire region
+	 *
+	 * @return A representation of our lock on the item; or null.
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public SoftLock lockRegion() throws CacheException;
+
+	/**
+	 * Called when we have finished the attempted update/delete (which may or
+	 * may not have been successful), after transaction completion.  This method
+	 * is used by "asynchronous" concurrency strategies.
+	 *
+	 * @param key The item key
+	 * @param lock The lock previously obtained from {@link #lockItem}
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void unlockItem(Object key, SoftLock lock) throws CacheException;
+
+	/**
+	 * Called after we have finished the attempted invalidation of the entire
+	 * region
+	 *
+	 * @param lock The lock previously obtained from {@link #lockRegion}
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void unlockRegion(SoftLock lock) throws CacheException;
+
+	/**
+	 * Called after an item has become stale (before the transaction completes).
+	 * This method is used by "synchronous" concurrency strategies.
+	 *
+	 * @param key The key of the item to remove
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void remove(Object key) throws CacheException;
+
+	/**
+	 * Called to evict data from the entire region
+	 *
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void removeAll() throws CacheException;
+
+	/**
+	 * Forcibly evict an item from the cache immediately without regard for transaction
+	 * isolation.
+	 *
+	 * @param key The key of the item to remove
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void evict(Object key) throws CacheException;
+
+	/**
+	 * Forcibly evict all items from the cache immediately without regard for transaction
+	 * isolation.
+	 *
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void evictAll() throws CacheException;
+
+	/**
+	 * Clean up all resources.
+	 */
+	public void destroy();
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/access/EntityRegionAccessStrategy.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/access/EntityRegionAccessStrategy.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/access/EntityRegionAccessStrategy.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,211 @@
+package org.hibernate.cache.access;
+
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.CacheException;
+
+/**
+ * Contract for managing transactional and concurrent access to cached entity
+ * data.  The expected call sequences related to various operations are:<ul>
+ * <li><b>INSERTS</b> : {@link #insert} -> {@link #afterInsert}</li>
+ * <li><b>UPDATES</b> : {@link #lockItem} -> {@link #update} -> {@link #afterUpdate}</li>
+ * <li><b>DELETES</b> : {@link #lockItem} -> {@link #remove} -> {@link #unlockItem}</li>
+ * </ul>
+ * <p/>
+ * There is another usage pattern that is used to invalidate entries
+ * after performing "bulk" HQL/SQL operations:
+ * {@link #lockRegion} -> {@link #removeAll} -> {@link #unlockRegion}
+ *
+ * @author Gavin King
+ * @author Steve Ebersole
+ */
+public interface EntityRegionAccessStrategy {
+
+	/**
+	 * Get the wrapped entity cache region
+	 *
+	 * @return The underlying region
+	 */
+	public EntityRegion getRegion();
+
+	/**
+	 * Attempt to retrieve an object from the cache. Mainly used in attempting
+	 * to resolve entities/collections from the second level cache.
+	 *
+	 * @param key The key of the item to be retrieved.
+	 * @param txTimestamp a timestamp prior to the transaction start time
+	 * @return the cached object or <tt>null</tt>
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public Object get(Object key, long txTimestamp) throws CacheException;
+
+	/**
+	 * Attempt to cache an object, after loading from the database.
+	 *
+	 * @param key The item key
+	 * @param value The item
+	 * @param txTimestamp a timestamp prior to the transaction start time
+	 * @param version the item version number
+	 * @return <tt>true</tt> if the object was successfully cached
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public boolean putFromLoad(
+			Object key,
+			Object value,
+			long txTimestamp,
+			Object version) throws CacheException;
+
+	/**
+	 * Attempt to cache an object, after loading from the database, explicitly
+	 * specifying the minimalPut behavior.
+	 *
+	 * @param key The item key
+	 * @param value The item
+	 * @param txTimestamp a timestamp prior to the transaction start time
+	 * @param version the item version number
+	 * @param minimalPutOverride Explicit minimalPut flag
+	 * @return <tt>true</tt> if the object was successfully cached
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public boolean putFromLoad(
+			Object key,
+			Object value,
+			long txTimestamp,
+			Object version,
+			boolean minimalPutOverride) throws CacheException;
+
+	/**
+	 * We are going to attempt to update/delete the keyed object. This
+	 * method is used by "asynchronous" concurrency strategies.
+	 * <p/>
+	 * The returned object must be passed back to release(), to release the
+	 * lock. Concurrency strategies which do not support client-visible
+	 * locks may silently return null.
+	 *
+	 * @param key The key of the item to lock
+	 * @param version The item's current version value
+	 * @return A representation of our lock on the item; or null.
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public SoftLock lockItem(Object key, Object version) throws CacheException;
+
+	/**
+	 * Lock the entire region
+	 *
+	 * @return A representation of our lock on the item; or null.
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public SoftLock lockRegion() throws CacheException;
+
+	/**
+	 * Called when we have finished the attempted update/delete (which may or
+	 * may not have been successful), after transaction completion.  This method
+	 * is used by "asynchronous" concurrency strategies.
+	 *
+	 * @param key The item key
+	 * @param lock The lock previously obtained from {@link #lockItem}
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void unlockItem(Object key, SoftLock lock) throws CacheException;
+
+	/**
+	 * Called after we have finished the attempted invalidation of the entire
+	 * region
+	 *
+	 * @param lock The lock previously obtained from {@link #lockRegion}
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void unlockRegion(SoftLock lock) throws CacheException;
+
+	/**
+	 * Called after an item has been inserted (before the transaction completes),
+	 * instead of calling evict().
+	 * This method is used by "synchronous" concurrency strategies.
+	 *
+	 * @param key The item key
+	 * @param value The item
+	 * @param version The item's version value
+	 * @return Were the contents of the cache actual changed by this operation?
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public boolean insert(Object key, Object value, Object version) throws CacheException;
+
+	/**
+	 * Called after an item has been inserted (after the transaction completes),
+	 * instead of calling release().
+	 * This method is used by "asynchronous" concurrency strategies.
+	 *
+	 * @param key The item key
+	 * @param value The item
+	 * @param version The item's version value
+	 * @return Were the contents of the cache actual changed by this operation?
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public boolean afterInsert(Object key, Object value, Object version) throws CacheException;
+
+	/**
+	 * Called after an item has been updated (before the transaction completes),
+	 * instead of calling evict(). This method is used by "synchronous" concurrency
+	 * strategies.
+	 *
+	 * @param key The item key
+	 * @param value The item
+	 * @param currentVersion The item's current version value
+	 * @param previousVersion The item's previous version value
+	 * @return Were the contents of the cache actual changed by this operation?
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException;
+
+	/**
+	 * Called after an item has been updated (after the transaction completes),
+	 * instead of calling release().  This method is used by "asynchronous"
+	 * concurrency strategies.
+	 *
+	 * @param key The item key
+	 * @param value The item
+	 * @param currentVersion The item's current version value
+	 * @param previousVersion The item's previous version value
+	 * @param lock The lock previously obtained from {@link #lockItem}
+	 * @return Were the contents of the cache actual changed by this operation?
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException;
+
+	/**
+	 * Called after an item has become stale (before the transaction completes).
+	 * This method is used by "synchronous" concurrency strategies.
+	 *
+	 * @param key The key of the item to remove
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void remove(Object key) throws CacheException;
+
+	/**
+	 * Called to evict data from the entire region
+	 *
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void removeAll() throws CacheException;
+
+	/**
+	 * Forcibly evict an item from the cache immediately without regard for transaction
+	 * isolation.
+	 *
+	 * @param key The key of the item to remove
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void evict(Object key) throws CacheException;
+
+	/**
+	 * Forcibly evict all items from the cache immediately without regard for transaction
+	 * isolation.
+	 *
+	 * @throws CacheException Propogated from underlying {@link org.hibernate.cache.Region}
+	 */
+	public void evictAll() throws CacheException;
+
+	/**
+	 * Clean up all resources.
+	 */
+	public void destroy();
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/access/SoftLock.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/access/SoftLock.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/access/SoftLock.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,10 @@
+package org.hibernate.cache.access;
+
+/**
+ * Moved up from inner definition on the now deprecated
+ * {@link org.hibernate.cache.CacheConcurrencyStrategy}.
+ *
+ * @author Steve Ebersole
+ */
+public interface SoftLock {
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/access/package.html
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/access/package.html	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/access/package.html	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,41 @@
+<html>
+<head></head>
+<body>
+<p>
+	Defines contracts for transactional and concurrent access to cached
+    {@link org.hibernate.cache.access.EntityRegionAccessStrategy entity} and
+    {@link org.hibernate.cache.access.CollectionRegionAccessStrategy collection} data.  Transactions pass in a
+    timestamp indicating transaction start time which is then used to protect against concurrent access (exactly how
+    that occurs is based on the actual access-strategy impl used). Two different implementation patterns are provided
+    for.
+    <ul>
+        <li>
+            A transaction-aware cache implementation might be wrapped by a <i>synchronous</i> access strategy,
+            where updates to the cache are written to the cache inside the transaction.
+        </li>
+        <li>
+            A non-transaction-aware cache would be wrapped by an <i>asynchronous</i> access strategy, where items
+            are merely "soft locked" during the transaction and then updated during the "after transaction completion"
+            phase; the soft lock is not an actual lock on the database row - only upon the cached representation of the
+            item.
+        </li>
+    </ul>
+    The <i>asynchronous</i> access strategies are: {@link org.hibernate.cache.access.AccessType.READ_ONLY read-only},
+    {@link org.hibernate.cache.access.AccessType.READ_WRITE read-write} and
+    {@link org.hibernate.cache.access.AccessType.NONSTRICT_READ_WRITE nonstrict-read-write}.  The only
+    <i>synchronous</i> access strategy is {@link org.hibernate.cache.access.AccessType.TRANSACTIONAL transactional}.
+</p>
+<p>
+    Note that, for an <i>asynchronous</i> cache, cache invalidation must be a two step process (lock->unlock or
+    lock->afterUpdate), since this is the only way to guarantee consistency with the database for a nontransactional
+    cache implementation. For a <i>synchronous</i> cache, cache invalidation is a single step process (evict or update).
+    Hence, these contracts ({@link org.hibernate.cache.access.EntityRegionAcessStrategy} and
+    {@link org.hibernate.cache.access.CollectionRegionAccessStrategy}) define a three step process to cater for both 
+    models (see the individual contracts for details).
+</p>
+<p>
+    Note that query result caching does not go through an access strategy; those caches are managed directly against
+    the underlying {@link org.hibernate.cache.QueryResultsRegion}.
+</p>
+</body>
+</html>

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/CacheDataDescriptionImpl.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/CacheDataDescriptionImpl.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/CacheDataDescriptionImpl.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,53 @@
+package org.hibernate.cache.impl;
+
+import java.util.Comparator;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Collection;
+import org.hibernate.type.VersionType;
+
+/**
+ * {@inheritDoc}
+ *
+ * @author Steve Ebersole
+ */
+public class CacheDataDescriptionImpl implements CacheDataDescription {
+	private final boolean mutable;
+	private final boolean versioned;
+	private final Comparator versionComparator;
+
+	public CacheDataDescriptionImpl(boolean mutable, boolean versioned, Comparator versionComparator) {
+		this.mutable = mutable;
+		this.versioned = versioned;
+		this.versionComparator = versionComparator;
+	}
+
+	public boolean isMutable() {
+		return mutable;
+	}
+
+	public boolean isVersioned() {
+		return versioned;
+	}
+
+	public Comparator getVersionComparator() {
+		return versionComparator;
+	}
+
+	public static CacheDataDescriptionImpl decode(PersistentClass model) {
+		return new CacheDataDescriptionImpl(
+				model.isMutable(),
+				model.isVersioned(),
+				model.isVersioned() ? ( ( VersionType ) model.getVersion().getType() ).getComparator() : null
+		);
+	}
+
+	public static CacheDataDescriptionImpl decode(Collection model) {
+		return new CacheDataDescriptionImpl(
+				model.isMutable(),
+				model.getOwner().isVersioned(),
+				model.getOwner().isVersioned() ? ( ( VersionType ) model.getOwner().getVersion().getType() ).getComparator() : null
+		);
+	}
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/NoCachingRegionFactory.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/NoCachingRegionFactory.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/NoCachingRegionFactory.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,57 @@
+package org.hibernate.cache.impl;
+
+import java.util.Properties;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.TimestampsRegion;
+import org.hibernate.cache.NoCachingEnabledException;
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Factory used if no caching enabled in config...
+ *
+ * @author Steve Ebersole
+ */
+public class NoCachingRegionFactory implements RegionFactory {
+
+
+	public NoCachingRegionFactory(Properties properties) {
+	}
+
+	public void start(Settings settings, Properties properties) throws CacheException {
+	}
+
+	public void stop() {
+	}
+
+	public boolean isMinimalPutsEnabledByDefault() {
+		return false;
+	}
+
+	public long nextTimestamp() {
+		return System.currentTimeMillis() / 100;
+	}
+
+	public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
+			throws CacheException {
+		throw new NoCachingEnabledException();
+	}
+
+	public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata)
+			throws CacheException {
+		throw new NoCachingEnabledException();
+	}
+
+	public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
+		throw new NoCachingEnabledException();
+	}
+
+	public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
+		throw new NoCachingEnabledException();
+	}
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseGeneralDataRegionAdapter.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseGeneralDataRegionAdapter.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseGeneralDataRegionAdapter.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,34 @@
+package org.hibernate.cache.impl.bridge;
+
+import org.hibernate.cache.GeneralDataRegion;
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cfg.Settings;
+
+/**
+ * {@inheritDoc}
+*
+* @author Steve Ebersole
+*/
+public abstract class BaseGeneralDataRegionAdapter extends BaseRegionAdapter implements GeneralDataRegion {
+
+	protected BaseGeneralDataRegionAdapter(Cache underlyingCache, Settings settings) {
+		super( underlyingCache, settings );
+	}
+
+	public Object get(Object key) throws CacheException {
+		return underlyingCache.get( key );
+	}
+
+	public void put(Object key, Object value) throws CacheException {
+		underlyingCache.put( key, value );
+	}
+
+	public void evict(Object key) throws CacheException {
+		underlyingCache.remove( key );
+	}
+
+	public void evictAll() throws CacheException {
+		underlyingCache.clear();
+	}
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseRegionAdapter.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseRegionAdapter.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseRegionAdapter.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,59 @@
+package org.hibernate.cache.impl.bridge;
+
+import java.util.Map;
+
+import org.hibernate.cache.Region;
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Basic adapter bridging between {@link Region} and {@link Cache}.
+ *
+ * @author Steve Ebersole
+ */
+public abstract class BaseRegionAdapter implements Region {
+	protected final Cache underlyingCache;
+	protected final Settings settings;
+
+	protected BaseRegionAdapter(Cache underlyingCache, Settings settings) {
+		this.underlyingCache = underlyingCache;
+		this.settings = settings;
+	}
+
+	public String getName() {
+		return underlyingCache.getRegionName();
+	}
+
+	public void clear() throws CacheException {
+		underlyingCache.clear();
+	}
+
+	public void destroy() throws CacheException {
+		underlyingCache.destroy();
+	}
+
+	public long getSizeInMemory() {
+		return underlyingCache.getSizeInMemory();
+	}
+
+	public long getElementCountInMemory() {
+		return underlyingCache.getElementCountInMemory();
+	}
+
+	public long getElementCountOnDisk() {
+		return underlyingCache.getElementCountOnDisk();
+	}
+
+	public Map toMap() {
+		return underlyingCache.toMap();
+	}
+
+	public long nextTimestamp() {
+		return underlyingCache.nextTimestamp();
+	}
+
+	public int getTimeout() {
+		return underlyingCache.getTimeout();
+	}
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseTransactionalDataRegionAdapter.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseTransactionalDataRegionAdapter.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/BaseTransactionalDataRegionAdapter.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,63 @@
+package org.hibernate.cache.impl.bridge;
+
+import org.hibernate.cache.TransactionalDataRegion;
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cfg.Settings;
+
+/**
+ * {@inheritDoc}
+*
+* @author Steve Ebersole
+*/
+public abstract class BaseTransactionalDataRegionAdapter extends BaseRegionAdapter implements TransactionalDataRegion {
+
+	protected final CacheDataDescription metadata;
+
+	protected BaseTransactionalDataRegionAdapter(Cache underlyingCache, Settings settings, CacheDataDescription metadata) {
+		super( underlyingCache, settings );
+		this.metadata = metadata;
+	}
+
+	public boolean isTransactionAware() {
+		return underlyingCache instanceof org.hibernate.cache.TreeCache
+				|| underlyingCache instanceof org.hibernate.cache.OptimisticTreeCache;
+	}
+
+	public CacheDataDescription getCacheDataDescription() {
+		return metadata;
+	}
+
+//		public void lock() throws CacheException {
+//			// impl note: unfortunately this was not a capability of the original Cache contract
+//		}
+//
+//		public void unlock() throws CacheException {
+//			// impl note: unfortunately this was not a capability of the original Cache contract
+//		}
+//
+//		public void lock(Object key) throws CacheException {
+//			underlyingCache.lock( key );
+//		}
+//
+//		public void unlock(Object key) throws CacheException {
+//			underlyingCache.unlock( key );
+//		}
+//
+//		public Object get(Object key) throws CacheException {
+//			return underlyingCache.get( key );
+//		}
+//
+//		public Object read(Object key) throws CacheException {
+//			return underlyingCache.read( key );
+//		}
+//
+//		public void writeLoad(Object key, Object value, Object version) throws CacheException {
+//			if ( underlyingCache instanceof OptimisticCache ) {
+//				( ( OptimisticCache ) underlyingCache ).writeLoad( key, value, version );
+//			}
+//			else {
+//				underlyingCache.put( key, value );
+//			}
+//		}
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/CollectionAccessStrategyAdapter.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/CollectionAccessStrategyAdapter.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/CollectionAccessStrategyAdapter.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,91 @@
+package org.hibernate.cache.impl.bridge;
+
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.CacheConcurrencyStrategy;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Adapter specifically bridging {@link CollectionRegionAccessStrategy} to {@link CacheConcurrencyStrategy}.
+ *
+ * @author Steve Ebersole
+ */
+public class CollectionAccessStrategyAdapter implements CollectionRegionAccessStrategy {
+	private final CollectionRegion region;
+	private final CacheConcurrencyStrategy ccs;
+	private final Settings settings;
+
+	public CollectionAccessStrategyAdapter(CollectionRegion region, CacheConcurrencyStrategy ccs, Settings settings) {
+		this.region = region;
+		this.ccs = ccs;
+		this.settings = settings;
+	}
+
+	public CollectionRegion getRegion() {
+		return region;
+	}
+
+	public Object get(Object key, long txTimestamp) throws CacheException {
+		return ccs.get( key, txTimestamp );
+	}
+
+	public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+		return putFromLoad( key, value, txTimestamp, version, settings.isMinimalPutsEnabled() );
+	}
+
+	public boolean putFromLoad(
+			Object key, 
+			Object value,
+			long txTimestamp,
+			Object version,
+			boolean minimalPutOverride) throws CacheException {
+		return ccs.put( key, value, txTimestamp, version, region.getCacheDataDescription().getVersionComparator(), minimalPutOverride );
+	}
+
+	public SoftLock lockItem(Object key, Object version) throws CacheException {
+		return ccs.lock( key, version );
+	}
+
+	public SoftLock lockRegion() throws CacheException {
+		// no-op; CCS did not have such a concept
+		return null;
+	}
+
+	public void unlockItem(Object key, SoftLock lock) throws CacheException {
+		ccs.release( key, lock );
+	}
+
+	public void unlockRegion(SoftLock lock) throws CacheException {
+		// again, CCS did not have such a concept; but a reasonable
+		// proximity is to clear the cache after transaction *as long as*
+		// the underlying cache is not JTA aware.
+		if ( !region.isTransactionAware() ) {
+			ccs.clear();
+		}
+	}
+
+	public void remove(Object key) throws CacheException {
+		ccs.evict( key );
+	}
+
+	public void removeAll() throws CacheException {
+		// again, CCS did not have such a concept; however a reasonable
+		// proximity is to clear the cache.  For non-transaction aware
+		// caches, we will also do a clear at the end of the transaction
+		ccs.clear();
+	}
+
+	public void evict(Object key) throws CacheException {
+		ccs.remove( key );
+	}
+
+	public void evictAll() throws CacheException {
+		ccs.clear();
+	}
+
+	public void destroy() {
+		ccs.destroy();
+	}
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/CollectionRegionAdapter.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/CollectionRegionAdapter.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/CollectionRegionAdapter.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,58 @@
+package org.hibernate.cache.impl.bridge;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.OptimisticCache;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CacheConcurrencyStrategy;
+import org.hibernate.cache.TransactionalCache;
+import org.hibernate.cache.ReadWriteCache;
+import org.hibernate.cache.NonstrictReadWriteCache;
+import org.hibernate.cache.ReadOnlyCache;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Adapter specifically bridging {@link CollectionRegion} to {@link Cache}.
+ *
+ * @author Steve Ebersole
+ */
+public class CollectionRegionAdapter extends BaseTransactionalDataRegionAdapter implements CollectionRegion {
+	private static final Log log = LogFactory.getLog( CollectionRegionAdapter.class );
+
+	public CollectionRegionAdapter(Cache underlyingCache, Settings settings, CacheDataDescription metadata) {
+		super( underlyingCache, settings, metadata );
+		if ( underlyingCache instanceof OptimisticCache ) {
+			( ( OptimisticCache ) underlyingCache ).setSource( new OptimisticCacheSourceAdapter( metadata ) );
+		}
+	}
+
+	public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
+		CacheConcurrencyStrategy ccs;
+		if ( AccessType.READ_ONLY.equals( accessType ) ) {
+			if ( metadata.isMutable() ) {
+				log.warn( "read-only cache configured for mutable collection [" + getName() + "]" );
+			}
+			ccs = new ReadOnlyCache();
+		}
+		else if ( AccessType.READ_WRITE.equals( accessType ) ) {
+			ccs = new ReadWriteCache();
+		}
+		else if ( AccessType.NONSTRICT_READ_WRITE.equals( accessType ) ) {
+			ccs = new NonstrictReadWriteCache();
+		}
+		else if ( AccessType.TRANSACTIONAL.equals( accessType ) ) {
+			ccs = new TransactionalCache();
+		}
+		else {
+			throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" );
+		}
+		ccs.setCache( underlyingCache );
+		return new CollectionAccessStrategyAdapter( this, ccs, settings );
+	}
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/EntityAccessStrategyAdapter.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/EntityAccessStrategyAdapter.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/EntityAccessStrategyAdapter.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,109 @@
+package org.hibernate.cache.impl.bridge;
+
+import org.hibernate.cache.CacheConcurrencyStrategy;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Adapter specifically bridging {@link EntityRegionAccessStrategy} to {@link CacheConcurrencyStrategy}.
+ *
+ * @author Steve Ebersole
+ */
+public class EntityAccessStrategyAdapter implements EntityRegionAccessStrategy {
+	private final EntityRegion region;
+	private final CacheConcurrencyStrategy ccs;
+	private final Settings settings;
+
+	public EntityAccessStrategyAdapter(EntityRegion region, CacheConcurrencyStrategy ccs, Settings settings) {
+		this.region = region;
+		this.ccs = ccs;
+		this.settings = settings;
+	}
+
+	public EntityRegion getRegion() {
+		return region;
+	}
+
+	public Object get(Object key, long txTimestamp) throws CacheException {
+		return ccs.get( key, txTimestamp );
+	}
+
+	public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+		return putFromLoad( key, value, txTimestamp, version, settings.isMinimalPutsEnabled() );
+	}
+
+	public boolean putFromLoad(
+			Object key,
+			Object value,
+			long txTimestamp,
+			Object version,
+			boolean minimalPutOverride) throws CacheException {
+		return ccs.put( key, value, txTimestamp, version, region.getCacheDataDescription().getVersionComparator(), minimalPutOverride );
+	}
+
+	public SoftLock lockItem(Object key, Object version) throws CacheException {
+		return ccs.lock( key, version );
+	}
+
+	public SoftLock lockRegion() throws CacheException {
+		// no-op; CCS did not have such a concept
+		return null;
+	}
+
+	public void unlockItem(Object key, SoftLock lock) throws CacheException {
+		ccs.release( key, lock );
+	}
+
+	public void unlockRegion(SoftLock lock) throws CacheException {
+		// again, CCS did not have such a concept; but a reasonable
+		// proximity is to clear the cache after transaction *as long as*
+		// the underlying cache is not JTA aware.
+		if ( !region.isTransactionAware() ) {
+			ccs.clear();
+		}
+	}
+
+	public boolean insert(Object key, Object value, Object version) throws CacheException {
+		return ccs.insert( key, value, version );
+	}
+
+	public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
+		return ccs.afterInsert( key, value, version );
+	}
+
+	public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
+			throws CacheException {
+		return ccs.update( key, value, currentVersion, previousVersion );
+	}
+
+	public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
+			throws CacheException {
+		return ccs.afterUpdate( key, value, currentVersion, lock );
+	}
+
+	public void remove(Object key) throws CacheException {
+		ccs.evict( key );
+	}
+
+	public void removeAll() throws CacheException {
+		// again, CCS did not have such a concept; however a reasonable
+		// proximity is to clear the cache.  For non-transaction aware
+		// caches, we will also do a clear at the end of the transaction
+		ccs.clear();
+	}
+
+	public void evict(Object key) throws CacheException {
+		ccs.remove( key );
+	}
+
+	public void evictAll() throws CacheException {
+		ccs.clear();
+	}
+
+	public void destroy() {
+		ccs.destroy();
+	}
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/EntityRegionAdapter.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/EntityRegionAdapter.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/EntityRegionAdapter.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,59 @@
+package org.hibernate.cache.impl.bridge;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.OptimisticCache;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CacheConcurrencyStrategy;
+import org.hibernate.cache.ReadOnlyCache;
+import org.hibernate.cache.ReadWriteCache;
+import org.hibernate.cache.NonstrictReadWriteCache;
+import org.hibernate.cache.TransactionalCache;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Adapter specifically bridging {@link EntityRegion} to {@link Cache}.
+ *
+ * @author Steve Ebersole
+ */
+public class EntityRegionAdapter extends BaseTransactionalDataRegionAdapter implements EntityRegion {
+	private static final Log log = LogFactory.getLog( EntityRegionAdapter.class );
+
+	public EntityRegionAdapter(Cache underlyingCache, Settings settings, CacheDataDescription metadata) {
+		super( underlyingCache, settings, metadata );
+		if ( underlyingCache instanceof OptimisticCache ) {
+			( ( OptimisticCache ) underlyingCache ).setSource( new OptimisticCacheSourceAdapter( metadata ) );
+		}
+	}
+
+	public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
+		CacheConcurrencyStrategy ccs;
+		if ( AccessType.READ_ONLY.equals( accessType ) ) {
+			if ( metadata.isMutable() ) {
+				log.warn( "read-only cache configured for mutable entity [" + getName() + "]" );
+			}
+			ccs = new ReadOnlyCache();
+		}
+		else if ( AccessType.READ_WRITE.equals( accessType ) ) {
+			ccs = new ReadWriteCache();
+		}
+		else if ( AccessType.NONSTRICT_READ_WRITE.equals( accessType ) ) {
+			ccs = new NonstrictReadWriteCache();
+		}
+		else if ( AccessType.TRANSACTIONAL.equals( accessType ) ) {
+			ccs = new TransactionalCache();
+		}
+		else {
+			throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" );
+		}
+		ccs.setCache( underlyingCache );
+		return new EntityAccessStrategyAdapter( this, ccs, settings );
+	}
+
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/OptimisticCacheSourceAdapter.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/OptimisticCacheSourceAdapter.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/OptimisticCacheSourceAdapter.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,27 @@
+package org.hibernate.cache.impl.bridge;
+
+import java.util.Comparator;
+
+import org.hibernate.cache.OptimisticCacheSource;
+import org.hibernate.cache.CacheDataDescription;
+
+/**
+ * {@inheritDoc}
+*
+* @author Steve Ebersole
+*/
+public class OptimisticCacheSourceAdapter implements OptimisticCacheSource {
+	private final CacheDataDescription dataDescription;
+
+	public OptimisticCacheSourceAdapter(CacheDataDescription dataDescription) {
+		this.dataDescription = dataDescription;
+	}
+
+	public boolean isVersioned() {
+		return dataDescription.isVersioned();
+	}
+
+	public Comparator getVersionComparator() {
+		return dataDescription.getVersionComparator();
+	}
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/QueryResultsRegionAdapter.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/QueryResultsRegionAdapter.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/QueryResultsRegionAdapter.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,16 @@
+package org.hibernate.cache.impl.bridge;
+
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.Cache;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Adapter specifically briding {@link QueryResultsRegion} to {@link Cache}.
+*
+* @author Steve Ebersole
+ */
+public class QueryResultsRegionAdapter extends BaseGeneralDataRegionAdapter implements QueryResultsRegion {
+	protected QueryResultsRegionAdapter(Cache underlyingCache, Settings settings) {
+		super( underlyingCache, settings );
+	}
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/RegionFactoryCacheProviderBridge.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/RegionFactoryCacheProviderBridge.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/RegionFactoryCacheProviderBridge.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,91 @@
+package org.hibernate.cache.impl.bridge;
+
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.CacheProvider;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.NoCacheProvider;
+import org.hibernate.cache.TimestampsRegion;
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.util.PropertiesHelper;
+import org.hibernate.util.ReflectHelper;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Acts as a bridge between the {@link RegionFactory} contract and the older
+ * {@link CacheProvider} contract.
+ *
+ * @author Steve Ebersole
+ */
+public class RegionFactoryCacheProviderBridge implements RegionFactory {
+	public static final String DEF_PROVIDER = NoCacheProvider.class.getName();
+	private static final Log log = LogFactory.getLog( RegionFactoryCacheProviderBridge.class );
+
+	private CacheProvider cacheProvider;
+	private Settings settings;
+
+	public RegionFactoryCacheProviderBridge(Properties properties) {
+		String providerClassName = PropertiesHelper.getString( Environment.CACHE_PROVIDER, properties, DEF_PROVIDER );
+		log.info( "Cache provider: " + providerClassName );
+		try {
+			cacheProvider = ( CacheProvider ) ReflectHelper.classForName( providerClassName ).newInstance();
+		}
+		catch ( Exception cnfe ) {
+			throw new CacheException( "could not instantiate CacheProvider [" + providerClassName + "]", cnfe );
+		}
+	}
+
+	public void start(Settings settings, Properties properties) throws CacheException {
+		this.settings = settings;
+		cacheProvider.start( properties );
+	}
+
+	public void stop() {
+		cacheProvider.stop();
+		cacheProvider = null;
+	}
+
+	public boolean isMinimalPutsEnabledByDefault() {
+		return cacheProvider.isMinimalPutsEnabledByDefault();
+	}
+
+	public long nextTimestamp() {
+		return cacheProvider.nextTimestamp();
+	}
+
+	public CacheProvider getCacheProvider() {
+		return cacheProvider;
+	}
+
+	public EntityRegion buildEntityRegion(
+			String regionName,
+			Properties properties,
+			CacheDataDescription metadata) throws CacheException {
+		return new EntityRegionAdapter( cacheProvider.buildCache( regionName, properties ), settings, metadata );
+	}
+
+	public CollectionRegion buildCollectionRegion(
+			String regionName,
+			Properties properties,
+			CacheDataDescription metadata) throws CacheException {
+		return new CollectionRegionAdapter( cacheProvider.buildCache( regionName, properties ), settings, metadata );
+	}
+
+	public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
+		return new QueryResultsRegionAdapter( cacheProvider.buildCache( regionName, properties ), settings );
+	}
+
+	public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
+		return new TimestampsRegionAdapter( cacheProvider.buildCache( regionName, properties ), settings );
+	}
+
+
+}

Added: trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/TimestampsRegionAdapter.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/TimestampsRegionAdapter.java	                        (rev 0)
+++ trunk/Hibernate3/src/org/hibernate/cache/impl/bridge/TimestampsRegionAdapter.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -0,0 +1,16 @@
+package org.hibernate.cache.impl.bridge;
+
+import org.hibernate.cache.TimestampsRegion;
+import org.hibernate.cache.Cache;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Adapter specifically briding {@link TimestampsRegion} to {@link Cache}.
+*
+* @author Steve Ebersole
+ */
+public class TimestampsRegionAdapter extends BaseGeneralDataRegionAdapter implements TimestampsRegion {
+	protected TimestampsRegionAdapter(Cache underlyingCache, Settings settings) {
+		super( underlyingCache, settings );
+	}
+}

Modified: trunk/Hibernate3/src/org/hibernate/cache/package.html
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cache/package.html	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cache/package.html	2007-04-10 14:54:07 UTC (rev 11398)
@@ -1,16 +1,36 @@
 <html>
-<head>
-</head>
-<body>
-<p>
-	This package defines APIs and implementations for the
-	second-level cache and query cache.
-</p>
-<p>
-	<tt>Cache</tt> abstracts the underlying cache implementation.
-	<tt>CacheConcurrencyStrategy</tt> abstracts various strategies
-	for maintaining consistency between the cache and database.
-	<tt>QueryCache</tt> abstracts the query result set cache.
-</p>
-</body>
+    <head>
+    </head>
+
+    <body>
+        <p>
+            This package defines APIs/SPIs and implementations for the Hibernate second-level cache.
+        </p>
+        <p>
+            The legacy (and now deprecated) approach to caching is defined by the {@link org.hibernate.cache.CacheProvider} and
+            {@link org.hibernate.cache.Cache} interfaces as well as the {@link org.hibernate.cache.CacheConcurrencyStrategy}
+            interface along with the various implementations of all these interfaces.  In that scheme, a
+            {@link org.hibernate.cache.CacheProvider} defined how to configure and perform lifecycle operations
+            in regards to a particular underlying caching library; it also defined how to build {@link org.hibernate.cache.Cache}
+            instances which in turn defined how to access the "regions" of the underlying cache instance.
+            For entity and collection data cache regions, {@link org.hibernate.cache.CacheConcurrencyStrategy} wrapped
+            access to those cache regions to apply transactional/concurrent access semantics.
+        </p>
+        <p>
+            The improved approach is based on {@link org.hibernate.cache.RegionFactory}, the various
+            {@link org.hibernate.cache.Region} specializations and the two access strategies contracts
+            ({@link org.hibernate.cache.access.EntityRegionAccessStrategy} and
+            {@link org.hibernate.cache.access.CollectionRegionAccessStrategy}).  The general approach here is that
+            {@link org.hibernate.cache.RegionFactory} defined how to configure and perform lifecycle operations
+            in regards to a particular underlying caching library (<b>or libraries</b>).
+            {@link org.hibernate.cache.RegionFactory} also defines how to build specialized
+            {@link org.hibernate.cache.Region} instances based on the type of data we will be storing in that given
+            region.  The fact that {@link org.hibernate.cache.RegionFactory} is asked to build <b>specialized</b>
+            regions (as opposed to just general access) is the first <i>improvement</i> over the legacy scheme.  The
+            second <i>improvement</i> is the fact that the regions (well the ones like entity and collection regions
+            that are responsible for storing {@link org.hibernate.cache.TransactionalDataRegion transactional} data) are
+            asked to build their own access strategies (see {@link org.hibernate.cache.EntityRegion#buildAccessStrategy}
+            and {@link org.hibernate.cache.CollectionRegion#buildAccessStrategy}).
+        </p>
+    </body>
 </html>

Modified: trunk/Hibernate3/src/org/hibernate/cfg/Environment.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cfg/Environment.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cfg/Environment.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -365,7 +365,13 @@
 	 * The <tt>CacheProvider</tt> implementation class
 	 */
 	public static final String CACHE_PROVIDER = "hibernate.cache.provider_class";
+
 	/**
+	 * The {@link org.hibernate.cache.RegionFactory} implementation class
+	 */
+	public static final String CACHE_REGION_FACTORY = "hibernate.cache.region.factory_class";
+
+	/**
 	 * The <tt>CacheProvider</tt> implementation class
 	 */
 	public static final String CACHE_PROVIDER_CONFIG = "hibernate.cache.provider_configuration_file_resource_path";

Modified: trunk/Hibernate3/src/org/hibernate/cfg/Settings.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cfg/Settings.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cfg/Settings.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -3,8 +3,8 @@
 
 import java.util.Map;
 
-import org.hibernate.cache.CacheProvider;
 import org.hibernate.cache.QueryCacheFactory;
+import org.hibernate.cache.RegionFactory;
 import org.hibernate.connection.ConnectionProvider;
 import org.hibernate.dialect.Dialect;
 import org.hibernate.hql.QueryTranslatorFactory;
@@ -51,7 +51,7 @@
 	private boolean flushBeforeCompletionEnabled;
 	private boolean autoCloseSessionEnabled;
 	private ConnectionReleaseMode connectionReleaseMode;
-	private CacheProvider cacheProvider;
+	private RegionFactory regionFactory;
 	private QueryCacheFactory queryCacheFactory;
 	private ConnectionProvider connectionProvider;
 	private TransactionFactory transactionFactory;
@@ -156,8 +156,8 @@
 		return maximumFetchDepth;
 	}
 
-	public CacheProvider getCacheProvider() {
-		return cacheProvider;
+	public RegionFactory getRegionFactory() {
+		return regionFactory;
 	}
 
 	public TransactionManagerLookup getTransactionManagerLookup() {
@@ -335,8 +335,8 @@
 		maximumFetchDepth = i;
 	}
 
-	void setCacheProvider(CacheProvider cacheProvider) {
-		this.cacheProvider = cacheProvider;
+	void setRegionFactory(RegionFactory regionFactory) {
+		this.regionFactory = regionFactory;
 	}
 
 	void setTransactionManagerLookup(TransactionManagerLookup lookup) {

Modified: trunk/Hibernate3/src/org/hibernate/cfg/SettingsFactory.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/cfg/SettingsFactory.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/cfg/SettingsFactory.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -16,9 +16,10 @@
 import org.hibernate.EntityMode;
 import org.hibernate.HibernateException;
 import org.hibernate.bytecode.BytecodeProvider;
-import org.hibernate.cache.CacheProvider;
-import org.hibernate.cache.NoCacheProvider;
 import org.hibernate.cache.QueryCacheFactory;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.impl.NoCachingRegionFactory;
+import org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge;
 import org.hibernate.connection.ConnectionProvider;
 import org.hibernate.connection.ConnectionProviderFactory;
 import org.hibernate.dialect.Dialect;
@@ -43,11 +44,12 @@
  * @author Gavin King
  */
 public class SettingsFactory implements Serializable {
-	
+
+	public static final String DEF_CACHE_REG_FACTORY = NoCachingRegionFactory.class.getName();
 	private static final Log log = LogFactory.getLog(SettingsFactory.class);
-	public static final String DEF_CACHE_PROVIDER = NoCacheProvider.class.getName();
 
-	protected SettingsFactory() throws HibernateException {}
+	protected SettingsFactory() {
+	}
 	
 	public Settings buildSettings(Properties props) {
 		Settings settings = new Settings();
@@ -235,17 +237,12 @@
 		log.info( "Query cache: " + enabledDisabled(useQueryCache) );
 		settings.setQueryCacheEnabled(useQueryCache);
 
-		if ( useSecondLevelCache || useQueryCache ) {
-			// The cache provider is needed when we either have second-level cache enabled
-			// or query cache enabled.  Note that useSecondLevelCache is enabled by default
-			settings.setCacheProvider( createCacheProvider( properties ) );
-		}
-		else {
-			settings.setCacheProvider( new NoCacheProvider() );
-		}
+		// The cache provider is needed when we either have second-level cache enabled
+		// or query cache enabled.  Note that useSecondLevelCache is enabled by default
+		settings.setRegionFactory( createRegionFactory( properties, ( useSecondLevelCache || useQueryCache ) ) );
 
 		boolean useMinimalPuts = PropertiesHelper.getBoolean(
-				Environment.USE_MINIMAL_PUTS, properties, settings.getCacheProvider().isMinimalPutsEnabledByDefault() 
+				Environment.USE_MINIMAL_PUTS, properties, settings.getRegionFactory().isMinimalPutsEnabledByDefault()
 		);
 		log.info( "Optimize cache for minimal puts: " + enabledDisabled(useMinimalPuts) );
 		settings.setMinimalPutsEnabled(useMinimalPuts);
@@ -362,16 +359,26 @@
 		}
 	}
 
-	protected CacheProvider createCacheProvider(Properties properties) {
-		String cacheClassName = PropertiesHelper.getString(
-				Environment.CACHE_PROVIDER, properties, DEF_CACHE_PROVIDER
-		);
-		log.info("Cache provider: " + cacheClassName);
+	protected RegionFactory createRegionFactory(Properties properties, boolean cachingEnabled) {
+		String regionFactoryClassName = PropertiesHelper.getString( Environment.CACHE_REGION_FACTORY, properties, null );
+		if ( regionFactoryClassName == null && cachingEnabled ) {
+			String providerClassName = PropertiesHelper.getString( Environment.CACHE_PROVIDER, properties, null );
+			if ( providerClassName != null ) {
+				// legacy behavior, apply the bridge...
+				regionFactoryClassName = RegionFactoryCacheProviderBridge.class.getName();
+			}
+		}
+		if ( regionFactoryClassName == null ) {
+			regionFactoryClassName = DEF_CACHE_REG_FACTORY;
+		}
+		log.info( "Cache region factory : " + regionFactoryClassName );
 		try {
-			return (CacheProvider) ReflectHelper.classForName(cacheClassName).newInstance();
+			return ( RegionFactory ) ReflectHelper.classForName( regionFactoryClassName )
+					.getConstructor( new Class[] { Properties.class } )
+					.newInstance( new Object[] { properties } );
 		}
-		catch (Exception cnfe) {
-			throw new HibernateException("could not instantiate CacheProvider: " + cacheClassName, cnfe);
+		catch ( Exception e ) {
+			throw new HibernateException( "could not instantiate RegionFactory [" + regionFactoryClassName + "]", e );
 		}
 	}
 	

Modified: trunk/Hibernate3/src/org/hibernate/engine/BatchFetchQueue.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/engine/BatchFetchQueue.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/engine/BatchFetchQueue.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -252,7 +252,7 @@
 					entityMode,
 					context.getSession().getFactory()
 			);
-			return persister.getCache().getCache().get( key ) != null;
+			return persister.getCacheAccessStrategy().get( key, context.getSession().getTimestamp() ) != null;
 		}
 		return false;
 	}
@@ -269,7 +269,7 @@
 			        entityMode,
 			        context.getSession().getFactory()
 			);
-			return persister.getCache().getCache().get( cacheKey ) != null;
+			return persister.getCacheAccessStrategy().get( cacheKey, context.getSession().getTimestamp() ) != null;
 		}
 		return false;
 	}

Modified: trunk/Hibernate3/src/org/hibernate/engine/Mapping.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/engine/Mapping.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/engine/Mapping.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -19,10 +19,3 @@
 	public String getIdentifierPropertyName(String className) throws MappingException;
 	public Type getReferencedPropertyType(String className, String propertyName) throws MappingException;
 }
-
-
-
-
-
-
-

Modified: trunk/Hibernate3/src/org/hibernate/engine/SessionFactoryImplementor.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/engine/SessionFactoryImplementor.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/engine/SessionFactoryImplementor.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -16,9 +16,9 @@
 import org.hibernate.engine.query.QueryPlanCache;
 import org.hibernate.persister.collection.CollectionPersister;
 import org.hibernate.persister.entity.EntityPersister;
-import org.hibernate.cache.Cache;
 import org.hibernate.cache.QueryCache;
 import org.hibernate.cache.UpdateTimestampsCache;
+import org.hibernate.cache.Region;
 import org.hibernate.cfg.Settings;
 import org.hibernate.connection.ConnectionProvider;
 import org.hibernate.dialect.Dialect;
@@ -40,18 +40,37 @@
 
 	/**
 	 * Get the persister for the named entity
+	 *
+	 * @param entityName The name of the entity for which to retrieve the persister.
+	 * @return The persister
+	 * @throws MappingException Indicates persister could not be found with that name.
 	 */
 	public EntityPersister getEntityPersister(String entityName) throws MappingException;
+
 	/**
-	 * Get the persister object for a collection role
+	 * Get the persister object for a collection role.
+	 *
+	 * @param role The role (name) of the collection for which to retrieve the
+	 * persister.
+	 * @return The persister
+	 * @throws MappingException Indicates persister could not be found with that role.
 	 */
 	public CollectionPersister getCollectionPersister(String role) throws MappingException;
 
 	/**
-	 * Get the SQL <tt>Dialect</tt>
+	 * Get the SQL dialect.
+	 * <p/>
+	 * Shorthand for {@link #getSettings()}.{@link Settings#getDialect()}
+	 *
+	 * @return The dialect
 	 */
 	public Dialect getDialect();
-	
+
+	/**
+	 * Get the factory scoped interceptor for this factory.
+	 *
+	 * @return The factory scope interceptor, or null if none.
+	 */
 	public Interceptor getInterceptor();
 
 	public QueryPlanCache getQueryPlanCache();
@@ -117,9 +136,19 @@
 	
 	/**
 	 * Get a named second-level cache region
+	 *
+	 * @param regionName The name of the region to retrieve.
+	 * @return The region
 	 */
-	public Cache getSecondLevelCacheRegion(String regionName);
-	
+	public Region getSecondLevelCacheRegion(String regionName);
+
+	/**
+	 * Get a map of all the second level cache regions currently maintained in
+	 * this session factory.  The map is structured with the region name as the
+	 * key and the {@link Region} instances as the values.
+	 *
+	 * @return The map of regions
+	 */
 	public Map getAllSecondLevelCacheRegions();
 	
 	/**

Modified: trunk/Hibernate3/src/org/hibernate/engine/TwoPhaseLoad.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/engine/TwoPhaseLoad.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/engine/TwoPhaseLoad.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -145,27 +145,24 @@
 					version, 
 					session, 
 					entity
-				);
+			);
 			CacheKey cacheKey = new CacheKey( 
 					id, 
 					persister.getIdentifierType(), 
 					persister.getRootEntityName(), 
 					session.getEntityMode(), 
 					session.getFactory() 
-				);
-			boolean put = persister.getCache().put( 
-					cacheKey, 
-					persister.getCacheEntryStructure().structure(entry), 
+			);
+			boolean put = persister.getCacheAccessStrategy().putFromLoad(
+					cacheKey,
+					persister.getCacheEntryStructure().structure( entry ),
 					session.getTimestamp(),
-					version, 
-					persister.isVersioned() ?
-							persister.getVersionType().getComparator() : 
-							null,
-					useMinimalPuts(session, entityEntry)
-				); //we could use persister.hasLazyProperties() instead of true
-	
+					version,
+					useMinimalPuts( session, entityEntry )
+			);
+
 			if ( put && factory.getStatistics().isStatisticsEnabled() ) {
-				factory.getStatisticsImplementor().secondLevelCachePut( persister.getCache().getRegionName() );
+				factory.getStatisticsImplementor().secondLevelCachePut( persister.getCacheAccessStrategy().getRegion().getName() );
 			}
 		}
 	

Modified: trunk/Hibernate3/src/org/hibernate/engine/loading/CollectionLoadContext.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/engine/loading/CollectionLoadContext.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/engine/loading/CollectionLoadContext.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -7,7 +7,6 @@
 import java.util.List;
 import java.util.Iterator;
 import java.util.ArrayList;
-import java.util.Comparator;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -284,16 +283,13 @@
 			return; // EARLY EXIT!!!!!
 		}
 
-		final Comparator versionComparator;
 		final Object version;
 		if ( persister.isVersioned() ) {
-			versionComparator = persister.getOwnerEntityPersister().getVersionType().getComparator();
 			final Object collectionOwner = getLoadContext().getPersistenceContext().getCollectionOwner( lce.getKey(), persister );
 			version = getLoadContext().getPersistenceContext().getEntry( collectionOwner ).getVersion();
 		}
 		else {
 			version = null;
-			versionComparator = null;
 		}
 
 		CollectionCacheEntry entry = new CollectionCacheEntry( lce.getCollection(), persister );
@@ -304,17 +300,16 @@
 				session.getEntityMode(),
 				session.getFactory()
 		);
-		boolean put = persister.getCache().put(
+		boolean put = persister.getCacheAccessStrategy().putFromLoad(
 				cacheKey,
 				persister.getCacheEntryStructure().structure(entry),
 				session.getTimestamp(),
 				version,
-				versionComparator,
-				factory.getSettings().isMinimalPutsEnabled() && session.getCacheMode()!= CacheMode.REFRESH
+				( factory.getSettings().isMinimalPutsEnabled() && session.getCacheMode()!= CacheMode.REFRESH )
 		);
 
 		if ( put && factory.getStatistics().isStatisticsEnabled() ) {
-			factory.getStatisticsImplementor().secondLevelCachePut( persister.getCache().getRegionName() );
+			factory.getStatisticsImplementor().secondLevelCachePut( persister.getCacheAccessStrategy().getRegion().getName() );
 		}
 	}
 

Modified: trunk/Hibernate3/src/org/hibernate/event/def/AbstractLockUpgradeEventListener.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/AbstractLockUpgradeEventListener.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/event/def/AbstractLockUpgradeEventListener.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -4,11 +4,10 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import org.hibernate.HibernateException;
 import org.hibernate.LockMode;
 import org.hibernate.ObjectDeletedException;
-import org.hibernate.cache.CacheConcurrencyStrategy;
 import org.hibernate.cache.CacheKey;
+import org.hibernate.cache.access.SoftLock;
 import org.hibernate.engine.EntityEntry;
 import org.hibernate.engine.Status;
 import org.hibernate.engine.SessionImplementor;
@@ -32,10 +31,8 @@
 	 * @param entry The entity's EntityEntry instance.
 	 * @param requestedLockMode The lock mode being requested for locking.
 	 * @param source The session which is the source of the event being processed.
-	 * @throws HibernateException
 	 */
-	protected void upgradeLock(Object object, EntityEntry entry, LockMode requestedLockMode, SessionImplementor source)
-	throws HibernateException {
+	protected void upgradeLock(Object object, EntityEntry entry, LockMode requestedLockMode, SessionImplementor source) {
 
 		if ( requestedLockMode.greaterThan( entry.getLockMode() ) ) {
 			// The user requested a "greater" (i.e. more restrictive) form of
@@ -59,7 +56,7 @@
 						requestedLockMode
 				);
 
-			final CacheConcurrencyStrategy.SoftLock lock;
+			final SoftLock lock;
 			final CacheKey ck;
 			if ( persister.hasCache() ) {
 				ck = new CacheKey( 
@@ -69,7 +66,7 @@
 						source.getEntityMode(), 
 						source.getFactory() 
 				);
-				lock = persister.getCache().lock( ck, entry.getVersion() );
+				lock = persister.getCacheAccessStrategy().lockItem( ck, entry.getVersion() );
 			}
 			else {
 				ck = null;
@@ -93,7 +90,7 @@
 				// the database now holds a lock + the object is flushed from the cache,
 				// so release the soft lock
 				if ( persister.hasCache() ) {
-					persister.getCache().release(ck, lock );
+					persister.getCacheAccessStrategy().unlockItem( ck, lock );
 				}
 			}
 

Modified: trunk/Hibernate3/src/org/hibernate/event/def/DefaultInitializeCollectionEventListener.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/DefaultInitializeCollectionEventListener.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/event/def/DefaultInitializeCollectionEventListener.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -71,13 +71,19 @@
 
 	/**
 	 * Try to initialize a collection from the cache
+	 *
+	 * @param id The id of the collection of initialize
+	 * @param persister The collection persister
+	 * @param collection The collection to initialize
+	 * @param source The originating session
+	 * @return true if we were able to initialize the collection from the cache;
+	 * false otherwise.
 	 */
 	private boolean initializeCollectionFromCache(
 			Serializable id,
 			CollectionPersister persister,
 			PersistentCollection collection,
-			SessionImplementor source)
-	throws HibernateException {
+			SessionImplementor source) {
 
 		if ( !source.getEnabledFilters().isEmpty() && persister.isAffectedByEnabledFilters( source ) ) {
 			log.trace( "disregarding cached version (if any) of collection due to enabled filters ");
@@ -101,18 +107,18 @@
 					source.getEntityMode(), 
 					source.getFactory() 
 				);
-			Object ce = persister.getCache().get( ck, source.getTimestamp() );
+			Object ce = persister.getCacheAccessStrategy().get( ck, source.getTimestamp() );
 			
 			if ( factory.getStatistics().isStatisticsEnabled() ) {
-				if (ce==null) {
-					factory.getStatisticsImplementor().secondLevelCacheMiss( 
-							persister.getCache().getRegionName() 
-						);
+				if ( ce == null ) {
+					factory.getStatisticsImplementor().secondLevelCacheMiss(
+							persister.getCacheAccessStrategy().getRegion().getName()
+					);
 				}
 				else {
-					factory.getStatisticsImplementor().secondLevelCacheHit( 
-							persister.getCache().getRegionName() 
-						);
+					factory.getStatisticsImplementor().secondLevelCacheHit(
+							persister.getCacheAccessStrategy().getRegion().getName()
+					);
 				}
 
 				

Modified: trunk/Hibernate3/src/org/hibernate/event/def/DefaultLoadEventListener.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/DefaultLoadEventListener.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/event/def/DefaultLoadEventListener.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -11,8 +11,8 @@
 import org.hibernate.PersistentObjectException;
 import org.hibernate.TypeMismatchException;
 import org.hibernate.EntityMode;
-import org.hibernate.cache.CacheConcurrencyStrategy;
 import org.hibernate.cache.CacheKey;
+import org.hibernate.cache.access.SoftLock;
 import org.hibernate.cache.entry.CacheEntry;
 import org.hibernate.engine.EntityEntry;
 import org.hibernate.engine.EntityKey;
@@ -116,6 +116,10 @@
 	/**
 	 * Perfoms the load of an entity.
 	 *
+	 * @param event The initiating load request event
+	 * @param persister The persister corresponding to the entity to be loaded
+	 * @param keyToLoad The key of the entity to be loaded
+	 * @param options The defined load options
 	 * @return The loaded entity.
 	 * @throws HibernateException
 	 */
@@ -123,8 +127,7 @@
 		final LoadEvent event,
 		final EntityPersister persister,
 		final EntityKey keyToLoad,
-		final LoadEventListener.LoadType options)
-	throws HibernateException {
+		final LoadEventListener.LoadType options) {
 
 		if ( event.getInstanceToLoad() != null ) {
 			if ( event.getSession().getPersistenceContext().getEntry( event.getInstanceToLoad() ) != null ) {
@@ -157,15 +160,17 @@
 	 * Based on configured options, will either return a pre-existing proxy,
 	 * generate a new proxy, or perform an actual load.
 	 *
+	 * @param event The initiating load request event
+	 * @param persister The persister corresponding to the entity to be loaded
+	 * @param keyToLoad The key of the entity to be loaded
+	 * @param options The defined load options
 	 * @return The result of the proxy/load operation.
-	 * @throws HibernateException
 	 */
 	protected Object proxyOrLoad(
 		final LoadEvent event,
 		final EntityPersister persister,
 		final EntityKey keyToLoad,
-		final LoadEventListener.LoadType options)
-	throws HibernateException {
+		final LoadEventListener.LoadType options) {
 
 		if ( log.isTraceEnabled() ) {
 			log.trace(
@@ -200,8 +205,16 @@
 	}
 
 	/**
-	 * Given that there is a pre-existing proxy.
-	 * Initialize it if necessary; narrow if necessary.
+	 * Given a proxy, initialize it and/or narrow it provided either
+	 * is necessary.
+	 *
+	 * @param event The initiating load request event
+	 * @param persister The persister corresponding to the entity to be loaded
+	 * @param keyToLoad The key of the entity to be loaded
+	 * @param options The defined load options
+	 * @param persistenceContext The originating session
+	 * @param proxy The proxy to narrow
+	 * @return The created/existing proxy
 	 */
 	private Object returnNarrowedProxy(
 			final LoadEvent event,
@@ -209,8 +222,7 @@
 			final EntityKey keyToLoad,
 			final LoadEventListener.LoadType options,
 			final PersistenceContext persistenceContext,
-			final Object proxy
-	) {
+			final Object proxy) {
 		log.trace("entity proxy found in session cache");
 		LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
 		if ( li.isUnwrap() ) {
@@ -227,17 +239,23 @@
 	}
 
 	/**
-	 * Given that there is no pre-existing proxy.
-	 * Check if the entity is already loaded. If it is, return the entity,
-	 * otherwise create and return a proxy.
+	 * If there is already a corresponding proxy associated with the
+	 * persistence context, return it; otherwise create a proxy, associate it
+	 * with the persistence context, and return the just-created proxy.
+	 *
+	 * @param event The initiating load request event
+	 * @param persister The persister corresponding to the entity to be loaded
+	 * @param keyToLoad The key of the entity to be loaded
+	 * @param options The defined load options
+	 * @param persistenceContext The originating session
+	 * @return The created/existing proxy
 	 */
 	private Object createProxyIfNecessary(
 			final LoadEvent event,
 			final EntityPersister persister,
 			final EntityKey keyToLoad,
 			final LoadEventListener.LoadType options,
-			final PersistenceContext persistenceContext
-	) {
+			final PersistenceContext persistenceContext) {
 		Object existing = persistenceContext.getEntity( keyToLoad );
 		if ( existing != null ) {
 			// return existing object or initialized proxy (unless deleted)
@@ -265,18 +283,21 @@
 	 * If the class to be loaded has been configured with a cache, then lock
 	 * given id in that cache and then perform the load.
 	 *
+	 * @param event The initiating load request event
+	 * @param persister The persister corresponding to the entity to be loaded
+	 * @param keyToLoad The key of the entity to be loaded
+	 * @param options The defined load options
+	 * @param source The originating session
 	 * @return The loaded entity
 	 * @throws HibernateException
 	 */
 	protected Object lockAndLoad(
-		final LoadEvent event,
-		final EntityPersister persister,
-		final EntityKey keyToLoad,
-		final LoadEventListener.LoadType options,
-		final SessionImplementor source)
-	throws HibernateException {
-
-		CacheConcurrencyStrategy.SoftLock lock = null;
+			final LoadEvent event,
+			final EntityPersister persister,
+			final EntityKey keyToLoad,
+			final LoadEventListener.LoadType options,
+			final SessionImplementor source) {
+		SoftLock lock = null;
 		final CacheKey ck;
 		if ( persister.hasCache() ) {
 			ck = new CacheKey(
@@ -285,8 +306,8 @@
 					persister.getRootEntityName(),
 					source.getEntityMode(),
 					source.getFactory()
-				);
-			lock = persister.getCache().lock(ck, null );
+			);
+			lock = persister.getCacheAccessStrategy().lockItem( ck, null );
 		}
 		else {
 			ck = null;
@@ -298,14 +319,11 @@
 		}
 		finally {
 			if ( persister.hasCache() ) {
-				persister.getCache().release(ck, lock );
+				persister.getCacheAccessStrategy().unlockItem( ck, lock );
 			}
 		}
 
-		Object proxy = event.getSession().getPersistenceContext()
-				.proxyFor( persister, keyToLoad, entity );
-
-		return proxy;
+		return event.getSession().getPersistenceContext().proxyFor( persister, keyToLoad, entity );
 	}
 
 
@@ -320,13 +338,12 @@
 	 * @param keyToLoad The EntityKey representing the entity to be loaded.
 	 * @param options The load options.
 	 * @return The loaded entity, or null.
-	 * @throws HibernateException
 	 */
 	protected Object doLoad(
 			final LoadEvent event,
 			final EntityPersister persister,
 			final EntityKey keyToLoad,
-			final LoadEventListener.LoadType options) throws HibernateException {
+			final LoadEventListener.LoadType options) {
 
 		if ( log.isTraceEnabled() ) {
 			log.trace(
@@ -384,13 +401,12 @@
 	 * @param keyToLoad The EntityKey representing the entity to be loaded.
 	 * @param options The load options.
 	 * @return The object loaded from the datasource, or null if not found.
-	 * @throws HibernateException
 	 */
 	protected Object loadFromDatasource(
 			final LoadEvent event,
 			final EntityPersister persister,
 			final EntityKey keyToLoad,
-			final LoadEventListener.LoadType options) throws HibernateException {
+			final LoadEventListener.LoadType options) {
 		final SessionImplementor source = event.getSession();
 		Object entity = persister.load(
 				event.getEntityId(),
@@ -459,20 +475,19 @@
 	 * @param persister The persister for the entity being requested for load
 	 * @param options The load options.
 	 * @return The entity from the second-level cache, or null.
-	 * @throws HibernateException
 	 */
 	protected Object loadFromSecondLevelCache(
 			final LoadEvent event,
 			final EntityPersister persister,
-			final LoadEventListener.LoadType options) throws HibernateException {
+			final LoadEventListener.LoadType options) {
 
 		final SessionImplementor source = event.getSession();
 
-		final boolean useCache = persister.hasCache() &&
-			source.getCacheMode().isGetEnabled() &&
-			event.getLockMode().lessThan(LockMode.READ);
+		final boolean useCache = persister.hasCache()
+				&& source.getCacheMode().isGetEnabled()
+				&& event.getLockMode().lessThan(LockMode.READ);
 
-		if (useCache) {
+		if ( useCache ) {
 
 			final SessionFactoryImplementor factory = source.getFactory();
 
@@ -482,35 +497,31 @@
 					persister.getRootEntityName(),
 					source.getEntityMode(),
 					source.getFactory()
-				);
-			Object ce = persister.getCache()
-				.get( ck, source.getTimestamp() );
-
+			);
+			Object ce = persister.getCacheAccessStrategy().get( ck, source.getTimestamp() );
 			if ( factory.getStatistics().isStatisticsEnabled() ) {
-				if (ce==null) {
+				if ( ce == null ) {
 					factory.getStatisticsImplementor().secondLevelCacheMiss(
-						persister.getCache().getRegionName()
+							persister.getCacheAccessStrategy().getRegion().getName()
 					);
 				}
 				else {
 					factory.getStatisticsImplementor().secondLevelCacheHit(
-						persister.getCache().getRegionName()
+							persister.getCacheAccessStrategy().getRegion().getName()
 					);
 				}
 			}
 
 			if ( ce != null ) {
+				CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory );
 
-				CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure()
-						.destructure(ce, factory);
-
 				// Entity was found in second-level cache...
 				return assembleCacheEntry(
 						entry,
 						event.getEntityId(),
 						persister,
 						event
-					);
+				);
 			}
 		}
 

Modified: trunk/Hibernate3/src/org/hibernate/event/def/DefaultRefreshEventListener.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/event/def/DefaultRefreshEventListener.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/event/def/DefaultRefreshEventListener.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -43,9 +43,8 @@
 	 * Handle the given refresh event.
 	 *
 	 * @param event The refresh event to be handled.
-	 * @throws HibernateException
 	 */
-	public void onRefresh(RefreshEvent event, Map refreshedAlready) throws HibernateException {
+	public void onRefresh(RefreshEvent event, Map refreshedAlready) {
 
 		final EventSource source = event.getSession();
 		
@@ -112,8 +111,8 @@
 					persister.getRootEntityName(),
 					source.getEntityMode(), 
 					source.getFactory()
-				);
-			persister.getCache().remove(ck);
+			);
+			persister.getCacheAccessStrategy().evict( ck );
 		}
 		
 		evictCachedCollections( persister, id, source.getFactory() );
@@ -127,11 +126,7 @@
 
 	}
 
-	/**
-	 * Evict collections from the factory-level cache
-	 */
-	private void evictCachedCollections(EntityPersister persister, Serializable id, SessionFactoryImplementor factory)
-	throws HibernateException {
+	private void evictCachedCollections(EntityPersister persister, Serializable id, SessionFactoryImplementor factory) {
 		evictCachedCollections( persister.getPropertyTypes(), id, factory );
 	}
 

Modified: trunk/Hibernate3/src/org/hibernate/impl/SessionFactoryImpl.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/impl/SessionFactoryImpl.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/impl/SessionFactoryImpl.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -35,13 +35,16 @@
 import org.hibernate.SessionFactory;
 import org.hibernate.StatelessSession;
 import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
-import org.hibernate.cache.Cache;
-import org.hibernate.cache.CacheConcurrencyStrategy;
-import org.hibernate.cache.CacheFactory;
 import org.hibernate.cache.CacheKey;
-import org.hibernate.cache.OptimisticCache;
 import org.hibernate.cache.QueryCache;
 import org.hibernate.cache.UpdateTimestampsCache;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.impl.CacheDataDescriptionImpl;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
 import org.hibernate.cfg.Configuration;
 import org.hibernate.cfg.Environment;
 import org.hibernate.cfg.Settings;
@@ -180,7 +183,7 @@
 		}
 
 		// Caches
-		settings.getCacheProvider().start( properties );
+		settings.getRegionFactory().start( settings, properties );
 
 		//Generators:
 
@@ -199,34 +202,32 @@
 			}
 		}
 
-		//Persisters:
 
-		Map caches = new HashMap();
+		///////////////////////////////////////////////////////////////////////
+		// Prepare persisters and link them up with their cache
+		// region/access-strategy
+
 		entityPersisters = new HashMap();
+		Map entityAccessStrategies = new HashMap();
 		Map classMeta = new HashMap();
 		classes = cfg.getClassMappings();
 		while ( classes.hasNext() ) {
-			PersistentClass model = (PersistentClass) classes.next();
+			final PersistentClass model = (PersistentClass) classes.next();
 			model.prepareTemporaryTables( mapping, settings.getDialect() );
-			String cacheRegion = model.getRootClass().getCacheRegionName();
-			CacheConcurrencyStrategy cache = (CacheConcurrencyStrategy) caches.get(cacheRegion);
-			if (cache==null) {
-				cache = CacheFactory.createCache(
-						model.getCacheConcurrencyStrategy(),
-				        cacheRegion,
-				        model.isMutable(),
-				        settings,
-				        properties
-				);
-				if (cache!=null) {
-					caches.put(cacheRegion, cache);
-					allCacheRegions.put( cache.getRegionName(), cache.getCache() );
+			// cache region is defined by the root-class in the hierarchy...
+			final String cacheRegionName = model.getRootClass().getCacheRegionName();
+			EntityRegionAccessStrategy accessStrategy = ( EntityRegionAccessStrategy ) entityAccessStrategies.get( cacheRegionName );
+			if ( accessStrategy == null && settings.isSecondLevelCacheEnabled() ) {
+				final AccessType accessType = AccessType.parse( model.getCacheConcurrencyStrategy() );
+				if ( accessType != null ) {
+					log.trace( "Building cache for entity data [" + model.getEntityName() + "]" );
+					EntityRegion entityRegion = settings.getRegionFactory().buildEntityRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) );
+					accessStrategy = entityRegion.buildAccessStrategy( accessType );
+					entityAccessStrategies.put( cacheRegionName, accessStrategy );
+					allCacheRegions.put( cacheRegionName, entityRegion );
 				}
 			}
-			EntityPersister cp = PersisterFactory.createClassPersister(model, cache, this, mapping);
-			if ( cache != null && cache.getCache() instanceof OptimisticCache ) {
-				( ( OptimisticCache ) cache.getCache() ).setSource( cp );
-			}
+			EntityPersister cp = PersisterFactory.createClassPersister( model, accessStrategy, this, mapping );
 			entityPersisters.put( model.getEntityName(), cp );
 			classMeta.put( model.getEntityName(), cp.getClassMetadata() );
 		}
@@ -237,17 +238,17 @@
 		Iterator collections = cfg.getCollectionMappings();
 		while ( collections.hasNext() ) {
 			Collection model = (Collection) collections.next();
-			CacheConcurrencyStrategy cache = CacheFactory.createCache(
-					model.getCacheConcurrencyStrategy(),
-			    	model.getCacheRegionName(),
-			    	model.isMutable(),
-			    	settings,
-			    	properties
-			);
-			if ( cache != null ) {
-				allCacheRegions.put( cache.getRegionName(), cache.getCache() );
+			final String cacheRegionName = model.getCacheRegionName();
+			final AccessType accessType = AccessType.parse( model.getCacheConcurrencyStrategy() );
+			CollectionRegionAccessStrategy accessStrategy = null;
+			if ( accessType != null && settings.isSecondLevelCacheEnabled() ) {
+				log.trace( "Building cache for collection data [" + model.getRole() + "]" );
+				CollectionRegion collectionRegion = settings.getRegionFactory().buildCollectionRegion( cacheRegionName, properties, CacheDataDescriptionImpl.decode( model ) );
+				accessStrategy = collectionRegion.buildAccessStrategy( accessType );
+				entityAccessStrategies.put( cacheRegionName, accessStrategy );
+				allCacheRegions.put( cacheRegionName, collectionRegion );
 			}
-			CollectionPersister persister = PersisterFactory.createCollectionPersister(cfg, model, cache, this);
+			CollectionPersister persister = PersisterFactory.createCollectionPersister( cfg, model, accessStrategy, this) ;
 			collectionPersisters.put( model.getRole(), persister.getCollectionMetadata() );
 			Type indexType = persister.getIndexType();
 			if ( indexType != null && indexType.isAssociationType() && !indexType.isAnyType() ) {
@@ -338,8 +339,8 @@
 			queryCache = settings.getQueryCacheFactory()
 			        .getQueryCache(null, updateTimestampsCache, settings, properties);
 			queryCaches = new HashMap();
-			allCacheRegions.put( updateTimestampsCache.getRegionName(), updateTimestampsCache.getCache() );
-			allCacheRegions.put( queryCache.getRegionName(), queryCache.getCache() );
+			allCacheRegions.put( updateTimestampsCache.getRegion().getName(), updateTimestampsCache.getRegion() );
+			allCacheRegions.put( queryCache.getRegion().getName(), queryCache.getRegion() );
 		}
 		else {
 			updateTimestampsCache = null;
@@ -420,14 +421,11 @@
 				log.debug("Checking named SQL query: " + queryName);
 				// TODO : would be really nice to cache the spec on the query-def so as to not have to re-calc the hash;
 				// currently not doable though because of the resultset-ref stuff...
-				NativeSQLQuerySpecification spec = null;
+				NativeSQLQuerySpecification spec;
 				if ( qd.getResultSetRef() != null ) {
-					ResultSetMappingDefinition definition = ( ResultSetMappingDefinition )
-							sqlResultSetMappings.get( qd.getResultSetRef() );
+					ResultSetMappingDefinition definition = ( ResultSetMappingDefinition ) sqlResultSetMappings.get( qd.getResultSetRef() );
 					if ( definition == null ) {
-						throw new MappingException(
-								"Unable to find resultset-ref definition: " + qd.getResultSetRef()
-							);
+						throw new MappingException( "Unable to find resultset-ref definition: " + qd.getResultSetRef() );
 					}
 					spec = new NativeSQLQuerySpecification(
 							qd.getQueryString(),
@@ -435,8 +433,7 @@
 					        qd.getQuerySpaces()
 					);
 				}
-				else
-				{
+				else {
 					spec =  new NativeSQLQuerySpecification(
 							qd.getQueryString(),
 					        qd.getQueryReturns(),
@@ -493,7 +490,7 @@
 		// returns an older JDBC connection that was associated with a
 		// transaction that was already begun before openSession() was called
 		// (don't know any possible solution to this!)
-		long timestamp = settings.getCacheProvider().nextTimestamp();
+		long timestamp = settings.getRegionFactory().nextTimestamp();
 		return openSession( null, true, timestamp, sessionLocalInterceptor );
 	}
 
@@ -510,7 +507,7 @@
 				null,
 		        this,
 		        true,
-		        settings.getCacheProvider().nextTimestamp(),
+		        settings.getRegionFactory().nextTimestamp(),
 		        interceptor,
 		        settings.getDefaultEntityMode(),
 		        false,
@@ -528,7 +525,7 @@
 				connection,
 		        this,
 		        true,
-		        settings.getCacheProvider().nextTimestamp(),
+		        settings.getRegionFactory().nextTimestamp(),
 		        interceptor,
 		        settings.getDefaultEntityMode(),
 		        flushBeforeCompletionEnabled,
@@ -640,12 +637,13 @@
 		return getEntityPersister(className).getIdentifierPropertyName();
 	}
 
-	private final void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
 		log.trace("deserializing");
 		in.defaultReadObject();
 		log.debug("deserialized: " + uuid);
 	}
-	private final void writeObject(ObjectOutputStream out) throws IOException {
+
+	private void writeObject(ObjectOutputStream out) throws IOException {
 		log.debug("serializing: " + uuid);
 		out.defaultWriteObject();
 		log.trace("serialized");
@@ -774,7 +772,7 @@
 		while ( iter.hasNext() ) {
 			EntityPersister p = (EntityPersister) iter.next();
 			if ( p.hasCache() ) {
-				p.getCache().destroy();
+				p.getCacheAccessStrategy().destroy();
 			}
 		}
 
@@ -782,7 +780,7 @@
 		while ( iter.hasNext() ) {
 			CollectionPersister p = (CollectionPersister) iter.next();
 			if ( p.hasCache() ) {
-				p.getCache().destroy();
+				p.getCacheAccessStrategy().destroy();
 			}
 		}
 
@@ -797,7 +795,7 @@
 			updateTimestampsCache.destroy();
 		}
 
-		settings.getCacheProvider().stop();
+		settings.getRegionFactory().stop();
 
 		try {
 			settings.getConnectionProvider().close();
@@ -813,23 +811,23 @@
 	}
 
 	public void evictEntity(String entityName, Serializable id) throws HibernateException {
-		EntityPersister p = getEntityPersister(entityName);
+		EntityPersister p = getEntityPersister( entityName );
 		if ( p.hasCache() ) {
 			if ( log.isDebugEnabled() ) {
 				log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, id, this) );
 			}
 			CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(), EntityMode.POJO, this );
-			p.getCache().remove( cacheKey );
+			p.getCacheAccessStrategy().evict( cacheKey );
 		}
 	}
 
 	public void evictEntity(String entityName) throws HibernateException {
-		EntityPersister p = getEntityPersister(entityName);
+		EntityPersister p = getEntityPersister( entityName );
 		if ( p.hasCache() ) {
 			if ( log.isDebugEnabled() ) {
 				log.debug( "evicting second-level cache: " + p.getEntityName() );
 			}
-			p.getCache().clear();
+			p.getCacheAccessStrategy().evictAll();
 		}
 	}
 
@@ -840,7 +838,7 @@
 				log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, id, this) );
 			}
 			CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(), EntityMode.POJO, this );
-			p.getCache().remove( cacheKey );
+			p.getCacheAccessStrategy().evict( cacheKey );
 		}
 	}
 
@@ -850,28 +848,28 @@
 			if ( log.isDebugEnabled() ) {
 				log.debug( "evicting second-level cache: " + p.getEntityName() );
 			}
-			p.getCache().clear();
+			p.getCacheAccessStrategy().evictAll();
 		}
 	}
 
 	public void evictCollection(String roleName, Serializable id) throws HibernateException {
-		CollectionPersister p = getCollectionPersister(roleName);
+		CollectionPersister p = getCollectionPersister( roleName );
 		if ( p.hasCache() ) {
 			if ( log.isDebugEnabled() ) {
 				log.debug( "evicting second-level cache: " + MessageHelper.collectionInfoString(p, id, this) );
 			}
 			CacheKey cacheKey = new CacheKey( id, p.getKeyType(), p.getRole(), EntityMode.POJO, this );
-			p.getCache().remove( cacheKey );
+			p.getCacheAccessStrategy().evict( cacheKey );
 		}
 	}
 
 	public void evictCollection(String roleName) throws HibernateException {
-		CollectionPersister p = getCollectionPersister(roleName);
+		CollectionPersister p = getCollectionPersister( roleName );
 		if ( p.hasCache() ) {
 			if ( log.isDebugEnabled() ) {
 				log.debug( "evicting second-level cache: " + p.getRole() );
 			}
-			p.getCache().clear();
+			p.getCacheAccessStrategy().evictAll();
 		}
 	}
 
@@ -892,8 +890,8 @@
 		return queryCache;
 	}
 
-	public QueryCache getQueryCache(String cacheRegion) throws HibernateException {
-		if (cacheRegion==null) {
+	public QueryCache getQueryCache(String regionName) throws HibernateException {
+		if ( regionName == null ) {
 			return getQueryCache();
 		}
 
@@ -901,27 +899,26 @@
 			return null;
 		}
 
-		synchronized (allCacheRegions) {
-			QueryCache currentQueryCache = (QueryCache) queryCaches.get(cacheRegion);
-			if (currentQueryCache==null) {
-				currentQueryCache = settings.getQueryCacheFactory()
-					.getQueryCache(cacheRegion, updateTimestampsCache, settings, properties);
-				queryCaches.put(cacheRegion, currentQueryCache);
-				allCacheRegions.put( currentQueryCache.getRegionName(), currentQueryCache.getCache() );
+		synchronized ( allCacheRegions ) {
+			QueryCache currentQueryCache = ( QueryCache ) queryCaches.get( regionName );
+			if ( currentQueryCache == null ) {
+				currentQueryCache = settings.getQueryCacheFactory().getQueryCache( regionName, updateTimestampsCache, settings, properties );
+				queryCaches.put( regionName, currentQueryCache );
+				allCacheRegions.put( currentQueryCache.getRegion().getName(), currentQueryCache.getRegion() );
 			}
 			return currentQueryCache;
 		}
 	}
 
-	public Cache getSecondLevelCacheRegion(String regionName) {
-		synchronized (allCacheRegions) {
-			return (Cache) allCacheRegions.get(regionName);
+	public Region getSecondLevelCacheRegion(String regionName) {
+		synchronized ( allCacheRegions ) {
+			return ( Region ) allCacheRegions.get( regionName );
 		}
 	}
 
 	public Map getAllSecondLevelCacheRegions() {
-		synchronized (allCacheRegions) {
-			return new HashMap(allCacheRegions);
+		synchronized ( allCacheRegions ) {
+			return new HashMap( allCacheRegions );
 		}
 	}
 
@@ -1028,7 +1025,7 @@
 	 * Custom serialization hook used during Session serialization.
 	 *
 	 * @param oos The stream to which to write the factory
-	 * @throws IOException
+	 * @throws IOException Indicates problems writing out the serial data stream
 	 */
 	void serialize(ObjectOutputStream oos) throws IOException {
 		oos.writeUTF( uuid );
@@ -1042,7 +1039,9 @@
 	 * Custom deserialization hook used during Session deserialization.
 	 *
 	 * @param ois The stream from which to "read" the factory
-	 * @throws IOException
+	 * @return The deserialized factory
+	 * @throws IOException indicates problems reading back serial data stream
+	 * @throws ClassNotFoundException indicates problems reading back serial data stream
 	 */
 	static SessionFactoryImpl deserialize(ObjectInputStream ois) throws IOException, ClassNotFoundException {
 		String uuid = ois.readUTF();

Modified: trunk/Hibernate3/src/org/hibernate/impl/StatelessSessionImpl.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/impl/StatelessSessionImpl.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/impl/StatelessSessionImpl.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -200,7 +200,7 @@
 			        this.getEntityMode(),
 			        this.getFactory()
 			);
-			persister.getCache().remove(ck);
+			persister.getCacheAccessStrategy().evict( ck );
 		}
 
 		String previousFetchProfile = this.getFetchProfile();

Modified: trunk/Hibernate3/src/org/hibernate/loader/Loader.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/loader/Loader.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/loader/Loader.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -2162,16 +2162,16 @@
 					queryParameters.isNaturalKeyLookup(), 
 					querySpaces, 
 					session 
-				);
+			);
 
 			if ( factory.getStatistics().isStatisticsEnabled() ) {
-				if (result==null) {
+				if ( result == null ) {
 					factory.getStatisticsImplementor()
-							.queryCacheMiss( getQueryIdentifier(), queryCache.getRegionName() );
+							.queryCacheMiss( getQueryIdentifier(), queryCache.getRegion().getName() );
 				}
 				else {
 					factory.getStatisticsImplementor()
-							.queryCacheHit( getQueryIdentifier(), queryCache.getRegionName() );
+							.queryCacheHit( getQueryIdentifier(), queryCache.getRegion().getName() );
 				}
 			}
 			
@@ -2198,7 +2198,7 @@
 			);
 			if ( put && factory.getStatistics().isStatisticsEnabled() ) {
 				factory.getStatisticsImplementor()
-						.queryCachePut( getQueryIdentifier(), queryCache.getRegionName() );
+						.queryCachePut( getQueryIdentifier(), queryCache.getRegion().getName() );
 			}
 		}
 	}

Modified: trunk/Hibernate3/src/org/hibernate/persister/PersisterFactory.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/persister/PersisterFactory.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/persister/PersisterFactory.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -6,7 +6,8 @@
 
 import org.hibernate.HibernateException;
 import org.hibernate.MappingException;
-import org.hibernate.cache.CacheConcurrencyStrategy;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
 import org.hibernate.cfg.Configuration;
 import org.hibernate.engine.Mapping;
 import org.hibernate.engine.SessionFactoryImplementor;
@@ -35,46 +36,54 @@
 	private PersisterFactory() {}
 
 	private static final Class[] PERSISTER_CONSTRUCTOR_ARGS = new Class[] {
-		PersistentClass.class, CacheConcurrencyStrategy.class, SessionFactoryImplementor.class, Mapping.class
+		PersistentClass.class, EntityRegionAccessStrategy.class, SessionFactoryImplementor.class, Mapping.class
 	};
 
 	// TODO: is it really neceassry to provide Configuration to CollectionPersisters ? Should it not be enough with associated class ?
 	// or why does EntityPersister's not get access to configuration ?
+	//
+	// The only reason I could see that Configuration gets passed to collection persisters
+	// is so that they can look up the dom4j node name of the entity element in case
+	// no explicit node name was applied at the collection element level.  Are you kidding me?
+	// Trivial to fix then.  Just store and expose the node name on the entity persister
+	// (which the collection persister looks up anyway via other means...).
 	private static final Class[] COLLECTION_PERSISTER_CONSTRUCTOR_ARGS = new Class[] {
-			Collection.class, CacheConcurrencyStrategy.class, Configuration.class, SessionFactoryImplementor.class
+			Collection.class, CollectionRegionAccessStrategy.class, Configuration.class, SessionFactoryImplementor.class
 		};
 
 	public static EntityPersister createClassPersister(
-			PersistentClass model, 
-			CacheConcurrencyStrategy cache, 
+			PersistentClass model,
+			EntityRegionAccessStrategy cacheAccessStrategy,
 			SessionFactoryImplementor factory,
-			Mapping cfg)
-	throws HibernateException {
+			Mapping cfg) throws HibernateException {
 		Class persisterClass = model.getEntityPersisterClass();
-		if (persisterClass==null || persisterClass==SingleTableEntityPersister.class) {
-			return new SingleTableEntityPersister(model, cache, factory, cfg);
+		if ( persisterClass == null || persisterClass == SingleTableEntityPersister.class ) {
+			return new SingleTableEntityPersister( model, cacheAccessStrategy, factory, cfg );
 		}
-		else if (persisterClass==JoinedSubclassEntityPersister.class) {
-			return new JoinedSubclassEntityPersister(model, cache, factory, cfg);
+		else if ( persisterClass == JoinedSubclassEntityPersister.class ) {
+			return new JoinedSubclassEntityPersister( model, cacheAccessStrategy, factory, cfg );
 		}
-		else if (persisterClass==UnionSubclassEntityPersister.class) {
-			return new UnionSubclassEntityPersister(model, cache, factory, cfg);
+		else if ( persisterClass == UnionSubclassEntityPersister.class ) {
+			return new UnionSubclassEntityPersister( model, cacheAccessStrategy, factory, cfg );
 		}
 		else {
-			return create(persisterClass, model, cache, factory, cfg);
+			return create( persisterClass, model, cacheAccessStrategy, factory, cfg );
 		}
 	}
 
-	public static CollectionPersister createCollectionPersister(Configuration cfg, Collection model, CacheConcurrencyStrategy cache, SessionFactoryImplementor factory)
-	throws HibernateException {
+	public static CollectionPersister createCollectionPersister(
+			Configuration cfg,
+			Collection model,
+			CollectionRegionAccessStrategy cacheAccessStrategy,
+			SessionFactoryImplementor factory) throws HibernateException {
 		Class persisterClass = model.getCollectionPersisterClass();
-		if(persisterClass==null) { // default behavior
-			return model.isOneToMany() ?
-				(CollectionPersister) new OneToManyPersister(model, cache, cfg, factory) :
-				(CollectionPersister) new BasicCollectionPersister(model, cache, cfg, factory);
+		if ( persisterClass == null ) {
+			return model.isOneToMany()
+					? ( CollectionPersister ) new OneToManyPersister( model, cacheAccessStrategy, cfg, factory )
+					: ( CollectionPersister ) new BasicCollectionPersister( model, cacheAccessStrategy, cfg, factory );
 		}
 		else {
-			return create(persisterClass, cfg, model, cache, factory);
+			return create( persisterClass, cfg, model, cacheAccessStrategy, factory );
 		}
 
 	}
@@ -82,20 +91,19 @@
 	private static EntityPersister create(
 			Class persisterClass, 
 			PersistentClass model, 
-			CacheConcurrencyStrategy cache, 
+			EntityRegionAccessStrategy cacheAccessStrategy,
 			SessionFactoryImplementor factory,
-			Mapping cfg)
-	throws HibernateException {
+			Mapping cfg) throws HibernateException {
 		Constructor pc;
 		try {
-			pc = persisterClass.getConstructor(PERSISTER_CONSTRUCTOR_ARGS);
+			pc = persisterClass.getConstructor( PERSISTER_CONSTRUCTOR_ARGS );
 		}
-		catch (Exception e) {
+		catch ( Exception e ) {
 			throw new MappingException( "Could not get constructor for " + persisterClass.getName(), e );
 		}
 
 		try {
-			return (EntityPersister) pc.newInstance( new Object[] { model, cache, factory, cfg } );
+			return (EntityPersister) pc.newInstance( new Object[] { model, cacheAccessStrategy, factory, cfg } );
 		}
 		catch (InvocationTargetException ite) {
 			Throwable e = ite.getTargetException();
@@ -111,17 +119,22 @@
 		}
 	}
 
-	private static CollectionPersister create(Class persisterClass, Configuration cfg, Collection model, CacheConcurrencyStrategy cache, SessionFactoryImplementor factory) throws HibernateException {
+	private static CollectionPersister create(
+			Class persisterClass,
+			Configuration cfg,
+			Collection model,
+			CollectionRegionAccessStrategy cacheAccessStrategy,
+			SessionFactoryImplementor factory) throws HibernateException {
 		Constructor pc;
 		try {
-			pc = persisterClass.getConstructor(COLLECTION_PERSISTER_CONSTRUCTOR_ARGS);
+			pc = persisterClass.getConstructor( COLLECTION_PERSISTER_CONSTRUCTOR_ARGS );
 		}
 		catch (Exception e) {
 			throw new MappingException( "Could not get constructor for " + persisterClass.getName(), e );
 		}
 
 		try {
-			return (CollectionPersister) pc.newInstance( new Object[] { model, cache, cfg, factory } );
+			return (CollectionPersister) pc.newInstance( new Object[] { model, cacheAccessStrategy, cfg, factory } );
 		}
 		catch (InvocationTargetException ite) {
 			Throwable e = ite.getTargetException();

Modified: trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/persister/collection/AbstractCollectionPersister.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -20,8 +20,8 @@
 import org.hibernate.TransientObjectException;
 import org.hibernate.jdbc.Expectation;
 import org.hibernate.jdbc.Expectations;
-import org.hibernate.cache.CacheConcurrencyStrategy;
 import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
 import org.hibernate.cache.entry.CacheEntryStructure;
 import org.hibernate.cache.entry.StructuredCollectionCacheEntry;
 import org.hibernate.cache.entry.StructuredMapCacheEntry;
@@ -158,7 +158,7 @@
 	private final IdentifierGenerator identifierGenerator;
 	private final PropertyMapping elementPropertyMapping;
 	private final EntityPersister elementPersister;
-	private final CacheConcurrencyStrategy cache;
+	private final CollectionRegionAccessStrategy cacheAccessStrategy;
 	private final CollectionType collectionType;
 	private CollectionInitializer initializer;
 	
@@ -195,17 +195,16 @@
 
 	public AbstractCollectionPersister(
 			final Collection collection,
-			final CacheConcurrencyStrategy cache,
+			final CollectionRegionAccessStrategy cacheAccessStrategy,
 			final Configuration cfg,
-			final SessionFactoryImplementor factory)
-	throws MappingException, CacheException {
+			final SessionFactoryImplementor factory) throws MappingException, CacheException {
 
 		this.factory = factory;
-		this.cache = cache;
+		this.cacheAccessStrategy = cacheAccessStrategy;
 		if ( factory.getSettings().isStructuredCacheEntriesEnabled() ) {
-			cacheEntryStructure = collection.isMap() ? 
-					(CacheEntryStructure) new StructuredMapCacheEntry() : 
-					(CacheEntryStructure) new StructuredCollectionCacheEntry();
+			cacheEntryStructure = collection.isMap() ?
+					( CacheEntryStructure ) new StructuredMapCacheEntry() :
+					( CacheEntryStructure ) new StructuredCollectionCacheEntry();
 		}
 		else {
 			cacheEntryStructure = new UnstructuredCacheEntry();
@@ -618,12 +617,12 @@
 	protected abstract CollectionInitializer createCollectionInitializer(Map enabledFilters)
 			throws MappingException;
 
-	public CacheConcurrencyStrategy getCache() {
-		return cache;
+	public CollectionRegionAccessStrategy getCacheAccessStrategy() {
+		return cacheAccessStrategy;
 	}
 
 	public boolean hasCache() {
-		return cache != null;
+		return cacheAccessStrategy != null;
 	}
 
 	public CollectionType getCollectionType() {

Modified: trunk/Hibernate3/src/org/hibernate/persister/collection/BasicCollectionPersister.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/persister/collection/BasicCollectionPersister.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/persister/collection/BasicCollectionPersister.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -12,8 +12,8 @@
 import org.hibernate.jdbc.Expectation;
 import org.hibernate.type.AssociationType;
 import org.hibernate.persister.entity.Joinable;
-import org.hibernate.cache.CacheConcurrencyStrategy;
 import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
 import org.hibernate.cfg.Configuration;
 import org.hibernate.collection.PersistentCollection;
 import org.hibernate.engine.SessionFactoryImplementor;
@@ -42,12 +42,12 @@
 		return false;
 	}
 
-	public BasicCollectionPersister(Collection collection,
-									CacheConcurrencyStrategy cache,
-									Configuration cfg,
-									SessionFactoryImplementor factory)
-			throws MappingException, CacheException {
-		super( collection, cache, cfg, factory );
+	public BasicCollectionPersister(
+			Collection collection,
+			CollectionRegionAccessStrategy cacheAccessStrategy,
+			Configuration cfg,
+			SessionFactoryImplementor factory) throws MappingException, CacheException {
+		super( collection, cacheAccessStrategy, cfg, factory );
 	}
 
 	/**

Modified: trunk/Hibernate3/src/org/hibernate/persister/collection/CollectionPersister.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/persister/collection/CollectionPersister.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/persister/collection/CollectionPersister.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -8,7 +8,7 @@
 
 import org.hibernate.HibernateException;
 import org.hibernate.MappingException;
-import org.hibernate.cache.CacheConcurrencyStrategy;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
 import org.hibernate.cache.entry.CacheEntryStructure;
 import org.hibernate.collection.PersistentCollection;
 import org.hibernate.engine.SessionFactoryImplementor;
@@ -45,14 +45,14 @@
 	public void initialize(Serializable key, SessionImplementor session) //TODO: add owner argument!!
 	throws HibernateException;
 	/**
-	 * Get the cache
-	 */
-	public CacheConcurrencyStrategy getCache();
-	/**
 	 * Is this collection role cacheable
 	 */
 	public boolean hasCache();
 	/**
+	 * Get the cache
+	 */
+	public CollectionRegionAccessStrategy getCacheAccessStrategy();
+	/**
 	 * Get the cache structure
 	 */
 	public CacheEntryStructure getCacheEntryStructure();

Modified: trunk/Hibernate3/src/org/hibernate/persister/collection/OneToManyPersister.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/persister/collection/OneToManyPersister.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/persister/collection/OneToManyPersister.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -10,8 +10,8 @@
 import org.hibernate.MappingException;
 import org.hibernate.jdbc.Expectation;
 import org.hibernate.jdbc.Expectations;
-import org.hibernate.cache.CacheConcurrencyStrategy;
 import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
 import org.hibernate.cfg.Configuration;
 import org.hibernate.collection.PersistentCollection;
 import org.hibernate.engine.SessionFactoryImplementor;
@@ -52,12 +52,12 @@
 		return cascadeDeleteEnabled;
 	}
 
-	public OneToManyPersister(Collection collection,
-							  CacheConcurrencyStrategy cache,
-							  Configuration cfg,
-							  SessionFactoryImplementor factory)
-			throws MappingException, CacheException {
-		super( collection, cache, cfg, factory );
+	public OneToManyPersister(
+			Collection collection,
+			CollectionRegionAccessStrategy cacheAccessStrategy,
+			Configuration cfg,
+			SessionFactoryImplementor factory) throws MappingException, CacheException {
+		super( collection, cacheAccessStrategy, cfg, factory );
 		cascadeDeleteEnabled = collection.getKey().isCascadeDeleteEnabled() &&
 				factory.getDialect().supportsCascadeDelete();
 		keyIsNullable = collection.getKey().isNullable();

Modified: trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/persister/entity/AbstractEntityPersister.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -31,6 +31,7 @@
 import org.hibernate.dialect.lock.LockingStrategy;
 import org.hibernate.cache.CacheConcurrencyStrategy;
 import org.hibernate.cache.CacheKey;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
 import org.hibernate.cache.entry.CacheEntry;
 import org.hibernate.cache.entry.CacheEntryStructure;
 import org.hibernate.cache.entry.StructuredCacheEntry;
@@ -105,7 +106,7 @@
 
 	// moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 	private final SessionFactoryImplementor factory;
-	private final CacheConcurrencyStrategy cache;
+	private final EntityRegionAccessStrategy cacheAccessStrategy;
 	private final boolean isLazyPropertiesCacheable;
 	private final CacheEntryStructure cacheEntryStructure;
 	private final EntityMetamodel entityMetamodel;
@@ -419,13 +420,12 @@
 
 	public AbstractEntityPersister(
 			final PersistentClass persistentClass,
-			final CacheConcurrencyStrategy cache,
-			final SessionFactoryImplementor factory)
-	throws HibernateException {
+			final EntityRegionAccessStrategy cacheAccessStrategy,
+			final SessionFactoryImplementor factory) throws HibernateException {
 
 		// moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 		this.factory = factory;
-		this.cache = cache;
+		this.cacheAccessStrategy = cacheAccessStrategy;
 		isLazyPropertiesCacheable = persistentClass.isLazyPropertiesCacheable();
 		this.cacheEntryStructure = factory.getSettings().isStructuredCacheEntriesEnabled() ?
 				(CacheEntryStructure) new StructuredCacheEntry(this) :
@@ -745,7 +745,7 @@
 
 		if ( hasCache() ) {
 			CacheKey cacheKey = new CacheKey(id, getIdentifierType(), getEntityName(), session.getEntityMode(), getFactory() );
-			Object ce = getCache().get( cacheKey, session.getTimestamp() );
+			Object ce = getCacheAccessStrategy().get( cacheKey, session.getTimestamp() );
 			if (ce!=null) {
 				CacheEntry cacheEntry = (CacheEntry) getCacheEntryStructure().destructure(ce, factory);
 				if ( !cacheEntry.areLazyPropertiesUnfetched() ) {
@@ -3200,11 +3200,11 @@
 	}
 
 	public boolean hasCache() {
-		return cache != null;
+		return cacheAccessStrategy != null;
 	}
 
-	public CacheConcurrencyStrategy getCache() {
-		return cache;
+	public EntityRegionAccessStrategy getCacheAccessStrategy() {
+		return cacheAccessStrategy;
 	}
 
 	public CacheEntryStructure getCacheEntryStructure() {
@@ -3341,7 +3341,7 @@
 					session.getEntityMode(),
 					session.getFactory()
 				);
-			if ( getCache().get( ck, session.getTimestamp() ) != null ) {
+			if ( getCacheAccessStrategy().get( ck, session.getTimestamp() ) != null ) {
 				return Boolean.FALSE;
 			}
 		}

Modified: trunk/Hibernate3/src/org/hibernate/persister/entity/EntityPersister.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/persister/entity/EntityPersister.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/persister/entity/EntityPersister.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -11,6 +11,7 @@
 import org.hibernate.tuple.entity.EntityMetamodel;
 import org.hibernate.cache.CacheConcurrencyStrategy;
 import org.hibernate.cache.OptimisticCacheSource;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
 import org.hibernate.cache.entry.CacheEntryStructure;
 import org.hibernate.engine.CascadeStyle;
 import org.hibernate.engine.SessionFactoryImplementor;
@@ -425,7 +426,7 @@
 	/**
 	 * Get the cache (optional operation)
 	 */
-	public CacheConcurrencyStrategy getCache();
+	public EntityRegionAccessStrategy getCacheAccessStrategy();
 	/**
 	 * Get the cache structure
 	 */

Modified: trunk/Hibernate3/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -12,7 +12,7 @@
 import org.hibernate.HibernateException;
 import org.hibernate.MappingException;
 import org.hibernate.QueryException;
-import org.hibernate.cache.CacheConcurrencyStrategy;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
 import org.hibernate.engine.Mapping;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.engine.Versioning;
@@ -83,12 +83,11 @@
 
 	public JoinedSubclassEntityPersister(
 			final PersistentClass persistentClass,
-			final CacheConcurrencyStrategy cache,
+			final EntityRegionAccessStrategy cacheAccessStrategy,
 			final SessionFactoryImplementor factory,
-			final Mapping mapping)
-	throws HibernateException {
+			final Mapping mapping) throws HibernateException {
 
-		super(persistentClass, cache, factory);
+		super( persistentClass, cacheAccessStrategy, factory );
 
 		// DISCRIMINATOR
 

Modified: trunk/Hibernate3/src/org/hibernate/persister/entity/SingleTableEntityPersister.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/persister/entity/SingleTableEntityPersister.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/persister/entity/SingleTableEntityPersister.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -11,7 +11,7 @@
 import org.hibernate.EntityMode;
 import org.hibernate.HibernateException;
 import org.hibernate.MappingException;
-import org.hibernate.cache.CacheConcurrencyStrategy;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
 import org.hibernate.engine.Mapping;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
@@ -101,12 +101,11 @@
 
 	public SingleTableEntityPersister(
 			final PersistentClass persistentClass, 
-			final CacheConcurrencyStrategy cache,
+			final EntityRegionAccessStrategy cacheAccessStrategy,
 			final SessionFactoryImplementor factory,
-			final Mapping mapping)
-	throws HibernateException {
+			final Mapping mapping) throws HibernateException {
 
-		super(persistentClass, cache, factory);
+		super( persistentClass, cacheAccessStrategy, factory );
 
 		// CLASS + TABLE
 

Modified: trunk/Hibernate3/src/org/hibernate/persister/entity/UnionSubclassEntityPersister.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/persister/entity/UnionSubclassEntityPersister.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/persister/entity/UnionSubclassEntityPersister.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -13,7 +13,7 @@
 import org.hibernate.HibernateException;
 import org.hibernate.LockMode;
 import org.hibernate.MappingException;
-import org.hibernate.cache.CacheConcurrencyStrategy;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
 import org.hibernate.cfg.Settings;
 import org.hibernate.dialect.Dialect;
 import org.hibernate.engine.Mapping;
@@ -56,12 +56,11 @@
 
 	public UnionSubclassEntityPersister(
 			final PersistentClass persistentClass, 
-			final CacheConcurrencyStrategy cache, 
+			final EntityRegionAccessStrategy cacheAccessStrategy,
 			final SessionFactoryImplementor factory,
-			final Mapping mapping)
-	throws HibernateException {
+			final Mapping mapping) throws HibernateException {
 
-		super(persistentClass, cache, factory);
+		super( persistentClass, cacheAccessStrategy, factory );
 		
 		if ( getIdentifierGenerator() instanceof IdentityGenerator ) {
 			throw new MappingException(

Modified: trunk/Hibernate3/src/org/hibernate/stat/SecondLevelCacheStatistics.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/stat/SecondLevelCacheStatistics.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/stat/SecondLevelCacheStatistics.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -5,8 +5,8 @@
 import java.util.Iterator;
 import java.util.Map;
 
-import org.hibernate.cache.Cache;
 import org.hibernate.cache.CacheKey;
+import org.hibernate.cache.Region;
 
 /**
  * Second level cache statistics of a specific region
@@ -15,14 +15,14 @@
  */
 public class SecondLevelCacheStatistics extends CategorizedStatistics {
 	
-    private transient Cache cache;
+    private transient Region region;
 	long hitCount;
 	long missCount;
 	long putCount;
 
-	SecondLevelCacheStatistics(Cache cache) {
-		super( cache.getRegionName() );
-		this.cache = cache;
+	SecondLevelCacheStatistics(Region region) {
+		super( region.getName() );
+		this.region = region;
 	}
 	public long getHitCount() {
 		return hitCount;
@@ -34,18 +34,18 @@
 		return putCount;
 	}
 	public long getElementCountInMemory() {
-		return cache.getElementCountInMemory();
+		return region.getElementCountInMemory();
 	}
 	public long getElementCountOnDisk() {
-		return cache.getElementCountOnDisk();
+		return region.getElementCountOnDisk();
 	}
 	public long getSizeInMemory() {
-		return cache.getSizeInMemory();
+		return region.getSizeInMemory();
 	}
 	
 	public Map getEntries() {
 		Map map = new HashMap();
-		Iterator iter = cache.toMap().entrySet().iterator();
+		Iterator iter = region.toMap().entrySet().iterator();
 		while ( iter.hasNext() ) {
 			Map.Entry me = (Map.Entry) iter.next();
 			map.put( ( (CacheKey) me.getKey() ).getKey(), me.getValue() );
@@ -60,7 +60,7 @@
 			.append(",missCount=").append(this.missCount)
 			.append(",putCount=").append(this.putCount);
 		//not sure if this would ever be null but wanted to be careful
-		if (this.cache != null) {
+		if ( region != null ) {
 			buf.append(",elementCountInMemory=").append(this.getElementCountInMemory())
 				.append(",elementCountOnDisk=").append(this.getElementCountOnDisk())
 				.append(",sizeInMemory=").append(this.getSizeInMemory());

Modified: trunk/Hibernate3/src/org/hibernate/stat/StatisticsImpl.java
===================================================================
--- trunk/Hibernate3/src/org/hibernate/stat/StatisticsImpl.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/src/org/hibernate/stat/StatisticsImpl.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -6,6 +6,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.hibernate.cache.Cache;
+import org.hibernate.cache.Region;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.util.ArrayHelper;
 
@@ -231,13 +232,17 @@
 	 * @return SecondLevelCacheStatistics
 	 */
 	public synchronized SecondLevelCacheStatistics getSecondLevelCacheStatistics(String regionName) {
-		SecondLevelCacheStatistics slcs = (SecondLevelCacheStatistics) secondLevelCacheStatistics.get(regionName);
-		if (slcs==null) {
-			if (sessionFactory == null) return null;
-			Cache cache = sessionFactory.getSecondLevelCacheRegion(regionName);
-			if (cache==null) return null;
-			slcs = new SecondLevelCacheStatistics(cache);
-			secondLevelCacheStatistics.put(regionName, slcs);
+		SecondLevelCacheStatistics slcs = ( SecondLevelCacheStatistics ) secondLevelCacheStatistics.get( regionName );
+		if ( slcs == null ) {
+			if ( sessionFactory == null ) {
+				return null;
+			}
+			Region region = sessionFactory.getSecondLevelCacheRegion( regionName );
+			if ( region == null ) {
+				return null;
+			}
+			slcs = new SecondLevelCacheStatistics( region );
+			secondLevelCacheStatistics.put( regionName, slcs );
 		}
 		return slcs;
 	}

Modified: trunk/Hibernate3/test/org/hibernate/test/cache/BaseCacheProviderTestCase.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/cache/BaseCacheProviderTestCase.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/test/org/hibernate/test/cache/BaseCacheProviderTestCase.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -120,7 +120,6 @@
 		Object entry = slcs.getEntries().get( i.getId() );
 		Map map;
 		if ( entry instanceof ReadWriteCache.Item ) {
-			map = new HashMap();
 			map = (Map) ( (ReadWriteCache.Item) entry ).getValue();
 		}
 		else {

Modified: trunk/Hibernate3/test/org/hibernate/test/cache/treecache/optimistic/OptimisticTreeCacheTest.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/cache/treecache/optimistic/OptimisticTreeCacheTest.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/test/org/hibernate/test/cache/treecache/optimistic/OptimisticTreeCacheTest.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -7,6 +7,7 @@
 import org.jboss.cache.optimistic.DataVersion;
 
 import org.hibernate.cache.OptimisticTreeCacheProvider;
+import org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge;
 import org.hibernate.cfg.Environment;
 import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
 import org.hibernate.test.cache.BaseCacheProviderTestCase;
@@ -51,7 +52,7 @@
 
 	public void testCacheLevelStaleWritesFail() throws Throwable {
 		Fqn fqn = new Fqn( "whatever" );
-		TreeCache treeCache = ( ( OptimisticTreeCacheProvider ) sfi().getSettings().getCacheProvider() ).getUnderlyingCache();
+		TreeCache treeCache = ( ( OptimisticTreeCacheProvider ) ( ( RegionFactoryCacheProviderBridge ) sfi().getSettings().getRegionFactory() ).getCacheProvider() ).getUnderlyingCache();
 
 		Long long1 = new Long(1);
 		Long long2 = new Long(2);

Modified: trunk/Hibernate3/test/org/hibernate/test/filter/DynamicFilterTest.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/filter/DynamicFilterTest.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/test/org/hibernate/test/filter/DynamicFilterTest.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -10,7 +10,6 @@
 import java.util.Set;
 
 import junit.framework.Test;
-import junit.framework.TestSuite;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -19,6 +18,7 @@
 import org.hibernate.Hibernate;
 import org.hibernate.Session;
 import org.hibernate.Transaction;
+import org.hibernate.engine.SessionImplementor;
 import org.hibernate.junit.functional.FunctionalTestCase;
 import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
 import org.hibernate.cache.CacheKey;
@@ -26,10 +26,8 @@
 import org.hibernate.cfg.Configuration;
 import org.hibernate.cfg.Environment;
 import org.hibernate.criterion.Expression;
-import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.impl.SessionFactoryImpl;
 import org.hibernate.persister.collection.CollectionPersister;
-import org.hibernate.test.TestCase;
 import org.hibernate.transform.DistinctRootEntityResultTransformer;
 
 /**
@@ -72,6 +70,7 @@
 		testData.prepare();
 
 		Session session = openSession();
+		long ts = ( ( SessionImplementor ) session ).getTimestamp();
 
 		// Force a collection into the second level cache, with its non-filtered elements
 		Salesperson sp = ( Salesperson ) session.load( Salesperson.class, testData.steveId );
@@ -79,21 +78,22 @@
 		CollectionPersister persister = ( ( SessionFactoryImpl ) getSessions() )
 		        .getCollectionPersister( Salesperson.class.getName() + ".orders" );
 		assertTrue( "No cache for collection", persister.hasCache() );
-		CollectionCacheEntry cachedData = ( CollectionCacheEntry ) persister.getCache().getCache()
-		        .read( new CacheKey( testData.steveId, persister.getKeyType(), persister.getRole(), EntityMode.POJO, sfi() ) );
+		CollectionCacheEntry cachedData = ( CollectionCacheEntry ) persister.getCacheAccessStrategy()
+		        .get( new CacheKey( testData.steveId, persister.getKeyType(), persister.getRole(), EntityMode.POJO, sfi() ), ts );
 		assertNotNull( "collection was not in cache", cachedData );
 
 		session.close();
 
 		session = openSession();
+		ts = ( ( SessionImplementor ) session ).getTimestamp();
 		session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
 		sp = ( Salesperson ) session.createQuery( "from Salesperson as s where s.id = :id" )
 		        .setLong( "id", testData.steveId.longValue() )
 		        .uniqueResult();
 		assertEquals( "Filtered-collection not bypassing 2L-cache", 1, sp.getOrders().size() );
 
-		CollectionCacheEntry cachedData2 = ( CollectionCacheEntry ) persister.getCache().getCache()
-		        .read( new CacheKey( testData.steveId, persister.getKeyType(), persister.getRole(), EntityMode.POJO, sfi() ) );
+		CollectionCacheEntry cachedData2 = ( CollectionCacheEntry ) persister.getCacheAccessStrategy()
+		        .get( new CacheKey( testData.steveId, persister.getKeyType(), persister.getRole(), EntityMode.POJO, sfi() ), ts );
 		assertNotNull( "collection no longer in cache!", cachedData2 );
 		assertSame( "Different cache values!", cachedData, cachedData2 );
 

Modified: trunk/Hibernate3/test/org/hibernate/test/legacy/CacheTest.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/legacy/CacheTest.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/test/org/hibernate/test/legacy/CacheTest.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -9,7 +9,7 @@
 import org.hibernate.cache.CacheProvider;
 import org.hibernate.cache.ReadWriteCache;
 import org.hibernate.cache.HashtableCacheProvider;
-import org.hibernate.cache.CacheConcurrencyStrategy.SoftLock;
+import org.hibernate.cache.access.SoftLock;
 import org.hibernate.junit.UnitTestCase;
 
 public class CacheTest extends UnitTestCase {

Modified: trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.java
===================================================================
--- trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.java	2007-04-10 09:36:19 UTC (rev 11397)
+++ trunk/Hibernate3/test/org/hibernate/test/legacy/CustomPersister.java	2007-04-10 14:54:07 UTC (rev 11398)
@@ -13,6 +13,7 @@
 import org.hibernate.MappingException;
 import org.hibernate.tuple.entity.EntityMetamodel;
 import org.hibernate.cache.CacheConcurrencyStrategy;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
 import org.hibernate.cache.entry.CacheEntryStructure;
 import org.hibernate.cache.entry.UnstructuredCacheEntry;
 import org.hibernate.engine.CascadeStyle;
@@ -45,7 +46,7 @@
 
 	public CustomPersister(
 			PersistentClass model, 
-			CacheConcurrencyStrategy cache, 
+			EntityRegionAccessStrategy cacheAccessStrategy,
 			SessionFactoryImplementor factory, 
 			Mapping mapping) {
 		this.factory = factory;
@@ -421,23 +422,14 @@
 		return "id";
 	}
 
-	/**
-	 * @see EntityPersister#hasCache()
-	 */
 	public boolean hasCache() {
 		return false;
 	}
 
-	/**
-	 * @see EntityPersister#getCache()
-	 */
-	public CacheConcurrencyStrategy getCache() {
+	public EntityRegionAccessStrategy getCacheAccessStrategy() {
 		return null;
 	}
 
-	/**
-	 * @see EntityPersister#getRootEntityName()
-	 */
 	public String getRootEntityName() {
 		return "CUSTOMS";
 	}




More information about the hibernate-commits mailing list