mcconnell 2002/07/03 12:08:55 Added: assembly/src/java/org/apache/excalibur/merlin/kernel Container.java ContainerClassLoader.java DefaultContainer.java DefaultContainer.xinfo DefaultKernel.java DefaultKernel.xinfo Fileset.java Kernel.java Main.java Resources.properties Verifiable.java package.html Log: Seperation of Kernel/Container/Registry Revision Changes Path 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Container.java Index: Container.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.merlin.kernel; import org.apache.excalibur.containerkit.verifier.VerifyException; /** * A service that provides support for the management of a set of component types * and factories. * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2002/07/03 19:08:54 $ */ public interface Container { /** * Request the startup of the kernel. */ void startup() throws Exception; /** * Request the shutdown of the kernel. */ void shutdown(); } 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/ContainerClassLoader.java Index: ContainerClassLoader.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.merlin.kernel; import java.io.File; import java.io.IOException; import java.util.jar.Attributes; import java.util.jar.Manifest; import java.util.Dictionary; import java.util.Hashtable; import java.util.Enumeration; import java.util.Vector; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.Map; import java.util.List; import java.util.LinkedList; import java.net.URLClassLoader; import java.net.URL; import java.net.JarURLConnection; import org.apache.avalon.framework.logger.Logger; import org.apache.avalon.framework.logger.LogEnabled; import org.apache.avalon.framework.CascadingRuntimeException; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; import org.apache.avalon.excalibur.extension.Extension; import org.apache.avalon.excalibur.extension.PackageManager; import org.apache.avalon.excalibur.extension.PackageRepository; import org.apache.avalon.excalibur.extension.OptionalPackage; import org.apache.excalibur.merlin.registry.*; /** * Classloader for an assembly of components. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2002/07/03 19:08:54 $ */ public class ContainerClassLoader extends URLClassLoader implements LogEnabled { //=================================================================== // static //=================================================================== private static final Resources REZ = ResourceManager.getPackageResources( ContainerClassLoader.class ); //=================================================================== // state //=================================================================== private File[] m_stack; /** * List of names of block implementation classes. */ private final List m_blocks = new LinkedList(); private PackageManager m_manager; private Logger m_logger; //=================================================================== // constructor //=================================================================== ContainerClassLoader( ClassLoader parent, Configuration classpath, Logger logger ) { this( null, parent, classpath, logger ); } ContainerClassLoader( PackageRepository repository, ClassLoader parent, Configuration classpath, Logger logger ) { super( new URL[ 0 ], parent ); m_logger = logger; if( repository != null ) m_manager = new PackageManager( repository ); addClasspath( classpath ); } public void addClasspath( Configuration classpath ) { try { URL[] urls = Fileset.expandClasspath( classpath ); for( int i = 0; i < urls.length; i++ ) { addURL( urls[ i ] ); } String[] path = Fileset.urlsToStrings( urls ); final File[] extensions = getOptionalPackagesFor( path ); for( int i = 0; i < extensions.length; i++ ) { addURL( extensions[ i ].toURL() ); } } catch( Throwable e ) { final String error = "Unexpected exception while creating classloader"; throw new RegistryRuntimeException( error, e ); } } //=================================================================== // LogEnabled //=================================================================== public void enableLogging( Logger logger ) { m_logger = logger; } public Logger getLogger() { return m_logger; } //=================================================================== // ClassLoader //=================================================================== /** * */ protected void addURL( URL url ) { try { super.addURL( url ); getLogger().debug("scanning: " + url ); String[] entries = getBlocksEntries( url ); for( int i=0; i<entries.length; i++ ) { getLogger().debug("component: " + entries[i] ); m_blocks.add( entries[i] ); } } catch( Throwable e ) { throw new CascadingRuntimeException( "Unexpected error while attempting to add classloader URL: " + url, e ); } } //=================================================================== // ClassLoader extensions //=================================================================== /** * Returns TRUE is the component classname is know by the classloader. * @return a component availablity status */ public boolean hasComponent( String classname ) { return m_blocks.contains( classname ); } /** * Return the array of component implementation class names within the scope * of the classloader. * @return the block names array */ public String[] getComponentClassnames() { return (String[]) m_blocks.toArray( new String[0] ); } //=================================================================== // internals //=================================================================== /** * Returns an array of <code>String</code>s corresponding to the set of classnames * where each classname is a declared block within the supplied jar file. * @param file a jar file * @exception RegistryRuntimeException if a general exception occurs */ private String[] getBlocksEntries( URL base ) throws RegistryRuntimeException { Vector vector = new Vector(); try { final URL url = new URL( "jar:" + base.toString() + "!/" ); final JarURLConnection jar = (JarURLConnection)url.openConnection(); final Map map = jar.getManifest().getEntries(); final Iterator iterator = map.keySet().iterator(); while( iterator.hasNext() ) { final String name = (String)iterator.next(); final Attributes attributes = (Attributes)map.get( name ); final Iterator it = attributes.keySet().iterator(); while( it.hasNext() ) { final Object entry = it.next(); if( entry.toString().equals( "Avalon-Block" ) ) { if( attributes.get( entry ).equals( "true" ) ) { vector.add( name.substring( 0, name.indexOf( ".class" ) ) ); } } } } } catch( IOException e ) { final String error = "IO exception while attempt to read block manifest."; throw new RegistryRuntimeException( error, e ); } catch( Throwable e ) { final String error = "Unexpected exception while inspecting manifest on file: "; throw new RegistryRuntimeException( error + base, e ); } finally { return (String[]) vector.toArray( new String[0] ); } } /** * 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 */ private File[] getOptionalPackagesFor( final String[] classPath ) throws Exception { if( m_manager == null ) { ClassLoader parent = getParent(); if( parent != null ) { if( parent instanceof ContainerClassLoader ) { return ((ContainerClassLoader)parent).getOptionalPackagesFor( classPath ); } } else { 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 ); getLogger().warn( message ); throw new Exception( message ); } } } return (Manifest[])manifests.toArray( new Manifest[ 0 ] ); } } 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultContainer.java Index: DefaultContainer.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.merlin.kernel; import java.io.InputStream; import java.io.File; import java.io.IOException; import java.net.URL; import java.net.JarURLConnection; import java.net.URLClassLoader; import java.util.List; import java.util.LinkedList; import java.util.Map; import java.util.Hashtable; import java.util.Properties; import java.util.Vector; import java.util.Iterator; import java.util.jar.Attributes; import java.util.jar.Manifest; import java.security.Policy; import java.io.FileInputStream; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; import org.apache.excalibur.configuration.ConfigurationUtil; import org.apache.avalon.framework.logger.Logger; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.logger.AvalonFormatter; import org.apache.avalon.framework.logger.LogKitLogger; import org.apache.avalon.framework.activity.Initializable; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.activity.Executable; import org.apache.avalon.framework.CascadingRuntimeException; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.DefaultConfiguration; import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.context.Contextualizable; import org.apache.avalon.framework.context.ContextException; import org.apache.avalon.framework.context.DefaultContext; import org.apache.avalon.framework.service.Serviceable; import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.DefaultServiceManager; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.Version; import org.apache.avalon.framework.ExceptionUtil; import org.apache.avalon.excalibur.extension.PackageRepository; import org.apache.avalon.excalibur.extension.Extension; import org.apache.avalon.excalibur.extension.OptionalPackage; import org.apache.avalon.excalibur.extension.DefaultPackageRepository; import org.apache.excalibur.containerkit.metainfo.ComponentDescriptor; import org.apache.excalibur.containerkit.metainfo.ComponentInfo; import org.apache.excalibur.containerkit.metainfo.ServiceDescriptor; import org.apache.excalibur.containerkit.metainfo.DependencyDescriptor; import org.apache.excalibur.containerkit.metainfo.ServiceDesignator; import org.apache.log.Hierarchy; import org.apache.log.Priority; import org.apache.log.output.io.StreamTarget; import org.apache.excalibur.merlin.registry.DefaultRegistry; import org.apache.excalibur.containerkit.verifier.VerifyException; /** * Default container implementation that manages a registry of componet providers and * a registry of child containers. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2002/07/03 19:08:54 $ */ public class DefaultContainer extends AbstractLogEnabled implements Container, Verifiable, Contextualizable, Configurable, Initializable { //======================================================================= // static //======================================================================= /** * Context key used to locate the application classloader. */ public static final String CLASSLOADER_KEY = "classloader"; /** * Context key used to locate the application classloader. */ public static final String CONTAINER_KEY = "container"; //======================================================================= // state //======================================================================= /** * The container context. */ private Context m_context; /** * Configuration. */ private Configuration m_config; /** * The registry of components. */ private DefaultRegistry m_components; /** * The registry of embedded containers. */ private DefaultRegistry m_containers; /** * Classloader. */ private ContainerClassLoader m_classloader; /** * Parent container. */ private Container m_parent; //======================================================================= // Contextualizable //======================================================================= /** * Service context from which the registry classloader is resolved. * @param context a context value containing the key 'classloader' */ public void contextualize( Context context ) throws ContextException { m_context = context; m_classloader = (ContainerClassLoader) context.get( CLASSLOADER_KEY ); try { m_parent = (Container) context.get( CONTAINER_KEY ); } catch( ContextException e ) { // no parent container } } //======================================================================= // Configurable //======================================================================= /** * Invoked by the container to establish the registry configuration. * @param config a component configuration */ public void configure( Configuration config) { m_config = config; getLogger().debug("configuration"); } //======================================================================= // Initializable //======================================================================= /** * Initalization of a <code>Container</code>. * @exception Exception if an error occurs during initialization. */ public void initialize() throws Exception { m_components = createComponentRegistry( m_config.getChild( "components") ); m_containers = createContainerRegistry( m_config.getChild( "containers") ); } //======================================================================= // Verifiable //======================================================================= /** * Method invoked by a parent container to request type and assembly validation of * this container. * * @exception ValidationException if a validation failure occurs */ public void verify() throws VerifyException { m_components.verify(); m_containers.verify(); } //======================================================================= // DefaultContainer //======================================================================= private DefaultRegistry createComponentRegistry( Configuration config ) throws Exception { return createRegistry( m_classloader, config ); } private DefaultRegistry createContainerRegistry( Configuration config ) throws Exception { final ContainerClassLoader loader = new ContainerClassLoader( m_classloader, config.getChild("classpath"), getLogger().getChildLogger( config.getName()) ); return createRegistry( loader, config ); } private DefaultRegistry createRegistry( final ContainerClassLoader loader, final Configuration config ) throws Exception { DefaultContext context = new DefaultContext(); context.put( DefaultRegistry.CLASSLOADER_KEY, loader ); context.put( DefaultRegistry.CONTAINER_KEY, this ); DefaultRegistry registry = new DefaultRegistry(); registry.enableLogging( getLogger().getChildLogger( config.getName() ) ); registry.contextualize( context ); registry.configure( config ); registry.initialize( ); return registry; } //======================================================================= // Container //======================================================================= public void startup() throws Exception { getLogger().debug("startup"); //m_registry.execute(); } public void shutdown() { getLogger().debug("shutdown"); //m_registry.dispose(); } } 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultContainer.xinfo Index: DefaultContainer.xinfo =================================================================== <?xml version="1.0"?> <!-- Copyright (C) The Apache Software Foundation. All rights reserved. This software is published under the terms of the Apache Software License version 1.1, a copy of which has been included with this distribution in the LICENSE.txt file. @author Stephen McConnell @version 1.0 12/03/2001 --> <component-info> <component> <name>container</name> <version>1.0</version> </component> <context> <entry key="classloader" type="org.apache.exccalibur.merlin.kernel.ContainerClassLoader" optional="false"/> </context> <services> <service> <service-ref type="org.apache.excalibur.merlin.kernel.Container" version="1.0"/> </service> </services> </component-info> 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.java Index: DefaultKernel.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.merlin.kernel; import java.io.InputStream; import java.io.File; import java.io.IOException; import java.net.URL; import java.net.JarURLConnection; import java.net.URLClassLoader; import java.util.List; import java.util.LinkedList; import java.util.Map; import java.util.Hashtable; import java.util.Properties; import java.util.Vector; import java.util.Iterator; import java.util.jar.Attributes; import java.util.jar.Manifest; import java.security.Policy; import java.io.FileInputStream; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; import org.apache.excalibur.configuration.ConfigurationUtil; import org.apache.avalon.framework.logger.Logger; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.logger.AvalonFormatter; import org.apache.avalon.framework.logger.LogKitLogger; import org.apache.avalon.framework.activity.Initializable; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.activity.Executable; import org.apache.avalon.framework.activity.Startable; import org.apache.avalon.framework.CascadingRuntimeException; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.DefaultConfiguration; import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.context.Contextualizable; import org.apache.avalon.framework.context.ContextException; import org.apache.avalon.framework.context.DefaultContext; import org.apache.avalon.framework.service.Serviceable; import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.DefaultServiceManager; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.Version; import org.apache.avalon.framework.ExceptionUtil; import org.apache.avalon.excalibur.extension.PackageRepository; import org.apache.avalon.excalibur.extension.Extension; import org.apache.avalon.excalibur.extension.OptionalPackage; import org.apache.avalon.excalibur.extension.DefaultPackageRepository; import org.apache.excalibur.containerkit.metainfo.ComponentDescriptor; import org.apache.excalibur.containerkit.metainfo.ComponentInfo; import org.apache.excalibur.containerkit.metainfo.ServiceDescriptor; import org.apache.excalibur.containerkit.metainfo.DependencyDescriptor; import org.apache.excalibur.containerkit.metainfo.ServiceDesignator; import org.apache.log.Hierarchy; import org.apache.log.Priority; import org.apache.log.output.io.StreamTarget; import org.apache.excalibur.merlin.registry.DefaultRegistry; /** * Default kernel implementation. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2002/07/03 19:08:54 $ */ public class DefaultKernel extends AbstractLogEnabled implements Kernel, Configurable, Initializable { //======================================================================= // state //======================================================================= private Configuration m_config; private DefaultContainer m_container = new DefaultContainer(); //======================================================================= // Configurable //======================================================================= /** * Invoked by the container to establish the registry configuration. * @param config a component configuration */ public void configure( Configuration config) { m_config = config; getLogger().debug("configuration"); } //======================================================================= // Initializable //======================================================================= public void initialize() throws Exception { final ContainerClassLoader loader = new ContainerClassLoader( new DefaultPackageRepository( Fileset.expandExtensions( m_config.getChild( "extensions" ) ) ), Thread.currentThread().getContextClassLoader(), m_config.getChild("classpath"), getLogger().getChildLogger( m_config.getName()) ); DefaultContext context = new DefaultContext(); context.put( DefaultContainer.CLASSLOADER_KEY, loader ); m_container.enableLogging( getLogger().getChildLogger("container") ); m_container.contextualize( context ); m_container.configure( m_config ); m_container.initialize( ); } //======================================================================= // Startable //======================================================================= public void startup() throws Exception { m_container.startup(); } public void shutdown() { m_container.shutdown(); } } 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.xinfo Index: DefaultKernel.xinfo =================================================================== <?xml version="1.0"?> <!-- Copyright (C) The Apache Software Foundation. All rights reserved. This software is published under the terms of the Apache Software License version 1.1, a copy of which has been included with this distribution in the LICENSE.txt file. @author Stephen McConnell @version 1.0 12/03/2001 --> <component-info> <component> <name>kernel</name> <version>1.0</version> </component> <services> <service> <service-ref type="org.apache.excalibur.merlin.kernel.Kernel" version="1.0"/> </service> </services> </component-info> 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Fileset.java Index: Fileset.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.merlin.kernel; import org.apache.avalon.framework.configuration.Configuration; import java.net.MalformedURLException; import java.net.URL; import java.io.File; import java.util.Vector; import java.util.StringTokenizer; /** * Provides support for general manipulation of configuration fragments * related to classpath and fileset declarations. * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2002/07/03 19:08:54 $ */ class Fileset { //======================================================================= // static //======================================================================= public static File[] expandExtensions( Configuration conf ) { Vector vector = new Vector(); Configuration[] dirsets = conf.getChildren("dirset"); for( int i=0; i<dirsets.length; i++ ) { expandDirSetToVector( vector, dirsets[i] ); } return (File[]) vector.toArray( new File[ vector.size() ] ); } public static URL[] expandClasspath( Configuration conf ) { Vector vector = new Vector(); Configuration[] filesets = conf.getChildren("fileset"); for( int i=0; i<filesets.length; i++ ) { expandFileSetToVector( vector, filesets[i] ); } return (URL[]) vector.toArray( new URL[ vector.size() ] ); } public static URL[] expandFileSet( Configuration conf ) { Vector vector = new Vector(); expandFileSetToVector( vector, conf ); return (URL[]) vector.toArray( new URL[ vector.size() ] ); } private static void expandDirSetToVector( Vector vector, Configuration dirset ) { File base = new File( dirset.getAttribute("dir", System.getProperty("user.dir") ) ); if( !base.isDirectory() ) throw new IllegalArgumentException("Base dir does not refer to a directory in path: " + base ); Configuration[] includes = dirset.getChildren("include"); for( int i=0; i<includes.length; i++ ) { String name = includes[i].getAttribute("name", null ); if( name == null ) throw new IllegalArgumentException( "Include does not contain the name attribute: " + includes[i].getLocation() ); File file = new File( base, name ); if( file.isDirectory() ) { vector.add( file ); } else { throw new IllegalArgumentException( "Include dir does not refer to a directory: " + file + ", base: " + base ); } } } private static void expandFileSetToVector( Vector vector, Configuration conf ) { File base = new File( conf.getAttribute("dir", System.getProperty("user.dir") ) ); if( !base.isDirectory() ) throw new IllegalArgumentException("Base dir does not refer to a directory in path: " + base ); Configuration[] includes = conf.getChildren("include"); for( int i=0; i<includes.length; i++ ) { String name = includes[i].getAttribute("name", null ); if( name == null ) throw new IllegalArgumentException( "Include does not contain the name attribute: " + includes[i].getLocation() ); File file = new File( base, name ); if( !file.exists() ) throw new IllegalArgumentException( "Include references file that does not exist: " + includes[i].getLocation() ); try { vector.add( file.toURL() ); } catch( Throwable e ) { throw new IllegalArgumentException( "Could not convert include to a URL: " + includes[i].getLocation() ); } } } public static String[] splitPath( String path, String token ) { StringTokenizer tokenizer = new StringTokenizer( path, token ); Vector vector = new Vector(); while( tokenizer.hasMoreElements() ) { vector.add( tokenizer.nextToken() ); } return (String[]) vector.toArray( new String[ vector.size() ] ); } public static File[] expandPath( String[] path ) { Vector vector = new Vector(); for( int i=0; i<path.length; i++ ) { File file = new File( path[i] ); vector.add( file ); if( file.isDirectory() ) { expandDirectory( vector, file ); } } return (File[]) vector.toArray( new File[ vector.size() ] ); } private static void expandDirectory( Vector vector, File dir ) { if( !dir.isDirectory() ) return; final File[] files = dir.listFiles(); for( int i=0; i<files.length; i++ ) { File file = files[i]; vector.add( file ); if( file.isDirectory() ) { expandDirectory( vector, file ); } } } public static 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() ] ); } public static URL[] fileToURL( File[] files ) throws MalformedURLException { Vector vector = new Vector(); for( int i=0; i<files.length; i++ ) { vector.add( files[i].toURL() ); } return (URL[]) vector.toArray( new URL[ vector.size() ] ); } } 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Kernel.java Index: Kernel.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.merlin.kernel; /** * A service that provides support for the hosting of multiple containers. * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2002/07/03 19:08:54 $ */ public interface Kernel extends Container { } 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Main.java Index: Main.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.merlin.kernel; import java.io.InputStream; import java.io.File; import java.io.IOException; import java.net.URL; import java.net.JarURLConnection; import java.net.URLClassLoader; import java.util.List; import java.util.LinkedList; import java.util.Map; import java.util.Hashtable; import java.util.Properties; import java.util.Vector; import java.util.Iterator; import java.util.jar.Attributes; import java.util.jar.Manifest; import java.security.Policy; import java.io.FileInputStream; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; import org.apache.excalibur.configuration.ConfigurationUtil; import org.apache.avalon.framework.logger.Logger; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.logger.AvalonFormatter; import org.apache.avalon.framework.logger.LogKitLogger; import org.apache.avalon.framework.activity.Initializable; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.activity.Executable; import org.apache.avalon.framework.CascadingRuntimeException; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.DefaultConfiguration; import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.context.Contextualizable; import org.apache.avalon.framework.context.ContextException; import org.apache.avalon.framework.context.DefaultContext; import org.apache.avalon.framework.service.Serviceable; import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.DefaultServiceManager; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.Version; import org.apache.avalon.framework.ExceptionUtil; import org.apache.avalon.excalibur.extension.PackageRepository; import org.apache.avalon.excalibur.extension.Extension; import org.apache.avalon.excalibur.extension.OptionalPackage; import org.apache.avalon.excalibur.extension.DefaultPackageRepository; import org.apache.excalibur.containerkit.metainfo.ComponentDescriptor; import org.apache.excalibur.containerkit.metainfo.ComponentInfo; import org.apache.excalibur.containerkit.metainfo.ServiceDescriptor; import org.apache.excalibur.containerkit.metainfo.DependencyDescriptor; import org.apache.excalibur.containerkit.metainfo.ServiceDesignator; import org.apache.log.Hierarchy; import org.apache.log.Priority; import org.apache.log.output.io.StreamTarget; import org.apache.excalibur.merlin.registry.DefaultRegistry; /** * Application bootstrap. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2002/07/03 19:08:54 $ */ public class Main { //======================================================================= // static //======================================================================= private static final String DEFAULT_FORMAT = "[%7.7{priority}] (%{category}): %{message}\\n%{throwable}"; private static final Resources REZ = ResourceManager.getPackageResources( DefaultRegistry.class ); /** * Creation of a root type registry. */ public static void main( String[] args ) { final DefaultKernel kernel = new DefaultKernel(); // get a configuration object containing the kernel profile // from which we can establish the logger and extensions directory String path = null; Configuration config = null; if( args.length > 0 ) { path = args[0]; config = getProfile( new File( path ) ); } else { throw new RuntimeException("Missing kernel configuration path argument."); } // create a bootstrap logger - this needs to be replaced with // the Avalon Exvalibur Logkit package final Logger logger = getLogger( config ); DefaultContext context = new DefaultContext(); try { kernel.enableLogging( logger ); kernel.configure( config ); kernel.initialize( ); } catch( Throwable e ) { logger.error("Unexpected error while processing kernel lifecycle.", e); System.exit(0); } // // add a shutdown hook so we can stop services and target and invoke shutdown // Runtime.getRuntime().addShutdownHook( new Thread() { public void run() { kernel.shutdown(); } } ); // invoke the registry demo try { kernel.startup(); } catch( Throwable e ) { logger.error("Kernel startup failure.", e ); System.exit(0); } } private static Logger getLogger( Configuration config ) { // create an internal logger for the registry final Hierarchy hierarchy = createHierarchy( Priority.getPriorityForName( config.getChild("logger").getAttribute("priority","INFO") ) ); return new LogKitLogger( hierarchy.getLoggerFor( "" ) ); } private static Hierarchy createHierarchy( Priority priority ) { try { Hierarchy hierarchy = Hierarchy.getDefaultHierarchy(); hierarchy.setDefaultLogTarget( new StreamTarget( System.out, new AvalonFormatter( DEFAULT_FORMAT ) ) ); hierarchy.setDefaultPriority( priority ); return hierarchy; } catch( Throwable e ) { final String error = "Unexpected exception while creating bootstrap logger."; throw new CascadingRuntimeException( error, e ); } } private static Configuration getProfile( final File file ) { try { DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(); InputStream is = new FileInputStream( file ); if( is == null ) { throw new RuntimeException( "Could not load the configuration resource \"" + file + "\"" ); } return builder.build( is ); } catch( Throwable e ) { final String error = "Unable to create configuration from file: " + file; throw new CascadingRuntimeException( error, e ); } } } 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Resources.properties Index: Resources.properties =================================================================== xinfo-load=Creating ComponentInfo from {0}. xinfo-missing=XINFO resource unavailable for class "{0}". xinfo-parse-error=Error occured while parsing xinfo resource "{0}". xinfo-nocreate=Failed to create ComponentInfo from resource "{0}" (Reason: {1}). xinfo-props-error=Unable to construct attributes using key "{0}" (Reason: {1}). cinfo-nocreate=Failed to create ComponentDescriptor from resource "{0}" (Reason: {1}). cinfo-properties-error=Failed to create ComponentInfo attributes from resource "{0}" (Reason: {1}). sinfo-noname=Missing name attribute in service declaration from resource "{0}". sinfo-version=Bad service version in resource "(Reason: {0})". sinfo-nocreate=Failed to create ServiceInfo from resource "{0}" (Reason: {1}). dinfo-service-error="Could not create dependecy service delcaration (Reason: {0}). dinfo-nocreate="Could not create dependecy delcaration from resource "{0}" (Reason: {1}). missing.extension=Unable to locate an extension that is required by application.\n Extension Name: {0}\n Specification Vendor: {1}\n Specification Version: {2}\n Implementation Vendor: {3}\n Implementation Vendor-Id: {4}\n Implementation Version: {5}\n Implementation URL: {6} unsatisfied.extensions=Missing {0} extensions and thus can not build ClassLoader for application. bad-classpath-entry=There is a bad entry ("{0}") on classpath that made it impossible to load a manifest. available-extensions=Available extensions: {0} required-extensions=The list of required extensions for application includes: {0} optional-packages-added=The list of "Optional Packages" added to the application include: {0} classpath-entries=The list of classpath entrys for the application include: {0} 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/Verifiable.java Index: Verifiable.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE.txt file. */ package org.apache.excalibur.merlin.kernel; import org.apache.excalibur.containerkit.verifier.VerifyException; /** * A interface declaring operations related to type and assembly validation. * @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a> * @version $Revision: 1.1 $ $Date: 2002/07/03 19:08:54 $ */ public interface Verifiable { /** * Method invoked by a parent container to request type level validation of * the container. * * @exception ValidationException if a validation failure occurs */ void verify() throws VerifyException; } 1.1 jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/package.html Index: package.html =================================================================== <body> <p> The kernel package defines a top level {@link org.apache.excalibur.merlin.kernel.Kernel} that serves as a host to a root {@link org.apache.excalibur.merlin.kernel.Container} that provides support for container hierachy creation. The default kernel implementation handles the setup of the logging infrastructure, extension manager, and the root container. </p> <h3>Funtional Summary</h3> <ul> <li>Geneneric container architecture. <li>Hierachical container composition. </ul> <h3>Key Features</h3> <p>A primary objective of this container is to provide simple composition of applications and the management of service provission from parent to child containers with minimal administration overhead.</p> <ul> <li>Component-based architecture. <li>Deployment as a stand-alone application or as an embedeed component. <li>Fully configurable classpaths at the kernel and container levels. <li>Support for cascading startup and shutdown. <li>Protected classloader hierachy. <li>Graceful management of interupts. <li>Integral logging. </ul> <h3>Object Model</h3> <p>An container is primarily a component type manager. Actual type management is handled by an embedded {@link org.apache.excalibur.merlin.registry.Registry} and the associated default implementation {@link org.apache.excalibur.merlin.registry.DefaultRegistry}. In addition to component type support, the container provides a framework from the creation of container hierachies. Services established in a parent container are available as potential candidate suppliers to component providers in sibling containers. <h3>Package Structure (UML)</h3> <!--<p><img src=doc-files/kernel.gif border=0></p>--> </body>
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>