package org.codehaus.plexus.component.composition;
import org.codehaus.plexus.PlexusTestCase;
import static org.codehaus.plexus.PlexusConstants.PLEXUS_DEFAULT_HINT;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import java.io.File;
import java.net.URL;
import java.util.Map;
import java.util.List;
import java.util.TreeMap;
/** @author Jason van Zyl */
public class ComponentRealmCompositionTest
extends PlexusTestCase
{
//
// Component archives
//
private static final String PLUGIN_0_JAR = "src/test/test-components/plugin0-1.0-SNAPSHOT.jar";
private static final String PLUGIN_1_JAR = "src/test/test-components/plugin1-1.0-SNAPSHOT.jar";
private static final String COMPONENT_A_JAR = "src/test/test-components/component-a-1.0-SNAPSHOT.jar";
private static final String COMPONENT_B_JAR = "src/test/test-components/component-b-1.0-SNAPSHOT.jar";
private static final String COMPONENT_C_JAR = "src/test/test-components/component-c-1.0-SNAPSHOT.jar";
private static final String ARCHIVER_JAR = "src/test/test-components/plexus-archiver-1.0-alpha-8.jar";
//
// Component roles
//
private static final String PLUGIN_0_ROLE = "org.codehaus.plexus.plugins.Plugin0";
private static final String PLUGIN_1_ROLE = "org.codehaus.plexus.plugins.Plugin1";
//
// Component realms
//
private static final String PLUGIN_0_REALM = "plugin0Realm";
private static final String PLUGIN_1_REALM = "plugin1Realm";
private ClassRealm classRealm0;
private ClassRealm classRealm1;
protected void setUp() throws Exception
{
super.setUp();
// Create ClassRealm plugin0 with plugin0 -> A, plugin0 -> B
classRealm0 = createClassRealm( PLUGIN_0_REALM,
PLUGIN_0_JAR,
COMPONENT_A_JAR,
COMPONENT_B_JAR,
ARCHIVER_JAR );
// Create ClassRealm plugin1 with plugin1 -> A, plugin1 -> C
classRealm1 = createClassRealm( PLUGIN_1_REALM,
PLUGIN_1_JAR,
COMPONENT_A_JAR,
COMPONENT_C_JAR,
ARCHIVER_JAR );
}
/*
* We are testing that when the same component implementation exists in more then one
* realm and components depend on those implementations, that the right realm is used
* to wire up the components.
*
* An example of this in practice are Maven plugins where each plugin is loaded into
* a separate realm and the plugin may have dependencies on other components. We want
* to make sure that a requirement, say a JarArchiver, for a given component, say the
* maven-jar-plugin, is wired up with a JarArchiver taken from the same realm as the
* maven-jar-plugin and not a different realm.
*/
public void testCompositionWhereTheSameImplementationExistsInDifferentRealms()
throws Exception
{
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
try
{
// Plugin0
Thread.currentThread().setContextClassLoader( classRealm0 );
getContainer().lookup( PLUGIN_0_ROLE );
// Plugin1
Thread.currentThread().setContextClassLoader( classRealm1 );
getContainer().lookup( PLUGIN_1_ROLE );
// Plugin0(alt)
Thread.currentThread().setContextClassLoader( classRealm0 );
getContainer().lookup( PLUGIN_0_ROLE, "alt" );
// Plugin1(alt)
Thread.currentThread().setContextClassLoader( classRealm1 );
getContainer().lookup( PLUGIN_1_ROLE, "alt" );
}
finally
{
Thread.currentThread().setContextClassLoader( oldClassLoader );
}
}
public void testThatASingletonComponentIntheCoreRealmWhenLookedUpInComponentRealmsYieldsTheSameInstance()
throws Exception
{
}
public void testMultiRealmLookupMap()
throws Exception
{
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
try
{
Thread.currentThread().setContextClassLoader( classRealm0 );
Map<String,Object> plugin0Map = getContainer().lookupMap( PLUGIN_0_ROLE );
assertNotNull("plugin0Map is null", plugin0Map );
assertNotNull("plugin0Map does not contain a DefaultPlugin0", plugin0Map.get( PLEXUS_DEFAULT_HINT));
assertNotNull("plugin0Map does not contain a AltPlugin0", plugin0Map.get( "alt"));
assertEquals("Expected only 2 components in plugin0Map", 2, plugin0Map.size());
Thread.currentThread().setContextClassLoader( classRealm1 );
Map<String,Object> plugin1Map = getContainer().lookupMap( PLUGIN_1_ROLE );
assertNotNull("plugin1Map is null", plugin1Map);
assertNotNull("plugin1Map does not contain a DefaultPlugin1", plugin1Map.get( PLEXUS_DEFAULT_HINT));
assertNotNull("plugin1Map does not contain a AltPlugin1", plugin1Map.get( "alt"));
assertEquals("Expected only 2 components in plugin1Map", 2, plugin1Map.size());
Thread.currentThread().setContextClassLoader( null );
}
finally
{
Thread.currentThread().setContextClassLoader( oldClassLoader );
}
}
public void testMultiRealmLookupList()
throws Exception
{
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
try
{
Thread.currentThread().setContextClassLoader( classRealm0 );
List<Object> plugin0List = getContainer().lookupList( PLUGIN_0_ROLE );
assertNotNull("plugin0List is null", plugin0List );
Map<String, Object> plugin0Map = mapByClassSimpleName( plugin0List );
assertNotNull("plugin0List does not contain a DefaultPlugin0", plugin0Map.get( "DefaultPlugin0"));
assertNotNull("plugin0List does not contain a AltPlugin0", plugin0Map.get( "AltPlugin0"));
assertEquals("Expected only 2 components in plugin0Map", 2, plugin0Map.size());
Thread.currentThread().setContextClassLoader( classRealm1 );
List<Object> plugin1List = getContainer().lookupList( PLUGIN_1_ROLE );
assertNotNull("plugin1List is null", plugin1List );
Map<String, Object> plugin1Map = mapByClassSimpleName( plugin1List );
assertNotNull("plugin1List does not contain a DefaultPlugin1", plugin1Map.get( "DefaultPlugin1"));
assertNotNull("plugin1List does not contain a AltPlugin1", plugin1Map.get( "AltPlugin1"));
assertEquals("Expected only 2 components in plugin0Map", 2, plugin1Map.size());
}
finally
{
Thread.currentThread().setContextClassLoader( oldClassLoader );
}
}
private ClassRealm createClassRealm(String id, String... jars)
throws Exception
{
// create the realm
ClassRealm classRealm = getContainer().createChildRealm( id );
// populate the realm
for ( String jar : jars )
{
File file = new File(jar);
assertTrue( jar + " is not a file", file.isFile() );
URL url = file.toURI().toURL();
classRealm.addURL( url );
}
// descover all component definitions in the realm and register them with the repository
getContainer().discoverComponents( classRealm );
return classRealm;
}
private Map<String, Object> mapByClassSimpleName(List<Object> objects)
{
Map<String, Object> map = new TreeMap<String, Object>();
for ( Object object : objects )
{
map.put(object.getClass().getSimpleName(), object);
}
return map;
}
}