* Add TypeDeployer interface, which allows control over the deployment of types from a typelib. * Add RoleManager.addNameRoleMapping(). * TypeManager methods now take a role Class object, rather than role name. * Replace implicit role and type deployment in DefaultRoleManager.initialize() and DefaultDeployer.initialize() with explicit createDeployer( ClassLoader ) method. * DefaultDeployer now keeps track of the ClassLoader created for each typelib. * Moved all ClassLoader creation to DefaultDeployer, for the time being. * ConverterDef and AbstractTypeDef now use Deployer, rather than deploying manually. * Fixed DefaultMasterConverter for the case where destination is an interface, and there is no appropriate converter registered. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271030 13f79535-47bb-0310-9956-ffa450edef68master
@@ -54,7 +54,7 @@ public class Property | |||
{ | |||
try | |||
{ | |||
final TypeFactory typeFactory = getTypeFactory( DataType.ROLE ); | |||
final TypeFactory typeFactory = getTypeFactory( DataType.class ); | |||
final DataType value = (DataType)typeFactory.create( children[ i ].getName() ); | |||
configure( value, children[ i ] ); | |||
setValue( value ); | |||
@@ -8,15 +8,12 @@ | |||
package org.apache.antlib.runtime; | |||
import java.io.File; | |||
import java.net.URL; | |||
import org.apache.avalon.excalibur.i18n.ResourceManager; | |||
import org.apache.avalon.excalibur.i18n.Resources; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.converter.Converter; | |||
import org.apache.myrmidon.interfaces.converter.ConverterRegistry; | |||
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | |||
import org.apache.myrmidon.interfaces.type.TypeManager; | |||
import org.apache.myrmidon.interfaces.deployer.Deployer; | |||
import org.apache.myrmidon.interfaces.deployer.TypeDeployer; | |||
/** | |||
* Task to define a converter. | |||
@@ -80,15 +77,10 @@ public class ConverterDef | |||
try | |||
{ | |||
final ConverterRegistry converterRegistry = (ConverterRegistry)getService( ConverterRegistry.class ); | |||
converterRegistry.registerConverter( m_classname, m_sourceType, m_destinationType ); | |||
final URL url = m_lib.toURL(); | |||
final DefaultTypeFactory factory = new DefaultTypeFactory( new URL[]{url} ); | |||
factory.addNameClassMapping( m_classname, m_classname ); | |||
final TypeManager typeManager = (TypeManager)getService( TypeManager.class ); | |||
typeManager.registerType( Converter.ROLE, m_classname, factory ); | |||
// Locate the deployer, then deploy the converter | |||
final Deployer deployer = (Deployer)getService( Deployer.class ); | |||
final TypeDeployer typeDeployer = deployer.createDeployer( m_lib ); | |||
typeDeployer.deployConverter( m_classname, m_sourceType, m_destinationType ); | |||
} | |||
catch( final Exception e ) | |||
{ | |||
@@ -50,7 +50,7 @@ public class Facility | |||
{ | |||
try | |||
{ | |||
final TypeFactory typeFactory = getTypeFactory( AspectHandler.ROLE ); | |||
final TypeFactory typeFactory = getTypeFactory( AspectHandler.class ); | |||
m_aspectHandler = (AspectHandler)typeFactory.create( children[ 0 ].getName() ); | |||
} | |||
catch( final Exception e ) | |||
@@ -14,6 +14,7 @@ import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.interfaces.deployer.Deployer; | |||
import org.apache.myrmidon.interfaces.deployer.DeploymentException; | |||
import org.apache.myrmidon.interfaces.deployer.TypeDeployer; | |||
/** | |||
* Task to import a tasklib. | |||
@@ -45,7 +46,8 @@ public class Import | |||
try | |||
{ | |||
final Deployer deployer = (Deployer)getService( Deployer.class ); | |||
deployer.deploy( m_lib ); | |||
TypeDeployer typeDeployer = deployer.createDeployer( m_lib ); | |||
typeDeployer.deployAll(); | |||
} | |||
catch( final DeploymentException de ) | |||
{ | |||
@@ -24,7 +24,7 @@ public class TypeDef | |||
m_type = type; | |||
} | |||
protected String getTypeName() | |||
protected String getRoleShorthand() | |||
{ | |||
return m_type; | |||
} | |||
@@ -403,6 +403,9 @@ public class DefaultConfigurer | |||
return configurer; | |||
} | |||
/** | |||
* Creates and configures an inline object. | |||
*/ | |||
private Object setupChild( final ConfigurationState state, | |||
final Configuration element, | |||
final Context context, | |||
@@ -424,14 +427,13 @@ public class DefaultConfigurer | |||
if( type.isInterface() ) | |||
{ | |||
child = createdTypedObject( name, type ); | |||
configureObject( child, element, context ); | |||
} | |||
else | |||
{ | |||
child = createObject( type ); | |||
configureObject( child, element, context ); | |||
} | |||
} | |||
configureObject( child, element, context ); | |||
return child; | |||
} | |||
@@ -444,7 +446,7 @@ public class DefaultConfigurer | |||
final Class type ) | |||
throws ConfigurationException | |||
{ | |||
final TypeFactory factory = getTypeFactory( type.getName() ); | |||
final TypeFactory factory = getTypeFactory( type ); | |||
try | |||
{ | |||
return factory.create( name ); | |||
@@ -481,7 +483,7 @@ public class DefaultConfigurer | |||
/** | |||
* Locates a type factory. | |||
*/ | |||
protected final TypeFactory getTypeFactory( final String role ) | |||
protected final TypeFactory getTypeFactory( final Class role ) | |||
throws ConfigurationException | |||
{ | |||
try | |||
@@ -490,7 +492,7 @@ public class DefaultConfigurer | |||
} | |||
catch( final TypeException te ) | |||
{ | |||
final String message = REZ.getString( "no-factory-for-role.error", role ); | |||
final String message = REZ.getString( "no-factory-for-role.error", role.getName() ); | |||
throw new ConfigurationException( message, te ); | |||
} | |||
} | |||
@@ -21,4 +21,5 @@ bad-set-element.error=Could not handle element <{1}>, nested in element <{0}>. | |||
no-content.error=Text content is not allowed for element <{0}>. | |||
bad-set-content.error=Could not set text content for element <{0}>. | |||
typed-adder-non-interface.error=The typed adder for class "{0}" must have a single parameter that is an interface rather than {1} which defines a class. | |||
no-factory-for-role.error=Unable to locate type factory for role "{0}" | |||
no-factory-for-role.error=Unable to locate type factory for role "{0}" | |||
create-typed-object.error=Could not create an object of type "{0}" of class {1}. |
@@ -53,7 +53,7 @@ public class DefaultMasterConverter | |||
final TypeManager typeManager = (TypeManager)componentManager.lookup( TypeManager.ROLE ); | |||
try | |||
{ | |||
m_factory = typeManager.getFactory( Converter.ROLE ); | |||
m_factory = typeManager.getFactory( Converter.class ); | |||
} | |||
catch( final TypeException te ) | |||
{ | |||
@@ -132,11 +132,10 @@ public class DefaultMasterConverter | |||
final Class destination ) | |||
throws ConverterException | |||
{ | |||
Class clazz = destination; | |||
//TODO: Maybe we should search the source classes hierarchy aswell | |||
final Class terminator = Object.class; | |||
while( terminator != clazz ) | |||
for( Class clazz = destination; | |||
clazz != null; | |||
clazz = clazz.getSuperclass() ) | |||
{ | |||
final String name = | |||
m_registry.getConverterName( originalClass.getName(), | |||
@@ -145,8 +144,6 @@ public class DefaultMasterConverter | |||
{ | |||
return name; | |||
} | |||
clazz = clazz.getSuperclass(); | |||
} | |||
final String message = | |||
@@ -14,33 +14,22 @@ import java.net.URL; | |||
import java.net.URLClassLoader; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Enumeration; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import java.util.jar.Manifest; | |||
import javax.xml.parsers.SAXParser; | |||
import javax.xml.parsers.SAXParserFactory; | |||
import org.apache.avalon.excalibur.extension.Extension; | |||
import org.apache.avalon.excalibur.extension.OptionalPackage; | |||
import org.apache.avalon.excalibur.extension.PackageManager; | |||
import org.apache.avalon.excalibur.i18n.ResourceManager; | |||
import org.apache.avalon.excalibur.i18n.Resources; | |||
import org.apache.avalon.framework.activity.Initializable; | |||
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.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.Deployer; | |||
import org.apache.myrmidon.interfaces.deployer.DeploymentException; | |||
import org.apache.myrmidon.interfaces.deployer.TypeDeployer; | |||
import org.apache.myrmidon.interfaces.extensions.ExtensionManager; | |||
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 a .tsk file into a registry. | |||
@@ -49,16 +38,38 @@ import org.xml.sax.XMLReader; | |||
*/ | |||
public class DefaultDeployer | |||
extends AbstractLogEnabled | |||
implements Deployer, Initializable, Composable | |||
implements Deployer, Composable | |||
{ | |||
private final static Resources REZ = | |||
ResourceManager.getPackageResources( DefaultDeployer.class ); | |||
private ConverterRegistry m_converterRegistry; | |||
private TypeManager m_typeManager; | |||
private RoleManager m_roleManager; | |||
private Deployer m_parent; | |||
private ComponentManager m_componentManager; | |||
private PackageManager m_packageManager; | |||
/** Map from ClassLoader to the deployer for that class loader. */ | |||
private Map m_classLoaderDeployers = new HashMap(); | |||
/** | |||
* Map from File to the ClassLoader for that library. This map is shared | |||
* by all descendents of the root deployer. | |||
*/ | |||
private Map m_fileDeployers; | |||
/** | |||
* Creates a root deployer. | |||
*/ | |||
public DefaultDeployer() | |||
{ | |||
m_fileDeployers = new HashMap(); | |||
} | |||
private DefaultDeployer( final DefaultDeployer parent ) | |||
{ | |||
m_parent = parent; | |||
m_fileDeployers = parent.m_fileDeployers; | |||
} | |||
/** | |||
* Retrieve relevent services needed to deploy. | |||
* | |||
@@ -68,145 +79,99 @@ public class DefaultDeployer | |||
public void compose( final ComponentManager componentManager ) | |||
throws ComponentException | |||
{ | |||
m_converterRegistry = (ConverterRegistry)componentManager.lookup( ConverterRegistry.ROLE ); | |||
m_typeManager = (TypeManager)componentManager.lookup( TypeManager.ROLE ); | |||
m_roleManager = (RoleManager)componentManager.lookup( RoleManager.ROLE ); | |||
m_componentManager = componentManager; | |||
final ExtensionManager extensionManager = | |||
(ExtensionManager)componentManager.lookup( ExtensionManager.ROLE ); | |||
m_packageManager = new PackageManager( extensionManager ); | |||
} | |||
public void initialize() | |||
throws Exception | |||
/** | |||
* Creates a child deployer. | |||
*/ | |||
public Deployer createChildDeployer( ComponentManager componentManager ) | |||
throws ComponentException | |||
{ | |||
final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); | |||
final SAXParser saxParser = saxParserFactory.newSAXParser(); | |||
final XMLReader parser = saxParser.getXMLReader(); | |||
//parser.setFeature( "http://xml.org/sax/features/namespace-prefixes", false ); | |||
final SAXConfigurationHandler handler = new SAXConfigurationHandler(); | |||
parser.setContentHandler( handler ); | |||
parser.setErrorHandler( handler ); | |||
final ClassLoader classLoader = getClass().getClassLoader(); | |||
final Enumeration enum = classLoader.getResources( Deployment.DESCRIPTOR_NAME ); | |||
while( enum.hasMoreElements() ) | |||
{ | |||
final URL url = (URL)enum.nextElement(); | |||
parser.parse( url.toString() ); | |||
final String message = REZ.getString( "url-deploy.notice", url ); | |||
getLogger().debug( message ); | |||
deployFromDescriptor( handler.getConfiguration(), classLoader, url ); | |||
} | |||
final DefaultDeployer child = new DefaultDeployer( this ); | |||
setupLogger( child ); | |||
child.compose( componentManager ); | |||
return child; | |||
} | |||
public void deploy( final File file ) | |||
/** | |||
* Returns the deployer for a ClassLoader, creating the deployer if | |||
* necessary. | |||
*/ | |||
public TypeDeployer createDeployer( final ClassLoader loader ) | |||
throws DeploymentException | |||
{ | |||
if( getLogger().isInfoEnabled() ) | |||
{ | |||
final String message = REZ.getString( "file-deploy.notice", file ); | |||
getLogger().info( message ); | |||
} | |||
checkFile( file ); | |||
try | |||
{ | |||
final File[] extensions = getOptionalPackagesFor( file ); | |||
final URL[] urls = buildClasspath( file, extensions ); | |||
final Deployment deployment = new Deployment( file ); | |||
final Configuration descriptor = deployment.getDescriptor(); | |||
final URLClassLoader classLoader = | |||
new URLClassLoader( urls, Thread.currentThread().getContextClassLoader() ); | |||
deployFromDescriptor( descriptor, classLoader, deployment.getURL() ); | |||
} | |||
catch( final DeploymentException de ) | |||
{ | |||
throw de; | |||
return createDeployment( loader, null ); | |||
} | |||
catch( final Exception e ) | |||
catch( Exception e ) | |||
{ | |||
final String message = REZ.getString( "deploy-lib.error" ); | |||
final String message = REZ.getString( "deploy-from-classloader.error" ); | |||
throw new DeploymentException( message, e ); | |||
} | |||
} | |||
public void deployConverter( final String name, final File file ) | |||
/** | |||
* Returns the deployer for a type library, creating the deployer if | |||
* necessary. | |||
*/ | |||
public TypeDeployer createDeployer( final File file ) | |||
throws DeploymentException | |||
{ | |||
checkFile( file ); | |||
final Deployment deployment = new Deployment( file ); | |||
final Configuration descriptor = deployment.getDescriptor(); | |||
final DefaultTypeFactory factory = new DefaultTypeFactory( deployment.getURL() ); | |||
try | |||
{ | |||
final Configuration[] converters = | |||
descriptor.getChild( "converters" ).getChildren( "converter" ); | |||
for( int i = 0; i < converters.length; i++ ) | |||
{ | |||
if( converters[ i ].getAttribute( "classname" ).equals( name ) ) | |||
{ | |||
handleConverter( converters[ i ], factory ); | |||
break; | |||
} | |||
} | |||
} | |||
catch( final ConfigurationException ce ) | |||
{ | |||
final String message = REZ.getString( "bad-descriptor.error" ); | |||
throw new DeploymentException( message, ce ); | |||
URLClassLoader classLoader = getClassLoaderForFile( file ); | |||
return createDeployment( classLoader, file.toURL() ); | |||
} | |||
catch( final Exception e ) | |||
catch( Exception e ) | |||
{ | |||
final String message = REZ.getString( "deploy-converter.error", name ); | |||
final String message = REZ.getString( "deploy-from-file.error", file ); | |||
throw new DeploymentException( message, e ); | |||
} | |||
} | |||
public void deployType( final String role, final String name, final File file ) | |||
throws DeploymentException | |||
/** | |||
* Locates the classloader for a typelib file. | |||
*/ | |||
private URLClassLoader getClassLoaderForFile( final File file ) | |||
throws Exception | |||
{ | |||
checkFile( file ); | |||
File canonFile = file.getCanonicalFile(); | |||
final String shorthand = getNameForRole( role ); | |||
final Deployment deployment = new Deployment( file ); | |||
final Configuration descriptor = deployment.getDescriptor(); | |||
final DefaultTypeFactory factory = new DefaultTypeFactory( deployment.getURL() ); | |||
try | |||
{ | |||
final Configuration[] datatypes = | |||
descriptor.getChild( "types" ).getChildren( shorthand ); | |||
for( int i = 0; i < datatypes.length; i++ ) | |||
{ | |||
if( datatypes[ i ].getAttribute( "name" ).equals( name ) ) | |||
{ | |||
handleType( role, datatypes[ i ], factory ); | |||
break; | |||
} | |||
} | |||
} | |||
catch( final ConfigurationException ce ) | |||
// Locate cached classloader, creating it if necessary | |||
URLClassLoader classLoader = (URLClassLoader)m_fileDeployers.get( canonFile ); | |||
if( classLoader == null ) | |||
{ | |||
final String message = REZ.getString( "bad-descriptor.error" ); | |||
throw new DeploymentException( message, ce ); | |||
checkFile( canonFile ); | |||
final File[] extensions = getOptionalPackagesFor( canonFile ); | |||
final URL[] urls = buildClasspath( canonFile, extensions ); | |||
classLoader = new URLClassLoader( urls, Thread.currentThread().getContextClassLoader() ); | |||
m_fileDeployers.put( canonFile, classLoader ); | |||
} | |||
catch( final Exception e ) | |||
return classLoader; | |||
} | |||
/** | |||
* Creates a deployer for a ClassLoader. | |||
*/ | |||
private Deployment createDeployment( final ClassLoader loader, | |||
final URL jarUrl ) throws Exception | |||
{ | |||
// Locate cached deployer, creating it if necessary | |||
Deployment deployment = (Deployment)m_classLoaderDeployers.get( loader ); | |||
if( deployment == null ) | |||
{ | |||
final String message = REZ.getString( "deploy-type.error", name ); | |||
throw new DeploymentException( message, e ); | |||
deployment = new Deployment( loader, m_componentManager ); | |||
setupLogger( deployment ); | |||
deployment.loadDescriptors( jarUrl ); | |||
m_classLoaderDeployers.put( loader, deployment ); | |||
} | |||
return deployment; | |||
} | |||
private URL[] buildClasspath( final File file, final File[] dependencies ) | |||
@@ -243,10 +208,10 @@ public class DefaultDeployer | |||
if( getLogger().isDebugEnabled() ) | |||
{ | |||
final String message1 = | |||
REZ.getString( "available-extensions", Arrays.asList( available ) ); | |||
REZ.getString( "available-extensions.notice", Arrays.asList( available ) ); | |||
getLogger().debug( message1 ); | |||
final String message2 = | |||
REZ.getString( "required-extensions", Arrays.asList( required ) ); | |||
REZ.getString( "required-extensions.notice", Arrays.asList( required ) ); | |||
getLogger().debug( message2 ); | |||
} | |||
@@ -279,7 +244,7 @@ public class DefaultDeployer | |||
} | |||
final String message = | |||
REZ.getString( "unsatisfied.extensions", new Integer( size ) ); | |||
REZ.getString( "unsatisfied.extensions.error", new Integer( size ) ); | |||
throw new Exception( message ); | |||
} | |||
@@ -288,87 +253,9 @@ public class DefaultDeployer | |||
return OptionalPackage.toFiles( packages ); | |||
} | |||
private void deployFromDescriptor( final Configuration descriptor, | |||
final ClassLoader classLoader, | |||
final URL url ) | |||
throws DeploymentException, Exception | |||
{ | |||
try | |||
{ | |||
//Have to keep a new factory per role | |||
//To avoid name clashes (ie a datatype and task with same name) | |||
final HashMap factorys = new HashMap(); | |||
final Configuration[] types = descriptor.getChild( "types" ).getChildren(); | |||
for( int i = 0; i < types.length; i++ ) | |||
{ | |||
final String name = types[ i ].getName(); | |||
final String role = getRoleForName( name ); | |||
final DefaultTypeFactory factory = getFactory( role, classLoader, factorys ); | |||
handleType( role, types[ i ], factory ); | |||
} | |||
final DefaultTypeFactory factory = new DefaultTypeFactory( classLoader ); | |||
final Configuration[] converters = descriptor.getChild( "converters" ).getChildren(); | |||
for( int i = 0; i < converters.length; i++ ) | |||
{ | |||
handleConverter( converters[ i ], factory ); | |||
} | |||
} | |||
catch( final DeploymentException de ) | |||
{ | |||
throw de; | |||
} | |||
catch( final Exception e ) | |||
{ | |||
final String message = REZ.getString( "deploy-lib.error", url ); | |||
throw new DeploymentException( message, e ); | |||
} | |||
} | |||
private DefaultTypeFactory getFactory( final String role, | |||
final ClassLoader classLoader, | |||
final HashMap factorys ) | |||
{ | |||
DefaultTypeFactory factory = (DefaultTypeFactory)factorys.get( role ); | |||
if( null == factory ) | |||
{ | |||
factory = new DefaultTypeFactory( classLoader ); | |||
factorys.put( role, factory ); | |||
} | |||
return factory; | |||
} | |||
private String getNameForRole( final String role ) | |||
throws DeploymentException | |||
{ | |||
final String name = m_roleManager.getNameForRole( role ); | |||
if( null == name ) | |||
{ | |||
final String message = REZ.getString( "unknown-name4role.error", role ); | |||
throw new DeploymentException( message ); | |||
} | |||
return name; | |||
} | |||
private String getRoleForName( final String name ) | |||
throws DeploymentException | |||
{ | |||
final String role = m_roleManager.getRoleForName( name ); | |||
if( null == role ) | |||
{ | |||
final String message = REZ.getString( "unknown-role4name.error", name ); | |||
throw new DeploymentException( message ); | |||
} | |||
return role; | |||
} | |||
/** | |||
* Ensures a file exists and is not a directory. | |||
*/ | |||
private void checkFile( final File file ) | |||
throws DeploymentException | |||
{ | |||
@@ -385,43 +272,4 @@ public class DefaultDeployer | |||
} | |||
} | |||
private void handleConverter( final Configuration converter, | |||
final DefaultTypeFactory factory ) | |||
throws Exception | |||
{ | |||
final String name = converter.getAttribute( "classname" ); | |||
final String source = converter.getAttribute( "source" ); | |||
final String destination = converter.getAttribute( "destination" ); | |||
m_converterRegistry.registerConverter( name, source, destination ); | |||
factory.addNameClassMapping( name, name ); | |||
m_typeManager.registerType( Converter.ROLE, name, factory ); | |||
if( getLogger().isDebugEnabled() ) | |||
{ | |||
final String message = | |||
REZ.getString( "register-converter.notice", name, source, destination ); | |||
getLogger().debug( message ); | |||
} | |||
} | |||
private void handleType( final String role, | |||
final Configuration type, | |||
final DefaultTypeFactory factory ) | |||
throws Exception | |||
{ | |||
final String name = type.getAttribute( "name" ); | |||
final String className = type.getAttribute( "classname" ); | |||
factory.addNameClassMapping( name, className ); | |||
m_typeManager.registerType( role, name, factory ); | |||
if( getLogger().isDebugEnabled() ) | |||
{ | |||
final String message = | |||
REZ.getString( "register-role.notice", role, name, className ); | |||
getLogger().debug( message ); | |||
} | |||
} | |||
} |
@@ -7,99 +7,391 @@ | |||
*/ | |||
package org.apache.myrmidon.components.deployer; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.FileNotFoundException; | |||
import java.net.URL; | |||
import javax.xml.parsers.ParserConfigurationException; | |||
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.DeploymentException; | |||
import org.xml.sax.SAXException; | |||
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 a .tsk file into a registry. | |||
* This class deploys type libraries from a ClassLoader into a registry. | |||
* | |||
* @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||
*/ | |||
public class Deployment | |||
class Deployment | |||
extends AbstractLogEnabled | |||
implements TypeDeployer | |||
{ | |||
private final static Resources REZ = | |||
ResourceManager.getPackageResources( Deployment.class ); | |||
public final static String DESCRIPTOR_NAME = "META-INF/ant-descriptor.xml"; | |||
private final static String DESCRIPTOR_NAME = "META-INF/ant-descriptor.xml"; | |||
private final static String ROLE_DESCRIPTOR = "META-INF/ant-roles.xml"; | |||
private File m_file; | |||
private ClassLoader m_classLoader; | |||
private ConverterRegistry m_converterRegistry; | |||
private TypeManager m_typeManager; | |||
private RoleManager m_roleManager; | |||
private String[] m_descriptorUrls; | |||
private Configuration[] m_descriptors; | |||
private DefaultTypeFactory m_converterFactory; | |||
private Configuration m_descriptor; | |||
/** Map from role name -> DefaultTypeFactory for that role. */ | |||
private Map m_factories = new HashMap(); | |||
public Deployment( final File file ) | |||
public Deployment( final ClassLoader classLoader, ComponentManager manager ) | |||
throws ComponentException | |||
{ | |||
m_file = file; | |||
// Locate the various components needed | |||
m_classLoader = classLoader; | |||
m_converterRegistry = (ConverterRegistry)manager.lookup( ConverterRegistry.ROLE ); | |||
m_typeManager = (TypeManager)manager.lookup( TypeManager.ROLE ); | |||
m_roleManager = (RoleManager)manager.lookup( RoleManager.ROLE ); | |||
} | |||
public Configuration getDescriptor() | |||
/** | |||
* Load the descriptors. Deploys all roles, then loads the descriptors | |||
* for, but does not deploy, all the types. | |||
*/ | |||
public void loadDescriptors( 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(); | |||
final SAXParser saxParser = saxParserFactory.newSAXParser(); | |||
final XMLReader parser = saxParser.getXMLReader(); | |||
//parser.setFeature( "http://xml.org/sax/features/namespace-prefixes", false ); | |||
final SAXConfigurationHandler handler = new SAXConfigurationHandler(); | |||
parser.setContentHandler( handler ); | |||
parser.setErrorHandler( handler ); | |||
// Load the role descriptors, and deploy all roles | |||
final List roleUrls = locateResources( ROLE_DESCRIPTOR, 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; | |||
} | |||
handleRoleDescriptor( handler.getConfiguration(), url ); | |||
} | |||
// 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 | |||
} | |||
descriptors.add( handler.getConfiguration() ); | |||
} | |||
m_descriptorUrls = (String[])typeUrls.toArray( new String[ typeUrls.size() ] ); | |||
m_descriptors = (Configuration[])descriptors.toArray( new Configuration[ descriptors.size() ] ); | |||
} | |||
/** | |||
* Deploys everything in the type library. | |||
*/ | |||
public void deployAll() | |||
throws DeploymentException | |||
{ | |||
if( null == m_descriptor ) | |||
for( int i = 0; i < m_descriptors.length; i++ ) | |||
{ | |||
m_descriptor = buildDescriptor(); | |||
Configuration descriptor = m_descriptors[ i ]; | |||
deployFromDescriptor( descriptor, m_classLoader, m_descriptorUrls[i] ); | |||
} | |||
} | |||
return m_descriptor; | |||
/** | |||
* Deploys a single type in the type library. | |||
*/ | |||
public void deployType( final String roleShorthand, final String typeName ) | |||
throws DeploymentException | |||
{ | |||
try | |||
{ | |||
// Locate the entry 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++ ) | |||
{ | |||
Configuration datatype = datatypes[ j ]; | |||
if( datatype.getAttribute( "name" ).equals( typeName ) ) | |||
{ | |||
final String className = datatype.getAttribute( "classname" ); | |||
handleType( roleShorthand, typeName, className ); | |||
} | |||
} | |||
} | |||
} | |||
catch( Exception e ) | |||
{ | |||
final String message = REZ.getString( "deploy-type.error", roleShorthand, typeName ); | |||
throw new DeploymentException( message, e ); | |||
} | |||
} | |||
public URL getURL() | |||
/** | |||
* Deploys a single type from the type library. | |||
*/ | |||
public void deployType( String roleShorthand, String typeName, String className ) | |||
throws DeploymentException | |||
{ | |||
try | |||
{ | |||
return m_file.getCanonicalFile().toURL(); | |||
handleType( roleShorthand, typeName, className ); | |||
} | |||
catch( final IOException ioe ) | |||
catch( Exception e ) | |||
{ | |||
final String message = REZ.getString( "bad-url.error", m_file ); | |||
throw new DeploymentException( message, ioe ); | |||
final String message = REZ.getString( "deploy-type.error", roleShorthand, typeName ); | |||
throw new DeploymentException( message, e ); | |||
} | |||
} | |||
private Configuration buildDescriptor() | |||
/** | |||
* Deploys a converter from the type library. The converter definition | |||
* is read from the type library descriptor. | |||
*/ | |||
public void deployConverter( String className ) | |||
throws DeploymentException | |||
{ | |||
final String systemID = "jar:" + getURL() + "!/" + DESCRIPTOR_NAME; | |||
// TODO - implement this | |||
throw new DeploymentException( "Not implemented." ); | |||
} | |||
/** | |||
* Deploys a converter from the type library. | |||
*/ | |||
public void deployConverter( String className, String srcClass, String destClass ) | |||
throws DeploymentException | |||
{ | |||
try | |||
{ | |||
final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); | |||
final SAXParser saxParser = saxParserFactory.newSAXParser(); | |||
final XMLReader parser = saxParser.getXMLReader(); | |||
//parser.setFeature( "http://xml.org/sax/features/namespace-prefixes", false ); | |||
handleConverter( className, srcClass, destClass ); | |||
} | |||
catch( Exception e ) | |||
{ | |||
final String message = REZ.getString( "deploy-converter.error", srcClass, destClass ); | |||
throw new DeploymentException( message, e ); | |||
} | |||
} | |||
final SAXConfigurationHandler handler = new SAXConfigurationHandler(); | |||
parser.setContentHandler( handler ); | |||
parser.setErrorHandler( handler ); | |||
/** | |||
* Locates all resources of a particular name. | |||
*/ | |||
private List locateResources( final String resource, final URL jarUrl ) | |||
throws Exception | |||
{ | |||
ArrayList urls = new ArrayList(); | |||
if( jarUrl != null ) | |||
{ | |||
final String systemID = "jar:" + jarUrl + "!/" + resource; | |||
urls.add( systemID ); | |||
} | |||
else | |||
{ | |||
Enumeration enum = m_classLoader.getResources( resource ); | |||
while( enum.hasMoreElements() ) | |||
{ | |||
urls.add( enum.nextElement().toString() ); | |||
} | |||
} | |||
parser.parse( systemID ); | |||
return handler.getConfiguration(); | |||
return urls; | |||
} | |||
/** | |||
* Configure RoleManager based on contents of single descriptor. | |||
* | |||
* @param descriptor the descriptor | |||
* @exception ConfigurationException if an error occurs | |||
*/ | |||
private void handleRoleDescriptor( final Configuration descriptor, | |||
final String url ) | |||
throws ConfigurationException | |||
{ | |||
final String message = REZ.getString( "url-deploy-roles.notice", url ); | |||
getLogger().info( message ); | |||
final Configuration[] types = descriptor.getChildren( "role" ); | |||
for( int i = 0; i < types.length; i++ ) | |||
{ | |||
final String name = types[ i ].getAttribute( "shorthand" ); | |||
final String role = types[ i ].getAttribute( "name" ); | |||
m_roleManager.addNameRoleMapping( name, role ); | |||
if( getLogger().isDebugEnabled() ) | |||
{ | |||
final String debugMessage = REZ.getString( "register-role.notice", role, name ); | |||
getLogger().debug( debugMessage ); | |||
} | |||
} | |||
catch( final SAXException se ) | |||
} | |||
/** | |||
* Deploys all types from a typelib descriptor. | |||
*/ | |||
private void deployFromDescriptor( final Configuration descriptor, | |||
final ClassLoader classLoader, | |||
final String url ) | |||
throws DeploymentException | |||
{ | |||
try | |||
{ | |||
final String message = REZ.getString( "bad-descriptor.error" ); | |||
throw new DeploymentException( message, se ); | |||
final String message = REZ.getString( "url-deploy-types.notice", url ); | |||
getLogger().info( message ); | |||
// Deploy all the types | |||
final Configuration[] typeEntries = descriptor.getChild( "types" ).getChildren(); | |||
for( int i = 0; i < typeEntries.length; i++ ) | |||
{ | |||
final Configuration typeEntry = typeEntries[ i ]; | |||
final String roleShorthand = typeEntry.getName(); | |||
final String typeName = typeEntry.getAttribute( "name" ); | |||
final String className = typeEntry.getAttribute( "classname" ); | |||
handleType( roleShorthand, typeName, className ); | |||
} | |||
// Deploy all the converters | |||
final Configuration[] converterEntries = descriptor.getChild( "converters" ).getChildren(); | |||
for( int i = 0; i < converterEntries.length; i++ ) | |||
{ | |||
final Configuration converter = converterEntries[ i ]; | |||
final String className = converter.getAttribute( "classname" ); | |||
final String source = converter.getAttribute( "source" ); | |||
final String destination = converter.getAttribute( "destination" ); | |||
handleConverter( className, source, destination ); | |||
} | |||
} | |||
catch( final ParserConfigurationException pce ) | |||
catch( final Exception e ) | |||
{ | |||
final String message = REZ.getString( "bad-parser.error" ); | |||
throw new DeploymentException( message, pce ); | |||
final String message = REZ.getString( "deploy-lib.error", url ); | |||
throw new DeploymentException( message, e ); | |||
} | |||
catch( final IOException ioe ) | |||
} | |||
/** | |||
* Returns the type factory for a role. | |||
*/ | |||
private DefaultTypeFactory getFactory( final Class roleType) | |||
{ | |||
DefaultTypeFactory factory = (DefaultTypeFactory)m_factories.get( roleType ); | |||
if( null == factory ) | |||
{ | |||
final String message = REZ.getString( "bad-read.error" ); | |||
throw new DeploymentException( message, ioe ); | |||
factory = new DefaultTypeFactory( m_classLoader ); | |||
m_factories.put( roleType, factory ); | |||
} | |||
return factory; | |||
} | |||
/** | |||
* Handles a converter definition. | |||
*/ | |||
private void handleConverter( final String className, | |||
final String source, | |||
final String destination ) throws Exception | |||
{ | |||
m_converterRegistry.registerConverter( className, source, destination ); | |||
if( m_converterFactory == null ) | |||
{ | |||
m_converterFactory = new DefaultTypeFactory( m_classLoader ); | |||
} | |||
m_converterFactory.addNameClassMapping( className, className ); | |||
m_typeManager.registerType( Converter.class, className, m_converterFactory ); | |||
if( getLogger().isDebugEnabled() ) | |||
{ | |||
final String message = | |||
REZ.getString( "register-converter.notice", source, destination ); | |||
getLogger().debug( message ); | |||
} | |||
} | |||
/** | |||
* Handles a type definition. | |||
*/ | |||
private void handleType( final String roleShorthand, | |||
final String typeName, | |||
final String className ) | |||
throws Exception | |||
{ | |||
// TODO - detect duplicates | |||
final String role = getRoleForName( roleShorthand ); | |||
final Class roleType = m_classLoader.loadClass( role ); | |||
final DefaultTypeFactory factory = getFactory( roleType ); | |||
factory.addNameClassMapping( typeName, className ); | |||
m_typeManager.registerType( roleType, typeName, factory ); | |||
if( getLogger().isDebugEnabled() ) | |||
{ | |||
final String message = | |||
REZ.getString( "register-type.notice", roleShorthand, typeName ); | |||
getLogger().debug( message ); | |||
} | |||
} | |||
/** | |||
* Determines the role name from shorthand name. | |||
*/ | |||
private String getRoleForName( final String name ) | |||
throws DeploymentException | |||
{ | |||
final String role = m_roleManager.getRoleForName( name ); | |||
if( null == role ) | |||
{ | |||
final String message = REZ.getString( "unknown-role4name.error", name ); | |||
throw new DeploymentException( message ); | |||
} | |||
return role; | |||
} | |||
} |
@@ -1,24 +1,18 @@ | |||
register-converter.notice=Registered converter {0} that converts from {1} to {2}. | |||
register-role.notice=Registered {0}/{1} as {2}. | |||
url-deploy.notice=Deploying {0}. | |||
file-deploy.notice=Deploying AntLib file ({0}). | |||
register-converter.notice=Registered converter that converts from {1} to {2}. | |||
register-type.notice=Registered type {0}/{1}. | |||
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-lib.error=Error deploying library from {0}. | |||
deploy-converter.error=Failed to deploy {0} converter. | |||
bad-descriptor.error=Malformed descriptor. | |||
deploy-type.error=Failed to deploy {0} type. | |||
unknown-name4role.error=RoleManager does not know name for role {0}. | |||
unknown-role4name.error=RoleManager does not know role for name {0}. | |||
no-file.error=Could not find application archive at {0}. | |||
file-is-dir.error=Could not find application archive at {0} as it is a directory. | |||
deploy-from-classloader.error=Could not register types from ClassLoader {0}. | |||
deploy-from-file.error=Could not register types from type library "{0}". | |||
deploy-lib.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}". | |||
no-file.error=Could not find type library "{0}". | |||
file-is-dir.error=Type library "{0}" is a directory. | |||
bad-url.error=Unable to form url from file {0}. | |||
bad-parser.error=Error configuring parser. | |||
bad-read.error=Error reading configuration. | |||
available-extensions=The list of available extensions for Type Library includes; {0} | |||
required-extensions=The list of required extensions for Type Library includes; {0} | |||
optional-packages-added=The list of "Optional Packages" added to the Type Library includes; {0} | |||
classpath-entries=The list of classpath entrys for the Type Library includes; {0} | |||
missing.extension=Unable to locate an extension that is required by Type Library.\nExtension Name: {0}\nSpecification Vendor: {1}\nSpecification Version: {2}\nImplementation Vendor: {3}\nImplementation Vendor-Id: {4}\nImplementation Version: {5}\nImplementation URL: {6} | |||
unsatisfied.extensions=Missing {0} extensions and thus can not build ClassLoader for Type Library. | |||
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} | |||
unsatisfied.extensions.error=Missing {0} extensions for type library. |
@@ -27,6 +27,7 @@ import org.apache.myrmidon.interfaces.converter.ConverterRegistry; | |||
import org.apache.myrmidon.interfaces.converter.MasterConverter; | |||
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.embeddor.Embeddor; | |||
import org.apache.myrmidon.interfaces.executor.Executor; | |||
import org.apache.myrmidon.interfaces.extensions.ExtensionManager; | |||
@@ -106,7 +107,7 @@ public class DefaultEmbeddor | |||
throws Exception | |||
{ | |||
final TypeFactory factory = m_typeManager.getFactory( ProjectBuilder.ROLE ); | |||
final TypeFactory factory = m_typeManager.getFactory( ProjectBuilder.class ); | |||
final ProjectBuilder builder = (ProjectBuilder)factory.create( type ); | |||
setupLogger( builder ); | |||
@@ -181,6 +182,12 @@ public class DefaultEmbeddor | |||
public void start() | |||
throws Exception | |||
{ | |||
// Deploy all type libraries found in the classpath | |||
final ClassLoader libClassloader = Thread.currentThread().getContextClassLoader(); | |||
final TypeDeployer typeDeployer = m_deployer.createDeployer( libClassloader ); | |||
typeDeployer.deployAll(); | |||
// Deploy all type libraries in the lib directory | |||
final ExtensionFileFilter filter = new ExtensionFileFilter( ".atl" ); | |||
deployFromDirectory( m_deployer, m_taskLibDir, filter ); | |||
} | |||
@@ -479,6 +486,9 @@ public class DefaultEmbeddor | |||
} | |||
} | |||
/** | |||
* Deploys all type libraries in a directory. | |||
*/ | |||
private void deployFromDirectory( final Deployer deployer, | |||
final File directory, | |||
final FilenameFilter filter ) | |||
@@ -492,6 +502,9 @@ public class DefaultEmbeddor | |||
} | |||
} | |||
/** | |||
* Deploys a set of type libraries. | |||
*/ | |||
private void deployFiles( final Deployer deployer, final File[] files ) | |||
throws DeploymentException | |||
{ | |||
@@ -508,7 +521,8 @@ public class DefaultEmbeddor | |||
try | |||
{ | |||
final File file = files[ i ].getCanonicalFile(); | |||
deployer.deploy( file ); | |||
final TypeDeployer typeDeployer = deployer.createDeployer( file ); | |||
typeDeployer.deployAll(); | |||
} | |||
catch( final DeploymentException de ) | |||
{ | |||
@@ -32,8 +32,6 @@ public class DefaultExecutor | |||
private final static Resources REZ = | |||
ResourceManager.getPackageResources( DefaultExecutor.class ); | |||
private final static String TASK_ROLE = Task.class.getName(); | |||
private Configurer m_configurer; | |||
/** | |||
@@ -81,7 +79,7 @@ public class DefaultExecutor | |||
{ | |||
try | |||
{ | |||
final TypeFactory factory = frame.getTypeManager().getFactory( TASK_ROLE ); | |||
final TypeFactory factory = frame.getTypeManager().getFactory( Task.class ); | |||
return (Task)factory.create( name ); | |||
} | |||
catch( final TypeException te ) | |||
@@ -7,19 +7,10 @@ | |||
*/ | |||
package org.apache.myrmidon.components.role; | |||
import java.net.URL; | |||
import java.util.Enumeration; | |||
import java.util.HashMap; | |||
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.activity.Initializable; | |||
import org.apache.avalon.framework.configuration.Configuration; | |||
import org.apache.avalon.framework.configuration.ConfigurationException; | |||
import org.apache.avalon.framework.configuration.SAXConfigurationHandler; | |||
import org.apache.myrmidon.interfaces.role.RoleManager; | |||
import org.xml.sax.XMLReader; | |||
/** | |||
* Interface to manage roles and mapping to names. | |||
@@ -28,13 +19,11 @@ import org.xml.sax.XMLReader; | |||
* @version CVS $Revision$ $Date$ | |||
*/ | |||
public class DefaultRoleManager | |||
implements RoleManager, Initializable | |||
implements RoleManager | |||
{ | |||
private final static Resources REZ = | |||
ResourceManager.getPackageResources( DefaultRoleManager.class ); | |||
private final static String ROLE_DESCRIPTOR = "META-INF/ant-roles.xml"; | |||
/** Parent <code>RoleManager</code> for nested resolution */ | |||
private final RoleManager m_parent; | |||
@@ -63,51 +52,6 @@ public class DefaultRoleManager | |||
m_parent = parent; | |||
} | |||
/** | |||
* initialize the RoleManager. | |||
* This involves reading all Role descriptors in common classloader. | |||
* | |||
* @exception Exception if an error occurs | |||
*/ | |||
public void initialize() | |||
throws Exception | |||
{ | |||
final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); | |||
final SAXParser saxParser = saxParserFactory.newSAXParser(); | |||
final XMLReader parser = saxParser.getXMLReader(); | |||
//parser.setFeature( "http://xml.org/sax/features/namespace-prefixes", false ); | |||
final SAXConfigurationHandler handler = new SAXConfigurationHandler(); | |||
parser.setContentHandler( handler ); | |||
parser.setErrorHandler( handler ); | |||
final Enumeration enum = getClass().getClassLoader().getResources( ROLE_DESCRIPTOR ); | |||
while( enum.hasMoreElements() ) | |||
{ | |||
final URL url = (URL)enum.nextElement(); | |||
parser.parse( url.toString() ); | |||
handleDescriptor( handler.getConfiguration() ); | |||
} | |||
} | |||
/** | |||
* Configure RoleManager based on contents of single descriptor. | |||
* | |||
* @param descriptor the descriptor | |||
* @exception ConfigurationException if an error occurs | |||
*/ | |||
private void handleDescriptor( final Configuration descriptor ) | |||
throws ConfigurationException | |||
{ | |||
final Configuration[] types = descriptor.getChildren( "role" ); | |||
for( int i = 0; i < types.length; i++ ) | |||
{ | |||
final String name = types[ i ].getAttribute( "shorthand" ); | |||
final String role = types[ i ].getAttribute( "name" ); | |||
addNameRoleMapping( name, role ); | |||
} | |||
} | |||
/** | |||
* Find Role name based on shorthand name. | |||
* | |||
@@ -155,14 +99,14 @@ public class DefaultRoleManager | |||
throws IllegalArgumentException | |||
{ | |||
final String oldRole = (String)m_names.get( name ); | |||
if( null != oldRole && oldRole.equals( role ) ) | |||
if( null != oldRole && ! oldRole.equals( role ) ) | |||
{ | |||
final String message = REZ.getString( "duplicate-name.error", oldRole ); | |||
throw new IllegalArgumentException( message ); | |||
} | |||
final String oldName = (String)m_roles.get( role ); | |||
if( null != oldName && oldName.equals( name ) ) | |||
if( null != oldName && ! oldName.equals( name ) ) | |||
{ | |||
final String message = REZ.getString( "duplicate-role.error", oldName ); | |||
throw new IllegalArgumentException( message ); | |||
@@ -28,7 +28,7 @@ public class DefaultTypeManager | |||
///Parent type manager to inherit values from. | |||
private final DefaultTypeManager m_parent; | |||
///Maps role to MultiSourceTypeFactory. | |||
///Maps role Class to MultiSourceTypeFactory. | |||
private final HashMap m_roleMap = new HashMap(); | |||
public DefaultTypeManager() | |||
@@ -41,7 +41,7 @@ public class DefaultTypeManager | |||
m_parent = parent; | |||
} | |||
public void registerType( final String role, | |||
public void registerType( final Class role, | |||
final String shorthandName, | |||
final TypeFactory factory ) | |||
throws TypeException | |||
@@ -50,7 +50,7 @@ public class DefaultTypeManager | |||
msFactory.register( shorthandName, factory ); | |||
} | |||
public TypeFactory getFactory( final String role ) | |||
public TypeFactory getFactory( final Class role ) | |||
throws TypeException | |||
{ | |||
return createFactory( role ); | |||
@@ -61,7 +61,7 @@ public class DefaultTypeManager | |||
return new DefaultTypeManager( this ); | |||
} | |||
protected final MultiSourceTypeFactory lookupFactory( final String role ) | |||
protected final MultiSourceTypeFactory lookupFactory( final Class role ) | |||
{ | |||
return (MultiSourceTypeFactory)m_roleMap.get( role ); | |||
} | |||
@@ -74,7 +74,7 @@ public class DefaultTypeManager | |||
* @return the Factory for interface | |||
* @exception TypeException role does not specify accessible work interface | |||
*/ | |||
private MultiSourceTypeFactory createFactory( final String role ) | |||
private MultiSourceTypeFactory createFactory( final Class role ) | |||
throws TypeException | |||
{ | |||
MultiSourceTypeFactory factory = (MultiSourceTypeFactory)m_roleMap.get( role ); | |||
@@ -92,17 +92,7 @@ public class DefaultTypeManager | |||
///If we haven't got factory try to create a new one | |||
if( null == factory ) | |||
{ | |||
try | |||
{ | |||
//TODO: Should we use ContextClassLoader here ??? Or perhaps try that on failure?? | |||
final Class clazz = Class.forName( role ); | |||
factory = new MultiSourceTypeFactory( clazz ); | |||
} | |||
catch( final Exception e ) | |||
{ | |||
final String message = REZ.getString( "no-work-interface.error", role ); | |||
throw new TypeException( message ); | |||
} | |||
factory = new MultiSourceTypeFactory( role ); | |||
} | |||
m_roleMap.put( role, factory ); | |||
@@ -110,7 +100,7 @@ public class DefaultTypeManager | |||
return factory; | |||
} | |||
private MultiSourceTypeFactory getParentTypedFactory( final String role ) | |||
private MultiSourceTypeFactory getParentTypedFactory( final Class role ) | |||
{ | |||
if( null != m_parent ) | |||
{ | |||
@@ -28,11 +28,11 @@ import org.apache.avalon.framework.parameters.Parameters; | |||
import org.apache.log.Hierarchy; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.components.deployer.DefaultDeployer; | |||
import org.apache.myrmidon.components.executor.DefaultExecutionFrame; | |||
import org.apache.myrmidon.framework.Condition; | |||
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.executor.ExecutionFrame; | |||
import org.apache.myrmidon.interfaces.executor.Executor; | |||
import org.apache.myrmidon.interfaces.model.Project; | |||
@@ -61,6 +61,7 @@ public class DefaultWorkspace | |||
private TaskContext m_baseContext; | |||
private HashMap m_entrys = new HashMap(); | |||
private TypeManager m_typeManager; | |||
private Deployer m_deployer; | |||
private Hierarchy m_hierarchy; | |||
private int m_projectID; | |||
@@ -96,6 +97,7 @@ public class DefaultWorkspace | |||
m_componentManager = componentManager; | |||
m_typeManager = (TypeManager)componentManager.lookup( TypeManager.ROLE ); | |||
m_executor = (Executor)componentManager.lookup( Executor.ROLE ); | |||
m_deployer = (Deployer)componentManager.lookup( Deployer.ROLE ); | |||
} | |||
public void parameterize( final Parameters parameters ) | |||
@@ -198,13 +200,16 @@ public class DefaultWorkspace | |||
try | |||
{ | |||
final TypeDeployer typeDeployer = deployer.createDeployer( file ); | |||
if( null == typeLib.getRole() ) | |||
{ | |||
deployer.deploy( file ); | |||
// Deploy everything in the typelib | |||
typeDeployer.deployAll(); | |||
} | |||
else | |||
{ | |||
deployer.deployType( typeLib.getRole(), typeLib.getName(), file ); | |||
// Deploy the specified type | |||
typeDeployer.deployType( typeLib.getRole(), typeLib.getName() ); | |||
} | |||
} | |||
catch( final DeploymentException de ) | |||
@@ -227,27 +232,34 @@ public class DefaultWorkspace | |||
final TypeManager typeManager = m_typeManager.createChildTypeManager(); | |||
componentManager.put( TypeManager.ROLE, typeManager ); | |||
//try | |||
//{ | |||
// //Add VFS manager | |||
// // TODO - need to drive this from a typelib descriptor, plus | |||
// // should be adding services to the root frame, rather than here | |||
// final DefaultFileSystemManager vfsManager = new DefaultFileSystemManager(); | |||
// vfsManager.setBaseFile( project.getBaseDirectory() ); | |||
// componentManager.put( FileSystemManager.ROLE, vfsManager ); | |||
//} | |||
//catch( Exception e ) | |||
//{ | |||
// throw new TaskException( e.getMessage(), e ); | |||
//} | |||
//We need to create a new deployer so that it deploys | |||
//to project specific TypeManager | |||
final DefaultDeployer deployer = new DefaultDeployer(); | |||
deployer.enableLogging( getLogger() ); | |||
final Deployer deployer; | |||
try | |||
{ | |||
deployer.compose( componentManager ); | |||
deployer = m_deployer.createChildDeployer( componentManager ); | |||
componentManager.put( Deployer.ROLE, deployer ); | |||
} | |||
catch( final ComponentException ce ) | |||
catch( ComponentException e ) | |||
{ | |||
final String message = REZ.getString( "bad-deployer-config.error" ); | |||
throw new TaskException( message, ce ); | |||
throw new TaskException( e.getMessage(), e ); | |||
} | |||
//HACK: Didn't call initialize because Deployer contained in Embeddor | |||
// Already initialized and this would be reduendent | |||
//deployer.initialize(); | |||
componentManager.put( Deployer.ROLE, deployer ); | |||
// Deploy the imported typelibs | |||
deployTypeLib( deployer, project ); | |||
//We need to place projects and ProjectManager | |||
@@ -109,17 +109,17 @@ public abstract class AbstractContainerTask | |||
/** | |||
* Locates a type factory. | |||
*/ | |||
protected final TypeFactory getTypeFactory( final String role ) | |||
protected final TypeFactory getTypeFactory( final Class roleType ) | |||
throws TaskException | |||
{ | |||
final TypeManager typeManager = (TypeManager)getService( TypeManager.class ); | |||
try | |||
{ | |||
return typeManager.getFactory( role ); | |||
return typeManager.getFactory( roleType ); | |||
} | |||
catch( final TypeException te ) | |||
{ | |||
final String message = REZ.getString( "container.no-factory.error", role ); | |||
final String message = REZ.getString( "container.no-factory.error", roleType.getName() ); | |||
throw new TaskException( message, te ); | |||
} | |||
} | |||
@@ -8,16 +8,13 @@ | |||
package org.apache.myrmidon.framework; | |||
import java.io.File; | |||
import java.net.URL; | |||
import java.net.URLClassLoader; | |||
import org.apache.avalon.excalibur.i18n.ResourceManager; | |||
import org.apache.avalon.excalibur.i18n.Resources; | |||
import org.apache.myrmidon.api.AbstractTask; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.interfaces.role.RoleManager; | |||
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | |||
import org.apache.myrmidon.interfaces.type.TypeException; | |||
import org.apache.myrmidon.interfaces.type.TypeManager; | |||
import org.apache.myrmidon.interfaces.deployer.Deployer; | |||
import org.apache.myrmidon.interfaces.deployer.DeploymentException; | |||
import org.apache.myrmidon.interfaces.deployer.TypeDeployer; | |||
/** | |||
* Abstract task to extend to define a type. | |||
@@ -66,44 +63,20 @@ public abstract class AbstractTypeDef | |||
throw new TaskException( message ); | |||
} | |||
final String typeName = getTypeName(); | |||
final RoleManager roleManager = (RoleManager)getService( RoleManager.class ); | |||
final String role = roleManager.getRoleForName( typeName ); | |||
final String shorthand = getRoleShorthand(); | |||
final ClassLoader classLoader = createClassLoader(); | |||
final DefaultTypeFactory factory = new DefaultTypeFactory( classLoader ); | |||
factory.addNameClassMapping( m_name, m_className ); | |||
final TypeManager typeManager = (TypeManager)getService( TypeManager.class ); | |||
try | |||
{ | |||
typeManager.registerType( role, m_name, factory ); | |||
} | |||
catch( final TypeException te ) | |||
{ | |||
final String message = REZ.getString( "typedef.no-register.error" ); | |||
throw new TaskException( message, te ); | |||
} | |||
} | |||
protected ClassLoader createClassLoader() | |||
throws TaskException | |||
{ | |||
//TODO: Make this support classpath sub-element in future | |||
try | |||
{ | |||
final URL url = m_lib.toURL(); | |||
final ClassLoader classLoader = | |||
Thread.currentThread().getContextClassLoader(); | |||
return new URLClassLoader( new URL[]{url}, classLoader ); | |||
// Locate the deployer, and use it to deploy the type | |||
final Deployer deployer = (Deployer)getService( Deployer.class ); | |||
final TypeDeployer typeDeployer = deployer.createDeployer( m_lib ); | |||
typeDeployer.deployType( shorthand, m_name, m_className ); | |||
} | |||
catch( final Exception e ) | |||
catch( DeploymentException e ) | |||
{ | |||
final String message = REZ.getString( "typedef.bad-classloader.error", e ); | |||
throw new TaskException( message, e ); | |||
throw new TaskException( e.getMessage(), e ); | |||
} | |||
} | |||
protected abstract String getTypeName(); | |||
protected abstract String getRoleShorthand(); | |||
} |
@@ -63,7 +63,7 @@ public class TypeInstanceTask | |||
try | |||
{ | |||
final TypeFactory typeFactory = getTypeFactory( DataType.ROLE ); | |||
final TypeFactory typeFactory = getTypeFactory( DataType.class ); | |||
m_value = typeFactory.create( configuration.getName() ); | |||
} | |||
catch( final Exception e ) | |||
@@ -9,9 +9,11 @@ package org.apache.myrmidon.interfaces.deployer; | |||
import java.io.File; | |||
import org.apache.avalon.framework.component.Component; | |||
import org.apache.avalon.framework.component.ComponentException; | |||
import org.apache.avalon.framework.component.ComponentManager; | |||
/** | |||
* This class deploys a .tsk file into a registry. | |||
* This class deploys type libraries into a registry. | |||
* | |||
* @author <a href="mailto:peter@apache.org">Peter Donald</a> | |||
*/ | |||
@@ -21,17 +23,28 @@ public interface Deployer | |||
String ROLE = "org.apache.myrmidon.interfaces.deployer.Deployer"; | |||
/** | |||
* Deploy a library. | |||
* Returns the deployer for the type libraries contained in a ClassLoader, | |||
* creating the deployer if necessary. | |||
* | |||
* @param file the file deployment | |||
* @exception DeploymentException if an error occurs | |||
* @param loader The ClassLoader to get the deployer for. | |||
* @exception DeploymentException if an error occurs. | |||
*/ | |||
void deploy( File file ) | |||
TypeDeployer createDeployer( ClassLoader loader ) | |||
throws DeploymentException; | |||
void deployConverter( String name, File file ) | |||
/** | |||
* Returns the deployer for a type library, creating the deployer if | |||
* necessary. | |||
* | |||
* @param file the file containing the type library. | |||
* @exception DeploymentException if an error occurs. | |||
*/ | |||
TypeDeployer createDeployer( File file ) | |||
throws DeploymentException; | |||
void deployType( String role, String name, File file ) | |||
throws DeploymentException; | |||
/** | |||
* Creates a child deployer. | |||
*/ | |||
Deployer createChildDeployer( ComponentManager componentManager ) | |||
throws ComponentException; | |||
} |
@@ -0,0 +1,54 @@ | |||
/* | |||
* 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.interfaces.deployer; | |||
/** | |||
* A deployer for a type library. Allows individual elements from a type | |||
* library to be deployed. | |||
* | |||
* @author Adam Murdoch | |||
*/ | |||
public interface TypeDeployer | |||
{ | |||
/** | |||
* Deploys everything in the type library. | |||
*/ | |||
void deployAll() | |||
throws DeploymentException; | |||
/** | |||
* Deploys a single type from the type library. The type definition is | |||
* read from the type library descriptor. | |||
* | |||
* @param roleShorthand | |||
* The <em>shorthand</em> for the role. | |||
* @param typeName | |||
* The type name. | |||
*/ | |||
void deployType( String roleShorthand, String typeName ) | |||
throws DeploymentException; | |||
/** | |||
* Deploys a single type from the type library. | |||
*/ | |||
void deployType( String roleShorthand, String typeName, String className ) | |||
throws DeploymentException; | |||
/** | |||
* Deploys a converter from the type library. The converter definition | |||
* is read from the type library descriptor. | |||
*/ | |||
void deployConverter( String className ) | |||
throws DeploymentException; | |||
/** | |||
* Deploys a converter from the type library. | |||
*/ | |||
void deployConverter( String className, String srcClass, String destClass ) | |||
throws DeploymentException; | |||
} |
@@ -38,4 +38,13 @@ public interface RoleManager | |||
* @return the name | |||
*/ | |||
String getNameForRole( String role ); | |||
/** | |||
* Adds a role mapping. | |||
* | |||
* @param name the shorthand name. | |||
* @param role the role name. | |||
*/ | |||
void addNameRoleMapping( String name, String role ) | |||
throws IllegalArgumentException; | |||
} |
@@ -7,8 +7,6 @@ | |||
*/ | |||
package org.apache.myrmidon.interfaces.type; | |||
import java.net.URL; | |||
import java.net.URLClassLoader; | |||
import java.util.HashMap; | |||
import org.apache.avalon.excalibur.i18n.ResourceManager; | |||
import org.apache.avalon.excalibur.i18n.Resources; | |||
@@ -28,34 +26,11 @@ public class DefaultTypeFactory | |||
///A Map of shortnames to classnames | |||
private final HashMap m_classNames = new HashMap(); | |||
///A list of URLs from which classLoader is constructed | |||
private final URL[] m_urls; | |||
///The parent classLoader (if any) | |||
private final ClassLoader m_parent; | |||
///The parent classLoader (if any) | |||
private ClassLoader m_classLoader; | |||
public DefaultTypeFactory( final URL url ) | |||
{ | |||
this( new URL[]{url} ); | |||
} | |||
public DefaultTypeFactory( final URL[] urls ) | |||
{ | |||
this( urls, Thread.currentThread().getContextClassLoader() ); | |||
} | |||
public DefaultTypeFactory( final URL[] urls, final ClassLoader parent ) | |||
{ | |||
m_urls = urls; | |||
m_parent = parent; | |||
} | |||
public DefaultTypeFactory( final ClassLoader classLoader ) | |||
{ | |||
this( null, null ); | |||
m_classLoader = classLoader; | |||
} | |||
@@ -78,7 +53,7 @@ public class DefaultTypeFactory | |||
try | |||
{ | |||
return getClassLoader().loadClass( className ).newInstance(); | |||
return m_classLoader.loadClass( className ).newInstance(); | |||
} | |||
catch( final Exception e ) | |||
{ | |||
@@ -100,14 +75,4 @@ public class DefaultTypeFactory | |||
return className; | |||
} | |||
private ClassLoader getClassLoader() | |||
{ | |||
if( null == m_classLoader ) | |||
{ | |||
m_classLoader = new URLClassLoader( m_urls, m_parent ); | |||
} | |||
return m_classLoader; | |||
} | |||
} |
@@ -19,11 +19,32 @@ public interface TypeManager | |||
{ | |||
String ROLE = "org.apache.myrmidon.interfaces.type.TypeManager"; | |||
void registerType( String role, String shorthandName, TypeFactory factory ) | |||
/** | |||
* Registers a new type. | |||
* | |||
* @param roleType | |||
* The role interface for the type. Objects created by the factory | |||
* must implement this interface. | |||
* | |||
* @param shorthandName | |||
* The shorthand name for the type. | |||
* | |||
* @param factory | |||
* The type factory. | |||
*/ | |||
void registerType( Class roleType, String shorthandName, TypeFactory factory ) | |||
throws TypeException; | |||
TypeFactory getFactory( String role ) | |||
/** | |||
* Returns the factory for a role. | |||
*/ | |||
TypeFactory getFactory( Class roleType ) | |||
throws TypeException; | |||
/** | |||
* Creates a child type manager. The child inherits the type factories | |||
* from this type manager. Additional type factories may be added to the | |||
* child, without affecting this type manager. | |||
*/ | |||
TypeManager createChildTypeManager(); | |||
} |
@@ -433,8 +433,8 @@ public class DefaultConfigurerTest | |||
final DefaultTypeFactory factory = new DefaultTypeFactory( loader ); | |||
factory.addNameClassMapping( "my-type1", MyType1.class.getName() ); | |||
factory.addNameClassMapping( "my-type2", MyType2.class.getName() ); | |||
m_typeManager.registerType( MyRole1.class.getName(), "my-type1", factory ); | |||
m_typeManager.registerType( MyRole1.class.getName(), "my-type2", factory ); | |||
m_typeManager.registerType( MyRole1.class, "my-type1", factory ); | |||
m_typeManager.registerType( MyRole1.class, "my-type2", factory ); | |||
final ConfigTest6 test = new ConfigTest6(); | |||
@@ -433,8 +433,8 @@ public class DefaultConfigurerTest | |||
final DefaultTypeFactory factory = new DefaultTypeFactory( loader ); | |||
factory.addNameClassMapping( "my-type1", MyType1.class.getName() ); | |||
factory.addNameClassMapping( "my-type2", MyType2.class.getName() ); | |||
m_typeManager.registerType( MyRole1.class.getName(), "my-type1", factory ); | |||
m_typeManager.registerType( MyRole1.class.getName(), "my-type2", factory ); | |||
m_typeManager.registerType( MyRole1.class, "my-type1", factory ); | |||
m_typeManager.registerType( MyRole1.class, "my-type2", factory ); | |||
final ConfigTest6 test = new ConfigTest6(); | |||