mcconnell 2003/07/03 16:34:50
Modified: merlin/assembly maven.xml
merlin/assembly/src/java/org/apache/avalon/assembly/model
ClassLoaderModel.java CompositionModel.java
ContainmentModel.java
merlin/assembly/src/test/conf block.xml
merlin/assembly/src/test/org/apache/avalon/assembly/model
ClasspathTestCase.java CompositionTestCase.java
merlin/merlin-platform/xdocs/resources index.xml
Log:
Updates to the containment and classloader model to optimise classpath generation.
Revision Changes Path
1.2 +4 -0 avalon-sandbox/merlin/assembly/maven.xml
Index: maven.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/assembly/maven.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- maven.xml 3 Jul 2003 04:31:16 -0000 1.1
+++ maven.xml 3 Jul 2003 23:34:50 -0000 1.2
@@ -26,6 +26,10 @@
manifest="${basedir}/src/test/etc/d.mf"
includes="**/testd/*.class" basedir="${basedir}/target/test-classes">
</ant:jar>
+ <ant:jar
jarfile="${basedir}/target/test-classes/repository/test/jars/test-e.jar"
+ manifest="${basedir}/src/test/etc/e.mf"
+ includes="**/teste/*.class" basedir="${basedir}/target/test-classes">
+ </ant:jar>
</postGoal>
</project>
1.2 +183 -62
avalon-sandbox/merlin/assembly/src/java/org/apache/avalon/assembly/model/ClassLoaderModel.java
Index: ClassLoaderModel.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/assembly/src/java/org/apache/avalon/assembly/model/ClassLoaderModel.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ClassLoaderModel.java 3 Jul 2003 04:28:53 -0000 1.1
+++ ClassLoaderModel.java 3 Jul 2003 23:34:50 -0000 1.2
@@ -75,11 +75,31 @@
/**
- * Implementation of a classloader model within which a
+ * <p>Implementation of a classloader model within which a
* repository, a base directory and a classloader directive
- * are associated togther enabling the creation of a fully
- * populated classpath.
+ * are associated together enabling the creation of a fully
+ * qualified classpath.</p>
*
+ * <p>The classpath established by this model implementation
+ * applies the following logic:</p>
+ * <ul>
+ * <li>establish an extensions manager relative to the
+ * <library/>> directives</li>
+ * <li>build an uqualifed classpath relative to the
+ * <classpath/>> directives</li>
+ * <li>resolve any optional jar file extension jar file
+ * entries based on the manifest declarations of
+ * the unqualified classpath, together with recursive
+ * resolution of resolved optional extensions</li>
+ * <li>consolidate the generated classpath relative to
+ * the optional extensions established by any parent
+ * classloader models</li>
+ * </li>
+ * <p>
+ * Class dependecies include the Excalibur i18n, the assembly
+ * repository package, the avalon framework and meta packages,
+ * and the extensions package.
+ * </p>
* @author <a href="mailto:[EMAIL PROTECTED]">Avalon Development Team</a>
* @version $Revision$ $Date$
*/
@@ -103,6 +123,8 @@
private ClassLoaderDirective m_directive;
+ private ClassLoaderModel m_parent;
+
private String[] m_classpath;
private ExtensionManager m_extension;
@@ -111,11 +133,48 @@
private Logger m_logger;
+ private OptionalPackage[] m_packages;
+
+ private URL[] m_urls;
+
//==============================================================
// constructor
//==============================================================
/**
+ * Creation of a root classloader model. The model associated a
+ * repository, a base directory and a classloader directive
+ * enabling the creation of a fully populated classpath.
+ *
+ * @param base the base directory from which relative references
+ * shall be resolved
+ * @param repository a local cache of jar files addressable
+ * relative to group/name/version identifiers
+ * @param directive the classloader directive containing the
+ * primative classpath entries and resource directives
+ */
+ public ClassLoaderModel(
+ Logger logger, File base, Repository repository, ClassLoaderDirective
directive )
+ throws Exception
+ {
+ m_logger = logger;
+ m_extension = new DefaultExtensionManager(
+ directive.getLibrary().getOptionalExtensionDirectories( base ) );
+ m_manager = new PackageManager( m_extension );
+ m_repository = repository;
+ m_directive = directive;
+ m_base = base;
+
+ //
+ // generate the primitive classpath
+ //
+
+ m_classpath = createClassPath();
+ m_packages = buildOptionalPackages( m_classpath );
+ m_urls = buildQualifiedClassPath();
+ }
+
+ /**
* Creation of a new classloader model. The model associated a
* repository, a base directory and a classloader directive
* enabling the creation of a fully populated classpath.
@@ -143,6 +202,7 @@
m_logger = logger;
m_base = parent.getBaseDirectory();
+ m_parent = parent;
DefaultExtensionManager local =
new DefaultExtensionManager(
@@ -157,45 +217,76 @@
// generate the primitive classpath
//
- getClassPath();
+ m_classpath = createClassPath();
+ m_packages = buildOptionalPackages(
+ m_classpath, parent.getOptionalPackages( true ) );
+ m_urls = buildQualifiedClassPath();
}
+ //==============================================================
+ // public implementation
+ //==============================================================
+
/**
- * Creation of a root classloader model. The model associated a
- * repository, a base directory and a classloader directive
- * enabling the creation of a fully populated classpath.
+ * Return the fully qualified classpath including extension jar files
+ * resolved relative to the classpath directives in the meta-data
+ * and any parent classloader models.
*
- * @param base the base directory from which relative references
- * shall be resolved
- * @param repository a local cache of jar files addressable
- * relative to group/name/version identifiers
- * @param directive the classloader directive containing the
- * primative classpath entries and resource directives
+ * @return an array of URL representing the complete classpath
*/
- public ClassLoaderModel(
- Logger logger, File base, Repository repository, ClassLoaderDirective
directive )
+ public URL[] getQualifiedClassPath()
throws Exception
{
- m_logger = logger;
- m_extension = new DefaultExtensionManager(
- directive.getLibrary().getOptionalExtensionDirectories( base ) );
- m_manager = new PackageManager( m_extension );
- m_repository = repository;
- m_directive = directive;
- m_base = base;
-
- //
- // generate the primitive classpath
- //
-
- getClassPath();
+ return m_urls;
}
//==============================================================
- // implementation
+ // protected implementation
//==============================================================
/**
+ * Return the set of local established optional packages.
+ *
+ * @return the local set of optional packages
+ */
+ protected OptionalPackage[] getOptionalPackages()
+ {
+ return getOptionalPackages( false );
+ }
+
+ /**
+ * Return the set of optional packages already established including
+ * the optional packages established by any parent classloader model.
+ *
+ * @param policy if TRUE, return the local and all ancestor optional
+ * package - if FALSE only return the local packages
+ * @return the OptionalPackage instances
+ */
+ protected OptionalPackage[] getOptionalPackages( boolean policy )
+ {
+ if( !policy )
+ {
+ return m_packages;
+ }
+
+ final ArrayList list = new ArrayList();
+ if( m_parent != null )
+ {
+ OptionalPackage[] available = m_parent.getOptionalPackages( true );
+ for( int i=0; i<available.length; i++ )
+ {
+ list.add( available[i] );
+ }
+ }
+ for( int i=0; i<m_packages.length; i++ )
+ {
+ list.add( m_packages[i] );
+ }
+
+ return (OptionalPackage[]) list.toArray( new OptionalPackage[0] );
+ }
+
+ /**
* Return the base directory from which any relative file references
* shall be resolved.
* @return the base directory
@@ -223,29 +314,26 @@
return m_repository;
}
+ //==============================================================
+ // private implementation
+ //==============================================================
+
/**
- * Get the fully qulalified classpath including extension jar files
+ * Build the fully qulalified classpath including extension jar files
* resolved relative to the classpath directives in the meta-data.
*
* @return an array of URL representing the complete classpath
*/
- public URL[] getClasspath()
+ private URL[] buildQualifiedClassPath()
throws Exception
{
- ArrayList list = new ArrayList();
-
- //
- // resolve the classpath which will include resolution of
- // resources relative to the local repository
- //
-
- String[] uris = getClassPath();
- for( int i=0; i<uris.length; i++ )
+ final ArrayList list = new ArrayList();
+ final String[] classpath = getClassPath();
+ for( int i=0; i<classpath.length; i++ )
{
- list.add( new URL( uris[i] ) );
+ list.add( new URL( classpath[i] ) );
}
-
- File[] extensions = getOptionalExtensions();
+ File[] extensions = OptionalPackage.toFiles( getOptionalPackages() );
for( int i=0; i<extensions.length; i++ )
{
list.add( extensions[i].toURL() );
@@ -254,13 +342,13 @@
}
private String[] getClassPath()
- throws Exception
{
- if( m_classpath != null )
- {
- return m_classpath;
- }
+ return m_classpath;
+ }
+ private String[] createClassPath()
+ throws Exception
+ {
ArrayList classpath = new ArrayList();
addToClassPath(
classpath, m_directive.getClasspathDirective().expandFileSetDirectives(
m_base ) );
@@ -280,33 +368,45 @@
}
}
- m_classpath = (String[]) classpath.toArray( new String[0] );
- return m_classpath;
+ return (String[]) classpath.toArray( new String[0] );
}
-
- private File[] getOptionalExtensions( )
- throws Exception
+ /**
+ * Retrieve the files for the optional packages required by
+ * the jars in ClassPath.
+ *
+ * @param classPath the Classpath array
+ * @return the files that need to be added to ClassLoader
+ * @exception Exception if a extension error occurs
+ */
+ private OptionalPackage[] buildOptionalPackages( final String[] classPath )
+ throws Exception
{
- return getOptionalPackagesFor( getClassPath() );
+ return buildOptionalPackages( classPath, new OptionalPackage[0] );
}
/**
* Retrieve the files for the optional packages required by
- * the jars in ClassPath.
+ * the jars in the ClassPath.
*
* @param classPath the Classpath array
* @return the files that need to be added to ClassLoader
* @exception Exception if a extension error occurs
*/
- private File[] getOptionalPackagesFor( final String[] classPath )
- throws Exception
+ private OptionalPackage[] buildOptionalPackages(
+ final String[] classPath, final OptionalPackage[] established )
+ throws Exception
{
+ final ArrayList unsatisfied = new ArrayList();
+ final ArrayList dependencies = new ArrayList();
+ for( int i=0; i<established.length; i++ )
+ {
+ dependencies.add( established[i] );
+ }
+
final Manifest[] manifests = getManifests( classPath );
final Extension[] available = Extension.getAvailable( manifests );
final Extension[] required = Extension.getRequired( manifests );
- final ArrayList dependencies = new ArrayList();
- final ArrayList unsatisfied = new ArrayList();
m_manager.scanDependencies( required, available, dependencies, unsatisfied
);
if( 0 != unsatisfied.size() )
@@ -331,13 +431,34 @@
final String entry = REZ.format( "missing.extension", params );
buffer.append( "\n" + entry );
}
-
throw new Exception( buffer.toString() );
}
final OptionalPackage[] packages =
(OptionalPackage[]) dependencies.toArray( new OptionalPackage[0] );
- return OptionalPackage.toFiles( packages );
+ return consolidate( packages, established );
+ }
+
+ private OptionalPackage[] consolidate( OptionalPackage[] includes,
OptionalPackage[] excludes )
+ {
+ ArrayList list = new ArrayList();
+ for( int i=0; i<includes.length; i++ )
+ {
+ boolean skip = false;
+ OptionalPackage inc = includes[i];
+ File file = inc.getFile();
+ for( int j=0; j<excludes.length; j++ )
+ {
+ if( file.equals( excludes[j].getFile() ) );
+ skip = true;
+ break;
+ }
+ if( !skip )
+ {
+ list.add( inc );
+ }
+ }
+ return (OptionalPackage[]) list.toArray( new OptionalPackage[0] );
}
private void addToClassPath( List list, File[] files )
1.2 +21 -1
avalon-sandbox/merlin/assembly/src/java/org/apache/avalon/assembly/model/CompositionModel.java
Index: CompositionModel.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/assembly/src/java/org/apache/avalon/assembly/model/CompositionModel.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- CompositionModel.java 3 Jul 2003 04:28:53 -0000 1.1
+++ CompositionModel.java 3 Jul 2003 23:34:50 -0000 1.2
@@ -54,7 +54,9 @@
import org.apache.avalon.assembly.repository.Repository;
import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.meta.data.ServiceDirective;
import org.apache.avalon.meta.data.CompositionProfile;
+import org.apache.avalon.meta.info.DependencyDescriptor;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
@@ -223,6 +225,24 @@
protected Repository getRepository()
{
return m_repository;
+ }
+
+ /**
+ * Return the set of service export mappings
+ * @return the block implementation model
+ */
+ protected ServiceDirective[] getServiceDirectives()
+ {
+ return m_profile.getServiceDirectives();
+ }
+
+ /**
+ * Return the set of dependencies
+ * @return the block implementation model
+ */
+ protected DependencyDescriptor[] getDependencies()
+ {
+ return m_profile.getDependencies();
}
/**
1.2 +19 -5
avalon-sandbox/merlin/assembly/src/java/org/apache/avalon/assembly/model/ContainmentModel.java
Index: ContainmentModel.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/assembly/src/java/org/apache/avalon/assembly/model/ContainmentModel.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ContainmentModel.java 3 Jul 2003 04:28:53 -0000 1.1
+++ ContainmentModel.java 3 Jul 2003 23:34:50 -0000 1.2
@@ -54,6 +54,8 @@
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Hashtable;
+import java.util.List;
+import java.util.ArrayList;
import org.apache.avalon.assembly.engine.type.TypeRepository;
import org.apache.avalon.assembly.repository.Repository;
@@ -95,11 +97,12 @@
private final ClassLoaderModel m_classLoaderModel;
- private final ClassLoader m_classLoader;
+ private final URLClassLoader m_classLoader;
private final DefaultTypeRepository m_types;
private Hashtable m_children = new Hashtable();
+ private List m_models = new ArrayList();
//==============================================================
// constructor
@@ -136,7 +139,7 @@
profile.getClassLoaderDirective() );
ClassLoader classloader =
Thread.currentThread().getContextClassLoader();
- URL[] classpath = m_classLoaderModel.getClasspath();
+ URL[] classpath = m_classLoaderModel.getQualifiedClassPath();
m_classLoader =
new URLClassLoader( classpath, classloader);
}
@@ -192,7 +195,7 @@
logger.getChildLogger("classloader"),
ancestor,
profile.getClassLoaderDirective() );
- URL[] classpath = m_classLoaderModel.getClasspath();
+ URL[] classpath = m_classLoaderModel.getQualifiedClassPath();
m_classLoader =
new URLClassLoader(
classpath, parent.getClassLoader() );
@@ -248,6 +251,7 @@
this,
containment );
m_children.put( profile.getName(), model );
+ m_models.add( model );
}
catch( Throwable e )
{
@@ -272,6 +276,7 @@
deployment,
getPath() );
m_children.put( profile.getName(), model );
+ m_models.add( model );
}
catch( Throwable e )
{
@@ -324,7 +329,7 @@
* Return the classloader for this containment context.
* @return the classloader
*/
- public ClassLoader getClassLoader()
+ public URLClassLoader getClassLoader()
{
return m_classLoader;
}
@@ -336,6 +341,15 @@
protected ClassLoaderModel getClassLoaderModel()
{
return m_classLoaderModel;
+ }
+
+ /**
+ * Return the set of models nested within this model.
+ * @return the classloader model
+ */
+ protected Model[] getNestedModels()
+ {
+ return (Model[]) m_models.toArray( new Model[0] );
}
/**
1.2 +8 -1 avalon-sandbox/merlin/assembly/src/test/conf/block.xml
Index: block.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/assembly/src/test/conf/block.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- block.xml 3 Jul 2003 04:28:54 -0000 1.1
+++ block.xml 3 Jul 2003 23:34:50 -0000 1.2
@@ -1,6 +1,6 @@
-<block>
+<block name="test">
<implementation>
@@ -20,6 +20,13 @@
</classloader>
<container name="primary">
+ <classloader>
+ <classpath>
+ <repository>
+ <resource id="test:test-e"/>
+ </repository>
+ </classpath>
+ </classloader>
<component name="test"
class="org.apache.avalon.assembly.model.test.TestComponent"/>
</container>
1.2 +2 -2
avalon-sandbox/merlin/assembly/src/test/org/apache/avalon/assembly/model/ClasspathTestCase.java
Index: ClasspathTestCase.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/assembly/src/test/org/apache/avalon/assembly/model/ClasspathTestCase.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ClasspathTestCase.java 3 Jul 2003 04:34:44 -0000 1.1
+++ ClasspathTestCase.java 3 Jul 2003 23:34:50 -0000 1.2
@@ -73,13 +73,13 @@
getLogger().info( "listing classpath:" );
Logger classpath = getLogger().getChildLogger( "classpath" );
- URL[] urls = m_model.getClasspath();
+ URL[] urls = m_model.getQualifiedClassPath();
for( int i=0; i<urls.length; i++ )
{
classpath.info( urls[i].toString() );
}
- assertTrue( m_model.getClasspath().length == 4 );
+ assertTrue( m_model.getQualifiedClassPath().length == 4 );
getLogger().info( "classpath ok" );
}
1.2 +49 -14
avalon-sandbox/merlin/assembly/src/test/org/apache/avalon/assembly/model/CompositionTestCase.java
Index: CompositionTestCase.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/merlin/assembly/src/test/org/apache/avalon/assembly/model/CompositionTestCase.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- CompositionTestCase.java 3 Jul 2003 04:34:44 -0000 1.1
+++ CompositionTestCase.java 3 Jul 2003 23:34:50 -0000 1.2
@@ -53,20 +53,55 @@
*/
public void testCompositionModel() throws Exception
{
- m_logger.info( "composition test case" );
- ClassLoader classloader = m_model.getImplementation().getClassLoader();
- assertTrue(
- classloader.loadClass(
- "org.apache.avalon.assembly.model.testa.TestA" ) != null );
- assertTrue(
- classloader.loadClass(
- "org.apache.avalon.assembly.model.testb.TestB" ) != null );
- assertTrue(
- classloader.loadClass(
- "org.apache.avalon.assembly.model.testc.TestC" ) != null );
- assertTrue(
- classloader.loadClass(
- "org.apache.avalon.assembly.model.testd.TestD" ) != null );
+ getLogger().info( "composition test case" );
+ printCompositionModel( m_model );
+ assertTrue( true );
+ }
+
+ private void printCompositionModel( CompositionModel model ) throws Exception
+ {
+ getLogger().info( " composition model: " + model.getName() );
+ getLogger().info( " services: " +
model.getServiceDirectives().length );
+ getLogger().info( " dependencies: " + model.getDependencies().length );
+ getLogger().info( " implementation: " + model.getImplementation() );
+ printContainmentModel( model.getImplementation() );
+ }
+
+ private void printContainmentModel( ContainmentModel model ) throws Exception
+ {
+ getLogger().info( " containment model: " + model.getName() );
+ printClassLoaderModel( model.getClassLoaderModel() );
+ printDeploymentModel( model );
+ getLogger().info( " profiles: " + model.getNestedModels().length );
+ Model[] models = model.getNestedModels();
+ for( int i=0; i<models.length; i++ )
+ {
+ Model m = models[i];
+ if( m instanceof ContainmentModel )
+ {
+ printContainmentModel( (ContainmentModel) m );
+ }
+ else if( m instanceof DeploymentModel )
+ {
+ printDeploymentModel( (DeploymentModel) m );
+ }
+ }
+ }
+
+ private void printClassLoaderModel( ClassLoaderModel model ) throws Exception
+ {
+ getLogger().info( " classloader model: " + model );
+ getLogger().info( " classpath: " +
model.getQualifiedClassPath().length );
+ URL[] classpath = model.getQualifiedClassPath();
+ for( int i=0; i<classpath.length; i++ )
+ {
+ getLogger().info( classpath[i].toString() );
+ }
+ }
+
+ private void printDeploymentModel( DeploymentModel model ) throws Exception
+ {
+ getLogger().info( " deployment model: " + model.getName() );
}
//-------------------------------------------------------
1.2 +1 -1 avalon-sandbox/merlin/merlin-platform/xdocs/resources/index.xml
Index: index.xml
===================================================================
RCS file: /home/cvs/avalon-sandbox/merlin/merlin-platform/xdocs/resources/index.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- index.xml 10 Jun 2003 02:14:25 -0000 1.1
+++ index.xml 3 Jul 2003 23:34:50 -0000 1.2
@@ -33,7 +33,7 @@
</td>
</tr>
<tr>
- <td><a href="/api/index.html">Javadoc</a></td>
+ <td><a href="api/index.html">Javadoc</a></td>
<td>
The Merlin Platform Javadoc pages.
</td>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]