Author: rhauch
Date: 2008-07-09 17:20:54 -0400 (Wed, 09 Jul 2008)
New Revision: 350
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/component/ComponentLibrary.java
trunk/dna-common/src/test/java/org/jboss/dna/common/component/ComponentLibraryTest.java
Log:
DNA-176 - Changing class loader factory on ComponentLibrary should update the instances
http://jira.jboss.com/jira/browse/DNA-176
Added method to explicitly refresh the instances, and should automatically do this when
setting the class loader factory.
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/component/ComponentLibrary.java
===================================================================
---
trunk/dna-common/src/main/java/org/jboss/dna/common/component/ComponentLibrary.java 2008-07-09
20:37:01 UTC (rev 349)
+++
trunk/dna-common/src/main/java/org/jboss/dna/common/component/ComponentLibrary.java 2008-07-09
21:20:54 UTC (rev 350)
@@ -37,11 +37,11 @@
/**
* Maintains the list of component instances for the system. This class does not actively
update the component configurations, but
* is designed to properly maintain the sequencer instances when those configurations are
changed by other callers. If the
- * components are subclasses of {@link Component}, then they will be
- * {@link Component#setConfiguration(ComponentConfig) configured} with the appropriate
configuration.
+ * components are subclasses of {@link Component}, then they will be {@link
Component#setConfiguration(ComponentConfig)
+ * configured} with the appropriate configuration.
* <p>
- * Therefore, this library does guarantee that the {@link #getInstances() instances} at
the time they are
- * {@link #getInstances() obtained} are always reflected by the configurations.
+ * Therefore, this library does guarantee that the {@link #getInstances() instances} at
the time they are {@link #getInstances()
+ * obtained} are always reflected by the configurations.
* </p>
*
* @author Randall Hauch
@@ -52,9 +52,8 @@
public class ComponentLibrary<ComponentType, ConfigType extends ComponentConfig> {
/**
- * Class loader factory instance that always returns the
- * {@link Thread#getContextClassLoader() current thread's context class loader}
(if not null) or component library's class
- * loader.
+ * Class loader factory instance that always returns the {@link
Thread#getContextClassLoader() current thread's context class
+ * loader} (if not null) or component library's class loader.
*/
public static final ClassLoaderFactory DEFAULT = new
StandardClassLoaderFactory(ComponentLibrary.class.getClassLoader());
@@ -81,9 +80,8 @@
/**
* Get the class loader factory that should be used to load the component classes.
Unless changed, the library uses the
- * {@link #DEFAULT default} class loader factory, which uses the
- * {@link Thread#getContextClassLoader() current thread's context class loader}
if not null or the class loader that loaded
- * the library class.
+ * {@link #DEFAULT default} class loader factory, which uses the {@link
Thread#getContextClassLoader() current thread's
+ * context class loader} if not null or the class loader that loaded the library
class.
*
* @return the class loader factory; never null
* @see #setClassLoaderFactory(ClassLoaderFactory)
@@ -94,9 +92,8 @@
/**
* Set the Maven Repository that should be used to load the sequencer classes. Unless
changed, the library uses the
- * {@link #DEFAULT default} class loader factory, which uses the
- * {@link Thread#getContextClassLoader() current thread's context class loader}
if not null or the class loader that loaded
- * the library class.
+ * {@link #DEFAULT default} class loader factory, which uses the {@link
Thread#getContextClassLoader() current thread's
+ * context class loader} if not null or the class loader that loaded the library
class.
*
* @param classLoaderFactory the class loader factory reference, or null if the
{@link #DEFAULT default class loader factory}
* should be used
@@ -104,11 +101,12 @@
*/
public void setClassLoaderFactory( ClassLoaderFactory classLoaderFactory ) {
this.classLoaderFactory.set(classLoaderFactory != null ? classLoaderFactory :
DEFAULT);
+ refreshInstances();
}
/**
- * Add the configuration for a sequencer, or update any existing one that represents
the
- * {@link ConfigType#equals(Object) same configuration}
+ * Add the configuration for a sequencer, or update any existing one that represents
the {@link ConfigType#equals(Object) same
+ * configuration}
*
* @param config the new configuration
* @return true if the component was added, or false if there already was an existing
and
@@ -143,7 +141,8 @@
}
/**
- * Update the configuration for a sequencer, or add it if there is no {@link
ConfigType#equals(Object) matching configuration}.
+ * Update the configuration for a sequencer, or add it if there is no {@link
ConfigType#equals(Object) matching configuration}
+ * .
*
* @param config the updated (or new) configuration
* @return true if the component was updated, or false if there already was an
existing and
@@ -184,6 +183,29 @@
}
/**
+ * Refresh the instances by attempting to re-instantiate each registered
configuration.
+ *
+ * @return true if at least one instance was instantiated, or false if none were
+ */
+ public boolean refreshInstances() {
+ try {
+ this.lock.lock();
+ // Loop through and create new instances for each configuration ...
+ boolean found = false;
+ int index = 0;
+ for (ConfigType config : this.configs) {
+ ComponentType instance = newInstance(config);
+ found = found || instance != null;
+ this.instances.set(index, instance);
+ ++index;
+ }
+ return found;
+ } finally {
+ this.lock.unlock();
+ }
+ }
+
+ /**
* Return the list of sequencers.
*
* @return the unmodifiable list of sequencers; never null
Modified:
trunk/dna-common/src/test/java/org/jboss/dna/common/component/ComponentLibraryTest.java
===================================================================
---
trunk/dna-common/src/test/java/org/jboss/dna/common/component/ComponentLibraryTest.java 2008-07-09
20:37:01 UTC (rev 349)
+++
trunk/dna-common/src/test/java/org/jboss/dna/common/component/ComponentLibraryTest.java 2008-07-09
21:20:54 UTC (rev 350)
@@ -168,4 +168,66 @@
}
assertThat(firstComponentB.getCounter(), is(10));
}
+
+ @Test
+ public void shouldRefreshInstancesWhenCalledDirectly() {
+ library.add(configA);
+ library.add(configB);
+ List<SampleComponent> components = library.getInstances();
+ assertThat(components.size(), is(2));
+ assertThat(components.get(0), instanceOf(MockComponentA.class));
+ assertThat(components.get(1), instanceOf(MockComponentB.class));
+ MockComponentA firstInstanceA = (MockComponentA)components.get(0);
+ MockComponentB firstInstanceB = (MockComponentB)components.get(1);
+ assertThat(components.get(0),
is(sameInstance((SampleComponent)firstInstanceA)));
+ assertThat(components.get(1),
is(sameInstance((SampleComponent)firstInstanceB)));
+
+ // Refresh the instances ...
+ assertThat(library.refreshInstances(), is(true));
+
+ // Check that there are instances for each of the components ...
+ components = library.getInstances();
+ assertThat(components.size(), is(2));
+ assertThat(components.get(0), instanceOf(MockComponentA.class));
+ assertThat(components.get(1), instanceOf(MockComponentB.class));
+ MockComponentA secondInstanceA = (MockComponentA)components.get(0);
+ MockComponentB secondInstanceB = (MockComponentB)components.get(1);
+ assertThat(components.get(0),
is(sameInstance((SampleComponent)secondInstanceA)));
+ assertThat(components.get(1),
is(sameInstance((SampleComponent)secondInstanceB)));
+
+ // And check that the instances have changed ...
+ assertThat(firstInstanceA,
is(not(sameInstance((SampleComponent)secondInstanceA))));
+ assertThat(firstInstanceB,
is(not(sameInstance((SampleComponent)secondInstanceB))));
+ }
+
+ @Test
+ public void shouldRefreshInstancesWhenSettingClassLoaderFactory() {
+ library.add(configA);
+ library.add(configB);
+ List<SampleComponent> components = library.getInstances();
+ assertThat(components.size(), is(2));
+ assertThat(components.get(0), instanceOf(MockComponentA.class));
+ assertThat(components.get(1), instanceOf(MockComponentB.class));
+ MockComponentA firstInstanceA = (MockComponentA)components.get(0);
+ MockComponentB firstInstanceB = (MockComponentB)components.get(1);
+ assertThat(components.get(0),
is(sameInstance((SampleComponent)firstInstanceA)));
+ assertThat(components.get(1),
is(sameInstance((SampleComponent)firstInstanceB)));
+
+ // Set the class loader factory to the SAME instance, and this should always
refresh the instances ...
+ library.setClassLoaderFactory(library.getClassLoaderFactory());
+
+ // Check that there are instances for each of the components ...
+ components = library.getInstances();
+ assertThat(components.size(), is(2));
+ assertThat(components.get(0), instanceOf(MockComponentA.class));
+ assertThat(components.get(1), instanceOf(MockComponentB.class));
+ MockComponentA secondInstanceA = (MockComponentA)components.get(0);
+ MockComponentB secondInstanceB = (MockComponentB)components.get(1);
+ assertThat(components.get(0),
is(sameInstance((SampleComponent)secondInstanceA)));
+ assertThat(components.get(1),
is(sameInstance((SampleComponent)secondInstanceB)));
+
+ // And check that the instances have changed ...
+ assertThat(firstInstanceA,
is(not(sameInstance((SampleComponent)secondInstanceA))));
+ assertThat(firstInstanceB,
is(not(sameInstance((SampleComponent)secondInstanceB))));
+ }
}