* 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(); | |||