Author: galder.zamarreno(a)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);
+// }
+// }
+
}