[hibernate-commits] Hibernate SVN: r20652 - in core/branches/Branch_3_5/cache-infinispan/src: main/java/org/hibernate/cache/infinispan/impl and 4 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Sep 16 13:05:14 EDT 2010


Author: galder.zamarreno at jboss.com
Date: 2010-09-16 13:05:14 -0400 (Thu, 16 Sep 2010)
New Revision: 20652

Added:
   core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/ClassLoaderAwareCache.java
   core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/JndiRegionFactoryTestCase.java
Modified:
   core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java
   core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/FlagAdapter.java
   core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/JndiInfinispanRegionFactoryTestCase.java
   core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicJdbcTransactionalTestCase.java
   core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java
   core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java
   core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/SingleNodeTestCase.java
   core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java
Log:
[HHH-5552] (Infinispan listener implementations need to load entities and keys using application classloader) A wrapper class now puts the right classloader for listener calls.
[HHH-5563] (JndiInfinispanRegionFactory creates region with a stopped cache, if region previously existed) A check was added to start the cache if no invocations are allowed any more.

Modified: core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java
===================================================================
--- core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java	2010-09-16 16:53:09 UTC (rev 20651)
+++ core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java	2010-09-16 17:05:14 UTC (rev 20652)
@@ -21,6 +21,7 @@
 import org.hibernate.cache.access.AccessType;
 import org.hibernate.cache.infinispan.collection.CollectionRegionImpl;
 import org.hibernate.cache.infinispan.entity.EntityRegionImpl;
+import org.hibernate.cache.infinispan.impl.ClassLoaderAwareCache;
 import org.hibernate.cache.infinispan.query.QueryResultsRegionImpl;
 import org.hibernate.cache.infinispan.timestamp.TimestampsRegionImpl;
 import org.hibernate.cache.infinispan.timestamp.TimestampTypeOverrides;
@@ -29,6 +30,7 @@
 import org.hibernate.cache.infinispan.util.CacheAdapterImpl;
 import org.hibernate.cfg.Settings;
 import org.hibernate.util.PropertiesHelper;
+import org.infinispan.AdvancedCache;
 import org.infinispan.Cache;
 import org.infinispan.config.Configuration;
 import org.infinispan.manager.DefaultCacheManager;
@@ -203,11 +205,19 @@
       if (log.isDebugEnabled()) log.debug("Building timestamps cache region [" + regionName + "]");
       Cache cache = getCache(regionName, TIMESTAMPS_KEY, properties);
       CacheAdapter cacheAdapter = CacheAdapterImpl.newInstance(cache);
-      TimestampsRegionImpl region = new TimestampsRegionImpl(cacheAdapter, regionName, transactionManager, this);
+      TimestampsRegionImpl region = createTimestampsRegion(cacheAdapter, regionName);
       region.start();
       return region;
    }
 
+   protected TimestampsRegionImpl createTimestampsRegion(CacheAdapter cacheAdapter, String regionName) {
+      return new TimestampsRegionImpl(cacheAdapter, regionName, transactionManager, this);
+   }
+
+   protected TransactionManager getTransactionManager() {
+      return transactionManager;
+   }
+
    /**
     * {@inheritDoc}
     */
@@ -393,9 +403,17 @@
          manager.defineConfiguration(regionName, templateCacheName, regionCacheCfg);
          definedConfigurations.add(regionName);
       }
-      return manager.getCache(regionName);
+      Cache cache = manager.getCache(regionName);
+      if (!cache.getStatus().allowInvocations()) {
+         cache.start();
+      }
+      return createCacheWrapper(cache.getAdvancedCache());
    }
 
+   protected ClassLoaderAwareCache createCacheWrapper(AdvancedCache cache) {
+      return new ClassLoaderAwareCache(cache, Thread.currentThread().getContextClassLoader());
+   }
+
    private Configuration configureTransactionManager(Configuration regionOverrides, String templateCacheName, Properties properties) {
       // Get existing configuration to verify whether a tm was configured or not.
       Configuration templateConfig = manager.defineConfiguration(templateCacheName, new Configuration());

Added: core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/ClassLoaderAwareCache.java
===================================================================
--- core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/ClassLoaderAwareCache.java	                        (rev 0)
+++ core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/ClassLoaderAwareCache.java	2010-09-16 17:05:14 UTC (rev 20652)
@@ -0,0 +1,170 @@
+package org.hibernate.cache.infinispan.impl;
+
+import java.lang.annotation.Annotation;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.infinispan.AbstractDelegatingAdvancedCache;
+import org.infinispan.AdvancedCache;
+import org.infinispan.commands.VisitableCommand;
+import org.infinispan.context.InvocationContext;
+import org.infinispan.interceptors.base.CommandInterceptor;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryActivated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryEvicted;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryInvalidated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryLoaded;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryPassivated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited;
+import org.infinispan.notifications.cachelistener.event.Event;
+import org.infinispan.stats.Stats;
+
+/**
+ * @author Paul Ferraro
+ */
+public class ClassLoaderAwareCache<K, V> extends AbstractDelegatingAdvancedCache<K, V> {
+   final WeakReference<ClassLoader> classLoaderRef;
+
+   public ClassLoaderAwareCache(AdvancedCache<K, V> cache, ClassLoader classLoader) {
+      super(cache);
+      this.classLoaderRef = new WeakReference<ClassLoader>(classLoader);
+      cache.removeInterceptor(ClassLoaderAwareCommandInterceptor.class);
+      cache.addInterceptor(new ClassLoaderAwareCommandInterceptor(), 0);
+   }
+
+   @Override
+   public Stats getStats() {
+      return this.getAdvancedCache().getStats();
+   }
+
+   @Override
+   public void stop() {
+      super.stop();
+      this.classLoaderRef.clear();
+   }
+
+   @Override
+   public void addListener(Object listener) {
+      super.addListener(new ClassLoaderAwareListener(listener, this));
+   }
+
+   void setContextClassLoader(final ClassLoader classLoader) {
+      PrivilegedAction<Void> action = new PrivilegedAction<Void>() {
+         @Override
+         public Void run() {
+            Thread.currentThread().setContextClassLoader(classLoader);
+            return null;
+         }
+      };
+      AccessController.doPrivileged(action);
+   }
+
+   private class ClassLoaderAwareCommandInterceptor extends CommandInterceptor {
+      @Override
+      protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
+         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+         ClassLoaderAwareCache.this.setContextClassLoader(ClassLoaderAwareCache.this.classLoaderRef.get());
+         try {
+            return super.handleDefault(ctx, command);
+         }
+         finally {
+            ClassLoaderAwareCache.this.setContextClassLoader(classLoader);
+         }
+      }
+   }
+
+   static final Map<Class<? extends Annotation>, Event.Type> events = new HashMap<Class<? extends Annotation>, Event.Type>();
+
+   static {
+      events.put(CacheEntryActivated.class, Event.Type.CACHE_ENTRY_ACTIVATED);
+      events.put(CacheEntryCreated.class, Event.Type.CACHE_ENTRY_CREATED);
+      events.put(CacheEntryEvicted.class, Event.Type.CACHE_ENTRY_EVICTED);
+      events.put(CacheEntryInvalidated.class, Event.Type.CACHE_ENTRY_INVALIDATED);
+      events.put(CacheEntryLoaded.class, Event.Type.CACHE_ENTRY_LOADED);
+      events.put(CacheEntryModified.class, Event.Type.CACHE_ENTRY_MODIFIED);
+      events.put(CacheEntryPassivated.class, Event.Type.CACHE_ENTRY_PASSIVATED);
+      events.put(CacheEntryRemoved.class, Event.Type.CACHE_ENTRY_REMOVED);
+      events.put(CacheEntryVisited.class, Event.Type.CACHE_ENTRY_VISITED);
+   }
+
+   @Listener
+   public static class ClassLoaderAwareListener {
+      private final Object listener;
+      private final Map<Event.Type, List<Method>> methods = new EnumMap<Event.Type, List<Method>>(Event.Type.class);
+      private final ClassLoaderAwareCache cache;
+
+      public ClassLoaderAwareListener(Object listener, ClassLoaderAwareCache cache) {
+         this.listener = listener;
+         this.cache = cache;
+         for (Method method : listener.getClass().getMethods()) {
+            for (Map.Entry<Class<? extends Annotation>, Event.Type> entry : events.entrySet()) {
+               Class<? extends Annotation> annotation = entry.getKey();
+               if (method.isAnnotationPresent(annotation)) {
+                  List<Method> methods = this.methods.get(entry.getValue());
+                  if (methods == null) {
+                     methods = new LinkedList<Method>();
+                     this.methods.put(entry.getValue(), methods);
+                  }
+                  methods.add(method);
+               }
+            }
+         }
+      }
+
+      @CacheEntryActivated
+      @CacheEntryCreated
+      @CacheEntryEvicted
+      @CacheEntryInvalidated
+      @CacheEntryLoaded
+      @CacheEntryModified
+      @CacheEntryPassivated
+      @CacheEntryRemoved
+      @CacheEntryVisited
+      public void event(Event event) throws Throwable {
+         List<Method> methods = this.methods.get(event.getType());
+         if (methods != null) {
+            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+            ClassLoader visible = (ClassLoader) cache.classLoaderRef.get();
+            cache.setContextClassLoader(visible);
+            try {
+               for (Method method : this.methods.get(event.getType())) {
+                  try {
+                     method.invoke(this.listener, event);
+                  }
+                  catch (InvocationTargetException e) {
+                     throw e.getCause();
+                  }
+               }
+            }
+            finally {
+               cache.setContextClassLoader(classLoader);
+            }
+         }
+      }
+
+      public int hashCode() {
+         return this.listener.hashCode();
+      }
+
+      public boolean equals(Object object) {
+         if (object == null) return false;
+         if (object instanceof ClassLoaderAwareCache.ClassLoaderAwareListener) {
+            @SuppressWarnings("unchecked")
+            ClassLoaderAwareListener listener = (ClassLoaderAwareListener) object;
+            return this.listener.equals(listener.listener);
+         }
+         return this.listener.equals(object);
+      }
+   }
+}

Modified: core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/FlagAdapter.java
===================================================================
--- core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/FlagAdapter.java	2010-09-16 16:53:09 UTC (rev 20651)
+++ core/branches/Branch_3_5/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/FlagAdapter.java	2010-09-16 17:05:14 UTC (rev 20652)
@@ -34,7 +34,8 @@
 public enum FlagAdapter {
    ZERO_LOCK_ACQUISITION_TIMEOUT,
    CACHE_MODE_LOCAL,
-   FORCE_ASYNCHRONOUS;
+   FORCE_ASYNCHRONOUS,
+   FORCE_SYNCHRONOUS;
    
    Flag toFlag() {
       switch(this) {
@@ -44,6 +45,8 @@
             return Flag.CACHE_MODE_LOCAL;
          case FORCE_ASYNCHRONOUS:
             return Flag.FORCE_ASYNCHRONOUS;
+         case FORCE_SYNCHRONOUS:
+            return Flag.FORCE_SYNCHRONOUS;
          default:
             throw new CacheException("Unmatched Infinispan flag " + this);
       }

Modified: core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/JndiInfinispanRegionFactoryTestCase.java
===================================================================
--- core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/JndiInfinispanRegionFactoryTestCase.java	2010-09-16 16:53:09 UTC (rev 20651)
+++ core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/JndiInfinispanRegionFactoryTestCase.java	2010-09-16 17:05:14 UTC (rev 20652)
@@ -8,8 +8,8 @@
 /**
  * // TODO: Document this
  *
- * @author Galder Zamarre�o
- * @since // TODO
+ * @author Galder Zamarreño
+ * @since 3.5
  */
 public class JndiInfinispanRegionFactoryTestCase extends TestCase {
 

Modified: core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicJdbcTransactionalTestCase.java
===================================================================
--- core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicJdbcTransactionalTestCase.java	2010-09-16 16:53:09 UTC (rev 20651)
+++ core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicJdbcTransactionalTestCase.java	2010-09-16 17:05:14 UTC (rev 20652)
@@ -107,4 +107,14 @@
          s.close();
       }
    }
+
+   public void testEmptySecondLevelCacheEntry() throws Exception {
+      getSessions().getCache().evictEntityRegion(Item.class.getName());
+      Statistics stats = getSessions().getStatistics();
+      stats.clear();
+      SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics(Item.class.getName() + ".items");
+      Map cacheEntries = statistics.getEntries();
+      assertEquals(0, cacheEntries.size());
+   }
+   
 }

Modified: core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java
===================================================================
--- core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java	2010-09-16 16:53:09 UTC (rev 20651)
+++ core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java	2010-09-16 17:05:14 UTC (rev 20652)
@@ -1,5 +1,10 @@
 package org.hibernate.test.cache.infinispan.functional;
 
+import org.hibernate.stat.SecondLevelCacheStatistics;
+import org.hibernate.stat.Statistics;
+
+import java.util.Map;
+
 /**
  * @author Galder Zamarreño
  * @since 3.5
@@ -15,4 +20,13 @@
       return "read-only";
    }
 
+   public void testEmptySecondLevelCacheEntry() throws Exception {
+      getSessions().getCache().evictEntityRegion(Item.class.getName());
+      Statistics stats = getSessions().getStatistics();
+      stats.clear();
+      SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics(Item.class.getName() + ".items");
+      Map cacheEntries = statistics.getEntries();
+      assertEquals(0, cacheEntries.size());
+   }
+   
 }
\ No newline at end of file

Modified: core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java
===================================================================
--- core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java	2010-09-16 16:53:09 UTC (rev 20651)
+++ core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java	2010-09-16 17:05:14 UTC (rev 20652)
@@ -339,5 +339,15 @@
       } finally {
          commitOrRollbackTx();
       }
-   }   
+   }
+
+   public void testEmptySecondLevelCacheEntry() throws Exception {
+      getSessions().getCache().evictEntityRegion(Item.class.getName());
+      Statistics stats = getSessions().getStatistics();
+      stats.clear();
+      SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics(Item.class.getName() + ".items");
+      Map cacheEntries = statistics.getEntries();
+      assertEquals(0, cacheEntries.size());
+   }
+
 }

Added: core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/JndiRegionFactoryTestCase.java
===================================================================
--- core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/JndiRegionFactoryTestCase.java	                        (rev 0)
+++ core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/JndiRegionFactoryTestCase.java	2010-09-16 17:05:14 UTC (rev 20652)
@@ -0,0 +1,180 @@
+package org.hibernate.test.cache.infinispan.functional;
+
+import org.hibernate.Session;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cache.infinispan.JndiInfinispanRegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Mappings;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.junit.functional.ExecutionEnvironment;
+import org.hibernate.stat.Statistics;
+import org.infinispan.Cache;
+import org.infinispan.lifecycle.ComponentStatus;
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+import org.jboss.util.naming.NonSerializableFactory;
+import org.jnp.server.Main;
+import org.jnp.server.SingletonNamingServer;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.Name;
+import javax.naming.NameNotFoundException;
+import javax.naming.Reference;
+import javax.naming.StringRefAddr;
+import java.util.Properties;
+
+/**
+ * // TODO: Document this
+ *
+ * @author Galder Zamarreño
+ * @since // TODO
+ */
+public class JndiRegionFactoryTestCase extends SingleNodeTestCase {
+   private static final Log log = LogFactory.getLog(JndiRegionFactoryTestCase.class);
+   private static final String JNDI_NAME = "java:CacheManager";
+   private Main namingMain;
+   private SingletonNamingServer namingServer;
+   private Properties props;
+   private boolean bindToJndi = true;
+   private EmbeddedCacheManager manager;
+
+   public JndiRegionFactoryTestCase(String string) {
+      super(string);
+   }
+
+   @Override
+   protected void cleanupTest() throws Exception {
+      Context ctx = new InitialContext(props);
+      unbind(JNDI_NAME, ctx);
+      namingServer.destroy();
+      namingMain.stop();
+      manager.stop(); // Need to stop cos JNDI region factory does not stop it.
+   }
+
+   @Override
+   protected Class<? extends RegionFactory> getCacheRegionFactory() {
+      return JndiInfinispanRegionFactory.class;
+   }
+
+   @Override
+   public void afterConfigurationBuilt(Mappings mappings, Dialect dialect) {
+      if (bindToJndi) {
+         try {
+            // Create an in-memory jndi
+            namingServer = new SingletonNamingServer();
+            namingMain = new Main();
+            namingMain.setInstallGlobalService(true);
+            namingMain.setPort(-1);
+            namingMain.start();
+            props = new Properties();
+            props.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
+            props.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
+
+            manager = new DefaultCacheManager(InfinispanRegionFactory.DEF_INFINISPAN_CONFIG_RESOURCE, false);
+            Context ctx = new InitialContext(props);
+            bind(JNDI_NAME, manager, EmbeddedCacheManager.class, ctx);
+         } catch(Exception e) {
+            throw new RuntimeException("Failure to set up JNDI", e);
+         }
+      }
+   }
+
+   @Override
+   public void configure(Configuration cfg) {
+      super.configure(cfg);
+      cfg.setProperty(JndiInfinispanRegionFactory.CACHE_MANAGER_RESOURCE_PROP, JNDI_NAME);
+      cfg.setProperty(Environment.JNDI_CLASS, "org.jnp.interfaces.NamingContextFactory");
+      cfg.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
+   }
+
+   public void testRedeployment() throws Exception {
+      addEntityCheckCache();
+      getEnvironment().getSessionFactory().close();
+      bindToJndi = false;
+      ExecutionEnvironment environment = new ExecutionEnvironment( this );
+      environment.initialize();
+      setEnvironment(environment);
+      addEntityCheckCache();
+      JndiInfinispanRegionFactory regionFactory = (JndiInfinispanRegionFactory) ((SessionFactoryImplementor)
+            environment.getSessionFactory()).getSettings().getRegionFactory();
+      Cache cache = regionFactory.getCacheManager().getCache("org.hibernate.test.cache.infinispan.functional.Item");
+      assertEquals(ComponentStatus.RUNNING, cache.getStatus());
+   }
+
+   private void addEntityCheckCache() throws Exception {
+      Item item = new Item("chris", "Chris's Item");
+      beginTx();
+      try {
+         Session s = openSession();
+         s.getTransaction().begin();
+         s.persist(item);
+         s.getTransaction().commit();
+         s.close();
+      } catch (Exception e) {
+         setRollbackOnlyTx(e);
+      } finally {
+         commitOrRollbackTx();
+      }
+
+      beginTx();
+      try {
+         Session s = openSession();
+         Item found = (Item) s.load(Item.class, item.getId());
+         Statistics stats = s.getSessionFactory().getStatistics();
+         log.info(stats.toString());
+         assertEquals(item.getDescription(), found.getDescription());
+         assertEquals(0, stats.getSecondLevelCacheMissCount());
+         assertEquals(1, stats.getSecondLevelCacheHitCount());
+         s.delete(found);
+         s.close();
+      } catch (Exception e) {
+         setRollbackOnlyTx(e);
+      } finally {
+         commitOrRollbackTx();
+      }
+
+   }
+
+   /**
+    * Helper method that binds the a non serializable object to the JNDI tree.
+    *
+    * @param jndiName Name under which the object must be bound
+    * @param who Object to bind in JNDI
+    * @param classType Class type under which should appear the bound object
+    * @param ctx Naming context under which we bind the object
+    * @throws Exception Thrown if a naming exception occurs during binding
+    */
+   private void bind(String jndiName, Object who, Class<?> classType, Context ctx) throws Exception {
+      // Ah ! This service isn't serializable, so we use a helper class
+      NonSerializableFactory.bind(jndiName, who);
+      Name n = ctx.getNameParser("").parse(jndiName);
+      while (n.size() > 1) {
+         String ctxName = n.get(0);
+         try {
+            ctx = (Context) ctx.lookup(ctxName);
+         } catch (NameNotFoundException e) {
+            log.debug("creating Subcontext " + ctxName);
+            ctx = ctx.createSubcontext(ctxName);
+         }
+         n = n.getSuffix(1);
+      }
+
+      // The helper class NonSerializableFactory uses address type nns, we go on to
+      // use the helper class to bind the service object in JNDI
+      StringRefAddr addr = new StringRefAddr("nns", jndiName);
+      Reference ref = new Reference(classType.getName(), addr, NonSerializableFactory.class.getName(), null);
+      ctx.rebind(n.get(0), ref);
+   }
+
+   private void unbind(String jndiName, Context ctx) throws Exception {
+      NonSerializableFactory.unbind(jndiName);
+//      ctx.unbind(jndiName);
+   }
+
+}

Modified: core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/SingleNodeTestCase.java
===================================================================
--- core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/SingleNodeTestCase.java	2010-09-16 16:53:09 UTC (rev 20651)
+++ core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/SingleNodeTestCase.java	2010-09-16 17:05:14 UTC (rev 20652)
@@ -90,15 +90,6 @@
       cfg.setProperty(Environment.TRANSACTION_STRATEGY, getTransactionFactoryClass().getName());
    }
 
-   public void testEmptySecondLevelCacheEntry() throws Exception {
-      getSessions().getCache().evictEntityRegion(Item.class.getName());
-      Statistics stats = getSessions().getStatistics();
-      stats.clear();
-      SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics(Item.class.getName() + ".items");
-      Map cacheEntries = statistics.getEntries();
-      assertEquals(0, cacheEntries.size());
-   }
-
    protected void beginTx() throws Exception {
       tm.begin();
    }

Modified: core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java
===================================================================
--- core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java	2010-09-16 16:53:09 UTC (rev 20651)
+++ core/branches/Branch_3_5/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java	2010-09-16 17:05:14 UTC (rev 20652)
@@ -27,12 +27,36 @@
 
 import org.hibernate.cache.CacheDataDescription;
 import org.hibernate.cache.Region;
+import org.hibernate.cache.RegionFactory;
 import org.hibernate.cache.UpdateTimestampsCache;
 import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cache.infinispan.impl.ClassLoaderAwareCache;
+import org.hibernate.cache.infinispan.timestamp.TimestampsRegionImpl;
 import org.hibernate.cache.infinispan.util.CacheAdapter;
 import org.hibernate.cache.infinispan.util.CacheAdapterImpl;
+import org.hibernate.cache.infinispan.util.FlagAdapter;
+import org.hibernate.cfg.Configuration;
 import org.hibernate.test.cache.infinispan.AbstractGeneralDataRegionTestCase;
+import org.hibernate.test.cache.infinispan.functional.classloader.Account;
+import org.hibernate.test.cache.infinispan.functional.classloader.AccountHolder;
+import org.hibernate.test.cache.infinispan.functional.classloader.SelectedClassnameClassLoader;
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+import org.infinispan.AdvancedCache;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryActivated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryEvicted;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryInvalidated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryLoaded;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryPassivated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited;
+import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
+import org.infinispan.notifications.cachelistener.event.Event;
 
+import javax.transaction.TransactionManager;
+
 /**
  * Tests of TimestampsRegionImpl.
  * 
@@ -40,15 +64,15 @@
  * @since 3.5
  */
 public class TimestampsRegionImplTestCase extends AbstractGeneralDataRegionTestCase {
-    
-    public TimestampsRegionImplTestCase(String name) {
-        super(name);
-    }
 
+   public TimestampsRegionImplTestCase(String name) {
+      super(name);
+   }
+
     @Override
-    protected String getStandardRegionName(String regionPrefix) {
-        return regionPrefix + "/" + UpdateTimestampsCache.class.getName();
-    }
+   protected String getStandardRegionName(String regionPrefix) {
+      return regionPrefix + "/" + UpdateTimestampsCache.class.getName();
+   }
 
    @Override
    protected Region createRegion(InfinispanRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
@@ -60,4 +84,127 @@
       return CacheAdapterImpl.newInstance(regionFactory.getCacheManager().getCache("timestamps"));
    }
 
+   public void testClearTimestampsRegionInIsolated() throws Exception {
+      Configuration cfg = createConfiguration();
+      InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+      // Sleep a bit to avoid concurrent FLUSH problem
+      avoidConcurrentFlush();
+
+      Configuration cfg2 = createConfiguration();
+      InfinispanRegionFactory regionFactory2 = CacheTestUtil.startRegionFactory(cfg2, getCacheTestSupport());
+      // Sleep a bit to avoid concurrent FLUSH problem
+      avoidConcurrentFlush();
+
+      TimestampsRegionImpl region = (TimestampsRegionImpl) regionFactory.buildTimestampsRegion(getStandardRegionName(REGION_PREFIX), cfg.getProperties());
+      TimestampsRegionImpl region2 = (TimestampsRegionImpl) regionFactory2.buildTimestampsRegion(getStandardRegionName(REGION_PREFIX), cfg2.getProperties());
+//      QueryResultsRegion region2 = regionFactory2.buildQueryResultsRegion(getStandardRegionName(REGION_PREFIX), cfg2.getProperties());
+
+//      ClassLoader cl = Thread.currentThread().getContextClassLoader();
+//      Thread.currentThread().setContextClassLoader(cl.getParent());
+//      log.info("TCCL is " + cl.getParent());
+
+      Account acct = new Account();
+      acct.setAccountHolder(new AccountHolder());
+      region.getCacheAdapter().withFlags(FlagAdapter.FORCE_SYNCHRONOUS).put(acct, "boo");
+
+//      region.put(acct, "boo");
+//
+//      region.evictAll();
+
+//      Account acct = new Account();
+//      acct.setAccountHolder(new AccountHolder());
+
+
+
+   }
+
+   @Override
+   protected Configuration createConfiguration() {
+      Configuration cfg = CacheTestUtil.buildConfiguration("test", MockInfinispanRegionFactory.class, false, true);
+      return cfg;
+   }
+
+   public static class MockInfinispanRegionFactory extends InfinispanRegionFactory {
+
+      public MockInfinispanRegionFactory() {
+      }
+
+      public MockInfinispanRegionFactory(Properties props) {
+         super(props);
+      }
+
+//      @Override
+//      protected TimestampsRegionImpl createTimestampsRegion(CacheAdapter cacheAdapter, String regionName) {
+//         return new MockTimestampsRegionImpl(cacheAdapter, regionName, getTransactionManager(), this);
+//      }
+
+      @Override
+      protected ClassLoaderAwareCache createCacheWrapper(AdvancedCache cache) {
+         return new ClassLoaderAwareCache(cache, Thread.currentThread().getContextClassLoader()) {
+            @Override
+            public void addListener(Object listener) {
+               super.addListener(new MockClassLoaderAwareListener(listener, this));
+            }
+         };
+      }
+
+      //      @Override
+//      protected EmbeddedCacheManager createCacheManager(Properties properties) throws CacheException {
+//         try {
+//            EmbeddedCacheManager manager = new DefaultCacheManager(InfinispanRegionFactory.DEF_INFINISPAN_CONFIG_RESOURCE);
+//            org.infinispan.config.Configuration ispnCfg = new org.infinispan.config.Configuration();
+//            ispnCfg.setCacheMode(org.infinispan.config.Configuration.CacheMode.REPL_SYNC);
+//            manager.defineConfiguration("timestamps", ispnCfg);
+//            return manager;
+//         } catch (IOException e) {
+//            throw new CacheException("Unable to create default cache manager", e);
+//         }
+//      }
+
+      @Listener      
+      public static class MockClassLoaderAwareListener extends ClassLoaderAwareCache.ClassLoaderAwareListener {
+         MockClassLoaderAwareListener(Object listener, ClassLoaderAwareCache cache) {
+            super(listener, cache);
+         }
+
+         @CacheEntryActivated
+         @CacheEntryCreated
+         @CacheEntryEvicted
+         @CacheEntryInvalidated
+         @CacheEntryLoaded
+         @CacheEntryModified
+         @CacheEntryPassivated
+         @CacheEntryRemoved
+         @CacheEntryVisited
+         public void event(Event event) throws Throwable {
+            ClassLoader cl = Thread.currentThread().getContextClassLoader();
+            String notFoundPackage = "org.hibernate.test.cache.infinispan.functional.classloader";
+            String[] notFoundClasses = { notFoundPackage + ".Account", notFoundPackage + ".AccountHolder" };
+            SelectedClassnameClassLoader visible = new SelectedClassnameClassLoader(null, null, notFoundClasses, cl);
+            Thread.currentThread().setContextClassLoader(visible);
+            super.event(event);
+            Thread.currentThread().setContextClassLoader(cl);            
+         }
+      }
+   }
+
+//   @Listener
+//   public static class MockTimestampsRegionImpl extends TimestampsRegionImpl {
+//
+//      public MockTimestampsRegionImpl(CacheAdapter cacheAdapter, String name, TransactionManager transactionManager, RegionFactory factory) {
+//         super(cacheAdapter, name, transactionManager, factory);
+//      }
+//
+//      @CacheEntryModified
+//      public void nodeModified(CacheEntryModifiedEvent event) {
+////         ClassLoader cl = Thread.currentThread().getContextClassLoader();
+////         String notFoundPackage = "org.hibernate.test.cache.infinispan.functional.classloader";
+////         String[] notFoundClasses = { notFoundPackage + ".Account", notFoundPackage + ".AccountHolder" };
+////         SelectedClassnameClassLoader visible = new SelectedClassnameClassLoader(null, null, notFoundClasses, cl);
+////         Thread.currentThread().setContextClassLoader(visible);
+//         super.nodeModified(event);
+////         Thread.currentThread().setContextClassLoader(cl);
+//      }
+//   }
+
 }



More information about the hibernate-commits mailing list