[jboss-cvs] JBossAS SVN: r58550 - trunk/ejb3/src/main/org/jboss/ejb3/entity

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sat Nov 18 06:17:52 EST 2006


Author: bstansberry at jboss.com
Date: 2006-11-18 06:17:49 -0500 (Sat, 18 Nov 2006)
New Revision: 58550

Added:
   trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java
   trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCacheFactory.java
   trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticJBCCache.java
   trunk/ejb3/src/main/org/jboss/ejb3/entity/TransactionalCacheFactory.java
Log:
Add Hibernate Cache impls that can talk to JBC 2.0

Added: trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java
===================================================================
--- trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java	2006-11-18 11:17:07 UTC (rev 58549)
+++ trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCache.java	2006-11-18 11:17:49 UTC (rev 58550)
@@ -0,0 +1,228 @@
+package org.jboss.ejb3.entity;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.OptimisticCache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.Node;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.lock.TimeoutException;
+
+/**
+ * {@link Cache} implementation that uses a 2.x or later release of JBoss Cache.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1.1 $
+ */
+public class JBCCache implements Cache
+{
+    
+    private static final Log log = LogFactory.getLog(JBCCache.class);
+
+    private static final String ITEM = "item";
+
+    private org.jboss.cache.Cache cache;
+    private final String regionName;
+    private final Fqn regionFqn;
+    private final TransactionManager transactionManager;
+
+    public JBCCache(org.jboss.cache.Cache cache, String regionName, TransactionManager transactionManager) 
+    throws CacheException {
+        this.cache = cache;
+        this.regionName = regionName;
+        this.regionFqn = Fqn.fromString( regionName.replace( '.', '/' ) );
+        this.transactionManager = transactionManager;
+    }
+
+    public Object get(Object key) throws CacheException {
+        Transaction tx = suspend();
+        try {
+            return read(key);
+        }
+        finally {
+            resume( tx );
+        }
+    }
+    
+    public Object read(Object key) throws CacheException {
+        try {
+            return cache.get( new Fqn( regionFqn, key ), ITEM );
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    public void update(Object key, Object value) throws CacheException {
+        try {
+            cache.put( new Fqn( regionFqn, key ), ITEM, value );
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    public void put(Object key, Object value) throws CacheException {
+        Transaction tx = suspend();
+        try {
+            //do the failfast put outside the scope of the JTA txn
+            cache.putForExternalRead(new Fqn( regionFqn, key ), ITEM, value);
+        }
+        catch (TimeoutException te) {
+            //ignore!
+            log.debug("ignoring write lock acquisition failure");
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+        finally {
+            resume( tx );
+        }
+    }
+
+    private void resume(Transaction tx) {
+        try {
+            if (tx!=null) transactionManager.resume(tx);
+        }
+        catch (Exception e) {
+            throw new CacheException("Could not resume transaction", e);
+        }
+    }
+
+    private Transaction suspend() {
+        Transaction tx = null;
+        try {
+            if ( transactionManager!=null ) {
+                tx = transactionManager.suspend();
+            }
+        }
+        catch (SystemException se) {
+            throw new CacheException("Could not suspend transaction", se);
+        }
+        return tx;
+    }
+
+    public void remove(Object key) throws CacheException {
+        try {
+            cache.removeNode( new Fqn( regionFqn, key ) );
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    public void clear() throws CacheException {
+        try {
+            cache.removeNode( regionFqn );
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    public void destroy() throws CacheException {
+        try {
+            // NOTE : evict() operates locally only (i.e., does not propogate
+            // to any other nodes in the potential cluster).  This is
+            // exactly what is needed when we destroy() here; destroy() is used
+            // as part of the process of shutting down a SessionFactory; thus
+            // these removals should not be propogated
+           // FIXME NPE bug in 2.0.0.ALPHA1, so we don't use evict 'til fixed
+//            cache.evict( regionFqn, true );
+           InvocationContext ctx = cache.getInvocationContext();
+           Option opt = new Option();
+           opt.setCacheModeLocal(true);
+           ctx.setOptionOverrides(opt);
+           cache.removeNode( regionFqn );
+        }
+        catch( Exception e ) {
+            throw new CacheException( e );
+        }
+    }
+
+    public void lock(Object key) throws CacheException {
+        throw new UnsupportedOperationException( "TreeCache is a fully transactional cache" + regionName );
+    }
+
+    public void unlock(Object key) throws CacheException {
+        throw new UnsupportedOperationException( "TreeCache is a fully transactional cache: " + regionName );
+    }
+
+    public long nextTimestamp() {
+        return System.currentTimeMillis() / 100;
+    }
+
+    public int getTimeout() {
+        return 600; //60 seconds
+    }
+
+    public String getRegionName() {
+        return regionName;
+    }
+
+    public long getSizeInMemory() {
+        return -1;
+    }
+
+    public long getElementCountInMemory() {
+        try {
+            Set children = getChildrenNames();
+            return children == null ? 0 : children.size();
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    public long getElementCountOnDisk() {
+        return 0;
+    }
+    
+    public Map toMap() {
+        try {
+            Map result = new HashMap();
+            Set childrenNames = getChildrenNames();
+            if (childrenNames != null) {
+                Iterator iter = childrenNames.iterator();
+                while ( iter.hasNext() ) {
+                    Object key = iter.next();
+                    result.put( 
+                            key, 
+                            cache.get( new Fqn( regionFqn, key ), ITEM )
+                        );
+                }
+            }
+            return result;
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+    
+    private Set getChildrenNames()
+    {
+       try {
+          Node base = cache.getChild( regionFqn );
+          return base == null ? null : base.getChildrenNames();
+       }
+       catch (Exception e) {
+          throw new CacheException(e);
+       }   
+    }
+    
+    public String toString() {
+        return "JBCCache(" + regionName + ')';
+    }
+}

Added: trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCacheFactory.java
===================================================================
--- trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCacheFactory.java	2006-11-18 11:17:07 UTC (rev 58549)
+++ trunk/ejb3/src/main/org/jboss/ejb3/entity/JBCCacheFactory.java	2006-11-18 11:17:49 UTC (rev 58550)
@@ -0,0 +1,51 @@
+package org.jboss.ejb3.entity;
+
+import java.util.Properties;
+
+import javax.management.ObjectName;
+
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.CacheException;
+import org.jboss.cache.jmx.CacheJmxWrapperMBean;
+import org.jboss.ejb3.tx.TxUtil;
+import org.jboss.mx.util.MBeanProxyExt;
+import org.jboss.mx.util.MBeanServerLocator;
+
+class JBCCacheFactory extends TransactionalCacheFactory
+{
+   private org.jboss.cache.Cache cache;
+   private boolean optimistic;
+   
+   JBCCacheFactory()
+   {
+       
+   }
+   
+   protected void configure(Properties hibernateConfig)
+   {
+       try
+       {
+          ObjectName mbeanObjectName = new ObjectName((String) hibernateConfig.get("hibernate.treecache.mbean.object_name"));
+          CacheJmxWrapperMBean mbean = (CacheJmxWrapperMBean) MBeanProxyExt.create(CacheJmxWrapperMBean.class, mbeanObjectName, MBeanServerLocator.locateJBoss());
+          cache = mbean.getCache();
+          optimistic = cache.getConfiguration().isNodeLockingOptimistic();
+       }
+       catch (Exception e)
+       {
+          throw new CacheException(e);
+       }      
+   }
+   
+   public Cache buildCache(String regionName, Properties properties) throws CacheException
+   {
+//      if (optimistic)
+//      {
+//         return new OptimisticJBCCache(cache, regionName);
+//      }
+//      else
+//      {
+         return new JBCCache(cache, regionName, TxUtil.getTransactionManager());
+//      }
+   }
+
+}

Added: trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticJBCCache.java
===================================================================
--- trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticJBCCache.java	2006-11-18 11:17:07 UTC (rev 58549)
+++ trunk/ejb3/src/main/org/jboss/ejb3/entity/OptimisticJBCCache.java	2006-11-18 11:17:49 UTC (rev 58550)
@@ -0,0 +1,409 @@
+package org.jboss.ejb3.entity;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.OptimisticCache;
+import org.hibernate.cache.OptimisticCacheSource;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.Node;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.lock.TimeoutException;
+import org.jboss.cache.optimistic.DataVersion;
+
+public class OptimisticJBCCache implements OptimisticCache
+{
+    // todo : eventually merge this with TreeCache and just add optional opt-lock support there.
+
+    private static final Log log = LogFactory.getLog( OptimisticJBCCache.class);
+
+    private static final String ITEM = "item";
+
+    private static final Option NONLOCKING_OPTION = new Option();
+    private static final Option FAIL_SILENT_OPTION = new Option();
+    private static final Option FAIL_SILENT_NONLOCKING_OPTION = new Option();
+    
+    static
+    {
+       FAIL_SILENT_OPTION.setFailSilently( true );
+       
+       FAIL_SILENT_NONLOCKING_OPTION.setFailSilently( true );
+       FAIL_SILENT_NONLOCKING_OPTION.setDataVersion( NonLockingDataVersion.INSTANCE );
+       NONLOCKING_OPTION.setDataVersion( NonLockingDataVersion.INSTANCE );        
+    }
+    
+    private org.jboss.cache.Cache cache;
+    private final String regionName;
+    private final Fqn regionFqn;
+    private OptimisticCacheSource source;
+
+    public OptimisticJBCCache(org.jboss.cache.Cache cache, String regionName)
+    throws CacheException {
+        this.cache = cache;
+        this.regionName = regionName;
+        this.regionFqn = Fqn.fromString( regionName.replace( '.', '/' ) );
+    }
+
+
+    // OptimisticCache impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    public void setSource(OptimisticCacheSource source) {
+        this.source = source;
+    }
+
+    public void writeInsert(Object key, Object value, Object currentVersion) {
+        writeUpdate( key, value, currentVersion, null );
+    }
+
+    public void writeUpdate(Object key, Object value, Object currentVersion, Object previousVersion) 
+    {
+       InvocationContext ctx = cache.getInvocationContext();
+       Option existing = ctx.getOptionOverrides();
+        try {
+            Option option = new Option();
+            DataVersion dv = ( source != null && source.isVersioned() )
+                             ? new DataVersionAdapter( currentVersion, previousVersion, source.getVersionComparator(), source.toString() )
+                             : NonLockingDataVersion.INSTANCE;
+            option.setDataVersion( dv );
+            
+            ctx.setOptionOverrides(option);
+            cache.put( new Fqn( regionFqn, key ), ITEM, value);
+        }
+        catch ( Exception e ) {
+            throw new CacheException( e );
+        }
+        finally
+        {
+           ctx.setOptionOverrides(existing);
+        }
+    }
+
+    public void writeLoad(Object key, Object value, Object currentVersion) 
+    {
+       InvocationContext ctx = cache.getInvocationContext();
+       Option existing = ctx.getOptionOverrides();
+        try {
+           
+            ctx.setOptionOverrides(FAIL_SILENT_NONLOCKING_OPTION);
+            cache.remove( new Fqn( regionFqn, key ), "ITEM");
+
+            Option option = new Option();
+            option.setFailSilently( true );
+            DataVersion dv = ( source != null && source.isVersioned() )
+                             ? new DataVersionAdapter( currentVersion, currentVersion, source.getVersionComparator(), source.toString() )
+                             : NonLockingDataVersion.INSTANCE;
+            option.setDataVersion( dv );
+            
+            ctx = cache.getInvocationContext();
+            ctx.setOptionOverrides(option);
+            cache.put( new Fqn( regionFqn, key ), ITEM, value);
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+        finally
+        {
+           ctx.setOptionOverrides(existing);
+        }
+    }
+
+
+    // Cache impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    public Object get(Object key) throws CacheException 
+    {
+       InvocationContext ctx = cache.getInvocationContext();
+       Option existing = ctx.getOptionOverrides();
+        try {
+            
+//            ctx.setOptionOverrides(FAIL_SILENT_NONLOCKING_OPTION);
+            ctx.setOptionOverrides(FAIL_SILENT_OPTION);
+            return cache.get( new Fqn( regionFqn, key ), ITEM);
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+        finally
+        {
+           ctx.setOptionOverrides(existing);
+        }
+    }
+
+    public Object read(Object key) throws CacheException {
+        try {
+            return cache.get( new Fqn( regionFqn, key ), ITEM );
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    public void update(Object key, Object value) throws CacheException 
+    {
+       InvocationContext ctx = cache.getInvocationContext();
+       Option existing = ctx.getOptionOverrides();
+        try {
+            ctx.setOptionOverrides(NONLOCKING_OPTION);
+            cache.put( new Fqn( regionFqn, key ), ITEM, value );
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+        finally
+        {
+           ctx.setOptionOverrides(existing);
+        }
+    }
+
+    public void put(Object key, Object value) throws CacheException 
+    {
+       InvocationContext ctx = cache.getInvocationContext();
+       Option existing = ctx.getOptionOverrides();
+        try {
+            log.trace( "performing put() into region [" + regionName + "]" );
+            // do the put outside the scope of the JTA txn
+            ctx.setOptionOverrides(FAIL_SILENT_NONLOCKING_OPTION);
+            cache.put( new Fqn( regionFqn, key ), ITEM, value );
+        }
+        catch (TimeoutException te) {
+            //ignore!
+            log.debug("ignoring write lock acquisition failure");
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+        finally
+        {
+           ctx.setOptionOverrides(existing);
+        }
+    }
+
+    public void remove(Object key) throws CacheException 
+    {
+       InvocationContext ctx = cache.getInvocationContext();
+       Option existing = ctx.getOptionOverrides();
+        try {
+            // tree cache in optimistic mode seems to have as very difficult
+            // time with remove calls on non-existent nodes (NPEs)...
+            if ( cache.get( new Fqn( regionFqn, key ), ITEM ) != null ) {
+                Option option = new Option();
+                option.setDataVersion( NonLockingDataVersion.INSTANCE );
+                ctx.setOptionOverrides(option);
+                cache.removeNode( new Fqn( regionFqn, key ) );
+            }
+            else {
+                log.trace( "skipping remove() call as the underlying node did not seem to exist" );
+            }
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+        finally
+        {
+           ctx.setOptionOverrides(existing);
+        }
+    }
+
+    public void clear() throws CacheException 
+    {
+       InvocationContext ctx = cache.getInvocationContext();
+       Option existing = ctx.getOptionOverrides();
+        try {
+            Option option = new Option();
+            option.setDataVersion( NonLockingDataVersion.INSTANCE );
+            ctx.setOptionOverrides(option);
+            cache.removeNode( regionFqn );
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+        finally
+        {
+           ctx.setOptionOverrides(existing);
+        }
+    }
+
+    public void destroy() throws CacheException 
+    {
+       InvocationContext ctx = cache.getInvocationContext();
+       Option existing = ctx.getOptionOverrides();
+        try {
+            Option option = new Option();
+            option.setCacheModeLocal( true );
+            option.setFailSilently( true );
+            option.setDataVersion( NonLockingDataVersion.INSTANCE );
+            ctx.setOptionOverrides(option);
+            cache.removeNode( regionFqn );
+        }
+        catch( Exception e ) {
+            throw new CacheException( e );
+        }
+        finally
+        {
+           ctx.setOptionOverrides(existing);
+        }
+    }
+
+    public void lock(Object key) throws CacheException {
+        throw new UnsupportedOperationException( "TreeCache is a fully transactional cache" + regionName );
+    }
+
+    public void unlock(Object key) throws CacheException {
+        throw new UnsupportedOperationException( "TreeCache is a fully transactional cache: " + regionName );
+    }
+
+    public long nextTimestamp() {
+        return System.currentTimeMillis() / 100;
+    }
+
+    public int getTimeout() {
+        return 600; //60 seconds
+    }
+
+    public String getRegionName() {
+        return regionName;
+    }
+
+    public long getSizeInMemory() {
+        return -1;
+    }
+
+    public long getElementCountInMemory() {
+        try {
+            Set children = getChildrenNames();
+            return children == null ? 0 : children.size();
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+
+    public long getElementCountOnDisk() {
+        return 0;
+    }
+
+    public Map toMap() {
+        try {
+            Map result = new HashMap();
+            Set childrenNames = getChildrenNames();
+            if (childrenNames != null) {
+                Iterator iter = childrenNames.iterator();
+                while ( iter.hasNext() ) {
+                    Object key = iter.next();
+                    result.put(
+                            key,
+                            cache.get( new Fqn( regionFqn, key ), ITEM )
+                        );
+                }
+            }
+            return result;
+        }
+        catch (Exception e) {
+            throw new CacheException(e);
+        }
+    }
+    
+    private Set getChildrenNames()
+    {
+       try {
+          Node base = cache.getChild( regionFqn );
+          return base == null ? null : base.getChildrenNames();
+       }
+       catch (Exception e) {
+          throw new CacheException(e);
+       }   
+    }
+
+    public String toString() {
+        return "OptimisticTreeCache(" + regionName + ')';
+    }
+
+    public static class DataVersionAdapter implements DataVersion {
+        private final Object currentVersion;
+        private final Object previousVersion;
+        private final Comparator versionComparator;
+        private final String sourceIdentifer;
+
+        public DataVersionAdapter(Object currentVersion, Object previousVersion, Comparator versionComparator, String sourceIdentifer) {
+            this.currentVersion = currentVersion;
+            this.previousVersion = previousVersion;
+            this.versionComparator = versionComparator;
+            this.sourceIdentifer = sourceIdentifer;
+            log.trace( "created " + this );
+        }
+
+        /**
+         * newerThan() call is dispatched against the DataVersion currently
+         * associated with the node; the passed dataVersion param is the
+         * DataVersion associated with the data we are trying to put into
+         * the node.
+         * <p/>
+         * we are expected to return true in the case where we (the current
+         * node DataVersion) are newer that then incoming value.  Returning
+         * true here essentially means that a optimistic lock failure has
+         * occured (because conversely, the value we are trying to put into
+         * the node is "older than" the value already there...)
+         */
+        public boolean newerThan(DataVersion dataVersion) {
+            log.trace( "checking [" + this + "] against [" + dataVersion + "]" );
+            if ( dataVersion instanceof CircumventChecksDataVersion ) {
+                log.trace( "skipping lock checks..." );
+                return false;
+            }
+            else if ( dataVersion instanceof NonLockingDataVersion ) {
+                // can happen because of the multiple ways Cache.remove()
+                // can be invoked :(
+                log.trace( "skipping lock checks..." );
+                return false;
+            }
+            DataVersionAdapter other = ( DataVersionAdapter ) dataVersion;
+            if ( other.previousVersion == null ) {
+                log.warn( "Unexpected optimistic lock check on inserting data" );
+                // work around the "feature" where tree cache is validating the
+                // inserted node during the next transaction.  no idea...
+                if ( this == dataVersion ) {
+                    log.trace( "skipping lock checks due to same DV instance" );
+                    return false;
+                }
+            }
+            return versionComparator.compare( currentVersion, other.previousVersion ) >= 1;
+        }
+
+        public String toString() {
+            return super.toString() + " [current=" + currentVersion + ", previous=" + previousVersion + ", src=" + sourceIdentifer + "]";
+        }
+    }
+
+    /**
+     * Used in regions where no locking should ever occur.  This includes query-caches,
+     * update-timestamps caches, collection caches, and entity caches where the entity
+     * is not versioned.
+     */
+    public static class NonLockingDataVersion implements DataVersion {
+        public static final DataVersion INSTANCE = new NonLockingDataVersion();
+        public boolean newerThan(DataVersion dataVersion) {
+            log.trace( "non locking lock check...");
+            return false;
+        }
+    }
+
+    /**
+     * Used to signal to a DataVersionAdapter to simply not perform any checks.  This
+     * is currently needed for proper handling of remove() calls for entity cache regions
+     * (we do not know the version info...).
+     */
+    public static class CircumventChecksDataVersion implements DataVersion {
+        public static final DataVersion INSTANCE = new CircumventChecksDataVersion();
+        public boolean newerThan(DataVersion dataVersion) {
+            throw new CacheException( "optimistic locking checks should never happen on CircumventChecksDataVersion" );
+        }
+    }
+
+}

Added: trunk/ejb3/src/main/org/jboss/ejb3/entity/TransactionalCacheFactory.java
===================================================================
--- trunk/ejb3/src/main/org/jboss/ejb3/entity/TransactionalCacheFactory.java	2006-11-18 11:17:07 UTC (rev 58549)
+++ trunk/ejb3/src/main/org/jboss/ejb3/entity/TransactionalCacheFactory.java	2006-11-18 11:17:49 UTC (rev 58550)
@@ -0,0 +1,76 @@
+package org.jboss.ejb3.entity;
+
+import java.util.Properties;
+
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.CacheException;
+import org.jboss.cache.Version;
+
+public abstract class TransactionalCacheFactory
+{
+
+   /**
+    * Gets and configures a concrete TransactionalCacheFactory suitable for 
+    * interoperation with the version of JBoss Cache visible on the classpath.
+    * 
+    * @param hibernateConfig properties to use to {@link #configure(Properties) configure}
+    *                        the factory.
+    * @return the factory
+    * 
+    * @throws CacheException
+    */
+   public static TransactionalCacheFactory getFactory(Properties hibernateConfig) throws CacheException
+   {
+      String factoryClass = null;
+      short version = Version.getVersionShort();
+      if (version >= Version.getVersionShort("2.0.0.GA") || version <= 0)
+      {
+         factoryClass = "org.jboss.ejb3.entity.JBCCacheFactory";
+      }
+      else
+      {
+         // TODO write a factory for the old hibernate stuff
+         // needs to be in a separate code tree from JBCCacheFactory as 
+         // TreeCacheMBean is no longer available in 2.0
+         throw new IllegalStateException("Cannot create factory for JBC 1.x");
+      }
+      
+      try
+      {
+         Class clazz = Thread.currentThread().getContextClassLoader().loadClass(factoryClass);
+         TransactionalCacheFactory factory = (TransactionalCacheFactory) clazz.newInstance();
+         factory.configure(hibernateConfig);
+         
+         return factory;
+      }
+      catch (CacheException e)
+      {
+         throw e;
+      }
+      catch (Exception e)
+      {
+         throw new CacheException(e);
+      }
+      
+   }
+   
+   /**
+    * Construct and configure the Cache representation of a named cache region.
+    *
+    * @param regionName the name of the cache region
+    * @param properties configuration settings
+    * @return The Cache representation of the named cache region.
+    * @throws org.hibernate.cache.CacheException
+    *          Indicates an error building the cache region.
+    */
+   public abstract Cache buildCache(String regionName, Properties properties) throws CacheException;
+   
+   /**
+    * Configures the factory using the Hibernate configuration properties.  
+    * Called by {@link #getFactory(Properties)}.
+    *  
+    * @param hibernateConfig the Hibernate configuration properties
+    */
+   protected abstract void configure(Properties hibernateConfig);
+   
+}




More information about the jboss-cvs-commits mailing list