diff --git a/proposal/myrmidon/build.xml b/proposal/myrmidon/build.xml index f0bd28124..a7d0ffe19 100644 --- a/proposal/myrmidon/build.xml +++ b/proposal/myrmidon/build.xml @@ -416,20 +416,35 @@ Legal: - - - - - + + - - - - + + + + + + + + + + + + + + + + + + + @@ -437,8 +452,7 @@ Legal: - - + diff --git a/proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/deployer/ant-descriptor.xml b/proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/deployer/ant-descriptor.xml new file mode 100644 index 000000000..ddc7fb823 --- /dev/null +++ b/proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/deployer/ant-descriptor.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/deployer/ant-roles.xml b/proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/deployer/ant-roles.xml new file mode 100644 index 000000000..fb2e57743 --- /dev/null +++ b/proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/deployer/ant-roles.xml @@ -0,0 +1,4 @@ + + + + diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ClassLoaderManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ClassLoaderManager.java new file mode 100644 index 000000000..636307e2d --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ClassLoaderManager.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) The Apache Software Foundation. All rights reserved. + * + * This software is published under the terms of the Apache Software License + * version 1.1, a copy of which has been included with this distribution in + * the LICENSE.txt file. + */ +package org.apache.myrmidon.components.deployer; + +import java.io.File; +import org.apache.myrmidon.interfaces.deployer.DeploymentException; +import org.apache.avalon.framework.component.Component; + +/** + * Manages a classloader hierarchy. + * + * @author Adam Murdoch + */ +public interface ClassLoaderManager + extends Component +{ + String ROLE = ClassLoaderManager.class.getName(); + + /** + * Builds the ClassLoader for a Jar file. + */ + ClassLoader createClassLoader( File jar ) throws DeploymentException; +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultClassLoaderManager.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultClassLoaderManager.java new file mode 100644 index 000000000..b08a3ed72 --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultClassLoaderManager.java @@ -0,0 +1,209 @@ +/* + * Copyright (C) The Apache Software Foundation. All rights reserved. + * + * This software is published under the terms of the Apache Software License + * version 1.1, a copy of which has been included with this distribution in + * the LICENSE.txt file. + */ +package org.apache.myrmidon.components.deployer; + +import java.io.File; +import java.net.JarURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.jar.Manifest; +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.logger.AbstractLogEnabled; +import org.apache.myrmidon.interfaces.deployer.DeploymentException; +import org.apache.myrmidon.interfaces.extensions.ExtensionManager; + +/** + * A default implementation of a classloader manager. + * + * @author Adam Murdoch + */ +public class DefaultClassLoaderManager + extends AbstractLogEnabled + implements ClassLoaderManager, Composable, Initializable +{ + private final static Resources REZ = + ResourceManager.getPackageResources( DefaultClassLoaderManager.class ); + + /** + * Map from File to the ClassLoader for that file. + */ + private final Map m_fileDeployers = new HashMap(); + + private PackageManager m_packageManager; + private ClassLoader m_baseClassLoader; + + public void initialize() throws Exception + { + if( m_baseClassLoader == null ) + { + m_baseClassLoader = Thread.currentThread().getContextClassLoader(); + } + } + + /** + * Sets the ClassLoader to use as the parent for all classloaders + * created by this ClassLoader manager. + */ + public void setBaseClassLoader( final ClassLoader classLoader ) + { + m_baseClassLoader = classLoader; + } + + /** + * Retrieve relevent services needed to deploy. + */ + public void compose( final ComponentManager componentManager ) + throws ComponentException + { + final ExtensionManager extensionManager = + (ExtensionManager)componentManager.lookup( ExtensionManager.ROLE ); + m_packageManager = new PackageManager( extensionManager ); + } + + /** + * Creates a class loader for a Jar file. + */ + public ClassLoader createClassLoader( File file ) throws DeploymentException + { + try + { + final File canonFile = file.getCanonicalFile(); + + // Locate cached classloader, creating it if necessary + URLClassLoader classLoader = (URLClassLoader)m_fileDeployers.get( canonFile ); + if( classLoader == null ) + { + checkFile( canonFile ); + final File[] extensions = getOptionalPackagesFor( canonFile ); + final URL[] urls = buildClasspath( canonFile, extensions ); + classLoader = new URLClassLoader( urls, m_baseClassLoader ); + m_fileDeployers.put( canonFile, classLoader ); + } + return classLoader; + } + catch( Exception e ) + { + final String message = REZ.getString( "create-classloader-for-file.error", file ); + throw new DeploymentException( message ); + } + } + + /** + * Assembles a set of files into a URL classpath. + */ + private URL[] buildClasspath( final File file, final File[] dependencies ) + throws MalformedURLException + { + final URL[] urls = new URL[ dependencies.length + 1 ]; + + for( int i = 0; i < dependencies.length; i++ ) + { + urls[ i ] = dependencies[ i ].toURL(); + } + + urls[ dependencies.length ] = file.toURL(); + + return urls; + } + + /** + * Retrieve the files for the optional packages required by + * the specified typeLibrary jar. + * + * @param typeLibrary the typeLibrary + * @return the files that need to be added to ClassLoader + */ + private File[] getOptionalPackagesFor( final File typeLibrary ) + throws Exception + { + final URL url = new URL( "jar:" + typeLibrary.getCanonicalFile().toURL() + "!/" ); + final JarURLConnection connection = (JarURLConnection)url.openConnection(); + final Manifest manifest = connection.getManifest(); + final Extension[] available = Extension.getAvailable( manifest ); + final Extension[] required = Extension.getRequired( manifest ); + + if( getLogger().isDebugEnabled() ) + { + final String message1 = + REZ.getString( "available-extensions.notice", Arrays.asList( available ) ); + getLogger().debug( message1 ); + final String message2 = + REZ.getString( "required-extensions.notice", Arrays.asList( required ) ); + getLogger().debug( message2 ); + } + + final ArrayList dependencies = new ArrayList(); + final ArrayList unsatisfied = new ArrayList(); + + m_packageManager.scanDependencies( required, + available, + dependencies, + unsatisfied ); + + if( 0 != unsatisfied.size() ) + { + final int size = unsatisfied.size(); + for( int i = 0; i < size; i++ ) + { + final Extension extension = (Extension)unsatisfied.get( i ); + final Object[] params = new Object[] + { + extension.getExtensionName(), + extension.getSpecificationVendor(), + extension.getSpecificationVersion(), + extension.getImplementationVendor(), + extension.getImplementationVendorId(), + extension.getImplementationVersion(), + extension.getImplementationURL() + }; + final String message = REZ.format( "missing.extension", params ); + getLogger().warn( message ); + } + + final String message = + REZ.getString( "unsatisfied.extensions.error", new Integer( size ) ); + throw new Exception( message ); + } + + final OptionalPackage[] packages = + (OptionalPackage[])dependencies.toArray( new OptionalPackage[ 0 ] ); + return OptionalPackage.toFiles( packages ); + } + + /** + * Ensures a file exists and is not a directory. + */ + private void checkFile( final File file ) + throws DeploymentException + { + if( !file.exists() ) + { + final String message = REZ.getString( "no-file.error", file ); + throw new DeploymentException( message ); + } + + if( file.isDirectory() ) + { + final String message = REZ.getString( "file-is-dir.error", file ); + throw new DeploymentException( message ); + } + } +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java index 5b04e24f8..f3e31d808 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java @@ -8,31 +8,30 @@ package org.apache.myrmidon.components.deployer; import java.io.File; -import java.net.JarURLConnection; -import java.net.MalformedURLException; import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.jar.Manifest; -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.component.ComponentException; import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.component.Composable; import org.apache.avalon.framework.logger.AbstractLogEnabled; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; import org.apache.myrmidon.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.deployer.TypeDefinition; +import org.apache.myrmidon.interfaces.deployer.ConverterDefinition; +import org.apache.myrmidon.interfaces.converter.ConverterRegistry; +import org.apache.myrmidon.interfaces.type.TypeManager; +import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; +import org.apache.myrmidon.interfaces.role.RoleManager; +import org.apache.myrmidon.converter.Converter; /** - * This class deploys a .tsk file into a registry. + * This class deploys roles, types and services from a typelib. * * @author Peter Donald * @version $Revision$ $Date$ @@ -44,34 +43,15 @@ public class DefaultDeployer private final static Resources REZ = ResourceManager.getPackageResources( DefaultDeployer.class ); - private Deployer m_parent; - private ComponentManager m_componentManager; - private PackageManager m_packageManager; + // The components used to deploy + private ConverterRegistry m_converterRegistry; + private TypeManager m_typeManager; + private RoleManager m_roleManager; + private ClassLoaderManager m_classLoaderManager; /** Map from ClassLoader to the deployer for that class loader. */ private final 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 final Map m_fileDeployers; - - /** - * Creates a root deployer. - */ - public DefaultDeployer() - { - m_fileDeployers = new HashMap(); - } - - private DefaultDeployer( final DefaultDeployer parent ) - { - m_parent = parent; - m_fileDeployers = new HashMap(); - m_fileDeployers.putAll( parent.m_fileDeployers ); - } - /** * Retrieve relevent services needed to deploy. * @@ -81,10 +61,10 @@ public class DefaultDeployer public void compose( final ComponentManager componentManager ) throws ComponentException { - m_componentManager = componentManager; - final ExtensionManager extensionManager = - (ExtensionManager)componentManager.lookup( ExtensionManager.ROLE ); - m_packageManager = new PackageManager( extensionManager ); + m_converterRegistry = (ConverterRegistry)componentManager.lookup( ConverterRegistry.ROLE ); + m_typeManager = (TypeManager)componentManager.lookup( TypeManager.ROLE ); + m_roleManager = (RoleManager)componentManager.lookup( RoleManager.ROLE ); + m_classLoaderManager = (ClassLoaderManager)componentManager.lookup( ClassLoaderManager.ROLE ); } /** @@ -93,7 +73,7 @@ public class DefaultDeployer public Deployer createChildDeployer( ComponentManager componentManager ) throws ComponentException { - final DefaultDeployer child = new DefaultDeployer( this ); + final DefaultDeployer child = new DefaultDeployer( ); setupLogger( child ); child.compose( componentManager ); return child; @@ -126,7 +106,7 @@ public class DefaultDeployer { try { - final URLClassLoader classLoader = getClassLoaderForFile( file ); + final ClassLoader classLoader = m_classLoaderManager.createClassLoader( file ); return createDeployment( classLoader, file.toURL() ); } catch( Exception e ) @@ -136,27 +116,6 @@ public class DefaultDeployer } } - /** - * Locates the classloader for a typelib file. - */ - private URLClassLoader getClassLoaderForFile( final File file ) - throws Exception - { - final File canonFile = file.getCanonicalFile(); - - // Locate cached classloader, creating it if necessary - URLClassLoader classLoader = (URLClassLoader)m_fileDeployers.get( canonFile ); - if( classLoader == null ) - { - 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 ); - } - return classLoader; - } - /** * Creates a deployer for a ClassLoader. */ @@ -168,7 +127,7 @@ public class DefaultDeployer Deployment deployment = (Deployment)m_classLoaderDeployers.get( loader ); if( deployment == null ) { - deployment = new Deployment( loader, m_componentManager ); + deployment = new Deployment( this, loader ); setupLogger( deployment ); deployment.loadDescriptors( jarUrl ); m_classLoaderDeployers.put( loader, deployment ); @@ -177,102 +136,165 @@ public class DefaultDeployer return deployment; } - private URL[] buildClasspath( final File file, final File[] dependencies ) - throws MalformedURLException + /** + * Creates a type definition. + */ + public TypeDefinition createTypeDefinition( final Configuration configuration ) + throws ConfigurationException { - final URL[] urls = new URL[ dependencies.length + 1 ]; - - for( int i = 0; i < dependencies.length; i++ ) + final String converterShorthand = m_roleManager.getNameForRole( Converter.ROLE ); + final String roleShorthand = configuration.getName(); + if( roleShorthand.equals( converterShorthand ) ) { - urls[ i ] = dependencies[ i ].toURL(); + // A converter definition + final String className = configuration.getAttribute( "classname" ); + final String source = configuration.getAttribute( "source" ); + final String destination = configuration.getAttribute( "destination" ); + return new ConverterDefinition( className, source, destination ); + } + else + { + // A type definition + final String typeName = configuration.getAttribute( "name" ); + final String className = configuration.getAttribute( "classname" ); + return new TypeDefinition( typeName, roleShorthand, className ); } - - urls[ dependencies.length ] = file.toURL(); - - return urls; } /** - * Retrieve the files for the optional packages required by - * the specified typeLibrary jar. - * - * @param typeLibrary the typeLibrary - * @return the files that need to be added to ClassLoader + * Handles a converter definition. */ - private File[] getOptionalPackagesFor( final File typeLibrary ) + private void handleConverter( final Deployment deployment, + final String className, + final String source, + final String destination ) throws Exception { - final URL url = new URL( "jar:" + typeLibrary.getCanonicalFile().toURL() + "!/" ); - final JarURLConnection connection = (JarURLConnection)url.openConnection(); - final Manifest manifest = connection.getManifest(); - final Extension[] available = Extension.getAvailable( manifest ); - final Extension[] required = Extension.getRequired( manifest ); + m_converterRegistry.registerConverter( className, source, destination ); + final DefaultTypeFactory factory = deployment.getFactory( Converter.class ); + factory.addNameClassMapping( className, className ); + m_typeManager.registerType( Converter.class, className, factory ); if( getLogger().isDebugEnabled() ) { - final String message1 = - REZ.getString( "available-extensions.notice", Arrays.asList( available ) ); - getLogger().debug( message1 ); - final String message2 = - REZ.getString( "required-extensions.notice", Arrays.asList( required ) ); - getLogger().debug( message2 ); + final String message = + REZ.getString( "register-converter.notice", source, destination ); + getLogger().debug( message ); } + } + + /** + * Handles a type definition. + */ + public void handleType( final Deployment deployment, + final TypeDefinition typeDef ) + throws Exception + { + final String typeName = typeDef.getName(); + final String roleShorthand = typeDef.getRole(); - final ArrayList dependencies = new ArrayList(); - final ArrayList unsatisfied = new ArrayList(); + final String className = typeDef.getClassname(); + if( null == className ) + { + final String message = REZ.getString( "typedef.no-classname.error" ); + throw new DeploymentException( message ); + } - m_packageManager.scanDependencies( required, - available, - dependencies, - unsatisfied ); + if( typeDef instanceof ConverterDefinition ) + { + // Validate the definition + final ConverterDefinition converterDef = (ConverterDefinition)typeDef; + final String srcClass = converterDef.getSourceType(); + final String destClass = converterDef.getDestinationType(); + if( null == srcClass ) + { + final String message = REZ.getString( "converterdef.no-source.error" ); + throw new DeploymentException( message ); + } + if( null == destClass ) + { + final String message = REZ.getString( "converterdef.no-destination.error" ); + throw new DeploymentException( message ); + } - if( 0 != unsatisfied.size() ) + // Deploy the converter + handleConverter( deployment, className, srcClass, destClass ); + } + else { - final int size = unsatisfied.size(); - for( int i = 0; i < size; i++ ) + // Validate the definition + if( null == roleShorthand ) + { + final String message = REZ.getString( "typedef.no-role.error" ); + throw new DeploymentException( message ); + } + else if( null == typeName ) { - final Extension extension = (Extension)unsatisfied.get( i ); - final Object[] params = new Object[] - { - extension.getExtensionName(), - extension.getSpecificationVendor(), - extension.getSpecificationVersion(), - extension.getImplementationVendor(), - extension.getImplementationVendorId(), - extension.getImplementationVersion(), - extension.getImplementationURL() - }; - final String message = REZ.format( "missing.extension", params ); - getLogger().warn( message ); + final String message = REZ.getString( "typedef.no-name.error" ); + throw new DeploymentException( message ); } - final String message = - REZ.getString( "unsatisfied.extensions.error", new Integer( size ) ); - throw new Exception( message ); + // Deploy general-purpose type + handleType( deployment, roleShorthand, typeName, className ); } + } + + /** + * Handles a type definition. + */ + private void handleType( final Deployment deployment, + final String roleShorthand, + final String typeName, + final String className ) + throws Exception + { + // TODO - detect duplicates + final String role = getRoleForName( roleShorthand ); + final Class roleType = deployment.getClassLoader().loadClass( role ); + final DefaultTypeFactory factory = deployment.getFactory( roleType ); + factory.addNameClassMapping( typeName, className ); + m_typeManager.registerType( roleType, typeName, factory ); - final OptionalPackage[] packages = - (OptionalPackage[])dependencies.toArray( new OptionalPackage[ 0 ] ); - return OptionalPackage.toFiles( packages ); + if( getLogger().isDebugEnabled() ) + { + final String message = + REZ.getString( "register-type.notice", roleShorthand, typeName ); + getLogger().debug( message ); + } } /** - * Ensures a file exists and is not a directory. + * Handles a role definition. */ - private void checkFile( final File file ) - throws DeploymentException + public void handleRole( final Deployment deployment, + final RoleDefinition roleDef ) { - if( !file.exists() ) + final String name = roleDef.getShortHand(); + final String role = roleDef.getRoleName(); + m_roleManager.addNameRoleMapping( name, role ); + + if( getLogger().isDebugEnabled() ) { - final String message = REZ.getString( "no-file.error", file ); - throw new DeploymentException( message ); + final String debugMessage = REZ.getString( "register-role.notice", role, name ); + getLogger().debug( debugMessage ); } + } + + /** + * Determines the role name from shorthand name. + */ + private String getRoleForName( final String name ) + throws DeploymentException + { + final String role = m_roleManager.getRoleForName( name ); - if( file.isDirectory() ) + if( null == role ) { - final String message = REZ.getString( "file-is-dir.error", file ); + final String message = REZ.getString( "unknown-role4name.error", name ); throw new DeploymentException( message ); } + + return role; } } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java index 869a39400..418f5a5ed 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java @@ -50,27 +50,20 @@ class Deployment ResourceManager.getPackageResources( Deployment.class ); private final static String DESCRIPTOR_NAME = "META-INF/ant-descriptor.xml"; - private final static String ROLE_DESCRIPTOR = "META-INF/ant-roles.xml"; + private final static String ROLE_DESCRIPTOR_NAME = "META-INF/ant-roles.xml"; private ClassLoader m_classLoader; - private ConverterRegistry m_converterRegistry; - private TypeManager m_typeManager; - private RoleManager m_roleManager; + private DefaultDeployer m_deployer; private String[] m_descriptorUrls; private Configuration[] m_descriptors; - private DefaultTypeFactory m_converterFactory; - /** Map from role name -> DefaultTypeFactory for that role. */ + /** Map from role Class -> DefaultTypeFactory for that role. */ private Map m_factories = new HashMap(); - public Deployment( final ClassLoader classLoader, ComponentManager manager ) - throws ComponentException + public Deployment( final DefaultDeployer deployer, final ClassLoader classLoader ) { - // Locate the various components needed + m_deployer = deployer; m_classLoader = classLoader; - m_converterRegistry = (ConverterRegistry)manager.lookup( ConverterRegistry.ROLE ); - m_typeManager = (TypeManager)manager.lookup( TypeManager.ROLE ); - m_roleManager = (RoleManager)manager.lookup( RoleManager.ROLE ); } /** @@ -94,7 +87,7 @@ class Deployment parser.setErrorHandler( handler ); // Load the role descriptors, and deploy all roles - final List roleUrls = locateResources( ROLE_DESCRIPTOR, jarUrl ); + final List roleUrls = locateResources( ROLE_DESCRIPTOR_NAME, jarUrl ); for( Iterator iterator = roleUrls.iterator(); iterator.hasNext(); ) { String url = (String)iterator.next(); @@ -143,7 +136,7 @@ class Deployment for( int i = 0; i < m_descriptors.length; i++ ) { Configuration descriptor = m_descriptors[ i ]; - deployFromDescriptor( descriptor, m_classLoader, m_descriptorUrls[ i ] ); + deployFromDescriptor( descriptor, m_descriptorUrls[ i ] ); } } @@ -166,8 +159,8 @@ class Deployment Configuration datatype = datatypes[ j ]; if( datatype.getAttribute( "name" ).equals( typeName ) ) { - final String className = datatype.getAttribute( "classname" ); - handleType( roleShorthand, typeName, className ); + final TypeDefinition typeDef = m_deployer.createTypeDefinition( datatype ); + m_deployer.handleType( this, typeDef ); } } } @@ -187,53 +180,9 @@ class Deployment { final String typeName = typeDef.getName(); final String roleShorthand = typeDef.getRole(); - - final String className = typeDef.getClassname(); - if( null == className ) - { - final String message = REZ.getString( "typedef.no-classname.error" ); - throw new DeploymentException( message ); - } - try { - if( typeDef instanceof ConverterDefinition ) - { - // Validate the definition - final ConverterDefinition converterDef = (ConverterDefinition)typeDef; - final String srcClass = converterDef.getSourceType(); - final String destClass = converterDef.getDestinationType(); - if( null == srcClass ) - { - final String message = REZ.getString( "converterdef.no-source.error" ); - throw new DeploymentException( message ); - } - if( null == destClass ) - { - final String message = REZ.getString( "converterdef.no-destination.error" ); - throw new DeploymentException( message ); - } - - // Deploy the converter - handleConverter( className, srcClass, destClass ); - } - else - { - // Validate the definition - if( null == roleShorthand ) - { - final String message = REZ.getString( "typedef.no-role.error" ); - throw new DeploymentException( message ); - } - else if( null == typeName ) - { - final String message = REZ.getString( "typedef.no-name.error" ); - throw new DeploymentException( message ); - } - - // Deploy general-purpose type - handleType( roleShorthand, typeName, className ); - } + m_deployer.handleType( this, typeDef ); } catch( Exception e ) { @@ -284,13 +233,8 @@ class Deployment { 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 ); - } + final RoleDefinition roleDef = new RoleDefinition( role, name ); + m_deployer.handleRole( this, roleDef ); } } @@ -298,7 +242,6 @@ class Deployment * Deploys all types from a typelib descriptor. */ private void deployFromDescriptor( final Configuration descriptor, - final ClassLoader classLoader, final String url ) throws DeploymentException { @@ -312,21 +255,8 @@ class Deployment 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 ); + final TypeDefinition typeDef = m_deployer.createTypeDefinition( typeEntry ); + m_deployer.handleType( this, typeDef ); } } catch( final Exception e ) @@ -339,7 +269,7 @@ class Deployment /** * Returns the type factory for a role. */ - private DefaultTypeFactory getFactory( final Class roleType ) + public DefaultTypeFactory getFactory( final Class roleType ) { DefaultTypeFactory factory = (DefaultTypeFactory)m_factories.get( roleType ); @@ -353,67 +283,10 @@ class Deployment } /** - * 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. + * Returns the classloader for this deployment. */ - private void handleType( final String roleShorthand, - final String typeName, - final String className ) - throws Exception + public ClassLoader getClassLoader() { - // 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; + return m_classLoader; } - } diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Resources.properties b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Resources.properties index b9d73e61a..8a443c002 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Resources.properties +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Resources.properties @@ -21,3 +21,4 @@ converterdef.no-destination.error=Must specify the destination-type parameter. 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. +create-classloader-for-file.error=Could not create ClassLoader for file {0}. diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDefinition.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDefinition.java new file mode 100644 index 000000000..d9fcf4b1a --- /dev/null +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDefinition.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) The Apache Software Foundation. All rights reserved. + * + * This software is published under the terms of the Apache Software License + * version 1.1, a copy of which has been included with this distribution in + * the LICENSE.txt file. + */ +package org.apache.myrmidon.components.deployer; + +/** + * A role definition. + * + * @author Adam Murdoch + */ +class RoleDefinition +{ + private final String m_roleName; + private final String m_shortHand; + + public RoleDefinition( final String roleName, + final String shortHand ) + { + m_roleName = roleName; + m_shortHand = shortHand; + } + + public String getRoleName() + { + return m_roleName; + } + + public String getShortHand() + { + return m_shortHand; + } +} diff --git a/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java b/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java index c4ec0bea3..5a6cdb9d4 100644 --- a/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java +++ b/proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java @@ -9,10 +9,14 @@ package org.apache.myrmidon.components.embeddor; import java.io.File; import java.io.FilenameFilter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import org.apache.avalon.excalibur.i18n.ResourceManager; import org.apache.avalon.excalibur.i18n.Resources; import org.apache.avalon.excalibur.io.ExtensionFileFilter; import org.apache.avalon.excalibur.io.FileUtil; +import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.activity.Initializable; import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.component.Composable; @@ -20,6 +24,7 @@ import org.apache.avalon.framework.component.DefaultComponentManager; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.parameters.Parameterizable; import org.apache.avalon.framework.parameters.Parameters; +import org.apache.myrmidon.components.deployer.ClassLoaderManager; import org.apache.myrmidon.interfaces.aspect.AspectManager; import org.apache.myrmidon.interfaces.builder.ProjectBuilder; import org.apache.myrmidon.interfaces.configurer.Configurer; @@ -52,37 +57,33 @@ public class DefaultEmbeddor ResourceManager.getPackageResources( DefaultEmbeddor.class ); private Deployer m_deployer; - private RoleManager m_roleManager; - - private AspectManager m_aspectManager; private TypeManager m_typeManager; - private MasterConverter m_converter; - private ConverterRegistry m_converterRegistry; - private ExtensionManager m_extensionManager; - - private Executor m_executor; - private Configurer m_configurer; - private DefaultComponentManager m_componentManager; + private List m_components = new ArrayList(); + private DefaultComponentManager m_componentManager = new DefaultComponentManager(); private Parameters m_parameters; private Parameters m_defaults; private File m_homeDir; - private File m_binDir; - private File m_libDir; private File m_taskLibDir; + /** Package containing the default component implementations. */ + private static final String PREFIX = "org.apache.myrmidon.components."; + /** * Setup basic properties of engine. * Called before init() and can be used to specify alternate components in system. * - * @param properties the properties + * @param parameters the parameters. */ public void parameterize( final Parameters parameters ) { m_parameters = parameters; } + /** + * Builds a project. + */ public Project createProject( final String location, final String type, final Parameters parameters ) @@ -91,18 +92,16 @@ public class DefaultEmbeddor String projectType = type; if( null == projectType ) { - projectType = guessTypeFor( location ); + projectType = FileUtil.getExtension( location ); } final ProjectBuilder builder = getProjectBuilder( projectType, parameters ); return builder.build( location ); } - private String guessTypeFor( final String location ) - { - return FileUtil.getExtension( location ); - } - + /** + * Creates a project builder for a project type. + */ private ProjectBuilder getProjectBuilder( final String type, final Parameters parameters ) throws Exception @@ -110,51 +109,20 @@ public class DefaultEmbeddor final TypeFactory factory = m_typeManager.getFactory( ProjectBuilder.class ); final ProjectBuilder builder = (ProjectBuilder)factory.create( type ); - - setupLogger( builder ); - - if( builder instanceof Composable ) - { - ( (Composable)builder ).compose( m_componentManager ); - } - - if( builder instanceof Parameterizable ) - { - ( (Parameterizable)builder ).parameterize( parameters ); - } - - if( builder instanceof Initializable ) - { - ( (Initializable)builder ).initialize(); - } - + setupObject( builder, parameters ); return builder; } + /** + * Creates a workspace. + */ public Workspace createWorkspace( final Parameters parameters ) throws Exception { final String component = getParameter( Workspace.ROLE ); final Workspace workspace = (Workspace)createComponent( component, Workspace.class ); - - setupLogger( workspace ); - - if( workspace instanceof Composable ) - { - ( (Composable)workspace ).compose( m_componentManager ); - } - - if( workspace instanceof Parameterizable ) - { - ( (Parameterizable)workspace ).parameterize( parameters ); - } - - if( workspace instanceof Initializable ) - { - ( (Initializable)workspace ).initialize(); - } - + setupObject( workspace, parameters ); return workspace; } @@ -172,11 +140,12 @@ public class DefaultEmbeddor //create all the components createComponents(); - //setup the component manager - m_componentManager = createComponentManager(); - + //setup the components setupComponents(); + m_deployer = (Deployer)m_componentManager.lookup( Deployer.ROLE ); + m_typeManager = (TypeManager)m_componentManager.lookup( TypeManager.ROLE ); + setupFiles(); } @@ -193,32 +162,36 @@ public class DefaultEmbeddor deployFromDirectory( m_deployer, m_taskLibDir, filter ); } + /** + * Stops the engine. + */ public void stop() { - //Undeploy all the tasks by killing ExecutionFrame??? + //TODO - Undeploy all the tasks by killing ExecutionFrame??? } /** * Dispose engine. - * - * @exception Exception if an error occurs */ public void dispose() { - m_extensionManager = null; - m_aspectManager = null; - m_roleManager = null; - m_converterRegistry = null; - m_converter = null; - m_executor = null; + // Dispose any disposable components + for( Iterator iterator = m_components.iterator(); iterator.hasNext(); ) + { + Component component = (Component)iterator.next(); + if( component instanceof Disposable ) + { + ( (Disposable)component ).dispose(); + } + } + + // Ditch everything + m_components = null; m_deployer = null; - m_configurer = null; m_componentManager = null; m_parameters = null; m_defaults = null; m_homeDir = null; - m_binDir = null; - m_libDir = null; m_taskLibDir = null; } @@ -236,137 +209,55 @@ public class DefaultEmbeddor defaults.setParameter( "myrmidon.bin.path", "bin" ); defaults.setParameter( "myrmidon.lib.path", "lib" ); - //create all the default properties for components - final String PREFIX = "org.apache.myrmidon.components."; - defaults.setParameter( AspectManager.ROLE, PREFIX + "aspect.DefaultAspectManager" ); - defaults.setParameter( RoleManager.ROLE, PREFIX + "role.DefaultRoleManager" ); - defaults.setParameter( MasterConverter.ROLE, PREFIX + "converter.DefaultMasterConverter" ); - defaults.setParameter( ConverterRegistry.ROLE, PREFIX + "converter.DefaultConverterRegistry" ); - defaults.setParameter( TypeManager.ROLE, PREFIX + "type.DefaultTypeManager" ); - defaults.setParameter( Executor.ROLE, - //"org.apache.myrmidon.components.executor.DefaultExecutor" ); - //"org.apache.myrmidon.components.executor.PrintingExecutor" ); - PREFIX + "executor.AspectAwareExecutor" ); + // Default workspace implementation defaults.setParameter( Workspace.ROLE, PREFIX + "workspace.DefaultWorkspace" ); - defaults.setParameter( Deployer.ROLE, PREFIX + "deployer.DefaultDeployer" ); - defaults.setParameter( Configurer.ROLE, PREFIX + "configurer.DefaultConfigurer" ); - defaults.setParameter( ExtensionManager.ROLE, PREFIX + "extensions.DefaultExtensionManager" ); return defaults; } - /** - * Create a ComponentManager containing all components in engine. - * - * @return the ComponentManager - */ - private DefaultComponentManager createComponentManager() - { - final DefaultComponentManager componentManager = new DefaultComponentManager(); - - componentManager.put( MasterConverter.ROLE, m_converter ); - - //Following components required when Myrmidon is used as build tool - componentManager.put( Embeddor.ROLE, this ); - - //Following components required when Myrmidon allows user deployment of tasks etal. - componentManager.put( RoleManager.ROLE, m_roleManager ); - componentManager.put( Deployer.ROLE, m_deployer ); - componentManager.put( ExtensionManager.ROLE, m_extensionManager ); - - //Following components used when want to types (ie tasks/mappers etc) - componentManager.put( TypeManager.ROLE, m_typeManager ); - componentManager.put( ConverterRegistry.ROLE, m_converterRegistry ); - - componentManager.put( AspectManager.ROLE, m_aspectManager ); - - //Following components required when allowing Container tasks - componentManager.put( Configurer.ROLE, m_configurer ); - componentManager.put( Executor.ROLE, m_executor ); - - return componentManager; - } - /** * Create all required components. - * - * @exception Exception if an error occurs */ private void createComponents() throws Exception { - String component = null; - - component = getParameter( ConverterRegistry.ROLE ); - m_converterRegistry = (ConverterRegistry)createComponent( component, ConverterRegistry.class ); - - component = getParameter( ExtensionManager.ROLE ); - m_extensionManager = (ExtensionManager)createComponent( component, ExtensionManager.class ); - - component = getParameter( MasterConverter.ROLE ); - m_converter = (MasterConverter)createComponent( component, MasterConverter.class ); - - component = getParameter( Configurer.ROLE ); - m_configurer = (Configurer)createComponent( component, Configurer.class ); - - component = getParameter( TypeManager.ROLE ); - m_typeManager = (TypeManager)createComponent( component, TypeManager.class ); - - component = getParameter( RoleManager.ROLE ); - m_roleManager = (RoleManager)createComponent( component, RoleManager.class ); - - component = getParameter( AspectManager.ROLE ); - m_aspectManager = (AspectManager)createComponent( component, AspectManager.class ); - - component = getParameter( Deployer.ROLE ); - m_deployer = (Deployer)createComponent( component, Deployer.class ); - - component = getParameter( Executor.ROLE ); - m_executor = (Executor)createComponent( component, Executor.class ); + createComponent( ConverterRegistry.class, PREFIX + "converter.DefaultConverterRegistry" ); + createComponent( ExtensionManager.class, PREFIX + "extensions.DefaultExtensionManager" ); + createComponent( MasterConverter.class, PREFIX + "converter.DefaultMasterConverter" ); + createComponent( Configurer.class, PREFIX + "configurer.DefaultConfigurer" ); + createComponent( TypeManager.class, PREFIX + "type.DefaultTypeManager" ); + createComponent( RoleManager.class, PREFIX + "role.DefaultRoleManager" ); + createComponent( AspectManager.class, PREFIX + "aspect.DefaultAspectManager" ); + createComponent( Deployer.class, PREFIX + "deployer.DefaultDeployer" ); + createComponent( ClassLoaderManager.class, PREFIX + "deployer.DefaultClassLoaderManager" ); + createComponent( Executor.class, PREFIX + "executor.AspectAwareExecutor" ); } /** - * Setup all the components. (ir run all required lifecycle methods). - * - * @exception Exception if an error occurs + * Creates a component. */ - private void setupComponents() + private void createComponent( Class roleType, String defaultImpl ) throws Exception { - setupComponent( m_extensionManager ); - setupComponent( m_roleManager ); - setupComponent( m_aspectManager ); - setupComponent( m_converterRegistry ); - setupComponent( m_converter ); - setupComponent( m_executor ); - setupComponent( m_deployer ); - setupComponent( m_configurer ); + final String role = roleType.getName(); + final String className = m_parameters.getParameter( role, defaultImpl ); + final Component component = createComponent( className, roleType ); + m_componentManager.put( role, component ); + m_components.add( component ); } /** - * Setup an individual component. + * Setup all the components. (ir run all required lifecycle methods). * - * @param component the component * @exception Exception if an error occurs */ - private void setupComponent( final Component component ) + private void setupComponents() throws Exception { - setupLogger( component ); - - if( component instanceof Composable ) + for( Iterator iterator = m_components.iterator(); iterator.hasNext(); ) { - ( (Composable)component ).compose( m_componentManager ); - } - - if( component instanceof Parameterizable ) - { - ( (Parameterizable)component ).parameterize( m_parameters ); - } - - if( component instanceof Initializable ) - { - ( (Initializable)component ).initialize(); + final Component component = (Component)iterator.next(); + setupObject( component, m_parameters ); } } @@ -382,9 +273,6 @@ public class DefaultEmbeddor m_homeDir = ( new File( filepath ) ).getAbsoluteFile(); checkDirectory( m_homeDir, "home" ); - filepath = getParameter( "myrmidon.bin.path" ); - m_binDir = resolveDirectory( filepath, "bin-dir" ); - filepath = getParameter( "myrmidon.lib.path" ); m_taskLibDir = resolveDirectory( filepath, "task-lib-dir" ); } @@ -453,7 +341,7 @@ public class DefaultEmbeddor * @return the created object * @exception Exception if an error occurs */ - private Object createComponent( final String component, final Class clazz ) + private Component createComponent( final String component, final Class clazz ) throws Exception { try @@ -465,8 +353,13 @@ public class DefaultEmbeddor final String message = REZ.getString( "bad-type.error", component, clazz.getName() ); throw new Exception( message ); } + if( !( object instanceof Component) ) + { + final String message = REZ.getString( "bad-type.error", component, Component.class.getName() ); + throw new Exception( message ); + } - return object; + return (Component)object; } catch( final IllegalAccessException iae ) { @@ -487,6 +380,32 @@ public class DefaultEmbeddor } } + /** + * Sets-up an object by running it through the log-enable, compose, + * parameterise and initialise lifecycle stages. + */ + private void setupObject( final Object object, + final Parameters parameters ) + throws Exception + { + setupLogger( object ); + + if( object instanceof Composable ) + { + ( (Composable)object ).compose( m_componentManager ); + } + + if( object instanceof Parameterizable ) + { + ( (Parameterizable)object ).parameterize( parameters ); + } + + if( object instanceof Initializable ) + { + ( (Initializable)object ).initialize(); + } + } + /** * Deploys all type libraries in a directory. */ diff --git a/proposal/myrmidon/src/manifest/ant1-ant-descriptor.xml b/proposal/myrmidon/src/manifest/ant1-ant-descriptor.xml index a11b941c3..4146be221 100644 --- a/proposal/myrmidon/src/manifest/ant1-ant-descriptor.xml +++ b/proposal/myrmidon/src/manifest/ant1-ant-descriptor.xml @@ -5,13 +5,11 @@ - - - - + /> + + \ No newline at end of file diff --git a/proposal/myrmidon/src/manifest/core-ant-descriptor.template b/proposal/myrmidon/src/manifest/core-ant-descriptor.template index 54a1a7a17..b17bd3c34 100644 --- a/proposal/myrmidon/src/manifest/core-ant-descriptor.template +++ b/proposal/myrmidon/src/manifest/core-ant-descriptor.template @@ -18,10 +18,6 @@ - - - - - + diff --git a/proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractFileSystemTest.java b/proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractFileSystemTest.java index 2102122f5..9bf3aefbf 100644 --- a/proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractFileSystemTest.java +++ b/proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractFileSystemTest.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Map; import junit.framework.TestCase; import org.apache.aut.vfs.impl.DefaultFileSystemManager; +import org.apache.myrmidon.AbstractMyrmidonTest; /** * File system test cases, which verifies the structure and naming @@ -28,7 +29,8 @@ import org.apache.aut.vfs.impl.DefaultFileSystemManager; * * @author Adam Murdoch */ -public abstract class AbstractFileSystemTest extends TestCase +public abstract class AbstractFileSystemTest + extends AbstractMyrmidonTest { protected FileObject m_baseFolder; protected DefaultFileSystemManager m_manager; @@ -63,7 +65,7 @@ public abstract class AbstractFileSystemTest extends TestCase /** * Returns the URI for the base folder. */ - protected abstract String getBaseFolderURI(); + protected abstract String getBaseFolderURI() throws Exception; /** * Sets up the test @@ -160,7 +162,7 @@ public abstract class AbstractFileSystemTest extends TestCase // Try using a compound name to find a child try { - FileName name2 = name.resolveName( "a/b", NameScope.CHILD ); + name.resolveName( "a/b", NameScope.CHILD ); assertTrue( false ); } catch( FileSystemException e ) @@ -170,7 +172,7 @@ public abstract class AbstractFileSystemTest extends TestCase // Try using a empty name to find a child try { - FileName name2 = name.resolveName( "", NameScope.CHILD ); + name.resolveName( "", NameScope.CHILD ); assertTrue( false ); } catch( FileSystemException e ) @@ -180,7 +182,7 @@ public abstract class AbstractFileSystemTest extends TestCase // Try using '.' to find a child try { - FileName name2 = name.resolveName( ".", NameScope.CHILD ); + name.resolveName( ".", NameScope.CHILD ); assertTrue( false ); } catch( FileSystemException e ) @@ -190,7 +192,7 @@ public abstract class AbstractFileSystemTest extends TestCase // Try using '..' to find a child try { - FileName name2 = name.resolveName( "..", NameScope.CHILD ); + name.resolveName( "..", NameScope.CHILD ); assertTrue( false ); } catch( FileSystemException e ) @@ -280,14 +282,6 @@ public abstract class AbstractFileSystemTest extends TestCase assertSameName( childPath, baseName, "a/b/../../some-child" ); } - /** - * Tests relative name resolution, relative to the root file. - */ - public void testNameResolutionRoot() throws Exception - { - FileName rootName = m_baseFolder.getRoot().getName(); - } - /** * Walks the folder structure, asserting it contains exactly the * expected files and folders. diff --git a/proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractWritableFileSystemTest.java b/proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractWritableFileSystemTest.java index da0ad75bd..2481390df 100644 --- a/proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractWritableFileSystemTest.java +++ b/proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractWritableFileSystemTest.java @@ -27,7 +27,7 @@ public abstract class AbstractWritableFileSystemTest extends AbstractFileSystemT /** * Returns the URI for the area to do tests in. */ - protected abstract String getWriteFolderURI(); + protected abstract String getWriteFolderURI() throws Exception; /** * Sets up a scratch folder for the test to use. diff --git a/proposal/myrmidon/src/test/org/apache/aut/vfs/LocalFileSystemTest.java b/proposal/myrmidon/src/test/org/apache/aut/vfs/LocalFileSystemTest.java index 4e53b92ea..ae74afe75 100644 --- a/proposal/myrmidon/src/test/org/apache/aut/vfs/LocalFileSystemTest.java +++ b/proposal/myrmidon/src/test/org/apache/aut/vfs/LocalFileSystemTest.java @@ -16,33 +16,29 @@ import java.io.File; */ public class LocalFileSystemTest extends AbstractWritableFileSystemTest { - private File m_baseDir; - public LocalFileSystemTest( String name ) { super( name ); - String baseDir = System.getProperty( "test.local.dir" ); - m_baseDir = new File( baseDir ); } /** * Returns the URI for the base folder. */ protected String getBaseFolderURI() + throws Exception { - String testDir = new File( m_baseDir, "read-tests" ).getAbsolutePath(); - String uri = "file:/" + testDir; - return uri; + final File testDir = getTestResource( "basedir" ); + return testDir.toURL().toString(); } /** * Returns the URI for the area to do tests in. */ protected String getWriteFolderURI() + throws Exception { - String testDir = new File( m_baseDir, "write-tests" ).getAbsolutePath(); - String uri = "file:/" + testDir; - return uri; + final File testDir = getTestResource( "write-tests" ); + return testDir.toURL().toString(); } /** diff --git a/proposal/myrmidon/src/test/org/apache/aut/vfs/ZipFileSystemTest.java b/proposal/myrmidon/src/test/org/apache/aut/vfs/ZipFileSystemTest.java index 1d4e9ff9a..8755781c9 100644 --- a/proposal/myrmidon/src/test/org/apache/aut/vfs/ZipFileSystemTest.java +++ b/proposal/myrmidon/src/test/org/apache/aut/vfs/ZipFileSystemTest.java @@ -26,8 +26,7 @@ public class ZipFileSystemTest extends AbstractReadOnlyFileSystemTest */ protected String getBaseFolderURI() { - String zipFileName = System.getProperty( "test.zip.file" ); - String zipFile = new File( zipFileName ).getAbsolutePath(); + File zipFile = getTestResource( "test.zip" ); String uri = "zip:" + zipFile + "!basedir"; return uri; } diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java new file mode 100644 index 000000000..91e7311c6 --- /dev/null +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java @@ -0,0 +1,71 @@ +/* + * 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; + +import junit.framework.TestCase; +import java.io.File; + +/** + * A base class for Myrmidon tests. Provides utility methods for locating + * test resources. + * + * @author Adam Murdoch + */ +public abstract class AbstractMyrmidonTest + extends TestCase +{ + private final File m_testBaseDir; + + public AbstractMyrmidonTest( String name ) + { + super( name ); + final String baseDirProp = System.getProperty( "test.basedir" ); + String packagePath = getClass().getName(); + int idx = packagePath.lastIndexOf('.'); + packagePath = packagePath.substring(0, idx); + packagePath = packagePath.replace('.', File.separatorChar); + m_testBaseDir = new File( baseDirProp, packagePath ).getAbsoluteFile(); + } + + /** + * Locates a test resource. + */ + protected File getTestResource( final String name ) + { + return new File( m_testBaseDir, name ); + } + + /** + * Asserts that an exception contains the expected message. + * + * TODO - should take the expected exception, rather than the message, + * to check the entire cause chain. + */ + protected void assertSameMessage( final String message, final Throwable throwable ) + { + assertEquals( message, throwable.getMessage() ); + } + + /** + * Compares 2 objects for equality, nulls are equal. Used by the test + * classes' equals() methods. + */ + public static boolean equals( final Object o1, final Object o2 ) + { + if( o1 == null && o2 == null ) + { + return true; + } + if( o1 == null || o2 == null ) + { + return false; + } + return o1.equals( o2 ); + } + +} diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java index 378c19dde..fd4248301 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java @@ -28,6 +28,8 @@ import org.apache.myrmidon.components.configurer.DefaultConfigurer; import org.apache.myrmidon.components.converter.DefaultConverterRegistry; import org.apache.myrmidon.components.converter.DefaultMasterConverter; import org.apache.myrmidon.components.deployer.DefaultDeployer; +import org.apache.myrmidon.components.deployer.DefaultClassLoaderManager; +import org.apache.myrmidon.components.deployer.ClassLoaderManager; import org.apache.myrmidon.components.extensions.DefaultExtensionManager; import org.apache.myrmidon.components.role.DefaultRoleManager; import org.apache.myrmidon.components.type.DefaultTypeManager; @@ -41,6 +43,7 @@ import org.apache.myrmidon.interfaces.type.TypeManager; import org.apache.myrmidon.interfaces.type.TypeException; import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; import org.apache.myrmidon.converter.Converter; +import org.apache.myrmidon.AbstractMyrmidonTest; /** * A base class for tests for the default components. @@ -48,7 +51,7 @@ import org.apache.myrmidon.converter.Converter; * @author Adam Murdoch */ public abstract class AbstractComponentTest - extends TestCase + extends AbstractMyrmidonTest { private DefaultComponentManager m_componentManager; private Logger m_logger; @@ -117,6 +120,11 @@ public abstract class AbstractComponentTest m_componentManager.put( Deployer.ROLE, component ); components.add( component ); + final DefaultClassLoaderManager classLoaderMgr = new DefaultClassLoaderManager(); + classLoaderMgr.setBaseClassLoader( getClass().getClassLoader() ); + m_componentManager.put( ClassLoaderManager.ROLE, classLoaderMgr ); + components.add( classLoaderMgr ); + component = new DefaultExtensionManager(); m_componentManager.put( ExtensionManager.ROLE, component ); components.add( component ); @@ -162,32 +170,4 @@ public abstract class AbstractComponentTest factory.addNameClassMapping( converterClass.getName(), converterClass.getName() ); getTypeManager().registerType( Converter.class, converterClass.getName(), factory ); } - - /** - * Asserts that an exception contains the expected message. - * - * TODO - should take the expected exception, rather than the message, - * to check the entire cause chain. - */ - protected void assertSameMessage( final String message, final Throwable throwable ) - { - assertEquals( message, throwable.getMessage() ); - } - - /** - * Compares 2 objects for equality, nulls are equal. Used by the test - * classes' equals() methods. - */ - public static boolean equals( final Object o1, final Object o2 ) - { - if( o1 == null && o2 == null ) - { - return true; - } - if( o1 == null || o2 == null ) - { - return false; - } - return o1.equals( o2 ); - } } diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java index 010cbb021..81d17279a 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java @@ -16,6 +16,11 @@ import org.apache.myrmidon.interfaces.deployer.TypeDefinition; import org.apache.myrmidon.interfaces.deployer.TypeDeployer; import org.apache.myrmidon.interfaces.role.RoleManager; import org.apache.myrmidon.interfaces.type.TypeFactory; +import org.apache.myrmidon.interfaces.type.TypeManager; +import org.apache.myrmidon.interfaces.type.TypeException; +import org.apache.myrmidon.converter.ConverterException; +import org.apache.myrmidon.converter.Converter; +import java.io.File; /** * Test cases for the default deployer. @@ -25,7 +30,12 @@ import org.apache.myrmidon.interfaces.type.TypeFactory; public class DefaultDeployerTest extends AbstractComponentTest { + private static final String TEST_TYPE1_NAME = "test-type1"; + private static final String DATA_TYPE_ROLE = "data-type"; + private Deployer m_deployer; + private RoleManager m_roleManager; + private MasterConverter m_converter; public DefaultDeployerTest( final String name ) { @@ -40,6 +50,12 @@ public class DefaultDeployerTest { super.setUp(); m_deployer = (Deployer)getComponentManager().lookup( Deployer.ROLE ); + m_converter = (MasterConverter)getComponentManager().lookup( MasterConverter.ROLE ); + + // Add some core roles + m_roleManager = (RoleManager)getComponentManager().lookup( RoleManager.ROLE ); + m_roleManager.addNameRoleMapping( DATA_TYPE_ROLE, DataType.ROLE ); + m_roleManager.addNameRoleMapping( "converter", Converter.ROLE ); } /** @@ -47,27 +63,26 @@ public class DefaultDeployerTest */ public void testSingleType() throws Exception { - final String roleName = "data-type"; - final String typeName = "test-type1"; + final String typeName = TEST_TYPE1_NAME; final String classname = TestType1.class.getName(); // Determine the shorthand for the DataType role - final RoleManager roleManager = (RoleManager)getComponentManager().lookup( RoleManager.ROLE ); - roleManager.addNameRoleMapping( roleName, DataType.ROLE ); // Create the type definition - final TypeDefinition typeDef = new TypeDefinition( typeName, roleName, classname ); + final TypeDefinition typeDef = new TypeDefinition( typeName, DATA_TYPE_ROLE, classname ); - // Deploy the type final ClassLoader classLoader = getClass().getClassLoader(); final TypeDeployer typeDeployer = m_deployer.createDeployer( classLoader ); + + // Make sure the test types have not been deployed + assertTypesNotRegistered( ); + + // Deploy the type typeDeployer.deployType( typeDef ); - // Create an instance + // Check the type has been registered final TypeFactory typeFactory = getTypeManager().getFactory( DataType.class ); final Object result = typeFactory.create( typeName ); - - // Check the type assertTrue( result instanceof TestType1 ); } @@ -84,16 +99,99 @@ public class DefaultDeployerTest final ConverterDefinition typeDef = new ConverterDefinition( classname, source, destClass ); - // Deploy the type final ClassLoader classLoader = getClass().getClassLoader(); final TypeDeployer typeDeployer = m_deployer.createDeployer( classLoader ); + + // Make sure the test types have not been deployed + assertTypesNotRegistered( ); + + // Deploy the type typeDeployer.deployType( typeDef ); // Try to convert from string to test type - final MasterConverter converter = (MasterConverter)getComponentManager().lookup( MasterConverter.ROLE ); - final Object result = converter.convert( TestType1.class, "some-string", null ); - - // Check the type + final Object result = m_converter.convert( TestType1.class, "some-string", null ); assertTrue( result instanceof TestType1 ); } + + /** + * Tests deployment of types from a typelib descriptor. + */ + public void testLibDescriptor() throws Exception + { + final File typelib = getTestResource( "test.atl" ); + assertTrue( "File " + typelib + " does not exist", typelib.exists() ); + + final TypeDeployer typeDeployer = m_deployer.createDeployer( typelib ); + + // Make sure the test types have not been deployed + assertTypesNotRegistered(); + + // Deploy all the types from the descriptor + typeDeployer.deployAll(); + + // Make sure the test types have been deployed + assertTypesRegistered(); + } + + /** + * Ensures that the test types have not ben deployed. + */ + private void assertTypesNotRegistered() throws Exception + { + // Check the data-type + TypeFactory typeFactory = getTypeManager().getFactory( DataType.class ); + try + { + typeFactory.create( TEST_TYPE1_NAME ); + fail(); + } + catch( TypeException e ) + { + // TODO - check error message + } + + // Check the custom role implementation + typeFactory = getTypeManager().getFactory( TestRole1.class ); + try + { + typeFactory.create( TEST_TYPE1_NAME ); + fail(); + } + catch( TypeException e ) + { + // TODO - check error message + } + + // Check the converter + try + { + m_converter.convert( TestType1.class, "some string", null ); + fail(); + } + catch( ConverterException e ) + { + // TODO - check error message + } + } + + /** + * Ensures the types from the test typelib descriptor have been correctly + * deployed. + */ + private void assertTypesRegistered( ) throws Exception + { + // Check the data-type + TypeFactory typeFactory = getTypeManager().getFactory( DataType.class ); + Object object = typeFactory.create( TEST_TYPE1_NAME ); + assertTrue( object instanceof TestType1 ); + + // Check the custom role implementation + typeFactory = getTypeManager().getFactory( TestRole1.class ); + object = typeFactory.create( TEST_TYPE1_NAME ); + assertTrue( object instanceof TestType1 ); + + // Check the converter + object = m_converter.convert( TestType1.class, "some string", null ); + assertTrue( object instanceof TestType1 ); + } } diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/TestRole1.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/TestRole1.java new file mode 100644 index 000000000..93dc94f6d --- /dev/null +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/TestRole1.java @@ -0,0 +1,18 @@ +/* + * Copyright (C) The Apache Software Foundation. All rights reserved. + * + * This software is published under the terms of the Apache Software License + * version 1.1, a copy of which has been included with this distribution in + * the LICENSE.txt file. + */ +package org.apache.myrmidon.components.deployer; + +/** + * A test role interface. + * + * @author Adam Murdoch + */ +public interface TestRole1 +{ + String ROLE = TestRole1.class.getName(); +} diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/TestType1.java b/proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/TestType1.java index a0c6e3109..444ea9e62 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/TestType1.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/TestType1.java @@ -15,6 +15,6 @@ import org.apache.myrmidon.framework.DataType; * @author Adam Murdoch */ public class TestType1 - implements DataType + implements DataType, TestRole1 { } diff --git a/proposal/myrmidon/src/test/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java b/proposal/myrmidon/src/test/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java index 6b3f8fad9..28d583555 100644 --- a/proposal/myrmidon/src/test/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java +++ b/proposal/myrmidon/src/test/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java @@ -10,15 +10,16 @@ package org.apache.myrmidon.interfaces.type; import java.io.File; import java.net.URL; import junit.framework.TestCase; +import org.apache.myrmidon.AbstractMyrmidonTest; /** - * These are unit tests that test the basic operation of TypeFactorys. + * These are unit tests that test the basic operation of TypeFactories. * * @author Peter Donald * @version $Revision$ $Date$ */ public class TypeFactoryTest - extends TestCase + extends AbstractMyrmidonTest { private final static String TYPE_NAME1 = "my-type1"; private final static String TYPE_NAME2 = "my-type2"; @@ -27,9 +28,6 @@ public class TypeFactoryTest private final static String TYPE_CLASSNAME1 = TYPE_CLASS1.getName(); private final static String TYPE_CLASSNAME2 = TYPE_CLASS2.getName(); - private final static String TYPE_JAR = - "src/testcases/org/apache/myrmidon/interfaces/type/types.jar".replace( '/', File.separatorChar ); - public TypeFactoryTest( final String name ) { super( name ); @@ -64,11 +62,10 @@ public class TypeFactoryTest public void testReloadingTypeFactory() throws Exception { - final File file = new File( TYPE_JAR ); - assertTrue( "Support Jar exists", file.exists() ); + final File file = getTestResource( "types.jar" ); + assertTrue( "Support Jar " + file + " exists", file.exists() ); final URL[] classpath = new URL[]{file.toURL()}; - final ClassLoader classLoader = getClass().getClassLoader(); final ReloadingTypeFactory factory = new ReloadingTypeFactory( classpath, null ); factory.addNameClassMapping( TYPE_NAME1, TYPE_CLASSNAME1 ); diff --git a/proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractFileSystemTest.java b/proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractFileSystemTest.java index 2102122f5..9bf3aefbf 100644 --- a/proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractFileSystemTest.java +++ b/proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractFileSystemTest.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Map; import junit.framework.TestCase; import org.apache.aut.vfs.impl.DefaultFileSystemManager; +import org.apache.myrmidon.AbstractMyrmidonTest; /** * File system test cases, which verifies the structure and naming @@ -28,7 +29,8 @@ import org.apache.aut.vfs.impl.DefaultFileSystemManager; * * @author Adam Murdoch */ -public abstract class AbstractFileSystemTest extends TestCase +public abstract class AbstractFileSystemTest + extends AbstractMyrmidonTest { protected FileObject m_baseFolder; protected DefaultFileSystemManager m_manager; @@ -63,7 +65,7 @@ public abstract class AbstractFileSystemTest extends TestCase /** * Returns the URI for the base folder. */ - protected abstract String getBaseFolderURI(); + protected abstract String getBaseFolderURI() throws Exception; /** * Sets up the test @@ -160,7 +162,7 @@ public abstract class AbstractFileSystemTest extends TestCase // Try using a compound name to find a child try { - FileName name2 = name.resolveName( "a/b", NameScope.CHILD ); + name.resolveName( "a/b", NameScope.CHILD ); assertTrue( false ); } catch( FileSystemException e ) @@ -170,7 +172,7 @@ public abstract class AbstractFileSystemTest extends TestCase // Try using a empty name to find a child try { - FileName name2 = name.resolveName( "", NameScope.CHILD ); + name.resolveName( "", NameScope.CHILD ); assertTrue( false ); } catch( FileSystemException e ) @@ -180,7 +182,7 @@ public abstract class AbstractFileSystemTest extends TestCase // Try using '.' to find a child try { - FileName name2 = name.resolveName( ".", NameScope.CHILD ); + name.resolveName( ".", NameScope.CHILD ); assertTrue( false ); } catch( FileSystemException e ) @@ -190,7 +192,7 @@ public abstract class AbstractFileSystemTest extends TestCase // Try using '..' to find a child try { - FileName name2 = name.resolveName( "..", NameScope.CHILD ); + name.resolveName( "..", NameScope.CHILD ); assertTrue( false ); } catch( FileSystemException e ) @@ -280,14 +282,6 @@ public abstract class AbstractFileSystemTest extends TestCase assertSameName( childPath, baseName, "a/b/../../some-child" ); } - /** - * Tests relative name resolution, relative to the root file. - */ - public void testNameResolutionRoot() throws Exception - { - FileName rootName = m_baseFolder.getRoot().getName(); - } - /** * Walks the folder structure, asserting it contains exactly the * expected files and folders. diff --git a/proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractWritableFileSystemTest.java b/proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractWritableFileSystemTest.java index da0ad75bd..2481390df 100644 --- a/proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractWritableFileSystemTest.java +++ b/proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractWritableFileSystemTest.java @@ -27,7 +27,7 @@ public abstract class AbstractWritableFileSystemTest extends AbstractFileSystemT /** * Returns the URI for the area to do tests in. */ - protected abstract String getWriteFolderURI(); + protected abstract String getWriteFolderURI() throws Exception; /** * Sets up a scratch folder for the test to use. diff --git a/proposal/myrmidon/src/testcases/org/apache/aut/vfs/LocalFileSystemTest.java b/proposal/myrmidon/src/testcases/org/apache/aut/vfs/LocalFileSystemTest.java index 4e53b92ea..ae74afe75 100644 --- a/proposal/myrmidon/src/testcases/org/apache/aut/vfs/LocalFileSystemTest.java +++ b/proposal/myrmidon/src/testcases/org/apache/aut/vfs/LocalFileSystemTest.java @@ -16,33 +16,29 @@ import java.io.File; */ public class LocalFileSystemTest extends AbstractWritableFileSystemTest { - private File m_baseDir; - public LocalFileSystemTest( String name ) { super( name ); - String baseDir = System.getProperty( "test.local.dir" ); - m_baseDir = new File( baseDir ); } /** * Returns the URI for the base folder. */ protected String getBaseFolderURI() + throws Exception { - String testDir = new File( m_baseDir, "read-tests" ).getAbsolutePath(); - String uri = "file:/" + testDir; - return uri; + final File testDir = getTestResource( "basedir" ); + return testDir.toURL().toString(); } /** * Returns the URI for the area to do tests in. */ protected String getWriteFolderURI() + throws Exception { - String testDir = new File( m_baseDir, "write-tests" ).getAbsolutePath(); - String uri = "file:/" + testDir; - return uri; + final File testDir = getTestResource( "write-tests" ); + return testDir.toURL().toString(); } /** diff --git a/proposal/myrmidon/src/testcases/org/apache/aut/vfs/ZipFileSystemTest.java b/proposal/myrmidon/src/testcases/org/apache/aut/vfs/ZipFileSystemTest.java index 1d4e9ff9a..8755781c9 100644 --- a/proposal/myrmidon/src/testcases/org/apache/aut/vfs/ZipFileSystemTest.java +++ b/proposal/myrmidon/src/testcases/org/apache/aut/vfs/ZipFileSystemTest.java @@ -26,8 +26,7 @@ public class ZipFileSystemTest extends AbstractReadOnlyFileSystemTest */ protected String getBaseFolderURI() { - String zipFileName = System.getProperty( "test.zip.file" ); - String zipFile = new File( zipFileName ).getAbsolutePath(); + File zipFile = getTestResource( "test.zip" ); String uri = "zip:" + zipFile + "!basedir"; return uri; } diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/AbstractMyrmidonTest.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/AbstractMyrmidonTest.java new file mode 100644 index 000000000..91e7311c6 --- /dev/null +++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/AbstractMyrmidonTest.java @@ -0,0 +1,71 @@ +/* + * 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; + +import junit.framework.TestCase; +import java.io.File; + +/** + * A base class for Myrmidon tests. Provides utility methods for locating + * test resources. + * + * @author Adam Murdoch + */ +public abstract class AbstractMyrmidonTest + extends TestCase +{ + private final File m_testBaseDir; + + public AbstractMyrmidonTest( String name ) + { + super( name ); + final String baseDirProp = System.getProperty( "test.basedir" ); + String packagePath = getClass().getName(); + int idx = packagePath.lastIndexOf('.'); + packagePath = packagePath.substring(0, idx); + packagePath = packagePath.replace('.', File.separatorChar); + m_testBaseDir = new File( baseDirProp, packagePath ).getAbsoluteFile(); + } + + /** + * Locates a test resource. + */ + protected File getTestResource( final String name ) + { + return new File( m_testBaseDir, name ); + } + + /** + * Asserts that an exception contains the expected message. + * + * TODO - should take the expected exception, rather than the message, + * to check the entire cause chain. + */ + protected void assertSameMessage( final String message, final Throwable throwable ) + { + assertEquals( message, throwable.getMessage() ); + } + + /** + * Compares 2 objects for equality, nulls are equal. Used by the test + * classes' equals() methods. + */ + public static boolean equals( final Object o1, final Object o2 ) + { + if( o1 == null && o2 == null ) + { + return true; + } + if( o1 == null || o2 == null ) + { + return false; + } + return o1.equals( o2 ); + } + +} diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java index 378c19dde..fd4248301 100644 --- a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java +++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java @@ -28,6 +28,8 @@ import org.apache.myrmidon.components.configurer.DefaultConfigurer; import org.apache.myrmidon.components.converter.DefaultConverterRegistry; import org.apache.myrmidon.components.converter.DefaultMasterConverter; import org.apache.myrmidon.components.deployer.DefaultDeployer; +import org.apache.myrmidon.components.deployer.DefaultClassLoaderManager; +import org.apache.myrmidon.components.deployer.ClassLoaderManager; import org.apache.myrmidon.components.extensions.DefaultExtensionManager; import org.apache.myrmidon.components.role.DefaultRoleManager; import org.apache.myrmidon.components.type.DefaultTypeManager; @@ -41,6 +43,7 @@ import org.apache.myrmidon.interfaces.type.TypeManager; import org.apache.myrmidon.interfaces.type.TypeException; import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; import org.apache.myrmidon.converter.Converter; +import org.apache.myrmidon.AbstractMyrmidonTest; /** * A base class for tests for the default components. @@ -48,7 +51,7 @@ import org.apache.myrmidon.converter.Converter; * @author Adam Murdoch */ public abstract class AbstractComponentTest - extends TestCase + extends AbstractMyrmidonTest { private DefaultComponentManager m_componentManager; private Logger m_logger; @@ -117,6 +120,11 @@ public abstract class AbstractComponentTest m_componentManager.put( Deployer.ROLE, component ); components.add( component ); + final DefaultClassLoaderManager classLoaderMgr = new DefaultClassLoaderManager(); + classLoaderMgr.setBaseClassLoader( getClass().getClassLoader() ); + m_componentManager.put( ClassLoaderManager.ROLE, classLoaderMgr ); + components.add( classLoaderMgr ); + component = new DefaultExtensionManager(); m_componentManager.put( ExtensionManager.ROLE, component ); components.add( component ); @@ -162,32 +170,4 @@ public abstract class AbstractComponentTest factory.addNameClassMapping( converterClass.getName(), converterClass.getName() ); getTypeManager().registerType( Converter.class, converterClass.getName(), factory ); } - - /** - * Asserts that an exception contains the expected message. - * - * TODO - should take the expected exception, rather than the message, - * to check the entire cause chain. - */ - protected void assertSameMessage( final String message, final Throwable throwable ) - { - assertEquals( message, throwable.getMessage() ); - } - - /** - * Compares 2 objects for equality, nulls are equal. Used by the test - * classes' equals() methods. - */ - public static boolean equals( final Object o1, final Object o2 ) - { - if( o1 == null && o2 == null ) - { - return true; - } - if( o1 == null || o2 == null ) - { - return false; - } - return o1.equals( o2 ); - } } diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java index 010cbb021..81d17279a 100644 --- a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java +++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java @@ -16,6 +16,11 @@ import org.apache.myrmidon.interfaces.deployer.TypeDefinition; import org.apache.myrmidon.interfaces.deployer.TypeDeployer; import org.apache.myrmidon.interfaces.role.RoleManager; import org.apache.myrmidon.interfaces.type.TypeFactory; +import org.apache.myrmidon.interfaces.type.TypeManager; +import org.apache.myrmidon.interfaces.type.TypeException; +import org.apache.myrmidon.converter.ConverterException; +import org.apache.myrmidon.converter.Converter; +import java.io.File; /** * Test cases for the default deployer. @@ -25,7 +30,12 @@ import org.apache.myrmidon.interfaces.type.TypeFactory; public class DefaultDeployerTest extends AbstractComponentTest { + private static final String TEST_TYPE1_NAME = "test-type1"; + private static final String DATA_TYPE_ROLE = "data-type"; + private Deployer m_deployer; + private RoleManager m_roleManager; + private MasterConverter m_converter; public DefaultDeployerTest( final String name ) { @@ -40,6 +50,12 @@ public class DefaultDeployerTest { super.setUp(); m_deployer = (Deployer)getComponentManager().lookup( Deployer.ROLE ); + m_converter = (MasterConverter)getComponentManager().lookup( MasterConverter.ROLE ); + + // Add some core roles + m_roleManager = (RoleManager)getComponentManager().lookup( RoleManager.ROLE ); + m_roleManager.addNameRoleMapping( DATA_TYPE_ROLE, DataType.ROLE ); + m_roleManager.addNameRoleMapping( "converter", Converter.ROLE ); } /** @@ -47,27 +63,26 @@ public class DefaultDeployerTest */ public void testSingleType() throws Exception { - final String roleName = "data-type"; - final String typeName = "test-type1"; + final String typeName = TEST_TYPE1_NAME; final String classname = TestType1.class.getName(); // Determine the shorthand for the DataType role - final RoleManager roleManager = (RoleManager)getComponentManager().lookup( RoleManager.ROLE ); - roleManager.addNameRoleMapping( roleName, DataType.ROLE ); // Create the type definition - final TypeDefinition typeDef = new TypeDefinition( typeName, roleName, classname ); + final TypeDefinition typeDef = new TypeDefinition( typeName, DATA_TYPE_ROLE, classname ); - // Deploy the type final ClassLoader classLoader = getClass().getClassLoader(); final TypeDeployer typeDeployer = m_deployer.createDeployer( classLoader ); + + // Make sure the test types have not been deployed + assertTypesNotRegistered( ); + + // Deploy the type typeDeployer.deployType( typeDef ); - // Create an instance + // Check the type has been registered final TypeFactory typeFactory = getTypeManager().getFactory( DataType.class ); final Object result = typeFactory.create( typeName ); - - // Check the type assertTrue( result instanceof TestType1 ); } @@ -84,16 +99,99 @@ public class DefaultDeployerTest final ConverterDefinition typeDef = new ConverterDefinition( classname, source, destClass ); - // Deploy the type final ClassLoader classLoader = getClass().getClassLoader(); final TypeDeployer typeDeployer = m_deployer.createDeployer( classLoader ); + + // Make sure the test types have not been deployed + assertTypesNotRegistered( ); + + // Deploy the type typeDeployer.deployType( typeDef ); // Try to convert from string to test type - final MasterConverter converter = (MasterConverter)getComponentManager().lookup( MasterConverter.ROLE ); - final Object result = converter.convert( TestType1.class, "some-string", null ); - - // Check the type + final Object result = m_converter.convert( TestType1.class, "some-string", null ); assertTrue( result instanceof TestType1 ); } + + /** + * Tests deployment of types from a typelib descriptor. + */ + public void testLibDescriptor() throws Exception + { + final File typelib = getTestResource( "test.atl" ); + assertTrue( "File " + typelib + " does not exist", typelib.exists() ); + + final TypeDeployer typeDeployer = m_deployer.createDeployer( typelib ); + + // Make sure the test types have not been deployed + assertTypesNotRegistered(); + + // Deploy all the types from the descriptor + typeDeployer.deployAll(); + + // Make sure the test types have been deployed + assertTypesRegistered(); + } + + /** + * Ensures that the test types have not ben deployed. + */ + private void assertTypesNotRegistered() throws Exception + { + // Check the data-type + TypeFactory typeFactory = getTypeManager().getFactory( DataType.class ); + try + { + typeFactory.create( TEST_TYPE1_NAME ); + fail(); + } + catch( TypeException e ) + { + // TODO - check error message + } + + // Check the custom role implementation + typeFactory = getTypeManager().getFactory( TestRole1.class ); + try + { + typeFactory.create( TEST_TYPE1_NAME ); + fail(); + } + catch( TypeException e ) + { + // TODO - check error message + } + + // Check the converter + try + { + m_converter.convert( TestType1.class, "some string", null ); + fail(); + } + catch( ConverterException e ) + { + // TODO - check error message + } + } + + /** + * Ensures the types from the test typelib descriptor have been correctly + * deployed. + */ + private void assertTypesRegistered( ) throws Exception + { + // Check the data-type + TypeFactory typeFactory = getTypeManager().getFactory( DataType.class ); + Object object = typeFactory.create( TEST_TYPE1_NAME ); + assertTrue( object instanceof TestType1 ); + + // Check the custom role implementation + typeFactory = getTypeManager().getFactory( TestRole1.class ); + object = typeFactory.create( TEST_TYPE1_NAME ); + assertTrue( object instanceof TestType1 ); + + // Check the converter + object = m_converter.convert( TestType1.class, "some string", null ); + assertTrue( object instanceof TestType1 ); + } } diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/TestRole1.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/TestRole1.java new file mode 100644 index 000000000..93dc94f6d --- /dev/null +++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/TestRole1.java @@ -0,0 +1,18 @@ +/* + * Copyright (C) The Apache Software Foundation. All rights reserved. + * + * This software is published under the terms of the Apache Software License + * version 1.1, a copy of which has been included with this distribution in + * the LICENSE.txt file. + */ +package org.apache.myrmidon.components.deployer; + +/** + * A test role interface. + * + * @author Adam Murdoch + */ +public interface TestRole1 +{ + String ROLE = TestRole1.class.getName(); +} diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/TestType1.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/TestType1.java index a0c6e3109..444ea9e62 100644 --- a/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/TestType1.java +++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/TestType1.java @@ -15,6 +15,6 @@ import org.apache.myrmidon.framework.DataType; * @author Adam Murdoch */ public class TestType1 - implements DataType + implements DataType, TestRole1 { } diff --git a/proposal/myrmidon/src/testcases/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java b/proposal/myrmidon/src/testcases/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java index 6b3f8fad9..28d583555 100644 --- a/proposal/myrmidon/src/testcases/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java +++ b/proposal/myrmidon/src/testcases/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java @@ -10,15 +10,16 @@ package org.apache.myrmidon.interfaces.type; import java.io.File; import java.net.URL; import junit.framework.TestCase; +import org.apache.myrmidon.AbstractMyrmidonTest; /** - * These are unit tests that test the basic operation of TypeFactorys. + * These are unit tests that test the basic operation of TypeFactories. * * @author Peter Donald * @version $Revision$ $Date$ */ public class TypeFactoryTest - extends TestCase + extends AbstractMyrmidonTest { private final static String TYPE_NAME1 = "my-type1"; private final static String TYPE_NAME2 = "my-type2"; @@ -27,9 +28,6 @@ public class TypeFactoryTest private final static String TYPE_CLASSNAME1 = TYPE_CLASS1.getName(); private final static String TYPE_CLASSNAME2 = TYPE_CLASS2.getName(); - private final static String TYPE_JAR = - "src/testcases/org/apache/myrmidon/interfaces/type/types.jar".replace( '/', File.separatorChar ); - public TypeFactoryTest( final String name ) { super( name ); @@ -64,11 +62,10 @@ public class TypeFactoryTest public void testReloadingTypeFactory() throws Exception { - final File file = new File( TYPE_JAR ); - assertTrue( "Support Jar exists", file.exists() ); + final File file = getTestResource( "types.jar" ); + assertTrue( "Support Jar " + file + " exists", file.exists() ); final URL[] classpath = new URL[]{file.toURL()}; - final ClassLoader classLoader = getClass().getClassLoader(); final ReloadingTypeFactory factory = new ReloadingTypeFactory( classpath, null ); factory.addNameClassMapping( TYPE_NAME1, TYPE_CLASSNAME1 );