diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ClassLoaderManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ClassLoaderManager.java
index 636307e2d..c59594b66 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ClassLoaderManager.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ClassLoaderManager.java
@@ -8,8 +8,8 @@
package org.apache.myrmidon.components.deployer;
import java.io.File;
-import org.apache.myrmidon.interfaces.deployer.DeploymentException;
import org.apache.avalon.framework.component.Component;
+import org.apache.myrmidon.interfaces.deployer.DeploymentException;
/**
* Manages a classloader hierarchy.
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java
index f3e31d808..590b0610a 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java
@@ -17,23 +17,22 @@ import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.myrmidon.converter.Converter;
+import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
+import org.apache.myrmidon.interfaces.deployer.ConverterDefinition;
import org.apache.myrmidon.interfaces.deployer.Deployer;
import org.apache.myrmidon.interfaces.deployer.DeploymentException;
-import org.apache.myrmidon.interfaces.deployer.TypeDeployer;
import org.apache.myrmidon.interfaces.deployer.TypeDefinition;
-import org.apache.myrmidon.interfaces.deployer.ConverterDefinition;
-import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
-import org.apache.myrmidon.interfaces.type.TypeManager;
-import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
+import org.apache.myrmidon.interfaces.deployer.TypeDeployer;
import org.apache.myrmidon.interfaces.role.RoleManager;
-import org.apache.myrmidon.converter.Converter;
+import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
+import org.apache.myrmidon.interfaces.type.TypeManager;
/**
* This class deploys roles, types and services from a typelib.
*
* @author Peter Donald
+ * @author Adam Murdoch
* @version $Revision$ $Date$
*/
public class DefaultDeployer
@@ -136,57 +135,10 @@ public class DefaultDeployer
return deployment;
}
- /**
- * Creates a type definition.
- */
- public TypeDefinition createTypeDefinition( final Configuration configuration )
- throws ConfigurationException
- {
- final String converterShorthand = m_roleManager.getNameForRole( Converter.ROLE );
- final String roleShorthand = configuration.getName();
- if( roleShorthand.equals( converterShorthand ) )
- {
- // A converter definition
- final String className = configuration.getAttribute( "classname" );
- final String source = configuration.getAttribute( "source" );
- final String destination = configuration.getAttribute( "destination" );
- return new ConverterDefinition( className, source, destination );
- }
- else
- {
- // A type definition
- final String typeName = configuration.getAttribute( "name" );
- final String className = configuration.getAttribute( "classname" );
- return new TypeDefinition( typeName, roleShorthand, className );
- }
- }
-
- /**
- * Handles a converter definition.
- */
- private void handleConverter( final Deployment deployment,
- final String className,
- final String source,
- final String destination )
- throws Exception
- {
- m_converterRegistry.registerConverter( className, source, destination );
- final DefaultTypeFactory factory = deployment.getFactory( Converter.class );
- factory.addNameClassMapping( className, className );
- m_typeManager.registerType( Converter.class, className, factory );
-
- if( getLogger().isDebugEnabled() )
- {
- final String message =
- REZ.getString( "register-converter.notice", source, destination );
- getLogger().debug( message );
- }
- }
-
/**
* Handles a type definition.
*/
- public void handleType( final Deployment deployment,
+ public void deployType( final Deployment deployment,
final TypeDefinition typeDef )
throws Exception
{
@@ -263,10 +215,32 @@ public class DefaultDeployer
}
}
+ /**
+ * Handles a converter definition.
+ */
+ private void handleConverter( final Deployment deployment,
+ final String className,
+ final String source,
+ final String destination )
+ throws Exception
+ {
+ m_converterRegistry.registerConverter( className, source, destination );
+ final DefaultTypeFactory factory = deployment.getFactory( Converter.class );
+ factory.addNameClassMapping( className, className );
+ m_typeManager.registerType( Converter.class, className, factory );
+
+ if( getLogger().isDebugEnabled() )
+ {
+ final String message =
+ REZ.getString( "register-converter.notice", source, destination );
+ getLogger().debug( message );
+ }
+ }
+
/**
* Handles a role definition.
*/
- public void handleRole( final Deployment deployment,
+ public void deployRole( final Deployment deployment,
final RoleDefinition roleDef )
{
final String name = roleDef.getShortHand();
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java
index 418f5a5ed..9f8fde92f 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java
@@ -12,34 +12,24 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
-import org.apache.avalon.framework.component.ComponentException;
-import org.apache.avalon.framework.component.ComponentManager;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.myrmidon.converter.Converter;
-import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
-import org.apache.myrmidon.interfaces.deployer.ConverterDefinition;
import org.apache.myrmidon.interfaces.deployer.DeploymentException;
import org.apache.myrmidon.interfaces.deployer.TypeDefinition;
import org.apache.myrmidon.interfaces.deployer.TypeDeployer;
-import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
-import org.apache.myrmidon.interfaces.type.TypeManager;
import org.xml.sax.XMLReader;
/**
* This class deploys type libraries from a ClassLoader into a registry.
*
* @author Peter Donald
+ * @author Adam Murdoch
* @version $Revision$ $Date$
*/
class Deployment
@@ -49,13 +39,19 @@ class Deployment
private final static Resources REZ =
ResourceManager.getPackageResources( Deployment.class );
- private final static String DESCRIPTOR_NAME = "META-INF/ant-descriptor.xml";
+ private final static String TYPE_DESCRIPTOR_NAME = "META-INF/ant-descriptor.xml";
private final static String ROLE_DESCRIPTOR_NAME = "META-INF/ant-roles.xml";
+ private final static String SERVICE_DESCRIPTOR_NAME = "META-INF/ant-services.xml";
private ClassLoader m_classLoader;
private DefaultDeployer m_deployer;
- private String[] m_descriptorUrls;
- private Configuration[] m_descriptors;
+ private TypeDescriptor[] m_descriptors;
+ private ServiceDescriptor[] m_services;
+
+ // TODO - create and configure these in DefaultDeployer
+ private DescriptorBuilder m_roleBuilder = new RoleDescriptorBuilder();
+ private DescriptorBuilder m_typeBuilder = new TypeDescriptorBuilder();
+ private DescriptorBuilder m_serviceBuilder = new ServiceDescriptorBuilder();
/** Map from role Class -> DefaultTypeFactory for that role. */
private Map m_factories = new HashMap();
@@ -69,12 +65,13 @@ class Deployment
/**
* Load the descriptors. Deploys all roles, then loads the descriptors
* for, but does not deploy, all the types.
+ *
+ * @param jarUrl The URL for the typelib, used to locate the descriptors.
+ * If null, the resources from the classloader are used.
*/
public void loadDescriptors( final URL jarUrl )
throws Exception
{
- final ArrayList descriptors = new ArrayList();
-
// Create a SAX parser to assemble the descriptors into Configuration
// objects
final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
@@ -86,45 +83,51 @@ class Deployment
parser.setContentHandler( handler );
parser.setErrorHandler( handler );
- // Load the role descriptors, and deploy all roles
- final List roleUrls = locateResources( ROLE_DESCRIPTOR_NAME, jarUrl );
- for( Iterator iterator = roleUrls.iterator(); iterator.hasNext(); )
- {
- String url = (String)iterator.next();
- try
- {
- parser.parse( url );
- }
- catch( FileNotFoundException e )
- {
- // Ignore - this happens when jarUrl != null and the Jar does
- // not contain a role descriptor.
- continue;
- }
+ // Build the role descriptors
+ final ArrayList roleUrls = locateResources( ROLE_DESCRIPTOR_NAME, jarUrl );
+ final ArrayList roleDescriptors = buildDescriptors( roleUrls, m_roleBuilder, parser, handler );
- handleRoleDescriptor( handler.getConfiguration(), url );
+ // Deploy the roles
+ // TODO - need to defer this
+ for( int i = 0; i < roleDescriptors.size(); i++ )
+ {
+ final RoleDescriptor descriptor = (RoleDescriptor)roleDescriptors.get( i );
+ deployRoles( descriptor );
}
- // Load type descriptors
- final List typeUrls = locateResources( DESCRIPTOR_NAME, jarUrl );
- for( Iterator iterator = typeUrls.iterator(); iterator.hasNext(); )
- {
- String url = (String)iterator.next();
- try
- {
- parser.parse( url.toString() );
- }
- catch( FileNotFoundException e )
- {
- // Ignore - this happens when jarUrl != null and the Jar does
- // not contain a type descriptor
- continue;
- }
+ // Build the type descriptors
+ final ArrayList typeUrls = locateResources( TYPE_DESCRIPTOR_NAME, jarUrl );
+ final ArrayList typeDescriptors = buildDescriptors( typeUrls, m_typeBuilder, parser, handler );
+ m_descriptors = (TypeDescriptor[])typeDescriptors.toArray( new TypeDescriptor[ typeDescriptors.size() ] );
- descriptors.add( handler.getConfiguration() );
+ // Build the service descriptors
+ final ArrayList serviceUrls = locateResources( SERVICE_DESCRIPTOR_NAME, jarUrl );
+ final ArrayList serviceDescriptors = buildDescriptors( serviceUrls, m_serviceBuilder, parser, handler );
+ m_services = (ServiceDescriptor[])serviceDescriptors.toArray( new ServiceDescriptor[ serviceDescriptors.size() ] );
+ }
+
+ /**
+ * Returns the type factory for a role.
+ */
+ public DefaultTypeFactory getFactory( final Class roleType )
+ {
+ DefaultTypeFactory factory = (DefaultTypeFactory)m_factories.get( roleType );
+
+ if( null == factory )
+ {
+ factory = new DefaultTypeFactory( m_classLoader );
+ m_factories.put( roleType, factory );
}
- m_descriptorUrls = (String[])typeUrls.toArray( new String[ typeUrls.size() ] );
- m_descriptors = (Configuration[])descriptors.toArray( new Configuration[ descriptors.size() ] );
+
+ return factory;
+ }
+
+ /**
+ * Returns the classloader for this deployment.
+ */
+ public ClassLoader getClassLoader()
+ {
+ return m_classLoader;
}
/**
@@ -135,8 +138,8 @@ class Deployment
{
for( int i = 0; i < m_descriptors.length; i++ )
{
- Configuration descriptor = m_descriptors[ i ];
- deployFromDescriptor( descriptor, m_descriptorUrls[ i ] );
+ TypeDescriptor descriptor = m_descriptors[ i ];
+ deployTypes( descriptor );
}
}
@@ -148,19 +151,21 @@ class Deployment
{
try
{
- // Locate the entry for the type
+ // Locate the definition for the type
for( int i = 0; i < m_descriptors.length; i++ )
{
- Configuration descriptor = m_descriptors[ i ];
- final Configuration[] datatypes =
- descriptor.getChild( "types" ).getChildren( roleShorthand );
- for( int j = 0; j < datatypes.length; j++ )
+ final TypeDescriptor descriptor = m_descriptors[ i ];
+ final TypeDefinition[] definitions = descriptor.getDefinitions();
+ for( int j = 0; j < definitions.length; j++ )
{
- Configuration datatype = datatypes[ j ];
- if( datatype.getAttribute( "name" ).equals( typeName ) )
+ TypeDefinition definition = definitions[ j ];
+ if( definition.getRole().equals( roleShorthand )
+ && definition.getName().equals( typeName ) )
{
- final TypeDefinition typeDef = m_deployer.createTypeDefinition( datatype );
- m_deployer.handleType( this, typeDef );
+ // Found the definition - deploy it. Note that we
+ // keep looking for matching types, and let the deployer
+ // deal with duplicates
+ m_deployer.deployType( this, definition );
}
}
}
@@ -178,30 +183,63 @@ class Deployment
public void deployType( final TypeDefinition typeDef )
throws DeploymentException
{
- final String typeName = typeDef.getName();
- final String roleShorthand = typeDef.getRole();
try
{
- m_deployer.handleType( this, typeDef );
+ m_deployer.deployType( this, typeDef );
}
catch( Exception e )
{
- final String message = REZ.getString( "deploy-type.error", roleShorthand, typeName );
+ final String message = REZ.getString( "deploy-type.error", typeDef.getRole(), typeDef.getName() );
throw new DeploymentException( message, e );
}
}
+ /**
+ * Builds descriptors.
+ */
+ private ArrayList buildDescriptors( final ArrayList urls,
+ final DescriptorBuilder builder,
+ final XMLReader parser,
+ final SAXConfigurationHandler handler )
+ throws Exception
+ {
+ final ArrayList descriptors = new ArrayList();
+ for( int i = 0; i < urls.size(); i++ )
+ {
+ final String url = (String)urls.get( i );
+
+ // Parse the file
+ parser.parse( url );
+ final TypelibDescriptor descriptor = builder.createDescriptor( handler.getConfiguration(), url );
+ descriptors.add( descriptor );
+ }
+
+ return descriptors;
+ }
+
/**
* Locates all resources of a particular name.
*/
- private List locateResources( final String resource, final URL jarUrl )
+ private ArrayList locateResources( final String resource, final URL jarUrl )
throws Exception
{
final ArrayList urls = new ArrayList();
if( null != jarUrl )
{
final String systemID = "jar:" + jarUrl + "!/" + resource;
- urls.add( systemID );
+ try
+ {
+ // Probe the resource
+ final URL url = new URL( systemID );
+ url.openStream().close();
+
+ // Add to the list
+ urls.add( systemID );
+ }
+ catch( FileNotFoundException e )
+ {
+ // Ignore
+ }
}
else
{
@@ -216,77 +254,45 @@ class Deployment
}
/**
- * Configure RoleManager based on contents of single descriptor.
- *
- * @param descriptor the descriptor
- * @exception ConfigurationException if an error occurs
+ * Deploys the roles from a role descriptor.
*/
- private void handleRoleDescriptor( final Configuration descriptor,
- final String url )
- throws ConfigurationException
+ private void deployRoles( final RoleDescriptor descriptor )
{
- final String message = REZ.getString( "url-deploy-roles.notice", url );
+ final String message = REZ.getString( "url-deploy-roles.notice", descriptor.getUrl() );
getLogger().info( message );
- final Configuration[] types = descriptor.getChildren( "role" );
- for( int i = 0; i < types.length; i++ )
+ final RoleDefinition[] definitions = descriptor.getDefinitions();
+ for( int i = 0; i < definitions.length; i++ )
{
- final String name = types[ i ].getAttribute( "shorthand" );
- final String role = types[ i ].getAttribute( "name" );
- final RoleDefinition roleDef = new RoleDefinition( role, name );
- m_deployer.handleRole( this, roleDef );
+ final RoleDefinition definition = definitions[ i ];
+ m_deployer.deployRole( this, definition );
}
}
/**
* Deploys all types from a typelib descriptor.
*/
- private void deployFromDescriptor( final Configuration descriptor,
- final String url )
+ private void deployTypes( final TypeDescriptor descriptor )
throws DeploymentException
{
try
{
- final String message = REZ.getString( "url-deploy-types.notice", url );
+ final String message = REZ.getString( "url-deploy-types.notice", descriptor.getUrl() );
getLogger().info( message );
// Deploy all the types
- final Configuration[] typeEntries = descriptor.getChild( "types" ).getChildren();
- for( int i = 0; i < typeEntries.length; i++ )
+ final TypeDefinition[] definitions = descriptor.getDefinitions();
+ for( int i = 0; i < definitions.length; i++ )
{
- final Configuration typeEntry = typeEntries[ i ];
- final TypeDefinition typeDef = m_deployer.createTypeDefinition( typeEntry );
- m_deployer.handleType( this, typeDef );
+ final TypeDefinition definition = definitions[ i ];
+ m_deployer.deployType( this, definition );
}
}
catch( final Exception e )
{
- final String message = REZ.getString( "deploy-lib.error", url );
+ final String message = REZ.getString( "deploy-types.error", descriptor.getUrl() );
throw new DeploymentException( message, e );
}
}
- /**
- * Returns the type factory for a role.
- */
- public DefaultTypeFactory getFactory( final Class roleType )
- {
- DefaultTypeFactory factory = (DefaultTypeFactory)m_factories.get( roleType );
-
- if( null == factory )
- {
- factory = new DefaultTypeFactory( m_classLoader );
- m_factories.put( roleType, factory );
- }
-
- return factory;
- }
-
- /**
- * Returns the classloader for this deployment.
- */
- public ClassLoader getClassLoader()
- {
- return m_classLoader;
- }
}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DescriptorBuilder.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DescriptorBuilder.java
new file mode 100644
index 000000000..701d79073
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DescriptorBuilder.java
@@ -0,0 +1,27 @@
+/*
+ * 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.myrmidon.components.deployer;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.myrmidon.interfaces.deployer.DeploymentException;
+
+/**
+ * Builds a descriptor.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+interface DescriptorBuilder
+{
+ /**
+ * Builds a descriptor from a set of configuration.
+ */
+ TypelibDescriptor createDescriptor( Configuration config,
+ String descriptorUrl )
+ throws DeploymentException;
+}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Resources.properties b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Resources.properties
index 8a443c002..91bf043c5 100644
--- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Resources.properties
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Resources.properties
@@ -4,9 +4,9 @@ register-role.notice=Registered role {0} with shorthand name {1}.
url-deploy-types.notice=Registering types from "{0}".
url-deploy-roles.notice=Registering roles from "{0}".
-deploy-from-classloader.error=Could not register types from ClassLoader {0}.
+deploy-from-classloader.error=Could not register types from ClassLoader.
deploy-from-file.error=Could not register types from type library "{0}".
-deploy-lib.error=Could not register types from "{0}".
+deploy-types.error=Could not register types from "{0}".
deploy-converter.error=Could not register converter that converts from {0} to {1}.
deploy-type.error=Could not register type {0}/{1}.
unknown-role4name.error=Unknown role "{0}".
@@ -17,6 +17,12 @@ typedef.no-name.error=Must specify name parameter.
typedef.no-role.error=Must specify type parameter.
converterdef.no-source.error=Must specify the source-type parameter.
converterdef.no-destination.error=Must specify the destination-type parameter.
+role-descriptor-version.error=Role descriptor version {0} is incompatible with current version {1}.
+build-role-descriptor.error=Could not build role descriptor from "{0}".
+type-descriptor-version.error=Type library descriptor version {0} is incompatible with current version {1}.
+build-type-descriptor.error=Could not build type library descriptor from "{0}".
+service-descriptor-version.error=Service descriptor version {0} is incompatible with current version {1}.
+build-service-descriptor.error=Could not build service descriptor from "{0}".
available-extensions.notice=The list of available extensions for type library includes; {0}
required-extensions.notice=The list of required extensions for type library includes; {0}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDescriptor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDescriptor.java
new file mode 100644
index 000000000..6e57bd8f0
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDescriptor.java
@@ -0,0 +1,44 @@
+/*
+ * 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.myrmidon.components.deployer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A typelib role descriptor, which defines a set of roles.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+class RoleDescriptor
+ extends TypelibDescriptor
+{
+ private final List m_definitions = new ArrayList();
+
+ public RoleDescriptor( final String url )
+ {
+ super( url );
+ }
+
+ /**
+ * Returns the role definitions in the descriptor.
+ */
+ public RoleDefinition[] getDefinitions()
+ {
+ return (RoleDefinition[])m_definitions.toArray( new RoleDefinition[ m_definitions.size() ] );
+ }
+
+ /**
+ * Adds a role definition to the descriptor.
+ */
+ public void addDefinition( final RoleDefinition def )
+ {
+ m_definitions.add( def );
+ }
+}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDescriptorBuilder.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDescriptorBuilder.java
new file mode 100644
index 000000000..865d3f23e
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDescriptorBuilder.java
@@ -0,0 +1,69 @@
+/*
+ * 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.myrmidon.components.deployer;
+
+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.myrmidon.interfaces.deployer.DeploymentException;
+
+/**
+ * Builds typelib role descriptors.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+class RoleDescriptorBuilder
+ implements DescriptorBuilder
+{
+ private final static Resources REZ =
+ ResourceManager.getPackageResources( RoleDescriptorBuilder.class );
+
+ private final static Version ROLE_DESCRIPTOR_VERSION = new Version( 1, 0, 0 );
+
+ /**
+ * Builds a descriptor from a set of configuration.
+ */
+ public TypelibDescriptor createDescriptor( final Configuration config,
+ final String url )
+ throws DeploymentException
+ {
+ try
+ {
+ // Check version
+ final String versionString = config.getAttribute( "version" );
+ final Version version = Version.getVersion( versionString );
+ if( ! ROLE_DESCRIPTOR_VERSION.complies( version ) )
+ {
+ final String message = REZ.getString( "role-descriptor-version.error", version, ROLE_DESCRIPTOR_VERSION );
+ throw new DeploymentException( message );
+ }
+
+ // Assemble the descriptor
+ final RoleDescriptor descriptor = new RoleDescriptor( url );
+
+ // Extract each of the role elements
+ final Configuration[] types = config.getChildren( "role" );
+ for( int i = 0; i < types.length; i++ )
+ {
+ final String name = types[ i ].getAttribute( "shorthand" );
+ final String role = types[ i ].getAttribute( "name" );
+ final RoleDefinition roleDef = new RoleDefinition( role, name );
+ descriptor.addDefinition( roleDef );
+ }
+
+ return descriptor;
+ }
+ catch( Exception e )
+ {
+ final String message = REZ.getString( "build-role-descriptor.error", url );
+ throw new DeploymentException( message, e );
+ }
+ }
+}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDefinition.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDefinition.java
new file mode 100644
index 000000000..9ae9a9109
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDefinition.java
@@ -0,0 +1,56 @@
+/*
+ * 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.myrmidon.components.deployer;
+
+import org.apache.avalon.framework.configuration.Configuration;
+
+/**
+ * A service definition.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+class ServiceDefinition
+{
+ private final String m_roleShorthand;
+ private final String m_factoryClass;
+ private final Configuration m_config;
+
+ public ServiceDefinition( final String roleShorthand,
+ final String factoryClass,
+ final Configuration config )
+ {
+ m_roleShorthand = roleShorthand;
+ m_factoryClass = factoryClass;
+ m_config = config;
+ }
+
+ /**
+ * Returns the role that the service implements.
+ */
+ public String getRoleShorthand()
+ {
+ return m_roleShorthand;
+ }
+
+ /**
+ * Returns the name of the factory class for creating the service.
+ */
+ public String getFactoryClass()
+ {
+ return m_factoryClass;
+ }
+
+ /**
+ * Returns the service configuration.
+ */
+ public Configuration getConfig()
+ {
+ return m_config;
+ }
+}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDescriptor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDescriptor.java
new file mode 100644
index 000000000..04e51062d
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDescriptor.java
@@ -0,0 +1,38 @@
+/*
+ * 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.myrmidon.components.deployer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A typelib service descriptor, which defines a set of services.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+class ServiceDescriptor
+ extends TypelibDescriptor
+{
+ private final List m_services = new ArrayList();
+
+ public ServiceDescriptor( final String url )
+ {
+ super( url );
+ }
+
+ public ServiceDefinition[] getDefinitions()
+ {
+ return (ServiceDefinition[])m_services.toArray( new ServiceDefinition[ m_services.size() ] );
+ }
+
+ public void addDefinition( final ServiceDefinition definition )
+ {
+ m_services.add( definition );
+ }
+}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDescriptorBuilder.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDescriptorBuilder.java
new file mode 100644
index 000000000..a7972e62b
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDescriptorBuilder.java
@@ -0,0 +1,58 @@
+/*
+ * 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.myrmidon.components.deployer;
+
+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.myrmidon.interfaces.deployer.DeploymentException;
+
+/**
+ * Builds typelib service descriptors.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+class ServiceDescriptorBuilder
+ implements DescriptorBuilder
+{
+ private final static Resources REZ =
+ ResourceManager.getPackageResources( ServiceDescriptorBuilder.class );
+
+ private final static Version SERVICE_DESCRIPTOR_VERSION = new Version( 1, 0, 0 );
+
+ /**
+ * Builds a descriptor from a set of configuration.
+ */
+ public TypelibDescriptor createDescriptor( final Configuration config,
+ final String url )
+ throws DeploymentException
+ {
+ try
+ {
+ // Check version
+ final String versionString = config.getAttribute( "version" );
+ final Version version = Version.getVersion( versionString );
+ if( ! SERVICE_DESCRIPTOR_VERSION.complies( version ) )
+ {
+ final String message = REZ.getString( "service-descriptor-version.error", version, SERVICE_DESCRIPTOR_VERSION );
+ throw new DeploymentException( message );
+ }
+
+ // TODO - populate the descriptor
+
+ return new ServiceDescriptor( url );
+ }
+ catch( Exception e )
+ {
+ final String message = REZ.getString( "build-service-descriptor.error", url );
+ throw new DeploymentException( message, e );
+ }
+ }
+}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypeDescriptor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypeDescriptor.java
new file mode 100644
index 000000000..17bf8f3e4
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypeDescriptor.java
@@ -0,0 +1,39 @@
+/*
+ * 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.myrmidon.components.deployer;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.myrmidon.interfaces.deployer.TypeDefinition;
+
+/**
+ * A typelib type descriptor, which defines a set of types.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+class TypeDescriptor
+ extends TypelibDescriptor
+{
+ private final List m_definitions = new ArrayList();
+
+ public TypeDescriptor( final String url )
+ {
+ super( url );
+ }
+
+ public TypeDefinition[] getDefinitions()
+ {
+ return (TypeDefinition[])m_definitions.toArray( new TypeDefinition[ m_definitions.size() ] );
+ }
+
+ public void addDefinition( final TypeDefinition def )
+ {
+ m_definitions.add( def );
+ }
+}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypeDescriptorBuilder.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypeDescriptorBuilder.java
new file mode 100644
index 000000000..3f6a4e5a3
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypeDescriptorBuilder.java
@@ -0,0 +1,95 @@
+/*
+ * 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.myrmidon.components.deployer;
+
+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.myrmidon.interfaces.deployer.ConverterDefinition;
+import org.apache.myrmidon.interfaces.deployer.DeploymentException;
+import org.apache.myrmidon.interfaces.deployer.TypeDefinition;
+
+/**
+ * Builds typelib type descriptors.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+class TypeDescriptorBuilder
+ implements DescriptorBuilder
+{
+ private final static Resources REZ =
+ ResourceManager.getPackageResources( TypeDescriptorBuilder.class );
+
+ private final static Version TYPE_DESCRIPTOR_VERSION = new Version( 1, 0, 0 );
+
+ /**
+ * Builds a descriptor from a set of configuration.
+ */
+ public TypelibDescriptor createDescriptor( final Configuration config,
+ final String url )
+ throws DeploymentException
+ {
+ try
+ {
+ // Check version
+ final String versionString = config.getAttribute( "version" );
+ final Version version = Version.getVersion( versionString );
+ if( ! TYPE_DESCRIPTOR_VERSION.complies( version ) )
+ {
+ final String message = REZ.getString( "type-descriptor-version.error", version, TYPE_DESCRIPTOR_VERSION );
+ throw new DeploymentException( message );
+ }
+
+ // Assemble the descriptor
+ final TypeDescriptor descriptor = new TypeDescriptor( url );
+
+ // Extract each of the types elements
+ final Configuration[] typeEntries = config.getChild( "types" ).getChildren();
+ for( int i = 0; i < typeEntries.length; i++ )
+ {
+ final Configuration typeEntry = typeEntries[ i ];
+ final TypeDefinition typeDef = createTypeDefinition( typeEntry );
+ descriptor.addDefinition( typeDef );
+ }
+
+ return descriptor;
+ }
+ catch( Exception e )
+ {
+ final String message = REZ.getString( "build-type-descriptor.error", url );
+ throw new DeploymentException( message, e );
+ }
+ }
+
+ /**
+ * Creates a type definition.
+ */
+ public TypeDefinition createTypeDefinition( final Configuration configuration )
+ throws ConfigurationException
+ {
+ final String roleShorthand = configuration.getName();
+ if( roleShorthand.equals( "converter" ) )
+ {
+ // A converter definition
+ final String className = configuration.getAttribute( "classname" );
+ final String source = configuration.getAttribute( "source" );
+ final String destination = configuration.getAttribute( "destination" );
+ return new ConverterDefinition( className, source, destination );
+ }
+ else
+ {
+ // A type definition
+ final String typeName = configuration.getAttribute( "name" );
+ final String className = configuration.getAttribute( "classname" );
+ return new TypeDefinition( typeName, roleShorthand, className );
+ }
+ }
+}
diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypelibDescriptor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypelibDescriptor.java
new file mode 100644
index 000000000..7f0e113cd
--- /dev/null
+++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypelibDescriptor.java
@@ -0,0 +1,32 @@
+/*
+ * 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.myrmidon.components.deployer;
+
+/**
+ * A descriptor from a typelib.
+ *
+ * @author Adam Murdoch
+ * @version $Revision$ $Date$
+ */
+class TypelibDescriptor
+{
+ private final String m_url;
+
+ public TypelibDescriptor( final String url )
+ {
+ m_url = url;
+ }
+
+ /**
+ * Returns the descriptor URL.
+ */
+ public String getUrl()
+ {
+ return m_url;
+ }
+}