mcconnell 2002/12/08 19:03:47
Modified: assembly/src/java/org/apache/avalon/assembly/engine
DefaultRepositoryManager.java Engine.java
EngineClassLoader.java RepositoryManager.java
Log:
Applied some rearrangements of locic between the classloader and
component repository to better support classloader extension.
Revision Changes Path
1.3 +37 -401
avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/DefaultRepositoryManager.java
Index: DefaultRepositoryManager.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/DefaultRepositoryManager.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- DefaultRepositoryManager.java 7 Dec 2002 14:00:53 -0000 1.2
+++ DefaultRepositoryManager.java 9 Dec 2002 03:03:47 -0000 1.3
@@ -77,7 +77,6 @@
import org.apache.avalon.assembly.profile.ProfileManager;
import org.apache.avalon.assembly.service.ServiceManager;
import org.apache.avalon.assembly.engine.model.*;
-import org.apache.avalon.assembly.util.DefaultFileFilter;
import org.apache.avalon.excalibur.extension.Extension;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
@@ -105,32 +104,16 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Gary Shea</a>
* @version $Revision$ $Date$
*/
-public class DefaultRepositoryManager extends AbstractLogEnabled implements
Contextualizable, Initializable, RepositoryManager
+public class DefaultRepositoryManager extends AbstractLogEnabled implements
Initializable, RepositoryManager
{
//===================================================================
// static
//===================================================================
- private static final FileFilter JAR_FILTER = new DefaultFileFilter( "jar" );
-
-
- private static final Resources REZ =
- ResourceManager.getPackageResources( DefaultRepositoryManager.class );
-
- /**
- * Optional context key referencing an instance of {@link LibraryDescriptor}
- * that defines the set of extension directories to use.
- */
- public static final String EXTENSIONS_DESCRIPTOR_KEY =
"urn:assembly:extensions.descriptor";
-
- /**
- * Optional classpath key referencing an instance of {@link ClasspathDescriptor}
- * that defines the set of jar files to install.
- */
- public static final String CLASSPATH_DESCRIPTOR_KEY =
"urn:assembly:classpath.descriptor";
-
private static final String X_INFO = "xinfo";
+
private static final String X_TYPE = "xtype";
+
private static final String X_SERVICE = "xservice";
private static final String AVALON_BLOCK_KEY = "Avalon-Block";
@@ -142,27 +125,12 @@
/**
* Parent repository.
*/
- private RepositoryManager m_parent = null;
+ private RepositoryManager m_parent;
/**
* Parent repository.
*/
- private EngineClassLoader m_classloader;
-
- /**
- * The base directory.
- */
- private File m_home;
-
- /**
- * Description of the extension directories.
- */
- private LibraryDescriptor m_extensions;
-
- /**
- * Utility class to manage extension jar files.
- */
- private PackageManager m_manager;
+ private ClassLoader m_classloader;
/**
* The registry of installed component types.
@@ -180,58 +148,28 @@
private ProfileManager m_profiles;
/**
- * The bootstrap flag..
+ * List of jar files already installed.
*/
- private Boolean m_bootstrap = new Boolean( false );
-
private List m_scanned = new ArrayList();
- //==============================================================
- // Contextualizable
- //==============================================================
-
- /**
- * <p>Application of a runtime context to the lifestyle service.
- * The context value will be passed directly to lifestyle handlers
- * established by this service.
- * @param context the runtime context
- */
- public void contextualize( Context context ) throws ContextException
+ //===================================================================
+ // constructor
+ //===================================================================
+
+ DefaultRepositoryManager( ClassLoader classloader )
{
- m_classloader = (EngineClassLoader) context.get(
"urn:assembly:engine.classloader" );
- m_extensions = (LibraryDescriptor) context.get(
"urn:assembly:libraries-descriptor" );
- m_home = (File) context.get( "urn:avalon:home" );
+ this( classloader, null );
+ }
- try
- {
- m_bootstrap = (Boolean) context.get( "urn:assembly:engine.bootstrap" );
- }
- catch( ContextException ce )
- {
- // use default value
- }
- catch( Throwable ce )
- {
- throw new IllegalArgumentException( "urn:assembly:engine.bootstrap" );
- }
-
- try
+ DefaultRepositoryManager( ClassLoader classloader, RepositoryManager parent )
+ {
+ if( classloader == null )
{
- m_parent = (RepositoryManager) context.get(
"urn:assembly:repository.parent" );
- m_types = new TypeManager( m_classloader, m_parent.getTypeManager() );
- m_services = new ServiceManager( m_classloader,
m_parent.getServiceManager() );
- m_profiles = new ProfileManager( m_classloader,
m_parent.getProfileManager() );
- }
- catch( ContextException ce )
- {
- m_services = new ServiceManager( m_classloader, null );
- m_types = new TypeManager( m_classloader, null );
- m_profiles = new ProfileManager( m_classloader, null );
+ throw new NullPointerException( "classloader" );
}
- m_services.enableLogging( getLogger().getChildLogger( "services" ) );
- m_types.enableLogging( getLogger().getChildLogger( "types" ) );
- m_profiles.enableLogging( getLogger().getChildLogger( "profiles" ) );
+ m_classloader = classloader;
+ m_parent = parent;
}
//===================================================================
@@ -249,101 +187,25 @@
throw new IllegalStateException( "logging" );
}
- ArrayList list = new ArrayList();
- File anchor = new File( m_home, m_extensions.getBaseDirectory() );
- IncludeDescriptor[] includes = m_extensions.getIncludeDescriptors();
- for( int j = 0; j < includes.length; j++ )
- {
- File include = new File( anchor, includes[ j ].getFile() );
- if( include.isDirectory() )
- {
- list.add( include );
- getLogger().debug( "including kernel extension dir: " + include );
- }
- else
- {
- final String error = "Invalid include directory: " + include;
- throw new IllegalArgumentException( error );
- }
- }
+ ServiceManager services = null;
+ TypeManager types = null;
+ ProfileManager profiles = null;
- if( m_bootstrap.booleanValue() )
+ if( m_parent != null )
{
- String sep = System.getProperty( "path.separator" );
- String exts = System.getProperty( "java.ext.dirs" );
- StringTokenizer tokenizer = new StringTokenizer( exts, sep );
- while( tokenizer.hasMoreTokens() )
- {
- String token = tokenizer.nextToken();
- File test = new File( token );
- if( test.exists() )
- {
- list.add( test );
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug( "including system extension dir: " +
test );
- }
- }
- else
- {
- File file = new File( m_home, token );
- if( file.exists() )
- {
- list.add( file );
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug( "including relative extension dir: "
+ file );
- }
- }
- else
- {
- if( getLogger().isWarnEnabled() )
- {
- final String warning =
- "The extension directory path: '" + token
- + "' deas not refer to a directory.";
- getLogger().warn( warning );
- }
- }
- }
- }
+ services = m_parent.getServiceManager();
+ types = m_parent.getTypeManager();
+ profiles = m_parent.getProfileManager();
}
- File[] files = (File[])list.toArray( new File[ 0 ] );
- ExtensionManager repository = new DefaultExtensionManager( files );
- m_manager = new PackageManager( repository );
-
- //
- // handle the system bootstrap process
- //
-
- if( m_bootstrap.booleanValue() )
- {
-
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug( "bootstraping from classpath" );
- }
-
- //
- // handle the classpath
- //
+ m_services = new ServiceManager( m_classloader, services );
+ m_services.enableLogging( getLogger().getChildLogger( "services" ) );
- String sep = System.getProperty( "path.separator" );
- String classpath = System.getProperty( "java.class.path" );
+ m_types = new TypeManager( m_classloader, types );
+ m_types.enableLogging( getLogger().getChildLogger( "types" ) );
- StringTokenizer tokenizer = new StringTokenizer( classpath, sep );
- while( tokenizer.hasMoreTokens() )
- {
- String token = tokenizer.nextToken();
- URL jar = new File( token ).toURL();
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug( "path: " + jar );
- }
- addLibrary( jar );
- }
- }
+ m_profiles = new ProfileManager( m_classloader, profiles );
+ m_profiles.enableLogging( getLogger().getChildLogger( "profiles" ) );
}
//=======================================================================
@@ -366,121 +228,10 @@
}
/**
- * Add a classpath to the repository.
- * @param base the base directory from which relative classpath entries
- * will be resolved.
- */
- public void addClasspath( ClasspathDescriptor classpath )
- {
- if( classpath == null )
- {
- throw new NullPointerException( "classpath" );
- }
-
- if( getLogger() == null )
- {
- throw new IllegalStateException( "logging" );
- }
-
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug( "adding classpath" );
- }
-
- List list = new ArrayList();
- Vector stack = new Vector();
- FilesetDescriptor[] dirs = classpath.getFilesetDescriptors();
- for( int i = 0; i < dirs.length; i++ )
- {
- FilesetDescriptor descriptor = dirs[ i ];
- File anchor = new File( m_home, descriptor.getBaseDirectory() );
- if( !anchor.exists() )
- {
- final String error =
- "Classpath base directory does not exist: "
- + anchor;
- throw new EngineRuntimeException( error );
- }
-
- IncludeDescriptor[] includes = descriptor.getIncludeDescriptors();
- for( int j = 0; j < includes.length; j++ )
- {
- String inc = includes[ j ].getFile();
- try
- {
- addLibrary( new File( anchor, inc ).toURL() );
- }
- catch( Throwable e )
- {
- final String error =
- "Error processing a classpath include: "
- + inc;
- throw new EngineRuntimeException( error, e );
- }
- }
- }
-
- if( getLogger().isDebugEnabled() )
- {
- getLogger().debug( "classpath ok" );
- }
- }
-
- /**
* Add a URL to the classpath.
- * @param url the URL to add to the classpath
- */
- public void addLibrary( URL url )
- {
- //if( !m_scanned.contains( url ) )
- //{
- addExtensions( url );
- m_classloader.addLibraryURL( url );
- scan( url );
- //}
- }
-
- private void addExtensions( URL url )
- {
- if( isDirectory( url ) )
- {
- return;
- }
-
- try
- {
- String[] path = urlsToStrings( new URL[]{ url } );
- final File[] extensions = getOptionalPackagesFor( path );
- for( int i = 0; i < extensions.length; i++ )
- {
- File ext = extensions[ i ];
- try
- {
- URL target = ext.toURL();
- addLibrary( target );
- }
- catch( Throwable e )
- {
- final String error =
- "Internal error while attempting to add optional package: " +
ext;
- throw new EngineRuntimeException( error, e );
- }
- }
- }
- catch( Throwable e )
- {
- final String error =
- "Internal error while attempting to add extension url: " + url;
- throw new EngineRuntimeException( error, e );
- }
- }
-
- /**
- * Register any components declared in the manifest.
- * @param url pointing to the jar file
- * @exception EngineRuntimeException if an scanning error occurs
+ * @param url the URL to add to the repository
*/
- private void scan( URL url ) throws EngineRuntimeException
+ public void install( URL url )
{
if( isDirectory( url ) )
{
@@ -521,8 +272,7 @@
getLogger().debug( "scanning: " + url );
}
JarFile base = jar.getJarFile();
- loadComponents( base );
-
+ load( base );
}
catch( IOException e )
{
@@ -538,7 +288,7 @@
}
}
- private void loadComponents( JarFile base ) throws IOException
+ private void load( JarFile base ) throws IOException
{
List list = new ArrayList();
@@ -634,118 +384,4 @@
return name.replace( '/', '.' );
}
- private String[] urlsToStrings( URL[] urls )
- {
- Vector vector = new Vector();
- for( int i = 0; i < urls.length; i++ )
- {
- vector.add( urls[ i ].toString() );
- }
- return (String[])vector.toArray( new String[ vector.size() ] );
- }
-
-
//================================================================================
- // extension libraries
-
//================================================================================
-
- /**
- * 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
- */
- protected File[] getOptionalPackagesFor( final String[] classPath )
- throws Exception
- {
- if( m_manager == null )
- {
- RepositoryManager parent = getParent();
- if( parent != null )
- {
- if( parent instanceof DefaultRepositoryManager )
- {
- return (
(DefaultRepositoryManager)parent).getOptionalPackagesFor( classPath );
- }
- }
- return new File[ 0 ];
- }
-
- 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() )
- {
- final int size = unsatisfied.size();
- for( int i = 0; i < size; i++ )
- {
- final Extension extension = (Extension)unsatisfied.get( i );
- final Object[] params = new Object[]
- {
- extension.getExtensionName(),
- extension.getSpecificationVendor(),
- extension.getSpecificationVersion(),
- extension.getImplementationVendor(),
- extension.getImplementationVendorID(),
- extension.getImplementationVersion(),
- extension.getImplementationURL()
- };
- final String message = REZ.format( "missing.extension", params );
- getLogger().warn( message );
- }
-
- final String message =
- REZ.getString( "unsatisfied.extensions", new Integer( size ) );
- throw new Exception( message );
- }
-
- final OptionalPackage[] packages =
- (OptionalPackage[])dependencies.toArray( new OptionalPackage[ 0 ] );
- return OptionalPackage.toFiles( packages );
- }
-
- private Manifest[] getManifests( final String[] classPath )
- throws Exception
- {
- final ArrayList manifests = new ArrayList();
-
- for( int i = 0; i < classPath.length; i++ )
- {
- final String element = classPath[ i ];
- if( element.endsWith( ".jar" ) )
- {
- try
- {
- final URL url = new URL( "jar:" + element + "!/" );
- final JarURLConnection connection =
- (JarURLConnection)url.openConnection();
- final Manifest manifest = connection.getManifest();
- manifests.add( manifest );
- }
- catch( final IOException ioe )
- {
- final String message =
- REZ.getString( "bad-classpath-entry", element );
- throw new EngineException(
- message + ": " + element, ioe );
- }
- }
- }
- return (Manifest[])manifests.toArray( new Manifest[ 0 ] );
- }
-
- RepositoryManager getParent()
- {
- return m_parent;
- }
}
1.4 +2 -2
avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/Engine.java
Index: Engine.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/Engine.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Engine.java 7 Dec 2002 09:34:28 -0000 1.3
+++ Engine.java 9 Dec 2002 03:03:47 -0000 1.4
@@ -71,7 +71,7 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Avalon Development
Team</a>
* @version $Revision$ $Date$
*/
-public interface Engine extends RepositoryManager, AssemblyService
+public interface Engine extends AssemblyService
{
/**
* Creation of a new lifestyle handler.
1.3 +409 -98
avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/EngineClassLoader.java
Index: EngineClassLoader.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/EngineClassLoader.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- EngineClassLoader.java 7 Dec 2002 14:00:53 -0000 1.2
+++ EngineClassLoader.java 9 Dec 2002 03:03:47 -0000 1.3
@@ -53,9 +53,22 @@
import java.io.File;
import java.util.Map;
import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.List;
import java.net.URL;
import java.net.URLClassLoader;
-
+import java.util.jar.Manifest;
+import java.util.jar.Attributes;
+import java.net.JarURLConnection;
+import java.util.ArrayList;
+import java.io.IOException;
+
+import org.apache.avalon.excalibur.extension.Extension;
+import org.apache.avalon.excalibur.i18n.ResourceManager;
+import org.apache.avalon.excalibur.i18n.Resources;
+import org.apache.avalon.excalibur.packagemanager.OptionalPackage;
+import org.apache.avalon.excalibur.packagemanager.PackageManager;
+import org.apache.avalon.excalibur.packagemanager.impl.DefaultExtensionManager;
import org.apache.avalon.framework.Version;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.logger.Logger;
@@ -77,6 +90,8 @@
import org.apache.avalon.meta.info.ReferenceDescriptor;
import org.apache.avalon.meta.info.Type;
import org.apache.avalon.meta.model.Profile;
+import org.apache.avalon.meta.model.LoggingDirective;
+import org.apache.avalon.meta.model.Category;
import org.apache.avalon.assembly.type.TypeManager;
import org.apache.avalon.assembly.profile.ProfileManager;
import org.apache.avalon.assembly.appliance.Appliance;
@@ -94,9 +109,14 @@
import org.apache.avalon.assembly.lifestyle.LifestyleService;
import org.apache.avalon.assembly.lifestyle.DefaultLifestyleService;
import org.apache.avalon.assembly.lifestyle.LifestyleHandler;
+import org.apache.avalon.assembly.logging.LoggingDescriptor;
+import org.apache.avalon.assembly.logging.DefaultLoggingManager;
import org.apache.avalon.assembly.logging.LoggingManager;
+import org.apache.avalon.assembly.logging.TargetDescriptor;
import org.apache.avalon.assembly.engine.model.LibraryDescriptor;
import org.apache.avalon.assembly.engine.model.ClasspathDescriptor;
+import org.apache.avalon.assembly.engine.model.FilesetDescriptor;
+import org.apache.avalon.assembly.engine.model.IncludeDescriptor;
import org.apache.excalibur.mpool.DefaultPoolManager;
import org.apache.excalibur.mpool.PoolManager;
import org.apache.excalibur.event.command.CommandManager;
@@ -111,6 +131,13 @@
public class EngineClassLoader extends URLClassLoader implements Engine,
LogEnabled, Configurable, Contextualizable, Serviceable, Initializable
{
//==============================================================
+ // static
+ //==============================================================
+
+ private static final Resources REZ =
+ ResourceManager.getPackageResources( Engine.class );
+
+ //==============================================================
// state
//==============================================================
@@ -146,7 +173,7 @@
* The repository maanger holds the service, types and profiels associated
* with the class loader.
*/
- private RepositoryManager m_repository;
+ private DefaultRepositoryManager m_repository;
/**
* The lifestyle service.
@@ -184,25 +211,34 @@
/**
* Description of the extension directories.
*/
- private LibraryDescriptor m_extensions;
+ private LibraryDescriptor m_descriptor;
/**
- * Flag indicating if system classpath based bootstrapping should take place.
+ * The set of facilities.
*/
- private Boolean m_bootstrap = new Boolean( false );
+ private Map m_facilities = new Hashtable();
/**
- * The set of facilities.
+ * Utility class to manage packages.
*/
- private Map m_facilities = new Hashtable();
+ private PackageManager m_packages;
+
+ /**
+ * Utility class to manage extension paths.
+ */
+ private DefaultExtensionManager m_extensions;
+
+ /**
+ * Flag indicating if system classpath based bootstrapping should take place.
+ */
+ private boolean m_bootstrap = false;
//=======================================================================
// constructor
//=======================================================================
/**
- * Creation of a new type manager using the supplied parent class loader.
- * @param parent the parent class loader
+ * Creation of a new type manager using.
*/
public EngineClassLoader()
{
@@ -232,7 +268,6 @@
return m_logger;
}
-
//==============================================================
// Configurable
//==============================================================
@@ -274,11 +309,11 @@
try
{
- m_extensions = (LibraryDescriptor)context.get(
"urn:assembly:extensions.descriptor" );
+ m_descriptor = (LibraryDescriptor)context.get(
"urn:assembly:extensions.descriptor" );
}
catch( ContextException e )
{
- m_extensions = new LibraryDescriptor();
+ m_descriptor = new LibraryDescriptor();
}
try
@@ -292,11 +327,11 @@
try
{
- m_bootstrap = (Boolean) context.get( "urn:assembly:engine.bootstrap" );
+ m_bootstrap = "true".equals( context.get(
"urn:assembly:engine.bootstrap" ) );
}
- catch( ContextException e )
+ catch( ContextException ce )
{
- // default already set
+ // use default value
}
}
@@ -353,84 +388,240 @@
{
getLogger().debug( "initialization" );
}
-
- m_repository = createRepositoryManager();
+
+ createRepositoryManager();
+
m_lifestyle = createLifestyleService( m_facilities );
m_appliances = createApplianceManager( m_facilities );
m_assembly = createAssemblyService( m_facilities, m_graph );
- if( getLogger().isDebugEnabled() )
+ //
+ // install the set of extensions
+ //
+
+ ArrayList list = new ArrayList();
+ File anchor = new File( m_home, m_descriptor.getBaseDirectory() );
+ IncludeDescriptor[] includes = m_descriptor.getIncludeDescriptors();
+ for( int j = 0; j < includes.length; j++ )
{
- getLogger().debug( "ready" );
+ File include = new File( anchor, includes[ j ].getFile() );
+ if( include.isDirectory() )
+ {
+ list.add( include );
+ getLogger().debug( "including kernel extension dir: " + include );
+ }
+ else
+ {
+ final String error = "Invalid include directory: " + include;
+ throw new IllegalArgumentException( error );
+ }
}
- }
+ if( m_bootstrap )
+ {
+ String sep = System.getProperty( "path.separator" );
+ String exts = System.getProperty( "java.ext.dirs" );
+ StringTokenizer tokenizer = new StringTokenizer( exts, sep );
+ while( tokenizer.hasMoreTokens() )
+ {
+ String token = tokenizer.nextToken();
+ File test = new File( token );
+ if( test.exists() )
+ {
+ list.add( test );
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "including system extension dir: " +
test );
+ }
+ }
+ else
+ {
+ File file = new File( m_home, token );
+ if( file.exists() )
+ {
+ list.add( file );
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "including relative extension dir: "
+ file );
+ }
+ }
+ else
+ {
+ if( getLogger().isWarnEnabled() )
+ {
+ final String warning =
+ "The extension directory path: '" + token
+ + "' deas not refer to a directory.";
+ getLogger().warn( warning );
+ }
+ }
+ }
+ }
+ }
- //==============================================================
- // AssemblyService
- //==============================================================
+ File[] files = (File[])list.toArray( new File[ 0 ] );
+ m_extensions = new DefaultExtensionManager( files );
+ m_packages = new PackageManager( m_extensions );
- /**
- * Assemble the supplied appliance.
- * @param appliance the object to assembly
- */
- public void assemble( Appliance appliance ) throws AssemblyException
- {
- m_assembly.assemble( appliance );
+ //
+ // handle the system bootstrap process
+ //
+
+ if( m_bootstrap )
+ {
+
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "bootstraping from classpath" );
+ }
+
+ //
+ // handle the classpath
+ //
+
+ String sep = System.getProperty( "path.separator" );
+ String classpath = System.getProperty( "java.class.path" );
+
+ StringTokenizer tokenizer = new StringTokenizer( classpath, sep );
+ while( tokenizer.hasMoreTokens() )
+ {
+ String token = tokenizer.nextToken();
+ URL url = new File( token ).toURL();
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "path: " + url );
+ }
+ addURL( url );
+ }
+ }
+
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "ready" );
+ }
}
//==============================================================
- // RepositoryManager
+ // URLClassLoader
//==============================================================
- /**
- * Add a URL to a jar file. A repository implementation is responsible for
- * the registration of any declared component services, types and packaged
- * profiles.
- *
- * @param url a url to a jar file
- */
- public void addLibrary( URL url )
+ /**
+ * Add a URL to the classpath.
+ * @param url the URL to add to the classpath
+ */
+ protected void addURL( URL url )
{
- m_repository.addLibrary( url );
+ addExtensions( url );
+ super.addURL( url );
+ m_repository.install( url );
}
/**
* Add a classpath to the repository.
* @param base the base directory from which relative classpath entries
* will be resolved.
- * @param classpath the classpath descriptor
*/
public void addClasspath( ClasspathDescriptor classpath )
{
- m_repository.addClasspath( classpath );
- }
+ if( classpath == null )
+ {
+ throw new NullPointerException( "classpath" );
+ }
- /**
- * Returns the type manager.
- * @return the type manager
- */
- public TypeManager getTypeManager()
- {
- return m_repository.getTypeManager();
+ if( getLogger() == null )
+ {
+ throw new IllegalStateException( "logging" );
+ }
+
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "adding classpath" );
+ }
+
+ List list = new ArrayList();
+ FilesetDescriptor[] dirs = classpath.getFilesetDescriptors();
+ for( int i = 0; i < dirs.length; i++ )
+ {
+ FilesetDescriptor descriptor = dirs[ i ];
+ File anchor = new File( m_home, descriptor.getBaseDirectory() );
+ if( !anchor.exists() )
+ {
+ final String error =
+ "Classpath base directory does not exist: "
+ + anchor;
+ throw new EngineRuntimeException( error );
+ }
+
+ IncludeDescriptor[] includes = descriptor.getIncludeDescriptors();
+ for( int j = 0; j < includes.length; j++ )
+ {
+ String inc = includes[ j ].getFile();
+ try
+ {
+ addURL( new File( anchor, inc ).toURL() );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Error processing a classpath include: "
+ + inc;
+ throw new EngineRuntimeException( error, e );
+ }
+ }
+ }
+
+ if( getLogger().isDebugEnabled() )
+ {
+ getLogger().debug( "classpath ok" );
+ }
}
- /**
- * Returns the service manager.
- * @return the service manager
- */
- public org.apache.avalon.assembly.service.ServiceManager getServiceManager()
+ private void addExtensions( URL url )
{
- return m_repository.getServiceManager();
+ if( isDirectory( url ) )
+ {
+ return;
+ }
+
+ try
+ {
+ String[] path = urlsToStrings( new URL[]{ url } );
+ final File[] extensions = getOptionalPackagesFor( path );
+ for( int i = 0; i < extensions.length; i++ )
+ {
+ File ext = extensions[ i ];
+ try
+ {
+ URL target = ext.toURL();
+ addURL( target );
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Internal error while attempting to add optional package: " +
ext;
+ throw new EngineRuntimeException( error, e );
+ }
+ }
+ }
+ catch( Throwable e )
+ {
+ final String error =
+ "Internal error while attempting to add extension url: " + url;
+ throw new EngineRuntimeException( error, e );
+ }
}
+ //==============================================================
+ // AssemblyService
+ //==============================================================
+
/**
- * Returns the profile manager.
- * @return the profile manager
+ * Assemble the supplied appliance.
+ * @param appliance the object to assembly
*/
- public ProfileManager getProfileManager()
+ public void assemble( Appliance appliance ) throws AssemblyException
{
- return m_repository.getProfileManager();
+ m_assembly.assemble( appliance );
}
//==============================================================
@@ -438,6 +629,15 @@
//==============================================================
/**
+ * Returns the repository manager.
+ * @return the repository manager
+ */
+ public RepositoryManager getRepository()
+ {
+ return m_repository;
+ }
+
+ /**
* Creation of a new lifestyle handler.
* @param appliance the appliance that the handler will manage
* @param context the system context
@@ -448,20 +648,6 @@
return m_lifestyle.createHandler( appliance, this, context );
}
- /**
- * Add a URL to the classpath.
- * @param url the URL to add to the classpath
- */
- void addLibraryURL( URL url )
- {
- addURL( url );
- }
-
- protected void addURL( URL url )
- {
- super.addURL( url );
- }
-
/**
* Register a type and associated profiles with the container.
* @param path the path to the appliance implementation class
@@ -474,12 +660,14 @@
getLogger().debug( "register:" + path );
}
+ TypeManager types = getRepository().getTypeManager();
+ ProfileManager profiles = getRepository().getProfileManager();
try
{
- Type type = getTypeManager().createType( path );
- getTypeManager().addType( type );
- Profile[] profiles = getProfileManager().loadProfiles( type );
- getProfileManager().addProfiles( profiles );
+ Type type = types.createType( path );
+ types.addType( type );
+ Profile[] packaged = profiles.loadProfiles( type );
+ profiles.addProfiles( packaged );
}
catch( Throwable e )
{
@@ -510,7 +698,7 @@
Appliance appliance = m_appliances.getAppliance( dependency );
if( appliance == null )
{
- Profile profile = getProfileManager().getProfile( dependency );
+ Profile profile = getRepository().getProfileManager().getProfile(
dependency );
if( profile == null )
{
final String error =
@@ -547,7 +735,7 @@
Appliance appliance = m_appliances.getAppliance( stage );
if( appliance == null )
{
- Profile profile = getProfileManager().getProfile( stage );
+ Profile profile = getRepository().getProfileManager().getProfile( stage
);
if( profile == null )
{
final String error =
@@ -607,26 +795,21 @@
// utilities
//==============================================================
- private RepositoryManager createRepositoryManager() throws Exception
+ private void createRepositoryManager() throws Exception
{
- if( getLogger().isDebugEnabled() )
+ ClassLoader parent = getParent();
+ if(( parent != null ) && ( parent instanceof EngineClassLoader ))
{
- getLogger().debug( "creating repository manager" );
+ m_repository =
+ new DefaultRepositoryManager(
+ this, ((EngineClassLoader)parent).getRepository() );
}
-
- DefaultRepositoryManager manager = new DefaultRepositoryManager();
-
- manager.enableLogging( getLogger() );
- DefaultContext context = new DefaultContext( getSystemContext() );
- context.put( "urn:assembly:engine.classloader", this );
- context.put( "urn:assembly:libraries-descriptor", m_extensions );
- context.put( "urn:assembly:engine.bootstrap", m_bootstrap );
- context.put( "urn:avalon:home", m_home );
- context.makeReadOnly();
- manager.contextualize( context );
- manager.initialize();
-
- return manager;
+ else
+ {
+ m_repository = new DefaultRepositoryManager( this );
+ }
+ m_repository.enableLogging( getLogger() );
+ m_repository.initialize();
}
private ApplianceManager createApplianceManager( Map facilities )
@@ -809,5 +992,133 @@
"Internal error during establishment of the default pool manager.";
throw new EngineRuntimeException( error, e );
}
+ }
+
+ private boolean isDirectory( URL url )
+ {
+ if( url.getProtocol().equals( "file" ) )
+ {
+ File file = new File( url.toString().substring( 5 ) );
+ return file.isDirectory();
+ }
+ return false;
+ }
+
+ private String[] urlsToStrings( URL[] urls )
+ {
+ ArrayList list = new ArrayList();
+ for( int i = 0; i < urls.length; i++ )
+ {
+ list.add( urls[ i ].toString() );
+ }
+ return (String[])list.toArray( new String[ list.size() ] );
+ }
+
+
//================================================================================
+ // extension support
+
//================================================================================
+
+ /**
+ * 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
+ */
+ protected File[] getOptionalPackagesFor( final String[] classPath )
+ throws Exception
+ {
+ if( m_packages == null )
+ {
+ ClassLoader parent = getParent();
+ if( parent != null )
+ {
+ if( parent instanceof EngineClassLoader )
+ {
+ return ((EngineClassLoader)parent).getOptionalPackagesFor(
classPath );
+ }
+ }
+ return new File[ 0 ];
+ }
+
+ 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_packages.scanDependencies( required, available, dependencies, unsatisfied
);
+
+ if(( 0 != unsatisfied.size() ) && ( getLogger().isWarnEnabled() ))
+ {
+ final int size = unsatisfied.size();
+ for( int i = 0; i < size; i++ )
+ {
+ final Extension extension = (Extension)unsatisfied.get( i );
+ final Object[] params = new Object[]
+ {
+ extension.getExtensionName(),
+ extension.getSpecificationVendor(),
+ extension.getSpecificationVersion(),
+ extension.getImplementationVendor(),
+ extension.getImplementationVendorID(),
+ extension.getImplementationVersion(),
+ extension.getImplementationURL()
+ };
+ final String message = REZ.format( "missing.extension", params );
+ getLogger().warn( message );
+ }
+
+ final String message =
+ REZ.getString( "unsatisfied.extensions", new Integer( size ) );
+ throw new Exception( message );
+ }
+
+ final OptionalPackage[] packages =
+ (OptionalPackage[])dependencies.toArray( new OptionalPackage[ 0 ] );
+ return OptionalPackage.toFiles( packages );
+ }
+
+ private Manifest[] getManifests( final String[] classPath )
+ throws Exception
+ {
+ final ArrayList manifests = new ArrayList();
+
+ for( int i = 0; i < classPath.length; i++ )
+ {
+ final String element = classPath[ i ];
+
+ if( element.endsWith( ".jar" ) )
+ {
+ try
+ {
+ final URL url = new URL( "jar:" + element + "!/" );
+ final JarURLConnection connection =
+ (JarURLConnection)url.openConnection();
+ final Manifest manifest = connection.getManifest();
+ manifests.add( manifest );
+ }
+ catch( final IOException ioe )
+ {
+ final String message =
+ REZ.getString( "bad-classpath-entry", element );
+ throw new EngineException(
+ message + ": " + element, ioe );
+ }
+ }
+ }
+
+ return (Manifest[])manifests.toArray( new Manifest[ 0 ] );
+ }
+
+ /**
+ * Strips the ".class" ending off of a Type/Block/Service name.
+ */
+ private final String cleanName( String name )
+ {
+ int end = name.indexOf( ".class" );
+ return name.substring( 0, ( end >= 0 ) ? end : name.length() );
}
}
1.2 +1 -19
avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/RepositoryManager.java
Index: RepositoryManager.java
===================================================================
RCS file:
/home/cvs/avalon-sandbox/assembly/src/java/org/apache/avalon/assembly/engine/RepositoryManager.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- RepositoryManager.java 7 Dec 2002 09:34:28 -0000 1.1
+++ RepositoryManager.java 9 Dec 2002 03:03:47 -0000 1.2
@@ -55,7 +55,6 @@
import org.apache.avalon.assembly.profile.ProfileManager;
import org.apache.avalon.assembly.service.ServiceManager;
import org.apache.avalon.assembly.type.TypeManager;
-import org.apache.avalon.assembly.engine.model.ClasspathDescriptor;
/**
* An appliance is a class that encapsulates the deployment criteria
@@ -70,23 +69,6 @@
public interface RepositoryManager
{
- /**
- * Add a URL to a jar file. A repository implementation is responsible for
- * the registration of any declared component services, types and packaged
- * profiles.
- *
- * @param url a url to a jar file
- */
- void addLibrary( URL url );
-
- /**
- * Add a classpath to the repository.
- * @param base the base directory from which relative classpath entries
- * will be resolved.
- * @param classpath the classpath descriptor
- */
- void addClasspath( ClasspathDescriptor classpath );
-
/**
* Returns the type manager.
* @return the type manager
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>