* 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-ffa450edef68master
@@ -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"/> | |||
@@ -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> |
@@ -0,0 +1,4 @@ | |||
<roles> | |||
<!-- A custom role --> | |||
<role shorthand="test-role1" name="org.apache.myrmidon.components.deployer.TestRole1"/> | |||
</roles> |
@@ -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; | |||
} |
@@ -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 ); | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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}. |
@@ -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; | |||
} | |||
} |
@@ -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. | |||
*/ | |||
@@ -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> |
@@ -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> |
@@ -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. | |||
@@ -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. | |||
@@ -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(); | |||
} | |||
/** | |||
@@ -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; | |||
} | |||
@@ -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 ); | |||
} | |||
} |
@@ -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 ); | |||
} | |||
} |
@@ -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 ); | |||
} | |||
} |
@@ -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(); | |||
} |
@@ -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 | |||
{ | |||
} |
@@ -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 ); | |||
@@ -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. | |||
@@ -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. | |||
@@ -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(); | |||
} | |||
/** | |||
@@ -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; | |||
} | |||
@@ -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 ); | |||
} | |||
} |
@@ -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 ); | |||
} | |||
} |
@@ -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 ); | |||
} | |||
} |
@@ -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(); | |||
} |
@@ -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 | |||
{ | |||
} |
@@ -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 ); | |||