JBoss Cache SVN: r4875 - in core/branches/1.4.X: tests/perf/org/jboss/cache/manualtests and 1 other directory.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-12-19 07:50:02 -0500 (Wed, 19 Dec 2007)
New Revision: 4875
Added:
core/branches/1.4.X/tests/perf/org/jboss/cache/manualtests/OptimisticMemLeakTest.java
Modified:
core/branches/1.4.X/src/org/jboss/cache/interceptors/TxInterceptor.java
Log:
JBCACHE-1246 - memory leak when using fail silently option
Modified: core/branches/1.4.X/src/org/jboss/cache/interceptors/TxInterceptor.java
===================================================================…
[View More]
--- core/branches/1.4.X/src/org/jboss/cache/interceptors/TxInterceptor.java 2007-12-18 20:45:17 UTC (rev 4874)
+++ core/branches/1.4.X/src/org/jboss/cache/interceptors/TxInterceptor.java 2007-12-19 12:50:02 UTC (rev 4875)
@@ -92,7 +92,12 @@
if (optionOverride!= null && optionOverride.isFailSilently() && ctx.getTransaction() != null)
{
- suspendedTransaction = txManager.suspend();
+ // make sure we remove the tx and global tx from the transaction table, since we don't care about this transaction
+ // and will just suspend it. - JBCACHE-1246
+ GlobalTransaction gtx = txTable.remove(ctx.getTransaction());
+ if (gtx != null) txTable.remove(gtx);
+
+ suspendedTransaction = txManager.suspend();
// set the tx in the invocation context to null now! - JBCACHE-785
ctx.setTransaction(null);
ctx.setGlobalTransaction(null);
Added: core/branches/1.4.X/tests/perf/org/jboss/cache/manualtests/OptimisticMemLeakTest.java
===================================================================
--- core/branches/1.4.X/tests/perf/org/jboss/cache/manualtests/OptimisticMemLeakTest.java (rev 0)
+++ core/branches/1.4.X/tests/perf/org/jboss/cache/manualtests/OptimisticMemLeakTest.java 2007-12-19 12:50:02 UTC (rev 4875)
@@ -0,0 +1,50 @@
+package org.jboss.cache.manualtests;
+
+import junit.framework.TestCase;
+import org.jboss.cache.DummyTransactionManagerLookup;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.TreeCache;
+import org.jboss.cache.config.Option;
+
+import javax.transaction.TransactionManager;
+
+/**
+ * To test memory leak reported in http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4112143#4112143
+ *
+ * @author Manik Surtani (<a href="mailto:manik@jboss.org">manik(a)jboss.org</a>)
+ */
+public class OptimisticMemLeakTest extends TestCase
+{
+ private TreeCache cache;
+ private TransactionManager tm;
+ private Fqn fqn = Fqn.fromString("/a/b/c");
+ private String key = "key", value = "value";
+
+ protected void tearDown()
+ {
+ cache.stop();
+ }
+
+ protected void setUp() throws Exception
+ {
+ cache = new TreeCache();
+ cache.setNodeLockingScheme("OPTIMISTIC");
+ cache.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.startService();
+ tm = cache.getTransactionManager();
+ }
+
+ public void testLeakWithFailSilently() throws Exception
+ {
+ tm.begin();
+ Option option = new Option();
+ option.setFailSilently(true);
+ cache.put(fqn, key, value, option);
+ tm.commit();
+
+ int gtxCnt = cache.getTransactionTable().getNumGlobalTransactions();
+ int txCnt = cache.getTransactionTable().getNumLocalTransactions();
+ assertEquals("Global transaction count is > 0", 0, gtxCnt);
+ assertEquals("Local transaction count is > 0", 0, txCnt);
+ }
+}
[View Less]
17 years, 2 months
Build failed in Hudson: jboss-cache-core-jdk1.5 » JBoss Cache - Core Edition #182
by jboss-qa-internal@redhat.com
See https://hudson.jboss.org/hudson/job/jboss-cache-core-jdk1.5/org.jboss.cac...
------------------------------------------
started
Building remotely on dev40-linux
Reusing existing maven process
[INFO] Scanning for projects...
WAGON_VERSION: 1.0-beta-2
[INFO] ----------------------------------------------------------------------------
[INFO] Building JBoss Cache - Core Edition
[INFO] task-segment: [package]
[INFO] ----------------------------------------------------------------------------
…
[View More][INFO] [enforcer:enforce {execution: enforce-java}]
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] Compiling 205 source files to /home/hudson/hudson_workspace/workspace/jboss-cache-core-jdk1.5/./target/test-classes
[HUDSON] Archiving /home/hudson/hudson_workspace/workspace/jboss-cache-core-jdk1.5/./pom.xml
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Compilation failure
/home/hudson/hudson_workspace/workspace/jboss-cache-core-jdk1.5/./src/test/java/org/jboss/cache/factories/ComponentRegistryTest.java:[64,27] cannot find symbol
symbol : variable registry
location: class org.jboss.cache.factories.ComponentRegistry
/home/hudson/hudson_workspace/workspace/jboss-cache-core-jdk1.5/./src/test/java/org/jboss/cache/factories/ComponentRegistryTest.java:[64,27] cannot find symbol
symbol : variable registry
location: class org.jboss.cache.factories.ComponentRegistry
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 38 seconds
[INFO] Finished at: Wed Dec 19 07:22:25 EST 2007
[INFO] Final Memory: 14M/45M
[INFO] ------------------------------------------------------------------------
Sending e-mails to: dpospisi(a)redhat.com
Build was marked for publishing on https://hudson.jboss.org/hudson/
finished: FAILURE
[View Less]
17 years, 2 months
Build failed in Hudson: jboss-cache-core-jdk1.5 » JBoss Cache - Core Edition #181
by jboss-qa-internal@redhat.com
See https://hudson.jboss.org/hudson/job/jboss-cache-core-jdk1.5/org.jboss.cac...
Changes:
[manik.surtani(a)jboss.com] better success rates
[manik.surtani(a)jboss.com] obsolete class
[manik.surtani(a)jboss.com] Updated injection framework and component registry internals and bootstrap
------------------------------------------
started
Building remotely on dev40-linux
$ /qa/tools/opt/jdk1.5.0_12/bin/java -Xmx256m -cp /home/hudson/hudson_workspace/maven-agent.jar:/qa/tools/opt/maven-2.0.6/…
[View More]boot/classworlds-1.1.jar hudson.maven.agent.Main /qa/tools/opt/maven-2.0.6 /qa/services/hudson/hudson_1.149/slave.jar /home/hudson/hudson_workspace/maven-interceptor.jar
channel started
[INFO] Scanning for projects...
WAGON_VERSION: 1.0-beta-2
[INFO] ----------------------------------------------------------------------------
[INFO] Building JBoss Cache - Core Edition
[INFO] task-segment: [package]
[INFO] ----------------------------------------------------------------------------
[INFO] artifact org.apache.maven.plugins:maven-resources-plugin: checking for updates from Main Maven Repo
[INFO] artifact org.apache.maven.plugins:maven-resources-plugin: checking for updates from repository.jboss.org
[INFO] artifact org.apache.maven.plugins:maven-resources-plugin: checking for updates from snapshots.jboss.org
[INFO] artifact org.apache.maven.plugins:maven-jar-plugin: checking for updates from Main Maven Repo
[INFO] artifact org.apache.maven.plugins:maven-jar-plugin: checking for updates from repository.jboss.org
[INFO] artifact org.apache.maven.plugins:maven-jar-plugin: checking for updates from snapshots.jboss.org
[INFO] artifact org.apache.maven.plugins:maven-javadoc-plugin: checking for updates from Main Maven Repo
[INFO] artifact org.apache.maven.plugins:maven-javadoc-plugin: checking for updates from snapshots.jboss.org
[INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from Main Maven Repo
[INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from repository.jboss.org
[INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from snapshots.jboss.org
[INFO] [enforcer:enforce {execution: enforce-java}]
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 319 source files to /home/hudson/hudson_workspace/workspace/jboss-cache-core-jdk1.5/./target/classes
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] Compiling 338 source files to /home/hudson/hudson_workspace/workspace/jboss-cache-core-jdk1.5/./target/test-classes
[HUDSON] Archiving /home/hudson/hudson_workspace/workspace/jboss-cache-core-jdk1.5/./pom.xml
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Compilation failure
/home/hudson/hudson_workspace/workspace/jboss-cache-core-jdk1.5/./src/test/java/org/jboss/cache/factories/ComponentRegistryTest.java:[64,27] cannot find symbol
symbol : variable registry
location: class org.jboss.cache.factories.ComponentRegistry
/home/hudson/hudson_workspace/workspace/jboss-cache-core-jdk1.5/./src/test/java/org/jboss/cache/factories/ComponentRegistryTest.java:[64,27] cannot find symbol
symbol : variable registry
location: class org.jboss.cache.factories.ComponentRegistry
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 minute 22 seconds
[INFO] Finished at: Wed Dec 19 07:19:08 EST 2007
[INFO] Final Memory: 14M/45M
[INFO] ------------------------------------------------------------------------
Sending e-mails to: dpospisi(a)redhat.com manik.surtani(a)jboss.com
Build was marked for publishing on https://hudson.jboss.org/hudson/
finished: FAILURE
[View Less]
17 years, 2 months
JBoss Cache SVN: r4874 - in core/trunk/src/main/java/org/jboss/cache: config and 5 other directories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-12-18 15:45:17 -0500 (Tue, 18 Dec 2007)
New Revision: 4874
Modified:
core/trunk/src/main/java/org/jboss/cache/CacheImpl.java
core/trunk/src/main/java/org/jboss/cache/config/CacheLoaderConfig.java
core/trunk/src/main/java/org/jboss/cache/config/ConfigurationComponent.java
core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java
core/trunk/src/main/java/org/jboss/cache/interceptors/Interceptor.java
core/trunk/…
[View More]src/main/java/org/jboss/cache/loader/CacheLoaderManager.java
core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java
core/trunk/src/main/java/org/jboss/cache/util/reflect/ReflectionUtil.java
Log:
better success rates
Modified: core/trunk/src/main/java/org/jboss/cache/CacheImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/CacheImpl.java 2007-12-18 20:00:25 UTC (rev 4873)
+++ core/trunk/src/main/java/org/jboss/cache/CacheImpl.java 2007-12-18 20:45:17 UTC (rev 4874)
@@ -45,6 +45,7 @@
import org.jboss.cache.transaction.OptimisticTransactionEntry;
import org.jboss.cache.transaction.TransactionEntry;
import org.jboss.cache.transaction.TransactionTable;
+import org.jboss.cache.util.CachePrinter;
import org.jboss.cache.util.ThreadGate;
import org.jboss.cache.util.concurrent.ConcurrentHashSet;
import org.jgroups.*;
@@ -182,6 +183,7 @@
private final ComponentRegistry componentRegistry;
private NodeFactory nodeFactory;
private CacheSPI spi;
+ private Interceptor interceptorChain;
/**
* Constructs an uninitialized CacheImpl.
@@ -213,7 +215,8 @@
@Inject
private void injectDependencies(Notifier notifier, RegionManager regionManager, TransactionManager transactionManager, Marshaller marshaller,
TransactionTable transactionTable, StateTransferManager stateTransferManager, NodeFactory nodeFactory,
- CacheSPI spi, CacheMessageListener messageListener, @ComponentName("remoteDelegate")RemoteCacheInvocationDelegate remoteDelegate)
+ CacheSPI spi, CacheMessageListener messageListener, @ComponentName("remoteDelegate")RemoteCacheInvocationDelegate remoteDelegate,
+ Interceptor interceptorChain)
{
this.notifier = notifier;
this.regionManager = regionManager;
@@ -225,6 +228,7 @@
this.messageListener = messageListener;
this.remoteDelegate = remoteDelegate;
this.marshaller = marshaller;
+ this.interceptorChain = interceptorChain;
}
public Configuration getConfiguration()
@@ -634,6 +638,12 @@
// start all internal components
componentRegistry.start();
+ if (log.isInfoEnabled())
+ {
+ log.info("Interceptor chain is:\n" + CachePrinter.printInterceptorChain(interceptorChain));
+ }
+
+
correctRootNodeType();
// createTransactionManager();
@@ -3770,15 +3780,13 @@
private List<Interceptor> getInterceptors()
{
- Interceptor i = componentRegistry.getComponent(Interceptor.class);
InterceptorChainFactory icf = componentRegistry.getComponent(InterceptorChainFactory.class);
- return icf.asList(i);
+ return icf.asList(interceptorChain);
}
private void setInterceptorChain(Interceptor startOfNewChain)
{
componentRegistry.registerComponent(Interceptor.class.getName(), startOfNewChain);
- componentRegistry.updateDependencies();
}
public synchronized void addInterceptor(Interceptor i, int position)
Modified: core/trunk/src/main/java/org/jboss/cache/config/CacheLoaderConfig.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/config/CacheLoaderConfig.java 2007-12-18 20:00:25 UTC (rev 4873)
+++ core/trunk/src/main/java/org/jboss/cache/config/CacheLoaderConfig.java 2007-12-18 20:45:17 UTC (rev 4874)
@@ -148,7 +148,19 @@
return clone;
}
+ /**
+ * Loops through all individual cache loader configs and checks if fetchPersistentState is set on any of them
+ */
+ public boolean isFetchPersistentState()
+ {
+ for (IndividualCacheLoaderConfig iclc : cacheLoaderConfigs)
+ {
+ if (iclc.isFetchPersistentState()) return true;
+ }
+ return false;
+ }
+
/**
* Configuration object that holds the confguration of an individual cache loader.
*
Modified: core/trunk/src/main/java/org/jboss/cache/config/ConfigurationComponent.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/config/ConfigurationComponent.java 2007-12-18 20:00:25 UTC (rev 4873)
+++ core/trunk/src/main/java/org/jboss/cache/config/ConfigurationComponent.java 2007-12-18 20:45:17 UTC (rev 4874)
@@ -34,9 +34,10 @@
protected transient Log log = LogFactory.getLog(getClass());
private transient CacheSPI cache; // back-reference to test whether the cache is running.
- private final Set<ConfigurationComponent> children =
- Collections.synchronizedSet(new HashSet<ConfigurationComponent>());
+ private final Set<ConfigurationComponent> children = Collections.synchronizedSet(new HashSet<ConfigurationComponent>());
private ComponentRegistry cr;
+ // a workaround to get over immutability checks
+ private boolean accessible;
protected ConfigurationComponent()
{
@@ -104,7 +105,7 @@
{
try
{
- if (cache != null && cache.getCacheStatus() != null && (cache.getCacheStatus() == CacheStatus.STARTED || cache.getCacheStatus() == CacheStatus.STARTING) && !getClass().getDeclaredField(fieldName).isAnnotationPresent(Dynamic.class))
+ if (!accessible && cache != null && cache.getCacheStatus() != null && (cache.getCacheStatus() == CacheStatus.STARTED || cache.getCacheStatus() == CacheStatus.STARTING) && !getClass().getDeclaredField(fieldName).isAnnotationPresent(Dynamic.class))
{
throw new ConfigurationException("Attempted to modify a non-Dynamic configuration element [" + fieldName + "] after the cache has started!");
}
@@ -113,6 +114,10 @@
{
log.warn("Field " + fieldName + " not found!!");
}
+ finally
+ {
+ accessible = false;
+ }
}
/**
Modified: core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java 2007-12-18 20:00:25 UTC (rev 4873)
+++ core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java 2007-12-18 20:45:17 UTC (rev 4874)
@@ -6,12 +6,10 @@
*/
package org.jboss.cache.factories;
-import org.jboss.cache.buddyreplication.BuddyManager;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.config.ConfigurationException;
import org.jboss.cache.factories.annotations.DefaultFactoryFor;
import org.jboss.cache.interceptors.*;
-import org.jboss.cache.loader.CacheLoaderManager;
import java.util.ArrayList;
import java.util.List;
@@ -101,12 +99,8 @@
call_interceptor = createInterceptor(CallInterceptor.class);
- //((CallInterceptor) call_interceptor).setTreeCacheInstance();
- if (componentRegistry.getOrCreateComponent(null, BuddyManager.class) != null)
- {
- dataGravitatorInterceptor = createInterceptor(DataGravitatorInterceptor.class);
- }
+ if (isUsingBuddyReplication()) dataGravitatorInterceptor = createInterceptor(DataGravitatorInterceptor.class);
lock_interceptor = createInterceptor(PessimisticLockInterceptor.class);
@@ -130,11 +124,9 @@
//Nothing...
}
- CacheLoaderManager cacheLoaderMgr = componentRegistry.getOrCreateComponent(null, CacheLoaderManager.class);
-
- if (cacheLoaderMgr != null && cacheLoaderMgr.getCacheLoader() != null)
+ if (isUsingCacheLoaders())
{
- if (cacheLoaderMgr.isPassivation())
+ if (configuration.getCacheLoaderConfig().isPassivation())
{
activation_interceptor = createInterceptor(ActivationInterceptor.class);
passivation_interceptor = createInterceptor(PassivationInterceptor.class);
@@ -285,14 +277,19 @@
addInterceptor(first, call_interceptor);
}
- if (log.isDebugEnabled())
- {
- log.debug("interceptor chain is:\n" + printInterceptorChain(first));
- }
-
return setLastInterceptorPointer(first, call_interceptor);
}
+ private boolean isUsingCacheLoaders()
+ {
+ return configuration.getCacheLoaderConfig() != null && !configuration.getCacheLoaderConfig().getIndividualCacheLoaderConfigs().isEmpty();
+ }
+
+ private boolean isUsingBuddyReplication()
+ {
+ return configuration.getBuddyReplicationConfig() != null && configuration.getBuddyReplicationConfig().isEnabled();
+ }
+
private Interceptor createOptimisticInterceptorChain() throws IllegalAccessException, InstantiationException, ClassNotFoundException
{
Interceptor txInterceptor, replicationInterceptor = null, lockInterceptor, validationInterceptor;
@@ -302,10 +299,9 @@
Interceptor invocationCtxInterceptor = createInterceptor(InvocationContextInterceptor.class);
Interceptor notificationInterceptor = createInterceptor(NotificationInterceptor.class);
- CacheLoaderManager cacheLoaderManager = componentRegistry.getOrCreateComponent(null, CacheLoaderManager.class);
- if (cacheLoaderManager != null && cacheLoaderManager.getCacheLoader() != null)
+ if (isUsingCacheLoaders())
{
- if (cacheLoaderManager.isPassivation())
+ if (configuration.getCacheLoaderConfig().isPassivation())
{
activationInterceptor = createInterceptor(ActivationInterceptor.class);
passivationInterceptor = createInterceptor(PassivationInterceptor.class);
@@ -319,10 +315,7 @@
txInterceptor = createInterceptor(TxInterceptor.class);
- if (componentRegistry.getOrCreateComponent(null, BuddyManager.class) != null)
- {
- dataGravitatorInterceptor = createInterceptor(DataGravitatorInterceptor.class);
- }
+ if (isUsingBuddyReplication()) dataGravitatorInterceptor = createInterceptor(DataGravitatorInterceptor.class);
switch (configuration.getCacheMode())
{
@@ -394,7 +387,7 @@
addInterceptor(first, replicationInterceptor);
}
- if (passivationInterceptor != null && !cacheLoaderManager.isFetchPersistentState())
+ if (passivationInterceptor != null && !configuration.getCacheLoaderConfig().isFetchPersistentState())
{
if (first == null)
{
@@ -407,7 +400,7 @@
}
// add the cache store interceptor here
- if (cacheStoreInterceptor != null && !cacheLoaderManager.isFetchPersistentState())
+ if (cacheStoreInterceptor != null && !configuration.getCacheLoaderConfig().isFetchPersistentState())
{
if (first == null)
{
@@ -431,7 +424,7 @@
addInterceptor(first, activationInterceptor);
}
- if (cacheLoaderManager.isFetchPersistentState())
+ if (configuration.getCacheLoaderConfig().isFetchPersistentState())
{
if (first == null)
{
@@ -455,7 +448,7 @@
addInterceptor(first, cacheLoaderInterceptor);
}
- if (cacheLoaderManager.isFetchPersistentState())
+ if (configuration.getCacheLoaderConfig().isFetchPersistentState())
{
if (first == null)
{
@@ -537,28 +530,9 @@
addInterceptor(first, invokerInterceptor);
}
- if (log.isInfoEnabled())
- {
- log.info("interceptor chain is:\n" + printInterceptorChain(first));
- }
-
return setLastInterceptorPointer(first, invokerInterceptor);
}
- public String printInterceptorChain(Interceptor i)
- {
- StringBuffer sb = new StringBuffer();
- if (i != null)
- {
- if (i.getNext() != null)
- {
- sb.append(printInterceptorChain(i.getNext())).append("\n");
- }
- sb.append(i.getClass());
- }
- return sb.toString();
- }
-
public List<Interceptor> asList(Interceptor interceptor)
{
if (interceptor == null)
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/Interceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/Interceptor.java 2007-12-18 20:00:25 UTC (rev 4873)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/Interceptor.java 2007-12-18 20:45:17 UTC (rev 4874)
@@ -38,7 +38,6 @@
/**
* Class representing an interceptor.
- * <em>Note that this will be replaced by {@link org.jboss.aop.advice.Interceptor} in one of the next releases</em>
*
* @author Bela Ban
* @version $Id$
Modified: core/trunk/src/main/java/org/jboss/cache/loader/CacheLoaderManager.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/loader/CacheLoaderManager.java 2007-12-18 20:00:25 UTC (rev 4873)
+++ core/trunk/src/main/java/org/jboss/cache/loader/CacheLoaderManager.java 2007-12-18 20:45:17 UTC (rev 4874)
@@ -18,6 +18,7 @@
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.factories.annotations.Start;
import org.jboss.cache.factories.annotations.Stop;
+import org.jboss.cache.util.reflect.ReflectionUtil;
import java.util.ArrayList;
import java.util.Iterator;
@@ -79,7 +80,7 @@
@Inject
public void setConfig(CacheLoaderConfig config, CacheSPI cache, Configuration configuration) throws CacheException
{
- this.config = config == null ? new CacheLoaderConfig() : config;
+ this.config = config == null ? configuration.getCacheLoaderConfig() : config;
this.cache = cache;
this.configuration = configuration;
@@ -159,6 +160,7 @@
}
// Update the config with those actually used by the loaders
+ ReflectionUtil.setValue(config, "accessible", true);
config.setIndividualCacheLoaderConfigs(finalConfigs);
return tmpLoader;
@@ -390,6 +392,21 @@
@Start
public void startCacheLoader() throws CacheException
{
+ if (config == null) config = configuration.getCacheLoaderConfig();
+
+ if (config != null && loader == null)
+ {
+ try
+ {
+ loader = createCacheLoader();
+ }
+ catch (Exception e)
+ {
+ throw new CacheException("Unable to create cache loaders", e);
+ }
+ }
+
+
if (loader != null)
{
try
Modified: core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java 2007-12-18 20:00:25 UTC (rev 4873)
+++ core/trunk/src/main/java/org/jboss/cache/util/CachePrinter.java 2007-12-18 20:45:17 UTC (rev 4874)
@@ -56,4 +56,19 @@
}
return b.toString();
}
+
+ public static String printInterceptorChain(Interceptor i)
+ {
+ StringBuffer sb = new StringBuffer();
+ if (i != null)
+ {
+ if (i.getNext() != null)
+ {
+ sb.append(printInterceptorChain(i.getNext())).append("\n");
+ }
+ sb.append(">> ");
+ sb.append(i.getClass().getName());
+ }
+ return sb.toString();
+ }
}
Modified: core/trunk/src/main/java/org/jboss/cache/util/reflect/ReflectionUtil.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/reflect/ReflectionUtil.java 2007-12-18 20:00:25 UTC (rev 4873)
+++ core/trunk/src/main/java/org/jboss/cache/util/reflect/ReflectionUtil.java 2007-12-18 20:45:17 UTC (rev 4874)
@@ -1,6 +1,10 @@
package org.jboss.cache.util.reflect;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
@@ -15,6 +19,8 @@
*/
public class ReflectionUtil
{
+ private static Log log = LogFactory.getLog(ReflectionUtil.class);
+
/**
* Returns a set of Methods that contain the given method annotation. This includes all public, protected, package and private
* methods, as well as those of superclasses. Note that this does *not* include overridden methods.
@@ -70,4 +76,34 @@
}
return false;
}
+
+ public static void setValue(Object instance, String fieldName, Object value)
+ {
+ try
+ {
+ Field f = findFieldRecursively(instance.getClass(), fieldName);
+ if (f == null)
+ throw new NoSuchMethodException("Cannot find field " + fieldName + " on " + instance.getClass() + " or superclasses");
+ f.setAccessible(true);
+ f.set(instance, value);
+ }
+ catch (Exception e)
+ {
+ log.error("Unable to set value!", e);
+ }
+ }
+
+ private static Field findFieldRecursively(Class c, String fieldName)
+ {
+ Field f = null;
+ try
+ {
+ f = c.getDeclaredField(fieldName);
+ }
+ catch (NoSuchFieldException e)
+ {
+ if (!c.equals(Object.class)) f = findFieldRecursively(c.getSuperclass(), fieldName);
+ }
+ return f;
+ }
}
[View Less]
17 years, 3 months
JBoss Cache SVN: r4873 - core/trunk/src/test/java/org/jboss/cache/factories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-12-18 15:00:25 -0500 (Tue, 18 Dec 2007)
New Revision: 4873
Removed:
core/trunk/src/test/java/org/jboss/cache/factories/DependencyGraphTest.java
Log:
obsolete class
Deleted: core/trunk/src/test/java/org/jboss/cache/factories/DependencyGraphTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/factories/DependencyGraphTest.java 2007-12-18 19:58:10 UTC (rev 4872)
+++ core/trunk/…
[View More]src/test/java/org/jboss/cache/factories/DependencyGraphTest.java 2007-12-18 20:00:25 UTC (rev 4873)
@@ -1,78 +0,0 @@
-package org.jboss.cache.factories;
-
-import org.jboss.cache.factories.annotations.Inject;
-import org.testng.annotations.Test;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Manik Surtani (<a href="mailto:manik@jboss.org">manik(a)jboss.org</a>)
- * @since 2.1.0
- */
-@Test(groups = "functional")
-public class DependencyGraphTest
-{
- public void testDependencies()
- {
- Map<Object, Object> components = new HashMap<Object, Object>();
- components.put(Test1.class, new Test1());
- components.put(Test2.class, new Test2());
- components.put(Test3.class, new Test3());
- components.put(Test4.class, new Test4());
-
- // expected order - Test4, Test3, Test2, Test1
- DependencyGraph dg = new DependencyGraph(components);
- List<Object> ordered = dg.getOrderedComponentKeys();
-
- assert ordered.size() == 4;
-
- System.out.println(ordered);
-
- int n = 0;
- assert ordered.get(n++) == Test4.class;
- assert ordered.get(n++) == Test3.class;
- assert ordered.get(n++) == Test2.class;
- assert ordered.get(n) == Test1.class;
- }
-
- public static class Test1
- {
- private Test2 test2;
-
- @Inject
- private void inject(Test2 test2)
- {
- this.test2 = test2;
- }
- }
-
- public static class Test2
- {
- private Test3 test3;
- private Test4 test4;
-
- @Inject
- private void inject(Test3 test3, Test4 test4)
- {
- this.test3 = test3;
- this.test4 = test4;
- }
- }
-
- public static class Test3
- {
- private Test4 test4;
-
- @Inject
- private void inject(Test4 test4)
- {
- this.test4 = test4;
- }
- }
-
- public static class Test4
- {
- }
-}
[View Less]
17 years, 3 months
JBoss Cache SVN: r4872 - in core/trunk/src: main/java/org/jboss/cache/config and 12 other directories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-12-18 14:58:10 -0500 (Tue, 18 Dec 2007)
New Revision: 4872
Added:
core/trunk/src/main/java/org/jboss/cache/util/reflect/
core/trunk/src/main/java/org/jboss/cache/util/reflect/ClasspathScanner.java
core/trunk/src/main/java/org/jboss/cache/util/reflect/ReflectionUtil.java
core/trunk/src/test/java/org/jboss/cache/factories/ComponentRegistryFunctionalTest.java
core/trunk/src/test/java/org/jboss/cache/factories/ComponentRegistryUnitTest.…
[View More]java
core/trunk/src/test/java/org/jboss/cache/factories/DependencyGraphTest.java
core/trunk/src/test/java/org/jboss/cache/util/reflect/
core/trunk/src/test/java/org/jboss/cache/util/reflect/ClasspathScannerTest.java
Removed:
core/trunk/src/test/java/org/jboss/cache/factories/annotations/
Modified:
core/trunk/src/main/java/org/jboss/cache/CacheImpl.java
core/trunk/src/main/java/org/jboss/cache/DefaultCacheFactory.java
core/trunk/src/main/java/org/jboss/cache/config/ConfigurationComponent.java
core/trunk/src/main/java/org/jboss/cache/factories/CacheMarshallerFactory.java
core/trunk/src/main/java/org/jboss/cache/factories/ComponentRegistry.java
core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java
core/trunk/src/main/java/org/jboss/cache/interceptors/CacheLoaderInterceptor.java
core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java
core/trunk/src/test/java/org/jboss/cache/interceptors/EvictionInterceptorTest.java
core/trunk/src/test/java/org/jboss/cache/loader/CacheLoaderTestsBase.java
core/trunk/src/test/java/org/jboss/cache/loader/UnnecessaryLoadingTest.java
core/trunk/src/test/java/org/jboss/cache/misc/TestingUtil.java
core/trunk/src/test/java/org/jboss/cache/passivation/PassivationToDummyInMemoryCacheLoaderTest.java
Log:
Updated injection framework and component registry internals and bootstrap
Modified: core/trunk/src/main/java/org/jboss/cache/CacheImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/CacheImpl.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/main/java/org/jboss/cache/CacheImpl.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -502,6 +502,8 @@
// Include our clusterName in our log category
configureLogCategory();
+ componentRegistry.wire();
+
// initialise the node factory and set this in the runtime.
// NodeFactory nf;
// if ((nf = configuration.getRuntimeConfig().getNodeFactory()) == null)
@@ -617,9 +619,11 @@
// remove the Interceptor.class component though, since it may pertain to an old config
componentRegistry.unregisterComponent(Interceptor.class);
+ // re-do the bootstrap sequence
componentRegistry.registerComponent(configuration);
componentRegistry.registerComponent(this);
- componentRegistry.registerComponent(CacheSPI.class, spi);
+ componentRegistry.registerComponent(CacheSPI.class.getName(), spi);
+ componentRegistry.registerComponent(Cache.class.getName(), spi);
componentRegistry.registerComponent(componentRegistry);
componentRegistry.updateDependencies();
@@ -628,7 +632,7 @@
cacheStatus = CacheStatus.STARTING;
// start all internal components
- componentRegistry.startComponents();
+ componentRegistry.start();
correctRootNodeType();
@@ -873,7 +877,7 @@
{
cacheStatus = CacheStatus.STOPPING;
- componentRegistry.stopComponents();
+ componentRegistry.stop();
// before closing the channel stop the buddy manager
// if (buddyManager != null && buddyManager.isEnabled())
@@ -3773,7 +3777,7 @@
private void setInterceptorChain(Interceptor startOfNewChain)
{
- componentRegistry.registerComponent(Interceptor.class, startOfNewChain);
+ componentRegistry.registerComponent(Interceptor.class.getName(), startOfNewChain);
componentRegistry.updateDependencies();
}
@@ -3781,21 +3785,22 @@
{
List<Interceptor> interceptors = getInterceptors();
- InterceptorChainFactory factory = InterceptorChainFactory.getInstance();
+ InterceptorChainFactory factory = componentRegistry.getComponent(InterceptorChainFactory.class);
interceptors.add(position, i);
// now correct the chaining of interceptors...
- Interceptor linkedChain = factory.correctInterceptorChaining(interceptors, configuration, componentRegistry);
+ Interceptor linkedChain = factory.correctInterceptorChaining(interceptors);
setInterceptorChain(linkedChain);
}
public synchronized void removeInterceptor(int position)
{
+ InterceptorChainFactory factory = componentRegistry.getComponent(InterceptorChainFactory.class);
List<Interceptor> i = getInterceptors();
i.remove(position);
- setInterceptorChain(InterceptorChainFactory.getInstance().correctInterceptorChaining(i, configuration, componentRegistry));
+ setInterceptorChain(factory.correctInterceptorChaining(i));
}
public RPCManager getRPCManager()
Modified: core/trunk/src/main/java/org/jboss/cache/DefaultCacheFactory.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/DefaultCacheFactory.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/main/java/org/jboss/cache/DefaultCacheFactory.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -11,7 +11,6 @@
import org.jboss.cache.factories.ComponentFactory;
import org.jboss.cache.factories.ComponentRegistry;
import org.jboss.cache.factories.XmlConfigurationParser;
-import org.jboss.cache.factories.annotations.DefaultFactoryFor;
import org.jboss.cache.invocation.CacheInvocationDelegate;
import java.io.InputStream;
@@ -23,34 +22,27 @@
* This is a special instance of a {@link ComponentFactory} which contains bootstrap information for the
* {@link ComponentRegistry}.
* <p/>
- * E.g., {@link #bootstrap()} is used to create a cache, a {@link ComponentRegistry}, and then wire dependencies as needed.
+ * E.g., {@link #bootstrap(CacheImpl, CacheSPI, org.jboss.cache.config.Configuration)} is used to create a cache, a {@link ComponentRegistry}, and then wire dependencies as needed.
*
* @author <a href="mailto:manik@jboss.org">Manik Surtani (manik(a)jboss.org)</a>
* @see org.jboss.cache.factories.ComponentFactory
*/
-@DefaultFactoryFor(classes = {CacheSPI.class})
+//@DefaultFactoryFor(classes = {CacheSPI.class})
public class DefaultCacheFactory<K, V> extends ComponentFactory implements CacheFactory<K, V>
{
private volatile static CacheFactory<?, ?> singleton = new DefaultCacheFactory();
- protected DefaultCacheFactory()
- {
- }
-
/**
- * @return a singleton instance of this class.
+ * Note - this method used to return a singleton instance, and since 2.1.0 returns a new instance. The method is
+ * deprecated and you should use the no-arg constructor to create a new instance of this factory.
+ *
+ * @return a NEW instance of this class.
*/
@SuppressWarnings("unchecked")
+ @Deprecated
public static <K, V> CacheFactory<K, V> getInstance()
{
- if (singleton == null)
- {
- synchronized (DefaultCacheFactory.class)
- {
- if (singleton == null) singleton = new DefaultCacheFactory();
- }
- }
- return (CacheFactory<K, V>) singleton;
+ return new DefaultCacheFactory();
}
public Cache<K, V> createCache() throws ConfigurationException
@@ -124,11 +116,7 @@
bootstrap(cache, spi, configuration);
- // wire dependencies into cache
- componentRegistry.wireDependencies(cache);
- // wire dependencies into SPI delegate
- componentRegistry.wireDependencies(spi);
-
+ componentRegistry.wire();
return spi;
}
@@ -143,17 +131,18 @@
// injection bootstrap stuff
componentRegistry = cache.getComponentRegistry();
- // make sure we set the CacheImpl and CacheSPI instance in the component registry.
- componentRegistry.registerComponent(cache);
- componentRegistry.registerComponent(spi);
-
// and the configuration
componentRegistry.registerComponent(configuration);
this.configuration = configuration;
- componentRegistry.wireDependencies(configuration);
+
// and the component registry itself. This bit of recursiveness is needed for factories that are also components.
// See NodeFactory for example, which is created by an EmptyConstructorFactory
componentRegistry.registerComponent(componentRegistry);
+
+ // make sure we set the CacheImpl and CacheSPI instance in the component registry.
+ componentRegistry.registerComponent(cache);
+ componentRegistry.registerComponent(CacheSPI.class.getName(), spi);
+ componentRegistry.registerComponent(Cache.class.getName(), spi);
}
public Cache<K, V> createCache(InputStream is) throws ConfigurationException
Modified: core/trunk/src/main/java/org/jboss/cache/config/ConfigurationComponent.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/config/ConfigurationComponent.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/main/java/org/jboss/cache/config/ConfigurationComponent.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -10,7 +10,9 @@
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.CacheStatus;
+import org.jboss.cache.factories.ComponentRegistry;
import org.jboss.cache.factories.annotations.Inject;
+import org.jboss.cache.factories.annotations.Start;
import java.io.Serializable;
import java.util.Collection;
@@ -34,6 +36,7 @@
private transient CacheSPI cache; // back-reference to test whether the cache is running.
private final Set<ConfigurationComponent> children =
Collections.synchronizedSet(new HashSet<ConfigurationComponent>());
+ private ComponentRegistry cr;
protected ConfigurationComponent()
{
@@ -117,7 +120,6 @@
*
* @param cache
*/
- @Inject
public void setCache(CacheSPI cache)
{
this.cache = cache;
@@ -130,6 +132,18 @@
}
}
+ @Inject
+ private void injectDependencies(ComponentRegistry cr)
+ {
+ this.cr = cr;
+ }
+
+ @Start
+ private void start()
+ {
+ setCache(cr.getComponent(CacheSPI.class));
+ }
+
public ConfigurationComponent clone() throws CloneNotSupportedException
{
ConfigurationComponent c = (ConfigurationComponent) super.clone();
Modified: core/trunk/src/main/java/org/jboss/cache/factories/CacheMarshallerFactory.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/factories/CacheMarshallerFactory.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/main/java/org/jboss/cache/factories/CacheMarshallerFactory.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -42,7 +42,7 @@
throw new ConfigurationException("Unable to instantiate marshaller of type " + marshallerClass, e);
}
- componentRegistry.wireDependencies(m);
+ //componentRegistry.wireDependencies(m);
if (log.isDebugEnabled()) log.debug("Instantiated " + marshallerClass + "; wrapping in a VersionAwareMarshaller");
Modified: core/trunk/src/main/java/org/jboss/cache/factories/ComponentRegistry.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/factories/ComponentRegistry.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/main/java/org/jboss/cache/factories/ComponentRegistry.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -2,23 +2,25 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheImpl;
+import org.jboss.cache.CacheSPI;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.config.ConfigurationException;
import org.jboss.cache.config.RuntimeConfig;
-import org.jboss.cache.factories.annotations.ClasspathScanner;
+import static org.jboss.cache.factories.ComponentRegistry.State.*;
import org.jboss.cache.factories.annotations.ComponentName;
import org.jboss.cache.factories.annotations.DefaultFactoryFor;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.factories.annotations.Start;
import org.jboss.cache.factories.annotations.Stop;
import org.jboss.cache.util.BeanUtils;
+import org.jboss.cache.util.reflect.ClasspathScanner;
+import org.jboss.cache.util.reflect.ReflectionUtil;
import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@@ -34,17 +36,36 @@
* Components can be retrieved from the registry using {@link #getComponent(Class)}, or they can be constructed using
* {@link #getOrCreateComponent(String, Class)} which will scan for default factories and attempt to use such
* factpries to create the component if needed.
+ * <p/>
+ * Default factories are treated as components too and will need to be wired and started before being used.
+ * <p/>
+ * Components can exist in one of 4 states, as defined by the {@link State} enumeration. The component registry also
+ * has a state for the overall component set. While some components may move to the {@link org.jboss.cache.factories.ComponentRegistry.State#STARTED}
+ * state before others (such as factories to create other components) the ComponentRegistry's overall state depicts the lowest
+ * possible form for all components.
+ * <p/>
+ * In terms of the cache, overall state changes in the following manner:
+ * <ul>
+ * <li>CONSTRUCTED - when created using the DefaultCacheFactory</li>
+ * <li>WIRED - when {@link org.jboss.cache.Cache#create()} is called</li>
+ * <li>STARTED - when {@link org.jboss.cache.Cache#start()} is called</li>
+ * <li>STOPPED - when {@link org.jboss.cache.Cache#stop()} is called</li>
+ * </ul>
+ * <p/>
+ * Cache configuration can only be changed and will only be reinjected if the cache is not in the {@link org.jboss.cache.CacheStatus#STARTED} state.
*
* @author Manik Surtani (<a href="mailto:manik@jboss.org">manik(a)jboss.org</a>)
* @since 2.1.0
*/
public class ComponentRegistry
{
+ State overallState = CONSTRUCTED;
+
/**
- * Can contain either unnamed singletons (in which case the key is the class of the instance) or named singletons, keyed by a
- * String representing the name of the instance.
+ * The registry of components. Components are stored under their name.
*/
- Map<Object, Object> registry = new HashMap<Object, Object>();
+ Map<String, Component> componentLookup = new HashMap<String, Component>();
+
/**
* Contains class definitions of component factories that can be used to construct certain components
*/
@@ -52,6 +73,11 @@
private static Log log = LogFactory.getLog(ComponentRegistry.class);
+ /**
+ * Creates an instance of the component registry. The configuration passed in is automatically registered.
+ *
+ * @param configuration
+ */
public ComponentRegistry(Configuration configuration)
{
// bootstrap.
@@ -61,72 +87,50 @@
/**
* Adds a singleton instance to the registry. Note that if an instance of this component already exists in the
* registry it is overwritten. The instance is registered under type <tt>component.getClass()</tt>. If the component
- * implements an interface or extends an abstract class, it may make more sense to use {@link #registerComponent(Class, Object)}
+ * implements an interface or extends an abstract class, it may make more sense to use {@link #registerComponent(String, Object)}
+ * <p/>
+ * The status of the component is updated th the overall state of the registry, which may involve calling of methods annotated
+ * with {@link org.jboss.cache.factories.annotations.Inject}, {@link org.jboss.cache.factories.annotations.Start} or
+ * {@link org.jboss.cache.factories.annotations.Stop}.
+ * <p/>
*
* @param component component to add to the registry.
*/
public void registerComponent(Object component)
{
- registerComponent(component.getClass(), component);
+ registerComponent(component.getClass().getName(), component);
}
/**
- * Adds a singleton instance to the registry. Note that if an instance of this component already exists in the
- * registry it is overwritten.
- *
- * @param componentType the type to register the component under.
- * @param component component to add to the registry.
- */
- public void registerComponent(Class componentType, Object component)
- {
- registry.put(componentType, component);
- }
-
- /**
* Adds an instance component to the registry, registering the component under the given name. If an instance already
* exists in the registry under the given name, it will be overwritten.
+ * <p/>
+ * The status of the component is updated th the overall state of the registry, which may involve calling of methods annotated
+ * with {@link org.jboss.cache.factories.annotations.Inject}, {@link org.jboss.cache.factories.annotations.Start} or
+ * {@link org.jboss.cache.factories.annotations.Stop}.
+ * <p/>
*
* @param name name of the instance
* @param component component to add
*/
public void registerComponent(String name, Object component)
{
- registry.put(name, component);
+ // this will make sure all dependent components are stopped or set to CONSTRUCTED so they can be re-wired later.
+ unregisterComponent(name);
+
+ Component c = new Component(name, component);
+ componentLookup.put(name, c);
+ // build any dependent components if necessary
+ for (Dependency d : c.dependencies)
+ {
+ getOrCreateComponent(d.name, d.type);
+ }
+ c.changeState(overallState);
}
- /**
- * Retrieves a singleton component which can be assigned to the type passed in. Will return a null if no such component
- * is registered
- *
- * @param c type to be able to assign component to.
- * @return component, if found, or a null otherwise.
- */
- @SuppressWarnings("unchecked")
public <T> T getComponent(Class<T> c)
{
- if (c == null)
- {
- log.error("Scanning for component null!! This is a bug!!", new Throwable());
- return null;
- }
-
- //if (log.isTraceEnabled()) log.trace("Scanning registry for an instance that can be assigned to class " + c);
- T component = (T) registry.get(c);
-
- if (component == null)
- {
- // search for subclasses.
- for (Object object : registry.keySet())
- {
- if (object instanceof Class)
- {
- if (c.isAssignableFrom((Class) object)) component = (T) registry.get(object);
- }
-
- }
- }
-
- return component;
+ return getComponent(c.getName(), c);
}
/**
@@ -139,8 +143,11 @@
@SuppressWarnings("unchecked")
public <T> T getComponent(String name, Class<T> c)
{
- T component = (T) registry.get(name);
- if (component == null) return null;
+ Component wrapper = componentLookup.get(name);
+ if (wrapper == null) return null;
+
+ T component = (T) wrapper.instance;
+
if (c.isAssignableFrom(component.getClass())) return component;
else
throw new ConfigurationException("Component registered under " + name + " is of type " + component.getClass() + " and cannot be assigned to " + c);
@@ -160,6 +167,29 @@
* 3. Attempt to create it by looking for an appropriate factory (annotated with {@link org.jboss.cache.factories.annotations.DefaultFactoryFor})
* <p/>
*
+ * @param componentClass type of component to be retrieved. Should not be null.
+ * @return a fully wired component instance, or null if one cannot be found or constructed.
+ * @throws ConfigurationException if there is a problem with consructing or wiring the instance.
+ */
+ public <T> T getOrCreateComponent(Class<T> componentClass)
+ {
+ return getOrCreateComponent(null, componentClass);
+ }
+
+ /**
+ * Retrieves a named component if one exists, and if not, attempts to find a factory capable of constructing the component
+ * (factories annotated with the {@link org.jboss.cache.factories.annotations.DefaultFactoryFor} annotation that is capable
+ * of creating the component class).
+ * <p/>
+ * If an instance needs to be constructed, dependencies are then automatically wired into the instance, based on methods
+ * on the component type annotated with {@link org.jboss.cache.factories.annotations.Inject}.
+ * <p/>
+ * Summing it up, component retrieval happens in the following order:<br />
+ * 1. Look for an appropriate component that exists in the {@link Configuration} that may be injected from an external system.
+ * 2. Look for a class definition passed in to the {@link org.jboss.cache.config.Configuration} - such as an EvictionPolicy implementation
+ * 3. Attempt to create it by looking for an appropriate factory (annotated with {@link org.jboss.cache.factories.annotations.DefaultFactoryFor})
+ * <p/>
+ *
* @param componentName name of component to be created. If null, uses the fully qualified class name as component name.
* @param componentClass type of component to be retrieved. Should not be null.
* @return a fully wired component instance, or null if one cannot be found or constructed.
@@ -167,14 +197,14 @@
*/
public <T> T getOrCreateComponent(String componentName, Class<T> componentClass)
{
- T component = (componentName == null) ? getComponent(componentClass) : getComponent(componentName, componentClass);
+ T component = getComponent(componentName == null ? componentClass.getName() : componentName, componentClass);
if (component == null)
{
// first see if this has been injected externally.
component = getFromConfiguration(componentClass);
- if (component == null)
+ if (component == null && isNonBootstrap(componentClass))
{
// create this component and add it to the registry
ComponentFactory factory = getFactory(componentClass);
@@ -184,9 +214,9 @@
if (component != null)
{
// wire dependencies
- wireDependencies(component);
+// wireDependencies(component);
if (componentName == null)
- registerComponent(componentClass, component);
+ registerComponent(componentClass.getName(), component);
else
registerComponent(componentName, component);
}
@@ -194,8 +224,14 @@
return component;
}
+ private boolean isNonBootstrap(Class<?> componentClass)
+ {
+ return !(componentClass.equals(CacheSPI.class) || componentClass.equals(CacheImpl.class) || componentClass.equals(Cache.class)
+ || componentClass.equals(ComponentRegistry.class));
+ }
+
@SuppressWarnings("unchecked")
- private <T> T getFromConfiguration(Class<T> componentClass)
+ <T> T getFromConfiguration(Class<T> componentClass)
{
//if (log.isDebugEnabled()) log.debug("Looking in configuration for an instance of " + componentClass + " that may have been injected from an external source.");
Method getter = BeanUtils.getterMethod(Configuration.class, componentClass);
@@ -243,12 +279,9 @@
*/
public void updateDependencies()
{
- // make sure we work off a copy of the values set since wireDependencies may add components to the registry
- // and this may otherwise end up in a CME.
-
- Set<Object> components = new HashSet<Object>(registry.values());
-
- for (Object component : components) wireDependencies(component);
+ State originalState = overallState;
+ moveComponentsToState(overallState == STARTED ? CONSTRUCTED : STOPPED);
+ moveComponentsToState(originalState);
}
/**
@@ -259,7 +292,7 @@
*/
public void unregisterComponent(Class<?> clazz)
{
- registry.remove(clazz);
+ unregisterComponent(clazz.getName());
}
/**
@@ -270,13 +303,14 @@
*/
public void unregisterComponent(String name)
{
- registry.remove(name);
+ Component c = componentLookup.remove(name);
+ if (c != null) c.changeState(c.state == STARTED ? STOPPED : CONSTRUCTED);
}
/**
* Wires an object instance with dependencies annotated with the {@link org.jboss.cache.factories.annotations.Inject} annotation, creating more components
* as needed based on the Configuration passed in if these additional components don't exist in the
- * {@link ComponentRegistry}.
+ * {@link ComponentRegistry}. Strictly for components that don't otherwise live in the registry and have a lifecycle, such as Nodes.
*
* @param target object to wire
* @throws ConfigurationException if there is a problem wiring the instance
@@ -286,7 +320,7 @@
//if (log.isTraceEnabled()) log.trace("Inspecting class " + target.getClass());
try
{
- List<Method> methods = getAllMethods(target.getClass(), Inject.class);
+ List<Method> methods = ReflectionUtil.getAllMethods(target.getClass(), Inject.class);
//if (log.isTraceEnabled()) log.trace("Found method set containing " + methods.size() + " methods that need injection: " + methods);
// search for anything we need to inject
@@ -316,14 +350,13 @@
private <T> void performInjection(Method method, T target) throws IllegalAccessException, InvocationTargetException
{
Class[] parameterTypes = method.getParameterTypes();
- Annotation[][] annotationsOnParams = method.getParameterAnnotations();
+ List<Dependency> componentsToInject = getDeclaredDependencies(method);
Object[] parameters = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++)
{
- String componentName = extractComponentName(annotationsOnParams[i]);
- parameters[i] = getOrCreateComponent(componentName, parameterTypes[i]);
+ parameters[i] = getComponent(componentsToInject.get(i).name, parameterTypes[i]);
}
// make sure we set this method to be accessible, so we can call private, package and protected
@@ -347,53 +380,23 @@
return null;
}
- /**
- * Returns a set of Methods that require components injected. This includes all public, protected, package and private
- * methods, as well as those of superclasses. Note that this does *not* include overridden methods.
- * <p/>
- * Includes all methods annotated with &Inject as well as methods that are <i>not</i> annotated, but instead
- * have parameters annotated accordingly.
- *
- * @param c class to inspect
- * @param annotationType the type of annotation to look for
- * @return Set of Method objects that require injection.
- */
- private List<Method> getAllMethods(Class c, Class<? extends Annotation> annotationType)
+ private List<Dependency> getDeclaredDependencies(Method method)
{
- List<Method> annotated = new LinkedList<Method>();
- inspectRecursively(c, annotated, annotationType);
- return annotated;
- }
-
- private void inspectRecursively(Class c, List<Method> s, Class<? extends Annotation> annotationType)
- {
- // Superclass first
- if (!c.equals(Object.class)) inspectRecursively(c.getSuperclass(), s, annotationType);
-
- for (Method m : c.getDeclaredMethods())
+ List<Dependency> dependencies = new LinkedList<Dependency>();
+ Class[] parameterTypes = method.getParameterTypes();
+ Annotation[][] annotationsOnParams = method.getParameterAnnotations();
+ for (int i = 0; i < parameterTypes.length; i++)
{
- // don't bother if this method has already been overridden by a subclass
- if (!alreadyFound(m, s) && m.isAnnotationPresent(annotationType))
- {
- s.add(m);
- }
+ String componentName = extractComponentName(annotationsOnParams[i]);
+ Dependency d = new Dependency(componentName == null ? parameterTypes[i].getName() : componentName, parameterTypes[i]);
+ dependencies.add(d);
}
+ return dependencies;
}
- private boolean alreadyFound(Method m, Collection<Method> s)
- {
- for (Method found : s)
- {
- if (m.getName().equals(found.getName()) &&
- Arrays.equals(m.getParameterTypes(), found.getParameterTypes()))
- return true;
- }
- return false;
- }
-
-
/**
- * Retrieves a component factory instance capable of constructing components of a specified type.
+ * Retrieves a component factory instance capable of constructing components of a specified type. If the factory doesn't
+ * exist in the registry, one is created. Always changes the state of any factory to {@link State#STARTED} before returning.
*
* @param componentClass type of component to construct
* @return component factory capable of constructing such components
@@ -412,15 +415,19 @@
cf = instantiateFactory(cfClass);
if (cf != null)
{
- // wire factory deps
- wireDependencies(cf);
- // register this factory
+ // we simply register this factory. Registration will take care of constructing any dependencies.
registerComponent(cf);
}
}
if (cf == null)
throw new ConfigurationException("Unable to locate component factory for component " + componentClass);
+
+ // ensure the component factory is in the STARTED state!
+ Component c = componentLookup.get(cfClass.getName());
+ if (c.instance != cf)
+ throw new ConfigurationException("Component factory " + cfClass + " incorrectly registered!");
+ c.changeState(STARTED);
return cf;
}
@@ -445,111 +452,339 @@
/**
* No such thing as a meta factory yet. Factories are created using this method which attempts to use an empty public
- * constructor, or a "getInstance" method.
+ * constructor.
*
* @param factory class of factory to be created
* @return factory instance
*/
ComponentFactory instantiateFactory(Class<? extends ComponentFactory> factory)
{
- Constructor ctor = null;
- Method singletonAccessor = null;
try
{
- ctor = factory.getConstructor();
+ return factory.newInstance();
}
- catch (NoSuchMethodException e)
+ catch (Exception e)
{
- log.trace("No default, public constructor on " + factory);
- // perhaps this factory is a singleton.
- try
- {
- singletonAccessor = factory.getMethod("getInstance");
- }
- catch (NoSuchMethodException e1)
- {
- log.trace("No getInstance() method on " + factory);
- }
+ // unable to get a hold of an instance!!
+ throw new ConfigurationException("Unable to instantiate factory " + factory, e);
}
+ }
- if (ctor == null && singletonAccessor == null)
+ /**
+ * Wipes everything in the registry. Use with care.
+ */
+ public void reset()
+ {
+ componentLookup.clear();
+ overallState = CONSTRUCTED;
+ }
+
+ /**
+ * Starts all components that contain the {@link Start} annotation.
+ */
+ public void start()
+ {
+ moveComponentsToState(STARTED);
+ }
+
+ /**
+ * Stops all components that contain the {@link Stop} annotation.
+ */
+ public void stop()
+ {
+ moveComponentsToState(STOPPED);
+ }
+
+ /**
+ * Injects dependencies to all components that require injection.
+ */
+ public void wire()
+ {
+ moveComponentsToState(WIRED);
+ }
+
+ void moveComponentsToState(State state)
+ {
+ for (Component c : componentLookup.values())
{
- // unable to get a hold of an instance!!
- throw new ConfigurationException("Unable to instantiate factory " + factory + ": no public, default constructor or getInstance() static method!");
+ c.changeState(state);
}
+ overallState = state;
+ }
- ComponentFactory instance;
- try
+ /**
+ * Represents the state of a component
+ */
+ enum State
+ {
+ STOPPED, CONSTRUCTED, WIRED, STARTED;
+
+ /**
+ * Tests whether the current state is "greater" than the state passed in
+ *
+ * @param other state to compare with
+ * @return true if the current state is "greater" than the state passed in
+ */
+ boolean isGreaterThan(State other)
{
- if (ctor == null)
- {
- instance = (ComponentFactory) singletonAccessor.invoke(null);
- }
- else
- {
- instance = (ComponentFactory) ctor.newInstance();
- }
+ return this.ordinal() > other.ordinal();
}
- catch (Exception e)
+
+ /**
+ * Tests whether the current state is "less" than the state passed in
+ *
+ * @param other state to compare with
+ * @return true if the current state is "less" than the state passed in
+ */
+ boolean isLessThan(State other)
{
- throw new ConfigurationException("Unable to instantiate factory " + factory, e);
+ return this.ordinal() < other.ordinal();
}
- return instance;
+ /**
+ * @param other state to compare with
+ * @return the absolute difference in ordinal places between 2 states
+ */
+ int absoluteDifference(State other)
+ {
+ return Math.abs(this.ordinal() - other.ordinal());
+ }
}
/**
- * Wipes everything in the registry. Use with care.
+ * Represents a potentially unconstructed dependency. A simple wrapper around a name and type pair.
*/
- public void reset()
+ class Dependency
{
- registry.clear();
+ String name;
+ Class<?> type;
+
+ public Dependency(String name, Class type)
+ {
+ this.name = name;
+ this.type = type;
+ }
+
+ public int hashCode()
+ {
+ return 31 * name.hashCode();
+ }
+
+ public boolean equals(Object other)
+ {
+ return other instanceof Dependency && name.equals(((Dependency) other).name);
+ }
+
+ public String toString()
+ {
+ return "Dependency (name = " + name + ")";
+ }
}
/**
- * Starts all components that contain the {@link Start} annotation.
+ * Represents a component in the registry, along with state and dependencies.
*/
- public void startComponents()
+ class Component
{
- for (Object component : registry.values())
+ Object instance;
+ String name;
+ State state = CONSTRUCTED;
+ Set<Dependency> dependencies = new HashSet<Dependency>(3);
+ Set<Dependency> dependencyFor = new HashSet<Dependency>(3);
+ Dependency me;
+ boolean deepRecursionDetector = false;
+
+ /**
+ * Constructs a Component out of an instance and a name. Scans instance for dependencies and populates
+ * the "dependencies" and "dependencyFor" collections.
+ *
+ * @param name name of component
+ * @param instance component instance
+ */
+ public Component(String name, Object instance)
{
- List<Method> methods = getAllMethods(component.getClass(), Start.class);
- for (Method m : methods)
+ this.instance = instance;
+ this.name = name;
+
+ // now scan the instance for all dependencies.
+ List<Method> injectionMethods = ReflectionUtil.getAllMethods(instance.getClass(), Inject.class);
+
+ // now for each injection method, get dependencies
+ for (Method m : injectionMethods) dependencies.addAll(getDeclaredDependencies(m));
+
+ // backward-chaining - make sure I know about components that depend on me.
+ me = asDependency();
+ for (Dependency d : dependencies)
{
- try
+ Component c = componentLookup.get(d.name);
+ if (c != null) c.dependencyFor.add(me);
+ }
+ }
+
+ /**
+ * @return a {@link org.jboss.cache.factories.ComponentRegistry.Dependency} object that represents the current component
+ */
+ Dependency asDependency()
+ {
+ if (me == null) me = new Dependency(name, null);
+ return me;
+ }
+
+ /**
+ * Changes the state of a component - along with all dependent components - to a new state. This method is recursion
+ * and cyclic dependency safe.
+ *
+ * @param newState new state to move component to
+ */
+ void changeState(State newState)
+ {
+ // Deep recursion is when this component depends on another component which in turn may depend on this component again.
+ // if this is encountered then break out of the recursive loop.
+ if (state != newState && !deepRecursionDetector)
+ {
+ // Step by step. If the new state is > 1 step away from the current state, change state gradually.
+ boolean increase = newState.isGreaterThan(state);
+ int numSteps = newState.absoluteDifference(state);
+
+ while (numSteps > 1)
{
- m.setAccessible(true);
- m.invoke(component);
+ changeState(State.values()[state.ordinal() + (increase ? 1 : -1)]);
+ numSteps = newState.absoluteDifference(state);
}
- catch (Exception e)
+
+ // now we update the state of dependent components accordingly.
+ Set<Dependency> dependentComponents = new HashSet<Dependency>();
+ Set<Component> shallowCyclic = new HashSet<Component>();
+
+ if (increase)
{
- log.warn("Unable to invoke @Start annotated method " + m, e);
+ // if I am moving to a "higher" state make sure all components that I depend on have moved to that state as well.
+ dependentComponents.addAll(dependencies);
}
+ else
+ {
+ // if I am moving to a "lower" state make sure all components depend on me have moved to that state as well.
+ dependentComponents.addAll(dependencyFor);
+ }
+
+ // switch on the deep recursion detector
+ deepRecursionDetector = true;
+ for (Dependency d : dependentComponents)
+ {
+ Component c = componentLookup.get(d.name);
+ if (c != null)
+ {
+ if (isShallowCyclic(c))
+ {
+ // don't process shallow cyclic deps here - shoud do that after we set our state.
+ shallowCyclic.add(c);
+ }
+ else
+ {
+ // of we are "moving up" - only do this if the component is lower than what is needed.
+ if ((increase && newState.isGreaterThan(c.state)) || (!increase && newState.isLessThan(c.state)))
+ c.changeState(newState);
+
+ }
+ }
+ }
+
+ // NOW we update our state.
+ switch (newState)
+ {
+ case STOPPED:
+ stop();
+ break;
+ case WIRED:
+ wire();
+ break;
+ case STARTED:
+ start();
+ break;
+ case CONSTRUCTED:
+ // nothing to do here.
+ }
+
+ state = newState;
+
+ // now process the shallow cyclic deps
+ for (Component c : shallowCyclic)
+ {
+ // of we are "moving up" - only do this if the component is lower than what is needed.
+ if ((increase && newState.isGreaterThan(c.state)) || (!increase && newState.isLessThan(c.state)))
+ c.changeState(newState);
+ }
+
+ // make sure we switch off the deep recursion detector now.
+ deepRecursionDetector = false;
}
}
- }
- /**
- * Stops all components that contain the {@link Stop} annotation.
- */
- public void stopComponents()
- {
- for (Object component : registry.values())
+ /**
+ * Tests whether there is an immediate cyclic dependency (i.e., both components depend on each other) between the current component and another one.
+ *
+ * @param c other component to test with
+ * @return true if there is an immediate cyclic dependency between the 2 components
+ */
+ private boolean isShallowCyclic(Component c)
{
- List<Method> methods = getAllMethods(component.getClass(), Stop.class);
+ return (dependencies.contains(c.asDependency()) && c.dependencies.contains(asDependency()));
+ }
+
+ /**
+ * Used to wire dependencies into this component instance.
+ */
+ void wire()
+ {
+ try
+ {
+ List<Method> methods = ReflectionUtil.getAllMethods(instance.getClass(), Inject.class);
+
+ // search for anything we need to inject
+ for (Method method : methods) performInjection(method, instance);
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationException("Unable to configure component (type: " + instance.getClass() + ", instance " + instance + ")", e);
+ }
+ }
+
+ /**
+ * Used to call all methods annotated with {@link Start} on component instance
+ */
+ void start()
+ {
+ invokeMethods(Start.class);
+ }
+
+ /**
+ * Used to call all methods annotated with {@link Stop} on component instance
+ */
+ void stop()
+ {
+ invokeMethods(Stop.class);
+ }
+
+ private void invokeMethods(Class<? extends Annotation> annotation)
+ {
+ List<Method> methods = ReflectionUtil.getAllMethods(instance.getClass(), annotation);
for (Method m : methods)
{
try
{
m.setAccessible(true);
- m.invoke(component);
+ m.invoke(instance);
}
catch (Exception e)
{
- log.warn("Unable to invoke @Stop annotated method " + m, e);
+ log.warn("Unable to invoke annotated method " + m, e);
}
}
}
+
+ public String toString()
+ {
+ return "Component (name = " + name + ", state = " + state + ")";
+ }
}
-
-}
+}
\ No newline at end of file
Modified: core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/main/java/org/jboss/cache/factories/InterceptorChainFactory.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -58,7 +58,7 @@
if (i == null)
{
i = clazz.newInstance();
- componentRegistry.wireDependencies(i);
+// componentRegistry.wireDependencies(i);
// add this interceptor as a NAMED component into the registry
componentRegistry.registerComponent(clazz.getName(), i);
}
@@ -584,41 +584,37 @@
}
/**
- * The same as {@link #correctInterceptorChaining(java.util.List, org.jboss.cache.config.Configuration, ComponentRegistry)}
+ * The same as {@link #correctInterceptorChaining(java.util.List)}
* except that it takes in the first interceptor in the chain instead of a list of interceptors, and traverses the chain to
* generate a list. Identical to calling
* <pre>
* InterceptorChainFactory.correctInterceptorChaining( InterceptorChainFactory.asList(first), configuration, componentRegistry );
* </pre>
*
- * @param first first interceptor in the chain to correct.
- * @param configuration cache configuration
- * @param componentRegistry component registry
+ * @param first first interceptor in the chain to correct.
* @return the first interceptor in the chain.
*/
- public Interceptor correctInterceptorChaining(Interceptor first, Configuration configuration, ComponentRegistry componentRegistry)
+ public Interceptor correctInterceptorChaining(Interceptor first)
{
- return correctInterceptorChaining(asList(first), configuration, componentRegistry);
+ return correctInterceptorChaining(asList(first));
}
/**
* "Fixes" the next() and last() pointers for each interceptor, based on the order presented in the list passed in, and
* also re-assesses dependencies for each interceptor, injecting dependencies accordingingly.
*
- * @param interceptors interceptor chain to correct
- * @param configuration cache configuration
- * @param componentRegistry component registry
+ * @param interceptors interceptor chain to correct
* @return the first interceptor in the chain.
*/
- public Interceptor correctInterceptorChaining(List<Interceptor> interceptors, Configuration configuration, ComponentRegistry componentRegistry)
+ public Interceptor correctInterceptorChaining(List<Interceptor> interceptors)
{
+ // re-wire
+ componentRegistry.updateDependencies();
+
Interceptor first = null, last = null;
for (Interceptor next : interceptors)
{
- // re-wire
- componentRegistry.wireDependencies(next);
-
if (first == null)
{
first = last = next;
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/CacheLoaderInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/CacheLoaderInterceptor.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/CacheLoaderInterceptor.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -316,6 +316,7 @@
if (node != null && node.isChildrenLoaded())
{
+ log.trace("Children already loaded!");
return;
}
Set children_names = loader.getChildrenNames(fqn);
Modified: core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -414,7 +414,6 @@
public Node getNode(Fqn<?> fqn)
{
- GlobalTransaction tx = cache.getCurrentTransaction();
MethodCall m = MethodCallFactory.create(MethodDeclarations.getNodeMethodLocal, fqn);
return (Node) invoke(m);
}
Copied: core/trunk/src/main/java/org/jboss/cache/util/reflect/ClasspathScanner.java (from rev 4871, core/trunk/src/main/java/org/jboss/cache/factories/annotations/ClasspathScanner.java)
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/reflect/ClasspathScanner.java (rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/util/reflect/ClasspathScanner.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -0,0 +1,171 @@
+package org.jboss.cache.util.reflect;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * Class for scanning archives and classpaths in the current JBoss Cache classpath for classes annotated with a given annotation. Inspired by a similar class in
+ * JBoss SEAM.
+ *
+ * @author Manik Surtani
+ */
+public class ClasspathScanner
+{
+ private Log log = LogFactory.getLog(ClasspathScanner.class);
+ private URLClassLoader classLoader;
+
+ /**
+ * Constructor with the type of annotation to scan for.
+ */
+ public ClasspathScanner()
+ {
+ classLoader = (URLClassLoader) ClasspathScanner.class.getClassLoader();
+ }
+
+ /**
+ * Scans the class path element that contains JBoss Cache for all classes that contain the annotation type this class is
+ * initialised with. Note that this only scans CLASSES for the annotation; not methods, etc.
+ *
+ * @param annotationType the type of annotation to scan for.
+ * @param classType the type of class to scan for. Subclasses will be scanned, others will not.
+ * @return a set of Classes that contain the specified annotation on the class.
+ */
+ public <T> Set<Class<? extends T>> scan(Class<? extends Annotation> annotationType, Class<T> classType)
+ {
+ Set<Class<? extends T>> classes = Collections.emptySet();
+
+ try
+ {
+ // only scan the current ClassPath location that contains this file. Could be a directory or a JAR file.
+ URL url = getURLPathFromClassLoader();
+ String urlPath = url.getFile();
+ if (urlPath.endsWith("/"))
+ {
+ urlPath = urlPath.substring(0, urlPath.length() - 1);
+ }
+
+ if (log.isDebugEnabled()) log.debug("scanning: " + urlPath);
+ File file = new File(urlPath);
+ if (file.isDirectory())
+ {
+ classes = handleDirectory(file, null, classType, annotationType);
+ }
+ else
+ {
+ classes = handleArchive(file, classType, annotationType);
+ }
+ }
+ catch (IOException ioe)
+ {
+ log.warn("could not read entries", ioe);
+ }
+ catch (ClassNotFoundException e)
+ {
+ log.warn("Unable to load class", e);
+ }
+
+ return classes;
+ }
+
+ private URL getURLPathFromClassLoader() throws MalformedURLException
+ {
+ URL u2 = classLoader.findResource("org/jboss/cache/Version.class");
+
+ for (URL u : classLoader.getURLs())
+ {
+ String urlString = u.toString().replaceAll("\\/\\.\\/", "/");
+ if (u2.toString().startsWith(urlString))
+ {
+ return new URL(urlString);
+ }
+ }
+
+ return null;
+ }
+
+
+ private <T> Set<Class<? extends T>> handleArchive(File file, Class<T> classType, Class<? extends Annotation> annotationType) throws IOException, ClassNotFoundException
+ {
+ Set<Class<? extends T>> classesWithAnnotations = new HashSet<Class<? extends T>>();
+ ZipFile zip = new ZipFile(file);
+ Enumeration<? extends ZipEntry> entries = zip.entries();
+ while (entries.hasMoreElements())
+ {
+ ZipEntry entry = entries.nextElement();
+ String name = entry.getName();
+ Class<? extends T> c = handleItem(name, classType, annotationType);
+ if (c != null) classesWithAnnotations.add(c);
+ }
+
+ return classesWithAnnotations;
+ }
+
+ private <T> Set<Class<? extends T>> handleDirectory(File file, String path, Class<T> classType, Class<? extends Annotation> annotationType) throws IOException, ClassNotFoundException
+ {
+ Set<Class<? extends T>> classesWithAnnotations = new HashSet<Class<? extends T>>();
+ for (File child : file.listFiles())
+ {
+ String newPath = path == null ? child.getName() : path + '/' + child.getName();
+ if (child.isDirectory())
+ {
+ classesWithAnnotations.addAll(handleDirectory(child, newPath, classType, annotationType));
+ }
+ else
+ {
+ Class<? extends T> c = handleItem(newPath, classType, annotationType);
+ if (c != null)
+ {
+ classesWithAnnotations.add(c);
+ }
+ }
+ }
+
+ return classesWithAnnotations;
+ }
+
+ private <T> Class<? extends T> handleItem(String name, Class<T> classType, Class<? extends Annotation> annotationType) throws IOException, ClassNotFoundException
+ {
+ if (!name.endsWith(".class")) return null;
+
+ Class<? extends T> c = getClassFile(filenameToClassname(name), classType);
+ if (c != null && hasAnnotation(c, annotationType))
+ {
+ return c;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private <T> Class<? extends T> getClassFile(String name, Class<T> classType) throws IOException, ClassNotFoundException
+ {
+ Class c = classLoader.loadClass(name);
+ if (c != null && classType.isAssignableFrom(c)) return c;
+ else return null;
+ }
+
+ private boolean hasAnnotation(Class clazz, Class<? extends Annotation> annotationType)
+ {
+ return (clazz.isAnnotationPresent(annotationType));
+ }
+
+ private static String filenameToClassname(String filename)
+ {
+ return filename.substring(0, filename.lastIndexOf(".class")).replace('/', '.').replace('\\', '.');
+ }
+
+}
Added: core/trunk/src/main/java/org/jboss/cache/util/reflect/ReflectionUtil.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/reflect/ReflectionUtil.java (rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/util/reflect/ReflectionUtil.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -0,0 +1,73 @@
+package org.jboss.cache.util.reflect;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Basic reflection utilities to enhance what the JDK provides.
+ *
+ * @author Manik Surtani (<a href="mailto:manik@jboss.org">manik(a)jboss.org</a>)
+ * @since 2.1.0
+ */
+public class ReflectionUtil
+{
+ /**
+ * Returns a set of Methods that contain the given method annotation. This includes all public, protected, package and private
+ * methods, as well as those of superclasses. Note that this does *not* include overridden methods.
+ *
+ * @param c class to inspect
+ * @param annotationType the type of annotation to look for
+ * @return List of Method objects that require injection.
+ */
+ public static List<Method> getAllMethods(Class c, Class<? extends Annotation> annotationType)
+ {
+ List<Method> annotated = new LinkedList<Method>();
+ inspectRecursively(c, annotated, annotationType);
+ return annotated;
+ }
+
+ /**
+ * Inspects a class and it's superclasses (all the way to {@link Object} for method instances that contain a given annotation.
+ * This even identifies private, package and protected methods, not just public ones.
+ *
+ * @param c
+ * @param s
+ * @param annotationType
+ */
+ private static void inspectRecursively(Class c, List<Method> s, Class<? extends Annotation> annotationType)
+ {
+ // Superclass first
+ if (!c.equals(Object.class)) inspectRecursively(c.getSuperclass(), s, annotationType);
+
+ for (Method m : c.getDeclaredMethods())
+ {
+ // don't bother if this method has already been overridden by a subclass
+ if (!alreadyFound(m, s) && m.isAnnotationPresent(annotationType))
+ {
+ s.add(m);
+ }
+ }
+ }
+
+ /**
+ * Tests whether a method has already been found, i.e., overridden.
+ *
+ * @param m method to inspect
+ * @param s collection of methods found
+ * @return true a method with the same signature already exists.
+ */
+ private static boolean alreadyFound(Method m, Collection<Method> s)
+ {
+ for (Method found : s)
+ {
+ if (m.getName().equals(found.getName()) &&
+ Arrays.equals(m.getParameterTypes(), found.getParameterTypes()))
+ return true;
+ }
+ return false;
+ }
+}
Copied: core/trunk/src/test/java/org/jboss/cache/factories/ComponentRegistryFunctionalTest.java (from rev 4851, core/trunk/src/test/java/org/jboss/cache/factories/ComponentRegistryTest.java)
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/factories/ComponentRegistryFunctionalTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/factories/ComponentRegistryFunctionalTest.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -0,0 +1,227 @@
+package org.jboss.cache.factories;
+
+import org.jboss.cache.CacheImpl;
+import org.jboss.cache.CacheSPI;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.RPCManager;
+import org.jboss.cache.RegionManager;
+import org.jboss.cache.buddyreplication.BuddyManager;
+import org.jboss.cache.buddyreplication.NextMemberBuddyLocator;
+import org.jboss.cache.config.BuddyReplicationConfig;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.factories.annotations.Inject;
+import org.jboss.cache.invocation.CacheInvocationDelegate;
+import org.jboss.cache.marshall.CacheMarshaller200;
+import org.jboss.cache.marshall.CacheMarshaller210;
+import org.jboss.cache.marshall.Marshaller;
+import org.jboss.cache.marshall.VersionAwareMarshaller;
+import org.jboss.cache.misc.TestingUtil;
+import org.jboss.cache.notifications.Notifier;
+import org.jboss.cache.statetransfer.StateTransferManager;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * @author Manik Surtani (<a href="mailto:manik@jboss.org">manik(a)jboss.org</a>)
+ * @since 2.1.0
+ */
+@Test(groups = {"functional"})
+public class ComponentRegistryFunctionalTest
+{
+ private ComponentFactory cf;
+ private ComponentRegistry cr;
+ private Configuration configuration;
+
+ @BeforeMethod
+ public void setUp() throws Exception
+ {
+ cf = (ComponentFactory) DefaultCacheFactory.getInstance();
+
+ CacheSPI spi = new CacheInvocationDelegate();
+ Constructor ctor = CacheImpl.class.getDeclaredConstructor();
+ ctor.setAccessible(true);
+ CacheImpl ci = (CacheImpl) ctor.newInstance();
+
+ configuration = ci.getConfiguration();
+ cr = TestingUtil.extractComponentRegistry(ci);
+
+ cf.componentRegistry = cr;
+ cf.configuration = configuration;
+
+ cr.registerComponent(cr); // register self
+ cr.registerComponent(ci);
+ cr.registerComponent(spi);
+ cr.registerComponent(configuration);
+
+ cr.wire();
+ }
+
+ public void testDefaultFactoryScanning()
+ {
+ cr.scanDefaultFactories();
+
+ assert cr.defaultFactories != null : "Should be populated";
+
+ // at very least, expecting a Marshaller factory and a DefaultCacheFactory.
+ assert cr.defaultFactories.containsKey(Marshaller.class);
+ assert cr.defaultFactories.get(Marshaller.class).equals(CacheMarshallerFactory.class);
+ assert cr.defaultFactories.containsKey(Notifier.class);
+ assert cr.defaultFactories.get(Notifier.class).equals(EmptyConstructorFactory.class);
+
+ }
+
+ public void testNamedComponents()
+ {
+ cr.registerComponent("blah", new Object());
+ Object namedComponent1 = cr.getOrCreateComponent("blah", Object.class);
+ Object namedComponent2 = cr.getOrCreateComponent("blah", Object.class);
+
+ assert namedComponent1 == namedComponent2;
+ }
+
+ /**
+ * Case 1:
+ * nothing injected, nothing specified in Configuration. Should use default factory.
+ */
+ public void testConstructionOrder1()
+ {
+ Class<Marshaller> componentToTest = Marshaller.class;
+ Marshaller m = cr.getOrCreateComponent(null, componentToTest);
+ assert m instanceof VersionAwareMarshaller;
+ VersionAwareMarshaller vam = (VersionAwareMarshaller) m;
+ m = (Marshaller) TestingUtil.extractField(vam, "defaultMarshaller");
+ assert m instanceof CacheMarshaller210;
+ }
+
+ /**
+ * Case 2:
+ * instance injected, class specified in Configuration. Should use injected.
+ */
+ public void testConstructionOrder2()
+ {
+ Class<Marshaller> componentToTest = Marshaller.class;
+ configuration.setMarshallerClass(CacheMarshaller200.class.getName());
+ Marshaller instance = new CacheMarshaller210(null, false, false);
+ configuration.setCacheMarshaller(instance);
+
+ // the setup() would have wired the default marshaller. Need to update deps.
+ cr.unregisterComponent(Marshaller.class);
+ cr.updateDependencies();
+
+ Marshaller m = cr.getOrCreateComponent(null, componentToTest);
+ assert m == instance : "m is " + m + " but expected " + instance;
+ }
+
+ /**
+ * Case 3:
+ * instance injected, no class specified in Configuration. Should use injected.
+ */
+ public void testConstructionOrder3()
+ {
+ Class<Marshaller> componentToTest = Marshaller.class;
+ Marshaller instance = new CacheMarshaller210(null, false, false);
+ configuration.setCacheMarshaller(instance);
+
+ // the setup() would have wired the default marshaller. Need to update deps.
+ cr.unregisterComponent(Marshaller.class);
+ cr.updateDependencies();
+
+ Marshaller m = cr.getOrCreateComponent(null, componentToTest);
+ assert m == instance : "m is " + m + " but expected " + instance;
+ }
+
+ /**
+ * Case 4:
+ * nothing injected, class specified in Configuration. Should use class specified.
+ */
+ public void testConstructionOrder4()
+ {
+ Class<Marshaller> componentToTest = Marshaller.class;
+ configuration.setMarshallerClass(CacheMarshaller200.class.getName());
+ Marshaller m = cr.getOrCreateComponent(null, componentToTest);
+ assert m instanceof VersionAwareMarshaller;
+ VersionAwareMarshaller vam = (VersionAwareMarshaller) m;
+ m = (Marshaller) TestingUtil.extractField(vam, "defaultMarshaller");
+ assert m instanceof CacheMarshaller200;
+ }
+
+ public void testTransitiveDependencies()
+ {
+ Class<BuddyManager> componentToTest = BuddyManager.class;
+
+ // configure the cfg to use BR
+ BuddyReplicationConfig brc = new BuddyReplicationConfig();
+ brc.setEnabled(true);
+ BuddyReplicationConfig.BuddyLocatorConfig blc = new BuddyReplicationConfig.BuddyLocatorConfig();
+ blc.setBuddyLocatorClass(NextMemberBuddyLocator.class.getName());
+ brc.setBuddyLocatorConfig(blc);
+ configuration.setBuddyReplicationConfig(brc);
+
+ BuddyManager bm = cr.getOrCreateComponent(null, componentToTest);
+ assert bm != null;
+
+ StateTransferManager stm = (StateTransferManager) TestingUtil.extractField(bm, "stateTransferManager");
+ assert stm != null;
+
+ RPCManager rpcm = (RPCManager) TestingUtil.extractField(bm, "rpcManager");
+ assert rpcm != null;
+
+ RegionManager rm = (RegionManager) TestingUtil.extractField(bm, "regionManager");
+ assert rm != null;
+
+ Configuration cfg = (Configuration) TestingUtil.extractField(bm, "configuration");
+ assert cfg == configuration;
+ }
+
+ public void testInjectionOrder()
+ {
+ // injection should only occur after dependent components have been fully wired.
+
+ // E.g. Test1 depends on Test2 and Test2 depends on Test3.
+ //cr.reset();
+
+ // DefaultFactoryFor annotation won't work since tests are compiled into a separate classpath
+ cr.defaultFactories.put(Test1.class, EmptyConstructorFactory.class);
+ cr.defaultFactories.put(Test2.class, EmptyConstructorFactory.class);
+ cr.defaultFactories.put(Test3.class, EmptyConstructorFactory.class);
+
+ Test1 t1 = cr.getOrCreateComponent(null, Test1.class);
+
+ assert t1 != null;
+ assert t1.test2 != null;
+ assert t1.test2.test3 != null;
+ assert t1.someValue == t1.test2.test3.someValue;
+ }
+
+ public static class Test1
+ {
+ private Test2 test2;
+ private boolean someValue = false;
+
+ @Inject
+ public void setTest2(Test2 test2)
+ {
+ this.test2 = test2;
+ someValue = test2.test3.someValue;
+ }
+ }
+
+ public static class Test2
+ {
+ private Test3 test3;
+
+ @Inject
+ public void setTest3(Test3 test3)
+ {
+ this.test3 = test3;
+ }
+ }
+
+ public static class Test3
+ {
+ private boolean someValue = true;
+ }
+}
+
Added: core/trunk/src/test/java/org/jboss/cache/factories/ComponentRegistryUnitTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/factories/ComponentRegistryUnitTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/factories/ComponentRegistryUnitTest.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -0,0 +1,107 @@
+package org.jboss.cache.factories;
+
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.factories.annotations.ComponentName;
+import org.jboss.cache.factories.annotations.Inject;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * @author Manik Surtani (<a href="mailto:manik@jboss.org">manik(a)jboss.org</a>)
+ * @since 2.1.0
+ */
+@Test(groups = "functional")
+public class ComponentRegistryUnitTest
+{
+ ComponentRegistry cr;
+ Configuration cfg;
+
+ @BeforeMethod
+ public void setUp()
+ {
+ cr = new ComponentRegistry(new Configuration());
+ cfg = cr.getConfiguration();
+ }
+
+ public void testChangingComponentState()
+ {
+ cr.registerComponent("c2", new C2());
+ cr.registerComponent("c1", new C1());
+ cr.registerComponent("c3", new C3());
+
+ ComponentRegistry.Component c1 = cr.componentLookup.get("c1");
+ ComponentRegistry.Component c2 = cr.componentLookup.get("c2");
+ ComponentRegistry.Component c3 = cr.componentLookup.get("c3");
+
+ // add some dependencies
+ ComponentRegistry.Dependency d1 = cr.new Dependency("c1", null);
+ ComponentRegistry.Dependency d2 = cr.new Dependency("c2", null);
+ ComponentRegistry.Dependency d3 = cr.new Dependency("c3", null);
+
+ // c1 depends on c2
+ // c3 depends on c1
+
+ // test dependency and dependencyFor
+
+ assert c2.dependencies.isEmpty();
+ assert c1.dependencies.contains(d2);
+ assert c1.dependencies.size() == 1;
+ assert c3.dependencies.contains(d1);
+ assert c3.dependencies.size() == 1;
+
+ assert c2.dependencyFor.contains(d1);
+ assert c2.dependencyFor.size() == 1;
+ assert c1.dependencyFor.contains(d3);
+ assert c1.dependencyFor.size() == 1;
+ assert c3.dependencyFor.isEmpty();
+
+ assert c1.state == ComponentRegistry.State.CONSTRUCTED;
+ assert c2.state == ComponentRegistry.State.CONSTRUCTED;
+ assert c3.state == ComponentRegistry.State.CONSTRUCTED;
+
+ c1.changeState(ComponentRegistry.State.WIRED);
+
+ assert c1.state == ComponentRegistry.State.WIRED;
+ assert c2.state == ComponentRegistry.State.WIRED;
+ assert c3.state == ComponentRegistry.State.CONSTRUCTED;
+
+ c3.changeState(ComponentRegistry.State.STARTED);
+
+ assert c1.state == ComponentRegistry.State.STARTED;
+ assert c2.state == ComponentRegistry.State.STARTED;
+ assert c3.state == ComponentRegistry.State.STARTED;
+
+ c1.changeState(ComponentRegistry.State.CONSTRUCTED);
+
+ assert c1.state == ComponentRegistry.State.CONSTRUCTED;
+ assert c2.state == ComponentRegistry.State.STARTED;
+ assert c3.state == ComponentRegistry.State.CONSTRUCTED;
+ }
+
+ public static class C1
+ {
+ C2 c2;
+
+ @Inject
+ private void inject(@ComponentName("c2")C2 c2)
+ {
+ this.c2 = c2;
+ }
+ }
+
+ public static class C2
+ {
+
+ }
+
+ public static class C3
+ {
+ C1 c1;
+
+ @Inject
+ private void inject(@ComponentName("c1")C1 c1)
+ {
+ this.c1 = c1;
+ }
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/factories/DependencyGraphTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/factories/DependencyGraphTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/factories/DependencyGraphTest.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -0,0 +1,78 @@
+package org.jboss.cache.factories;
+
+import org.jboss.cache.factories.annotations.Inject;
+import org.testng.annotations.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Manik Surtani (<a href="mailto:manik@jboss.org">manik(a)jboss.org</a>)
+ * @since 2.1.0
+ */
+@Test(groups = "functional")
+public class DependencyGraphTest
+{
+ public void testDependencies()
+ {
+ Map<Object, Object> components = new HashMap<Object, Object>();
+ components.put(Test1.class, new Test1());
+ components.put(Test2.class, new Test2());
+ components.put(Test3.class, new Test3());
+ components.put(Test4.class, new Test4());
+
+ // expected order - Test4, Test3, Test2, Test1
+ DependencyGraph dg = new DependencyGraph(components);
+ List<Object> ordered = dg.getOrderedComponentKeys();
+
+ assert ordered.size() == 4;
+
+ System.out.println(ordered);
+
+ int n = 0;
+ assert ordered.get(n++) == Test4.class;
+ assert ordered.get(n++) == Test3.class;
+ assert ordered.get(n++) == Test2.class;
+ assert ordered.get(n) == Test1.class;
+ }
+
+ public static class Test1
+ {
+ private Test2 test2;
+
+ @Inject
+ private void inject(Test2 test2)
+ {
+ this.test2 = test2;
+ }
+ }
+
+ public static class Test2
+ {
+ private Test3 test3;
+ private Test4 test4;
+
+ @Inject
+ private void inject(Test3 test3, Test4 test4)
+ {
+ this.test3 = test3;
+ this.test4 = test4;
+ }
+ }
+
+ public static class Test3
+ {
+ private Test4 test4;
+
+ @Inject
+ private void inject(Test4 test4)
+ {
+ this.test4 = test4;
+ }
+ }
+
+ public static class Test4
+ {
+ }
+}
Modified: core/trunk/src/test/java/org/jboss/cache/interceptors/EvictionInterceptorTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/interceptors/EvictionInterceptorTest.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/test/java/org/jboss/cache/interceptors/EvictionInterceptorTest.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -17,6 +17,7 @@
import org.jboss.cache.eviction.DummyEvictionConfiguration;
import org.jboss.cache.eviction.EvictedEventNode;
import org.jboss.cache.eviction.NodeEventType;
+import org.jboss.cache.factories.ComponentRegistry;
import org.jboss.cache.factories.InterceptorChainFactory;
import org.jboss.cache.lock.IsolationLevel;
import org.jboss.cache.marshall.MethodCall;
@@ -88,10 +89,12 @@
CallInterceptor ci = new CallInterceptor();
ei.setNext(ci);
- InterceptorChainFactory.getInstance().correctInterceptorChaining(interceptor, cache.getConfiguration(), TestingUtil.extractComponentRegistry(cache));
-
cache.getConfiguration().setCacheMode("LOCAL");
cache.start();
+
+ ComponentRegistry cr = TestingUtil.extractComponentRegistry(cache);
+
+ cr.getComponent(InterceptorChainFactory.class).correctInterceptorChaining(interceptor);
}
@AfterMethod(alwaysRun = true)
Modified: core/trunk/src/test/java/org/jboss/cache/loader/CacheLoaderTestsBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/loader/CacheLoaderTestsBase.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/test/java/org/jboss/cache/loader/CacheLoaderTestsBase.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -44,7 +44,6 @@
@Test(groups = {"functional"})
abstract public class CacheLoaderTestsBase extends AbstractCacheLoaderTestBase
{
-
private static final Log log = LogFactory.getLog(CacheLoaderTestsBase.class);
CacheSPI<Object, Object> cache;
CacheLoader loader = null;
@@ -80,6 +79,7 @@
@AfterMethod(alwaysRun = true)
public void tearDown() throws Exception
{
+ log.warn("********* Starting tearDown()");
cleanup();
try
{
@@ -755,7 +755,11 @@
cache.evict(Fqn.fromString("/a"));
// now load the children - this set childrenLoaded in /a/b to true
- cache.getNode("/a/b").getChildrenNames();
+// cache.getNode("/a/b").getChildrenNames();
+
+ NodeSPI n = (NodeSPI) cache.getNode("/a/b");
+ assert !n.isChildrenLoaded();
+
children = cache.getNode("/a/b").getChildrenNames();
assertEquals(3, children.size());
Modified: core/trunk/src/test/java/org/jboss/cache/loader/UnnecessaryLoadingTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/loader/UnnecessaryLoadingTest.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/test/java/org/jboss/cache/loader/UnnecessaryLoadingTest.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -48,7 +48,7 @@
cache.getCacheLoaderManager().setCacheLoader(mockCacheLoader);
// re-set the cache so that the mock CL is registered with the inerceptors.
- InterceptorChainFactory.getInstance().correctInterceptorChaining(cache.getInterceptorChain(), cache.getConfiguration(), TestingUtil.extractComponentRegistry(cache));
+ TestingUtil.extractComponentRegistry(cache).getComponent(InterceptorChainFactory.class).correctInterceptorChaining(cache.getInterceptorChain());
// lifecycle stuff
mockCacheLoader.stop();
Modified: core/trunk/src/test/java/org/jboss/cache/misc/TestingUtil.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/misc/TestingUtil.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/test/java/org/jboss/cache/misc/TestingUtil.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -94,7 +94,7 @@
System.out.println("Old interceptor chain: " + CachePrinter.printCacheInterceptors(cache));
// make sure the new interceptor is wired
ComponentRegistry cr = extractComponentRegistry(cache);
- cr.wireDependencies(interceptorToInject);
+ cr.registerComponent(interceptorToInject);
interceptorToInject.setCache(cache);
int index = -1;
for (Interceptor i : cache.getInterceptorChain())
@@ -527,13 +527,15 @@
ComponentRegistry cr = extractComponentRegistry(cache);
// This will replace the previous interceptor chain in the component registry
- cr.registerComponent(Interceptor.class, interceptor);
+ cr.registerComponent(Interceptor.class.getName(), interceptor);
// update all component dependencies
cr.updateDependencies();
+ InterceptorChainFactory factory = cr.getComponent(InterceptorChainFactory.class);
+
// make sure the new interceptors have their deps satisfied.
- InterceptorChainFactory.getInstance().correctInterceptorChaining(interceptor, cache.getConfiguration(), cr);
+ factory.correctInterceptorChaining(interceptor);
}
/**
Modified: core/trunk/src/test/java/org/jboss/cache/passivation/PassivationToDummyInMemoryCacheLoaderTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/passivation/PassivationToDummyInMemoryCacheLoaderTest.java 2007-12-18 15:03:42 UTC (rev 4871)
+++ core/trunk/src/test/java/org/jboss/cache/passivation/PassivationToDummyInMemoryCacheLoaderTest.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -2,7 +2,9 @@
import org.jboss.cache.config.CacheLoaderConfig;
import org.jboss.cache.loader.DummyInMemoryCacheLoader;
+import org.testng.annotations.Test;
+@Test(groups = {"functional"})
public class PassivationToDummyInMemoryCacheLoaderTest extends PassivationTestsBase
{
protected void configureCache() throws Exception
Copied: core/trunk/src/test/java/org/jboss/cache/util/reflect/ClasspathScannerTest.java (from rev 4836, core/trunk/src/test/java/org/jboss/cache/factories/annotations/ClasspathScannerTest.java)
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/util/reflect/ClasspathScannerTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/util/reflect/ClasspathScannerTest.java 2007-12-18 19:58:10 UTC (rev 4872)
@@ -0,0 +1,27 @@
+package org.jboss.cache.util.reflect;
+
+import org.jboss.cache.factories.CacheMarshallerFactory;
+import org.jboss.cache.factories.ComponentFactory;
+import org.jboss.cache.factories.TransactionManagerFactory;
+import org.jboss.cache.factories.annotations.DefaultFactoryFor;
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+/**
+ * @author Manik Surtani (<a href="mailto:manik@jboss.org">manik(a)jboss.org</a>)
+ * @since 2.1.0
+ */
+@Test(groups = {"functional"})
+public class ClasspathScannerTest
+{
+ public void testScanning()
+ {
+ ClasspathScanner cs = new ClasspathScanner();
+ Set<Class<? extends ComponentFactory>> sc = cs.scan(DefaultFactoryFor.class, ComponentFactory.class);
+
+ // should at least contain these 2.
+ assert sc.contains(TransactionManagerFactory.class);
+ assert sc.contains(CacheMarshallerFactory.class);
+ }
+}
[View Less]
17 years, 3 months
JBoss Cache SVN: r4871 - core/trunk/src/main/java/org/jboss/cache/factories/annotations.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-12-18 10:03:42 -0500 (Tue, 18 Dec 2007)
New Revision: 4871
Modified:
core/trunk/src/main/java/org/jboss/cache/factories/annotations/ClasspathScanner.java
Log:
Make this work on Hudson
Modified: core/trunk/src/main/java/org/jboss/cache/factories/annotations/ClasspathScanner.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/factories/annotations/ClasspathScanner.java 2007-12-18 14:…
[View More]49:44 UTC (rev 4870)
+++ core/trunk/src/main/java/org/jboss/cache/factories/annotations/ClasspathScanner.java 2007-12-18 15:03:42 UTC (rev 4871)
@@ -6,6 +6,7 @@
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
+import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
@@ -44,17 +45,18 @@
*/
public <T> Set<Class<? extends T>> scan(Class<? extends Annotation> annotationType, Class<T> classType)
{
- // only scan the current ClassPath location that contains this file. Could be a directory or a JAR file.
- URL url = getURLPathFromClassLoader();
- String urlPath = url.getFile();
- if (urlPath.endsWith("/"))
- {
- urlPath = urlPath.substring(0, urlPath.length() - 1);
- }
+ Set<Class<? extends T>> classes = Collections.emptySet();
- Set<Class<? extends T>> classes = Collections.emptySet();
try
{
+ // only scan the current ClassPath location that contains this file. Could be a directory or a JAR file.
+ URL url = getURLPathFromClassLoader();
+ String urlPath = url.getFile();
+ if (urlPath.endsWith("/"))
+ {
+ urlPath = urlPath.substring(0, urlPath.length() - 1);
+ }
+
if (log.isDebugEnabled()) log.debug("scanning: " + urlPath);
File file = new File(urlPath);
if (file.isDirectory())
@@ -78,7 +80,7 @@
return classes;
}
- private URL getURLPathFromClassLoader()
+ private URL getURLPathFromClassLoader() throws MalformedURLException
{
URL u2 = classLoader.findResource("org/jboss/cache/Version.class");
@@ -87,7 +89,7 @@
String urlString = u.toString().replaceAll("\\/\\.\\/", "/");
if (u2.toString().startsWith(urlString))
{
- return u;
+ return new URL(urlString);
}
}
[View Less]
17 years, 3 months
JBoss Cache SVN: r4870 - core/trunk/src/main/java/org/jboss/cache/factories/annotations.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-12-18 09:49:44 -0500 (Tue, 18 Dec 2007)
New Revision: 4870
Modified:
core/trunk/src/main/java/org/jboss/cache/factories/annotations/ClasspathScanner.java
Log:
Make this work on Hudson
Modified: core/trunk/src/main/java/org/jboss/cache/factories/annotations/ClasspathScanner.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/factories/annotations/ClasspathScanner.java 2007-12-18 10:…
[View More]33:07 UTC (rev 4869)
+++ core/trunk/src/main/java/org/jboss/cache/factories/annotations/ClasspathScanner.java 2007-12-18 14:49:44 UTC (rev 4870)
@@ -84,7 +84,8 @@
for (URL u : classLoader.getURLs())
{
- if (u2.toString().startsWith(u.toString()))
+ String urlString = u.toString().replaceAll("\\/\\.\\/", "/");
+ if (u2.toString().startsWith(urlString))
{
return u;
}
[View Less]
17 years, 3 months
JBoss Cache SVN: r4869 - cache-bench-fwk/trunk/cache-products/terracotta-2.4.8/src/org/cachebench/cachewrappers.
by jbosscache-commits@lists.jboss.org
Author: bela(a)jboss.com
Date: 2007-12-18 05:33:07 -0500 (Tue, 18 Dec 2007)
New Revision: 4869
Modified:
cache-bench-fwk/trunk/cache-products/terracotta-2.4.8/src/org/cachebench/cachewrappers/TerracottaWrapper.java
Log:
made map final
Modified: cache-bench-fwk/trunk/cache-products/terracotta-2.4.8/src/org/cachebench/cachewrappers/TerracottaWrapper.java
===================================================================
--- cache-bench-fwk/trunk/cache-products/terracotta-2.4.8/src/org/…
[View More]cachebench/cachewrappers/TerracottaWrapper.java 2007-12-18 03:55:14 UTC (rev 4868)
+++ cache-bench-fwk/trunk/cache-products/terracotta-2.4.8/src/org/cachebench/cachewrappers/TerracottaWrapper.java 2007-12-18 10:33:07 UTC (rev 4869)
@@ -16,7 +16,7 @@
public class TerracottaWrapper implements CacheWrapper
{
// Since terracotta
- private Map cache = new HashMap();
+ private final Map cache = new HashMap();
public void init(Properties parameters) throws Exception
{
[View Less]
17 years, 3 months
JBoss Cache SVN: r4868 - in pojo/trunk/src: test/java/org/jboss/cache/pojo/notification and 1 other directory.
by jbosscache-commits@lists.jboss.org
Author: jason.greene(a)jboss.com
Date: 2007-12-17 22:55:14 -0500 (Mon, 17 Dec 2007)
New Revision: 4868
Added:
pojo/trunk/src/test/java/org/jboss/cache/pojo/notification/ListenerCountTest.java
Modified:
pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/NotificationDispatcher.java
pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java
Log:
Fix PCACHE-56
Modified: pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/NotificationDispatcher.java
=============================…
[View More]======================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/NotificationDispatcher.java 2007-12-16 17:38:31 UTC (rev 4867)
+++ pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/NotificationDispatcher.java 2007-12-18 03:55:14 UTC (rev 4868)
@@ -122,7 +122,8 @@
if (! (o instanceof Entry))
return false;
- return ((Entry)o).equals(listener);
+ // Must be the same instance
+ return ((Entry)o).listener == this.listener;
}
private static Map<Class<?>, List<Method>> buildNotifiers(Class clazz)
Modified: pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java 2007-12-16 17:38:31 UTC (rev 4867)
+++ pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java 2007-12-18 03:55:14 UTC (rev 4868)
@@ -296,7 +296,10 @@
{
try
{
+ boolean wasEmpty = listenerAdaptor.isEmpty();
listenerAdaptor.addListener(listener, pattern);
+ if (wasEmpty)
+ cache.addCacheListener(listenerAdaptor);
}
catch (IllegalArgumentException e)
{
@@ -304,7 +307,6 @@
e.fillInStackTrace();
throw e;
}
- cache.addCacheListener(listenerAdaptor);
}
}
Added: pojo/trunk/src/test/java/org/jboss/cache/pojo/notification/ListenerCountTest.java
===================================================================
--- pojo/trunk/src/test/java/org/jboss/cache/pojo/notification/ListenerCountTest.java (rev 0)
+++ pojo/trunk/src/test/java/org/jboss/cache/pojo/notification/ListenerCountTest.java 2007-12-18 03:55:14 UTC (rev 4868)
@@ -0,0 +1,74 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.notification;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import org.jboss.cache.pojo.PojoCache;
+import org.jboss.cache.pojo.PojoCacheFactory;
+import org.jboss.cache.pojo.impl.CacheListenerAdaptor;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+// $Id: ObjectTest.java 4698 2007-10-26 18:30:20Z jason.greene(a)jboss.com $
+
+/**
+ * Tests that CacheListenerAdaptor is attached properly.
+ *
+ * @author Jason T. Greene
+ */
+@Test(groups = {"functional"})
+public class ListenerCountTest
+{
+ protected PojoCache cache;
+
+ @BeforeMethod(alwaysRun = true)
+ protected void setUp() throws Exception
+ {
+ String configFile = "META-INF/local-service.xml";
+ boolean toStart = false;
+ cache = PojoCacheFactory.createCache(configFile, toStart);
+ cache.start();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ protected void tearDown() throws Exception
+ {
+ cache.stop();
+ }
+
+ public void testAddRemoveListener() throws Exception
+ {
+ assertEquals(0, getAdaptorCount());
+
+ Object listener1 = new Listener();
+ cache.addListener(listener1);
+ assertEquals(1, getAdaptorCount());
+
+ Object listener2 = new Listener();
+ cache.addListener(listener2);
+ assertEquals(1, getAdaptorCount());
+
+ cache.removeListener(listener1);
+ assertEquals(1, getAdaptorCount());
+
+ cache.removeListener(listener2);
+ assertEquals(0, getAdaptorCount());
+ }
+
+ private int getAdaptorCount()
+ {
+ int count = 0;
+ for (Object listener : cache.getCache().getCacheListeners())
+ if (listener instanceof CacheListenerAdaptor)
+ count++;
+
+ return count;
+ }
+}
\ No newline at end of file
[View Less]
17 years, 3 months