Browse Source

Changes to DefaultDeployer:

* Got rid of <converters> element from antlib descriptor.  Converters are
  now defined in the <types> element.

* Moved (most of) the role-specific knowledge from Deployment back to DefaultDeployer.

* Split out ClassLoader management into DefaultClassLoaderManager.  This is
  living in the deployer package for now.

* Tidied-up the component set-up and clean-up in DefaultEmbeddor.  Added
  the ClassLoaderManager component.

* Added test for TypeDeployer.deployAll().

Changes to unit tests:

* Added AbstractMyrmidonTest, which takes care of locating test resources.

* Changed the VFS, type factory, and deployer tests to use AbstractMyrmidonTest.


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271271 13f79535-47bb-0310-9956-ffa450edef68
master
adammurdoch 23 years ago
parent
commit
2e6e170fb3
32 changed files with 1054 additions and 630 deletions
  1. +25
    -11
      proposal/myrmidon/build.xml
  2. +18
    -0
      proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/deployer/ant-descriptor.xml
  3. +4
    -0
      proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/deployer/ant-roles.xml
  4. +28
    -0
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ClassLoaderManager.java
  5. +209
    -0
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultClassLoaderManager.java
  6. +148
    -126
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java
  7. +18
    -145
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java
  8. +1
    -0
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Resources.properties
  9. +36
    -0
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDefinition.java
  10. +99
    -180
      proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java
  11. +3
    -5
      proposal/myrmidon/src/manifest/ant1-ant-descriptor.xml
  12. +1
    -5
      proposal/myrmidon/src/manifest/core-ant-descriptor.template
  13. +8
    -14
      proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractFileSystemTest.java
  14. +1
    -1
      proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractWritableFileSystemTest.java
  15. +6
    -10
      proposal/myrmidon/src/test/org/apache/aut/vfs/LocalFileSystemTest.java
  16. +1
    -2
      proposal/myrmidon/src/test/org/apache/aut/vfs/ZipFileSystemTest.java
  17. +71
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java
  18. +9
    -29
      proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java
  19. +112
    -14
      proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java
  20. +18
    -0
      proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/TestRole1.java
  21. +1
    -1
      proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/TestType1.java
  22. +5
    -8
      proposal/myrmidon/src/test/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java
  23. +8
    -14
      proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractFileSystemTest.java
  24. +1
    -1
      proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractWritableFileSystemTest.java
  25. +6
    -10
      proposal/myrmidon/src/testcases/org/apache/aut/vfs/LocalFileSystemTest.java
  26. +1
    -2
      proposal/myrmidon/src/testcases/org/apache/aut/vfs/ZipFileSystemTest.java
  27. +71
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/AbstractMyrmidonTest.java
  28. +9
    -29
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java
  29. +112
    -14
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java
  30. +18
    -0
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/TestRole1.java
  31. +1
    -1
      proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/TestType1.java
  32. +5
    -8
      proposal/myrmidon/src/testcases/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java

+ 25
- 11
proposal/myrmidon/build.xml View File

@@ -416,20 +416,35 @@ Legal:
<classpath refid="project.class.path"/>
</javac>

<property name="test.local.dir" location="${test.working.dir}/localfs"/>
<property name="test.zip.file" location="${test.working.dir}/zipfs/test.zip"/>

<!-- Prepare test files -->
<delete dir="${test.working.dir}"/>
<copy todir="${test.local.dir}/read-tests">
<fileset dir="etc/testcases/org/apache/aut/vfs/basedir"/>
<copy todir="${test.working.dir}">
<fileset dir="etc/testcases"/>
</copy>
<mkdir dir="${test.local.dir}/read-tests/emptydir"/>
<mkdir dir="${test.working.dir}/zipfs"/>
<zip zipfile="${test.zip.file}">
<zipfileset dir="${test.local.dir}/read-tests" prefix="/basedir"/>

<!-- Prepare the VFS tests -->
<property name="test.vfs.dir" location="${test.working.dir}/org/apache/aut/vfs"/>
<mkdir dir="${test.vfs.dir}/basedir/emptydir"/>
<zip zipfile="${test.vfs.dir}/test.zip">
<fileset dir="${test.vfs.dir}" includes="basedir/**"/>
</zip>

<!-- Prepare deployer tests -->
<property name="test.deployer.dir"
value="${test.working.dir}/org/apache/myrmidon/components/deployer"/>
<mkdir dir="${test.deployer.dir}"/>
<jar jarfile="${test.deployer.dir}/test.atl">
<zipfileset dir="etc/testcases/org/apache/myrmidon/components/deployer"
prefix="META-INF"
includes="*.xml"/>
</jar>

<!-- Prepare type factory tests -->
<mkdir dir="${test.working.dir}/org/apache/myrmidon/interfaces/type"/>
<jar jarfile="${test.working.dir}/org/apache/myrmidon/interfaces/type/types.jar">
<fileset dir="${test.classes}" includes="org/apache/myrmidon/interfaces/type/MyType1.class"/>
</jar>

<junit printsummary="on"
fork="true">
<formatter type="brief" usefile="false"/>
@@ -437,8 +452,7 @@ Legal:
<classpath location="${test.classes}"/>

<!-- Pass config to the tests -->
<sysproperty key="test.local.dir" value="${test.local.dir}"/>
<sysproperty key="test.zip.file" value="${test.zip.file}"/>
<sysproperty key="test.basedir" value="${test.working.dir}"/>
<sysproperty key="test.smb.uri" value="smb://${vfs.user}:${vfs.password}@${vfs.host}/${vfs.user}/vfs"/>
<sysproperty key="test.ftp.uri" value="ftp://${vfs.user}:${vfs.password}@${vfs.host}/home/${vfs.user}/vfs"/>



+ 18
- 0
proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/deployer/ant-descriptor.xml View File

@@ -0,0 +1,18 @@
<antlib>

<types>
<!-- Register a data-type -->
<data-type name="test-type1"
classname="org.apache.myrmidon.components.deployer.TestType1"/>

<!-- Register a custom role implementation -->
<test-role1 name="test-type1"
classname="org.apache.myrmidon.components.deployer.TestType1"/>

<!-- Register a converter -->
<converter classname="org.apache.myrmidon.components.deployer.TestConverter1"
source="java.lang.String"
destination="org.apache.myrmidon.components.deployer.TestType1"/>
</types>

</antlib>

+ 4
- 0
proposal/myrmidon/etc/testcases/org/apache/myrmidon/components/deployer/ant-roles.xml View File

@@ -0,0 +1,4 @@
<roles>
<!-- A custom role -->
<role shorthand="test-role1" name="org.apache.myrmidon.components.deployer.TestRole1"/>
</roles>

+ 28
- 0
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ClassLoaderManager.java View File

@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
public interface ClassLoaderManager
extends Component
{
String ROLE = ClassLoaderManager.class.getName();

/**
* Builds the ClassLoader for a Jar file.
*/
ClassLoader createClassLoader( File jar ) throws DeploymentException;
}

+ 209
- 0
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultClassLoaderManager.java View File

@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
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 );
}
}
}

+ 148
- 126
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java View File

@@ -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 <a href="mailto:peter@apache.org">Peter Donald</a>
* @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;
}

}

+ 18
- 145
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java View File

@@ -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;
}

}

+ 1
- 0
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Resources.properties View File

@@ -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}.

+ 36
- 0
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDefinition.java View File

@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
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;
}
}

+ 99
- 180
proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java View File

@@ -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.
*/


+ 3
- 5
proposal/myrmidon/src/manifest/ant1-ant-descriptor.xml View File

@@ -5,13 +5,11 @@

<data-type name="path" classname="org.apache.tools.ant.types.Path" />
<task name="path" classname="org.apache.myrmidon.framework.TypeInstanceTask" />
</types>

<converters>
<converter
classname="org.apache.tools.ant.types.converters.StringToPathConverter"
source="java.lang.String"
destination="org.apache.tools.ant.types.Path"
/>
</converters>
/>
</types>

</ant-lib>

+ 1
- 5
proposal/myrmidon/src/manifest/core-ant-descriptor.template View File

@@ -18,10 +18,6 @@
</XDtClass:ifHasClassTag>
</XDtClass:forAllClasses>

</types>

<converters>

<XDtClass:forAllClasses type="org.apache.myrmidon.converter.Converter">
<XDtClass:ifHasClassTag tagName="ant:converter">
<converter classname="<XDtClass:fullClassName/>"
@@ -30,6 +26,6 @@
</XDtClass:ifHasClassTag>
</XDtClass:forAllClasses>

</converters>
</types>

</ant-lib>

+ 8
- 14
proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractFileSystemTest.java View File

@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
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.


+ 1
- 1
proposal/myrmidon/src/test/org/apache/aut/vfs/AbstractWritableFileSystemTest.java View File

@@ -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.


+ 6
- 10
proposal/myrmidon/src/test/org/apache/aut/vfs/LocalFileSystemTest.java View File

@@ -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();
}

/**


+ 1
- 2
proposal/myrmidon/src/test/org/apache/aut/vfs/ZipFileSystemTest.java View File

@@ -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;
}


+ 71
- 0
proposal/myrmidon/src/test/org/apache/myrmidon/AbstractMyrmidonTest.java View File

@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
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 );
}

}

+ 9
- 29
proposal/myrmidon/src/test/org/apache/myrmidon/components/AbstractComponentTest.java View File

@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
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 );
}
}

+ 112
- 14
proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java View File

@@ -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 );
}
}

+ 18
- 0
proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/TestRole1.java View File

@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
public interface TestRole1
{
String ROLE = TestRole1.class.getName();
}

+ 1
- 1
proposal/myrmidon/src/test/org/apache/myrmidon/components/deployer/TestType1.java View File

@@ -15,6 +15,6 @@ import org.apache.myrmidon.framework.DataType;
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
public class TestType1
implements DataType
implements DataType, TestRole1
{
}

+ 5
- 8
proposal/myrmidon/src/test/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java View File

@@ -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 <a href="mailto:peter@apache.org">Peter Donald</a>
* @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 );



+ 8
- 14
proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractFileSystemTest.java View File

@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
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.


+ 1
- 1
proposal/myrmidon/src/testcases/org/apache/aut/vfs/AbstractWritableFileSystemTest.java View File

@@ -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.


+ 6
- 10
proposal/myrmidon/src/testcases/org/apache/aut/vfs/LocalFileSystemTest.java View File

@@ -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();
}

/**


+ 1
- 2
proposal/myrmidon/src/testcases/org/apache/aut/vfs/ZipFileSystemTest.java View File

@@ -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;
}


+ 71
- 0
proposal/myrmidon/src/testcases/org/apache/myrmidon/AbstractMyrmidonTest.java View File

@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
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 );
}

}

+ 9
- 29
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/AbstractComponentTest.java View File

@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
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 );
}
}

+ 112
- 14
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/DefaultDeployerTest.java View File

@@ -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 );
}
}

+ 18
- 0
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/TestRole1.java View File

@@ -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 <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
public interface TestRole1
{
String ROLE = TestRole1.class.getName();
}

+ 1
- 1
proposal/myrmidon/src/testcases/org/apache/myrmidon/components/deployer/TestType1.java View File

@@ -15,6 +15,6 @@ import org.apache.myrmidon.framework.DataType;
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
public class TestType1
implements DataType
implements DataType, TestRole1
{
}

+ 5
- 8
proposal/myrmidon/src/testcases/org/apache/myrmidon/interfaces/type/TypeFactoryTest.java View File

@@ -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 <a href="mailto:peter@apache.org">Peter Donald</a>
* @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 );



Loading…
Cancel
Save