[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.getSessio