mcconnell 2002/07/12 05:04:56
Modified: assembly/src/java/org/apache/excalibur/merlin Container.java
Main.java
assembly/src/java/org/apache/excalibur/merlin/container
DefaultContainer.java DefaultContainer.xinfo
ProfileRegistry.java ProfileTable.java
Resources.properties package.html
assembly/src/java/org/apache/excalibur/merlin/kernel
ContainerClassLoader.java DefaultKernel.java
DefaultKernel.xinfo DefaultLoggerManager.java
DefaultProvider.java DependencyGraph.java
TypeRegistry.java package.html
Added: assembly/src/java/org/apache/excalibur/merlin/model
AbstractContainer.java Association.java
CategoryDescriptor.java ClasspathDescriptor.java
ComponentDescriptor.java ContainerDescriptor.java
DefaultProfile.java DirsetDescriptor.java
ExtensionsDescriptor.java FileTargetProvider.java
FilesetDescriptor.java IncludeDescriptor.java
KernelDescriptor.java LoggingDescriptor.java
Profile.java TargetDescriptor.java
TargetProvider.java package.html
assembly/src/java/org/apache/excalibur/merlin/model/builder
ContainerCreator.java KernelCreator.java
ProfileBuilder.java ProfileCreator.java
Resources.properties TypeManager.java
XMLContainerCreator.java XMLKernelCreator.java
XMLProfileCreator.java package.html
assembly/src/java/org/apache/excalibur/merlin/model/verifier
AssemblyVerifier.java MetaDataVerifier.java
Resources.properties package.html
Log:
rationalization
Revision Changes Path
1.2 +10 -2
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/Container.java
Index: Container.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/Container.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Container.java 12 Jul 2002 10:16:19 -0000 1.1
+++ Container.java 12 Jul 2002 12:04:54 -0000 1.2
@@ -8,7 +8,7 @@
package org.apache.excalibur.merlin;
-import org.apache.excalibur.merlin.meta.data.Profile;
+import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.meta.info.ServiceDesignator;
/**
@@ -27,6 +27,14 @@
* @return the set of potential supplier profile
*/
Profile[] getProviders( ServiceDesignator service );
+
+ /**
+ * Test if the container is managing a supplied profile.
+ * @param profile the profile
+ * @return TRUE if the profile is managed by the container.
+ */
+ public boolean contains( Profile profile );
+
}
1.2 +7 -7
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/Main.java
Index: Main.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/Main.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Main.java 12 Jul 2002 10:16:19 -0000 1.1
+++ Main.java 12 Jul 2002 12:04:54 -0000 1.2
@@ -61,12 +61,12 @@
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.ServiceDesignator;
-import org.apache.excalibur.merlin.meta.data.builder.XMLKernelCreator;
-import org.apache.excalibur.merlin.meta.data.KernelDescriptor;
-import org.apache.excalibur.merlin.meta.data.ClasspathDescriptor;
-import org.apache.excalibur.merlin.meta.data.ExtensionsDescriptor;
-import org.apache.excalibur.merlin.meta.data.LoggingDescriptor;
-import org.apache.excalibur.merlin.meta.data.ContainerDescriptor;
+import org.apache.excalibur.merlin.model.builder.XMLKernelCreator;
+import org.apache.excalibur.merlin.model.KernelDescriptor;
+import org.apache.excalibur.merlin.model.ClasspathDescriptor;
+import org.apache.excalibur.merlin.model.ExtensionsDescriptor;
+import org.apache.excalibur.merlin.model.LoggingDescriptor;
+import org.apache.excalibur.merlin.model.ContainerDescriptor;
import org.apache.excalibur.merlin.kernel.DefaultKernel;
import org.apache.excalibur.merlin.kernel.DefaultLoggerManager;
import org.apache.excalibur.merlin.kernel.ContainerClassLoader;
1.2 +277 -40
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/DefaultContainer.java
Index: DefaultContainer.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/DefaultContainer.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DefaultContainer.java 12 Jul 2002 10:17:20 -0000 1.1
+++ DefaultContainer.java 12 Jul 2002 12:04:54 -0000 1.2
@@ -18,6 +18,7 @@
import java.util.LinkedList;
import java.util.Hashtable;
import java.util.Properties;
+import java.util.ArrayList;
import java.util.Vector;
import java.util.Iterator;
import java.util.jar.Attributes;
@@ -57,15 +58,18 @@
import org.apache.avalon.excalibur.extension.OptionalPackage;
import org.apache.avalon.excalibur.extension.DefaultPackageRepository;
import org.apache.avalon.excalibur.logger.LoggerManager;
+import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.info.DefaultType;
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.ServiceDesignator;
import org.apache.excalibur.meta.verifier.VerifyException;
import org.apache.excalibur.merlin.meta.data.Profile;
+import org.apache.excalibur.merlin.meta.data.ComponentDescriptor;
import org.apache.excalibur.merlin.meta.data.ContainerDescriptor;
import org.apache.excalibur.merlin.meta.data.CategoryDescriptor;
-import org.apache.excalibur.merlin.container.Registry;
+import org.apache.excalibur.merlin.meta.data.verifier.AssemblyVerifier;
+import org.apache.excalibur.merlin.meta.data.verifier.MetaDataVerifier;
import org.apache.excalibur.merlin.kernel.ContainerClassLoader;
import org.apache.excalibur.merlin.kernel.DependencyGraph;
import org.apache.excalibur.merlin.kernel.DefaultProvider;
@@ -73,6 +77,7 @@
import org.apache.excalibur.merlin.Container;
import org.apache.excalibur.merlin.Verifiable;
import org.apache.excalibur.merlin.Manageable;
+import org.apache.excalibur.merlin.ResourceProvider;
import org.apache.log.Hierarchy;
import org.apache.log.Priority;
import org.apache.log.output.io.StreamTarget;
@@ -88,20 +93,56 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision$ $Date$
*/
-public class DefaultContainer extends Registry implements Container
+public class DefaultContainer extends AbstractLogEnabled implements
Container, Contextualizable, Initializable, Disposable, Startable
{
-
//=======================================================================
- // state
+ // static
//=======================================================================
/**
- * Configuration.
+ * 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";
+
+ /**
+ * Context key used to locate the application classloader.
*/
- //private Configuration m_config;
+ public static final String MAP_KEY = "map";
/**
- * The registry of embedded containers.
+ * Context key used to locate the logger manager.
+ */
+ public static final String LOG_MANAGER_KEY = "logging";
+
+ /**
+ * Context key used to locate the logger manager.
+ */
+ public static final String CATEGORY_PATH_KEY = "path";
+
+ /**
+ * Context key used to locate the resource provider.
+ */
+ public static final String PROVIDER_KEY = "provider";
+
+ /**
+ * Context key used to locate the logger manager.
+ */
+ public static final String CONTAINER_DESCRIPTOR_KEY = "descriptor";
+
+ private static final Resources REZ =
+ ResourceManager.getPackageResources( DefaultContainer.class );
+
+ //=======================================================================
+ // state
+ //=======================================================================
+
+ /**
+ * The list of embedded containers.
*/
private List m_containers = new LinkedList();
@@ -116,7 +157,7 @@
private DependencyGraph m_map;
- private DefaultProvider m_provider;
+ private ResourceProvider m_provider;
private DefaultLoggerManager m_logging;
@@ -124,6 +165,17 @@
private ContainerDescriptor m_descriptor;
+ /**
+ * The lifecycle helper to use to process startup and shudown of services.
+ */
+ private LifecycleHelper m_helper = new LifecycleHelper();
+
+ /**
+ * Internal class that maintains information about profile types managed
+ * by this container.
+ */
+ private ProfileRegistry m_profiles;
+
//=======================================================================
// Contextualizable
//=======================================================================
@@ -137,45 +189,19 @@
m_classloader = (ContainerClassLoader) context.get( CLASSLOADER_KEY
);
m_logging = (DefaultLoggerManager) context.get( LOG_MANAGER_KEY );
m_descriptor = (ContainerDescriptor) context.get(
CONTAINER_DESCRIPTOR_KEY );
-
+ m_map = (DependencyGraph) context.get( MAP_KEY );
+ m_provider = (ResourceProvider) context.get( PROVIDER_KEY );
try
{
m_parent = (Container) context.get( CONTAINER_KEY );
- super.contextualize( context );
}
catch( ContextException e )
{
// root container
-
- m_map = new DependencyGraph();
- m_provider = new DefaultProvider( m_classloader, m_logging );
- m_provider.enableLogging( getLogger() );
-
- DefaultContext dc = new DefaultContext( context );
- dc.put( MAP_KEY, m_map );
- dc.put( PROVIDER_KEY, m_provider );
-
- super.contextualize( dc );
}
}
//=======================================================================
- // Configurable
- //=======================================================================
-
- /**
- * Invoked by the container to establish the registry configuration.
- * @param config a component configuration
- */
-/*
- public void configure( Configuration config)
- {
- getLogger().debug("container configuration");
- super.configure( config );
- m_config = config;
- }
-*/
- //=======================================================================
// Initializable
//=======================================================================
@@ -191,8 +217,48 @@
public void initialize() throws Exception
{
getLogger().debug("initilization");
- super.initialize();
-
+ m_helper.enableLogging( getLogger().getChildLogger("lifecycle") );
+
+ //
+ // initiate profile creation
+ //
+
+ m_profiles = new ProfileRegistry(
+ m_descriptor, m_classloader, m_classloader, m_parent, m_map );
+ m_profiles.enableLogging( getLogger().getChildLogger( "profiles") );
+
+ //
+ // explicit component profile registration
+ //
+
+ getLogger().debug("explicit profile registration");
+ ComponentDescriptor[] children =
m_descriptor.getComponentDescriptors();
+ for( int i=0; i<children.length; i++ )
+ {
+ m_profiles.register( children[i] );
+ }
+
+ //
+ // packaged and implict profile registration
+ //
+
+ getLogger().debug("packaged and implicit profile registration");
+ Type[] types = m_classloader.getTypes();
+ for( int i=0; i<types.length; i++ )
+ {
+ m_profiles.register( types[i] );
+ }
+
+ try
+ {
+ getLogger().debug("profile assembly");
+ m_profiles.assembleProfiles();
+ }
+ catch( Throwable e )
+ {
+ final String error = "Assembly failure.";
+ throw new AssemblyException( error, e );
+ }
getLogger().debug("subsidiary container creation");
ContainerDescriptor[] containers = m_descriptor.getContainers();
@@ -215,7 +281,7 @@
*/
public void verify() throws VerifyException
{
- super.verify();
+ verifyContainer();
Iterator iterator = m_containers.iterator();
while( iterator.hasNext() )
{
@@ -224,6 +290,75 @@
}
//======================================================================
+ // Startable
+ //======================================================================
+
+ public void start() throws Exception
+ {
+ getLogger().debug("start");
+ Profile[] startup = m_map.getStartupGraph();
+ for( int i=0; i<startup.length; i++ )
+ {
+ Profile profile = startup[i];
+ if( this.contains( profile ) )
+ {
+ final String name = profile.getName();
+ try
+ {
+ if( getLogger().isDebugEnabled() )
+ getLogger().debug("starting: " + name );
+ m_helper.startup( name, profile, m_provider );
+ if( getLogger().isInfoEnabled() )
+ getLogger().info("started: " + name );
+ }
+ catch( LifecycleException le )
+ {
+ final String warning =
+ "Could not startup a service derived from profile: " +
profile;
+ getLogger().warn( warning, le );
+
+ // need to retract all profiles dependent on this profile
+ }
+ }
+ }
+ getLogger().debug("started");
+ }
+
+ public void stop()
+ {
+ getLogger().debug("stop");
+ Profile[] shutdown = m_map.getShutdownGraph();
+ for( int i=0; i<shutdown.length; i++ )
+ {
+ Profile profile = shutdown[i];
+ if( this.contains( profile ) )
+ {
+ final String name = profile.getName();
+ if( getLogger().isDebugEnabled() )
+ getLogger().debug("stopping: " + name );
+ Object object = m_provider.getSingletonInstance( profile );
+ if( object != null )
+ {
+ try
+ {
+ m_helper.shutdown( name, object );
+ m_provider.release( profile );
+ if( getLogger().isInfoEnabled() )
+ getLogger().info("stopped: " + name );
+ }
+ catch( LifecycleException le )
+ {
+ final String warning =
+ "Could not shutdown a service derived from
profile: " + profile;
+ getLogger().warn( warning, le );
+ }
+ }
+ }
+ }
+ getLogger().debug("stopped");
+ }
+
+ //======================================================================
// Manageable
//======================================================================
@@ -265,8 +400,110 @@
}
//=======================================================================
+ // Container
+ //=======================================================================
+
+ public boolean contains( Profile profile )
+ {
+ return m_profiles.isLocalProfile( profile );
+ }
+
+ public Profile[] getProviders( ServiceDesignator designator )
+ {
+ Profile[] local = m_profiles.getProviders( designator );
+ if( m_parent != null )
+ {
+ Profile[] facilities = m_parent.getProviders( designator );
+ ArrayList list = new ArrayList();
+ for( int i=0; i<local.length; i++ )
+ {
+ list.add( local[i] );
+ }
+ for( int i=0; i<facilities.length; i++ )
+ {
+ list.add( facilities[i] );
+ }
+ return (Profile[]) list.toArray( new Profile[0] );
+ }
+ return local;
+ }
+
+ //=======================================================================
+ // Disposable
+ //=======================================================================
+
+ /**
+ * Disposal of this component.
+ */
+ public void dispose()
+ {
+ getLogger().debug("dispose");
+ }
+
+ //=======================================================================
// private
//=======================================================================
+
+ /**
+ * Internal verification of the container.
+ *
+ * @exception ValidationException if a validation failure occurs
+ */
+ private void verifyContainer() throws VerifyException
+ {
+ getLogger().debug("verify");
+
+ Profile[] profiles = m_map.getStartupGraph();
+ MetaDataVerifier mdv = new MetaDataVerifier();
+ for( int i=0; i<profiles.length; i++ )
+ {
+ try
+ {
+ mdv.verifyType( profiles[i], m_classloader );
+ }
+ catch( Throwable e )
+ {
+ getLogger().error("verification failure", e );
+ }
+ }
+
+ AssemblyVerifier verifier = new AssemblyVerifier();
+ verifier.enableLogging( getLogger().getChildLogger("verifier") );
+ getLogger().debug("commencing assembly verification");
+ verifier.verifyAssembly( profiles );
+ listProfiles( profiles );
+ }
+
+ private void listProfiles( Profile[] profiles )
+ {
+ getLogger().debug("listing profiles");
+ List reported = new LinkedList();
+ for( int i=0; i<profiles.length; i++ )
+ {
+ listProfile( i+1, profiles[i], m_map, reported );
+ }
+ }
+
+ private void listProfile( int n, Profile profile, DependencyGraph map,
List reported )
+ {
+ if( !reported.contains( profile ) )
+ {
+ reported.add( profile );
+ getLogger().debug( "" + n + ": " + profile.toString() );
+ Profile[] suppliers = map.getProviderGraph( profile );
+ for( int j=0; j<suppliers.length; j++ )
+ {
+ Profile supplier = suppliers[j];
+ getLogger().debug(" supplier: " + supplier );
+ }
+ Profile[] consumers = map.getConsumerGraph( profile );
+ for( int j=0; j<consumers.length; j++ )
+ {
+ Profile consumer = consumers[j];
+ getLogger().debug(" consumer: " + consumer.getName() );
+ }
+ }
+ }
private DefaultContainer createContainer( ContainerDescriptor descriptor
) throws Exception
{
1.2 +5 -0
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/DefaultContainer.xinfo
Index: DefaultContainer.xinfo
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/DefaultContainer.xinfo,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DefaultContainer.xinfo 12 Jul 2002 10:17:20 -0000 1.1
+++ DefaultContainer.xinfo 12 Jul 2002 12:04:54 -0000 1.2
@@ -19,6 +19,11 @@
<context>
<entry key="classloader"
type="org.apache.excalibur.merlin.kernel.ContainerClassLoader"
optional="false"/>
+ <entry key="logging"
type="org.apache.excalibur.merlin.kernel.DefaultLoggerManager"
optional="false"/>
+ <entry key="provider"
type="org.apache.excalibur.merlin.kernel.DefaultProvider" optional="false"/>
+ <entry key="descriptor"
type="org.apache.excalibur.merlin.model.ContainerDescriptor" optional="false"/>
+ <entry key="map"
type="org.apache.excalibur.merlin.kernel.DependencyGraph" optional="false"/>
+ <entry key="container" type="org.apache.excalibur.merlin.Container"
optional="true"/>
</context>
<services>
1.2 +7 -7
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/ProfileRegistry.java
Index: ProfileRegistry.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/ProfileRegistry.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ProfileRegistry.java 12 Jul 2002 10:17:20 -0000 1.1
+++ ProfileRegistry.java 12 Jul 2002 12:04:54 -0000 1.2
@@ -29,12 +29,12 @@
import org.apache.excalibur.meta.info.builder.TypeBuilder;
import org.apache.excalibur.meta.verifier.ComponentVerifier;
import org.apache.excalibur.configuration.ConfigurationUtil;
-import org.apache.excalibur.merlin.meta.data.builder.TypeManager;
-import org.apache.excalibur.merlin.meta.data.Profile;
-import org.apache.excalibur.merlin.meta.data.ContainerDescriptor;
-import org.apache.excalibur.merlin.meta.data.ComponentDescriptor;
-import org.apache.excalibur.merlin.meta.data.builder.ProfileBuilder;
-import org.apache.excalibur.merlin.meta.data.Selector;
+import org.apache.excalibur.merlin.model.builder.TypeManager;
+import org.apache.excalibur.merlin.model.Profile;
+import org.apache.excalibur.merlin.model.ContainerDescriptor;
+import org.apache.excalibur.merlin.model.ComponentDescriptor;
+import org.apache.excalibur.merlin.model.builder.ProfileBuilder;
+import org.apache.excalibur.merlin.Selector;
import org.apache.excalibur.merlin.kernel.DependencyGraph;
import org.apache.excalibur.merlin.Container;
1.2 +2 -2
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/ProfileTable.java
Index: ProfileTable.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/ProfileTable.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ProfileTable.java 12 Jul 2002 10:17:20 -0000 1.1
+++ ProfileTable.java 12 Jul 2002 12:04:54 -0000 1.2
@@ -13,7 +13,7 @@
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.excalibur.meta.info.ServiceDesignator;
import org.apache.excalibur.meta.info.Type;
-import org.apache.excalibur.merlin.meta.data.Profile;
+import org.apache.excalibur.merlin.model.Profile;
/**
* Internal table that holds references to the available component types
1.2 +3 -0
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/Resources.properties
Index: Resources.properties
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/Resources.properties,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Resources.properties 12 Jul 2002 10:17:20 -0000 1.1
+++ Resources.properties 12 Jul 2002 12:04:54 -0000 1.2
@@ -18,3 +18,6 @@
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}
+
+lifecycle.stage.notice=Component named "{0}" is passing through the
{1,choice,0#Creation|1#Logger
initialization|2#Contextualization|3#Composing|4#Configuration|5#Parameterizing|6#Initialization|7#Starting|8#Stopping|9#Disposing|10#Destruction}
stage.
+lifecycle.fail.error=Component named "{0}" failed to pass through the
{1,choice,0#Creation|1#Logger
initialization|2#Contextualization|3#Composing|4#Configuration|5#Parameterizing|6#Initialization|7#Starting|8#Stopping|9#Disposing|10#Destruction}
stage. (Reason: {2}).
1.2 +1 -1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/package.html
Index: package.html
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/container/package.html,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- package.html 12 Jul 2002 10:17:20 -0000 1.1
+++ package.html 12 Jul 2002 12:04:54 -0000 1.2
@@ -18,7 +18,7 @@
</ul>
<h3>Object Model</h3>
-<p>The primary service is a type [EMAIL PROTECTED]
org.apache.excalibur.merlin.container.Registry}. The registry acts as a
component [EMAIL PROTECTED] org.apache.excalibur.meta.info.Type} repository and
[EMAIL PROTECTED] org.apache.excalibur.merlin.meta.data.Profile} manager. Each
component type represents a concrete component implementation class. For each
component type, the container associates at least one instantiation [EMAIL
PROTECTED] org.apache.excalibur.merlin.meta.data.Profile}. A profile is either
a default profile generated by the registry based on meta-information derived
from the type, or, an explicit profile declared by the component assembler via
the registry configuration. Multiple profiles for a particular component type
can coexist in the same registry.
+<p>The primary service is a type [EMAIL PROTECTED]
org.apache.excalibur.merlin.container.Registry}. The registry acts as a
component [EMAIL PROTECTED] org.apache.excalibur.meta.info.Type} repository and
[EMAIL PROTECTED] org.apache.excalibur.merlin.model.Profile} manager. Each
component type represents a concrete component implementation class. For each
component type, the container associates at least one instantiation [EMAIL
PROTECTED] org.apache.excalibur.merlin.model.Profile}. A profile is either a
default profile generated by the registry based on meta-information derived
from the type, or, an explicit profile declared by the component assembler via
the registry configuration. Multiple profiles for a particular component type
can coexist in the same registry.
<h3>Package Structure (UML)</h3>
1.4 +240 -47
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/ContainerClassLoader.java
Index: ContainerClassLoader.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/ContainerClassLoader.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ContainerClassLoader.java 4 Jul 2002 09:01:34 -0000 1.3
+++ ContainerClassLoader.java 12 Jul 2002 12:04:54 -0000 1.4
@@ -29,14 +29,27 @@
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.activity.Initializable;
+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.activity.Initializable;
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.avalon.excalibur.extension.DefaultPackageRepository;
-import org.apache.excalibur.merlin.registry.*;
+import org.apache.excalibur.meta.info.Type;
+import org.apache.excalibur.meta.info.ServiceDesignator;
+import org.apache.excalibur.merlin.model.ClasspathDescriptor;
+import org.apache.excalibur.merlin.model.FilesetDescriptor;
+import org.apache.excalibur.merlin.model.IncludeDescriptor;
+import org.apache.excalibur.merlin.model.ExtensionsDescriptor;
+import org.apache.excalibur.merlin.model.DirsetDescriptor;
+import org.apache.excalibur.merlin.model.builder.TypeManager;
/**
* Classloader for an assembly of components.
@@ -45,7 +58,8 @@
* @version $Revision$ $Date$
*/
-public class ContainerClassLoader extends URLClassLoader implements
LogEnabled
+public class ContainerClassLoader extends URLClassLoader
+ implements LogEnabled, Contextualizable, Initializable, TypeManager
{
//===================================================================
@@ -55,6 +69,9 @@
private static final Resources REZ =
ResourceManager.getPackageResources( ContainerClassLoader.class );
+ public static final String EXTENSIONS_DESCRIPTOR_KEY = "extensions";
+ public static final String CLASSPATH_DESCRIPTOR_KEY = "classpath";
+
//===================================================================
// state
//===================================================================
@@ -70,60 +87,121 @@
private Logger m_logger;
+ private ExtensionsDescriptor m_extensions;
+
+ private ClasspathDescriptor m_classpath;
+
+ private TypeRegistry m_types;
+
//===================================================================
// constructor
//===================================================================
- ContainerClassLoader( ClassLoader parent, Configuration classpath,
Logger logger )
+ public ContainerClassLoader( )
{
- this( null, parent, classpath, logger );
+ super( new URL[ 0 ], Thread.currentThread().getContextClassLoader()
);
}
- ContainerClassLoader(
- PackageRepository repository, ClassLoader parent, Configuration
classpath, Logger logger )
+ public ContainerClassLoader( ClassLoader parent )
{
super( new URL[ 0 ], parent );
+ }
+
+ //===================================================================
+ // LogEnabled
+ //===================================================================
+
+ public void enableLogging( Logger logger )
+ {
m_logger = logger;
- if( repository != null )
- m_manager = new PackageManager( repository );
- addClasspath( classpath );
}
- public void addClasspath( Configuration classpath )
+ public Logger getLogger()
+ {
+ return m_logger;
+ }
+
+ //=======================================================================
+ // Contextualizable
+ //=======================================================================
+
+ /**
+ * Invoked by the bootstrap process to supply to kernel defintion.
+ * @param context the context object containing the inital parameters
+ * @exception ContextException if the supplied does not contain a
DESCRIPTOR_KEY value
+ */
+ public void contextualize( Context context ) throws ContextException
{
+ getLogger().debug( "contextualize" );
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() );
- }
+ m_extensions = (ExtensionsDescriptor) context.get(
EXTENSIONS_DESCRIPTOR_KEY );
}
- catch( Throwable e )
+ catch( ContextException e )
+ {
+ // ignore - optional context element
+ }
+
+ try
{
- final String error = "Unexpected exception while creating
classloader";
- throw new RegistryRuntimeException( error, e );
+ m_classpath = (ClasspathDescriptor) context.get(
CLASSPATH_DESCRIPTOR_KEY );
+ }
+ catch( ContextException e )
+ {
+ // ignore - optional context element
}
}
- //===================================================================
- // LogEnabled
- //===================================================================
+ //=======================================================================
+ // Initializable
+ //=======================================================================
- public void enableLogging( Logger logger )
+ public void initialize() throws Exception
{
- m_logger = logger;
+ getLogger().debug("initilize");
+
+ m_types = new TypeRegistry( this );
+ m_types.enableLogging( getLogger().getChildLogger( "types" ) );
+
+ if( m_extensions != null )
+ initializeExtensions();
+ if( m_classpath != null )
+ initializeClasspath();
}
- public Logger getLogger()
+ private void initializeExtensions() throws Exception
{
- return m_logger;
+ getLogger().debug( "initializing extensions" );
+ ArrayList list = new ArrayList();
+ File dir = new File( System.getProperty("user.dir") );
+ DirsetDescriptor[] dirs = m_extensions.getDirsetDescriptors();
+ for( int i=0; i<dirs.length; i++ )
+ {
+ DirsetDescriptor descriptor = dirs[i];
+ File base = new File( dir, descriptor.getBaseDirectory() );
+ IncludeDescriptor[] includes =
descriptor.getIncludeDescriptors();
+ for( int j=0; j<includes.length; j++ )
+ {
+ File include = new File( base, includes[j].getFile() );
+ if( include.isDirectory() )
+ {
+ list.add( include );
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Include dir does not refer to a directory: " + include
);
+ }
+ }
+ }
+ File[] files = (File[]) list.toArray( new File[0] );
+ PackageRepository repository = new DefaultPackageRepository( files );
+ m_manager = new PackageManager( repository );
+ }
+
+ private void initializeClasspath() throws Exception
+ {
+ addClasspath( m_classpath );
}
//===================================================================
@@ -131,28 +209,143 @@
//===================================================================
/**
- *
+ * Add a URL to the classpath.
+ * @param url the URL to add to the classpath
*/
protected void addURL( URL url )
{
- try
+ super.addURL( url );
+ String[] entries = getBlocksEntries( url );
+ for( int j=0; j<entries.length; j++ )
{
- super.addURL( url );
- getLogger().debug("scanning: " + url );
- String[] entries = getBlocksEntries( url );
- for( int i=0; i<entries.length; i++ )
+ getLogger().debug("located: " + entries[j] );
+ String classname = entries[j].replace('/','.');
+ try
{
- getLogger().debug("component: " + entries[i] );
- m_blocks.add( entries[i] );
+ m_types.register( classname );
+ }
+ catch( Throwable e )
+ {
+ final String warning = "Ignoring component: " + classname ;
+ getLogger().warn( warning, e );
}
}
- catch( Throwable e )
+ }
+
+ //===================================================================
+ // TypeManager
+ //===================================================================
+
+ //#######################################//
+ // Need to change this to protected //
+ //#######################################//
+
+ /**
+ * Add classes to the manager declared within a classpath structure.
+ * @param classpath the classpath descriptor
+ * @exception Exception if an exception occurs during class loading
+ */
+ public void addClasspath( ClasspathDescriptor classpath ) throws
Exception
+ {
+
+ getLogger().debug( "adding classpath" );
+ ArrayList list = new ArrayList();
+ File dir = new File( System.getProperty("user.dir") );
+ FilesetDescriptor[] dirs = classpath.getFilesetDescriptors();
+ for( int i=0; i<dirs.length; i++ )
+ {
+ FilesetDescriptor descriptor = dirs[i];
+ File base = new File( dir, descriptor.getBaseDirectory() );
+ IncludeDescriptor[] includes =
descriptor.getIncludeDescriptors();
+ for( int j=0; j<includes.length; j++ )
+ {
+ File include = new File( base, includes[j].getFile() );
+ list.add( include.toURL() );
+ }
+ }
+ URL[] urls = (URL[]) list.toArray( new URL[0] );
+ for( int i = 0; i < urls.length; i++ )
+ {
+ getLogger().info("adding: " + urls[i] );
+ addURL( urls[i] );
+ }
+ String[] path = urlsToStrings( urls );
+ final File[] extensions = getOptionalPackagesFor( path );
+ for( int i = 0; i < extensions.length; i++ )
+ {
+ URL url = extensions[ i ].toURL();
+ getLogger().info("extension: " + extensions[ i ].toURL() );
+ addURL( url );
+ }
+ getLogger().debug( "classpath addition complete" );
+
+ }
+
+ private String[] urlsToStrings( URL[] urls )
+ {
+ Vector vector = new Vector();
+ for( int i=0; i<urls.length; i++ )
{
- throw new CascadingRuntimeException(
- "Unexpected error while attempting to add classloader URL: " +
url, e );
+ vector.add( urls[i].toString() );
}
+ return (String[]) vector.toArray( new String[ vector.size() ] );
}
+ /**
+ * Resolve a [EMAIL PROTECTED] Type} from a classname.
+ *
+ * @param classname the component type
+ * @return the component type
+ */
+ public Type lookup( String classname ) throws Exception
+ {
+ return m_types.lookup( classname );
+ }
+
+ /**
+ * Register a potential supplier component type. The implementation will
+ * create a component type instance for the entry if not already known
and
+ * return the existing or new instance to the invoking client.
+ *
+ * @param classname the component class name
+ * @return the component type
+ */
+ public Type register( String classname ) throws Exception
+ {
+ System.out.println("classname: " + classname );
+ System.out.println("types: " + m_types);
+
+ return m_types.register( classname );
+ }
+
+ /**
+ * Returns the set of component types know to the registry.
+ * @return the set of component types registered with the registry
+ */
+ public Type[] getTypes()
+ {
+ return m_types.getTypes( );
+ }
+
+ /**
+ * Returns the set of component types know to the registry that are
capable of
+ * supporting the supplied service.
+ * @return the set of candidate component types
+ */
+ public Type[] getTypes( ServiceDesignator service )
+ {
+ return m_types.getTypes( service );
+ }
+
+ /**
+ * Returns a registered component type.
+ * @return the component type from the registry or null if the type is
unknown
+ */
+ public Type getType( String classname )
+ {
+ return m_types.getType( classname );
+ }
+
//===================================================================
// ClassLoader extensions
//===================================================================
@@ -184,10 +377,10 @@
* 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
+ * @exception KernelRuntimeException if a general exception occurs
*/
private String[] getBlocksEntries( URL base )
- throws RegistryRuntimeException
+ throws KernelRuntimeException
{
Vector vector = new Vector();
try
@@ -217,12 +410,12 @@
catch( IOException e )
{
final String error = "IO exception while attempt to read block
manifest.";
- throw new RegistryRuntimeException( error, e );
+ throw new KernelRuntimeException( error, e );
}
catch( Throwable e )
{
final String error = "Unexpected exception while inspecting
manifest on file: ";
- throw new RegistryRuntimeException( error + base, e );
+ throw new KernelRuntimeException( error + base, e );
}
finally
{
1.10 +98 -44
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.java
Index: DefaultKernel.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- DefaultKernel.java 9 Jul 2002 10:59:35 -0000 1.9
+++ DefaultKernel.java 12 Jul 2002 12:04:54 -0000 1.10
@@ -63,7 +63,14 @@
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.ServiceDesignator;
-import org.apache.excalibur.meta.data.Profile;
+import org.apache.excalibur.merlin.model.KernelDescriptor;
+import org.apache.excalibur.merlin.model.DirsetDescriptor;
+import org.apache.excalibur.merlin.model.Profile;
+import org.apache.excalibur.merlin.model.ContainerDescriptor;
+import org.apache.excalibur.merlin.model.CategoryDescriptor;
+import org.apache.excalibur.merlin.model.builder.TypeManager;
+import org.apache.excalibur.merlin.container.DefaultContainer;
+import org.apache.excalibur.merlin.Kernel;
/**
* Default kernel implementation.
@@ -72,32 +79,46 @@
* @version $Revision$ $Date$
*/
public class DefaultKernel extends AbstractLogEnabled
- implements Kernel, Configurable, Initializable
+ implements Kernel, Contextualizable, Initializable
{
+ //=======================================================================
+ // static
+ //=======================================================================
+
+ public static final String ROOT_CONTAINER_DESCRIPTOR_KEY = "descriptor";
+ public static final String CLASSLOADER_KEY = "classloader";
+ public static final String LOG_MANAGER_KEY = "logmanager";
//=======================================================================
// state
//=======================================================================
- private Configuration m_config;
-
- private DefaultContainer m_container = new DefaultContainer();
+ private DefaultContainer m_container;
private boolean m_verified = false;
- private LoggerManager m_manager;
+ private DefaultLoggerManager m_logging;
+
+ private ContainerDescriptor m_descriptor;
+
+ private boolean m_initialized = false;
+
+ private ClassLoader m_classloader;
//=======================================================================
- // Configurable
+ // Contextualizable
//=======================================================================
/**
- * Invoked by the container to establish the registry configuration.
- * @param config a component configuration
+ * Invoked by the bootstrap process to supply to kernel defintion.
+ * @param context the context object containing the inital parameters
+ * @exception ContextException if the supplied does not contain a
DESCRIPTOR_KEY value
*/
- public void configure( Configuration config)
+ public void contextualize( Context context ) throws ContextException
{
- m_config = config;
+ m_descriptor = (ContainerDescriptor) context.get(
ROOT_CONTAINER_DESCRIPTOR_KEY );
+ m_classloader = (ClassLoader) context.get( CLASSLOADER_KEY );
+ m_logging = (DefaultLoggerManager) context.get( LOG_MANAGER_KEY );
}
//=======================================================================
@@ -106,28 +127,70 @@
public void initialize() throws Exception
{
- m_manager = createLoggingManager();
- Logger logger = m_manager.getLoggerForCategory("kernel") ;
- enableLogging( logger );
-
- final ContainerClassLoader loader = new ContainerClassLoader(
- new DefaultPackageRepository(
- Fileset.expandExtensions(
- m_config.getChild( "extensions" )
- )
- ),
- Thread.currentThread().getContextClassLoader(),
- m_config.getChild("container").getChild("classpath"),
- getLogger().getChildLogger( "loader" )
- );
+ getLogger().debug( "initialize" );
+ //
+ // root container criteria
+ //
+
+ CategoryDescriptor loggers = m_descriptor.getCategoryDescriptor();
+ m_logging.addCategories( loggers );
+
+ //
+ // classloader setup
+ //
+
+ getLogger().debug( "root container classloader creation" );
+ final ContainerClassLoader loader = new ContainerClassLoader(
m_classloader );
try
{
- DefaultContext context = new DefaultContext();
- context.put( DefaultContainer.CLASSLOADER_KEY, loader );
- m_container.enableLogging(
getLogger().getChildLogger("container") );
+ loader.enableLogging( getLogger().getChildLogger( "loader" ) );
+ DefaultContext loaderContext = new DefaultContext();
+ loaderContext.put(
+ ContainerClassLoader.CLASSPATH_DESCRIPTOR_KEY,
+ m_descriptor.getClasspathDescriptor() );
+ loaderContext.makeReadOnly();
+ loader.contextualize( loaderContext );
+ loader.initialize();
+ }
+ catch( Throwable e )
+ {
+ final String error = "Error during root container classloader
creation.";
+ if( getLogger() != null )
+ getLogger().error( error, e );
+ throw new KernelException( error, e );
+ }
+
+ //
+ // provider setup
+ //
+
+ DefaultProvider provider = new DefaultProvider( loader, m_logging );
+ provider.enableLogging( getLogger().getChildLogger( "provider" ) );
+
+ //
+ // container context creation
+ //
+
+ getLogger().debug( "root container context creation" );
+ DefaultContext context = new DefaultContext();
+ context.put( DefaultContainer.CLASSLOADER_KEY, loader );
+ context.put( DefaultContainer.LOG_MANAGER_KEY, m_logging );
+ context.put( DefaultContainer.CONTAINER_DESCRIPTOR_KEY, m_descriptor
);
+ context.put( DefaultContainer.MAP_KEY, new DependencyGraph() );
+ context.put( DefaultContainer.PROVIDER_KEY, provider );
+ context.makeReadOnly();
+
+ //
+ // container instantiation
+ //
+
+ getLogger().debug( "root container instantiation" );
+ try
+ {
+ m_container = new DefaultContainer();
+ m_container.enableLogging( m_logging.getLoggerForCategory(
m_descriptor.getName() ) );
m_container.contextualize( context );
- m_container.configure( m_config.getChild("container" ) );
m_container.initialize( );
m_container.verify();
}
@@ -138,6 +201,9 @@
getLogger().error( error, e );
throw new KernelException( error, e );
}
+
+ m_initialized = true;
+
}
//=======================================================================
@@ -146,6 +212,7 @@
public void startup() throws Exception
{
+ if( !m_initialized ) return;
//listProfiles();
if( getLogger().isInfoEnabled() )
getLogger().info("startup");
@@ -164,22 +231,9 @@
public void shutdown()
{
+ if( !m_initialized ) return;
if( getLogger().isInfoEnabled() )
getLogger().info("shutdown");
m_container.shutdown();
- }
-
- //=======================================================================
- // internals
- //=======================================================================
-
- private LoggerManager createLoggingManager() throws Exception
- {
- final File home = new File( System.getProperty( "user.dir" ) );
- final Configuration config = m_config.getChild( "logging" );
- final DefaultLoggerManager manager = new DefaultLoggerManager(
- home, config );
- manager.initialize( );
- return manager;
}
}
1.4 +7 -1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.xinfo
Index: DefaultKernel.xinfo
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultKernel.xinfo,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- DefaultKernel.xinfo 4 Jul 2002 09:01:35 -0000 1.3
+++ DefaultKernel.xinfo 12 Jul 2002 12:04:54 -0000 1.4
@@ -17,9 +17,15 @@
<version>1.0</version>
</component>
+ <context>
+ <entry key="classloader"
type="org.apache.excalibur.merlin.kernel.ContainerClassLoader"
optional="false"/>
+ <entry key="logging"
type="org.apache.excalibur.merlin.kernel.DefaultLoggerManager"
optional="false"/>
+ <entry key="descriptor"
type="org.apache.excalibur.merlin.model.KernelDescriptor" optional="false"/>
+ </context>
+
<services>
<service>
- <service-ref type="org.apache.excalibur.merlin.kernel.Kernel"
version="1.0"/>
+ <service-ref type="org.apache.excalibur.merlin.Kernel" version="1.0"/>
</service>
</services>
1.2 +149 -141
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultLoggerManager.java
Index: DefaultLoggerManager.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultLoggerManager.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DefaultLoggerManager.java 9 Jul 2002 10:59:35 -0000 1.1
+++ DefaultLoggerManager.java 12 Jul 2002 12:04:54 -0000 1.2
@@ -13,7 +13,6 @@
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.excalibur.logger.LoggerManager;
-import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
@@ -29,6 +28,11 @@
import org.apache.log.Priority;
import org.apache.log.output.io.FileTarget;
import org.apache.log.output.io.StreamTarget;
+import org.apache.excalibur.merlin.model.CategoryDescriptor;
+import org.apache.excalibur.merlin.model.TargetDescriptor;
+import org.apache.excalibur.merlin.model.LoggingDescriptor;
+import org.apache.excalibur.merlin.model.TargetProvider;
+import org.apache.excalibur.merlin.model.FileTargetProvider;
/**
* A <code>LoggerManager</code> that supports a verifiable logging hierarchy
creation directive.
@@ -37,9 +41,12 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Eung-ju Park</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a>
*/
-class DefaultLoggerManager
- implements LoggerManager, Initializable
+public class DefaultLoggerManager
+ implements LoggerManager
{
+
+ public static final String DEFAULT_PRIORITY = "INFO";
+
public static final String HOME_KEY = "app.home";
private static final Resources REZ =
@@ -56,7 +63,7 @@
/**
* log hierarchy.
*/
- private Hierarchy m_logHierarchy = new Hierarchy();
+ private Hierarchy m_logHierarchy;
/**
* default logger
@@ -71,12 +78,13 @@
/**
* the default priority if undefined
*/
- private String m_defaultPriority = "INFO";
+ private String m_priority = "INFO";
- /**
- * the supplied configuration
- */
- private Configuration m_config;
+ private final HashMap m_targets = new HashMap();
+
+ private DefaultLoggerManager m_parent;
+
+ private String m_category;
//===============================================================
// constructor
@@ -84,132 +92,120 @@
/**
* Creation of a new LoggerManager.
- * @param base the base directory against which file targets are
- * logicaly created
- * @param config the logging configuration
+ * @param descriptor the logging system description
+ * @exception Exception is an error occurs
*/
- public DefaultLoggerManager( File base, Configuration config )
+ public DefaultLoggerManager( final LoggingDescriptor descriptor ) throws
Exception
{
- m_baseDirectory = base;
- m_config = config;
- }
- //===============================================================
- // Initializable
- //===============================================================
+ //
+ // setup the hierarchy, default logging target, and default priority
+ //
- /**
- * Initialization of the logging manager.
- * @exception Exception if an error furing the initialization process
occurs
- */
- public void initialize( ) throws Exception
- {
- m_defaultPriority = m_config.getAttribute("priority", "INFO" );
- Priority priority = Priority.getPriorityForName(
- m_defaultPriority
- );
m_stream = new StreamTarget( System.out, new AvalonFormatter(
DEFAULT_FORMAT ) );
+ m_baseDirectory = new File( System.getProperty("user.dir") );
+ m_logHierarchy = new Hierarchy();
getHierarchy().setDefaultLogTarget( m_stream );
- getHierarchy().setDefaultPriority( priority );
+ m_targets.put( descriptor.getTarget(), m_stream );
+ getHierarchy().setDefaultPriority(
+ Priority.getPriorityForName( descriptor.getPriority() ) );
- final Configuration[] targets = m_config.getChildren( "target" );
- final HashMap targetSet = configureTargets( targets );
- final Configuration[] categories = m_config.getChildren( "category"
);
- configureCategories( categories, targetSet );
- }
+ TargetDescriptor[] targets = descriptor.getTargetDescriptors();
+ for( int i=0; i<targets.length; i++ )
+ {
+ addTarget( targets[i] );
+ }
- //===============================================================
- // LoggerManager
- //===============================================================
+ addCategories( descriptor.getCategoryDescriptor() );
+ }
- /**
- * Return the Logger for the specified category.
- */
- public org.apache.avalon.framework.logger.Logger getLoggerForCategory(
final String category )
+ public void addCategories( CategoryDescriptor descriptor )
{
- return new LogKitLogger( getHierarchy().getLoggerFor( category ) );
+ addSingleCategory( descriptor );
+ CategoryDescriptor[] categories = descriptor.getCategories();
+ for( int i=0; i<categories.length; i++ )
+ {
+ addCategories( categories[i] );
+ }
}
- /**
- * Return the default Logger. This is the same
- * as getting the Logger for the "" category.
- */
- public org.apache.avalon.framework.logger.Logger getDefaultLogger( )
+ private Logger addSingleCategory( CategoryDescriptor descriptor )
{
- if( m_logger == null )
- m_logger = getLoggerForCategory("");
- return m_logger;
- }
+ final String name = descriptor.getPath();
+ final String priority = descriptor.getPriority();
+ final String target = descriptor.getTarget();
+ final String path = descriptor.getPath();
- //===============================================================
- // internals
- //===============================================================
+ final Priority priorityValue = Priority.getPriorityForName( priority
);
+ if( !priorityValue.getName().equals( priority ) )
+ {
+ final String message = REZ.getString( "unknown-priority",
priority, name );
+ throw new IllegalArgumentException( message );
+ }
- private Hierarchy getHierarchy()
+ String category = name;
+ if( category == null )
+ category = "";
+
+ final Logger logger = getHierarchy().getLoggerFor( category );
+
+ logger.setPriority( priorityValue );
+ final LogTarget logTarget = (LogTarget) m_targets.get(
descriptor.getTarget() );
+ if( logTarget != null )
+ logger.setLogTargets( new LogTarget[]{logTarget} );
+
+ if( getDefaultLogger().isDebugEnabled() )
+ {
+ final String message =
+ REZ.getString( "category-create", category, target,
priorityValue.getName() );
+ getDefaultLogger().debug( message );
+ }
+ return logger;
+ }
+
+ private void addTarget( TargetDescriptor target ) throws Exception
{
- return m_logHierarchy;
+ File base = new File( System.getProperty("user.dir") );
+ final String name = target.getName();
+ TargetProvider provider = target.getProvider();
+ if( provider instanceof FileTargetProvider )
+ {
+ FileTargetProvider fileProvider = (FileTargetProvider) provider;
+ String filename = fileProvider.getLocation();
+ final AvalonFormatter formatter = new AvalonFormatter(
DEFAULT_FORMAT );
+ try
+ {
+ File file = new File( base, filename );
+ FileTarget logTarget = new FileTarget(
file.getAbsoluteFile(), false, formatter );
+ m_targets.put( name, logTarget );
+ }
+ catch( final IOException ioe )
+ {
+ final String message =
+ REZ.getString( "target.nocreate", name, filename,
ioe.getMessage() );
+ throw new KernelException( message, ioe );
+ }
+ }
+ else
+ {
+ final String error =
+ "Unrecognized logging provider: " +
provider.getClass().getName();
+ throw new IllegalArgumentException( error );
+ }
}
/**
- * Configure a set of logtargets based on config data.
+ * Configure Logging categories.
*
- * @param targets the target configuration data
- * @return a Map of target-name to target
+ * @param categories configuration data for categories
+ * @param targets a hashmap containing the already existing taregt
* @throws ConfigurationException if an error occurs
*/
- private HashMap configureTargets( final Configuration[] targets )
- throws ConfigurationException
+ public org.apache.avalon.framework.logger.Logger getLoggerForCategory(
+ final String name, String target, String priority )
+ throws Exception
{
-
- final HashMap targetSet = new HashMap();
-
- //
- // Create the default target.
- //
-
- targetSet.put( "default", m_stream );
-
- for( int i = 0; i < targets.length; i++ )
- {
- final Configuration target = targets[ i ];
- final String name = target.getAttribute( "name" );
- final Configuration fileDef = target.getChild( "file", false );
- if( fileDef != null )
- {
- String location = fileDef.getAttribute( "location" ).trim();
- final String format = fileDef.getAttribute( "format",
DEFAULT_FORMAT );
- if( '/' == location.charAt( 0 ) )
- location = location.substring( 1 );
-
- final AvalonFormatter formatter = new AvalonFormatter(
format );
-
- //Specify output location for logging
- final File file = new File( m_baseDirectory, location );
-
- //Setup logtarget
- FileTarget logTarget = null;
- try
- {
- logTarget = new FileTarget( file.getAbsoluteFile(),
false, formatter );
- }
- catch( final IOException ioe )
- {
- final String message =
- REZ.getString( "target.nocreate", name, file,
ioe.getMessage() );
- throw new ConfigurationException( message, ioe );
- }
-
- targetSet.put( name, logTarget );
- }
- else
- {
- final String error =
- "Unrecognized elements declaration in the logging target
named: " + name;
- throw new IllegalArgumentException( error );
- }
- }
-
- return targetSet;
+ return new LogKitLogger( addSingleCategory( new CategoryDescriptor(
name, target, priority ) ) );
}
/**
@@ -219,38 +215,50 @@
* @param targets a hashmap containing the already existing taregt
* @throws ConfigurationException if an error occurs
*/
- private void configureCategories( final Configuration[] categories,
final HashMap targets )
- throws ConfigurationException
+ public org.apache.avalon.framework.logger.Logger getLoggerForCategory(
+ final CategoryDescriptor category )
+ throws Exception
{
- for( int i = 0; i < categories.length; i++ )
+ return new LogKitLogger( addSingleCategory( category ) );
+ }
+
+ //===============================================================
+ // LoggerManager
+ //===============================================================
+
+ /**
+ * Return the Logger for the specified category.
+ */
+ public org.apache.avalon.framework.logger.Logger getLoggerForCategory(
final String category )
+ {
+ if( category == null )
+ {
+ return new LogKitLogger( getHierarchy().getLoggerFor( "" ) );
+ }
+ else
{
- final Configuration category = categories[ i ];
- final String name = category.getAttribute( "name", "" );
- final String target = category.getAttribute( "target" ,
"default" );
- final String priorityName = category.getAttribute( "priority",
m_defaultPriority );
-
- final Logger logger = getHierarchy().getLoggerFor( name );
-
- final LogTarget logTarget = (LogTarget)targets.get( target );
-
- final Priority priority = Priority.getPriorityForName(
priorityName );
- if( !priority.getName().equals( priorityName ) )
- {
- final String message = REZ.getString( "unknown-priority",
priorityName, name );
- throw new ConfigurationException( message );
- }
-
- logger.setPriority( priority );
- if( logTarget != null )
- logger.setLogTargets( new LogTarget[]{logTarget} );
-
- if( getDefaultLogger().isDebugEnabled() )
- {
- final String message =
- REZ.getString( "category-create", name, target,
priorityName );
- getDefaultLogger().debug( message );
- }
+ return new LogKitLogger( getHierarchy().getLoggerFor( category )
);
}
+ }
+
+ /**
+ * Return the default Logger. This is the same
+ * as getting the Logger for the "" category.
+ */
+ public org.apache.avalon.framework.logger.Logger getDefaultLogger( )
+ {
+ if( m_logger == null )
+ m_logger = getLoggerForCategory("kernel.logging");
+ return m_logger;
+ }
+
+ private Hierarchy getHierarchy()
+ {
+ if( m_parent != null )
+ {
+ return m_parent.getHierarchy();
+ }
+ return m_logHierarchy;
}
}
1.2 +26 -16
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultProvider.java
Index: DefaultProvider.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DefaultProvider.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DefaultProvider.java 8 Jul 2002 09:57:36 -0000 1.1
+++ DefaultProvider.java 12 Jul 2002 12:04:54 -0000 1.2
@@ -63,16 +63,16 @@
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.meta.verifier.VerifyException;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.info.DefaultType;
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.ServiceDesignator;
-import org.apache.excalibur.meta.data.Profile;
-import org.apache.excalibur.meta.data.Association;
-import org.apache.excalibur.meta.lifecycle.ResourceProvider;
-import org.apache.excalibur.meta.verifier.VerifyException;
-import org.apache.excalibur.merlin.registry.Registry;
+import org.apache.excalibur.merlin.model.Profile;
+import org.apache.excalibur.merlin.model.Association;
+import org.apache.excalibur.merlin.model.CategoryDescriptor;
+import org.apache.excalibur.merlin.ResourceProvider;
import org.apache.log.Hierarchy;
import org.apache.log.Priority;
import org.apache.log.output.io.StreamTarget;
@@ -99,9 +99,9 @@
//=======================================================================
/**
- * The container that this provider is assigned to.
+ * The classloader to use when servicing object creation requests.
*/
- private final ClassLoader m_classloader;
+ private ClassLoader m_classloader;
/**
* The parent provider.
@@ -113,19 +113,25 @@
*/
private final Hashtable m_singletons = new Hashtable();
+ /**
+ * The log manager.
+ */
+ private DefaultLoggerManager m_logging;
+
//=======================================================================
// constructor
//=======================================================================
- DefaultProvider( ClassLoader loader )
+ public DefaultProvider( ClassLoader loader, DefaultLoggerManager manager
)
{
- this( null, loader );
+ this( null, loader, manager );
}
- DefaultProvider( DefaultProvider parent, ClassLoader loader )
+ public DefaultProvider( DefaultProvider parent, ClassLoader loader,
DefaultLoggerManager manager )
{
m_parent = parent;
m_classloader = loader;
+ m_logging = manager;
}
//=======================================================================
@@ -157,7 +163,7 @@
final String error =
"Unexpected exception while attempting to load class '"
+ classname + "' for the profile: " + profile;
- throw new ContainerException( error, e );
+ throw new KernelException( error, e );
}
try
@@ -168,8 +174,9 @@
catch( Throwable e )
{
final String error =
- "Unexpected exception while attempting to instantiate an
instance from profile: " + profile;
- throw new ContainerException( error, e );
+ "Unexpected exception while attempting to instantiate an
instance from profile: "
+ + profile;
+ throw new KernelException( error, e );
}
}
return object;
@@ -185,7 +192,10 @@
public Logger createLogger( Profile profile )
throws Exception
{
- return getLogger().getChildLogger( profile.getName() );
+ final String name = profile.getName();
+ CategoryDescriptor loggers = profile.getCategoryDescriptor();
+ m_logging.addCategories( loggers );
+ return m_logging.getLoggerForCategory( loggers );
}
/**
@@ -363,7 +373,7 @@
final String error =
"Unable to locate an instantiated service instance implementing
the interface: "
+ service + ", from the provider: " + provider;
- throw new ContainerException( error );
+ throw new KernelException( error );
}
private Object lookupInstance( Profile provider )
1.2 +3 -8
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DependencyGraph.java
Index: DependencyGraph.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/DependencyGraph.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DependencyGraph.java 8 Jul 2002 09:57:36 -0000 1.1
+++ DependencyGraph.java 12 Jul 2002 12:04:54 -0000 1.2
@@ -8,8 +8,8 @@
package org.apache.excalibur.merlin.kernel;
import java.util.ArrayList;
-import org.apache.excalibur.meta.data.Profile;
-import org.apache.excalibur.meta.data.Association;
+import org.apache.excalibur.merlin.model.Profile;
+import org.apache.excalibur.merlin.model.Association;
import org.apache.excalibur.meta.info.DependencyDescriptor;
/**
@@ -30,11 +30,6 @@
* if no profile in current assembly satisfies dependency.
*/
private final DependencyGraph m_parent;
-
- /**
- * The container providing the componenent.
- */
- private Container m_container;
/**
* The set of components declared by the container as available.,
1.2 +3 -4
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/TypeRegistry.java
Index: TypeRegistry.java
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/TypeRegistry.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- TypeRegistry.java 12 Jul 2002 10:22:05 -0000 1.1
+++ TypeRegistry.java 12 Jul 2002 12:04:54 -0000 1.2
@@ -22,8 +22,7 @@
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.info.builder.TypeBuilder;
-import org.apache.excalibur.merlin.meta.data.Profile;
-import org.apache.excalibur.merlin.meta.data.Selector;
+import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.meta.verifier.ComponentVerifier;
import org.apache.excalibur.configuration.ConfigurationUtil;
@@ -34,7 +33,7 @@
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision$ $Date$
*/
-public final class TypeRegistry extends AbstractLogEnabled
+final class TypeRegistry extends AbstractLogEnabled
{
//=======================================================================
1.7 +2 -2
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/package.html
Index: package.html
===================================================================
RCS file:
/home/cvs/jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/kernel/package.html,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- package.html 7 Jul 2002 23:18:34 -0000 1.6
+++ package.html 12 Jul 2002 12:04:54 -0000 1.7
@@ -1,7 +1,7 @@
<body>
<p>
-The kernel package defines a top level [EMAIL PROTECTED]
org.apache.excalibur.merlin.kernel.Kernel} that serves as a host to a root
[EMAIL PROTECTED] 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.
+The kernel package defines a top level [EMAIL PROTECTED]
org.apache.excalibur.merlin.Kernel} that serves as a host to a root [EMAIL
PROTECTED] org.apache.excalibur.merlin.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>
@@ -22,7 +22,7 @@
</ul>
<h3>Object Model (UML)</h3>
-<p>An [EMAIL PROTECTED] org.apache.excalibur.merlin.kernel.Container} is
primarily a component type manager. Actual type management is handled by an
supertype [EMAIL PROTECTED] org.apache.excalibur.merlin.registry.Registry}. 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.</p>
+<p>An [EMAIL PROTECTED] org.apache.excalibur.merlin.Container} is primarily
a component type manager. Actual type management is handled by an supertype
[EMAIL PROTECTED] org.apache.excalibur.merlin.container.Registry}. 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.</p>
<p><img src=doc-files/UML.gif border=0></p>
</body>
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/AbstractContainer.java
Index: AbstractContainer.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.model;
/**
* Interface implemeted by objects capable of acting as a container.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public interface AbstractContainer
{
/**
* Return the container name.
*
* @return the name of the container
*/
String getName();
/**
* Return the logging descriptor.
*
* @return the [EMAIL PROTECTED] CategoryDescriptor} for the component
loggers.
*/
CategoryDescriptor getCategoryDescriptor();
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/Association.java
Index: Association.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.model;
/**
* The Association is the mapping of a component as a dependency
* of another component. Each component declares dependencies (via Type)
* and for each dependency there must be a coressponding Association which
* has a matching role. The name value in Association object must refer
* to another Component that implements a service as specified in
DependencyInfo.
*
* <p>Note that it is invalid to have circular dependencies.</p>
*
* @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public final class Association
{
/**
* The name that the client component will use to access a dependency.
*/
private final String m_role;
/**
* the name of the component metadata instance that represents a component
* type that is capable of fullfilling the dependency.
*/
private final Profile m_provider;
/**
* Create Profile with specified name and role.
*
* @param role the name client uses to access component
* @param providerName the name of <code>ComponentProfile</code> instance
* that is associated as a service provider
*/
public Association( final String role,
final Profile provider )
{
m_role = role;
m_provider = provider;
}
/**
* Return the name that will be used by a component instance to access a
* dependent service.
*
* @return the name that the client component will use to access
dependency.
* @see org.apache.avalon.framework.service.ServiceManager#lookup( String
)
*/
public String getRole()
{
return m_role;
}
/**
* Return the name of a <code>ComponentProfile</code> instance that will
used to
* fulfill the dependency.
*
* @return the name of the Component that will provide the dependency.
*/
public Profile getProvider()
{
return m_provider;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/CategoryDescriptor.java
Index: CategoryDescriptor.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.model;
import java.util.Hashtable;
/**
* A logging category descriptor hierachy.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class CategoryDescriptor
{
public static final String DEBUG = "DEBUG";
public static final String INFO = "INFO";
public static final String WARN = "WARN";
public static final String ERROR = "ERROR";
public static final String DEFAULT_LOGGING_TARGET = "default";
public static final String DEFAULT_LOGGING_PRIORITY = INFO;
/**
* The logging category name.
*/
private String m_name;
/**
* The default logging priority.
*/
private final String m_priority;
/**
* The default logging target.
*/
private final String m_target;
/**
* The loggers descriptor parent.
*/
protected CategoryDescriptor m_parent;
/**
* Subsidiary categories.
*/
private final Hashtable m_categories = new Hashtable();
/**
*/
public CategoryDescriptor( CategoryDescriptor parent, final String name )
{
this( parent, name, null, null, new CategoryDescriptor[0] );
}
/**
*/
public CategoryDescriptor( final String name, final String priority,
final String target )
{
this( null, name, priority, target, new CategoryDescriptor[0] );
}
/**
*/
public CategoryDescriptor(
final String name, final String priority, final String target,
final CategoryDescriptor[] categories )
{
this( null, name, priority, target, categories );
}
/**
*/
public CategoryDescriptor(
CategoryDescriptor parent, final String name, final String priority,
final String target,
final CategoryDescriptor[] categories )
{
m_name = name;
m_target = target;
m_priority = priority;
m_parent = parent;
for( int i=0; i<categories.length; i++ )
{
CategoryDescriptor category = categories[i];
m_categories.put( category.getName(), category );
category.setParent( this );
}
}
/**
* Return the category name.
*
* @return the category name
*/
public String getName()
{
return m_name;
}
/**
* Return the default logging priority for the group of categories.
*
* @return the default logging priority
*/
public String getPriority( )
{
if( m_priority == null )
{
if( m_parent != null )
{
return m_parent.getPriority();
}
else
{
return DEFAULT_LOGGING_PRIORITY;
}
}
return m_priority;
}
/**
* Return the default log target for the group of categories.
*
* @return the default target name
*/
public String getTarget( )
{
if( m_target == null )
{
if( m_parent != null )
{
return m_parent.getTarget();
}
else
{
return DEFAULT_LOGGING_TARGET;
}
}
return m_target;
}
public void setParent( CategoryDescriptor parent )
{
m_parent = parent;
}
/**
* Return the category path.
*
* @return the category path
*/
public String getPath()
{
if( m_parent != null )
{
String path = m_parent.getPath();
if( path.equals("") )
{
return getName();
}
else
{
return path + "." + getName();
}
}
else
{
return getName();
}
}
/**
* Return the set of logging categories.
*
* @return the set of service provider assignments.
*/
public CategoryDescriptor[] getCategories()
{
return (CategoryDescriptor[]) m_categories.values().toArray( new
CategoryDescriptor[0] );
}
/**
* Return a named category.
* @param name the category name
* @return the named category of null if unknown
*/
public CategoryDescriptor getCategory( String name )
{
CategoryDescriptor category = (CategoryDescriptor) m_categories.get(
name );
if( category == null )
{
category = new CategoryDescriptor( this, name );
m_categories.put( name, category );
}
return category;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/ClasspathDescriptor.java
Index: ClasspathDescriptor.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.model;
/**
* A classpath descriptor.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class ClasspathDescriptor
{
/**
* The base directory
*/
private final FilesetDescriptor[] m_filesets;
/**
* Create a ClasspathDescriptor instance.
*
* @param filesets the set of filesets to include in the classpath
*/
public ClasspathDescriptor( final FilesetDescriptor[] filesets )
{
m_filesets = filesets;
}
/**
* Return the filesets held within the classpath descriptor.
*
* @return the filesets
*/
public FilesetDescriptor[] getFilesetDescriptors()
{
return m_filesets;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/ComponentDescriptor.java
Index: ComponentDescriptor.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.model;
import java.io.Serializable;
import java.util.Hashtable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.context.Context;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.Association;
import org.apache.excalibur.configuration.ConfigurationUtil;
/**
* A component profile description.
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class ComponentDescriptor extends DefaultProfile
{
/**
* Create a Profile instance.
*
* @param name the abstract name of component meta data instance
* @param dependencies the meta data for any dependencies
* @param type the component type
*/
public ComponentDescriptor( final String name,
final Parameters parameters,
final Configuration configuration,
final Context context,
final CategoryDescriptor loggers,
final Type type,
final int mode )
{
super( name, parameters, configuration, context, loggers, type, mode
);
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/ContainerDescriptor.java
Index: ContainerDescriptor.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.model;
import java.util.ArrayList;
/**
* A container profile.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class ContainerDescriptor implements AbstractContainer
{
/**
* The parent.
*/
private AbstractContainer m_parent;
/**
* The container name.
*/
private final String m_name;
/**
* The loggers defintion.
*/
private final CategoryDescriptor m_loggers;
/**
* The container classpath descriptor.
*/
private final ClasspathDescriptor m_classpath;
/**
* The component described within the scope of the container.
*/
//private final ArrayList m_components = new ArrayList();
private final ComponentDescriptor[] m_components;
/**
* The component described within the scope of the container.
*/
private final ContainerDescriptor[] m_containers;
/**
* Create a ContainerDescriptor instance.
*
*/
public ContainerDescriptor( final String name,
final CategoryDescriptor loggers,
final ClasspathDescriptor classpath,
final ComponentDescriptor[] components,
final ContainerDescriptor[] containers )
{
if( name == null )
throw new NullPointerException("name");
if( loggers == null )
throw new NullPointerException("loggers");
if( classpath == null )
throw new NullPointerException("classpath");
m_name = name;
m_loggers = loggers;
m_classpath = classpath;
m_components = components;
m_containers = containers;
for( int i=0; i<containers.length; i++ )
{
containers[i].getCategoryDescriptor().setParent( loggers );
}
for( int i=0; i<components.length; i++ )
{
components[i].getCategoryDescriptor().setParent( loggers );
}
}
/**
* Return the container name.
*
* @return the name of the container
*/
public String getName()
{
return m_name;
}
/**
* Return the logging descriptor.
*
* @return the [EMAIL PROTECTED] CategoryDescriptor} for the component
loggers.
*/
public CategoryDescriptor getCategoryDescriptor()
{
return m_loggers;
}
/**
* Return the classpath descriptor.
*
* @return the [EMAIL PROTECTED] ClasspathDescriptor} for the container.
*/
public ClasspathDescriptor getClasspathDescriptor()
{
return m_classpath;
}
/**
* Add a container to this container.
*
* @parent the container to add
*/
//public void addComponent( ComponentDescriptor component )
//{
// m_components.add( component );
// component.getCategoryDescriptor().setParent(
getCategoryDescriptor() );
//}
/**
* Return the set of component descriptors contained within this
container.
*
* @return the target descriptors
*/
public ComponentDescriptor[] getComponentDescriptors()
{
//return (ComponentDescriptor[]) m_components.toArray( new
ComponentDescriptor[0] );
return m_components;
}
/**
* Return the set of subsidiary containers contained within this
container.
*
* @return the target descriptors
*/
public ContainerDescriptor[] getContainers()
{
return m_containers;
}
/**
* Set the parent container.
*
* @param the container containing this container.
* @exception IllegalStateException if the parent is already set
*/
public void setParent( AbstractContainer parent ) throws
IllegalStateException
{
if( m_parent != null )
throw new IllegalStateException("parent");
m_parent = parent;
ContainerDescriptor[] containers = getContainers();
for( int i=0; i<containers.length; i++ )
{
containers[i].setParent( this );
}
}
/**
* Return the parent container.
*
* @return the container containing this container.
*/
public AbstractContainer getParent()
{
return m_parent;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/DefaultProfile.java
Index: DefaultProfile.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.model;
import java.io.Serializable;
import java.util.Hashtable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.context.Context;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.Association;
import org.apache.excalibur.configuration.ConfigurationUtil;
/**
* Abstract defintion of a compoent profile.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class DefaultProfile
implements Profile, Serializable
{
/**
* The name of the component metadata instance. This is an
* abstract name used during assembly.
*/
private final String m_name;
/**
* The dependencies keyed by role name.
*/
private final Hashtable m_dependencies = new Hashtable();
/**
* The info object for component type.
*/
private final Type m_type;
/**
* The parameters for component (if any).
*/
private final Parameters m_parameters;
/**
* The configuration for component (if any).
*/
private final Configuration m_configuration;
/**
* The configuration for component (if any).
*/
private final Context m_context;
/**
* The logging descriptor.
*/
private final CategoryDescriptor m_loggers;
/**
* The creation mode.
*/
private final int m_mode;
/**
* Create a Profile instance.
*
* @param name the abstract name of component meta data instance
* @param dependencies the meta data for any dependencies
* @param type the component type
*/
public DefaultProfile( final String name,
final Parameters parameters,
final Configuration configuration,
final Context context,
final CategoryDescriptor loggers,
final Type type,
final int mode )
{
if( null == name )
{
m_name = "" + System.identityHashCode( this );
}
else
{
m_name = name;
}
if( null == type )
{
throw new NullPointerException( "type" );
}
m_parameters = parameters;
m_configuration = configuration;
m_type = type;
m_context = context;
m_loggers = loggers;
m_mode = mode;
}
/**
* Return the name of component metadata instance.
*
* @return the name of the component.
*/
public String getName()
{
return m_name;
}
/**
* Return the info for component.
*
* @return the info for component type.
*/
public Type getType()
{
return m_type;
}
/**
* Return the assigned service providers.
*
* @return the set of service provider assignments.
*/
public Association[] getAssociations()
{
return (Association[])m_dependencies.values().toArray( new
Association[0] );
}
/**
* Return the Context for component (if any).
*
* @return the Context for component (if any).
*/
public Context getContext()
{
return m_context;
}
/**
* Return the Parameters for Component (if any).
*
* @return the Parameters for Component (if any).
*/
public Parameters getParameters()
{
return m_parameters;
}
/**
* Return the Configuration for Component (if any).
*
* @return the Configuration for Component (if any).
*/
public Configuration getConfiguration()
{
return m_configuration;
}
/**
* Return the logging descriptor.
*
* @return the [EMAIL PROTECTED] CategoryDescriptor} for the component
loggers.
*/
public CategoryDescriptor getCategoryDescriptor()
{
return m_loggers;
}
/**
* Return the dependency metadata for component type with specified role.
*
* @return the dependency metadata for component with specified role.
*/
public Association getAssociation( final String role )
{
return (Association) m_dependencies.get( role );
}
/**
* Returns the creation mode for this profile.
* @return a value of EXPLICIT, PACKAGED or IMPLICIT
*/
public int getMode()
{
return m_mode;
}
/**
* Add a provider for a service dependecy role.
* @param provider the compenont provider profile
* @param role the dependent role
*/
public void addProvider( Profile provider, String role )
{
m_dependencies.put( role, new Association( role, provider ) );
}
public String toString()
{
return "Profile name: " + getName()
+ ", type: " + getType().getInfo().getName()
+ ", mode: " + modeToString( getMode() );
}
private String modeToString( int mode )
{
if( mode == IMPLICIT )
{
return "IMPLICIT";
}
else if( mode == PACKAGED )
{
return "PACKAGED";
}
else if( mode == EXPLICIT )
{
return "EXPLICIT";
}
else
{
return "?";
}
}
/**
* Provide a textual report on the profile.
* @return the formatted profile report
*/
public String list()
{
StringBuffer buffer = new StringBuffer();
buffer.append( "PROFILE REPORT\n" );
buffer.append( "\n name: " + getName() );
buffer.append( "\n base: " + getType().getInfo().getName() );
buffer.append( "\n key: " +
getType().getInfo().getImplementationKey() );
buffer.append( "\n context: " + getContext( ) );
buffer.append( "\n configuration:" );
if( getConfiguration() != null )
{
buffer.append( ConfigurationUtil.list( getConfiguration() ) );
}
else
{
buffer.append( " null" );
}
buffer.append( "\n parameters: " + getParameters() );
buffer.append( "\n dependecies" );
Association[] dependencies = getAssociations();
if( dependencies.length == 0 )
{
buffer.append( " (none)\n\n" );
return buffer.toString();
}
for( int i=0; i<dependencies.length; i++ )
{
buffer.append( "\n dependency " + i );
buffer.append( "\n role: " + dependencies[i].getRole() );
buffer.append( "\n provider: " + dependencies[i].getProvider()
);
}
buffer.append( "\n\n" );
return buffer.toString();
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/DirsetDescriptor.java
Index: DirsetDescriptor.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.model;
/**
* A description of a directory set.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class DirsetDescriptor
{
/**
* The base directory
*/
private final String m_base;
/**
* The set of include directives.
*/
private final IncludeDescriptor[] m_includes;
/**
* Create a FilesetDescriptor instance.
*
* @param filesets the set of filesets to include in the classpath
*/
public DirsetDescriptor( final String base, final IncludeDescriptor[]
includes )
{
m_base = base;
m_includes = includes;
}
/**
* Return the base directory.
*
* @return the directory
*/
public String getBaseDirectory()
{
return m_base;
}
/**
* Return the filesets held within the classpath descriptor.
*
* @return the filesets
*/
public IncludeDescriptor[] getIncludeDescriptors()
{
return m_includes;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/ExtensionsDescriptor.java
Index: ExtensionsDescriptor.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.model;
/**
* An extensions descriptor.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class ExtensionsDescriptor
{
/**
* The base directory
*/
private final DirsetDescriptor[] m_dirs;
/**
* Create a ExtensionsDescriptor instance.
*
* @param filesets the set of filesets to include in the classpath
*/
public ExtensionsDescriptor( final DirsetDescriptor[] dirs )
{
m_dirs = dirs;
}
/**
* Return the dirset held within the extensions descriptor.
*
* @return the directory set
*/
public DirsetDescriptor[] getDirsetDescriptors()
{
return m_dirs;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/FileTargetProvider.java
Index: FileTargetProvider.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.model;
/**
* File target provider type.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class FileTargetProvider extends TargetProvider
{
private final String m_location;
public FileTargetProvider( final String location )
{
m_location = location;
}
public String getLocation()
{
return m_location;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/FilesetDescriptor.java
Index: FilesetDescriptor.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.model;
/**
* A fileset descriptor.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class FilesetDescriptor
{
/**
* The base directory
*/
private final String m_base;
/**
* The set of include directives.
*/
private final IncludeDescriptor[] m_includes;
/**
* Create a FilesetDescriptor instance.
*
* @param filesets the set of filesets to include in the classpath
*/
public FilesetDescriptor( final String base, final IncludeDescriptor[]
includes )
{
m_base = base;
m_includes = includes;
}
/**
* Return the base directory.
*
* @return the directory
*/
public String getBaseDirectory()
{
return m_base;
}
/**
* Return the filesets held within the classpath descriptor.
*
* @return the filesets
*/
public IncludeDescriptor[] getIncludeDescriptors()
{
return m_includes;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/IncludeDescriptor.java
Index: IncludeDescriptor.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.model;
/**
* An file include directive.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class IncludeDescriptor
{
/**
* The base directory
*/
private final String m_file;
/**
* Create a FilesetDescriptor instance.
*
* @param filesets the set of filesets to include in the classpath
*/
public IncludeDescriptor( final String file )
{
m_file = file;
}
/**
* Return the included filename.
*
* @return the file
*/
public String getFile()
{
return m_file;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/KernelDescriptor.java
Index: KernelDescriptor.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.model;
/**
* Kernel creation profile.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class KernelDescriptor implements AbstractContainer
{
/**
* The kernel name
*/
private final String m_name;
/**
* The logging defintion.
*/
private final LoggingDescriptor m_logging;
/**
* The extensions defintion.
*/
private final ExtensionsDescriptor m_extensions;
/**
* The root container.
*/
private ClasspathDescriptor m_classpath;
/**
* The root container.
*/
private ContainerDescriptor m_container;
/**
* Create a KernelDescriptor instance.
*
*/
public KernelDescriptor( final String name,
final LoggingDescriptor logging,
final ExtensionsDescriptor extensions,
final ContainerDescriptor container )
{
if( name == null )
throw new NullPointerException("name");
if( logging == null )
throw new NullPointerException("logging");
if( extensions == null )
throw new NullPointerException("extensions");
m_name = name;
m_logging = logging;
m_extensions = extensions;
m_container = container;
}
/**
* Return the container name.
*
* @return the name of the container
*/
public String getName()
{
return m_name;
}
/**
* Return the logging descriptor.
*
* @return the [EMAIL PROTECTED] LoggingDescriptor} for the component
loggers.
*/
public LoggingDescriptor getLoggingDescriptor()
{
return m_logging;
}
/**
* Return the root logging descriptor.
*
* @return the [EMAIL PROTECTED] CategoryDescriptor} for the component
loggers.
*/
public CategoryDescriptor getCategoryDescriptor()
{
return getLoggingDescriptor().getCategoryDescriptor();
}
/**
* Return the classpath descriptor.
*
* @return the [EMAIL PROTECTED] ClasspathDescriptor} for the container.
*/
public ExtensionsDescriptor getExtensionsDescriptor()
{
return m_extensions;
}
/**
* Return the classpath descriptor.
*
* @return the [EMAIL PROTECTED] ClasspathDescriptor} for the container.
*/
public ClasspathDescriptor getClasspathDescriptor()
{
return m_classpath;
}
/**
* Sets the root container for the kernel.
*
* @param root the root [EMAIL PROTECTED] ContainerDescriptor} of the
container hierachy.
*/
//public void setContainerDescriptor( ContainerDescriptor container )
//{
// if( container == null )
// throw new NullPointerException("container");
// m_container = container;
// container.setParent( this );
//}
/**
* Return the root container.
*
* @return the root [EMAIL PROTECTED] ContainerDescriptor}.
*/
public ContainerDescriptor getContainerDescriptor()
{
return m_container;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/LoggingDescriptor.java
Index: LoggingDescriptor.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.model;
/**
* Description of a top level logging environment.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public final class LoggingDescriptor
{
/**
* The root category hierachy.
*/
private CategoryDescriptor m_category;
/**
* The defaulr priority.
*/
private String m_priority;
/**
* The default target.
*/
private String m_target;
/**
* The dependencies keyed by role name.
*/
private final TargetDescriptor[] m_targets;
/**
* Create a LoggingDescriptor instance.
*/
public LoggingDescriptor( final String priority,
final String target,
final TargetDescriptor[] targets,
final CategoryDescriptor category )
{
m_targets = targets;
m_priority = priority;
m_target = target;
m_category = category;
}
/**
* Return the default logging priority for the group of categories.
*
* @return the default logging priority
*/
public String getPriority( )
{
return m_priority;
}
/**
* Return the default log target for the group of categories.
*
* @return the default target name
*/
public String getTarget( )
{
return m_target;
}
/**
* Return the set of logging target descriptors.
*
* @return the target descriptors
*/
public TargetDescriptor[] getTargetDescriptors()
{
return m_targets;
}
/**
* Return the root catagory descriptor.
*
* @return the target descriptors
*/
public CategoryDescriptor getCategoryDescriptor()
{
return m_category;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/Profile.java
Index: Profile.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.model;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.context.Context;
import org.apache.excalibur.meta.info.Type;
/**
* Each component declared in the application is represented by
* a Profile. Note that this does not necessarily imply
* that there is only one instance of actual component. The
* ComponentProfile could represent a pool of components, a single
* component or a component prototype that is reused to create
* new components as needed.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public interface Profile
{
static final int IMPLICIT = 0;
static final int PACKAGED = 1;
static final int EXPLICIT = 2;
/**
* Return the name of component metadata instance.
*
* @return the name of the component.
*/
String getName();
/**
* Return the info for component.
*
* @return the info for component type.
*/
Type getType();
/**
* Return the Parameters for component (if any).
*
* @return the Parameters for Component (if any).
*/
Parameters getParameters();
/**
* Return the Configuration for component(if any).
*
* @return the Configuration for component
*/
Configuration getConfiguration();
/**
* Return the Context for component (if any).
*
* @return the Context for component
*/
Context getContext();
/**
* Return the logging descriptor.
*
* @return the [EMAIL PROTECTED] CategoryDescriptor} for the component
loggers.
*/
public CategoryDescriptor getCategoryDescriptor();
/**
* Return the assigned service providers.
*
* @return the dependency metadata for component.
*/
Association[] getAssociations();
/**
* Return the Association for specified role.
*
* @return the Association for specified role.
*/
Association getAssociation( final String role );
/**
* Returns the creation mode for this profile.
* @return a value of EXPLICIT, PACKAGED or IMPLICIT
*/
int getMode();
/**
* Add a provider for a service dependency role.
* @param provider the compenont provider profile
* @param role the dependent role
*/
void addProvider( Profile provider, String role );
/**
* Provide a textual report on the profile.
* @return the formatted profile report
*/
String list();
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/TargetDescriptor.java
Index: TargetDescriptor.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.model;
/**
* A logging target descriptor.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public final class TargetDescriptor
{
/**
* The target name.
*/
private final String m_name;
/**
* The target provider descriptor.
*/
private final TargetProvider m_provider;
/**
* Create a LoggingDescriptor instance.
*
* @param name the abstract name of component meta data instance
* @param dependencies the meta data for any dependencies
* @param type the component type
*/
public TargetDescriptor( final String name,
final TargetProvider provider )
{
m_name = name;
m_provider = provider;
}
/**
* Return the target name.
*
* @return the target name.
*/
public String getName()
{
return m_name;
}
/**
* Return the target provider descriptor
*
* @return the provider descriptor
*/
public TargetProvider getProvider()
{
return m_provider;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/TargetProvider.java
Index: TargetProvider.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.model;
/**
* Abstract logging target provider type.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public abstract class TargetProvider
{
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/package.html
Index: package.html
===================================================================
<body>
<p>
The <code>model</code> package contains the formal meta data model for the
Merlin kernel, container and profile abstractions. These classes define the
criteria for creation of new containers, component and factory profiles,
classloaders, extensions, and the kernel itself.
</p>
</body>
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/ContainerCreator.java
Index: ContainerCreator.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.model.builder;
import org.apache.excalibur.merlin.model.ContainerDescriptor;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.excalibur.merlin.model.builder.TypeManager;
/**
* Simple interface used to create [EMAIL PROTECTED] ContainerDescriptor}
* from a Configuration sorce.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public interface ContainerCreator
{
/**
* Create a [EMAIL PROTECTED] Profile} from configuration
*
* @param config the confiugration source
* @return the newly created [EMAIL PROTECTED] ContainerDescriptor}
* @throws Exception
*/
ContainerDescriptor createContainerDescriptor( Configuration config,
TypeManager manager )
throws Exception;
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/KernelCreator.java
Index: KernelCreator.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.model.builder;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.excalibur.merlin.model.KernelDescriptor;
import org.apache.excalibur.merlin.model.builder.TypeManager;
/**
* Simple interface used to create [EMAIL PROTECTED] ContainerDescriptor}
* from a Configuration sorce.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public interface KernelCreator
{
/**
* Create a [EMAIL PROTECTED] KernelDescriptor} from configuration
*
* @param config the confiugration source
* @return the newly created [EMAIL PROTECTED] ContainerDescriptor}
* @throws Exception
*/
KernelDescriptor createKernelDescriptor( Configuration config,
TypeManager manager )
throws Exception;
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/ProfileBuilder.java
Index: ProfileBuilder.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.model.builder;
import java.io.InputStream;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.info.builder.TypeBuilder;
import org.apache.excalibur.merlin.model.Profile;
/**
* A ProfileBuilder is responsible for building [EMAIL PROTECTED] Profile}
* objects from Configuration objects.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public final class ProfileBuilder
{
private static final Resources REZ =
ResourceManager.getPackageResources( TypeBuilder.class );
private final ProfileCreator m_xmlProfileCreator =
createXMLProfileCreator();
/**
* Build Profile from the XML descriptor format.
*
* @param classname The classname of Component
* @param classLoader the ClassLoader to load info from
* @return the created Type
* @throws Exception if an error occurs
*/
public Profile[] build( Type type, final ClassLoader classLoader )
throws Exception
{
final String xprofile =
type.getInfo().getImplementationKey().replace( '.', '/' ) +
".xprofile";
final InputStream inputStream =
classLoader.getResourceAsStream( xprofile );
final ProfileCreator creator = getXMLProfileCreator( xprofile );
if( null == inputStream )
{
return creator.createProfiles( type, new
DefaultConfiguration("profiles", null ) );
}
else
{
return creator.createProfiles( type, inputStream );
}
}
public Profile build( Type type, Configuration profile )
throws Exception
{
final ProfileCreator creator = getXMLProfileCreator( "implicit" );
return creator.createProfile( type, profile );
}
/**
* Utility to get xml info builder, else throw
* an exception if missing descriptor.
*
* @return the TypeCreator
*/
private ProfileCreator getXMLProfileCreator( final String classname )
throws Exception
{
if( null != m_xmlProfileCreator )
{
return m_xmlProfileCreator;
}
else
{
final String message =
REZ.getString( "builder.missing-xml-creator.error",
classname );
throw new Exception( message );
}
}
/**
* Utility to get XMLProfileCreator if XML files are on
* ClassPath.
*
* @return the XML [EMAIL PROTECTED] TypeCreator}
*/
private static ProfileCreator createXMLProfileCreator()
{
ProfileCreator xmlProfileCreator = null;
try
{
xmlProfileCreator = new XMLProfileCreator();
}
catch( final Exception e )
{
//Ignore it if ClassNot found due to no
//XML Classes on classpath
}
return xmlProfileCreator;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/ProfileCreator.java
Index: ProfileCreator.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.model.builder;
import java.io.InputStream;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.merlin.model.Profile;
/**
* Simple interface used to create [EMAIL PROTECTED] Profile}
* from stream or Configuration sorce.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public interface ProfileCreator
{
/**
* Create a [EMAIL PROTECTED] Profile} from stream
*
* @param key the name of component type that we are looking up
* @param inputStream the stream that the resource is loaded from
* @return the newly created [EMAIL PROTECTED] Type}
* @throws Exception
*/
Profile[] createProfiles( Type type, InputStream inputStream )
throws Exception;
/**
* Create a [EMAIL PROTECTED] Profile} from a configuration
*
* @param key the name of component type that we are looking up
* @param inputStream the stream that the resource is loaded from
* @return the newly created [EMAIL PROTECTED] Type}
* @throws Exception
*/
Profile[] createProfiles( Type type, Configuration config )
throws Exception;
Profile createProfile( Type type, Configuration config )
throws Exception;
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/Resources.properties
Index: Resources.properties
===================================================================
builder.redundent-role.notice=Warning: Type for class {0} redundently
specifies role name "{1}" in dependency when it is identical to the name of
service. It is recomended that the <role/> section be elided.
builder.creating-info.notice=Creating a Type for class "{0}".
builder.created-info.notice=Constructed Type object for class {0}.
ComponentInfo contains {1} services, {2} dependencies, {3} context entrys and
{4} loggers.
builder.bad-toplevel-element.error=Error the component implemented by "{0}"
has an invalid element at top level of component info descriptor. Expected:
"component-info". Actual: "{1}"
builder.missing-info.error=Unable to locate resource from which to load info
for component implemented by class "{0}".
builder.missing-xml-creator.error=Unable to create XMLTypeCreator, usually
due to not having XML classes on Classpath. Thus unable to lookup XML
descriptor for component type "{0}".
builder.creating-profile.notice=Creating Profiles for class "{0}".
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/TypeManager.java
Index: TypeManager.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.model.builder;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.info.ServiceDesignator;
import org.apache.excalibur.merlin.model.ClasspathDescriptor;
/**
* Interface implemented by resources capable a resolving a Type form a
classname.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public interface TypeManager
{
/**
* Add classes to the manager declared within a classpath structure.
* @param classpath the classpath descriptor
* @exception Exception if an exception occurs during class loading
*/
void addClasspath( ClasspathDescriptor classpath ) throws Exception;
/**
* Resolve a [EMAIL PROTECTED] Type} from a classname.
*
* @param classname the component type
* @return the component type
*/
Type lookup( String classname ) throws Exception;
/**
* Register a potential supplier component type. The implementation will
* create a component type instance for the entry if not already known and
* return the existing or new instance to the invoking client.
*
* @param classname the component class name
* @return the component type
*/
Type register( String classname ) throws Exception;
/**
* Returns the set of component types know to the registry.
* @return the set of component types registered with the registry
*/
Type[] getTypes();
/**
* Returns the set of component types know to the registry that are
capable of
* supporting the supplied service.
* @return the set of candidate component types
*/
Type[] getTypes( ServiceDesignator service );
/**
* Returns a registered component type.
* @return the component type from the registry or null if the type is
unknown
*/
Type getType( String classname );
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/XMLContainerCreator.java
Index: XMLContainerCreator.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.model.builder;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Vector;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.Version;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.configuration.ContextFactory;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.DefaultProfile;
import org.apache.excalibur.merlin.model.CategoryDescriptor;
import org.apache.excalibur.merlin.model.IncludeDescriptor ;
import org.apache.excalibur.merlin.model.FilesetDescriptor;
import org.apache.excalibur.merlin.model.ClasspathDescriptor;
import org.apache.excalibur.merlin.model.ContainerDescriptor;
import org.apache.excalibur.merlin.model.ComponentDescriptor;
import org.apache.excalibur.merlin.model.builder.TypeManager;
/**
* Handles internalization of an XML based description of a [EMAIL PROTECTED]
Profile}
* from a Configuration object. The format for Configuration object
* is specified in the <a href="package-summary.html#external">package
summary</a>.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class XMLContainerCreator extends XMLProfileCreator
implements ContainerCreator
{
private static final Resources REZ =
ResourceManager.getPackageResources( XMLContainerCreator.class );
public ContainerDescriptor[] createContainerDescriptors( Configuration[]
configs, TypeManager manager )
throws Exception
{
ArrayList list = new ArrayList();
for( int i=0; i<configs.length; i++ )
{
Configuration config = configs[i];
list.add( createContainerDescriptor( config, manager ) );
}
return (ContainerDescriptor[]) list.toArray( new
ContainerDescriptor[0] );
}
/**
* Create a [EMAIL PROTECTED] ContainerDescriptor} from configuration
*
* @param config the confiugration source
* @return the newly created [EMAIL PROTECTED] ContainerDescriptor}
* @throws Exception
*/
public ContainerDescriptor createContainerDescriptor( Configuration
config, TypeManager manager )
throws Exception
{
final String name = config.getAttribute("name");
CategoryDescriptor loggers = createCategoryDescriptor(
config.getChild("loggers"), name );
ClasspathDescriptor classpath = createClasspathDescriptor(
config.getChild("classpath") );
manager.addClasspath( classpath );
ComponentDescriptor[] components = createComponentDescriptors(
manager, config.getChildren("component") );
ContainerDescriptor[] containers = createContainerDescriptors(
config.getChildren("container"), manager );
return new ContainerDescriptor( name, loggers, classpath, components,
containers );
}
public ComponentDescriptor[] createComponentDescriptors( TypeManager
manager, Configuration[] configs )
throws Exception
{
ArrayList list = new ArrayList();
for( int i=0; i<configs.length; i++ )
{
Configuration config = configs[i];
Type type = manager.lookup( config.getAttribute("class") );
list.add( super.createProfile( type, config ) );
}
return (ComponentDescriptor[]) list.toArray( new
ComponentDescriptor[0] );
}
public ClasspathDescriptor createClasspathDescriptor( Configuration
config )
throws ConfigurationException
{
ArrayList list = new ArrayList();
Configuration[] configs = config.getChildren("fileset");
for( int i=0; i<configs.length; i++ )
{
Configuration c = configs[i];
list.add( createFilesetDescriptor( c ) );
}
FilesetDescriptor[] filesets = (FilesetDescriptor[]) list.toArray(
new FilesetDescriptor[0] );
return new ClasspathDescriptor( filesets );
}
public FilesetDescriptor createFilesetDescriptor( Configuration config )
throws ConfigurationException
{
String base = config.getAttribute("dir");
ArrayList list = new ArrayList();
Configuration[] includeConfigs = config.getChildren("include");
for( int i=0; i<includeConfigs.length; i++ )
{
Configuration includeConfig = includeConfigs[i];
list.add( createIncludeDescriptor( includeConfig ) );
}
IncludeDescriptor[] includes = (IncludeDescriptor[]) list.toArray(
new IncludeDescriptor[0] );
return new FilesetDescriptor( base, includes );
}
public IncludeDescriptor createIncludeDescriptor( Configuration config )
throws ConfigurationException
{
String filename = config.getAttribute("name");
return new IncludeDescriptor( filename );
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/XMLKernelCreator.java
Index: XMLKernelCreator.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.model.builder;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Vector;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.Version;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.DefaultProfile;
import org.apache.excalibur.merlin.model.CategoryDescriptor;
import org.apache.excalibur.merlin.model.IncludeDescriptor ;
import org.apache.excalibur.merlin.model.FilesetDescriptor;
import org.apache.excalibur.merlin.model.ClasspathDescriptor;
import org.apache.excalibur.merlin.model.ContainerDescriptor;
import org.apache.excalibur.merlin.model.ComponentDescriptor;
import org.apache.excalibur.merlin.model.DirsetDescriptor;
import org.apache.excalibur.merlin.model.ExtensionsDescriptor;
import org.apache.excalibur.merlin.model.KernelDescriptor;
import org.apache.excalibur.merlin.model.TargetDescriptor;
import org.apache.excalibur.merlin.model.FileTargetProvider;
import org.apache.excalibur.merlin.model.TargetProvider;
import org.apache.excalibur.merlin.model.LoggingDescriptor;
import org.apache.excalibur.merlin.model.builder.TypeManager;
/**
* Handles internalization of an XML based description of a [EMAIL PROTECTED]
Profile}
* from a Configuration object. The format for Configuration object
* is specified in the <a href="package-summary.html#external">package
summary</a>.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public final class XMLKernelCreator extends XMLContainerCreator
implements KernelCreator
{
private static final Resources REZ =
ResourceManager.getPackageResources( XMLKernelCreator.class );
/**
* Create a [EMAIL PROTECTED] KernelDescriptor} from configuration
*
* @param config the confiugration source
* @return the newly created [EMAIL PROTECTED] ContainerDescriptor}
* @throws Exception
*/
public KernelDescriptor createKernelDescriptor( Configuration config,
TypeManager manager )
throws Exception
{
final String name = config.getName();
LoggingDescriptor logging = createLoggingDescriptor(
config.getChild("logging"), name );
ExtensionsDescriptor extensions = createExtensionsDescriptor(
config.getChild("extensions") );
ClasspathDescriptor classpath = createClasspathDescriptor(
config.getChild("classpath") );
ContainerDescriptor container = createContainerDescriptor(
config.getChild("container"), manager );
return new KernelDescriptor( name, logging, extensions, container );
}
public LoggingDescriptor createLoggingDescriptor( Configuration config,
String name )
throws ConfigurationException
{
final String target = config.getAttribute(
"target", CategoryDescriptor.DEFAULT_LOGGING_TARGET );
final String priority = config.getAttribute( "priority", null );
ArrayList list = new ArrayList();
Configuration[] configs = config.getChildren("target");
for( int i=0; i<configs.length; i++ )
{
Configuration c = configs[i];
list.add( createTargetDescriptor( c ) );
}
TargetDescriptor[] targets = (TargetDescriptor[]) list.toArray( new
TargetDescriptor[0] );
CategoryDescriptor loggers = super.createCategoryDescriptor(
config.getChild("loggers"), name );
return new LoggingDescriptor( priority, target, targets, loggers );
}
public TargetDescriptor createTargetDescriptor( Configuration config )
throws ConfigurationException
{
final String name = config.getAttribute("name");
if( config.getChildren().length == 0 )
throw new ConfigurationException(
"missing target provider elememt in '" + config.getName() + "'.");
final Configuration c = config.getChildren()[0];
TargetProvider provider = null;
if( c.getName().equals("file") )
{
provider = createFileTargetProvider( c );
}
else
{
throw new ConfigurationException(
"Unrecognized provider: " + c.getName() + " in " +
config.getName() );
}
return new TargetDescriptor( name, provider );
}
public FileTargetProvider createFileTargetProvider( Configuration config )
throws ConfigurationException
{
String file = config.getAttribute("location");
return new FileTargetProvider( file );
}
public ExtensionsDescriptor createExtensionsDescriptor( Configuration
config )
throws ConfigurationException
{
ArrayList list = new ArrayList();
Configuration[] configs = config.getChildren("dirset");
for( int i=0; i<configs.length; i++ )
{
Configuration c = configs[i];
list.add( createDirsetDescriptor( c ) );
}
DirsetDescriptor[] dirs = (DirsetDescriptor[]) list.toArray( new
DirsetDescriptor[0] );
return new ExtensionsDescriptor( dirs );
}
public DirsetDescriptor createDirsetDescriptor( Configuration config )
throws ConfigurationException
{
String base = config.getAttribute("dir");
ArrayList list = new ArrayList();
Configuration[] includeConfigs = config.getChildren("include");
for( int i=0; i<includeConfigs.length; i++ )
{
Configuration includeConfig = includeConfigs[i];
list.add( createIncludeDescriptor( includeConfig ) );
}
IncludeDescriptor[] includes = (IncludeDescriptor[]) list.toArray(
new IncludeDescriptor[0] );
return new DirsetDescriptor( base, includes );
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/XMLProfileCreator.java
Index: XMLProfileCreator.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.model.builder;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Vector;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.Version;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.info.builder.XMLTypeCreator;
import org.apache.excalibur.meta.ConfigurationBuilder;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.DefaultProfile;
import org.apache.excalibur.merlin.model.CategoryDescriptor;
import org.apache.excalibur.merlin.model.ComponentDescriptor;
import org.apache.excalibur.configuration.ContextFactory;
import org.xml.sax.InputSource;
/**
* Handles internalization of an XML based description of a [EMAIL PROTECTED]
Profile}
* from a Configuration object. The format for Configuration object
* is specified in the <a href="package-summary.html#external">package
summary</a>.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stephen McConnell</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:55 $
*/
public class XMLProfileCreator
implements ProfileCreator
{
private static final Resources REZ =
ResourceManager.getPackageResources( XMLTypeCreator.class );
/**
* Create a [EMAIL PROTECTED] Type} object for specified
* classname, loaded from specified [EMAIL PROTECTED] InputStream}.
*
* @param implementationKey The classname of Component
* @param inputStream the InputStream to load Type from
* @return the created Type
* @throws ConfigurationException if an error occurs
*/
public Profile[] createProfiles( Type type, InputStream inputStream )
throws Exception
{
final InputSource input = new InputSource( inputStream );
final Configuration configuration = ConfigurationBuilder.build( input
);
return createProfiles( type, configuration );
}
/**
* Create a [EMAIL PROTECTED] Profile} object for specified classname from
* specified configuration data associated with a single type.
*
* @param classname The classname of Component
* @param info the Type configuration
* @return the created Type
* @throws ConfigurationException if an error occurs
*/
public Profile[] createProfiles( Type type, final Configuration info )
throws Exception
{
Vector vector = new Vector();
Configuration[] profiles = info.getChildren("component");
if( profiles.length == 0 )
{
//
// build a default profile
//
CategoryDescriptor loggers = new CategoryDescriptor(
type.getInfo().getName(), null, null );
return new Profile[]{
new ComponentDescriptor( null, null, null, null, loggers,
type, Profile.IMPLICIT ) };
}
for( int i=0; i<profiles.length; i++ )
{
vector.add( buildProfile( type, profiles[i], Profile.PACKAGED ) );
}
return (Profile[]) vector.toArray( new Profile[0] );
}
public Profile createProfile( Type type, Configuration config )
throws Exception
{
return buildProfile( type, config, Profile.EXPLICIT );
}
private Profile buildProfile( Type type, Configuration profile, int mode
) throws Exception
{
String name = null;
if( mode == Profile.EXPLICIT )
{
name = profile.getAttribute("name");
}
Parameters params = Parameters.fromConfiguration(
profile.getChild("parameters") );
Configuration config = profile.getChild("configuration");
Configuration loggersConfig = profile.getChild("loggers");
CategoryDescriptor loggers = createCategoryDescriptor( loggersConfig,
name );
Context context = ContextFactory.createContextFromConfiguration(
null, profile.getChild("context") );
return new ComponentDescriptor( name, params, config, context,
loggers, type, mode );
}
public CategoryDescriptor createCategoryDescriptor( Configuration config,
String fallback )
throws ConfigurationException
{
final String name = config.getAttribute( "name", fallback );
final String priority = config.getAttribute( "priority", null );
final String target = config.getAttribute( "target", null );
CategoryDescriptor[] categories = createCategoryDescriptors( config );
return new CategoryDescriptor( name, priority, target, categories );
}
private CategoryDescriptor[] createCategoryDescriptors( Configuration
config )
throws ConfigurationException
{
ArrayList list = new ArrayList();
Configuration[] categories = config.getChildren( "category" );
for( int i=0; i<categories.length; i++ )
{
CategoryDescriptor category = createCategoryDescriptor(
categories[i], null );
list.add( category );
}
return (CategoryDescriptor[]) list.toArray( new CategoryDescriptor[0]
);
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/builder/package.html
Index: package.html
===================================================================
<html><body>
<p>Merlin model information builders that handle internalization of a model
supplied as a configuration instance.</P>
</body></html>
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/verifier/AssemblyVerifier.java
Index: AssemblyVerifier.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.model.verifier;
import java.util.ArrayList;
import java.util.Stack;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.verifier.VerifyException;
import org.apache.excalibur.meta.info.DependencyDescriptor;
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.ServiceDesignator;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.merlin.model.Association;
/**
* This Class verifies that a set of profiles are valid. It performs a number
* of checks to make sure that the profile set represents a valid
* application and excluding runtime errors will start up normally.
* Some of the checks performed include;
*
* <ul>
* <li>Verify names of Components contain only
* letters, digits or the '_' character.</li>
* <li>Verify that the names of the Components are unique to the
* Assembly.</li>
* <li>Verify that the specified dependeny mapping correspond to
* dependencies specified in Type files.</li>
* <li>Verify that the inter-Component dependendencies are valid.
* This essentially means that if Component A requires Service S
* from Component B then Component B must provide Service S.</li>
* <li>Verify that there are no circular dependendencies between
* components.</li>
* <li>Verify that the Class objects for Component implement the
* service interfaces.</li>
* <li>Verify that the Class is a valid Avalon Component as per the
* rules in [EMAIL PROTECTED] ComponentVerifier} object.</li>
* </ul>
*
* @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:56 $
*/
public class AssemblyVerifier
extends AbstractLogEnabled
{
private static final Resources REZ =
ResourceManager.getPackageResources( AssemblyVerifier.class );
/**
* Validate and Verify the specified assembly (ie organization
* of components). See the Class Javadocs for the rules and
* regulations of assembly.
*
* @param components the Components that make up assembly
* @throws VerifyException if an error occurs
*/
public void verifyAssembly( final Profile[] components )
throws VerifyException
{
String message = null;
message = REZ.getString( "assembly.valid-names.notice" );
getLogger().debug( message );
verifyValidNames( components );
message = REZ.getString( "assembly.unique-names.notice" );
getLogger().debug( message );
checkNamesUnique( components );
message = REZ.getString( "assembly.dependencies-mapping.notice" );
getLogger().debug( message );
verifyValidDependencies( components );
message = REZ.getString( "assembly.dependency-references.notice" );
getLogger().debug( message );
verifyDependencyReferences( components );
message = REZ.getString( "assembly.nocircular-dependencies.notice" );
getLogger().debug( message );
verifyNoCircularDependencies( components );
}
/**
* Verfiy that all Components have the needed dependencies specified
correctly.
*
* @param components the Profile objects for the components
* @throws VerifyException if an error occurs
*/
public void verifyValidDependencies( final Profile[] components )
throws VerifyException
{
for( int i = 0; i < components.length; i++ )
{
verifyDependenciesMap( components[ i ] );
}
}
/**
* Verfiy that there are no circular references between Components.
*
* @param components the Profile objects for the components
* @throws VerifyException if an circular dependency error occurs
*/
protected void verifyNoCircularDependencies( final Profile[] components )
throws VerifyException
{
for( int i = 0; i < components.length; i++ )
{
final Profile component = components[ i ];
final Stack stack = new Stack();
stack.push( component );
verifyNoCircularDependencies( component, components, stack );
stack.pop();
}
}
/**
* Verfiy that there are no circular references between Components.
*
* @param component ???
* @param components the Profile objects for the components
* @param stack the ???
* @throws VerifyException if an error occurs
*/
protected void verifyNoCircularDependencies( final Profile component,
final Profile[] components,
final Stack stack )
throws VerifyException
{
final Profile[] dependencies = getDependencies( component, components
);
for( int i = 0; i < dependencies.length; i++ )
{
final Profile dependency = dependencies[ i ];
if( stack.contains( dependency ) )
{
final String trace = getDependencyTrace( dependency, stack );
final String message =
REZ.getString( "assembly.circular-dependency.error",
component.getName(),
trace );
throw new VerifyException( message );
}
stack.push( dependency );
verifyNoCircularDependencies( dependency, components, stack );
stack.pop();
}
}
/**
* Get a string defining path from top of stack till
* it reaches specified component.
*
* @param component the component
* @param stack the Stack
* @return the path of dependency
*/
protected String getDependencyTrace( final Profile component,
final Stack stack )
{
final StringBuffer sb = new StringBuffer();
sb.append( "[ " );
final String name = component.getName();
final int size = stack.size();
final int top = size - 1;
for( int i = top; i >= 0; i-- )
{
final Profile other = (Profile)stack.get( i );
if( top != i )
{
sb.append( ", " );
}
sb.append( other.getName() );
if( other.getName().equals( name ) )
{
break;
}
}
sb.append( ", " );
sb.append( name );
sb.append( " ]" );
return sb.toString();
}
/**
* Get array of dependencies for specified Component from specified
* Component array.
*
* @param component the component to get dependencies of
* @param components the total set of components in application
* @return the dependencies of component
*/
protected Profile[] getDependencies( final Profile component,
final Profile[] components
)
{
final ArrayList dependencies = new ArrayList();
final Association[] deps = component.getAssociations();
for( int i = 0; i < deps.length; i++ )
{
final String name = deps[ i ].getProvider().getName();
final Profile other = getProfile( name, components );
dependencies.add( other );
}
return (Profile[])dependencies.toArray( new Profile[ 0 ] );
}
/**
* Verfiy that the inter-Component dependencies are valid.
*
* @param components the Profile objects for the components
* @throws VerifyException if an error occurs
*/
protected void verifyDependencyReferences( final Profile[] components )
throws VerifyException
{
for( int i = 0; i < components.length; i++ )
{
verifyDependencyReferences( components[ i ], components );
}
}
/**
* Verfiy that the inter-Component dependencies are valid for specified
Component.
*
* @param component the Profile object for the component
* @param others the Profile objects for the other components
* @throws VerifyException if an error occurs
*/
protected void verifyDependencyReferences( final Profile component,
final Profile[] others )
throws VerifyException
{
final Type info = component.getType();
final Association[] roles = component.getAssociations();
for( int i = 0; i < roles.length; i++ )
{
final String providerName = roles[ i ].getProvider().getName();
final String roleName = roles[ i ].getRole();
final ServiceDesignator service =
info.getDependency( roleName ).getService();
//Get the other component that is providing service
final Profile provider = getProfile( providerName, others );
if( null == provider )
{
final String message =
REZ.getString( "assembly.missing-dependency.error",
roleName,
providerName,
component.getName() );
throw new VerifyException( message );
}
//make sure that the component offers service
//that user expects it to be providing
final ServiceDescriptor[] services =
provider.getType().getServices();
if( !hasMatchingService( service, services ) )
{
final String message =
REZ.getString(
"assembly.dependency-missing-service.error",
component.getName(),
providerName,
roleName,
service );
throw new VerifyException( message );
}
}
}
/**
* Get component with specified name from specified Component array.
*
* @param name the name of component to get
* @param components the array of components to search
* @return the Component if found, else null
*/
protected Profile getProfile( final String name,
final Profile[]
components )
{
for( int i = 0; i < components.length; i++ )
{
if( components[ i ].getName().equals( name ) )
{
return components[ i ];
}
}
return null;
}
/**
* Verify that the names of the specified Components are valid.
*
* @param components the Components metadata
* @throws VerifyException if an error occurs
*/
protected void verifyValidNames( final Profile[] components )
throws VerifyException
{
for( int i = 0; i < components.length; i++ )
{
final String name = components[ i ].getName();
if( !isValidName( name ) )
{
final String message =
REZ.getString( "assembly.bad-name.error", name );
throw new VerifyException( message );
}
}
}
/**
* Return true if specified name is valid.
* Valid names consist of letters, digits or the '_' character.
*
* @param name the name to check
* @return true if valid, false otherwise
*/
protected boolean isValidName( final String name )
{
final int size = name.length();
for( int i = 0; i < size; i++ )
{
final char ch = name.charAt( i );
if( !Character.isLetterOrDigit( ch ) && '-' != ch )
{
return false;
}
}
return true;
}
/**
* Verify that the names of the specified components and listeners are
unique.
* It is not valid for the same name to be used in multiple components.
*
* @param components the Components
* @throws VerifyException if an error occurs
*/
protected void checkNamesUnique( final Profile[] components )
throws VerifyException
{
for( int i = 0; i < components.length; i++ )
{
final String name = components[ i ].getName();
verifyUniqueName( components, name, i );
}
}
/**
* Verfify that specified name is unique among the specified components.
*
* @param components the array of components to check
* @param name the name of component
* @param index the index of component in array (so we can skip it)
* @throws VerifyException if names are not unique
*/
private void verifyUniqueName( final Profile[] components,
final String name,
final int index )
throws VerifyException
{
for( int i = 0; i < components.length; i++ )
{
final String other = components[ i ].getName();
if( index != i && other.equals( name ) )
{
final String message =
REZ.getString( "assembly.duplicate-name.error", name );
throw new VerifyException( message );
}
}
}
/**
* Retrieve a list of Association objects for Profile
* and verify that there is a 1 to 1 map with dependencies specified
* in Type.
*
* @param component the Profile describing the component
* @throws VerifyException if an error occurs
*/
protected void verifyDependenciesMap( final Profile component )
throws VerifyException
{
//Make sure all role entries specified in config file are valid
final Association[] dependencySet = component.getAssociations();
for( int i = 0; i < dependencySet.length; i++ )
{
final String roleName = dependencySet[ i ].getRole();
final DependencyDescriptor descriptor =
component.getType().getDependency( roleName );
//If there is no dependency descriptor in Type then
//user has specified an uneeded dependency.
if( null == descriptor )
{
final String message =
REZ.getString( "assembly.unknown-dependency.error",
roleName,
roleName,
component.getName() );
throw new VerifyException( message );
}
}
//Make sure all dependencies in Type file are satisfied
final DependencyDescriptor[] dependencies =
component.getType().getDependencies();
for( int i = 0; i < dependencies.length; i++ )
{
final DependencyDescriptor dependency = dependencies[ i ];
final Association role = component.getAssociation(
dependency.getRole() );
//If there is no Role then the user has failed
//to specify a needed dependency.
if( null == role && !dependency.isOptional() )
{
final String message =
REZ.getString( "assembly.unspecified-dependency.error",
dependency.getRole(),
component.getName() );
throw new VerifyException( message );
}
}
}
/**
* Return true if specified service reference matches any of the
* candidate services.
*
* @param service the service descriptor reference
* @param candidates an array of candidate services
* @return true if candidate services contains a service that matches
* specified service, false otherwise
*/
protected boolean hasMatchingService( final ServiceDesignator service,
final ServiceDescriptor[]
candidates )
{
for( int i = 0; i < candidates.length; i++ )
{
final ServiceDesignator other = candidates[ i ].getService();
if( service.matches( other ) )
{
return true;
}
}
return false;
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/verifier/MetaDataVerifier.java
Index: MetaDataVerifier.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.model.verifier;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.excalibur.merlin.model.Profile;
import org.apache.excalibur.meta.info.Type;
import org.apache.excalibur.meta.info.ContextDescriptor;
import org.apache.excalibur.meta.info.ServiceDescriptor;
import org.apache.excalibur.meta.info.ServiceDesignator;
import org.apache.excalibur.meta.verifier.VerifyException;
import org.apache.excalibur.meta.verifier.ComponentVerifier;
/**
* This Class verifies that an implementation is valid wrt the
* Profile. It performs a number of checks to make sure
* that the implementation class is consistent with MetaData.
* Some of the checks it performs include;
*
* <ul>
* <li>Verify that the Class objects for Component implement the
* service interfaces.</li>
* <li>Verify that the Class is a valid Avalon Component as per the
* rules in [EMAIL PROTECTED] ComponentVerifier} object.</li>
* <li>Verify that the Class is Composable/Serviceable if and only if
* dependencies are declared.</li>
* <li>Verify that the Class is Contextualizable if and context
* entrys are declared.</li>
* </ul>
*
* @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2002/07/12 12:04:56 $
*/
public class MetaDataVerifier
extends AbstractLogEnabled
{
private static final Resources REZ =
ResourceManager.getPackageResources( MetaDataVerifier.class );
/**
* The verifier for components in assembly.
*/
private final ComponentVerifier m_verifier;
/**
* Create an MetaDataVerifier using base Componert ComponentVerifier.
*/
public MetaDataVerifier()
{
this( new ComponentVerifier() );
}
/**
* Create an AssemblyVerifier using specified Component ComponentVerifier.
*/
public MetaDataVerifier( final ComponentVerifier verifier )
{
if( null == verifier )
{
throw new NullPointerException( "verifier" );
}
m_verifier = verifier;
}
public void enableLogging( final Logger logger )
{
super.enableLogging( logger );
setupLogger( m_verifier );
}
/**
* Verfiy that specified components designate classes that implement the
* advertised interfaces. And confrorm to expectations of MetaData.
*
* @param component the Profile object for the components
* @param classLoader the ClassLoader to load component from
* @throws VerifyException if an error occurs
*/
public void verifyType( final Profile component,
final ClassLoader classLoader )
throws VerifyException
{
final Class clazz = getClass( classLoader, component );
verifyType( component, clazz );
}
/**
* Verfiy that specified components designate classes that implement the
* advertised interfaces. And confrorm to expectations of MetaData.
*
* @param component the Profile object for the components
* @throws VerifyException if an error occurs
*/
public void verifyType( final Profile component,
final Class clazz )
throws VerifyException
{
final String name = component.getName();
final Class[] interfaces =
getServiceClasses( name,
component.getType().getServices(),
clazz.getClassLoader() );
m_verifier.verifyComponent( name, clazz, interfaces );
verifyDependencyPresence( component, clazz );
verifyContextPresence( component, clazz );
}
/**
* Verify that the if the component is not Contextualizable that it
* does not declare Context Entrys.
*
* @param component the component metadata
* @param clazz the class implementing component
* @throws VerifyException if fails verification check
*/
protected void verifyContextPresence( final Profile component,
final Class clazz )
throws VerifyException
{
final Type info = component.getType();
final ContextDescriptor context = info.getContextDescriptor();
final int count = context.getEntrys().length;
if( !Contextualizable.class.isAssignableFrom( clazz ) )
{
if( 0 != count )
{
final String message =
REZ.getString( "metadata.declare-uneeded-entrys.error",
component.getName(),
getClassname( component ) );
throw new VerifyException( message );
}
}
}
/**
* Verify the component assembly logic.
* The implications verifies that the component:
* <p>Is not Composable/Serviceable and does not declare dependencys</p>
* <p>or</p>
* <p>Is Composable/Serviceable and does declare dependencys</p>
*
* @param component the component metadata
* @param clazz the class implementing component
* @throws VerifyException if fails verification check
*/
protected void verifyDependencyPresence( final Profile component,
final Class clazz )
throws VerifyException
{
final int count = component.getAssociations().length;
final boolean aquiresServices =
Composable.class.isAssignableFrom( clazz ) ||
Serviceable.class.isAssignableFrom( clazz );
if( !aquiresServices )
{
if( 0 != count )
{
final String message =
REZ.getString( "metadata.declare-uneeded-deps.error",
component.getName(),
getClassname( component ) );
throw new VerifyException( message );
}
}
}
/**
* Retrieve an array of Classes for all the services that a Component
* offers. This method also makes sure all services offered are
* interfaces.
*
* @param name the name of component
* @param services the services the component offers
* @param classLoader the classLoader
* @return an array of Classes for all the services
* @throws VerifyException if an error occurs
*/
protected Class[] getServiceClasses( final String name,
final ServiceDescriptor[] services,
final ClassLoader classLoader )
throws VerifyException
{
final Class[] classes = new Class[ services.length ];
for( int i = 0; i < services.length; i++ )
{
final ServiceDesignator service = services[ i ].getService();
final String classname = service.getClassname();
try
{
classes[ i ] = classLoader.loadClass( classname );
}
catch( final Throwable t )
{
final String message =
REZ.getString( "metadata.bad-service-class.error",
name,
classname,
t.toString() );
throw new VerifyException( message, t );
}
}
return classes;
}
/**
* Load class object for specified Profile.
*
* @param classLoader the ClassLoader to use
* @param component the meta data associate with component
* @return the Class object
* @throws VerifyException if unable to aquire class object
*/
private Class getClass( final ClassLoader classLoader,
final Profile component )
throws VerifyException
{
Class clazz = null;
try
{
clazz = classLoader.loadClass( getClassname( component ) );
}
catch( final Exception e )
{
final String message =
REZ.getString( "assembly.bad-class.error",
component.getName(),
getClassname( component ),
e.toString() );
throw new VerifyException( message );
}
return clazz;
}
/**
* Utility method to aquire classname for component.
*
* @param component the component
* @return the classname for component
*/
private String getClassname( final Profile component )
{
return component.getType().getInfo().getImplementationKey();
}
}
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/verifier/Resources.properties
Index: Resources.properties
===================================================================
#Assembly Verifier
assembly.valid-names.notice=Verifying that the names specified for Component
are valid.
assembly.unique-names.notice=Verifying that the names specified for the
Components are unique.
assembly.dependencies-mapping.notice=Verifying that the dependency mapping is
valid according to ComponentInfos.
assembly.dependency-references.notice=Verifying that the dependency mapping
for every Component is valid with respect to other components.
assembly.nocircular-dependencies.notice=Verifying that there are no circular
dependencies between Components.
assembly.component-type.notice=Verifying that the specified Components have
valid types.
assembly.circular-dependency.error=Component named "{0}" has a circular
dependency via path: {1}.
assembly.missing-dependency.error=Component "{1}" that satisfies the
dependency with role "{0}" of Component "{2}" does not exist.
assembly.dependency-missing-service.error=Profile {0}" is associated to
profile "{1}" under the role "{2}" however, the provider does not supply the
required service "{3}".
assembly.bad-class.error=Unable to load class "{1}" for Component named
"{0}". (Reason: {2}).
assembly.bad-name.error=The Component name "{0}" is invalid. Valid names
contain only letters, digits and the '-' character.
assembly.duplicate-name.error=The name "{0}" is used by multiple Components
in assembly.
assembly.unknown-dependency.error=Unknown dependency named "{0}" with role
"{1}" declared for Component {2}.
assembly.unspecified-dependency.error=Dependency for role "{0}" not specified
for the Component named "{1}".
#MetaData Verifier
metadata.bad-service-class.error=Unable to load service class "{1}" for
Component named "{0}". (Reason: {2}).
metadata.nodeclare-deps.error=Component named "{0}" of type "{1}" is
Composable or Serviceable but does not declare any dependencies.
metadata.declare-uneeded-deps.error=Component named "{0}" of type "{1}" is
not Composable or Serviceable but declares dependencies.
metadata.declare-uneeded-entrys.error=Component named "{0}" of type "{1}" is
not Contextualizable but declares Context Entrys.
1.1
jakarta-avalon-excalibur/assembly/src/java/org/apache/excalibur/merlin/model/verifier/package.html
Index: package.html
===================================================================
<body>
A set of classes supporting verification of components and component
assemblies using class and component meta-data information.
<h3>Overview</h3>
<p>This package includes a set of classes supporting the verification of the
integrity of a component class and the verification of the integrity of a
relationships and inter-dependecies based on supplied meta-data. The
[EMAIL PROTECTED]
org.apache.excalibur.merlin.model.verifier.ComponentVerifier} provides
support for the validation of a component class. It includes validation
functions that check for structural and best-practice integrity related to
the class, lifecycle patterns and service. The
[EMAIL PROTECTED]
org.apache.excalibur.merlin.model.verifier.AssemblyVerifier} performs
validation of the structural integrity of a set component assembly based on
assembly meta-data.
</body>
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>