Browse Source

Get this compiling again.

Note this wont run until we break out container-api.jar and place in lib/ so that the runtime/ant1compat classes will work at runtime. At the moment they will compile ma no run.


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272374 13f79535-47bb-0310-9956-ffa450edef68
master
Peter Donald 23 years ago
parent
commit
2943e6c208
100 changed files with 1 additions and 12379 deletions
  1. +1
    -1
      proposal/myrmidon/ant1compat.xml
  2. +0
    -34
      proposal/myrmidon/build.xml
  3. +0
    -179
      proposal/myrmidon/src/java/org/apache/myrmidon/components/aspect/DefaultAspectManager.java
  4. +0
    -2
      proposal/myrmidon/src/java/org/apache/myrmidon/components/aspect/Resources.properties
  5. +0
    -227
      proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/ATIProjectBuilder.java
  6. +0
    -247
      proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/ConvertingProjectBuilder.java
  7. +0
    -229
      proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/DefaultProject.java
  8. +0
    -553
      proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/DefaultProjectBuilder.java
  9. +0
    -60
      proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/ReactorPIHandler.java
  10. +0
    -37
      proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/Resources.properties
  11. +0
    -25
      proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/StopParsingException.java
  12. +0
    -97
      proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/TransformingProjectBuilder.java
  13. +0
    -151
      proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/ant1convert.xsl
  14. +0
    -305
      proposal/myrmidon/src/java/org/apache/myrmidon/components/classloader/DefaultClassLoaderManager.java
  15. +0
    -141
      proposal/myrmidon/src/java/org/apache/myrmidon/components/classloader/MultiParentURLClassLoader.java
  16. +0
    -5
      proposal/myrmidon/src/java/org/apache/myrmidon/components/classloader/Resources.properties
  17. +0
    -567
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ClassicConfigurer.java
  18. +0
    -57
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ConfigurationState.java
  19. +0
    -645
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java
  20. +0
    -395
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java
  21. +0
    -139
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultPropertyConfigurer.java
  22. +0
    -19
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/NoSuchPropertyException.java
  23. +0
    -75
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java
  24. +0
    -36
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/PropertyConfigurer.java
  25. +0
    -39
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ReportableConfigurationException.java
  26. +0
    -17
      proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/Resources.properties
  27. +0
    -70
      proposal/myrmidon/src/java/org/apache/myrmidon/components/converter/DefaultMasterConverter.java
  28. +0
    -289
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java
  29. +0
    -363
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java
  30. +0
    -27
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DescriptorBuilder.java
  31. +0
    -27
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Resources.properties
  32. +0
    -36
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDefinition.java
  33. +0
    -45
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDescriptor.java
  34. +0
    -70
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDescriptorBuilder.java
  35. +0
    -56
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDefinition.java
  36. +0
    -39
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDescriptor.java
  37. +0
    -72
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDescriptorBuilder.java
  38. +0
    -40
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypeDescriptor.java
  39. +0
    -96
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypeDescriptorBuilder.java
  40. +0
    -32
      proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypelibDescriptor.java
  41. +0
    -454
      proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java
  42. +0
    -6
      proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/Resources.properties
  43. +0
    -337
      proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/AspectAwareExecutor.java
  44. +0
    -141
      proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/DefaultExecutor.java
  45. +0
    -81
      proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/PrintingExecutor.java
  46. +0
    -11
      proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/Resources.properties
  47. +0
    -162
      proposal/myrmidon/src/java/org/apache/myrmidon/components/extensions/DefaultExtensionManager.java
  48. +0
    -49
      proposal/myrmidon/src/java/org/apache/myrmidon/components/property/ClassicPropertyResolver.java
  49. +0
    -290
      proposal/myrmidon/src/java/org/apache/myrmidon/components/property/DefaultPropertyResolver.java
  50. +0
    -3
      proposal/myrmidon/src/java/org/apache/myrmidon/components/property/Resources.properties
  51. +0
    -163
      proposal/myrmidon/src/java/org/apache/myrmidon/components/role/DefaultRoleManager.java
  52. +0
    -3
      proposal/myrmidon/src/java/org/apache/myrmidon/components/role/Resources.properties
  53. +0
    -248
      proposal/myrmidon/src/java/org/apache/myrmidon/components/service/InstantiatingServiceManager.java
  54. +0
    -3
      proposal/myrmidon/src/java/org/apache/myrmidon/components/service/Resources.properties
  55. +0
    -268
      proposal/myrmidon/src/java/org/apache/myrmidon/components/store/DefaultPropertyStore.java
  56. +0
    -5
      proposal/myrmidon/src/java/org/apache/myrmidon/components/store/Resources.properties
  57. +0
    -139
      proposal/myrmidon/src/java/org/apache/myrmidon/components/type/DefaultTypeManager.java
  58. +0
    -124
      proposal/myrmidon/src/java/org/apache/myrmidon/components/type/MultiSourceTypeFactory.java
  59. +0
    -9
      proposal/myrmidon/src/java/org/apache/myrmidon/components/type/Resources.properties
  60. +0
    -61
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultExecutionFrame.java
  61. +0
    -382
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java
  62. +0
    -437
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java
  63. +0
    -62
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/ProjectEntry.java
  64. +0
    -224
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/ProjectListenerSupport.java
  65. +0
    -19
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/Resources.properties
  66. +0
    -85
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/RoutingLogger.java
  67. +0
    -34
      proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/TargetState.java
  68. +0
    -167
      proposal/myrmidon/src/java/org/apache/myrmidon/frontends/AbstractLogger.java
  69. +0
    -124
      proposal/myrmidon/src/java/org/apache/myrmidon/frontends/BasicLogger.java
  70. +0
    -477
      proposal/myrmidon/src/java/org/apache/myrmidon/frontends/CLIMain.java
  71. +0
    -420
      proposal/myrmidon/src/java/org/apache/myrmidon/frontends/EmbeddedAnt.java
  72. +0
    -35
      proposal/myrmidon/src/java/org/apache/myrmidon/frontends/Resources.properties
  73. +0
    -56
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/ComponentException.java
  74. +0
    -59
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/aspect/AspectManager.java
  75. +0
    -33
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/builder/ProjectBuilder.java
  76. +0
    -41
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/builder/ProjectException.java
  77. +0
    -41
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/classloader/ClassLoaderException.java
  78. +0
    -55
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/classloader/ClassLoaderManager.java
  79. +0
    -98
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/configurer/Configurer.java
  80. +0
    -29
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/converter/ConverterRegistry.java
  81. +0
    -54
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/deployer/ConverterDefinition.java
  82. +0
    -55
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/deployer/Deployer.java
  83. +0
    -41
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/deployer/DeploymentException.java
  84. +0
    -60
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/deployer/TypeDefinition.java
  85. +0
    -54
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/deployer/TypeDeployer.java
  86. +0
    -65
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/embeddor/Embeddor.java
  87. +0
    -23
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionContainer.java
  88. +0
    -46
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionFrame.java
  89. +0
    -33
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/Executor.java
  90. +0
    -31
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/extensions/ExtensionManager.java
  91. +0
    -356
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/DefaultNameValidator.java
  92. +0
    -46
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/Dependency.java
  93. +0
    -26
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/NameValidator.java
  94. +0
    -100
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/Project.java
  95. +0
    -6
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/Resources.properties
  96. +0
    -65
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/Target.java
  97. +0
    -93
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/TypeLib.java
  98. +0
    -119
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/MapPropertyStore.java
  99. +0
    -41
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/PropertyResolver.java
  100. +0
    -86
      proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/PropertyStore.java

+ 1
- 1
proposal/myrmidon/ant1compat.xml View File

@@ -14,7 +14,7 @@
<path id="project.class.path"> <path id="project.class.path">
<pathelement location="build/classes"/> <pathelement location="build/classes"/>
<fileset dir="lib"> <fileset dir="lib">
<include name="*.jar"/>
<include name="**/*.jar"/>
</fileset> </fileset>
</path> </path>




+ 0
- 34
proposal/myrmidon/build.xml View File

@@ -251,9 +251,7 @@ Legal:
<src path="${build.src}" /> <src path="${build.src}" />
--> -->


<patternset refid="myrmidon-launcher.include"/>
<patternset refid="myrmidon-framework.include"/> <patternset refid="myrmidon-framework.include"/>
<patternset refid="myrmidon-container.include"/>
<patternset refid="ant1.todo.include"/> <patternset refid="ant1.todo.include"/>
<patternset refid="selftest.include"/> <patternset refid="selftest.include"/>
<patternset refid="selftest-extension1.include"/> <patternset refid="selftest-extension1.include"/>
@@ -269,22 +267,12 @@ Legal:
</target> </target>


<target name="setup-patterns" depends="check_for_optional_packages"> <target name="setup-patterns" depends="check_for_optional_packages">
<patternset id="myrmidon-launcher.include">
<include name="org/apache/myrmidon/launcher/**" />
</patternset>


<patternset id="myrmidon-framework.include"> <patternset id="myrmidon-framework.include">
<include name="org/apache/myrmidon/interfaces/**" /> <include name="org/apache/myrmidon/interfaces/**" />
<include name="org/apache/myrmidon/framework/**" /> <include name="org/apache/myrmidon/framework/**" />
</patternset> </patternset>


<patternset id="myrmidon-container.include">
<include name="org/apache/myrmidon/components/**" />
<include name="org/apache/myrmidon/frontends/**" />
<include name="org/apache/myrmidon/*" />
<exclude name="**/TransformingProjectBuilder.java" unless="trax.present"/>
</patternset>

<property name="ant.package" value="org/apache/tools/todo"/> <property name="ant.package" value="org/apache/tools/todo"/>
<property name="taskdefs.package" value="${ant.package}/taskdefs"/> <property name="taskdefs.package" value="${ant.package}/taskdefs"/>
<property name="antlib.package" value="org/apache/antlib"/> <property name="antlib.package" value="org/apache/antlib"/>
@@ -390,14 +378,6 @@ Legal:
</fileset> </fileset>
</antlib-descriptor> </antlib-descriptor>


<antlib-descriptor libName="container"
destdir="${gen.dir}"
classpathref="project.class.path">
<fileset dir="${java.dir}">
<patternset refid="myrmidon-container.include"/>
</fileset>
</antlib-descriptor>

<antlib-descriptor libName="selftest" <antlib-descriptor libName="selftest"
destdir="${gen.dir}" destdir="${gen.dir}"
classpathref="project.class.path"> classpathref="project.class.path">
@@ -422,20 +402,6 @@ Legal:
<mkdir dir="${build.lib}"/> <mkdir dir="${build.lib}"/>
<mkdir dir="${build.ext}"/> <mkdir dir="${build.ext}"/>


<jar jarfile="${build.bin}/myrmidon-launcher.jar"
basedir="${build.classes}"
manifest="${manifest.dir}/myrmidon-launcher.mf">
<patternset refid="myrmidon-launcher.include"/>
</jar>

<antlib-jar jarfile="${build.bin}/lib/myrmidon-container.jar"
basedir="${build.classes}"
manifest="${manifest.dir}/myrmidon-container.mf"
rolesDescriptor="${gen.dir}/container-ant-roles.xml"
descriptor="${gen.dir}/container-ant-descriptor.xml" >
<patternset refid="myrmidon-container.include"/>
</antlib-jar>

<antlib-jar jarfile="${build.lib}/myrmidon-framework.jar" <antlib-jar jarfile="${build.lib}/myrmidon-framework.jar"
basedir="${build.classes}" basedir="${build.classes}"
manifest="${manifest.dir}/myrmidon-api.mf" manifest="${manifest.dir}/myrmidon-api.mf"


+ 0
- 179
proposal/myrmidon/src/java/org/apache/myrmidon/components/aspect/DefaultAspectManager.java View File

@@ -1,179 +0,0 @@
/*
* 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.aspect;

import java.util.HashMap;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.myrmidon.api.Task;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.aspects.AspectHandler;
import org.apache.myrmidon.aspects.NoopAspectHandler;
import org.apache.myrmidon.interfaces.aspect.AspectManager;

/**
* Manage and propogate Aspects.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class DefaultAspectManager
implements AspectManager, Initializable
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultAspectManager.class );

private HashMap m_aspectMap = new HashMap();
private AspectHandler[] m_aspects = new AspectHandler[ 0 ];
private String[] m_names = new String[ 0 ];

public void initialize()
throws Exception
{
///UGLY HACK!!!!
addAspectHandler( "ant", new NoopAspectHandler() );
addAspectHandler( "doc", new NoopAspectHandler() );
}

public synchronized void addAspectHandler( final String name, final AspectHandler handler )
throws TaskException
{
m_aspectMap.put( name, handler );
rebuildArrays();
}

public synchronized void removeAspectHandler( final String name )
throws TaskException
{
final AspectHandler entry = (AspectHandler)m_aspectMap.remove( name );
if( null == entry )
{
final String message = REZ.getString( "no.aspect", name );
throw new TaskException( message );
}

rebuildArrays();
}

private void rebuildArrays()
{
m_aspects = (AspectHandler[])m_aspectMap.values().toArray( m_aspects );
m_names = (String[])m_aspectMap.keySet().toArray( m_names );
}

public String[] getNames()
{
return m_names;
}

public void dispatchAspectSettings( final String name,
final Parameters parameters,
final Configuration[] elements )
throws TaskException
{
final AspectHandler handler = (AspectHandler)m_aspectMap.get( name );
if( null == handler )
{
final String message = REZ.getString( "no.aspect", name );
throw new TaskException( message );
}

handler.aspectSettings( parameters, elements );
}

public Configuration preCreate( final Configuration configuration )
throws TaskException
{
Configuration model = configuration;

final AspectHandler[] aspects = m_aspects;
for( int i = 0; i < aspects.length; i++ )
{
model = aspects[ i ].preCreate( model );
}

return model;
}

public void aspectSettings( final Parameters parameters, final Configuration[] elements )
throws TaskException
{
final String message = REZ.getString( "no.settings" );
throw new UnsupportedOperationException( message );
}

public void postCreate( final Task task )
throws TaskException
{
final AspectHandler[] aspects = m_aspects;
for( int i = 0; i < aspects.length; i++ )
{
aspects[ i ].postCreate( task );
}
}

public void preLogEnabled( final Logger logger )
throws TaskException
{
final AspectHandler[] aspects = m_aspects;
for( int i = 0; i < aspects.length; i++ )
{
aspects[ i ].preLogEnabled( logger );
}
}

public void preConfigure( final Configuration taskModel )
throws TaskException
{
final AspectHandler[] aspects = m_aspects;
for( int i = 0; i < aspects.length; i++ )
{
aspects[ i ].preConfigure( taskModel );
}
}

public void preExecute()
throws TaskException
{
final AspectHandler[] aspects = m_aspects;
for( int i = 0; i < aspects.length; i++ )
{
aspects[ i ].preExecute();
}
}

public void preDestroy()
throws TaskException
{
final AspectHandler[] aspects = m_aspects;
for( int i = 0; i < aspects.length; i++ )
{
aspects[ i ].preDestroy();
}
}

public boolean error( final TaskException te )
throws TaskException
{
final AspectHandler[] aspects = m_aspects;
for( int i = 0; i < aspects.length; i++ )
{
final boolean isError = aspects[ i ].error( te );
if( isError )
{
return true;
}
}

return false;
}
}

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

@@ -1,2 +0,0 @@
no.aspect=No such aspect with name {0}.
no.settings=Can not provide Settings to AspectManager.

+ 0
- 227
proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/ATIProjectBuilder.java View File

@@ -1,227 +0,0 @@
/*
* 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.builder;

import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

/**
* Default implementation to construct project from a build file.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
* @ant.type type="project-builder" name="ati"
*/
public class ATIProjectBuilder
extends DefaultProjectBuilder
implements Parameterizable
{
private static final Resources REZ =
ResourceManager.getPackageResources( ATIProjectBuilder.class );

private Parameters m_parameters;

public void parameterize( final Parameters parameters )
{
m_parameters = parameters;
}

protected void process( final URL sourceID,
final SAXConfigurationHandler handler )
throws Exception
{
final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
final SAXParser saxParser = saxParserFactory.newSAXParser();
final XMLReader reader = saxParser.getXMLReader();
reader.setFeature( "http://xml.org/sax/features/validation", false );
reader.setErrorHandler( handler );

final ReactorPIHandler reactorHandler = new ReactorPIHandler();
reader.setContentHandler( reactorHandler );

try
{
reader.parse( sourceID.toString() );
}
catch( final StopParsingException spe )
{
//Ignore me
}

Transformer transformer = null;

final int size = reactorHandler.getPICount();
for( int i = 0; i < size; i++ )
{
final String target = reactorHandler.getTarget( i );
final String data = reactorHandler.getData( i );

if( target.equals( "xsl-param" ) )
{
handleParameter( data );
}
else if( target.equals( "xsl-params" ) )
{
handleParameters( data, sourceID );
}
else if( target.equals( "xsl-stylesheet" ) )
{
if( null != transformer )
{
final String message = REZ.getString( "ati.two.stylesheet.pis" );
throw new SAXException( message );
}

final TransformerFactory factory = TransformerFactory.newInstance();
final String stylesheet = getStylesheet( data, sourceID );
transformer = factory.newTransformer( new StreamSource( stylesheet ) );
}
}

if( null == transformer )
{
reader.setContentHandler( handler );
reader.parse( sourceID.toString() );
}
else
{
final String[] names = m_parameters.getNames();
for( int i = 0; i < names.length; i++ )
{
final String name = names[ i ];
final String value = m_parameters.getParameter( name );
transformer.setParameter( name, value );
}

final SAXResult result = new SAXResult( handler );
transformer.transform( new StreamSource( sourceID.toString() ), result );
//transformer.transform( new StreamSource( sourceID.toString() ),
//new StreamResult( System.out ) );
}
}

private void handleParameter( final String data )
throws SAXException
{
int index = data.indexOf( '\"' );
if( -1 == index )
{
final String message = REZ.getString( "ati.param.error" );
throw new SAXException( message );
}

index = data.indexOf( '\"', index + 1 );
if( -1 == index )
{
final String message = REZ.getString( "ati.param.error" );
throw new SAXException( message );
}

//split between two "attributes" occurs on index
final String[] name = parseAttribute( data.substring( 0, index + 1 ) );
final String[] value = parseAttribute( data.substring( index + 1 ).trim() );

if( !name[ 0 ].equals( "name" ) || !value[ 0 ].equals( "value" ) )
{
final String message = REZ.getString( "ati.param.error" );
throw new SAXException( message );
}

m_parameters.setParameter( name[ 1 ], value[ 1 ] );
}

private void handleParameters( final String data, final URL baseSource )
throws SAXException
{
final String[] params = parseAttribute( data );
if( !params[ 0 ].equals( "location" ) )
{
final String message = REZ.getString( "ati.params.error" );
throw new SAXException( message );
}

try
{
final Properties properties = new Properties();
final URL url = new URL( baseSource, params[ 1 ] );
final InputStream input = url.openStream();
properties.load( input );
final Parameters parameters = Parameters.fromProperties( properties );
m_parameters.merge( parameters );
}
catch( final Exception e )
{
final String message = REZ.getString( "ati.loading-params.error", params[ 1 ], e );
throw new SAXException( message );
}
}

private String getStylesheet( final String data, final URL baseSource )
throws SAXException
{
final String[] stylesheet = parseAttribute( data );
if( !stylesheet[ 0 ].equals( "href" ) )
{
final String message = REZ.getString( "ati.style.error" );
throw new SAXException( message );
}

try
{
return new URL( baseSource, stylesheet[ 1 ] ).toString();
}
catch( final Exception e )
{
final String message =
REZ.getString( "ati.loading-style.error", stylesheet[ 1 ], e );
throw new SAXException( message );
}
}

private String[] parseAttribute( final String data )
throws SAXException
{
//name="value"
int index = data.indexOf( '=' );
if( -1 == index )
{
final String message = REZ.getString( "ati.attribue-expected.error", data );
throw new SAXException( message );
}

final int size = data.length();
if( '\"' != data.charAt( index + 1 ) ||
'\"' != data.charAt( size - 1 ) ||
size - 1 == index )
{
final String message =
REZ.getString( "ati.attribue-unquoted.error", data.substring( 0, index ) );
throw new SAXException( message );
}

final String[] result = new String[ 2 ];
result[ 0 ] = data.substring( 0, index );
result[ 1 ] = data.substring( index + 2, size - 1 );

return result;
}
}

+ 0
- 247
proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/ConvertingProjectBuilder.java View File

@@ -1,247 +0,0 @@
/*
* 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.builder;

import java.util.HashSet;
import java.util.Set;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.myrmidon.interfaces.builder.ProjectException;

/**
* A simple ProjectBuilder, which programmatically converts an Ant1 Project
* configuration into a Myrmidon one.
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*
* @ant.type type="project-builder" name="xml"
* @ant.type type="project-builder" name="ant"
* @ant.type type="project-builder" name="default"
*/
public class ConvertingProjectBuilder
extends DefaultProjectBuilder
{
private static final String VERSION_ATTRIBUTE = "version";

/**
* Builds a Configuration from an Ant1 project file, converting it
* into a valid Myrmidon Project.
* @param systemID the xml Systemid of the project file.
* @return the configured project
* @throws ProjectException if an error occurs parsing the project file
*/
protected Configuration parseProject( final String systemID )
throws ProjectException
{
final Configuration originalConfig = super.parseProject( systemID );

// Check the version, if it's present, just use this config.
// TODO: check for version < 2.0
if( originalConfig.getAttribute( VERSION_ATTRIBUTE, null ) != null )
{
return originalConfig;
}

// Convert the config by prepending "ant1." on tasks,
// and using <if> tasks instead of target 'if=' and 'unless='
final DefaultConfiguration newConfig = copyConfiguration( originalConfig );

// Put a new version attribute.
newConfig.setAttribute( VERSION_ATTRIBUTE, "2.0" );

// Copy the remaining attributes.
final Set omitAttributes = new HashSet();
omitAttributes.add( VERSION_ATTRIBUTE );
copyAttributes( originalConfig, newConfig, omitAttributes );

// Now copy/convert the children
final Configuration[] children = originalConfig.getChildren();
for( int i = 0; i < children.length; i++ )
{
final Configuration child = children[ i ];

if( child.getName().equals( "target" ) )
{
newConfig.addChild( convertTarget( child ) );
}
else
{
newConfig.addChild( convertTask( child ) );
}
}

return newConfig;
}

/**
* Converts Configuration for an Ant1 Target into a Myrmidon version.
* @param originalTarget The Ant1 Target
* @return the converted target
*/
private Configuration convertTarget( final Configuration originalTarget )
{
final DefaultConfiguration newTarget = copyConfiguration( originalTarget );

// Copy all attributes except 'if' and 'unless'
final Set omitAttributes = new HashSet();
omitAttributes.add( "if" );
omitAttributes.add( "unless" );
copyAttributes( originalTarget, newTarget, omitAttributes );

DefaultConfiguration containerElement = newTarget;

// For 'if="prop-name"', replace with <if> task.
final String ifAttrib = originalTarget.getAttribute( "if", null );
if ( ifAttrib != null )
{
final DefaultConfiguration ifElement =
buildIfElement( ifAttrib, false, originalTarget.getLocation() );
containerElement.addChild( ifElement );
// Treat the ifElement as the enclosing target.
containerElement = ifElement;
}

// For 'unless="prop-name"', replace with <if> task (negated).
final String unlessAttrib = originalTarget.getAttribute( "unless", null );
if ( unlessAttrib != null )
{
final DefaultConfiguration unlessElement =
buildIfElement( unlessAttrib, true, originalTarget.getLocation() );
containerElement.addChild( unlessElement );
// Treat the unlessElement as the enclosing target.
containerElement = unlessElement;
}

// Now copy in converted tasks.
final Configuration[] tasks = originalTarget.getChildren();
for( int i = 0; i < tasks.length; i++ )
{
containerElement.addChild( convertTask( tasks[ i ] ) );
}

return newTarget;
}

/**
* Builds configuration for an <if> task, to replace a "if" or "unless"
* attribute on a Ant1 target.
* @param ifProperty the name of the property from the Ant1 attribute.
* @param unless if the attribute is actually an "unless" attribute.
* @param location the configuration location to use
* @return The configuration for an <if> task
*/
private DefaultConfiguration buildIfElement( final String ifProperty,
final boolean unless,
final String location )
{
// <if>
// <condition>
// <is-set property="prop-name"/>
// </condition>
// .. tasks
// </if>
final DefaultConfiguration isSetElement =
new DefaultConfiguration( "is-set", location );
isSetElement.setAttribute( "property", ifProperty );

final DefaultConfiguration conditionElement =
new DefaultConfiguration( "condition", location );

if ( unless )
{
// Surround <is-set> with <not>
final DefaultConfiguration notElement =
new DefaultConfiguration( "not", location );
notElement.addChild( isSetElement );
conditionElement.addChild( notElement );
}
else
{
conditionElement.addChild( isSetElement );
}


final DefaultConfiguration ifElement =
new DefaultConfiguration( "if", location );
ifElement.addChild( conditionElement );

return ifElement;
}

/**
* Converts Configuration for an Ant1 Task into a Myrmidon version.
* @param originalTask The Ant1 Task
* @return the converted task
*/
private Configuration convertTask( final Configuration originalTask )
{
// Create a new configuration with the "ant1." prefix.
final String newTaskName = "ant1." + originalTask.getName();
final DefaultConfiguration newTask =
new DefaultConfiguration( newTaskName, originalTask.getLocation() );

// Copy all attributes and elements of the task.
copyAttributes( originalTask, newTask, new HashSet() );
copyChildren( originalTask, newTask );

return newTask;
}

/**
* Copies all child elements from one configuration to another
* @param from Configuration to copy from
* @param to Configuration to copy to
*/
private void copyChildren( final Configuration from,
final DefaultConfiguration to )
{
final Configuration[] children = from.getChildren();
for( int i = 0; i < children.length; i++ )
{
to.addChild( children[ i ] );
}
}

/**
* Copies all attributes from one configuration to another, excluding
* specified attribute names.
* @param from Configuration to copy from
* @param to Configuration to copy to
* @param omitAttributes a Set of attribute names to exclude
*/
private void copyAttributes( final Configuration from,
final DefaultConfiguration to,
final Set omitAttributes )
{
// Copy other attributes
final String[] attribs = from.getAttributeNames();
for( int i = 0; i < attribs.length; i++ )
{
final String name = attribs[ i ];
if( omitAttributes.contains( name ) )
{
continue;
}
final String value = from.getAttribute( name, "" );
to.setAttribute( name, value );
}
}

/**
* Creates a DefaultConfiguration with the same name and location as
* the one supplied.
* @param originalConfig the COnfiguration to copy.
* @return the new Configuration
*/
private DefaultConfiguration copyConfiguration( final Configuration originalConfig )
{
return new DefaultConfiguration( originalConfig.getName(),
originalConfig.getLocation() );
}
}

+ 0
- 229
proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/DefaultProject.java View File

@@ -1,229 +0,0 @@
/*
* 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.builder;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.myrmidon.interfaces.model.Project;
import org.apache.myrmidon.interfaces.model.Target;
import org.apache.myrmidon.interfaces.model.TypeLib;

/**
* Default project implementation.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class DefaultProject
implements Project
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultProject.class );

///The imports
private final ArrayList m_imports = new ArrayList();

///The projects refferred to by this project
private final HashMap m_projects = new HashMap();

///The targets contained by this project
private final HashMap m_targets = new HashMap();

///The implicit target (not present in m_targets)
private Target m_implicitTarget;

///The name of the default target
private String m_defaultTarget;

///The base directory of project
private File m_baseDirectory;

///The project name
private String m_name;

/**
* @return the project name.
*/
public String getProjectName()
{
return m_name;
}

/**
* Sets the project name.
* @param name the project name
*/
public void setProjectName( String name )
{
m_name = name;
}

/**
* Get the imports for project.
*
* @return the imports
*/
public TypeLib[] getTypeLibs()
{
return (TypeLib[])m_imports.toArray( new TypeLib[ 0 ] );
}

/**
* Get names of projects referred to by this project.
*
* @return the names
*/
public String[] getProjectNames()
{
return (String[])m_projects.keySet().toArray( new String[ 0 ] );
}

/**
* Retrieve project reffered to by this project.
*
* @param name the project name
* @return the Project or null if none by that name
*/
public Project getProject( final String name )
{
return (Project)m_projects.get( name );
}

/**
* Retrieve base directory of project.
*
* @return the projects base directory
*/
public final File getBaseDirectory()
{
return m_baseDirectory;
}

/**
* Retrieve implicit target.
* The implicit target contains all the top level tasks.
*
* @return the Target
*/
public final Target getImplicitTarget()
{
return m_implicitTarget;
}

/**
* Set ImplicitTarget.
*
* @param target the implicit target
*/
public final void setImplicitTarget( final Target target )
{
m_implicitTarget = target;
}

/**
* Retrieve a target by name.
*
* @param targetName the name of target
* @return the Target or null if no target exists with name
*/
public final Target getTarget( final String targetName )
{
return (Target)m_targets.get( targetName );
}

/**
* Get name of default target.
*
* @return the default target name
*/
public final String getDefaultTargetName()
{
return m_defaultTarget;
}

/**
* Retrieve names of all targets in project.
*
* @return an array target names
*/
public final String[] getTargetNames()
{
return (String[])m_targets.keySet().toArray( new String[ 0 ] );
}

/**
* Set DefaultTargetName.
*
* @param defaultTarget the default target name
*/
public final void setDefaultTargetName( final String defaultTarget )
{
m_defaultTarget = defaultTarget;
}

/**
* Sets the project base directory.
* @param baseDirectory the base directory for the project
*/
public final void setBaseDirectory( final File baseDirectory )
{
m_baseDirectory = baseDirectory;
}

/**
* Adds a type library import to the project.
* @param typeLib the type library
*/
public final void addTypeLib( final TypeLib typeLib )
{
m_imports.add( typeLib );
}

/**
* Add a target.
*
* @param name the name of target
* @param target the Target
* @exception IllegalArgumentException if target already exists with same name
*/
public final void addTarget( final String name, final Target target )
{
if( null != m_targets.get( name ) )
{
final String message = REZ.getString( "duplicate-target.error", name );
throw new IllegalArgumentException( message );
}
else
{
m_targets.put( name, target );
}
}

/**
* Add a project reference.
*
* @param name the name of target
* @param project the Project
* @exception IllegalArgumentException if project already exists with same name
*/
public final void addProject( final String name, final Project project )
{
if( null != m_projects.get( name ) )
{
final String message = REZ.getString( "duplicate-project.error", name );
throw new IllegalArgumentException( message );
}
else
{
m_projects.put( name, project );
}
}
}

+ 0
- 553
proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/DefaultProjectBuilder.java View File

@@ -1,553 +0,0 @@
/*
* 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.builder;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.excalibur.io.FileUtil;
import org.apache.avalon.excalibur.util.StringUtil;
import org.apache.avalon.framework.Version;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.myrmidon.interfaces.builder.ProjectBuilder;
import org.apache.myrmidon.interfaces.builder.ProjectException;
import org.apache.myrmidon.interfaces.model.DefaultNameValidator;
import org.apache.myrmidon.interfaces.model.Dependency;
import org.apache.myrmidon.interfaces.model.Project;
import org.apache.myrmidon.interfaces.model.Target;
import org.apache.myrmidon.interfaces.model.TypeLib;
import org.xml.sax.XMLReader;

/**
* Default implementation to construct project from a build file.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*
* @ant.type type="project-builder" name="ant2"
*/
public class DefaultProjectBuilder
extends AbstractLogEnabled
implements ProjectBuilder
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultProjectBuilder.class );

private static final Version VERSION = new Version( 2, 0, 0 );

private static final int PROJECT_REFERENCES = 0;
private static final int LIBRARY_IMPORTS = 1;
private static final int IMPLICIT_TASKS = 2;
private static final int TARGETS = 3;

// Use a name validator with the default rules.
private DefaultNameValidator m_nameValidator = new DefaultNameValidator();

/**
* build a project from file.
*
* @param source the source
* @return the constructed Project
* @exception ProjectException if an error occurs
*/
public Project build( final String source )
throws ProjectException
{
final File file = new File( source );
return build( file, new HashMap() );
}

private Project build( final File file, final HashMap projects )
throws ProjectException
{
try
{
// Check for cached project
final String systemID = extractURL( file );
final Project result = (Project)projects.get( systemID );
if( null != result )
{
return result;
}

// Parse the project file
final Configuration configuration = parseProject( systemID );

// Build the project model and add to cache
final DefaultProject project = buildProject( file, configuration );
projects.put( systemID, project );

// Build using all top-level attributes
buildTopLevelProject( project, configuration, projects );

return project;
}
catch( Exception e )
{
final String message = REZ.getString( "ant.project-build.error",
file.getAbsolutePath() );
throw new ProjectException( message, e );
}
}

/**
* Builds a project configuration from a build file.
* @param systemID the XML system id of the build file
* @return the project configuration
* @throws ProjectException on parse error
*/
protected Configuration parseProject( final String systemID )
throws ProjectException
{
try
{
final SAXConfigurationHandler handler = new SAXConfigurationHandler();
final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
final SAXParser saxParser = saxParserFactory.newSAXParser();
final XMLReader parser = saxParser.getXMLReader();
parser.setFeature( "http://xml.org/sax/features/namespace-prefixes", false );
parser.setFeature( "http://xml.org/sax/features/namespaces", false );
//parser.setFeature( "http://xml.org/sax/features/validation", false );

parser.setContentHandler( handler );
parser.setErrorHandler( handler );
parser.parse( systemID );

return handler.getConfiguration();
}
catch( Exception e )
{
final String message = REZ.getString( "ant.project-parse.error" );
throw new ProjectException( message, e );
}
}

/**
* build project from configuration.
*
* @param file the file from which configuration was loaded
* @param configuration the configuration loaded
* @return the created Project
* @exception ProjectException if an error occurs building the project
*/
private DefaultProject buildProject( final File file,
final Configuration configuration )
throws ProjectException
{
if( !configuration.getName().equals( "project" ) )
{
final String message = REZ.getString( "ant.no-project-element.error" );
throw new ProjectException( message );
}

//get project-level attributes
final String projectName = getProjectName( configuration, file );
final String baseDirectoryName = configuration.getAttribute( "basedir", null );
final String defaultTarget = configuration.getAttribute( "default", "main" );
final Version version = getVersion( configuration );

if( !VERSION.complies( version ) )
{
final String message =
REZ.getString( "ant.bad-version.error", VERSION, version );
throw new ProjectException( message );
}

//determine base directory for project. Use the directory containing
//the build file as the default.
File baseDirectory = file.getParentFile();
if( baseDirectoryName != null )
{
baseDirectory = FileUtil.resolveFile( baseDirectory, baseDirectoryName );
}
baseDirectory = baseDirectory.getAbsoluteFile();

if( getLogger().isDebugEnabled() )
{
final String message = REZ.getString( "ant.project-banner.notice",
file, baseDirectory );
getLogger().debug( message );
}

//create project and ...
final DefaultProject project = new DefaultProject();
project.setProjectName( projectName );
project.setDefaultTargetName( defaultTarget );
project.setBaseDirectory( baseDirectory );

return project;
}

/**
* Get the project name from the configuration, or create a default name if none
* was supplied.
*/
private String getProjectName( final Configuration configuration,
final File file )
throws ProjectException
{
String projectName = configuration.getAttribute( "name", null );

if( projectName == null )
{
// Create a name based on the file name.
String fileNameBase = FileUtil.removeExtension( file.getName() );
try
{
projectName = m_nameValidator.makeValidName( fileNameBase );
}
catch( Exception e )
{
String message = REZ.getString( "ant.project-create-name.error" );
throw new ProjectException( message, e );
}
}
else
{
// Make sure the supplied name is valid.
try
{
m_nameValidator.validate( projectName );
}
catch( Exception e )
{
String message = REZ.getString( "ant.project-bad-name.error" );
throw new ProjectException( message, e );
}
}
return projectName;

}

/**
* Retrieve the version attribute from the specified configuration element.
* Throw exceptions with meaningful errors if malformed or missing.
*/
private Version getVersion( final Configuration configuration )
throws ProjectException
{
try
{
final String versionString = configuration.getAttribute( "version" );
return parseVersion( versionString );
}
catch( final ConfigurationException ce )
{
final String message = REZ.getString( "ant.version-missing.error" );
throw new ProjectException( message, ce );
}
}

/**
* Utility function to extract version
*/
private Version parseVersion( final String versionString )
throws ProjectException
{

try
{
return Version.getVersion( versionString );
}
catch( final Exception e )
{
final String message =
REZ.getString( "ant.malformed.version", versionString );
throw new ProjectException( message );
}
}

/**
* Handle all top level elements in configuration.
*
* @param project the project
* @param configuration the Configuration
* @exception ProjectException if an error occurs
*/
private void buildTopLevelProject( final DefaultProject project,
final Configuration configuration,
final HashMap projects )
throws ProjectException
{
final ArrayList implicitTaskList = new ArrayList();
final Configuration[] children = configuration.getChildren();

int state = PROJECT_REFERENCES;

for( int i = 0; i < children.length; i++ )
{
final Configuration element = children[ i ];
final String name = element.getName();

if( PROJECT_REFERENCES == state )
{
if( name.equals( "projectref" ) )
{
buildProjectRef( project, element, projects );
continue;
}
else
{
state = LIBRARY_IMPORTS;
}
}

if( LIBRARY_IMPORTS == state )
{
if( name.equals( "import" ) )
{
buildTypeLib( project, element );
continue;
}
else
{
state = IMPLICIT_TASKS;
}
}

if( IMPLICIT_TASKS == state )
{
//Check for any implicit tasks here
if( !name.equals( "target" ) )
{
implicitTaskList.add( element );
continue;
}
else
{
state = TARGETS;
}
}

if( name.equals( "target" ) )
{
buildTarget( project, element );
}
else
{
final String message =
REZ.getString( "ant.unknown-toplevel-element.error", name,
element.getLocation() );
throw new ProjectException( message );
}
}

final Configuration[] implicitTasks =
(Configuration[])implicitTaskList.toArray( new Configuration[ 0 ] );

final Target implicitTarget = new Target( implicitTasks, null );
project.setImplicitTarget( implicitTarget );
}

private void buildProjectRef( final DefaultProject project,
final Configuration element,
final HashMap projects )
throws ProjectException
{
final String name = element.getAttribute( "name", null );
final String location = element.getAttribute( "location", null );

if( null == name )
{
final String message =
REZ.getString( "ant.projectref-no-name.error",
element.getLocation() );
throw new ProjectException( message );
}

try
{
m_nameValidator.validate( name );
}
catch( Exception e )
{
final String message =
REZ.getString( "ant.projectref-bad-name.error",
element.getLocation() );
throw new ProjectException( message, e );
}

if( null == location )
{
final String message =
REZ.getString( "ant.projectref-no-location.error",
element.getLocation() );
throw new ProjectException( message );
}

// Build the URL of the referenced projects
final File baseDirectory = project.getBaseDirectory();
final File file = FileUtil.resolveFile( baseDirectory, location );

// Locate the referenced project, building it if necessary
final Project other = build( file, projects );

// Add the reference
project.addProject( name, other );
}

/**
* Validates a project file name, and builds the canonical URL for it.
*/
private String extractURL( final File file ) throws ProjectException
{
if( ! file.isFile() )
{
final String message = REZ.getString( "ant.no-project-file.error" );
throw new ProjectException( message );
}

try
{
return file.getCanonicalFile().toURL().toString();
}
catch( Exception e )
{
final String message = REZ.getString( "ant.project-unexpected.error" );
throw new ProjectException( message, e );
}
}

private void buildTypeLib( final DefaultProject project,
final Configuration element )
throws ProjectException
{
final String library = element.getAttribute( "library", null );
final String name = element.getAttribute( "name", null );
final String type = element.getAttribute( "type", null );

if( null == library )
{
final String message =
REZ.getString( "ant.import-no-library.error", element.getLocation() );
throw new ProjectException( message );
}

if( null == name || null == type )
{
if( null != name || null != type )
{
final String message =
REZ.getString( "ant.import-malformed.error", element.getLocation() );
throw new ProjectException( message );
}
}

project.addTypeLib( new TypeLib( library, type, name ) );
}

/**
* Build a target from configuration.
*
* @param project the project
* @param target the Configuration
*/
private void buildTarget( final DefaultProject project, final Configuration target )
throws ProjectException
{
final String name = target.getAttribute( "name", null );
final String depends = target.getAttribute( "depends", null );

verifyTargetName( name, target );

if( getLogger().isDebugEnabled() )
{
final String message = REZ.getString( "ant.target-parse.notice", name );
getLogger().debug( message );
}

final Dependency[] dependencies = buildDependsList( depends, target );
final Target defaultTarget = new Target( target.getChildren(), dependencies );

//add target to project
project.addTarget( name, defaultTarget );
}

private void verifyTargetName( final String name, final Configuration target )
throws ProjectException
{
if( null == name )
{
final String message =
REZ.getString( "ant.target-noname.error", target.getLocation() );
throw new ProjectException( message );
}

try
{
m_nameValidator.validate( name );
}
catch( Exception e )
{
final String message =
REZ.getString( "ant.target-bad-name.error", target.getLocation() );
throw new ProjectException( message, e );
}
}

private Dependency[] buildDependsList( final String depends,
final Configuration target )
throws ProjectException
{
//apply depends attribute
if( null == depends )
{
return null;
}

final String[] elements = StringUtil.split( depends, "," );
final ArrayList dependsList = new ArrayList();

for( int i = 0; i < elements.length; i++ )
{
final String dependency = elements[ i ].trim();

if( getLogger().isDebugEnabled() )
{
final String message = REZ.getString( "ant.target-dependency.notice",
dependency );
getLogger().debug( message );
}

// Split project->target dependencies
final int sep = dependency.indexOf( "->" );
final String projectName;
final String targetName;
if( sep != -1 )
{
projectName = dependency.substring( 0, sep );
targetName = dependency.substring( sep + 2 );
}
else
{
projectName = null;
targetName = dependency;
}

if( targetName.length() == 0 ||
( projectName != null && projectName.length() == 0 ) )
{
final String message = REZ.getString( "ant.target-bad-dependency.error",
target.getName(),
target.getLocation() );
throw new ProjectException( message );
}

dependsList.add( new Dependency( projectName, targetName ) );
}

return (Dependency[])dependsList.toArray( new Dependency[dependsList.size() ] );
}
}

+ 0
- 60
proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/ReactorPIHandler.java View File

@@ -1,60 +0,0 @@
/*
* 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.builder;

import java.util.ArrayList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
* Handler that reacts to PIs before first element.
* Have to do it this way as there doesn't seem to be a *safe* way
* of redirecting content handlers at runtime while using transformers.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class ReactorPIHandler
extends DefaultHandler
{
private ArrayList m_targets = new ArrayList();
private ArrayList m_data = new ArrayList();

public int getPICount()
{
return m_targets.size();
}

public String getTarget( final int index )
{
return (String)m_targets.get( index );
}

public String getData( final int index )
{
return (String)m_data.get( index );
}

public void processingInstruction( final String target, final String data )
throws SAXException
{
m_targets.add( target );
m_data.add( data );
}

public void startElement( final String uri,
final String localName,
final String qName,
final Attributes atts )
throws SAXException
{
//Workaround to stop SAX pipeline
throw new StopParsingException();
}
}

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

@@ -1,37 +0,0 @@
ati.two.stylesheet.pis=Build file can not contain two xsl-stylesheet PIs.
ati.params.error=Malformed PI: expected <?xsl-params location=\"myparams.properties\"?>
ati.param.error=Malformed PI: expected <?xsl-param name=\"foo\" value=\"bar\"?>
ati.style.error=Malformed PI: expected <?xsl-params href=\"mystylesheet.xsl\"?>
ati.loading-params.error=Error loading parameters {0}. Reason: {1}.
ati.loading-style.error=Error locating stylesheet {0}. Reason: {1}.
ati.attribue-expected.error=Expecting an attribute but received {0}.
ati.attribue-unquoted.error=Expecting the value of attribute {0} to be enclosed in quotes.

ant.project-banner.notice=Project {0} base directory: {1}.
ant.target-parse.notice=Parsing target: {0}.
ant.target-dependency.notice=Target dependency: {0}
ant.project-unexpected.error=Unexpected error building project.
ant.project-parse.error=Could not parse project file.
ant.project-build.error=Could not load project from "{0}".
ant.no-project-element.error=Project file must be enclosed in project element.
ant.unknown-toplevel-element.error=Unknown top-level element {0} at {1}.
ant.project-bad-name.error=Invalid project name.
ant.project-create-name.error=Could not create a name for this project.
ant.projectref-no-name.error=Malformed projectref without a name attribute at {0}.
ant.projectref-bad-name.error=Projectref with an invalid name attribute at {0}.
ant.projectref-no-location.error=Malformed projectref without a location attribute at {0}.
ant.import-no-library.error=Malformed import without a library attribute at {0}.
ant.import-malformed.error=Malformed import at {0}. If name or type attribute is specified, both attributes must be specified.
ant.target-noname.error=Discovered un-named target at {0}.
ant.target-bad-name.error=Target with an invalid name at {0}.
ant.target-bad-dependency.error=Discovered empty dependency in target {0} at {1}.
ant.malformed.version=Project has an invalid version "{0}".
ant.version-missing.error=Project has no version attribute.
ant.bad-version.error=Incompatible build file version detected. Expected version {0} but found version {1}.
ant.no-project-file.error=Project file does not exist, or is not a file.

ant.project-convert.notice=Applying compatibility stylesheet to project file.
ant.project-convert.error=Error converting build file.

duplicate-project.error=Can not have two projects referenced in a file with the name {0}.
duplicate-target.error=Can not have two targets in a file with the name {0}.

+ 0
- 25
proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/StopParsingException.java View File

@@ -1,25 +0,0 @@
/*
* 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.builder;

import org.xml.sax.SAXException;

/**
* Dummy exception to stop parsing "safely".
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
class StopParsingException
extends SAXException
{
public StopParsingException()
{
super( "" );
}
}

+ 0
- 97
proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/TransformingProjectBuilder.java View File

@@ -1,97 +0,0 @@
/*
* 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.builder;

import java.io.InputStream;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
import org.apache.myrmidon.interfaces.builder.ProjectException;

/**
* A Project Builder which performs an XSL transformation on a project.
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*
* @ant.type type="project-builder" name="ant-transform"
*/
public class TransformingProjectBuilder
extends DefaultProjectBuilder
{
private static final Resources REZ =
ResourceManager.getPackageResources( TransformingProjectBuilder.class );

private static final String STYLESHEET = "ant1convert.xsl";
private Transformer m_transformer;

/**
* Builds a project Configuration from a project file, applying the
* ant1 conversion stylesheet.
* @param systemID the XML system id for the project file
* @return the project configuration
* @throws ProjectException if a parse error occurs
*/
protected Configuration parseProject( String systemID )
throws ProjectException
{
if( getLogger().isDebugEnabled() )
{
final String message = REZ.getString( "ant.project-convert.notice" );
getLogger().debug( message );
}

try
{
// Create a XSLT source for the build file.
Source source = new StreamSource( systemID );

// Create a configuration handler for the output.
final SAXConfigurationHandler handler = new SAXConfigurationHandler();
Result result = new SAXResult( handler );

// Perform the transformation.
getTransformer().transform( source, result );

return handler.getConfiguration();
}
catch( Exception e )
{
throw new ProjectException( REZ.getString( "ant.project-convert.error" ),
e );
}
}

/**
* Lazy load a Transformer with the conversion stylesheet.
* @return the initialised Transformer
* @throws TransformerConfigurationException
*/
private Transformer getTransformer()
throws TransformerConfigurationException
{
// Lazy loading of stylesheet source.
if( m_transformer == null )
{
InputStream stylesheet =
this.getClass().getResourceAsStream( STYLESHEET );
StreamSource stylesheetSource = new StreamSource( stylesheet );
TransformerFactory xformFactory = TransformerFactory.newInstance();
m_transformer = xformFactory.newTransformer( stylesheetSource );
}
return m_transformer;
}
}

+ 0
- 151
proposal/myrmidon/src/java/org/apache/myrmidon/components/builder/ant1convert.xsl View File

@@ -1,151 +0,0 @@
<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/project">
<xsl:comment>Converted Project file.</xsl:comment>
<xsl:copy>
<xsl:attribute name="version">2.0</xsl:attribute>
<xsl:apply-templates select="@*[name() != 'version']" mode="copy"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<!-- For projects with a version attribute, simply copy the entire tree. -->
<!-- TODO check for version >= 2.0.0 -->
<xsl:template match="/project[@version]">
<xsl:comment>Copied Project file.</xsl:comment>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates mode="copy"/>
</xsl:copy>
</xsl:template>

<!-- Handle simple target nodes -->
<xsl:template match="/project/target">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<!-- Handle target nodes with 'if' -->
<xsl:template match="/project/target[@if]">
<xsl:copy>
<xsl:apply-templates select="@*[name() != 'if']"/>

<!-- Put in the if condition -->
<xsl:element name="if">
<xsl:element name="condition">
<xsl:element name="is-set">
<xsl:attribute name="property">
<xsl:value-of select="@if"/>
</xsl:attribute>
</xsl:element>
</xsl:element>

<!-- Now add the target content -->
<xsl:apply-templates/>

</xsl:element>
</xsl:copy>
</xsl:template>

<!-- Handle target nodes with 'unless' -->
<xsl:template match="/project/target[@unless]">
<xsl:copy>
<xsl:apply-templates select="@*[name() != 'unless']"/>

<!-- Put in the unless condition -->
<xsl:element name="if">
<xsl:element name="condition">
<xsl:element name="not">
<xsl:element name="is-set">
<xsl:attribute name="property">
<xsl:value-of select="@unless"/>
</xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:element>

<!-- Now add the target content -->
<xsl:apply-templates/>

</xsl:element>
</xsl:copy>
</xsl:template>

<!-- Handle target nodes with 'if' and 'unless' -->
<xsl:template match="/project/target[@if and @unless]">
<xsl:copy>
<xsl:apply-templates select="@*[name()!='if' and name()!='unless']"/>

<!-- Put in the 'if' condition -->
<xsl:element name="if">
<xsl:element name="condition">
<xsl:element name="is-set">
<xsl:attribute name="property">
<xsl:value-of select="@if"/>
</xsl:attribute>
</xsl:element>
</xsl:element>

<!-- Put in the 'unless' condition -->
<xsl:element name="if">
<xsl:element name="condition">
<xsl:element name="not">
<xsl:element name="is-set">
<xsl:attribute name="property">
<xsl:value-of select="@unless"/>
</xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:element>

<!-- Now add the target content -->
<xsl:apply-templates/>

</xsl:element>
</xsl:element>
</xsl:copy>
</xsl:template>


<!-- Handle task nodes, prepending "ant1." -->
<xsl:template match="*">
<xsl:element name="ant1.{name()}">
<xsl:apply-templates select="@*"/>
<xsl:apply-templates mode="copy"/>
</xsl:element>
</xsl:template>

<!-- Copy all elements in copy-mode -->
<xsl:template match="*" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates mode="copy"/>
</xsl:copy>
</xsl:template>

<!-- Always copy attributes -->
<xsl:template match="@*">
<xsl:copy/>
</xsl:template>

<xsl:template match="@*" mode="copy">
<xsl:copy/>
</xsl:template>

<!-- Always copy comments -->
<xsl:template match="comment()">
<xsl:copy/>
</xsl:template>

<xsl:template match="comment()" mode="copy">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>




+ 0
- 305
proposal/myrmidon/src/java/org/apache/myrmidon/components/classloader/DefaultClassLoaderManager.java View File

@@ -1,305 +0,0 @@
/*
* 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.classloader;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import org.apache.aut.nativelib.PathUtil;
import org.apache.avalon.excalibur.extension.Extension;
import org.apache.avalon.excalibur.extension.OptionalPackage;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.myrmidon.interfaces.classloader.ClassLoaderException;
import org.apache.myrmidon.interfaces.classloader.ClassLoaderManager;
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>
* @version $Revision$ $Date$
*/
public class DefaultClassLoaderManager
extends AbstractLogEnabled
implements ClassLoaderManager, Serviceable, Contextualizable
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultClassLoaderManager.class );

/**
* Map from File/ArrayList to the ClassLoader for that file/files.
*/
private final Map m_classLoaders = new HashMap();

private ExtensionManager m_extensionManager;
private ClassLoader m_commonClassLoader;

public DefaultClassLoaderManager()
{
}

public DefaultClassLoaderManager( final ClassLoader commonClassLoader )
{
m_commonClassLoader = commonClassLoader;
}

public void contextualize( final Context context ) throws ContextException
{
if( null == m_commonClassLoader )
{
m_commonClassLoader = (ClassLoader)context.get( "myrmidon.shared.classloader" );
}
}

/**
* Retrieve relevent services needed to deploy.
*/
public void service( final ServiceManager serviceManager )
throws ServiceException
{
m_extensionManager = (ExtensionManager)serviceManager.lookup( ExtensionManager.ROLE );
}

/**
* Returns the common ClassLoader. This is the parent of all classloaders
* built by this ClassLoaderManager.
*/
public ClassLoader getCommonClassLoader()
{
return m_commonClassLoader;
}

/**
* Creates a class loader for a Jar file.
*/
public ClassLoader getClassLoader( final File file ) throws ClassLoaderException
{
try
{
final File canonFile = file.getCanonicalFile();

// Check for cached classloader, creating it if required
ClassLoader loader = (ClassLoader)m_classLoaders.get( canonFile );
if( loader == null )
{
checkFile( canonFile );
final OptionalPackage optionalPackage = toOptionalPackage( canonFile );
loader = buildClassLoader( optionalPackage, new HashSet() );
}
return loader;
}
catch( final Exception e )
{
final String message = REZ.getString( "create-classloader-for-file.error", file );
throw new ClassLoaderException( message, e );
}
}

/**
* Creates a class loader for a set of Jar files.
*/
public ClassLoader createClassLoader( final File[] files ) throws ClassLoaderException
{
try
{
if( files == null || files.length == 0 )
{
return m_commonClassLoader;
}

// Build a list of optional packages for the files
final OptionalPackage[] packages = new OptionalPackage[ files.length ];
for( int i = 0; i < files.length; i++ )
{
final File canonFile = files[ i ].getCanonicalFile();
checkFile( canonFile );
packages[ i ] = toOptionalPackage( canonFile );
}

// Build the classloaders for the required extensions
final ClassLoader[] parentClassLoaders = buildParentClassLoaders( packages, new HashSet() );

// Build the classloader
final URL[] urls = buildClasspath( files );
return new MultiParentURLClassLoader( urls, parentClassLoaders );
}
catch( final Exception e )
{
final String fileNames = PathUtil.formatPath( files );
final String message = REZ.getString( "create-classloader-for-files.error", fileNames );
throw new ClassLoaderException( message, e );
}
}

/**
* Builds the classloader for an optional package.
*/
private ClassLoader buildClassLoader( final OptionalPackage pkg,
final Set pending )
throws Exception
{
final File jarFile = pkg.getFile();

// Check for cached classloader
ClassLoader classLoader = (ClassLoader)m_classLoaders.get( jarFile );
if( classLoader != null )
{
return classLoader;
}

// Check for cyclic dependency
if( pending.contains( jarFile ) )
{
final String message = REZ.getString( "dependency-cycle.error", jarFile );
throw new Exception( message );
}
pending.add( jarFile );

// Build the classloaders for the extensions required by this optional
// package
final ClassLoader[] parentClassLoaders =
buildParentClassLoaders( new OptionalPackage[] { pkg }, pending );

// Create and cache the classloader
final URL[] urls = { jarFile.toURL() };
classLoader = new MultiParentURLClassLoader( urls, parentClassLoaders );
m_classLoaders.put( jarFile, classLoader );
pending.remove( jarFile );
return classLoader;
}

/**
* Builds the parent classloaders for a set of optional packages. That is,
* the classloaders for all of the extensions required by the given set
* of optional packages.
*/
private ClassLoader[] buildParentClassLoaders( final OptionalPackage[] packages,
final Set pending )
throws Exception
{
final ArrayList classLoaders = new ArrayList();

// Include the common class loader
classLoaders.add( m_commonClassLoader );

// Build the classloader for each optional package, filtering out duplicates
for( int i = 0; i < packages.length; i++ )
{
final OptionalPackage optionalPackage = packages[ i ];

// Locate the dependencies for this jar file
final OptionalPackage[] requiredPackages = getOptionalPackagesFor( optionalPackage );

// Build the classloader for the package
for( int j = 0; j < requiredPackages.length; j++ )
{
final OptionalPackage requiredPackage = requiredPackages[j ];
final ClassLoader classLoader = buildClassLoader( requiredPackage, pending );
if( ! classLoaders.contains( classLoader ) )
{
classLoaders.add( classLoader );
}
}
}

return (ClassLoader[])classLoaders.toArray( new ClassLoader[classLoaders.size() ] );
}

/**
* Assembles a set of files into a URL classpath.
*/
private URL[] buildClasspath( final File[] files )
throws MalformedURLException
{
final URL[] urls = new URL[ files.length ];
for( int i = 0; i < files.length; i++ )
{
urls[ i ] = files[i ].toURL();
}

return urls;
}

/**
* Builds an OptionalPackage for a Jar file.
*
* @param file the jar.
*/
private OptionalPackage toOptionalPackage( final File file )
throws Exception
{
// Determine the extensions required by this file
final JarFile jarFile = new JarFile( file );
final Manifest manifest = jarFile.getManifest();
final Extension[] required = Extension.getRequired( manifest );
return new OptionalPackage( file, new Extension[0], required );
}

/**
* Locates the optional packages required by an optional package.
*/
private OptionalPackage[] getOptionalPackagesFor( final OptionalPackage pkg )
throws Exception
{
// Locate the optional packages that provide the required extesions
final Extension[] required = pkg.getRequiredExtensions();
final ArrayList packages = new ArrayList();
for( int i = 0; i < required.length; i++ )
{
final Extension extension = required[i ];
final OptionalPackage optionalPackage = m_extensionManager.getOptionalPackage( extension );
if( optionalPackage == null )
{
final String message =
REZ.getString( "unsatisfied.extension.error",
pkg.getFile(),
extension.getExtensionName(),
extension.getSpecificationVersion() );
throw new Exception( message );
}
packages.add( optionalPackage );
}

return (OptionalPackage[])packages.toArray( new OptionalPackage[packages.size() ] );
}

/**
* 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 );
}
}
}

+ 0
- 141
proposal/myrmidon/src/java/org/apache/myrmidon/components/classloader/MultiParentURLClassLoader.java View File

@@ -1,141 +0,0 @@
/*
* 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.classloader;

import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.HashSet;

/**
* A URLClassLoader with more than one parent.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public class MultiParentURLClassLoader
extends URLClassLoader
{
private final ClassLoader[] m_parents;

/**
* Constructs a new URLClassLoader for the given URLs.
*
* @param urls the URLs from which to load classes and resources
* @param parents the parent class loaderer for delegation
*/
public MultiParentURLClassLoader( final URL[] urls, final ClassLoader[] parents )
{
super( urls );
m_parents = parents;
}

/**
* Finds a class.
*
* @param name the name of the class
* @return the resulting class
* @exception ClassNotFoundException if the class could not be found
*/
protected Class findClass( final String name )
throws ClassNotFoundException
{
// Try the parent classloaders first
for( int i = 0; i < m_parents.length; i++ )
{
try
{
final ClassLoader parent = m_parents[ i ];
return parent.loadClass( name );
}
catch( ClassNotFoundException e )
{
// Ignore - continue to the next ClassLoader
}
}

// Now this classloader
return super.findClass( name );
}

/**
* Finds a resource.
*
* @param name the name of the resource
* @return a <code>URL</code> for the resource, or <code>null</code>
* if the resource could not be found.
*/
public URL findResource( final String name )
{
// Try the parent classloaders first
for( int i = 0; i < m_parents.length; i++ )
{
final ClassLoader parent = m_parents[ i ];
final URL resource = parent.getResource( name );
if( resource != null )
{
return resource;
}
}

// Now this classloader
return super.findResource( name );
}

/**
* Returns an Enumeration of URLs representing all of the resources
* having the specified name.
*
* @param name the resource name
* @throws IOException if an I/O exception occurs
* @return an <code>Enumeration</code> of <code>URL</code>s
*/
public Enumeration findResources( final String name ) throws IOException
{
// Need to filter out duplicate resources
final ArrayList urls = new ArrayList();
final Set urlSet = new HashSet();

// Gather the resources from the parent classloaders
for( int i = 0; i < m_parents.length; i++ )
{
final ClassLoader parent = m_parents[ i ];
final Enumeration enum = parent.getResources( name );
addUrls( enum, urls, urlSet );
}

// Gather the resources from this classloader
addUrls( super.findResources( name ), urls, urlSet );

return Collections.enumeration( urls );
}

/**
* Adds those URLs not already present.
*/
private void addUrls( final Enumeration enum,
final List urls,
final Set urlSet )
{
while( enum.hasMoreElements() )
{
final URL url = (URL)enum.nextElement();
final String urlStr = url.toExternalForm();
if( !urlSet.contains( urlStr ) )
{
urls.add( url );
urlSet.add( urlStr );
}
}
}
}

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

@@ -1,5 +0,0 @@
create-classloader-for-file.error=Could not create a ClassLoader for "{0}".
create-classloader-for-files.error=Could not create a ClassLoader for {0}.
unsatisfied.extension.error=Library "{0}" requires unknown extension "{1}" ( version {2}).
no-file.error=Could not find library "{0}".
file-is-dir.error=Library "{0}" is a directory.

+ 0
- 567
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ClassicConfigurer.java View File

@@ -1,567 +0,0 @@
/*
* 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.configurer;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import org.apache.aut.converter.Converter;
import org.apache.aut.converter.ConverterException;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.interfaces.configurer.Configurer;

/**
* Class used to configure tasks.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @ant.type type="configurer" name="classic"
*/
public class ClassicConfigurer
extends AbstractLogEnabled
implements Configurer, Serviceable, LogEnabled
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultConfigurer.class );

///Compile time constant to turn on extreme debugging
private static final boolean DEBUG = false;

///Converter to use for converting between values
private Converter m_converter;

public void service( final ServiceManager serviceManager )
throws ServiceException
{
m_converter = (Converter)serviceManager.lookup( Converter.ROLE );
}

/**
* Configure an object based on a configuration in a particular context.
* This configuring can be done in different ways for different
* configurers.
*
* The implementation of this method should only use the methods
* specified by the supplied class. It is an error for the specified
* class not to be a base class or interface compatible with specified
* object.
*
* @param object the object
* @param clazz the Class object to use during configuration
* @param configuration the configuration
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
public void configureElement( Object object,
Class clazz,
Configuration configuration,
TaskContext context )
throws ConfigurationException
{
throw new UnsupportedOperationException();
}

/**
* Configure named attribute of object in a particular context.
* This configuring can be done in different ways for different
* configurers.
*
* The implementation of this method should only use the methods
* specified by the supplied class. It is an error for the specified
* class not to be a base class or interface compatible with specified
* object.
*
* @param object the object
* @param clazz the Class object to use during configuration
* @param name the attribute name
* @param value the attribute value
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
public void configureAttribute( Object object,
Class clazz,
String name,
String value,
TaskContext context )
throws ConfigurationException
{
throw new UnsupportedOperationException();
}

/**
* Configure a task based on a configuration in a particular context.
* This configuring can be done in different ways for different
* configurers.
* This one does it by first checking if object implements Configurable
* and if it does will pass the task the configuration - else it will use
* mapping rules to map configuration to types
*
* @param object the object
* @param configuration the configuration
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
public void configureElement( final Object object,
final Configuration configuration,
final TaskContext context )
throws ConfigurationException
{
if( DEBUG )
{
final String message = REZ.getString( "configuring-object.notice", object );
getLogger().debug( message );
}

if( object instanceof Configurable )
{
if( DEBUG )
{
final String message = REZ.getString( "configurable.notice" );
getLogger().debug( message );
}

final Configurable configurable = (Configurable)object;
configurable.configure( configuration );
}
else
{
if( DEBUG )
{
final String message = REZ.getString( "reflection.notice" );
getLogger().debug( message );
}

final String[] attributes = configuration.getAttributeNames();
for( int i = 0; i < attributes.length; i++ )
{
final String name = attributes[ i ];
final String value = configuration.getAttribute( name );

if( DEBUG )
{
final String message = REZ.getString( "configure-attribute.notice",
name, value );
getLogger().debug( message );
}

doConfigureAttribute( object, name, value, context );
}

final Configuration[] children = configuration.getChildren();

for( int i = 0; i < children.length; i++ )
{
final Configuration child = children[ i ];

if( DEBUG )
{
final String message =
REZ.getString( "configure-subelement.notice", child.getName() );
getLogger().debug( message );
}

doConfigureElement( object, child, context );
}

final String content = configuration.getValue( null );
if( null != content )
{
if( !content.trim().equals( "" ) )
{
if( DEBUG )
{
final String message =
REZ.getString( "configure-content.notice", content );
getLogger().debug( message );
}

configureContent( object, content, context );
}
}
}
}

/**
* Configure named attribute of object in a particular context.
* This configuring can be done in different ways for different
* configurers.
*
* @param object the object
* @param name the attribute name
* @param value the attribute value
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
public void configureAttribute( final Object object,
final String name,
final String value,
final TaskContext context )
throws ConfigurationException
{
doConfigureAttribute( object, name, value, context );
}

/**
* Try to configure content of an object.
*
* @param object the object
* @param content the content value to be set
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
private void configureContent( final Object object,
final String content,
final TaskContext context )
throws ConfigurationException
{
setValue( object, "addContent", content, context );
}

private void doConfigureAttribute( final Object object,
final String name,
final String value,
final TaskContext context )
throws ConfigurationException
{
final String methodName = getMethodNameFor( name );
setValue( object, methodName, value, context );
}

private void setValue( final Object object,
final String methodName,
final String value,
final TaskContext context )
throws ConfigurationException
{
// OMFG the rest of this is soooooooooooooooooooooooooooooooo
// slow. Need to cache results per class etc.

final Class clazz = object.getClass();
final Method[] methods = getMethodsFor( clazz, methodName );
if( 0 == methods.length )
{
final String message =
REZ.getString( "no-attribute-method.error", methodName );
throw new ConfigurationException( message );
}

setValue( object, value, context, methods );
}

private void setValue( final Object object,
final String value,
final TaskContext context,
final Method[] methods )
throws ConfigurationException
{
try
{
final Object objectValue = context.resolveValue( value );
setValue( object, objectValue, methods, context );
}
catch( final TaskException te )
{
final String message =
REZ.getString( "bad-property-resolve.error", value );
throw new ConfigurationException( message, te );
}
}

private void setValue( final Object object,
Object value,
final Method[] methods,
final TaskContext context )
throws ConfigurationException
{
final Class sourceClass = value.getClass();
final String source = sourceClass.getName();

for( int i = 0; i < methods.length; i++ )
{
if( setValue( object, value, methods[ i ], context ) )
{
return;
}
}

final String message =
REZ.getString( "no-can-convert.error", methods[ 0 ].getName(), source );
throw new ConfigurationException( message );
}

private boolean setValue( final Object object,
final Object originalValue,
final Method method,
final TaskContext context )
throws ConfigurationException
{
Class parameterType = method.getParameterTypes()[ 0 ];
if( parameterType.isPrimitive() )
{
parameterType = getComplexTypeFor( parameterType );
}

Object value = originalValue;
try
{
value = m_converter.convert( parameterType, value, context );
}
catch( final ConverterException ce )
{
if( DEBUG )
{
final String message = REZ.getString( "no-converter.error" );
getLogger().debug( message, ce );
}

throw new ConfigurationException( ce.getMessage(), ce );
}
catch( final Exception e )
{
final String message =
REZ.getString( "bad-convert-for-attribute.error", method.getName() );
throw new ConfigurationException( message, e );
}

if( null == value )
{
return false;
}

try
{
method.invoke( object, new Object[]{value} );
}
catch( final IllegalAccessException iae )
{
//should never happen ....
final String message = REZ.getString( "illegal-access.error" );
throw new ConfigurationException( message, iae );
}
catch( final InvocationTargetException ite )
{
final String message = REZ.getString( "invoke-target.error", method.getName() );
throw new ConfigurationException( message, ite );
}

return true;
}

private Class getComplexTypeFor( final Class clazz )
{
if( String.class == clazz )
{
return String.class;
}
else if( Integer.TYPE.equals( clazz ) )
{
return Integer.class;
}
else if( Long.TYPE.equals( clazz ) )
{
return Long.class;
}
else if( Short.TYPE.equals( clazz ) )
{
return Short.class;
}
else if( Byte.TYPE.equals( clazz ) )
{
return Byte.class;
}
else if( Boolean.TYPE.equals( clazz ) )
{
return Boolean.class;
}
else if( Float.TYPE.equals( clazz ) )
{
return Float.class;
}
else if( Double.TYPE.equals( clazz ) )
{
return Double.class;
}
else
{
final String message = REZ.getString( "no-complex-type.error", clazz.getName() );
throw new IllegalArgumentException( message );
}
}

private Method[] getMethodsFor( final Class clazz, final String methodName )
{
final Method[] methods = clazz.getMethods();
final ArrayList matches = new ArrayList();

for( int i = 0; i < methods.length; i++ )
{
final Method method = methods[ i ];
if( methodName.equals( method.getName() ) &&
Method.PUBLIC == ( method.getModifiers() & Method.PUBLIC ) )
{
if( method.getReturnType().equals( Void.TYPE ) )
{
final Class[] parameters = method.getParameterTypes();
if( 1 == parameters.length )
{
matches.add( method );
}
}
}
}

return (Method[])matches.toArray( new Method[ 0 ] );
}

private Method[] getCreateMethodsFor( final Class clazz, final String methodName )
{
final Method[] methods = clazz.getMethods();
final ArrayList matches = new ArrayList();

for( int i = 0; i < methods.length; i++ )
{
final Method method = methods[ i ];
if( methodName.equals( method.getName() ) &&
Method.PUBLIC == ( method.getModifiers() & Method.PUBLIC ) )
{
final Class returnType = method.getReturnType();
if( !returnType.equals( Void.TYPE ) &&
!returnType.isPrimitive() )
{
final Class[] parameters = method.getParameterTypes();
if( 0 == parameters.length )
{
matches.add( method );
}
}
}
}

return (Method[])matches.toArray( new Method[ 0 ] );
}

private String getMethodNameFor( final String attribute )
{
return "set" + getJavaNameFor( attribute.toLowerCase() );
}

private String getJavaNameFor( final String name )
{
final StringBuffer sb = new StringBuffer();

int index = name.indexOf( '-' );
int last = 0;

while( -1 != index )
{
final String word = name.substring( last, index ).toLowerCase();
sb.append( Character.toUpperCase( word.charAt( 0 ) ) );
sb.append( word.substring( 1, word.length() ) );
last = index + 1;
index = name.indexOf( '-', last );
}

index = name.length();
final String word = name.substring( last, index ).toLowerCase();
sb.append( Character.toUpperCase( word.charAt( 0 ) ) );
sb.append( word.substring( 1, word.length() ) );

return sb.toString();
}

private void doConfigureElement( final Object object,
final Configuration configuration,
final TaskContext context )
throws ConfigurationException
{
final String name = configuration.getName();
final String javaName = getJavaNameFor( name );

// OMFG the rest of this is soooooooooooooooooooooooooooooooo
// slow. Need to cache results per class etc.
final Class clazz = object.getClass();
Method[] methods = getMethodsFor( clazz, "add" + javaName );

if( 0 != methods.length )
{
//guess it is first method ????
addElement( object, methods[ 0 ], configuration, context );
}
else
{
methods = getCreateMethodsFor( clazz, "create" + javaName );

if( 0 == methods.length )
{
final String message =
REZ.getString( "no-element-method.error", javaName );
throw new ConfigurationException( message );
}

//guess it is first method ????
createElement( object, methods[ 0 ], configuration, context );
}
}

private void createElement( final Object object,
final Method method,
final Configuration configuration,
final TaskContext context )
throws ConfigurationException
{
try
{
final Object created = method.invoke( object, new Object[ 0 ] );
doConfigureElement( created, configuration, context );
}
catch( final ConfigurationException ce )
{
throw ce;
}
catch( final Exception e )
{
final String message = REZ.getString( "subelement-create.error" );
throw new ConfigurationException( message, e );
}
}

private void addElement( final Object object,
final Method method,
final Configuration configuration,
final TaskContext context )
throws ConfigurationException
{
try
{
final Class clazz = method.getParameterTypes()[ 0 ];
final Object created = clazz.newInstance();

doConfigureElement( created, configuration, context );
method.invoke( object, new Object[]{created} );
}
catch( final ConfigurationException ce )
{
throw ce;
}
catch( final Exception e )
{
final String message = REZ.getString( "subelement-create.error" );
throw new ConfigurationException( message, e );
}
}
}

+ 0
- 57
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ConfigurationState.java View File

@@ -1,57 +0,0 @@
/*
* 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.configurer;

/**
* A default configuration state implementation. Keeps track of which
* of the object's properties have been set.
*
* @author Adam Murdoch
* @version $Revision$ $Date$
*/
class ConfigurationState
{
private final int[] m_propertyCount;
private final ObjectConfigurer m_configurer;
private final Object m_object;

public ConfigurationState( final ObjectConfigurer configurer,
final Object object,
final int propertyCount )
{
m_configurer = configurer;
m_object = object;
m_propertyCount = new int[ propertyCount ];
}

/**
* Returns the configurer being used to configure the object.
*/
public ObjectConfigurer getConfigurer()
{
return m_configurer;
}

/** Returns the object being configured. */
public Object getObject()
{
return m_object;
}

/** Returns a property count. */
public int getPropertyCount( final int index )
{
return m_propertyCount[ index ];
}

/** Increments a property count. */
public void incPropertyCount( final int index )
{
m_propertyCount[ index ]++;
}
}

+ 0
- 645
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultConfigurer.java View File

@@ -1,645 +0,0 @@
/*
* 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.configurer;

import java.util.HashMap;
import java.util.Map;
import org.apache.aut.converter.Converter;
import org.apache.aut.converter.ConverterException;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.framework.DataType;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.role.RoleInfo;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.TypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;

/**
* Class used to configure tasks.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
* @ant.type type="configurer" name="default"
*/
public class DefaultConfigurer
extends AbstractLogEnabled
implements Configurer, Serviceable, LogEnabled
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultConfigurer.class );

///Converter to use for converting between values
private Converter m_converter;

//TypeManager to use to create types in typed adders
private TypeManager m_typeManager;

//RoleManager to use to map from type names -> role shorthand
private RoleManager m_roleManager;

///Cached object configurers. This is a map from Class to the
///ObjectConfigurer for that class.
private Map m_configurerCache = new HashMap();

public void service( final ServiceManager serviceManager )
throws ServiceException
{
m_converter = (Converter)serviceManager.lookup( Converter.ROLE );
m_typeManager = (TypeManager)serviceManager.lookup( TypeManager.ROLE );
m_roleManager = (RoleManager)serviceManager.lookup( RoleManager.ROLE );
}

/**
* Configure a task based on a configuration in a particular context.
* This configuring can be done in different ways for different
* configurers.
* This one does it by first checking if object implements Configurable
* and if it does will pass the task the configuration - else it will use
* mapping rules to map configuration to types
*
* @param object the object
* @param configuration the configuration
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
public void configureElement( final Object object,
final Configuration configuration,
final TaskContext context )
throws ConfigurationException
{
configureElement( object, object.getClass(), configuration, context );
}

public void configureElement( final Object object,
final Class clazz,
final Configuration configuration,
final TaskContext context )
throws ConfigurationException
{
try
{
// Configure the object
configureObject( object, clazz, configuration, context );
}
catch( final ReportableConfigurationException e )
{
// Already have a reasonable error message - so rethrow
throw e.getCause();
}
catch( final Exception e )
{
// Wrap all other errors with general purpose error message
final String message = REZ.getString( "bad-configure-element.error",
configuration.getName() );
throw new ConfigurationException( message, e );
}
}

/**
* Does the work of configuring an object.
*
* @throws ReportableConfigurationException On error. This exception
* indicates that the error has been wrapped with an appropriate
* error message.
* @throws Exception On error
*/
private void configureObject( final Object object,
final Class clazz,
final Configuration configuration,
final TaskContext context )
throws Exception
{
if( object instanceof Configurable )
{
// Let the object configure itself
( (Configurable)object ).configure( configuration );
}
else
{
// Start configuration of the object
final String elemName = configuration.getName();
final ObjectConfigurer configurer = getConfigurer( clazz );
final ConfigurationState state = configurer.startConfiguration( object );

// Set each of the attributes
final String[] attributes = configuration.getAttributeNames();
for( int i = 0; i < attributes.length; i++ )
{
final String name = attributes[ i ];
try
{
// Set the attribute
final String value = configuration.getAttribute( name );
setAttribute( state, name, value, context );
}
catch( final NoSuchPropertyException nspe )
{
final String message =
REZ.getString( "no-such-attribute.error", elemName, name );
throw new ReportableConfigurationException( message );
}
catch( final Exception ce )
{
final String message =
REZ.getString( "bad-set-attribute.error", elemName, name );
throw new ReportableConfigurationException( message, ce );
}
}

// Set the text content
final String content = configuration.getValue( null );
if( null != content && content.length() > 0 )
{
try
{
// Set the content
setContent( state, content, context );
}
catch( final NoSuchPropertyException nspe )
{
final String message =
REZ.getString( "no-content.error", elemName );
throw new ReportableConfigurationException( message );
}
catch( final Exception ce )
{
final String message =
REZ.getString( "bad-set-content.error", elemName );
throw new ReportableConfigurationException( message, ce );
}
}

// Create and configure each of the child elements
final Configuration[] children = configuration.getChildren();
for( int i = 0; i < children.length; i++ )
{
final Configuration childConfig = children[ i ];
final String name = childConfig.getName();
try
{
configureElement( state, childConfig, context );
}
catch( final NoSuchPropertyException nspe )
{
final String message =
REZ.getString( "no-such-element.error", elemName, name );
throw new ReportableConfigurationException( message );
}
catch( final ReportableConfigurationException ce )
{
throw ce;
}
catch( final Exception ce )
{
final String message =
REZ.getString( "bad-configure-element.error", name );
throw new ReportableConfigurationException( message, ce );
}
}

// Finish configuring the object
configurer.finishConfiguration( state );
}
}

/**
* Configure named attribute of object in a particular context.
* This configuring can be done in different ways for different
* configurers.
*
* @param object the object
* @param name the attribute name
* @param value the attribute value
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
public void configureAttribute( final Object object,
final String name,
final String value,
final TaskContext context )
throws ConfigurationException
{
configureAttribute( object, object.getClass(), name, value, context );
}

/**
* Configure named attribute of object in a particular context.
* This configuring can be done in different ways for different
* configurers.
*
* @param object the object
* @param name the attribute name
* @param value the attribute value
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
public void configureAttribute( final Object object,
final Class clazz,
final String name,
final String value,
final TaskContext context )
throws ConfigurationException
{
// Locate the configurer for this object
final ObjectConfigurer configurer = getConfigurer( clazz );

// TODO - this ain't right, the validation is going to be screwed up
final ConfigurationState state = configurer.startConfiguration( object );

// Set the attribute value
try
{
setAttribute( state, name, value, context );
}
catch( final Exception ce )
{
final String message =
REZ.getString( "bad-set-class-attribute.error",
name,
object.getClass().getName() );
throw new ConfigurationException( message, ce );
}

// Finish up
configurer.finishConfiguration( state );
}

/**
* Sets the text content for the element.
*/
private void setContent( final ConfigurationState state,
final String content,
final TaskContext context )
throws Exception
{
// Locate the content configurer
final PropertyConfigurer contentConfigurer = state.getConfigurer().getContentConfigurer();
if( contentConfigurer == null )
{
throw new NoSuchPropertyException();
}

// Set the content
setValue( contentConfigurer, state, content, context );
}

/**
* Configures a property from a nested element.
*/
private void configureElement( final ConfigurationState state,
final Configuration element,
final TaskContext context )
throws Exception
{
final String elementName = element.getName();
if( elementName.toLowerCase().endsWith( "-ref" ) )
{
// A reference
configureReference( state, element, context );
}
else
{
// An inline object
configureInline( state, element, context );
}
}

/**
* Configure a property from an inline object.
*/
private void configureInline( final ConfigurationState state,
final Configuration element,
final TaskContext context )
throws Exception
{
final String name = element.getName();

// Locate the configurer for the child element
final PropertyConfigurer childConfigurer =
getConfigurerFromName( state.getConfigurer(), name, true, true );

// Create & configure the child element
final Object child =
setupChild( state, element, context, childConfigurer );

// Set the child element
childConfigurer.addValue( state, child );
}

/**
* Configures a property from a reference.
*/
private void configureReference( final ConfigurationState state,
final Configuration element,
final TaskContext context )
throws Exception
{
// Extract the id
final String id = element.getAttribute( "id" );
if( 1 != element.getAttributeNames().length ||
0 != element.getChildren().length )
{
final String message = REZ.getString( "extra-config-for-ref.error" );
throw new ConfigurationException( message );
}

// Set the property
final String name = element.getName();
setReference( state, name, id, context, true );
}

/**
* Sets a property using a reference.
*/
private void setReference( final ConfigurationState state,
final String refName,
final String unresolvedId,
final TaskContext context,
final boolean isAdder )
throws Exception
{
// Adjust the name
final String name = refName.substring( 0, refName.length() - 4 );

// Locate the configurer for the property
final PropertyConfigurer configurer =
getConfigurerFromName( state.getConfigurer(), name, false, isAdder );

// Resolve any props in the id
String id = context.resolveValue( unresolvedId ).toString();

// Locate the referenced object
Object ref = context.getProperty( id );
if( null == ref )
{
final String message = REZ.getString( "unknown-reference.error", id );
throw new ConfigurationException( message );
}

// Convert the object, if necessary
final Class type = configurer.getType();
if( !type.isInstance( ref ) )
{
try
{
ref = m_converter.convert( type, ref, context );
}
catch( ConverterException e )
{
final String message = REZ.getString( "mismatch-ref-types.error", id, name );
throw new ConfigurationException( message, e );
}
}

// Set the child element
configurer.addValue( state, ref );
}

/**
* Sets an attribute value.
*/
private void setAttribute( final ConfigurationState state,
final String name,
final String value,
final TaskContext context )
throws Exception
{
// Set the value
final PropertyConfigurer property =
getConfigurerFromName( state.getConfigurer(), name, false, false );
setValue( property, state, value, context );
}

/**
* Sets an attribute value, or an element's text content.
*/
private void setValue( final PropertyConfigurer setter,
final ConfigurationState state,
final String value,
final TaskContext context )
throws Exception
{
// Resolve property references in the attribute value
Object objValue = context.resolveValue( value );

// Convert the value to the appropriate type
final Class type = setter.getType();
if( !type.isInstance( objValue ) )
{
objValue = m_converter.convert( type, objValue, context );
}

// Set the value
setter.addValue( state, objValue );
}

/**
* Locates the configurer for a particular class.
*/
private ObjectConfigurer getConfigurer( final Class clazz )
throws ConfigurationException
{
ObjectConfigurer configurer =
(ObjectConfigurer)m_configurerCache.get( clazz );
if( null == configurer )
{
configurer = DefaultObjectConfigurer.getConfigurer( clazz );
m_configurerCache.put( clazz, configurer );
}
return configurer;
}

/**
* Creates and configures an inline object.
*/
private Object setupChild( final ConfigurationState state,
final Configuration element,
final TaskContext context,
final PropertyConfigurer childConfigurer )
throws Exception
{
final String name = element.getName();
final Class type = childConfigurer.getType();

if( Configuration.class == type )
{
//special case where you have add...(Configuration)
return element;
}

// Create an instance
Object child = null;
if( childConfigurer == state.getConfigurer().getTypedProperty() )
{
// Typed property
child = createTypedObject( name, type );
}
else
{
// Named property
child = createNamedObject( type );
}

// Configure the object
final Object object = child;
configureObject( object, object.getClass(), element, context );

// Convert the object, if necessary
if( !type.isInstance( child ) )
{
child = m_converter.convert( type, child, context );
}

return child;
}

/**
* Determines the property configurer to use for a particular element
* or attribute. If the supplied name matches a property of the
* class being configured, that property configurer is returned. If
* the supplied name matches the role shorthand for the class' typed
* property, then the typed property configurer is used.
*
* @param configurer The configurer for the class being configured.
* @param name The attribute/element name.
*/
private PropertyConfigurer getConfigurerFromName( final ObjectConfigurer configurer,
final String name,
boolean ignoreRoleName,
final boolean isAdder )
throws Exception
{
// Try a named property
if( !isAdder )
{
PropertyConfigurer propertyConfigurer = configurer.getSetter( name );
if( propertyConfigurer != null )
{
return propertyConfigurer;
}
}
else
{
PropertyConfigurer propertyConfigurer = configurer.getAdder( name );
if( propertyConfigurer != null )
{
return propertyConfigurer;
}

// Try a typed property
propertyConfigurer = configurer.getTypedProperty();
if( propertyConfigurer != null )
{
if( ignoreRoleName )
{
return propertyConfigurer;
}
else
{
// Check the role name
final RoleInfo roleInfo =
m_roleManager.getRoleByType( propertyConfigurer.getType() );
if( roleInfo != null && name.equalsIgnoreCase( roleInfo.getShorthand() ) )
{
return propertyConfigurer;
}
}
}
}
// Unknown prop
throw new NoSuchPropertyException();
}

/**
* Creates an instance for a named property.
*/
private Object createNamedObject( final Class type )
throws Exception
{
// Map the expected type to a role. If found, instantiate the default
// type for that role
final RoleInfo roleInfo = m_roleManager.getRoleByType( type );
if( roleInfo != null )
{
final String typeName = roleInfo.getDefaultType();
if( typeName != null )
{
// Create the instance
final TypeFactory factory = m_typeManager.getFactory( roleInfo.getName() );
return factory.create( typeName );
}
}

if( type.isInterface() )
{
// An interface - don't know how to instantiate it
final String message = REZ.getString( "instantiate-interface.error", type.getName() );
throw new ConfigurationException( message );
}

// Use the no-args constructor
return createObject( type );
}

/**
* Creates an instance of the typed property.
*/
private Object createTypedObject( final String name,
final Class type )
throws Exception
{
// Map the expected type to a role. If found, attempt to create
// an instance
final RoleInfo roleInfo = m_roleManager.getRoleByType( type );
if( roleInfo != null )
{
final TypeFactory factory = m_typeManager.getFactory( roleInfo.getName() );
if( factory.canCreate( name ) )
{
return factory.create( name );
}
}

// Use the generic 'data-type' role.
final TypeFactory factory = m_typeManager.getFactory( DataType.ROLE );
if( !factory.canCreate( name ) )
{
throw new NoSuchPropertyException();
}
return factory.create( name );
}

/**
* Utility method to instantiate an instance of the specified class.
*/
private Object createObject( final Class type )
throws Exception
{
try
{
return type.newInstance();
}
catch( final Exception e )
{
final String message =
REZ.getString( "create-object.error",
type.getName() );
throw new ConfigurationException( message, e );
}
}
}

+ 0
- 395
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultObjectConfigurer.java View File

@@ -1,395 +0,0 @@
/*
* 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.configurer;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.ConfigurationException;

/**
* An object configurer which uses reflection to determine the properties
* of a class.
*
* @author <a href="mailto:adammurdoch_ml@yahoo.com">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class DefaultObjectConfigurer
implements ObjectConfigurer
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultObjectConfigurer.class );

private final Class m_class;

/**
* Adder property configurers. (For XML elements)
*/
private final HashMap m_adders = new HashMap();

/**
* Setter property configurers. (For XML attributes)
*/
private final HashMap m_setters = new HashMap();

/**
* The typed property configurer.
*/
private PropertyConfigurer m_typedPropertyConfigurer;

/**
* Content configurer.
*/
private PropertyConfigurer m_contentConfigurer;

/**
* Total number of properties.
*/
private int m_propCount;

/**
* Creates an object configurer for a particular class. The newly
* created configurer will not handle any attributes, elements, or content.
* Use the various <code>enable</code> methods to enable handling of these.
*/
private DefaultObjectConfigurer( final Class classInfo )
{
m_class = classInfo;
}

/**
* Enables all properties and content handling.
*/
private void enableAll()
throws ConfigurationException
{
enableSetters();
enableAdders();
enableTypedAdder();
enableContent();
}

/**
* Enables all setters.
*/
private void enableSetters()
throws ConfigurationException
{
// Locate all the setter methods
final Collection methods = findMethods( "set", false );

// Create a configurer for each setter
final Iterator iterator = methods.iterator();
while( iterator.hasNext() )
{
final Method method = (Method)iterator.next();
final Class type = method.getParameterTypes()[ 0 ];
final String propName = extractName( 3, method.getName() );

final DefaultPropertyConfigurer setter =
new DefaultPropertyConfigurer( getPropertyCount(),
type,
method,
1 );
m_setters.put( propName, setter );
}
}

/**
* Enables all adders.
*/
private void enableAdders()
throws ConfigurationException
{
// Locate all the adder methods
final Collection methods = findMethods( "add", false );

final Iterator iterator = methods.iterator();
while( iterator.hasNext() )
{
final Method method = (Method)iterator.next();
final String methodName = method.getName();

// Skip the text content method
if( methodName.equals( "addContent" ) )
{
continue;
}

final Class type = method.getParameterTypes()[ 0 ];
final String propName = extractName( 3, methodName );

final DefaultPropertyConfigurer configurer =
new DefaultPropertyConfigurer( getPropertyCount(),
type,
method,
Integer.MAX_VALUE );
m_adders.put( propName, configurer );
}
}

/**
* Enables the typed adder.
*/
private void enableTypedAdder()
throws ConfigurationException
{
final Collection methods = findMethods( "add", true );
if( methods.size() == 0 )
{
return;
}

final Method method = (Method)methods.iterator().next();
final Class type = method.getParameterTypes()[ 0 ];

// TODO - this isn't necessary
if( !type.isInterface() )
{
final String message =
REZ.getString( "typed-adder-non-interface.error",
m_class.getName(),
type.getName() );
throw new ConfigurationException( message );
}

m_typedPropertyConfigurer
= new DefaultPropertyConfigurer( getPropertyCount(),
type,
method,
Integer.MAX_VALUE );
}

/**
* Enables text content.
*/
private void enableContent()
throws ConfigurationException
{
// Locate the 'addContent' methods, which return void, and take
// a single parameter.
final Collection methods = findMethods( "addContent", true );
if( methods.size() == 0 )
{
return;
}

final Method method = (Method)methods.iterator().next();
final Class type = method.getParameterTypes()[ 0 ];
m_contentConfigurer = new DefaultPropertyConfigurer( getPropertyCount(),
type,
method,
1 );
}

/**
* Locate all methods whose name starts with a particular
* prefix, and which are non-static, return void, and take a single
* non-array parameter. If there are more than one matching methods of
* a given name, the method that takes a String parameter (if any) is
* ignored. If after that there are more than one matching methods of
* a given name, an exception is thrown.
*
* @return Map from property name -> Method object for that property.
*/
private Collection findMethods( final String prefix,
final boolean exactMatch )
throws ConfigurationException
{
final Map methods = new HashMap();
final List allMethods = findMethodsWithPrefix( prefix, exactMatch );

final Iterator iterator = allMethods.iterator();
while( iterator.hasNext() )
{
final Method method = (Method)iterator.next();
final String methodName = method.getName();
if( Void.TYPE != method.getReturnType() ||
1 != method.getParameterTypes().length ||
method.getParameterTypes()[ 0 ].isArray() )
{
continue;
}

// Extract property name
final Class type = method.getParameterTypes()[ 0 ];

// Add to the adders map
if( methods.containsKey( methodName ) )
{
final Method candidate = (Method)methods.get( methodName );
final Class currentType = candidate.getParameterTypes()[ 0 ];

// Ditch the string version, if any
if( currentType != String.class && type == String.class )
{
// New type is string, and current type is not. Ignore
// the new method
continue;
}
else if( currentType != String.class || type == String.class )
{
// Both are string (which would be odd), or both are not string
final String message =
REZ.getString( "multiple-methods-for-element.error",
m_class.getName(),
methodName );
throw new ConfigurationException( message );
}

// Else, current type is string, and new type is not, so
// continue below, and replace the current method
}

methods.put( methodName, method );
}

return methods.values();
}

private int getPropertyCount()
{
return m_propCount++;
}

/**
* Locates the configurer for a particular class.
*/
public static ObjectConfigurer getConfigurer( final Class classInfo )
throws ConfigurationException
{
final DefaultObjectConfigurer configurer = new DefaultObjectConfigurer( classInfo );
configurer.enableAll();
return configurer;
}

/**
* Starts the configuration of an object.
*/
public ConfigurationState startConfiguration( Object object )
throws ConfigurationException
{
return new ConfigurationState( this, object, getPropertyCount() );
}

/**
* Finishes the configuration of an object, performing any final
* validation and type conversion.
*/
public Object finishConfiguration( final ConfigurationState state )
throws ConfigurationException
{
// Make sure there are no pending created objects
final ConfigurationState defState = (ConfigurationState)state;
return defState.getObject();
}

/**
* Returns a configurer for an element of this class.
*/
public PropertyConfigurer getAdder( final String name )
{
return (PropertyConfigurer)m_adders.get( name );
}

/**
* Returns a configurer for an element of this class.
*/
public PropertyConfigurer getSetter( final String name )
{
return (PropertyConfigurer)m_setters.get( name );
}

/**
* Returns a configurer for the typed property of this class.
*/
public PropertyConfigurer getTypedProperty()
{
return m_typedPropertyConfigurer;
}

/**
* Returns a configurer for the content of this class.
*/
public PropertyConfigurer getContentConfigurer()
{
return m_contentConfigurer;
}

/**
* Extracts a property name from a Java method name.
*
* <p>Removes the prefix, inserts '-' before each uppercase character
* (except the first), then converts all to lowercase.
*/
private String extractName( final int prefixLen, final String methodName )
{
final StringBuffer sb = new StringBuffer( methodName );
sb.delete( 0, prefixLen );

//Contains the index that we are up to in string buffer.
//May not be equal to i as length of string buffer may change
int index = 0;

final int size = sb.length();
for( int i = 0; i < size; i++ )
{
char ch = sb.charAt( index );
if( Character.isUpperCase( ch ) )
{
if( index > 0 )
{
sb.insert( index, '-' );
index++;
}
sb.setCharAt( index, Character.toLowerCase( ch ) );
}
index++;
}
return sb.toString();
}

/**
* Locates all non-static methods whose name starts with a particular
* prefix.
*/
private List findMethodsWithPrefix( final String prefix,
final boolean exactMatch )
{
final ArrayList matches = new ArrayList();
final int prefixLen = prefix.length();
final Method[] methods = m_class.getMethods();
for( int i = 0; i < methods.length; i++ )
{
final Method method = methods[ i ];
final String methodName = method.getName();
if( Modifier.isStatic( method.getModifiers() ) )
{
continue;
}
if( methodName.length() < prefixLen || !methodName.startsWith( prefix ) )
{
continue;
}
if( exactMatch && methodName.length() != prefixLen )
{
continue;
}

matches.add( method );
}
return matches;
}
}

+ 0
- 139
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/DefaultPropertyConfigurer.java View File

@@ -1,139 +0,0 @@
/*
* 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.configurer;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.ConfigurationException;

/**
* The default property configurer implementation, which uses reflection to
* create and set property values.
*
* @author <a href="mailto:adammurdoch_ml@yahoo.com">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class DefaultPropertyConfigurer
implements PropertyConfigurer
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultPropertyConfigurer.class );

private final int m_propertyIndex;
private final Class m_type;
private final Method m_method;
private final int m_maxCount;

public DefaultPropertyConfigurer( final int propIndex,
final Class type,
final Method method,
final int maxCount )
{
m_propertyIndex = propIndex;
if( type.isPrimitive() )
{
m_type = getComplexTypeFor( type );
}
else
{
m_type = type;
}
m_method = method;
m_maxCount = maxCount;

if( null == m_method )
{
throw new NullPointerException( "method" );
}
}

/**
* Returns the type of the element.
*/
public Class getType()
{
return m_type;
}

/**
* Adds a value for this property, to an object.
*/
public void addValue( final ConfigurationState state, final Object value )
throws ConfigurationException
{
final ConfigurationState defState = (ConfigurationState)state;
// Check the property count
if( defState.getPropertyCount( m_propertyIndex ) >= m_maxCount )
{
final String message = REZ.getString( "too-many-values.error" );
throw new ConfigurationException( message );
}
defState.incPropertyCount( m_propertyIndex );

try
{
// Add the value
m_method.invoke( defState.getObject(), new Object[]{value} );
}
catch( final InvocationTargetException ite )
{
final Throwable cause = ite.getTargetException();
throw new ConfigurationException( cause.getMessage(), cause );
}
catch( final Exception e )
{
throw new ConfigurationException( e.getMessage(), e );
}
}

/**
* Determines the complex type for a prmitive type.
*/
private Class getComplexTypeFor( final Class clazz )
{
if( String.class == clazz )
{
return String.class;
}
else if( Integer.TYPE.equals( clazz ) )
{
return Integer.class;
}
else if( Long.TYPE.equals( clazz ) )
{
return Long.class;
}
else if( Short.TYPE.equals( clazz ) )
{
return Short.class;
}
else if( Byte.TYPE.equals( clazz ) )
{
return Byte.class;
}
else if( Boolean.TYPE.equals( clazz ) )
{
return Boolean.class;
}
else if( Float.TYPE.equals( clazz ) )
{
return Float.class;
}
else if( Double.TYPE.equals( clazz ) )
{
return Double.class;
}
else
{
final String message = REZ.getString( "no-complex-type.error", clazz.getName() );
throw new IllegalArgumentException( message );
}
}
}

+ 0
- 19
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/NoSuchPropertyException.java View File

@@ -1,19 +0,0 @@
/*
* 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.configurer;

/**
* A marker exception that is thrown when an unknown property is encountered.
*
* @author Adam Murdoch
* @version $Revision$ $Date$
*/
class NoSuchPropertyException
extends Exception
{
}

+ 0
- 75
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ObjectConfigurer.java View File

@@ -1,75 +0,0 @@
/*
* 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.configurer;

import org.apache.avalon.framework.configuration.ConfigurationException;

/**
* Configures objects of a particular class.
*
* @author <a href="mailto:adammurdoch_ml@yahoo.com">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
interface ObjectConfigurer
{
/**
* Starts the configuration of an object.
*
* @param object The object about to be configured.
* @return The state object, used to track type-specific state during
* configuration.
* @throws ConfigurationException On error starting the configuration.
*/
ConfigurationState startConfiguration( Object object )
throws ConfigurationException;

/**
* Finishes the configuration of an object, performing any final
* validation and type conversion.
*
* @param state The state object.
* @return The configured object.
* @throws ConfigurationException On error finishing the configurtion.
*/
Object finishConfiguration( ConfigurationState state )
throws ConfigurationException;

/**
* Returns a configurer for a atribute property of this class.
*
* @param name The attribute name.
* @return A configurer for the property, or null if the property is not
* valid for this class.
*/
PropertyConfigurer getSetter( String name );

/**
* Returns a configurer for a element property of this class.
*
* @param name The element name.
* @return A configurer for the property, or null if the property is not
* valid for this class.
*/
PropertyConfigurer getAdder( String name );

/**
* Returns a configurer for the text content of this class.
*
* @return A configurer for the text content, or null if the class does not
* support text content.
*/
PropertyConfigurer getContentConfigurer();

/**
* Returns a configurer for the typed property of this class.
*
* @return A configurer for the typed property, or null if the class
* does not have a typed property.
*/
PropertyConfigurer getTypedProperty();
}

+ 0
- 36
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/PropertyConfigurer.java View File

@@ -1,36 +0,0 @@
/*
* 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.configurer;

import org.apache.avalon.framework.configuration.ConfigurationException;

/**
* Configures a property of an object.
* TODO - axe createValue().
*
* @author <a href="mailto:adammurdoch_ml@yahoo.com">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
interface PropertyConfigurer
{
/**
* Returns the type of this property.
*/
Class getType();

/**
* Adds a value for this property, to an object.
*
* @param state The state object, representing the object being configured.
* @param value The property value. This must be assignable to the type
* returned by {@link #getType}.
* @throws ConfigurationException If the property cannot be set.
*/
void addValue( ConfigurationState state, Object value )
throws ConfigurationException;
}

+ 0
- 39
proposal/myrmidon/src/java/org/apache/myrmidon/components/configurer/ReportableConfigurationException.java View File

@@ -1,39 +0,0 @@
/*
* 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.configurer;

import org.apache.avalon.framework.configuration.ConfigurationException;

/**
* A marker exception.
*
* TODO - this should extend ConfigurationException, except it is final.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class ReportableConfigurationException
extends Exception
{
private ConfigurationException m_cause;

public ReportableConfigurationException( String s )
{
m_cause = new ConfigurationException( s );
}

public ReportableConfigurationException( String s, Throwable throwable )
{
m_cause = new ConfigurationException( s, throwable );
}

public ConfigurationException getCause()
{
return m_cause;
}
}

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

@@ -1,17 +0,0 @@
create-object.error=Could not create an object of class {0}.
extra-config-for-ref.error=A reference element can only include an "id" attribute.
mismatch-ref-types.error=Could not convert reference "{0}" to the type expected for property "{1}".
incompatible-element-types.error=Incompatible creator and adder/setter methods found in class {0} for property "{1}".
multiple-methods-for-element.error=Multiple non-String {1}() methods found in class {0}.
too-many-values.error=Too many values for this property.
no-complex-type.error=Can not get complex type for non-primitive type {0}.
no-such-attribute.error=Element <{0}> does not support attribute "{1}".
bad-set-attribute.error=Could not set attribute "{1}" for element <{0}>.
bad-set-class-attribute.error=Could not set attribute "{0}" for object of class {1}.
no-such-element.error=Element <{0}> does not support nested <{1}> elements.
no-content.error=Element <{0} does not support text content.
bad-set-content.error=Could not set text content for element <{0}>.
typed-adder-non-interface.error=The typed adder for class "{0}" must have a single parameter that is an interface rather than {1} which defines a class.
create-typed-object.error=Could not create an object of type "{0}" of class {1}.
unknown-reference.error=Could not find referenced object "{0}".
bad-configure-element.error=Could not configure element <{0}>.

+ 0
- 70
proposal/myrmidon/src/java/org/apache/myrmidon/components/converter/DefaultMasterConverter.java View File

@@ -1,70 +0,0 @@
/*
* 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.converter;

import org.apache.aut.converter.Converter;
import org.apache.aut.converter.AbstractMasterConverter;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
import org.apache.myrmidon.interfaces.type.TypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;

/**
* Converter engine to handle converting between types.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class DefaultMasterConverter
extends AbstractMasterConverter
implements ConverterRegistry, Serviceable
{
private TypeManager m_typeManager;

/**
* Retrieve relevent services needed to deploy.
*
* @param serviceManager the ServiceManager
* @exception ServiceException if an error occurs
*/
public void service( final ServiceManager serviceManager )
throws ServiceException
{
m_typeManager = (TypeManager)serviceManager.lookup( TypeManager.ROLE );
}

/**
* Register a converter
*
* @param className the className of converter
* @param source the source classname
* @param destination the destination classname
*/
public void registerConverter( final String className,
final String source,
final String destination )
{
super.registerConverter( className, source, destination );
}

/**
* Create an instance of converter with specified name.
*
* @param name the name of converter
* @return the created converter instance
* @throws Exception if converter can not be created.
*/
protected Converter createConverter( final String name )
throws Exception
{
final TypeFactory factory = m_typeManager.getFactory( Converter.ROLE );
return (Converter)factory.create( name );
}
}

+ 0
- 289
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DefaultDeployer.java View File

@@ -1,289 +0,0 @@
/*
* 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.URL;
import java.util.HashMap;
import java.util.Map;
import org.apache.aut.converter.Converter;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.myrmidon.interfaces.classloader.ClassLoaderManager;
import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
import org.apache.myrmidon.interfaces.deployer.ConverterDefinition;
import org.apache.myrmidon.interfaces.deployer.Deployer;
import org.apache.myrmidon.interfaces.deployer.DeploymentException;
import org.apache.myrmidon.interfaces.deployer.TypeDefinition;
import org.apache.myrmidon.interfaces.deployer.TypeDeployer;
import org.apache.myrmidon.interfaces.role.RoleInfo;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.service.ServiceFactory;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;

/**
* This class deploys roles, types and services from a typelib.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public class DefaultDeployer
extends AbstractLogEnabled
implements Deployer, Serviceable
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultDeployer.class );

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

/**
* Retrieve relevent services needed to deploy.
*
* @param serviceManager the ServiceManager
* @exception ServiceException if an error occurs
*/
public void service( final ServiceManager serviceManager )
throws ServiceException
{
m_converterRegistry = (ConverterRegistry)serviceManager.lookup( ConverterRegistry.ROLE );
m_typeManager = (TypeManager)serviceManager.lookup( TypeManager.ROLE );
m_roleManager = (RoleManager)serviceManager.lookup( RoleManager.ROLE );
m_classLoaderManager = (ClassLoaderManager)serviceManager.lookup( ClassLoaderManager.ROLE );
}

/**
* Creates a child deployer.
*/
public Deployer createChildDeployer( final ServiceManager componentManager )
throws ServiceException
{
final DefaultDeployer child = new DefaultDeployer();
setupLogger( child );
child.service( componentManager );
return child;
}

/**
* Returns the deployer for a ClassLoader, creating the deployer if
* necessary.
*/
public TypeDeployer createDeployer( final ClassLoader loader )
throws DeploymentException
{
try
{
return createDeployment( loader, null );
}
catch( Exception e )
{
final String message = REZ.getString( "deploy-from-classloader.error", loader );
throw new DeploymentException( message, e );
}
}

/**
* Returns the deployer for a type library, creating the deployer if
* necessary.
*/
public TypeDeployer createDeployer( final File file )
throws DeploymentException
{
try
{
final ClassLoader classLoader = m_classLoaderManager.getClassLoader( file );
return createDeployment( classLoader, file.toURL() );
}
catch( final Exception e )
{
final String message = REZ.getString( "deploy-from-file.error", file );
throw new DeploymentException( message, e );
}
}

/**
* Creates a deployer for a ClassLoader.
*/
private Deployment createDeployment( final ClassLoader loader,
final URL jarUrl )
throws Exception
{
// Locate cached deployer, creating it if necessary
Deployment deployment = (Deployment)m_classLoaderDeployers.get( loader );
if( deployment == null )
{
deployment = new Deployment( this, loader );
setupLogger( deployment );
deployment.loadDescriptors( jarUrl );
m_classLoaderDeployers.put( loader, deployment );
}

return deployment;
}

/**
* Deploys a service.
*/
public void deployService( final Deployment deployment,
final ServiceDefinition definition )
throws Exception
{
final String roleShorthand = definition.getRoleShorthand();
final String roleName = getRole( roleShorthand ).getName();
final String factoryClassName = definition.getFactoryClass();
handleType( deployment, ServiceFactory.ROLE, roleName, factoryClassName );
}

/**
* Handles a type definition.
*/
public void deployType( final Deployment deployment,
final TypeDefinition typeDef )
throws Exception
{
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 );
}

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( deployment, 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
final String roleName = getRole( roleShorthand ).getName();
handleType( deployment, roleName, typeName, className );

if( getLogger().isDebugEnabled() )
{
final String message =
REZ.getString( "register-type.notice", roleShorthand, typeName );
getLogger().debug( message );
}
}
}

/**
* Handles a type definition.
*/
private void handleType( final Deployment deployment,
final String roleName,
final String typeName,
final String className )
throws Exception
{
// TODO - detect duplicates
final DefaultTypeFactory factory = deployment.getFactory( roleName );
factory.addNameClassMapping( typeName, className );
m_typeManager.registerType( roleName, typeName, factory );
}

/**
* Handles a converter definition.
*/
private void handleConverter( final Deployment deployment,
final String className,
final String source,
final String destination )
throws Exception
{
m_converterRegistry.registerConverter( className, source, destination );
final DefaultTypeFactory factory = deployment.getFactory( Converter.ROLE );
factory.addNameClassMapping( className, className );
m_typeManager.registerType( Converter.ROLE, className, factory );

if( getLogger().isDebugEnabled() )
{
final String message =
REZ.getString( "register-converter.notice", source, destination );
getLogger().debug( message );
}
}

/**
* Handles a role definition.
*/
public void deployRole( final Deployment deployment,
final RoleDefinition roleDef )
throws Exception
{
final String name = roleDef.getShortHand();
final String role = roleDef.getRoleName();
final Class type = deployment.getClassLoader().loadClass( role );
final RoleInfo roleInfo = new RoleInfo( role, name, type, null );
m_roleManager.addRole( roleInfo );

if( getLogger().isDebugEnabled() )
{
final String debugMessage = REZ.getString( "register-role.notice", role, name );
getLogger().debug( debugMessage );
}
}

/**
* Locates a role, from its shorthand.
*/
private RoleInfo getRole( final String roleShorthand )
throws DeploymentException
{
final RoleInfo roleInfo = m_roleManager.getRoleByShorthandName( roleShorthand );
if( null == roleInfo )
{
final String message = REZ.getString( "unknown-role4name.error", roleShorthand );
throw new DeploymentException( message );
}
return roleInfo;
}
}

+ 0
- 363
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/Deployment.java View File

@@ -1,363 +0,0 @@
/*
* 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.FileNotFoundException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.myrmidon.interfaces.deployer.DeploymentException;
import org.apache.myrmidon.interfaces.deployer.TypeDefinition;
import org.apache.myrmidon.interfaces.deployer.TypeDeployer;
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory;
import org.xml.sax.XMLReader;

/**
* This class deploys type libraries from a ClassLoader into a registry.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class Deployment
extends AbstractLogEnabled
implements TypeDeployer
{
private static final Resources REZ =
ResourceManager.getPackageResources( Deployment.class );

private static final String TYPE_DESCRIPTOR_NAME = "META-INF/ant-descriptor.xml";
private static final String ROLE_DESCRIPTOR_NAME = "META-INF/ant-roles.xml";
private static final String SERVICE_DESCRIPTOR_NAME = "META-INF/ant-services.xml";

private ClassLoader m_classLoader;
private DefaultDeployer m_deployer;
private TypeDescriptor[] m_descriptors;
private ServiceDescriptor[] m_services;

// TODO - create and configure these in DefaultDeployer
private DescriptorBuilder m_roleBuilder = new RoleDescriptorBuilder();
private DescriptorBuilder m_typeBuilder = new TypeDescriptorBuilder();
private DescriptorBuilder m_serviceBuilder = new ServiceDescriptorBuilder();

/** Map from role Class -> DefaultTypeFactory for that role. */
private Map m_factories = new HashMap();

public Deployment( final DefaultDeployer deployer, final ClassLoader classLoader )
{
m_deployer = deployer;
m_classLoader = classLoader;
}

/**
* Load the descriptors. Deploys all roles, then loads the descriptors
* for, but does not deploy, all the types.
*
* @param jarUrl The URL for the typelib, used to locate the descriptors.
* If null, the resources from the classloader are used.
*/
public void loadDescriptors( final URL jarUrl )
throws Exception
{
// Create a SAX parser to assemble the descriptors into Configuration
// objects
final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
final SAXParser saxParser = saxParserFactory.newSAXParser();
final XMLReader parser = saxParser.getXMLReader();
//parser.setFeature( "http://xml.org/sax/features/namespace-prefixes", false );

final SAXConfigurationHandler handler = new SAXConfigurationHandler();
parser.setContentHandler( handler );
parser.setErrorHandler( handler );

// Build the role descriptors
final ArrayList roleUrls = locateResources( ROLE_DESCRIPTOR_NAME, jarUrl );
final ArrayList roleDescriptors =
buildDescriptors( roleUrls, m_roleBuilder, parser, handler );

// Deploy the roles
// TODO - need to defer this
final int roleCount = roleDescriptors.size();
for( int i = 0; i < roleCount; i++ )
{
final RoleDescriptor descriptor = (RoleDescriptor)roleDescriptors.get( i );
deployRoles( descriptor );
}

// Build the type descriptors
final ArrayList typeUrls = locateResources( TYPE_DESCRIPTOR_NAME, jarUrl );
final ArrayList typeDescriptors =
buildDescriptors( typeUrls, m_typeBuilder, parser, handler );
m_descriptors = (TypeDescriptor[])typeDescriptors.toArray
( new TypeDescriptor[ typeDescriptors.size() ] );

// Build the service descriptors
final ArrayList serviceUrls = locateResources( SERVICE_DESCRIPTOR_NAME, jarUrl );
final ArrayList serviceDescriptors =
buildDescriptors( serviceUrls, m_serviceBuilder, parser, handler );
m_services = (ServiceDescriptor[])serviceDescriptors.toArray
( new ServiceDescriptor[ serviceDescriptors.size() ] );
}

/**
* Returns the type factory for a role.
*/
public DefaultTypeFactory getFactory( final String roleName )
{
DefaultTypeFactory factory = (DefaultTypeFactory)m_factories.get( roleName );

if( null == factory )
{
factory = new DefaultTypeFactory( m_classLoader );
m_factories.put( roleName, factory );
}

return factory;
}

/**
* Returns the classloader for this deployment.
*/
public ClassLoader getClassLoader()
{
return m_classLoader;
}

/**
* Deploys everything in the type library.
*/
public void deployAll()
throws DeploymentException
{
// Deploy types
for( int i = 0; i < m_descriptors.length; i++ )
{
TypeDescriptor descriptor = m_descriptors[ i ];
deployTypes( descriptor );
}

// Deploy services
for( int i = 0; i < m_services.length; i++ )
{
final ServiceDescriptor descriptor = m_services[ i ];
deployServices( descriptor );
}
}

/**
* Deploys a single type in the type library.
*/
public void deployType( final String roleShorthand, final String typeName )
throws DeploymentException
{
try
{
// Locate the definition for the type
for( int i = 0; i < m_descriptors.length; i++ )
{
final TypeDescriptor descriptor = m_descriptors[ i ];
final TypeDefinition[] definitions = descriptor.getDefinitions();
for( int j = 0; j < definitions.length; j++ )
{
TypeDefinition definition = definitions[ j ];
if( definition.getRole().equals( roleShorthand )
&& definition.getName().equals( typeName ) )
{
// Found the definition - deploy it. Note that we
// keep looking for matching types, and let the deployer
// deal with duplicates
m_deployer.deployType( this, definition );
}
}
}
}
catch( Exception e )
{
final String message = REZ.getString( "deploy-type.error", roleShorthand, typeName );
throw new DeploymentException( message, e );
}
}

/**
* Deploys a single type from the type library.
*/
public void deployType( final TypeDefinition typeDef )
throws DeploymentException
{
try
{
m_deployer.deployType( this, typeDef );
}
catch( Exception e )
{
final String message = REZ.getString( "deploy-type.error",
typeDef.getRole(), typeDef.getName() );
throw new DeploymentException( message, e );
}
}

/**
* Builds descriptors.
*/
private ArrayList buildDescriptors( final ArrayList urls,
final DescriptorBuilder builder,
final XMLReader parser,
final SAXConfigurationHandler handler )
throws Exception
{
final ArrayList descriptors = new ArrayList();
final int size = urls.size();
for( int i = 0; i < size; i++ )
{
final String url = (String)urls.get( i );

// Parse the file
parser.parse( url );
final TypelibDescriptor descriptor =
builder.createDescriptor( handler.getConfiguration(), url );
descriptors.add( descriptor );
}

return descriptors;
}

/**
* Locates all resources of a particular name.
*/
private ArrayList locateResources( final String resource, final URL jarUrl )
throws Exception
{
final ArrayList urls = new ArrayList();
if( null != jarUrl )
{
final String systemID = "jar:" + jarUrl + "!/" + resource;
try
{
// Probe the resource
final URL url = new URL( systemID );
url.openStream().close();

// Add to the list
urls.add( systemID );
}
catch( FileNotFoundException e )
{
// Ignore
}
}
else
{
final Enumeration enum = m_classLoader.getResources( resource );
while( enum.hasMoreElements() )
{
urls.add( enum.nextElement().toString() );
}
}

return urls;
}

/**
* Deploys the roles from a role descriptor.
*/
private void deployRoles( final RoleDescriptor descriptor )
throws DeploymentException
{

try
{
if( getLogger().isDebugEnabled() )
{
final String message =
REZ.getString( "url-deploy-roles.notice", descriptor.getUrl() );
getLogger().debug( message );
}

final RoleDefinition[] definitions = descriptor.getDefinitions();
for( int i = 0; i < definitions.length; i++ )
{
final RoleDefinition definition = definitions[ i ];
m_deployer.deployRole( this, definition );
}
}
catch( Exception e )
{
final String message = REZ.getString( "deploy-roles.error", descriptor.getUrl() );
throw new DeploymentException( message, e );
}
}

/**
* Deploys all types from a typelib descriptor.
*/
private void deployTypes( final TypeDescriptor descriptor )
throws DeploymentException
{
try
{
if( getLogger().isDebugEnabled() )
{
final String message =
REZ.getString( "url-deploy-types.notice", descriptor.getUrl() );
getLogger().debug( message );
}

// Deploy all the types
final TypeDefinition[] definitions = descriptor.getDefinitions();
for( int i = 0; i < definitions.length; i++ )
{
final TypeDefinition definition = definitions[ i ];
m_deployer.deployType( this, definition );
}
}
catch( final Exception e )
{
final String message = REZ.getString( "deploy-types.error", descriptor.getUrl() );
throw new DeploymentException( message, e );
}
}

/**
* Deploys all services from a typelib descriptor.
*/
private void deployServices( final ServiceDescriptor descriptor )
throws DeploymentException
{

try
{
if( getLogger().isDebugEnabled() )
{
final String message =
REZ.getString( "url-deploy-services.notice", descriptor.getUrl() );
getLogger().debug( message );
}

// Deploy the services
final ServiceDefinition[] definitions = descriptor.getDefinitions();
for( int i = 0; i < definitions.length; i++ )
{
final ServiceDefinition definition = definitions[ i ];
m_deployer.deployService( this, definition );
}
}
catch( Exception e )
{
final String message = REZ.getString( "deploy-services.error", descriptor.getUrl() );
throw new DeploymentException( message, e );
}
}
}

+ 0
- 27
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/DescriptorBuilder.java View File

@@ -1,27 +0,0 @@
/*
* 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 org.apache.avalon.framework.configuration.Configuration;
import org.apache.myrmidon.interfaces.deployer.DeploymentException;

/**
* Builds a descriptor.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
interface DescriptorBuilder
{
/**
* Builds a descriptor from a set of configuration.
*/
TypelibDescriptor createDescriptor( Configuration config,
String descriptorUrl )
throws DeploymentException;
}

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

@@ -1,27 +0,0 @@
register-converter.notice=Registered converter that converts from {0} to {1}.
register-type.notice=Registered type {0}/{1}.
register-role.notice=Registered role {0} with shorthand name {1}.
url-deploy-types.notice=Registering types from "{0}".
url-deploy-roles.notice=Registering roles from "{0}".
url-deploy-services.notice=Registering services from "{0}".

deploy-from-classloader.error=Could not register types from ClassLoader.
deploy-from-file.error=Could not register types from type library "{0}".
deploy-roles.error=Could not register roles from "{0}".
deploy-types.error=Could not register types from "{0}".
deploy-services.error=Could not register services from "{0}".
deploy-converter.error=Could not register converter that converts from {0} to {1}.
deploy-type.error=Could not register type {0}/{1}.
unknown-role4name.error=Unknown role "{0}".
typedef.no-classname.error=Must specify the classname parameter.
typedef.no-name.error=Must specify name parameter.
typedef.no-role.error=Must specify type parameter.
converterdef.no-source.error=Must specify the source-type parameter.
converterdef.no-destination.error=Must specify the destination-type parameter.
role-descriptor-version.error=Role descriptor version {0} is incompatible with current version {1}.
build-role-descriptor.error=Could not build role descriptor from "{0}".
type-descriptor-version.error=Type library descriptor version {0} is incompatible with current version {1}.
build-type-descriptor.error=Could not build type library descriptor from "{0}".
service-descriptor-version.error=Service descriptor version {0} is incompatible with current version {1}.
build-service-descriptor.error=Could not build service descriptor from "{0}".


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

@@ -1,36 +0,0 @@
/*
* 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;
}
}

+ 0
- 45
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDescriptor.java View File

@@ -1,45 +0,0 @@
/*
* 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.util.ArrayList;
import java.util.List;

/**
* A typelib role descriptor, which defines a set of roles.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class RoleDescriptor
extends TypelibDescriptor
{
private final List m_definitions = new ArrayList();

public RoleDescriptor( final String url )
{
super( url );
}

/**
* Returns the role definitions in the descriptor.
*/
public RoleDefinition[] getDefinitions()
{
return (RoleDefinition[])m_definitions.toArray
( new RoleDefinition[ m_definitions.size() ] );
}

/**
* Adds a role definition to the descriptor.
*/
public void addDefinition( final RoleDefinition def )
{
m_definitions.add( def );
}
}

+ 0
- 70
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/RoleDescriptorBuilder.java View File

@@ -1,70 +0,0 @@
/*
* 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 org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.Version;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.myrmidon.interfaces.deployer.DeploymentException;

/**
* Builds typelib role descriptors.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class RoleDescriptorBuilder
implements DescriptorBuilder
{
private static final Resources REZ =
ResourceManager.getPackageResources( RoleDescriptorBuilder.class );

private static final Version ROLE_DESCRIPTOR_VERSION = new Version( 1, 0, 0 );

/**
* Builds a descriptor from a set of configuration.
*/
public TypelibDescriptor createDescriptor( final Configuration config,
final String url )
throws DeploymentException
{
try
{
// Check version
final String versionString = config.getAttribute( "version" );
final Version version = Version.getVersion( versionString );
if( !ROLE_DESCRIPTOR_VERSION.complies( version ) )
{
final String message = REZ.getString( "role-descriptor-version.error",
version, ROLE_DESCRIPTOR_VERSION );
throw new DeploymentException( message );
}

// Assemble the descriptor
final RoleDescriptor descriptor = new RoleDescriptor( url );

// Extract each of the role elements
final Configuration[] types = config.getChildren( "role" );
for( int i = 0; i < types.length; i++ )
{
final String name = types[ i ].getAttribute( "shorthand" );
final String role = types[ i ].getAttribute( "name" );
final RoleDefinition roleDef = new RoleDefinition( role, name );
descriptor.addDefinition( roleDef );
}

return descriptor;
}
catch( Exception e )
{
final String message = REZ.getString( "build-role-descriptor.error", url );
throw new DeploymentException( message, e );
}
}
}

+ 0
- 56
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDefinition.java View File

@@ -1,56 +0,0 @@
/*
* 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 org.apache.avalon.framework.configuration.Configuration;

/**
* A service definition.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class ServiceDefinition
{
private final String m_roleShorthand;
private final String m_factoryClass;
private final Configuration m_config;

public ServiceDefinition( final String roleShorthand,
final String factoryClass,
final Configuration config )
{
m_roleShorthand = roleShorthand;
m_factoryClass = factoryClass;
m_config = config;
}

/**
* Returns the role that the service implements.
*/
public String getRoleShorthand()
{
return m_roleShorthand;
}

/**
* Returns the name of the factory class for creating the service.
*/
public String getFactoryClass()
{
return m_factoryClass;
}

/**
* Returns the service configuration.
*/
public Configuration getConfig()
{
return m_config;
}
}

+ 0
- 39
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDescriptor.java View File

@@ -1,39 +0,0 @@
/*
* 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.util.ArrayList;
import java.util.List;

/**
* A typelib service descriptor, which defines a set of services.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class ServiceDescriptor
extends TypelibDescriptor
{
private final List m_services = new ArrayList();

public ServiceDescriptor( final String url )
{
super( url );
}

public ServiceDefinition[] getDefinitions()
{
return (ServiceDefinition[])m_services.toArray
( new ServiceDefinition[ m_services.size() ] );
}

public void addDefinition( final ServiceDefinition definition )
{
m_services.add( definition );
}
}

+ 0
- 72
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/ServiceDescriptorBuilder.java View File

@@ -1,72 +0,0 @@
/*
* 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 org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.Version;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.myrmidon.interfaces.deployer.DeploymentException;

/**
* Builds typelib service descriptors.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class ServiceDescriptorBuilder
implements DescriptorBuilder
{
private static final Resources REZ =
ResourceManager.getPackageResources( ServiceDescriptorBuilder.class );

private static final Version SERVICE_DESCRIPTOR_VERSION = new Version( 1, 0, 0 );

/**
* Builds a descriptor from a set of configuration.
*/
public TypelibDescriptor createDescriptor( final Configuration config,
final String url )
throws DeploymentException
{
try
{
// Check version
final String versionString = config.getAttribute( "version" );
final Version version = Version.getVersion( versionString );
if( !SERVICE_DESCRIPTOR_VERSION.complies( version ) )
{
final String message = REZ.getString( "service-descriptor-version.error",
version, SERVICE_DESCRIPTOR_VERSION );
throw new DeploymentException( message );
}

// Build the descriptor
final ServiceDescriptor descriptor = new ServiceDescriptor( url );

// Add the service definitions
final Configuration[] elements = config.getChildren();
for( int i = 0; i < elements.length; i++ )
{
final Configuration element = elements[ i ];
final String roleShorthand = element.getName();
final String factoryClassName = element.getAttribute( "factory" );
final ServiceDefinition definition =
new ServiceDefinition( roleShorthand, factoryClassName, config );
descriptor.addDefinition( definition );
}

return descriptor;
}
catch( Exception e )
{
final String message = REZ.getString( "build-service-descriptor.error", url );
throw new DeploymentException( message, e );
}
}
}

+ 0
- 40
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypeDescriptor.java View File

@@ -1,40 +0,0 @@
/*
* 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.util.ArrayList;
import java.util.List;
import org.apache.myrmidon.interfaces.deployer.TypeDefinition;

/**
* A typelib type descriptor, which defines a set of types.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class TypeDescriptor
extends TypelibDescriptor
{
private final List m_definitions = new ArrayList();

public TypeDescriptor( final String url )
{
super( url );
}

public TypeDefinition[] getDefinitions()
{
return (TypeDefinition[])m_definitions.toArray
( new TypeDefinition[ m_definitions.size() ] );
}

public void addDefinition( final TypeDefinition def )
{
m_definitions.add( def );
}
}

+ 0
- 96
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypeDescriptorBuilder.java View File

@@ -1,96 +0,0 @@
/*
* 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 org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.Version;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.myrmidon.interfaces.deployer.ConverterDefinition;
import org.apache.myrmidon.interfaces.deployer.DeploymentException;
import org.apache.myrmidon.interfaces.deployer.TypeDefinition;

/**
* Builds typelib type descriptors.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class TypeDescriptorBuilder
implements DescriptorBuilder
{
private static final Resources REZ =
ResourceManager.getPackageResources( TypeDescriptorBuilder.class );

private static final Version TYPE_DESCRIPTOR_VERSION = new Version( 1, 0, 0 );

/**
* Builds a descriptor from a set of configuration.
*/
public TypelibDescriptor createDescriptor( final Configuration config,
final String url )
throws DeploymentException
{
try
{
// Check version
final String versionString = config.getAttribute( "version" );
final Version version = Version.getVersion( versionString );
if( !TYPE_DESCRIPTOR_VERSION.complies( version ) )
{
final String message = REZ.getString( "type-descriptor-version.error",
version, TYPE_DESCRIPTOR_VERSION );
throw new DeploymentException( message );
}

// Assemble the descriptor
final TypeDescriptor descriptor = new TypeDescriptor( url );

// Extract each of the types elements
final Configuration[] typeEntries = config.getChild( "types" ).getChildren();
for( int i = 0; i < typeEntries.length; i++ )
{
final Configuration typeEntry = typeEntries[ i ];
final TypeDefinition typeDef = createTypeDefinition( typeEntry );
descriptor.addDefinition( typeDef );
}

return descriptor;
}
catch( Exception e )
{
final String message = REZ.getString( "build-type-descriptor.error", url );
throw new DeploymentException( message, e );
}
}

/**
* Creates a type definition.
*/
private TypeDefinition createTypeDefinition( final Configuration configuration )
throws ConfigurationException
{
final String roleShorthand = configuration.getName();
if( roleShorthand.equals( "converter" ) )
{
// 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 );
}
}
}

+ 0
- 32
proposal/myrmidon/src/java/org/apache/myrmidon/components/deployer/TypelibDescriptor.java View File

@@ -1,32 +0,0 @@
/*
* 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 descriptor from a typelib.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
class TypelibDescriptor
{
private final String m_url;

protected TypelibDescriptor( final String url )
{
m_url = url;
}

/**
* Returns the descriptor URL.
*/
public String getUrl()
{
return m_url;
}
}

+ 0
- 454
proposal/myrmidon/src/java/org/apache/myrmidon/components/embeddor/DefaultEmbeddor.java View File

@@ -1,454 +0,0 @@
/*
* 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.embeddor;

import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.aut.converter.Converter;
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.CascadingException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.myrmidon.interfaces.aspect.AspectManager;
import org.apache.myrmidon.interfaces.builder.ProjectBuilder;
import org.apache.myrmidon.interfaces.classloader.ClassLoaderManager;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.converter.ConverterRegistry;
import org.apache.myrmidon.interfaces.deployer.Deployer;
import org.apache.myrmidon.interfaces.deployer.DeploymentException;
import org.apache.myrmidon.interfaces.deployer.TypeDeployer;
import org.apache.myrmidon.interfaces.embeddor.Embeddor;
import org.apache.myrmidon.interfaces.executor.Executor;
import org.apache.myrmidon.interfaces.executor.ExecutionFrame;
import org.apache.myrmidon.interfaces.executor.ExecutionContainer;
import org.apache.myrmidon.interfaces.extensions.ExtensionManager;
import org.apache.myrmidon.interfaces.model.Project;
import org.apache.myrmidon.interfaces.property.PropertyResolver;
import org.apache.myrmidon.interfaces.property.PropertyStore;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.service.MultiSourceServiceManager;
import org.apache.myrmidon.interfaces.type.TypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;
import org.apache.myrmidon.interfaces.workspace.Workspace;
import org.apache.myrmidon.listeners.ProjectListener;
import org.apache.myrmidon.components.workspace.DefaultExecutionFrame;
import org.apache.myrmidon.components.store.DefaultPropertyStore;

/**
* Default implementation of Embeddor.
* Instantiate this to embed inside other applications.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class DefaultEmbeddor
extends AbstractLogEnabled
implements Embeddor, Contextualizable, Initializable, Startable, Disposable
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultEmbeddor.class );

/** Package containing the default component implementations. */
private static final String PREFIX = "org.apache.myrmidon.components.";

private Deployer m_deployer;
private TypeManager m_typeManager;
private MultiSourceServiceManager m_workspaceServiceManager;

private List m_components = new ArrayList();
private DefaultServiceManager m_serviceManager = new DefaultServiceManager();
private Context m_context;

/**
* Setup basic properties of engine.
* Called before init() and can be used to specify alternate components in system.
*/
public void contextualize( final Context context ) throws ContextException
{
m_context = context;
}

/**
* Builds a project.
*/
public Project createProject( final String location,
final String type,
final Parameters parameters )
throws Exception
{
try
{
String projectType = type;
if( null == projectType )
{
projectType = FileUtil.getExtension( location );
}

// TODO - reuse the project builders, or dispose them
final ProjectBuilder builder = getProjectBuilder( projectType, parameters );
return builder.build( location );
}
catch( final Exception e )
{
final String message = REZ.getString( "create-project.error", location );
throw new CascadingException( message, e );
}
}

/**
* Creates a project builder for a project type.
*/
private ProjectBuilder getProjectBuilder( final String type,
final Parameters parameters )
throws Exception
{
final TypeFactory factory = m_typeManager.getFactory( ProjectBuilder.ROLE );
final ProjectBuilder builder = (ProjectBuilder)factory.create( type );
setupObject( builder, m_serviceManager, parameters );
return builder;
}

/**
* Creates a workspace.
*/
public Workspace createWorkspace( final Map properties )
throws Exception
{
final Workspace workspace =
(Workspace)createService( Workspace.class, PREFIX + "workspace.DefaultWorkspace" );
setupObject( workspace, m_workspaceServiceManager, null );

// Create the property store
final PropertyStore propStore = createBaseStore( properties );

// Create an execution frame, and attach it to the workspace
final ExecutionFrame frame =
new DefaultExecutionFrame( getLogger(),
propStore,
m_workspaceServiceManager);
( (ExecutionContainer)workspace ).setRootExecutionFrame( frame );

// TODO - should keep track of workspaces, to dispose them later
return workspace;
}

/**
* Creates a project listener.
*
* @param name The shorthand name of the listener.
* @return the listener.
*/
public ProjectListener createListener( final String name )
throws Exception
{
final TypeFactory factory = m_typeManager.getFactory( ProjectListener.ROLE );
return (ProjectListener)factory.create( name );
}

/**
* Initialize the system.
*
* @exception Exception if an error occurs
*/
public void initialize()
throws Exception
{
// setup the root components
setupComponents();

// locate the components we need
m_deployer = (Deployer)m_serviceManager.lookup( Deployer.ROLE );
m_typeManager = (TypeManager)m_serviceManager.lookup( TypeManager.ROLE );

// setup a service manager that creates the project services
final ServiceManager projServiceManager
= (ServiceManager)createService( ServiceManager.class,
PREFIX + "service.InstantiatingServiceManager" );
setupObject( projServiceManager, m_serviceManager, null );
m_components.add( projServiceManager );

// setup a service manager to be used by workspaces
m_workspaceServiceManager = new MultiSourceServiceManager();
m_workspaceServiceManager.add( projServiceManager );
m_workspaceServiceManager.add( m_serviceManager );
}

public void start()
throws Exception
{
// Deploy all type libraries found in the classpath
final ClassLoader libClassloader = getClass().getClassLoader();
final TypeDeployer typeDeployer = m_deployer.createDeployer( libClassloader );
typeDeployer.deployAll();

// Deploy all type libraries in the lib directory
final ExtensionFileFilter filter = new ExtensionFileFilter( ".atl" );
final File[] taskLibDirs = (File[])m_context.get( "myrmidon.lib.path" );
deployFromDirectories( m_deployer, taskLibDirs, filter );
}

/**
* Stops the engine.
*/
public void stop()
{
//TODO - Undeploy all the tasks by killing ExecutionFrame???
}

/**
* Dispose engine.
*/
public void dispose()
{
// Dispose any disposable components
for( Iterator iterator = m_components.iterator(); iterator.hasNext(); )
{
Object component = iterator.next();
if( component instanceof Disposable )
{
final Disposable disposable = (Disposable)component;
disposable.dispose();
}
}

// Ditch everything
m_components = null;
m_deployer = null;
m_serviceManager = null;
m_context = null;
}

/**
* Create all required components.
*/
private void setupComponents()
throws Exception
{
// Create the components
createComponent( ExtensionManager.class, PREFIX + "extensions.DefaultExtensionManager" );
final Object converter =
createComponent( Converter.class, PREFIX + "converter.DefaultMasterConverter" );
m_serviceManager.put( ConverterRegistry.ROLE, converter );
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 + "classloader.DefaultClassLoaderManager" );
createComponent( Executor.class, PREFIX + "executor.AspectAwareExecutor" );
createComponent( PropertyResolver.class, PREFIX + "property.DefaultPropertyResolver" );

m_serviceManager.put( Embeddor.ROLE, this );

// Setup the components
for( Iterator iterator = m_components.iterator(); iterator.hasNext(); )
{
final Object component = iterator.next();
setupObject( component, m_serviceManager, null );
}
}

/**
* Creates a component.
*/
private Object createComponent( final Class roleType,
final String defaultImpl )
throws Exception
{
final Object component = createService( roleType, defaultImpl );
m_serviceManager.put( roleType.getName(), component );
m_components.add( component );
return component;
}

/**
* Create a component that implements an interface.
*
* @param roleType the name of interface/type
* @param defaultImpl the classname of the default implementation
* @return the created object
* @exception Exception if an error occurs
*/
private Object createService( final Class roleType, final String defaultImpl )
throws Exception
{
// TODO - need to be able to provide different implementations
final String className = defaultImpl;

try
{
final Object object = Class.forName( className ).newInstance();

if( !roleType.isInstance( object ) )
{
final String message = REZ.getString( "bad-type.error",
className, roleType.getName() );
throw new Exception( message );
}

return object;
}
catch( final IllegalAccessException iae )
{
final String message = REZ.getString( "bad-ctor.error",
roleType.getName(), className );
throw new Exception( message );
}
catch( final InstantiationException ie )
{
final String message =
REZ.getString( "no-instantiate.error", roleType.getName(), className );
throw new Exception( message );
}
catch( final ClassNotFoundException cnfe )
{
final String message =
REZ.getString( "no-class.error", roleType.getName(), className );
throw new Exception( message );
}
}

/**
* Sets-up an object by running it through the log-enable, compose,
* parameterise and initialise lifecycle stages.
*/
private void setupObject( final Object object,
final ServiceManager serviceManager,
final Parameters parameters )
throws Exception
{
setupLogger( object );

if(object instanceof Contextualizable )
{
( (Contextualizable)object ).contextualize( m_context );

}
if( object instanceof Serviceable )
{
( (Serviceable)object ).service( serviceManager );
}

if( parameters != null && object instanceof Parameterizable )
{
( (Parameterizable)object ).parameterize( parameters );
}

if( object instanceof Initializable )
{
( (Initializable)object ).initialize();
}
}

/**
* Deploys all type libraries in a directory.
*/
private void deployFromDirectories( final Deployer deployer,
final File[] directories,
final FilenameFilter filter )
throws DeploymentException
{
for( int i = 0; i < directories.length; i++ )
{
File directory = directories[i ];
final File[] files = directory.listFiles( filter );

if( null != files )
{
deployFiles( deployer, files );
}
}
}

/**
* Deploys a set of type libraries.
*/
private void deployFiles( final Deployer deployer, final File[] files )
throws DeploymentException
{
for( int i = 0; i < files.length; i++ )
{
final String filename = files[ i ].getName();

int index = filename.lastIndexOf( '.' );
if( -1 == index )
{
index = filename.length();
}

try
{
final File file = files[ i ].getCanonicalFile();
final TypeDeployer typeDeployer = deployer.createDeployer( file );
typeDeployer.deployAll();
}
catch( final DeploymentException de )
{
throw de;
}
catch( final Exception e )
{
final String message = REZ.getString( "bad-filename.error", files[ i ] );
throw new DeploymentException( message, e );
}
}
}

/**
* Creates the root property store for a workspace
*/
private PropertyStore createBaseStore( final Map properties )
throws Exception
{
final DefaultPropertyStore store = new DefaultPropertyStore();

addToStore( store, properties );

//Add system properties so that they overide user-defined properties
addToStore( store, System.getProperties() );

return store;
}

/**
* Helper method to add values to a store.
*
* @param store the store
* @param map the map of names->values
*/
private void addToStore( final PropertyStore store, final Map map )
throws Exception
{
final Iterator keys = map.keySet().iterator();

while( keys.hasNext() )
{
final String key = (String)keys.next();
final Object value = map.get( key );
store.setProperty( key, value );
}
}
}

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

@@ -1,6 +0,0 @@
bad-type.error=Object {0} is not an instance of {1}.
bad-ctor.error=Non-public constructor for {0} {1}.
no-instantiate.error=Error instantiating class for {0} {1}.
no-class.error=Could not find the class for {0} ({1}).
bad-filename.error=Unable to retrieve filename for file {0}.
create-project.error=Could not load the project definition from {0}.

+ 0
- 337
proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/AspectAwareExecutor.java View File

@@ -1,337 +0,0 @@
/*
* 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.executor;

import java.util.ArrayList;
import java.util.HashMap;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.myrmidon.api.Task;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.interfaces.aspect.AspectManager;
import org.apache.myrmidon.interfaces.executor.ExecutionFrame;

/**
* The AspectAwareExecutor executes the tasks but also calls
* the aspects helpers.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class AspectAwareExecutor
extends DefaultExecutor
implements Serviceable
{
private static final Resources REZ =
ResourceManager.getPackageResources( AspectAwareExecutor.class );

private static final Configuration[] EMPTY_ELEMENTS = new Configuration[ 0 ];

private AspectManager m_aspectManager;

/**
* Retrieve relevent services.
*
* @param serviceManager the ServiceManager
* @exception ServiceException if an error occurs
*/
public void service( final ServiceManager serviceManager )
throws ServiceException
{
m_aspectManager = (AspectManager)serviceManager.lookup( AspectManager.ROLE );
}

public void execute( final Configuration taskModel, final ExecutionFrame frame )
throws TaskException
{
try
{
executeTask( taskModel, frame );
}
catch( final TaskException te )
{
final boolean isError = getAspectManager().error( te );
if( !isError )
{
throw te;
}
}
}

private void executeTask( final Configuration model,
final ExecutionFrame frame )
throws TaskException
{
try
{
Configuration taskModel = getAspectManager().preCreate( model );
taskModel = prepareAspects( taskModel );

final String taskName = taskModel.getName();
debug( "creating.notice", taskName );
final Task task = doCreateTask( taskName, frame );
getAspectManager().postCreate( task );

debug( "logger.notice", taskName );
final Logger logger = frame.getLogger();
getAspectManager().preLogEnabled( logger );

debug( "contextualizing.notice", taskName );
final TaskContext context = doCreateContext( frame );
doContextualize( task, taskModel, context, frame );

debug( "configuring.notice", taskName );
getAspectManager().preConfigure( taskModel );
doConfigure( task, taskModel, context, frame );

debug( "executing.notice", taskName );
getAspectManager().preExecute();
doExecute( taskModel, task );
getAspectManager().preDestroy();
}
catch( Exception e )
{
// Wrap in generic error message
final String message = REZ.getString( "execute.error",
model.getName(),
model.getLocation() );
throw new TaskException( message, e );
}
}

protected void doExecute( final Configuration taskModel, final Task task )
throws TaskException
{
task.execute();
}

//TODO: Extract and clean taskModel here.
//Get all parameters from model and provide to appropriate aspect.
//aspect( final Parameters parameters, final Configuration[] elements )
private final Configuration prepareAspects( final Configuration taskModel )
throws TaskException
{
final DefaultConfiguration newTaskModel =
new DefaultConfiguration( taskModel.getName(), taskModel.getLocation() );
final HashMap parameterMap = new HashMap();
final HashMap elementMap = new HashMap();

processAttributes( taskModel, newTaskModel, parameterMap );
processElements( taskModel, newTaskModel, elementMap );
try
{
newTaskModel.setValue( taskModel.getValue() );
}
catch( final ConfigurationException cee )
{
//Will never occur
}

dispatchAspectsSettings( parameterMap, elementMap );
checkForUnusedSettings( parameterMap, elementMap );

return newTaskModel;
}

private final void dispatchAspectsSettings( final HashMap parameterMap,
final HashMap elementMap )
throws TaskException
{
final String[] names = getAspectManager().getNames();

for( int i = 0; i < names.length; i++ )
{
final ArrayList elementList = (ArrayList)elementMap.remove( names[ i ] );

Parameters parameters = (Parameters)parameterMap.remove( names[ i ] );
if( null == parameters )
{
parameters = Parameters.EMPTY_PARAMETERS;
}

Configuration[] elements = null;
if( null == elementList )
{
elements = EMPTY_ELEMENTS;
}
else
{
elements = (Configuration[])elementList.toArray( EMPTY_ELEMENTS );
}

dispatch( names[ i ], parameters, elements );
}
}

private final void checkForUnusedSettings( final HashMap parameterMap,
final HashMap elementMap )
throws TaskException
{
if( 0 != parameterMap.size() )
{
final String[] namespaces =
(String[])parameterMap.keySet().toArray( new String[ 0 ] );

for( int i = 0; i < namespaces.length; i++ )
{
final String namespace = namespaces[ i ];
final Parameters parameters = (Parameters)parameterMap.get( namespace );
final ArrayList elementList = (ArrayList)elementMap.remove( namespace );

Configuration[] elements = null;

if( null == elementList )
{
elements = EMPTY_ELEMENTS;
}
else
{
elements = (Configuration[])elementList.toArray( EMPTY_ELEMENTS );
}

unusedSetting( namespace, parameters, elements );
}
}

if( 0 != elementMap.size() )
{
final String[] namespaces =
(String[])elementMap.keySet().toArray( new String[ 0 ] );

for( int i = 0; i < namespaces.length; i++ )
{
final String namespace = namespaces[ i ];
final ArrayList elementList = (ArrayList)elementMap.remove( namespace );
final Configuration[] elements =
(Configuration[])elementList.toArray( EMPTY_ELEMENTS );

unusedSetting( namespace, Parameters.EMPTY_PARAMETERS, elements );
}
}
}

private void unusedSetting( final String namespace,
final Parameters parameters,
final Configuration[] elements )
throws TaskException
{
final String message =
REZ.getString( "unused-settings.error",
namespace,
Integer.toString( parameters.getNames().length ),
Integer.toString( elements.length ) );
throw new TaskException( message );
}

private void dispatch( final String namespace,
final Parameters parameters,
final Configuration[] elements )
throws TaskException
{
getAspectManager().dispatchAspectSettings( namespace, parameters, elements );

if( getLogger().isDebugEnabled() )
{
final String message =
REZ.getString( "dispatch-settings.notice",
namespace,
Integer.toString( parameters.getNames().length ),
Integer.toString( elements.length ) );
getLogger().debug( message );
}
}

private final void processElements( final Configuration taskModel,
final DefaultConfiguration newTaskModel,
final HashMap map )
{
final Configuration[] elements = taskModel.getChildren();
for( int i = 0; i < elements.length; i++ )
{
final String name = elements[ i ].getName();
final int index = name.indexOf( ':' );

if( -1 == index )
{
newTaskModel.addChild( elements[ i ] );
}
else
{
final String namespace = name.substring( 0, index );
final ArrayList elementSet = getElements( namespace, map );
elementSet.add( elements[ i ] );
}
}
}

private final void processAttributes( final Configuration taskModel,
final DefaultConfiguration newTaskModel,
final HashMap map )
{
final String[] attributes = taskModel.getAttributeNames();
for( int i = 0; i < attributes.length; i++ )
{
final String name = attributes[ i ];
final String value = taskModel.getAttribute( name, null );

final int index = name.indexOf( ':' );

if( -1 == index )
{
newTaskModel.setAttribute( name, value );
}
else
{
final String namespace = name.substring( 0, index );
final String localName = name.substring( index + 1 );
final Parameters parameters = getParameters( namespace, map );
parameters.setParameter( localName, value );
}
}
}

private final ArrayList getElements( final String namespace, final HashMap map )
{
ArrayList elements = (ArrayList)map.get( namespace );

if( null == elements )
{
elements = new ArrayList();
map.put( namespace, elements );
}

return elements;
}

private final Parameters getParameters( final String namespace, final HashMap map )
{
Parameters parameters = (Parameters)map.get( namespace );

if( null == parameters )
{
parameters = new Parameters();
map.put( namespace, parameters );
}

return parameters;
}

private final AspectManager getAspectManager()
{
return m_aspectManager;
}
}

+ 0
- 141
proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/DefaultExecutor.java View File

@@ -1,141 +0,0 @@
/*
* 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.executor;

import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.myrmidon.api.Task;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.components.workspace.DefaultTaskContext;
import org.apache.myrmidon.interfaces.configurer.Configurer;
import org.apache.myrmidon.interfaces.executor.ExecutionFrame;
import org.apache.myrmidon.interfaces.executor.Executor;
import org.apache.myrmidon.interfaces.type.TypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;

/**
* The basic executor that just executes the tasks.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class DefaultExecutor
extends AbstractLogEnabled
implements Executor
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultExecutor.class );

/**
* Executes a task.
*/
public void execute( final Configuration taskModel, final ExecutionFrame frame )
throws TaskException
{
final String taskName = taskModel.getName();
try
{
debug( "creating.notice", taskName );
final Task task = doCreateTask( taskName, frame );

debug( "contextualizing.notice", taskName );
final TaskContext context = doCreateContext( frame );
doContextualize( task, taskModel, context, frame );

debug( "configuring.notice", taskName );
doConfigure( task, taskModel, context, frame );

debug( "executing.notice", taskName );
task.execute();
}
catch( Exception e )
{
// Wrap in generic error message
final String message = REZ.getString( "execute.error",
taskName, taskModel.getLocation() );
throw new TaskException( message, e );
}
}

protected final void debug( final String key, final String taskName )
{
if( getLogger().isDebugEnabled() )
{
final String message = REZ.getString( key, taskName );
getLogger().debug( message );
}
}

/**
* Creates a context for the task.
*/
protected TaskContext doCreateContext( final ExecutionFrame frame )
{
// TODO - need to deactivate the context once the task has finished
// executing
return new DefaultTaskContext( frame.getServiceManager(),
frame.getLogger(),
frame.getProperties() );
}

/**
* Creates a task instance.
*/
protected final Task doCreateTask( final String name, final ExecutionFrame frame )
throws TaskException
{
try
{
final TypeManager typeManager = (TypeManager)frame.getServiceManager().lookup( TypeManager.ROLE );
final TypeFactory factory = typeManager.getFactory( Task.ROLE );
return (Task)factory.create( name );
}
catch( final Exception te )
{
final String message = REZ.getString( "create.error", name );
throw new TaskException( message, te );
}
}

/**
* Configures a task instance.
*/
protected final void doConfigure( final Task task,
final Configuration taskModel,
final TaskContext taskContext,
final ExecutionFrame frame )
throws Exception
{
final Configurer configurer = (Configurer)frame.getServiceManager().lookup( Configurer.ROLE );
configurer.configureElement( task, taskModel, taskContext );
}

/**
* Sets the context for a task.
*/
protected final void doContextualize( final Task task,
final Configuration taskModel,
final TaskContext taskContext,
final ExecutionFrame frame )
throws TaskException
{
try
{
task.contextualize( taskContext );
}
catch( final Throwable throwable )
{
final String message =
REZ.getString( "contextualize.error", taskModel.getName() );
throw new TaskException( message, throwable );
}
}
}

+ 0
- 81
proposal/myrmidon/src/java/org/apache/myrmidon/components/executor/PrintingExecutor.java View File

@@ -1,81 +0,0 @@
/*
* 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.executor;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.myrmidon.api.Task;
import org.apache.myrmidon.api.TaskException;

/**
* An executor that just displays the tasks rather than executing them.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class PrintingExecutor
extends AspectAwareExecutor
{
protected void doExecute( final Configuration taskModel, final Task task )
throws TaskException
{
final StringBuffer sb = new StringBuffer();
printConfiguration( taskModel, 0, sb );

System.out.println( sb.toString() );
}

private void printConfiguration( final Configuration taskModel,
final int level,
final StringBuffer sb )
{
for( int i = 0; i < level; i++ )
{
sb.append( ' ' );
}

sb.append( '<' );
sb.append( taskModel.getName() );

final String[] names = taskModel.getAttributeNames();
for( int i = 0; i < names.length; i++ )
{
final String name = names[ i ];
final String value = taskModel.getAttribute( name, null );

sb.append( ' ' );
sb.append( name );
sb.append( "=\"" );
sb.append( value );
sb.append( '\"' );
}

final Configuration[] children = taskModel.getChildren();
if( 0 == children.length )
{
sb.append( "/>\n" );
}
else
{
sb.append( ">\n" );

for( int i = 0; i < children.length; i++ )
{
printConfiguration( children[ i ], level + 1, sb );
}

for( int i = 0; i < level; i++ )
{
sb.append( ' ' );
}

sb.append( "</" );
sb.append( taskModel.getName() );
sb.append( ">\n" );
}
}
}

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

@@ -1,11 +0,0 @@
creating.notice=Creating {0}.
contextualizing.notice=Contextualizing {0}.
configuring.notice=Configuring {0}.
executing.notice=Executing {0}.

create.error=Could not create task <{0}>.
contextualize.error=Could not set the context for task <{0}>.
execute.error={1}: Could not execute task <{0}>.

unused-settings.error=Unused aspect settings for namespace {0} (parameterCount={1} elementCount={2}).
dispatch-settings.notice=Dispatching Aspect Settings to namespace {0} (parameterCount={1} elementCount={2}).

+ 0
- 162
proposal/myrmidon/src/java/org/apache/myrmidon/components/extensions/DefaultExtensionManager.java View File

@@ -1,162 +0,0 @@
/*
* 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.extensions;

import java.io.File;
import org.apache.avalon.excalibur.extension.DefaultPackageRepository;
import org.apache.avalon.excalibur.extension.Extension;
import org.apache.avalon.excalibur.extension.OptionalPackage;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.apache.myrmidon.interfaces.extensions.ExtensionManager;

/**
* PhoenixPackageRepository
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class DefaultExtensionManager
extends DefaultPackageRepository
implements LogEnabled, Contextualizable, Initializable, Disposable, ExtensionManager
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultExtensionManager.class );

/**
* The standard location of tools.jar for IBM/Sun JDKs.
*/
private static final String TOOLS_JAR =
File.separator + "lib" + File.separator + "tools.jar";

/**
* The path relative to JRE in which tools.jar is located.
*/
private static final String DEBIAN_TOOLS_JAR =
File.separator + ".." + File.separator + "j2sdk1.3" +
File.separator + "lib" + File.separator + "tools.jar";

private Logger m_logger;
private File[] m_path;

public DefaultExtensionManager()
{
super( new File[ 0 ] );
}

public DefaultExtensionManager( final File[] path )
{
super( path );
}

public void enableLogging( final Logger logger )
{
m_logger = logger;
}

public void contextualize( final Context context ) throws ContextException
{
m_path = (File[])context.get( "myrmidon.ext.path" );
}

public void initialize()
throws Exception
{
setPath( m_path );
scanPath();

// Add the JVM's tools.jar as an extension
final Extension extension = createToolsExtension();
final File jar = getToolsJar();
final Extension[] available = new Extension[]{extension};
final Extension[] required = new Extension[ 0 ];
final OptionalPackage toolsPackage = new OptionalPackage( jar, available, required );
cacheOptionalPackage( toolsPackage );
}

public void dispose()
{
clearCache();
}

/**
* Locates the optional package which best matches a required extension.
*
* @param extension the extension to locate an optional package
* @return the optional package, or null if not found.
*/
public OptionalPackage getOptionalPackage( final Extension extension )
{
final OptionalPackage[] packages = getOptionalPackages( extension );

if( null == packages || 0 == packages.length ) return null;

//TODO: Use heurisitic to find which is best package

return packages[ 0 ];
}

protected void debug( final String message )
{
m_logger.debug( message );
}

private File getToolsJar()
throws Exception
{
final String javaHome = System.getProperty( "java.home" );
String jdkHome;
if( javaHome.endsWith( "jre" ) )
{
jdkHome = javaHome.substring( 0, javaHome.length() - 4 );
}
else
{
jdkHome = javaHome;
}

//We need to search through a few locations to locate tools.jar
File tools = new File( jdkHome + TOOLS_JAR );
if( tools.exists() )
{
return tools;
}

//The path to tools.jar. In some cases $JRE_HOME is not equal to
//$JAVA_HOME/jre. For example, on Debian, IBM's j2sdk1.3 .deb puts
//the JRE in /usr/lib/j2sdk1.3, and the JDK in /usr/lib/j2re1.3,
//tools.jar=${java.home}/../j2sdk1.3/lib/tools.jar
tools = new File( jdkHome + DEBIAN_TOOLS_JAR );

if( !tools.exists() )
{
final String message = REZ.getString( "extension.missing-tools.error" );
throw new Exception( message );
}

return tools;
}

private static Extension createToolsExtension()
{
return new Extension( "com.sun.tools",
"1.0",
"com.sun",
"1.0",
"com.sun",
"com.sun",
null );
}
}

+ 0
- 49
proposal/myrmidon/src/java/org/apache/myrmidon/components/property/ClassicPropertyResolver.java View File

@@ -1,49 +0,0 @@
/*
* 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.property;

import org.apache.myrmidon.interfaces.property.PropertyResolver;
import org.apache.myrmidon.interfaces.property.PropertyStore;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.api.TaskContext;

/**
* A {@link PropertyResolver} implementation which resolves properties
* as per Ant1, ignoring undefined properties.
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*
* @ant.type type="property-resolver" name="classic"
*/
public class ClassicPropertyResolver
extends DefaultPropertyResolver
implements PropertyResolver
{
/**
* Retrieve a value from the specified context using the specified key.
* If there is no such value, returns the original property reference.
*
* @param propertyName the name of the property to retrieve
* @param context the set of known properties
*/
protected Object getPropertyValue( final String propertyName,
final TaskContext context )
throws TaskException
{
final Object value = context.getProperty( propertyName );
if( value != null )
{
return value;
}
else
{
return "${" + propertyName + "}";
}
}
}

+ 0
- 290
proposal/myrmidon/src/java/org/apache/myrmidon/components/property/DefaultPropertyResolver.java View File

@@ -1,290 +0,0 @@
/*
* 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.property;

import org.apache.aut.converter.Converter;
import org.apache.aut.converter.ConverterException;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.interfaces.property.PropertyResolver;
import org.apache.myrmidon.interfaces.property.PropertyStore;

/**
* Base class for PropertyResolver implementations.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*
* @ant.type type="property-resolver" name="default"
*/
public class DefaultPropertyResolver
implements PropertyResolver, Serviceable
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultPropertyResolver.class );

private Converter m_converter;

public void service( final ServiceManager serviceManager ) throws ServiceException
{
m_converter = (Converter)serviceManager.lookup( Converter.ROLE );
}

/**
* Resolve a string property. This evaluates all property
* substitutions based on specified context.
*
* If the content contains a single property reference, then the property value
* <code>Object</code> itself is returned.
* Otherwise, a <code>String</code> is returned, comprising the supplied
* content, with all property references replaced with the result of
* <code>toString()</code> called on the property value.
*
* @param content the property to resolve
* @param context the context in which to resolve property
* @return the reolved property
* @exception TaskException if an error occurs
*/
public Object resolveProperties( final String content,
final TaskContext context )
throws TaskException
{
int start = findNextProperty( content, 0 );
if( -1 == start )
{
return content;
}

int end = findEnding( content, start );

final int length = content.length();

if( 0 == start && end == ( length - 1 ) )
{
return getPropertyValue( content.substring( start + 2, end ),
context );
}

final StringBuffer sb = new StringBuffer( length * 2 );
int lastPlace = 0;

while( true )
{
final String propertyValue =
getPropertyStringValue( content.substring( start + 2, end ),
context );

sb.append( content.substring( lastPlace, start ) );
sb.append( propertyValue );

lastPlace = end + 1;

start = findNextProperty( content, lastPlace );
if( -1 == start )
{
break;
}

end = findEnding( content, start );
}

sb.append( content.substring( lastPlace, length ) );

return sb.toString();
}

/**
* Resolve a string property. This recursively evaluates all property
* substitutions based on specified context.
*
* @param content the property to resolve
* @param context the context in which to resolve property
* @return the reolved property
* @exception TaskException if an error occurs
*/
private Object recursiveResolveProperty( final String content,
final TaskContext context )
throws TaskException
{
int start = findNextProperty( content, 0 );
if( -1 == start )
{
return content;
}

int end = findNestedEnding( content, start );

final int length = content.length();

if( 0 == start && end == ( length - 1 ) )
{
final String propertyName = content.substring( start + 2, end );
final Object key = recursiveResolveProperty( propertyName, context );
return getPropertyValue( key.toString(), context );
}

final StringBuffer sb = new StringBuffer( length * 2 );

int lastPlace = 0;

while( true )
{
final String propertyName = content.substring( start + 2, end );
final Object key = recursiveResolveProperty( propertyName, context );
final String value = getPropertyStringValue( key.toString(), context );

sb.append( content.substring( lastPlace, start ) );
sb.append( value );

lastPlace = end + 1;

start = findNextProperty( content, lastPlace );
if( -1 == start )
{
break;
}

end = findNestedEnding( content, start );
}

sb.append( content.substring( lastPlace, length ) );

return sb.toString();
}

/**
* Finds the next occurrance of the start of a Property identifier.
* @param content the String to search
* @param currentPosition start location of the search
* @return the position of the next occurrence, or <code>-1</code> if none
* was found.
*/
private int findNextProperty( final String content, final int currentPosition )
{
//TODO: Check if it is commented out
return content.indexOf( "${", currentPosition );
}

/**
* Finds the next occurrence of the end of a Property identifier.
* @param property the String to search
* @param currentPosition start location of the search
* @return the position of the next occurrence
* @throws TaskException if no end was found
*/
private int findEnding( final String property, final int currentPosition )
throws TaskException
{
//TODO: Check if it is commented out
final int index = property.indexOf( '}', currentPosition );
if( -1 == index )
{
final String message = REZ.getString( "prop.mismatched-braces.error" );
throw new TaskException( message );
}

return index;
}

/**
* Finds the end of the property identifier at the currentPosition,
* taking into account nested property identifiers.
* @param property the String to search
* @param currentPosition location of the property
* @return the position of the propery ending.
* @throws TaskException if the property is not properly ended.
*/
private int findNestedEnding( final String property, final int currentPosition )
throws TaskException
{
final int length = property.length();
final int start = currentPosition + 2;

int weight = 1;
for( int i = start; ( weight > 0 ) && ( i < length ); i++ )
{
final char ch = property.charAt( i );
switch( ch )
{
case '}':
//TODO: Check if it is commented out
weight--;
if( weight == 0 )
{
return i;
}
break;

case '$':
{
//TODO: Check if it is commented out
final int next = i + 1;
if( next < length && '{' == property.charAt( next ) )
{
weight++;
}
}
break;
}
}

final String message = REZ.getString( "prop.mismatched-braces.error" );
throw new TaskException( message );
}

/**
* Returns a property's value, converted to a String.
*/
private String getPropertyStringValue( final String propertyName,
final TaskContext context )
throws TaskException
{
final Object value = getPropertyValue( propertyName, context );
if( value instanceof String )
{
return (String)value;
}
try
{
return (String)m_converter.convert( String.class, value, context );
}
catch( final ConverterException e )
{
throw new TaskException( e.getMessage(), e );
}
}

/**
* Retrieve a value from the specified context using the specified key.
*
* @param propertyName the key of value in context
* @param context the set of known properties
* @return the object retrieved from context
* @exception TaskException if the property is undefined
*/
protected Object getPropertyValue( final String propertyName,
final TaskContext context )
throws TaskException
{
final Object value = context.getProperty( propertyName );
if( value != null )
{
return value;
}

final String message = REZ.getString( "prop.missing-value.error", propertyName );
throw new TaskException( message );
}
}


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

@@ -1,3 +0,0 @@
#AbstractPropertyResolver
prop.mismatched-braces.error=Malformed property with mismatched }'s.
prop.missing-value.error=Unknown property "{0}".

+ 0
- 163
proposal/myrmidon/src/java/org/apache/myrmidon/components/role/DefaultRoleManager.java View File

@@ -1,163 +0,0 @@
/*
* 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.role;

import java.util.HashMap;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.myrmidon.interfaces.role.RoleException;
import org.apache.myrmidon.interfaces.role.RoleInfo;
import org.apache.myrmidon.interfaces.role.RoleManager;

/**
* Interface to manage roles and mapping to names.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version CVS $Revision$ $Date$
*/
public class DefaultRoleManager
implements RoleManager
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultRoleManager.class );

/** Parent <code>RoleManager</code> for nested resolution */
private final RoleManager m_parent;

/** Map from shorthand name -> RoleInfo. */
private final HashMap m_shorthandMap = new HashMap();

/** Map from role name -> RoleInfo. */
private final HashMap m_nameMap = new HashMap();

/** Map from role type -> RoleInfo. */
private final HashMap m_typeMap = new HashMap();

/**
* constructor--this RoleManager has no parent.
*/
public DefaultRoleManager()
{
this( null );
}

/**
* Alternate constructor--this RoleManager has the specified
* parent.
*
* @param parent The parent <code>RoleManager</code>.
*/
public DefaultRoleManager( final RoleManager parent )
{
m_parent = parent;
}

/**
* Find role based on shorthand name.
*
* @param name the shorthand name
* @return the role, or null if the role cannot be found.
*/
public RoleInfo getRoleByShorthandName( final String name )
{
final RoleInfo role = (RoleInfo)m_shorthandMap.get( name );

if( null == role && null != m_parent )
{
return m_parent.getRoleByShorthandName( name );
}

return role;
}

/**
* Find role based on role type.
*
* @param type the role type.
* @return the role, or null if the role cannot be found.
*/
public RoleInfo getRoleByType( final Class type )
{
final RoleInfo role = (RoleInfo)m_typeMap.get( type );

if( null == role && null != m_parent )
{
return m_parent.getRoleByType( type );
}

return role;
}

/**
* Find role based on name.
*
* @param name the role name
* @return the role, or null if the role cannot be found.
*/
public RoleInfo getRole( final String name )
{
final RoleInfo role = (RoleInfo)m_nameMap.get( name );

if( null == role && null != m_parent )
{
return m_parent.getRole( name );
}

return role;
}

/**
* Adds a role definition.
*/
public void addRole( final RoleInfo role ) throws RoleException
{
// Check for duplicate role names
final String roleName = role.getName();
RoleInfo oldRole = (RoleInfo)m_nameMap.get( roleName );
if( null != oldRole && !oldRole.equals( role ) )
{
final String message = REZ.getString( "duplicate-role.error", roleName );
throw new RoleException( message );
}

// Check for duplicate shorthand names
final String shorthand = role.getShorthand();
if( shorthand != null )
{
oldRole = (RoleInfo)m_shorthandMap.get( shorthand );
if( null != oldRole && !oldRole.equals( role ) )
{
final String message = REZ.getString( "duplicate-shorthand.error", shorthand );
throw new RoleException( message );
}
}

// Check for duplicate types
final Class roleType = role.getType();
if( roleType != null )
{
oldRole = (RoleInfo)m_typeMap.get( roleType );
if( null != oldRole && !oldRole.equals( role ) )
{
final String message = REZ.getString( "duplicate-type.error", roleType.getName() );
throw new RoleException( message );
}
}

// Add the role to the maps
m_nameMap.put( roleName, role );
if( shorthand != null )
{
m_shorthandMap.put( shorthand, role );
}
if( roleType != null )
{
m_typeMap.put( roleType, role );
}
}
}

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

@@ -1,3 +0,0 @@
duplicate-shorthand.error=Duplicate roles with shorthand name "{0}".
duplicate-type.error=Duplicate roles with type "{0}".
duplicate-role.error=Duplicate roles with name "{0}".

+ 0
- 248
proposal/myrmidon/src/java/org/apache/myrmidon/components/service/InstantiatingServiceManager.java View File

@@ -1,248 +0,0 @@
/*
* 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.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.parameters.ParameterException;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.myrmidon.interfaces.role.RoleInfo;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.service.ServiceFactory;
import org.apache.myrmidon.interfaces.type.TypeException;
import org.apache.myrmidon.interfaces.type.TypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;

/**
* A service manager implementation, which creates service instances on demand.
*
* <p>This manager creates service instances, using a {@link ServiceFactory},
* and running the service instances through the service lifecycle:
* <ul>
* <li>log enable
* <li>contextualise
* <li>service
* <li>parameterise
* <li>initialise
* <li>use
* <li>dispose
* </ul>
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public class InstantiatingServiceManager
extends AbstractLogEnabled
implements ServiceManager, Contextualizable, Parameterizable, Serviceable, Disposable
{
private static final Resources REZ =
ResourceManager.getPackageResources( InstantiatingServiceManager.class );

/** Map from service class -> service object. */
private Map m_services = new HashMap();

/** The objects (services and factories) that have been created by this mgr. */
private List m_objects = new ArrayList();

/** Other services used by this service manager. */
private TypeFactory m_typeFactory;
private RoleManager m_roleManager;
private ServiceManager m_serviceManager;
private Parameters m_parameters;
private TypeManager m_typeManager;
private Context m_context;

public void contextualize( final Context context ) throws ContextException
{
m_context = context;
}

public void parameterize( final Parameters parameters ) throws ParameterException
{
m_parameters = parameters;
}

/**
* Pass the <code>ServiceManager</code> to the <code>servicable</code>.
* The <code>Servicable</code> implementation should use the specified
* <code>ServiceManager</code> to acquire the components it needs for
* execution.
*
* @param manager The <code>ServiceManager</code> which this
* <code>Servicable</code> uses.
*/
public void service( final ServiceManager manager )
throws ServiceException
{
m_serviceManager = manager;
m_roleManager = (RoleManager)manager.lookup( RoleManager.ROLE );
m_typeManager = (TypeManager)manager.lookup( TypeManager.ROLE );
}

/**
* Disposes this service manager, and all services created by it.
*/
public void dispose()
{
// Dispose the services
for( Iterator iterator = m_objects.iterator(); iterator.hasNext(); )
{
final Object object = iterator.next();
if( object instanceof Disposable )
{
( (Disposable)object ).dispose();
}
}

// Ditch state
m_services = null;
m_typeFactory = null;
m_objects = null;
m_parameters = null;
m_roleManager = null;
m_serviceManager = null;
}

/**
* Determines if this service manager contains a particular service.
*/
public boolean hasService( final String serviceRole )
{
// If we have already instantiated the service, or if we know how
// to instantiate it, then return true
if( m_services.containsKey( serviceRole ) )
{
return true;
}
try
{
return getFactory().canCreate( serviceRole );
}
catch( TypeException e )
{
// Throw away exception - yuck
}
return false;
}

/**
* Locates the type factory to use to instantiate service factories.
*/
private TypeFactory getFactory() throws TypeException
{
if( m_typeFactory == null )
{
m_typeFactory = m_typeManager.getFactory( ServiceFactory.ROLE );
}
return m_typeFactory;
}

/**
* Locates a service instance.
*/
public Object lookup( final String serviceRole )
throws ServiceException
{
Object service = m_services.get( serviceRole );
if( service == null )
{
// Create the service
service = createService( serviceRole );
m_services.put( serviceRole, service );
}

return service;
}

/**
* Releases a service.
*/
public void release( final Object service )
{
}

/**
* Creates the service object for a service role.
*/
private Object createService( final String serviceRole ) throws ServiceException
{
try
{
// Create the factory
final ServiceFactory factory = (ServiceFactory)getFactory().create( serviceRole );
setupObject( factory );

// Create the service
final Object service = factory.createService();

// Check the service is assignable to the role type
final RoleInfo roleInfo = m_roleManager.getRole( serviceRole );
final Class serviceType = roleInfo.getType();
if( serviceType != null && !serviceType.isInstance( service ) )
{
final String message = REZ.getString( "mismatched-service-type.error",
serviceRole, service.getClass().getName() );
throw new ServiceException( message );
}

setupObject( service );
return service;
}
catch( final Exception e )
{
final String message = REZ.getString( "create-service.error", serviceRole );
throw new ServiceException( message, e );
}
}

/**
* Sets-up an object, taking it through the lifecycle steps.
*/
private void setupObject( final Object object )
throws Exception
{
setupLogger( object );

if( m_context != null && object instanceof Contextualizable )
{
( (Contextualizable)object ).contextualize( m_context );
}

if( object instanceof Serviceable )
{
( (Serviceable)object ).service( m_serviceManager );
}

if( m_parameters != null && object instanceof Parameterizable )
{
( (Parameterizable)object ).parameterize( m_parameters );
}

if( object instanceof Initializable )
{
( (Initializable)object ).initialize();
}

m_objects.add( object );
}
}

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

@@ -1,3 +0,0 @@
unknown-service-type.error=Unknown service "{0}".
mismatched-service-type.error=Service factory for service "{0}" produced an object of unexpected type {1}.
create-service.error=Could not create service "{0}".

+ 0
- 268
proposal/myrmidon/src/java/org/apache/myrmidon/components/store/DefaultPropertyStore.java View File

@@ -1,268 +0,0 @@
/*
* 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.store;

import java.io.File;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.interfaces.model.DefaultNameValidator;
import org.apache.myrmidon.interfaces.model.NameValidator;
import org.apache.myrmidon.interfaces.property.PropertyStore;

/**
* This is the Default implementation of PropertyStore. It follows
* the following rules;
*
* <ul>
* <li>The property names must pass DefaultNameValidator checks</li>
* <li>The store is mutable</li>
* <li>If the key is TaskContext.NAME then value must be a string.</li>
* <li>If the key is TaskContext.BASE_DIRECTORY then value must be a key.</li>
* </ul>
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
* @see org.apache.myrmidon.interfaces.property.PropertyStore
*/
public class DefaultPropertyStore
implements PropertyStore
{
private final static Resources REZ =
ResourceManager.getPackageResources( DefaultPropertyStore.class );

/**
* The parent store (may be null).
*/
private final PropertyStore m_parent;

/**
* The name validator to check property names against.
*/
private final NameValidator m_validator;

/**
* The underlying map where propertys are actually stored.
*/
private final Map m_contextData = new Hashtable();

/**
* Construct a PropertyStore with no parent and
* default name-validator.
*/
public DefaultPropertyStore()
{
this( "", null, null );
}

/**
* Construct a PropertyStore with specified parent.
*
* @param parent the parent PropertyStore (may be null).
* @param validator the validator to use to check property names (may be null).
*/
public DefaultPropertyStore( final String name,
final PropertyStore parent,
final NameValidator validator )
{
m_parent = parent;

NameValidator candidateValidator = validator;
if( null == candidateValidator )
{
candidateValidator = createDefaultNameValidator();
}

m_validator = candidateValidator;

m_contextData.put( TaskContext.NAME, name );
}

/**
* Set the property with specified name to specified value.
* The specific implementation will apply various rules
* before setting the property.
*
* @param name the name of property
* @param value the value of property
* @throws TaskException if property can not be set
*/
public void setProperty( final String name, final Object value )
throws TaskException
{
checkPropertyName( name );
checkPropertyValid( name, value );

if ( value == null )
{
m_contextData.remove( name );
}
else
{
m_contextData.put( name, value );
}
}

/**
* Return <code>true</code> if the specified property is set.
*
* @param name the name of property
*/
public boolean isPropertySet( final String name )
{
try
{
getProperty( name );
return true;
}
catch( Exception e )
{
}
return false;
}

/**
* Retrieve the value of specified property.
* Will return null if no such property exists.
*
* @param name the name of the property
* @return the value of the property, or null if no such property
* @throws TaskException if theres an error retrieving property, such
* as an invalid property name
*/
public Object getProperty( final String name )
throws TaskException
{
Object value = m_contextData.get( name );
if( value != null )
{
return value;
}
if( m_parent != null )
{
return m_parent.getProperty( name );
}

final String message = REZ.getString( "unknown-prop.error", name );
throw new TaskException( message );
}

/**
* Retrieve a copy of all the properties that are "in-scope"
* for store.
*
* @return a copy of all the properties that are "in-scope"
* for store.
* @throws TaskException if theres an error retrieving propertys
*/
public Map getProperties()
throws TaskException
{
final Map properties = new HashMap();
if( m_parent != null )
{
properties.putAll( m_parent.getProperties() );
}
properties.putAll( m_contextData );
return properties;
}

/**
* Return a child PropertyStore with specified name.
* This is to allow support for scoped stores. However a
* store may choose to be unscoped and just return a
* reference to itself.
*
* @param name the name of child store
* @return the child store
* @throws TaskException if theres an error creating child store
*/
public PropertyStore createChildStore( final String name )
throws TaskException
{
// Build the name for the new store
final String thisName = (String)m_contextData.get( TaskContext.NAME );
final String newName;
if( name == null || name.length() == 0 )
{
newName = thisName;
}
else if( thisName.length() == 0 )
{
newName = name;
}
else
{
newName = thisName + "." + name;
}

return new DefaultPropertyStore( newName, this, m_validator );
}

/**
* Checks that the supplied property name is valid.
*/
private void checkPropertyName( final String name )
throws TaskException
{
try
{
m_validator.validate( name );
}
catch( Exception e )
{
String message = REZ.getString( "bad-property-name.error", name );
throw new TaskException( message, e );
}
}

/**
* Make sure property is valid if it is one of the "magic" properties.
*
* @param name the name of property
* @param value the value of proeprty
* @exception TaskException if an error occurs
*/
private void checkPropertyValid( final String name, final Object value )
throws TaskException
{
if( TaskContext.BASE_DIRECTORY.equals( name ) && !( value instanceof File ) )
{
final String message =
REZ.getString( "bad-property.error",
TaskContext.BASE_DIRECTORY,
File.class.getName() );
throw new TaskException( message );
}
else if( TaskContext.NAME.equals( name ) && !( value instanceof String ) )
{
final String message =
REZ.getString( "bad-property.error",
TaskContext.NAME,
String.class.getName() );
throw new TaskException( message );
}
}

/**
* Create an instance of the default the name validator.
*
* @return the default NameValidator
*/
private static NameValidator createDefaultNameValidator()
{
final DefaultNameValidator defaultValidator = new DefaultNameValidator();
defaultValidator.setAllowInternalWhitespace( false );
defaultValidator.setAdditionalInternalCharacters( "_-.+" );
return defaultValidator;
}
}

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

@@ -1,5 +0,0 @@
unknown-prop.error=Unknown property "{0}".
bad-property.error=Property "{0}" must have a value of type {1}.
bad-property-name.error=Invalid property name "{0}".
null-resolved-value.error=Value "{0}" resolved to null.
bad-resolve.error=Unable to resolve value "{0}".

+ 0
- 139
proposal/myrmidon/src/java/org/apache/myrmidon/components/type/DefaultTypeManager.java View File

@@ -1,139 +0,0 @@
/*
* 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.type;

import java.util.HashMap;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.Serviceable;
import org.apache.myrmidon.interfaces.role.RoleInfo;
import org.apache.myrmidon.interfaces.role.RoleManager;
import org.apache.myrmidon.interfaces.type.TypeException;
import org.apache.myrmidon.interfaces.type.TypeFactory;
import org.apache.myrmidon.interfaces.type.TypeManager;

/**
* The interface that is used to manage types.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class DefaultTypeManager
implements TypeManager, Serviceable
{
private static final Resources REZ
= ResourceManager.getPackageResources( DefaultTypeManager.class );

///Parent type manager to inherit values from.
private final DefaultTypeManager m_parent;

///Maps role Class to MultiSourceTypeFactory.
private final HashMap m_roleMap = new HashMap();

private RoleManager m_roleManager;

public DefaultTypeManager()
{
this( null );
}

private DefaultTypeManager( final DefaultTypeManager parent )
{
m_parent = parent;
if( m_parent != null )
{
m_roleManager = m_parent.m_roleManager;
}
}

public void service( final ServiceManager serviceManager )
throws ServiceException
{
m_roleManager = (RoleManager)serviceManager.lookup( RoleManager.ROLE );
}

public void registerType( final String roleName,
final String shorthandName,
final TypeFactory factory )
throws TypeException
{
final MultiSourceTypeFactory msFactory = createFactory( roleName );
msFactory.register( shorthandName, factory );
}

public TypeFactory getFactory( final String roleName )
throws TypeException
{
return createFactory( roleName );
}

public TypeManager createChildTypeManager()
{
return new DefaultTypeManager( this );
}

private final MultiSourceTypeFactory lookupFactory( final String roleName )
{
return (MultiSourceTypeFactory)m_roleMap.get( roleName );
}

/**
* Get a factory of appropriate role.
* Create a Factory if none exists with same name.
*
* @param roleName the role name
* @return the Factory for interface
* @exception TypeException role does not specify accessible work interface
*/
private MultiSourceTypeFactory createFactory( final String roleName )
throws TypeException
{
MultiSourceTypeFactory factory = (MultiSourceTypeFactory)m_roleMap.get( roleName );
if( null != factory )
{
return factory;
}

final MultiSourceTypeFactory parentFactory = getParentTypedFactory( roleName );
if( null != parentFactory )
{
factory = new MultiSourceTypeFactory( parentFactory );
}

///If we haven't got factory try to create a new one
if( null == factory )
{
// Lookup the role type
final RoleInfo role = m_roleManager.getRole( roleName );
if( role == null )
{
final String message = REZ.getString( "unknown-role.error", roleName );
throw new TypeException( message );
}
factory = new MultiSourceTypeFactory( role.getType() );
}

m_roleMap.put( roleName, factory );

return factory;
}

private MultiSourceTypeFactory getParentTypedFactory( final String roleName )
{
if( null != m_parent )
{
return m_parent.lookupFactory( roleName );
}
else
{
return null;
}
}
}

+ 0
- 124
proposal/myrmidon/src/java/org/apache/myrmidon/components/type/MultiSourceTypeFactory.java View File

@@ -1,124 +0,0 @@
/*
* 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.type;

import java.util.HashMap;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.myrmidon.interfaces.type.TypeException;
import org.apache.myrmidon.interfaces.type.TypeFactory;

/**
* This factory acts as a proxy to set of object factories.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class MultiSourceTypeFactory
implements TypeFactory
{
private static final Resources REZ =
ResourceManager.getPackageResources( MultiSourceTypeFactory.class );

///Parent Selector
private final MultiSourceTypeFactory m_parent;

///Map of name->factory list
private final HashMap m_factories = new HashMap();

///Type expected to be created from factories
private final Class m_type;

public MultiSourceTypeFactory( final Class type )
{
m_type = type;
m_parent = null;
}

public MultiSourceTypeFactory( final MultiSourceTypeFactory parent )
{
m_type = parent.getType();
m_parent = parent;
}

/**
* Populate the ComponentSelector.
*/
public void register( final String name, final TypeFactory factory )
{
m_factories.put( name, factory );
}

/**
* Determines if this factory can create instances of a particular type.
*/
public boolean canCreate( final String name )
{
return ( findFactory( name ) != null );
}

/**
* Create a type instance based on name.
*
* @param name the name
* @return the type instance
* @exception TypeException if an error occurs
*/
public Object create( final String name )
throws TypeException
{
// Locate the factory to use
TypeFactory factory = findFactory( name );
if( null == factory )
{
final String message = REZ.getString( "no-factory.error", name );
throw new TypeException( message );
}

// Create the object
final Object object = factory.create( name );
if( m_type != null && !m_type.isInstance( object ) )
{
final String message = REZ.getString( "mismatched-type.error",
name, object.getClass().getName() );
throw new TypeException( message );
}

return object;
}

/**
* Locates the type factory to use for a particular type.
*/
private TypeFactory findFactory( final String name )
{
TypeFactory factory = getTypeFactory( name );
if( null == factory && null != m_parent )
{
factory = m_parent.getTypeFactory( name );
}

return factory;
}

/**
* Retrieve type managed by selector.
* Used by other instances of TypedComponentSelector.
*
* @return the type class
*/
private final Class getType()
{
return m_type;
}

private final TypeFactory getTypeFactory( final String name )
{
return (TypeFactory)m_factories.get( name );
}
}

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

@@ -1,9 +0,0 @@
# DefaultTypeManager
unknown-role.error=Cannot create a type factory for unknown role {0}.

# MultiSourceTypeFactory
no-instantiate.error=Unable to instantiate ({0}).
no-mapping.error=Malconfigured factory, no classname for ({0}).
no-factory.error=Failed to locate factory for {0}.
mismatched-type.error=Factory for type {0} created an object of incompatible type {1}.
no-work-interface.error=Role {0} does not specify accessible work interface.

+ 0
- 61
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultExecutionFrame.java View File

@@ -1,61 +0,0 @@
/*
* 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.workspace;

import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.myrmidon.interfaces.executor.ExecutionFrame;
import org.apache.myrmidon.interfaces.property.PropertyStore;

/**
* Frames in which tasks are executed.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class DefaultExecutionFrame
implements ExecutionFrame
{
private final Logger m_logger;
private final PropertyStore m_propertyStore;
private final ServiceManager m_serviceManager;

public DefaultExecutionFrame( final Logger logger,
final PropertyStore propertyStore,
final ServiceManager serviceManager )
{
m_logger = logger;
m_propertyStore = propertyStore;
m_serviceManager = serviceManager;
}

/**
* Returns the logger which is to be supplied to tasks.
*/
public Logger getLogger()
{
return m_logger;
}

/**
* Returns the set of services to use to create, configure, and execute
* tasks.
*/
public ServiceManager getServiceManager()
{
return m_serviceManager;
}

/**
* Returns the set of properties to be supplied to tasks.
*/
public PropertyStore getProperties()
{
return m_propertyStore;
}
}

+ 0
- 382
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultTaskContext.java View File

@@ -1,382 +0,0 @@
/*
* 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.workspace;

import java.io.File;
import java.util.Map;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.excalibur.io.FileUtil;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.interfaces.property.PropertyResolver;
import org.apache.myrmidon.interfaces.property.PropertyStore;

/**
* Default implementation of TaskContext.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class DefaultTaskContext
implements TaskContext
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultTaskContext.class );

private final ServiceManager m_serviceManager;
private final Logger m_logger;
private final PropertyStore m_store;
private PropertyResolver m_propertyResolver;

/**
* Constructor that takes both parent context and a service directory.
*/
public DefaultTaskContext( final ServiceManager serviceManager,
final Logger logger,
final PropertyStore store )
{
m_serviceManager = serviceManager;
m_logger = logger;
m_store = store;

if( null == m_serviceManager )
{
throw new NullPointerException( "serviceManager" );
}
if( null == m_logger )
{
throw new NullPointerException( "logger" );
}
if( null == m_store )
{
throw new NullPointerException( "store" );
}
}

/**
* Retrieve Name of task.
*
* @return the name
*/
public String getName()
{
return (String)getProperty( NAME );
}

/**
* Retrieve base directory.
*
* @return the base directory
*/
public File getBaseDirectory()
{
return (File)getProperty( BASE_DIRECTORY );
}

/**
* Retrieve a service that is offered by the runtime.
* The actual services registered and in place for the
* task is determined by the container. The returned service
* <b>MUST</b> implement the specified interface.
*
* @param serviceClass the interface class that defines the service
* @return an instance of the service implementing interface specified by parameter
* @exception TaskException is thrown when the service is unavailable or not supported
*/
public Object getService( final Class serviceClass )
throws TaskException
{
final String name = serviceClass.getName();
//Note that this will chain up to parent ServiceManagers (if any)
if( null != m_serviceManager && m_serviceManager.hasService( name ) )
{
try
{
return m_serviceManager.lookup( name );
}
catch( final ServiceException se )
{
throw new TaskException( se.getMessage(), se );
}
}

// Not found
final String message = REZ.getString( "bad-find-service.error", name );
throw new TaskException( message );
}

/**
* Resolve filename.
* This involves resolving it against baseDirectory and
* removing ../ and ./ references. It also means formatting
* it appropriately for the particular OS (ie different OS have
* different volumes, file conventions etc)
*
* @param filename the filename to resolve
* @return the resolved filename
*/
public File resolveFile( final String filename )
{
return FileUtil.resolveFile( getBaseDirectory(), filename );
}

/**
* Resolve a value according to the context.
* This involves evaluating the string and thus removing
* ${} sequences according to the rules specified at
* ............
*
* @param value the value to resolve
* @return the resolved value
*/
public Object resolveValue( final String value )
throws TaskException
{
try
{
if( null == m_propertyResolver )
{
m_propertyResolver = (PropertyResolver)getService( PropertyResolver.class );
}
final Object object =
m_propertyResolver.resolveProperties( value, this );
if( null == object )
{
final String message = REZ.getString( "null-resolved-value.error", value );
throw new TaskException( message );
}

return object;
}
catch( final TaskException te )
{
final String message = REZ.getString( "bad-resolve.error", value );
throw new TaskException( message, te );
}
}

/**
* Retrieve property for name.
*
* @param name the name of property
* @return the value of the property
*/
public Object getProperty( final String name )
{
try
{
return m_store.getProperty( name );
}
catch( final Exception e )
{
return null;
}
}

/**
* Retrieve a copy of all the properties accessible via context.
*
* @return the map of all property names to values
*/
public Map getProperties()
throws TaskException
{
return m_store.getProperties();
}

/**
* Set property value in current context.
*
* @param name the name of property
* @param value the value of property
*/
public void setProperty( final String name, final Object value )
throws TaskException
{
m_store.setProperty( name, value );
}

/**
* Log a debug message.
*
* @param message the message
*/
public void debug( final String message )
{
m_logger.debug( message );
}

/**
* Log a debug message.
*
* @param message the message
* @param throwable the throwable
*/
public void debug( final String message, final Throwable throwable )
{
m_logger.debug( message, throwable );
}

/**
* Determine if messages of priority "debug" will be logged.
*
* @return true if "debug" messages will be logged
*/
public boolean isDebugEnabled()
{
return m_logger.isDebugEnabled();
}

/**
* Log a verbose message.
*
* @param message the message
*/
public void verbose( String message )
{
m_logger.info( message );
}

/**
* Log a verbose message.
*
* @param message the message
* @param throwable the throwable
*/
public void verbose( String message, Throwable throwable )
{
m_logger.info( message, throwable );
}

/**
* Determine if messages of priority "verbose" will be logged.
*
* @return true if "verbose" messages will be logged
*/
public boolean isVerboseEnabled()
{
return m_logger.isInfoEnabled();
}

/**
* Log a info message.
*
* @param message the message
*/
public void info( final String message )
{
m_logger.warn( message );
}

/**
* Log a info message.
*
* @param message the message
* @param throwable the throwable
*/
public void info( final String message, final Throwable throwable )
{
m_logger.warn( message, throwable );
}

/**
* Determine if messages of priority "info" will be logged.
*
* @return true if "info" messages will be logged
*/
public boolean isInfoEnabled()
{
return m_logger.isWarnEnabled();
}

/**
* Log a warn message.
*
* @param message the message
*/
public void warn( final String message )
{
m_logger.error( message );
}

/**
* Log a warn message.
*
* @param message the message
* @param throwable the throwable
*/
public void warn( final String message, final Throwable throwable )
{
m_logger.error( message, throwable );
}

/**
* Determine if messages of priority "warn" will be logged.
*
* @return true if "warn" messages will be logged
*/
public boolean isWarnEnabled()
{
return m_logger.isErrorEnabled();
}

/**
* Log a error message.
*
* @param message the message
*/
public void error( final String message )
{
m_logger.fatalError( message );
}

/**
* Log a error message.
*
* @param message the message
* @param throwable the throwable
*/
public void error( final String message, final Throwable throwable )
{
m_logger.fatalError( message, throwable );
}

/**
* Determine if messages of priority "error" will be logged.
*
* @return true if "error" messages will be logged
*/
public boolean isErrorEnabled()
{
return m_logger.isFatalErrorEnabled();
}

/**
* Create a Child Context.
* This allows separate hierarchly contexts to be easily constructed.
*
* @param name the name of sub-context
* @return the created TaskContext
* @exception TaskException if an error occurs
*/
public TaskContext createSubContext( final String name )
throws TaskException
{
final PropertyStore store = m_store.createChildStore( name );
final DefaultServiceManager serviceManager =
new DefaultServiceManager( m_serviceManager );
final Logger logger = m_logger.getChildLogger( name );

return new DefaultTaskContext( serviceManager, logger, store );
}
}

+ 0
- 437
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/DefaultWorkspace.java View File

@@ -1,437 +0,0 @@
/*
* 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.workspace;

import java.io.File;
import java.util.HashMap;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.service.DefaultServiceManager;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.interfaces.deployer.Deployer;
import org.apache.myrmidon.interfaces.deployer.DeploymentException;
import org.apache.myrmidon.interfaces.deployer.TypeDeployer;
import org.apache.myrmidon.interfaces.executor.ExecutionContainer;
import org.apache.myrmidon.interfaces.executor.ExecutionFrame;
import org.apache.myrmidon.interfaces.executor.Executor;
import org.apache.myrmidon.interfaces.model.Dependency;
import org.apache.myrmidon.interfaces.model.Project;
import org.apache.myrmidon.interfaces.model.Target;
import org.apache.myrmidon.interfaces.model.TypeLib;
import org.apache.myrmidon.interfaces.property.PropertyStore;
import org.apache.myrmidon.interfaces.type.TypeManager;
import org.apache.myrmidon.interfaces.workspace.Workspace;
import org.apache.myrmidon.listeners.ProjectListener;

/**
* This is the default implementation of Workspace.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class DefaultWorkspace
extends AbstractLogEnabled
implements Workspace, ExecutionContainer, Contextualizable
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultWorkspace.class );

private Executor m_executor;
private ProjectListenerSupport m_listenerSupport = new ProjectListenerSupport();
private ServiceManager m_serviceManager;
private PropertyStore m_baseStore;
private TypeManager m_typeManager;
private Deployer m_deployer;
private Context m_context;

/** A map from Project object -> ProjectEntry for that project. */
private HashMap m_entries = new HashMap();

/**
* Add a listener to project events.
*
* @param listener the listener
*/
public void addProjectListener( final ProjectListener listener )
{
m_listenerSupport.addProjectListener( listener );
}

/**
* Remove a listener from project events.
*
* @param listener the listener
*/
public void removeProjectListener( final ProjectListener listener )
{
m_listenerSupport.removeProjectListener( listener );
}

/**
* Sets the root execution frame.
*/
public void setRootExecutionFrame( final ExecutionFrame frame ) throws Exception
{
m_baseStore = frame.getProperties();
m_serviceManager = frame.getServiceManager();
m_typeManager = (TypeManager)m_serviceManager.lookup( TypeManager.ROLE );
m_executor = (Executor)m_serviceManager.lookup( Executor.ROLE );
m_deployer = (Deployer)m_serviceManager.lookup( Deployer.ROLE );
}

public void contextualize( final Context context ) throws ContextException
{
m_context = context;
}

/**
* Execute a target in a particular project.
* Execute in the project context.
*
* @param project the Project
* @param target the name of the target
* @exception TaskException if an error occurs
*/
public void executeProject( final Project project, final String target )
throws TaskException
{
final ProjectEntry entry = getProjectEntry( project );

m_listenerSupport.projectStarted( project.getProjectName() );

executeTarget( entry, target );

m_listenerSupport.projectFinished( project.getProjectName() );
}

private File findTypeLib( final String libraryName )
throws Exception
{
//TODO: In future this will be expanded to allow
//users to specify search path or automagically
//add entries to lib path (like user specific or
//workspace specific)
final String name = libraryName.replace( '/', File.separatorChar ) + ".atl";

final File[] extPath = (File[])m_context.get( "myrmidon.antlib.path" );
for( int i = 0; i < extPath.length; i++ )
{
final File extDir = extPath[ i ];
final File library = new File( extDir, name );

if( library.exists() )
{
if( !library.canRead() )
{
final String message = REZ.getString( "no-read.error", library );
throw new TaskException( message );
}
else
{
return library;
}
}
}

final String message = REZ.getString( "no-library.error", libraryName );
throw new TaskException( message );
}

private void deployTypeLib( final Deployer deployer, final Project project )
throws Exception
{
final TypeLib[] typeLibs = project.getTypeLibs();

for( int i = 0; i < typeLibs.length; i++ )
{
final TypeLib typeLib = typeLibs[ i ];
final File file = findTypeLib( typeLib.getLibrary() );

try
{
final TypeDeployer typeDeployer = deployer.createDeployer( file );
if( null == typeLib.getRole() )
{
// Deploy everything in the typelib
typeDeployer.deployAll();
}
else
{
// Deploy the specified type
typeDeployer.deployType( typeLib.getRole(), typeLib.getName() );
}
}
catch( final DeploymentException de )
{
final String message = REZ.getString( "no-deploy.error",
typeLib.getLibrary(), file );
throw new TaskException( message, de );
}
}
}

/**
* Creates an execution frame for a project.
*/
private ExecutionFrame createExecutionFrame( final Project project )
throws Exception
{
//Create per frame ComponentManager
final DefaultServiceManager serviceManager =
new DefaultServiceManager( m_serviceManager );

//Add in child type manager so each frame can register different
//sets of tasks etc
final TypeManager typeManager = m_typeManager.createChildTypeManager();
serviceManager.put( TypeManager.ROLE, typeManager );

// TODO - Add child role manager and configurer

//We need to create a new deployer so that it deploys
//to project specific TypeManager
final Deployer deployer = m_deployer.createChildDeployer( serviceManager );
serviceManager.put( Deployer.ROLE, deployer );

// Deploy the imported typelibs
deployTypeLib( deployer, project );

//We need to place projects and ProjectManager
//in ComponentManager so as to support project-local call()
// TODO - add project to properties, not services
serviceManager.put( Workspace.ROLE, this );
serviceManager.put( Project.ROLE, project );

// Create a logger
final Logger logger =
new RoutingLogger( getLogger(), m_listenerSupport );

// Properties
final PropertyStore store = m_baseStore.createChildStore("");
store.setProperty( TaskContext.BASE_DIRECTORY, project.getBaseDirectory() );

final DefaultExecutionFrame frame =
new DefaultExecutionFrame( logger, store, serviceManager );

/**
* @todo Should no occur but done for the time being to simplify evolution.
*/
serviceManager.put( ExecutionFrame.ROLE, frame );

return frame;
}

private ProjectEntry getProjectEntry( final Project project )
throws TaskException
{
ProjectEntry entry = (ProjectEntry)m_entries.get( project );

if( null == entry )
{
try
{
final ExecutionFrame frame = createExecutionFrame( project );
entry = new ProjectEntry( project, frame );
m_entries.put( project, entry );
}
catch( Exception e )
{
final String message = REZ.getString( "bad-frame.error" );
throw new TaskException( message, e );
}
}

return entry;
}

private Project getProject( final String name, final Project project )
throws TaskException
{
final Project other = project.getProject( name );

if( null == other )
{
//TODO: Fix this so location information included in description
final String message = REZ.getString( "no-project.error", name );
throw new TaskException( message );
}

return other;
}

/**
* Helper method to execute a target.
*
* @param entry the project to execute
* @param targetName the name of the target to execute
* @exception TaskException if an error occurs
*/
private void executeTarget( final ProjectEntry entry,
final String targetName )
throws TaskException
{
// Locate the target
final Target target = entry.getProject().getTarget( targetName );
if( null == target )
{
final String message = REZ.getString( "no-target.error", targetName );
throw new TaskException( message );
}

executeTarget( entry, targetName, target );
}

/**
* Executes a target. Does not execute the target if it has already been
* executed. Executes the dependencies of the target, before executing
* the target itself.
*
* @param name the name of target
* @param target the target
* @param entry the project in which to execute
* @exception TaskException if an error occurs
*/
private void executeTarget( final ProjectEntry entry,
final String name,
final Target target )
throws TaskException
{
final Project project = entry.getProject();

// Check target state, to see if it has already been executed, and
// to check for dependency cycles
final TargetState state = entry.getTargetState( target );
if( state == TargetState.FINISHED )
{
// Target has been executed
return;
}
if( state == TargetState.TRAVERSING )
{
// Cycle in target dependencies
final String message = REZ.getString( "target-dependency-cycle.error", name );
throw new TaskException( message );
}

// Set state to indicate this target has been started
entry.setTargetState( target, TargetState.TRAVERSING );

// Execute the target's dependencies

// Implicit target first
if( target != project.getImplicitTarget() )
{
executeTarget( entry, "<init>", project.getImplicitTarget() );
}

// Named dependencies
final Dependency[] dependencies = target.getDependencies();
for( int i = 0; i < dependencies.length; i++ )
{
final Dependency dependency = dependencies[ i ];
final String otherProjectName = dependency.getProjectName();
if( otherProjectName != null )
{
// Dependency in a referenced project
final Project otherProject = getProject( otherProjectName, project );
final ProjectEntry otherEntry = getProjectEntry( otherProject );
executeTarget( otherEntry, dependency.getTargetName() );
}
else
{
// Dependency in this project
executeTarget( entry, dependency.getTargetName() );
}
}

// Now execute the target itself
executeTargetNoDeps( entry, name, target );

// Mark target as complete
entry.setTargetState( target, TargetState.FINISHED );
}

/**
* Executes a target. Does not check whether the target has been
* executed already, and does not check that its dependencies have been
* executed.
*
* @param entry the project to execute the target in.
* @param name the name of the target.
* @param target the target itself
*/
private void executeTargetNoDeps( final ProjectEntry entry,
final String name,
final Target target )
throws TaskException
{
final Project project = entry.getProject();

// Notify listeners
m_listenerSupport.targetStarted( project.getProjectName(), name );

if( getLogger().isDebugEnabled() )
{
final String message = REZ.getString( "exec-target.notice",
project.getProjectName(), name );
getLogger().debug( message );
}

//TODO - put this back in
//frame.getContext().setProperty( Project.TARGET, target );

// Execute all tasks assciated with target
final Configuration[] tasks = target.getTasks();
for( int i = 0; i < tasks.length; i++ )
{
executeTask( tasks[ i ], entry.getFrame() );
}

// Notify listeners
m_listenerSupport.targetFinished();
}

/**
* Execute a task.
*
* @param task the task definition
* @param frame the frame to execute in
* @exception TaskException if an error occurs
*/
private void executeTask( final Configuration task, final ExecutionFrame frame )
throws TaskException
{
final String name = task.getName();

if( getLogger().isDebugEnabled() )
{
final String message = REZ.getString( "exec-task.notice", name );
getLogger().debug( message );
}

//is setting name even necessary ???
frame.getProperties().setProperty( TaskContext.NAME, name );

//notify listeners
m_listenerSupport.taskStarted( name );

//run task
m_executor.execute( task, frame );

//notify listeners task has ended
m_listenerSupport.taskFinished();
}

}

+ 0
- 62
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/ProjectEntry.java View File

@@ -1,62 +0,0 @@
/*
* 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.workspace;

import java.util.HashMap;
import java.util.Map;
import org.apache.myrmidon.interfaces.executor.ExecutionFrame;
import org.apache.myrmidon.interfaces.model.Project;
import org.apache.myrmidon.interfaces.model.Target;

/**
* This contains details for each project that is being executed by a
* DefaultWorkspace.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
final class ProjectEntry
{
private final Project m_project;
private final ExecutionFrame m_frame;

/** Map from Target -> TargetState for that target. */
private final Map m_targetState = new HashMap();

public ProjectEntry( final Project project,
final ExecutionFrame frame )
{
m_project = project;
m_frame = frame;
}

public Project getProject()
{
return m_project;
}

public ExecutionFrame getFrame()
{
return m_frame;
}

public TargetState getTargetState( final Target target )
{
TargetState state = (TargetState)m_targetState.get( target );
if( state == null )
{
state = TargetState.NOT_STARTED;
}
return state;
}

public void setTargetState( final Target target, final TargetState state )
{
m_targetState.put( target, state );
}
}

+ 0
- 224
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/ProjectListenerSupport.java View File

@@ -1,224 +0,0 @@
/*
* 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.workspace;

import org.apache.myrmidon.listeners.LogEvent;
import org.apache.myrmidon.listeners.ProjectListener;

/**
* Support for the project listener event dispatching.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
class ProjectListenerSupport
implements LogEvent
{
private ProjectListener[] m_listeners = new ProjectListener[ 0 ];
private String m_projectName;
private String m_targetName;
private String m_taskName;
private String m_message;
private Throwable m_throwable;

/**
* Add an extra project listener that wants to receive notification of listener events.
*
* @param listener the listener
*/
public void addProjectListener( final ProjectListener listener )
{
final ProjectListener[] listeners = new ProjectListener[ m_listeners.length + 1 ];
System.arraycopy( m_listeners, 0, listeners, 0, m_listeners.length );
listeners[ m_listeners.length ] = listener;
m_listeners = listeners;
}

/**
* Remove a project listener that wants to receive notification of listener events.
*
* @param listener the listener
*/
public void removeProjectListener( final ProjectListener listener )
{
int found = -1;

for( int i = 0; i < m_listeners.length; i++ )
{
if( listener == m_listeners[ i ] )
{
found = i;
break;
}
}

if( -1 == found )
{
return;
}

final ProjectListener[] listeners = new ProjectListener[ m_listeners.length - 1 ];
System.arraycopy( m_listeners, 0, listeners, 0, found );

final int count = m_listeners.length - found - 1;
System.arraycopy( m_listeners, found, listeners, found + 1, count );

m_listeners = listeners;
}

/**
* Fire a projectStarted event.
*/
public void projectStarted( final String projectName )
{
m_projectName = projectName;
m_targetName = null;
m_taskName = null;

for( int i = 0; i < m_listeners.length; i++ )
{
m_listeners[ i ].projectStarted( this );
}
}

/**
* Fire a projectFinished event.
*/
public void projectFinished( final String projectName )
{
m_projectName = projectName;

for( int i = 0; i < m_listeners.length; i++ )
{
m_listeners[ i ].projectFinished( this );
}

m_projectName = null;
m_targetName = null;
m_taskName = null;
}

/**
* Fire a targetStarted event.
*/
public void targetStarted( final String projectName, final String targetName )
{
m_projectName = projectName;
m_targetName = targetName;
m_taskName = null;

for( int i = 0; i < m_listeners.length; i++ )
{
m_listeners[ i ].targetStarted( this );
}
}

/**
* Fire a targetFinished event.
*/
public void targetFinished()
{
for( int i = 0; i < m_listeners.length; i++ )
{
m_listeners[ i ].targetFinished( this );
}

m_targetName = null;
m_taskName = null;
}

/**
* Fire a targetStarted event.
*/
public void taskStarted( final String taskName )
{
m_taskName = taskName;

for( int i = 0; i < m_listeners.length; i++ )
{
m_listeners[ i ].taskStarted( this );
}
}

/**
* Fire a taskFinished event.
*/
public void taskFinished()
{
for( int i = 0; i < m_listeners.length; i++ )
{
m_listeners[ i ].taskFinished( this );
}

m_taskName = null;
}

/**
* Fire a log event.
*
* @param message the log message
*/
public void log( String message, Throwable throwable )
{
m_message = message;
m_throwable = throwable;

try
{
for( int i = 0; i < m_listeners.length; i++ )
{
m_listeners[ i ].log( this );
}
}
finally
{
m_message = null;
m_throwable = null;
}
}

/**
* Returns the message.
*/
public String getMessage()
{
return m_message;
}

/**
* Returns the error that occurred.
*/
public Throwable getThrowable()
{
return m_throwable;
}

/**
* Returns the name of the task.
*/
public String getTaskName()
{
return m_taskName;
}

/**
* Returns the name of the target.
*/
public String getTargetName()
{
return m_targetName;
}

/**
* Returns the name of the project.
*/
public String getProjectName()
{
return m_projectName;
}
}

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

@@ -1,19 +0,0 @@
no-read.error=Unable to read library at {0}.
no-library.error=Unable to locate Type Library {0}.
no-deploy.error=Error deploying type library {0} at {1}.
bad-deployer-config.error=Error configuring deployer.
bad-frame.error=Error setting up ExecutionFrame.
no-project.error=Project {0} not found.
no-target.error=Target {0} not found.
exec-target.notice=Executing project {0}, target {1}.
exec-task.notice=Executing task {0}.
target-dependency-cycle.error=Cycle in dependencies for target {0}.

#DefaultTaskContext
unknown-prop.error=Unknown property {0}.
bad-property.error=Property {0} must have a value of type {1}.
bad-property-name.error=Invalid property name.
null-resolved-value.error=Value "{0}" resolved to null.
bad-resolve.error=Unable to resolve value "{0}".
bad-find-service.error=Could not find service "{0}".
bad-service-class.error=Find service "{0}" but it was of type {1} where it was expected to be of type {2}.

+ 0
- 85
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/RoutingLogger.java View File

@@ -1,85 +0,0 @@
/*
* 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.workspace;

import org.apache.avalon.framework.logger.Logger;
import org.apache.myrmidon.frontends.AbstractLogger;

/**
* A logger that just routes the messages to the ProjectListenerSupport.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
final class RoutingLogger
extends AbstractLogger
implements Logger
{
/**
* The endpoint of all the logging messages.
*/
private final ProjectListenerSupport m_listenerSupport;

/**
* A wrapped logger that is used to determine which message types are
* enabled.
*/
private final Logger m_logger;

/**
* Create a Logger that routes messages at specified level
* to specified support.
*
* @todo Use something other than a logger to figure out which messages
* are enabled.
*/
public RoutingLogger( final Logger logger,
final ProjectListenerSupport listenerSupport )
{
m_listenerSupport = listenerSupport;
m_logger = logger;
}

public boolean isDebugEnabled()
{
return m_logger.isDebugEnabled();
}

public boolean isInfoEnabled()
{
return m_logger.isInfoEnabled();
}

public boolean isWarnEnabled()
{
return m_logger.isWarnEnabled();
}

public boolean isErrorEnabled()
{
return m_logger.isErrorEnabled();
}

public boolean isFatalErrorEnabled()
{
return m_logger.isFatalErrorEnabled();
}

public Logger getChildLogger( final String name )
{
return new RoutingLogger( m_logger.getChildLogger( name ), m_listenerSupport );
}

/**
* Utility method to output messages.
*/
protected void output( final String message, final Throwable throwable )
{
m_listenerSupport.log( message, throwable );
}
}

+ 0
- 34
proposal/myrmidon/src/java/org/apache/myrmidon/components/workspace/TargetState.java View File

@@ -1,34 +0,0 @@
/*
* 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.workspace;

/**
* An enumerated type that represents the dependency traversal state of a
* target.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
final class TargetState
{
private TargetState()
{
}

/** Target has not been started. */
public static final TargetState NOT_STARTED = new TargetState();

/**
* Target has been started, and the dependencies of the target are being
* traversed.
*/
public static final TargetState TRAVERSING = new TargetState();

/** Target has been completed. */
public static final TargetState FINISHED = new TargetState();
}

+ 0
- 167
proposal/myrmidon/src/java/org/apache/myrmidon/frontends/AbstractLogger.java View File

@@ -1,167 +0,0 @@
/*
* 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.frontends;

import org.apache.avalon.framework.logger.Logger;

/**
* A partial logger implementation.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public abstract class AbstractLogger
implements Logger
{
public static final int LEVEL_DEBUG = 0;
public static final int LEVEL_INFO = 1;
public static final int LEVEL_WARN = 2;
public static final int LEVEL_ERROR = 3;
public static final int LEVEL_FATAL = 4;

/**
* Log a debug message.
*
* @param message the message
*/
public void debug( final String message )
{
if( isDebugEnabled() )
{
output( message, null );
}
}

/**
* Log a debug message.
*
* @param message the message
* @param throwable the throwable
*/
public void debug( final String message, final Throwable throwable )
{
if( isDebugEnabled() )
{
output( message, throwable );
}
}

/**
* Log a info message.
*
* @param message the message
*/
public void info( final String message )
{
if( isInfoEnabled() )
{
output( message, null );
}
}

/**
* Log a info message.
*
* @param message the message
* @param throwable the throwable
*/
public void info( final String message, final Throwable throwable )
{
if( isInfoEnabled() )
{
output( message, throwable );
}
}

/**
* Log a warn message.
*
* @param message the message
*/
public void warn( final String message )
{
if( isWarnEnabled() )
{
output( message, null );
}
}

/**
* Log a warn message.
*
* @param message the message
* @param throwable the throwable
*/
public void warn( final String message, final Throwable throwable )
{
if( isWarnEnabled() )
{
output( message, throwable );
}
}

/**
* Log a error message.
*
* @param message the message
*/
public void error( final String message )
{
if( isErrorEnabled() )
{
output( message, null );
}
}

/**
* Log a error message.
*
* @param message the message
* @param throwable the throwable
*/
public void error( final String message, final Throwable throwable )
{
if( isErrorEnabled() )
{
output( message, throwable );
}
}

/**
* Log a fatalError message.
*
* @param message the message
*/
public void fatalError( final String message )
{
if( isFatalErrorEnabled() )
{
output( message, null );
}
}

/**
* Log a fatalError message.
*
* @param message the message
* @param throwable the throwable
*/
public void fatalError( final String message, final Throwable throwable )
{
if( isFatalErrorEnabled() )
{
output( message, throwable );
}
}

/**
* Utility method to output messages.
*/
protected abstract void output( final String message,
final Throwable throwable );
}

+ 0
- 124
proposal/myrmidon/src/java/org/apache/myrmidon/frontends/BasicLogger.java View File

@@ -1,124 +0,0 @@
/*
* 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.frontends;

import org.apache.avalon.framework.ExceptionUtil;
import org.apache.avalon.framework.logger.Logger;

/**
* A basic logger that just prints out messages to <code>System.out</code>.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class BasicLogger
extends AbstractLogger
implements Logger
{
/**
* The string prefixed to all log messages.
*/
private final String m_prefix;

/**
* The level at which messages start becoming logged.
*/
private final int m_logLevel;

/**
* Create a logger that has specified prefix and is logging
* at specified level.
*/
public BasicLogger( final String prefix, final int logLevel )
{
m_prefix = prefix;
m_logLevel = logLevel;
}

/**
* Determine if messages of priority "debug" will be logged.
*
* @return true if "debug" messages will be logged
*/
public boolean isDebugEnabled()
{
return m_logLevel <= LEVEL_DEBUG;
}

/**
* Determine if messages of priority "info" will be logged.
*
* @return true if "info" messages will be logged
*/
public boolean isInfoEnabled()
{
return m_logLevel <= LEVEL_INFO;
}

/**
* Determine if messages of priority "warn" will be logged.
*
* @return true if "warn" messages will be logged
*/
public boolean isWarnEnabled()
{
return m_logLevel <= LEVEL_WARN;
}

/**
* Determine if messages of priority "error" will be logged.
*
* @return true if "error" messages will be logged
*/
public boolean isErrorEnabled()
{
return m_logLevel <= LEVEL_ERROR;
}

/**
* Determine if messages of priority "fatalError" will be logged.
*
* @return true if "fatalError" messages will be logged
*/
public boolean isFatalErrorEnabled()
{
return m_logLevel <= LEVEL_FATAL;
}

/**
* Create a new child logger.
* The name of the child logger is [current-loggers-name].[passed-in-name]
*
* @param name the subname of this logger
* @return the new logger
* @exception IllegalArgumentException if name has an empty element name
*/
public Logger getChildLogger( final String name )
{
return new BasicLogger( m_prefix + "." + name, m_logLevel );
}

/**
* Utility method to output messages.
*/
protected void output( final String message, final Throwable throwable )
{
final StringBuffer sb = new StringBuffer( m_prefix );
if( null != message )
{
sb.append( message );
}
System.out.println( sb );

if( null != throwable )
{
final String stackTrace = ExceptionUtil.printStackTrace( throwable, 8, true, true );
System.out.println( stackTrace );
}
}
}

+ 0
- 477
proposal/myrmidon/src/java/org/apache/myrmidon/frontends/CLIMain.java View File

@@ -1,477 +0,0 @@
/*
* 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.frontends;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.avalon.excalibur.cli.CLArgsParser;
import org.apache.avalon.excalibur.cli.CLOption;
import org.apache.avalon.excalibur.cli.CLOptionDescriptor;
import org.apache.avalon.excalibur.cli.CLUtil;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.framework.CascadingException;
import org.apache.avalon.framework.ExceptionUtil;
import org.apache.myrmidon.Constants;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.interfaces.executor.Executor;

/**
* The class to kick the tires and light the fires.
* Starts myrmidon, loads ProjectBuilder, builds project then uses ProjectManager
* to run project.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class CLIMain
{
private static final Resources REZ =
ResourceManager.getPackageResources( CLIMain.class );

//defines for the Command Line options
private static final int HELP_OPT = 'h';
private static final int QUIET_OPT = 'q';
private static final int VERBOSE_OPT = 'v';
private static final int FILE_OPT = 'f';
private static final int LOG_LEVEL_OPT = 'l';
private static final int DEFINE_OPT = 'D';
private static final int BUILDER_PARAM_OPT = 'B';
private static final int NO_PREFIX_OPT = 'p';
private static final int VERSION_OPT = 1;
private static final int LISTENER_OPT = 2;
private static final int TASKLIB_DIR_OPT = 5;
private static final int EXTLIB_DIR_OPT = 6;
private static final int INCREMENTAL_OPT = 7;
private static final int HOME_DIR_OPT = 8;
private static final int DRY_RUN_OPT = 9;
private static final int DEBUG_OPT = 10;
private static final int TYPE_OPT = 11;

//incompatable options for info options
private static final int[] INFO_OPT_INCOMPAT = new int[]
{
HELP_OPT, QUIET_OPT, VERBOSE_OPT, FILE_OPT,
LOG_LEVEL_OPT, BUILDER_PARAM_OPT, NO_PREFIX_OPT,
VERSION_OPT, LISTENER_OPT, TASKLIB_DIR_OPT, EXTLIB_DIR_OPT,
INCREMENTAL_OPT, HOME_DIR_OPT, DRY_RUN_OPT, TYPE_OPT
};

//incompatable options for other logging options
private static final int[] LOG_OPT_INCOMPAT = new int[]
{
QUIET_OPT, VERBOSE_OPT, LOG_LEVEL_OPT, DEBUG_OPT
};

//incompatible options for listener options
private static final int[] LISTENER_OPT_INCOMPAT = new int[]
{
LISTENER_OPT, NO_PREFIX_OPT
};

///List of targets supplied on command line to execute
private ArrayList m_targets = new ArrayList();

///Determine whether tasks are actually executed
private boolean m_dryRun = false;

///Enables incremental mode
private boolean m_incremental;

///The launcher
private EmbeddedAnt m_embedded = new EmbeddedAnt();

///Log level to use
private static int m_priority = BasicLogger.LEVEL_WARN;

/**
* Main entry point called to run standard Myrmidon.
*
* @param args the args
*/
public static void main( final String[] args )
{
final Map properties = new HashMap();
properties.put( "myrmidon.home", new File( "." ) );
main( properties, args );
}

/**
* Main entry point called to run standard Myrmidon.
*
* @param args the args
*/
public static void main( final Map properties, final String[] args )
{
int exitCode = 0;
final CLIMain main = new CLIMain();
try
{
main.execute( properties, args );
}
catch( final Throwable throwable )
{
main.reportError( throwable );
exitCode = -1;
}
finally
{
System.exit( exitCode );
}
}

/**
* Display usage report.
*
*/
private void usage( final CLOptionDescriptor[] options )
{
System.out.println( "ant [options] [targets]" );
System.out.println( "\tAvailable options:" );
System.out.println( CLUtil.describeOptions( options ) );
}

/**
* Initialise the options for command line parser.
*/
private CLOptionDescriptor[] createCLOptions()
{
//TODO: localise
final CLOptionDescriptor[] options = {
new CLOptionDescriptor( "help",
CLOptionDescriptor.ARGUMENT_DISALLOWED,
HELP_OPT,
REZ.getString( "help.opt" ),
INFO_OPT_INCOMPAT ),
new CLOptionDescriptor( "file",
CLOptionDescriptor.ARGUMENT_REQUIRED,
FILE_OPT,
REZ.getString( "file.opt" ) ),
new CLOptionDescriptor( "log-level",
CLOptionDescriptor.ARGUMENT_REQUIRED,
LOG_LEVEL_OPT,
REZ.getString( "log-level.opt" ),
LOG_OPT_INCOMPAT ),
new CLOptionDescriptor( "quiet",
CLOptionDescriptor.ARGUMENT_DISALLOWED,
QUIET_OPT,
REZ.getString( "quiet.opt" ),
LOG_OPT_INCOMPAT ),
new CLOptionDescriptor( "verbose",
CLOptionDescriptor.ARGUMENT_DISALLOWED,
VERBOSE_OPT,
REZ.getString( "verbose.opt" ),
LOG_OPT_INCOMPAT ),
new CLOptionDescriptor( "debug",
CLOptionDescriptor.ARGUMENT_DISALLOWED,
DEBUG_OPT,
REZ.getString( "debug.opt" ),
LOG_OPT_INCOMPAT ),
new CLOptionDescriptor( "listener",
CLOptionDescriptor.ARGUMENT_REQUIRED,
LISTENER_OPT,
REZ.getString( "listener.opt" ),
LISTENER_OPT_INCOMPAT ),
new CLOptionDescriptor( "noprefix",
CLOptionDescriptor.ARGUMENT_DISALLOWED,
NO_PREFIX_OPT,
REZ.getString( "noprefix.opt" ),
LISTENER_OPT_INCOMPAT ),
new CLOptionDescriptor( "version",
CLOptionDescriptor.ARGUMENT_DISALLOWED,
VERSION_OPT,
REZ.getString( "version.opt" ),
INFO_OPT_INCOMPAT ),
new CLOptionDescriptor( "antlib-path",
CLOptionDescriptor.ARGUMENT_REQUIRED,
TASKLIB_DIR_OPT,
REZ.getString( "tasklib.opt" ) ),
new CLOptionDescriptor( "ext-path",
CLOptionDescriptor.ARGUMENT_REQUIRED,
EXTLIB_DIR_OPT,
REZ.getString( "extlib.opt" ) ),
new CLOptionDescriptor( "incremental",
CLOptionDescriptor.ARGUMENT_DISALLOWED,
INCREMENTAL_OPT,
REZ.getString( "incremental.opt" ) ),
new CLOptionDescriptor( "ant-home",
CLOptionDescriptor.ARGUMENT_REQUIRED,
HOME_DIR_OPT,
REZ.getString( "home.opt" ) ),
new CLOptionDescriptor( "define",
CLOptionDescriptor.ARGUMENTS_REQUIRED_2,
DEFINE_OPT,
REZ.getString( "define.opt" ),
new int[ 0 ] ),
new CLOptionDescriptor( "builder-parameter",
CLOptionDescriptor.ARGUMENTS_REQUIRED_2,
BUILDER_PARAM_OPT,
REZ.getString( "build.opt" ) ),
new CLOptionDescriptor( "dry-run",
CLOptionDescriptor.ARGUMENT_DISALLOWED,
DRY_RUN_OPT,
REZ.getString( "dry-run.opt" ) ),
new CLOptionDescriptor( "type",
CLOptionDescriptor.ARGUMENT_REQUIRED,
TYPE_OPT,
REZ.getString( "type.opt" ) )
};

return options;
}

private boolean parseCommandLineOptions( final String[] args )
throws Exception
{
final CLOptionDescriptor[] options = createCLOptions();
final CLArgsParser parser = new CLArgsParser( args, options );

if( null != parser.getErrorString() )
{
final String message = REZ.getString( "error-message", parser.getErrorString() );
throw new Exception( message );
}

final List clOptions = parser.getArguments();
final int size = clOptions.size();

for( int i = 0; i < size; i++ )
{
final CLOption option = (CLOption)clOptions.get( i );

switch( option.getId() )
{
case HELP_OPT:
usage( options );
return false;
case VERSION_OPT:
System.out.println( Constants.BUILD_DESCRIPTION );
return false;

case HOME_DIR_OPT:
m_embedded.setEmbeddorProperty( "myrmidon.home", option.getArgument() );
break;
case TASKLIB_DIR_OPT:
m_embedded.setEmbeddorProperty( "myrmidon.antlib.path", option.getArgument() );
break;
case EXTLIB_DIR_OPT:
m_embedded.setEmbeddorProperty( "myrmidon.ext.path", option.getArgument() );
break;

case LOG_LEVEL_OPT:
m_priority = mapLogLevel( option.getArgument() );
break;
case VERBOSE_OPT:
m_priority = BasicLogger.LEVEL_INFO;
break;
case DEBUG_OPT:
m_priority = BasicLogger.LEVEL_DEBUG;
break;
case QUIET_OPT:
m_priority = BasicLogger.LEVEL_ERROR;
break;

case INCREMENTAL_OPT:
m_incremental = true;
break;

case FILE_OPT:
m_embedded.setProjectFile( option.getArgument() );
break;

case LISTENER_OPT:
m_embedded.setProjectListener( option.getArgument() );
break;
case NO_PREFIX_OPT:
m_embedded.setProjectListener( "noprefix" );
break;

case DEFINE_OPT:
m_embedded.setWorkspaceProperty( option.getArgument( 0 ), option.getArgument( 1 ) );
break;

case BUILDER_PARAM_OPT:
m_embedded.setBuilderProperty( option.getArgument( 0 ), option.getArgument( 1 ) );
break;

case DRY_RUN_OPT:
m_dryRun = true;
break;

case TYPE_OPT:
m_embedded.setProjectType( option.getArgument( 0 ) );
break;

case 0:
m_targets.add( option.getArgument() );
break;
}
}

return true;
}

private void execute( final Map properties, final String[] args )
throws Exception
{
try
{
// Set system properties set up by launcher
m_embedded.setHomeDirectory( (File)properties.get( "myrmidon.home" ) );

// Command line
if( !parseCommandLineOptions( args ) )
{
return;
}

// Setup logging
final BasicLogger logger = new BasicLogger( "[myrmidon] ", m_priority );
m_embedded.enableLogging( logger );

if( m_dryRun )
{
m_embedded.setEmbeddorProperty( Executor.ROLE,
"org.apache.myrmidon.components.executor.PrintingExecutor" );
}

// Set the common classloader
final ClassLoader sharedClassLoader = (ClassLoader)properties.get( "myrmidon.shared.classloader" );
m_embedded.setSharedClassLoader( sharedClassLoader );

//loop over build if we are in incremental mode..
if( !m_incremental )
{
executeBuild();
}
else
{
executeIncrementalBuild();
}
}
catch( final Exception e )
{
final String message = REZ.getString( "build-failed.error" );
throw new CascadingException( message, e );
}
finally
{
m_embedded.stop();
}
}

private void executeIncrementalBuild()
throws Exception
{
BufferedReader reader = null;

while( true )
{
try
{
executeBuild();
}
catch( final TaskException te )
{
reportError( te );
}

final String message = REZ.getString( "repeat.notice" );
System.out.println( message );

if( null == reader )
{
reader = new BufferedReader( new InputStreamReader( System.in ) );
}

String line = reader.readLine();

if( line.equalsIgnoreCase( "no" ) )
{
break;
}
}
}

private void executeBuild() throws Exception
{
//actually do the build ...
final String[] targets = (String[])m_targets.toArray( new String[ m_targets.size() ] );
m_embedded.executeTargets( targets );
}

/**
* Builds the error message for an exception
*/
private void reportError( final Throwable throwable )
{
// Build the message
final String message;
if( m_priority <= BasicLogger.LEVEL_INFO )
{
// Verbose mode - include the stack traces
message = ExceptionUtil.printStackTrace( throwable, 8, true, true );
}
else
{
// Build the message
final StringBuffer buffer = new StringBuffer();
buffer.append( throwable.getMessage() );
for( Throwable current = ExceptionUtil.getCause( throwable, true );
current != null;
current = ExceptionUtil.getCause( current, true ) )
{
final String causeMessage = REZ.getString( "cause.error", current.getMessage() );
buffer.append( causeMessage );
}
message = buffer.toString();
}

// Write the message out
System.err.println( message );
}

/**
* Sets the log level.
*/
private int mapLogLevel( final String logLevel )
throws Exception
{
final String logLevelCapitalized = logLevel.toUpperCase();
if( "DEBUG".equals( logLevelCapitalized ) )
{
return BasicLogger.LEVEL_DEBUG;
}
else if( "VERBOSE".equals( logLevelCapitalized ) )
{
return BasicLogger.LEVEL_INFO;
}
else if( "INFO".equals( logLevelCapitalized ) )
{
return BasicLogger.LEVEL_WARN;
}
else if( "WARN".equals( logLevelCapitalized ) )
{
return BasicLogger.LEVEL_ERROR;
}
else if( "ERROR".equals( logLevelCapitalized ) )
{
return BasicLogger.LEVEL_FATAL;
}
else
{
final String message = REZ.getString( "bad-loglevel.error", logLevel );
throw new Exception( message );
}
}
}

+ 0
- 420
proposal/myrmidon/src/java/org/apache/myrmidon/frontends/EmbeddedAnt.java View File

@@ -1,420 +0,0 @@
/*
* 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.frontends;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.excalibur.io.FileUtil;
import org.apache.avalon.excalibur.util.StringUtil;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Startable;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.interfaces.embeddor.Embeddor;
import org.apache.myrmidon.interfaces.model.Project;
import org.apache.myrmidon.interfaces.workspace.Workspace;
import org.apache.myrmidon.listeners.ProjectListener;

/**
* A utility class, that takes care of launching Myrmidon, and building and
* executing a project.
*
* <p>To use this class, create an instance and configure. To execute
* targets in a project, use the {@link #executeTargets} method. This can
* be done one or more times. Finally, call the {@link #stop} method to
* clean-up.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class EmbeddedAnt
extends AbstractLogEnabled
{
private static final Resources REZ =
ResourceManager.getPackageResources( EmbeddedAnt.class );

private static final String DEFAULT_EMBEDDOR_CLASS =
"org.apache.myrmidon.components.embeddor.DefaultEmbeddor";

private final ArrayList m_listeners = new ArrayList();
private final Parameters m_builderProps = new Parameters();
private final Map m_embeddorParameters = new HashMap();
private final Map m_workspaceProperties = new HashMap();

private String m_projectFile = "build.ant";
private Project m_project;
private String m_listenerName = "default";
private ClassLoader m_sharedClassLoader;
private Embeddor m_embeddor;
private File m_homeDir;
private String m_projectType;

/**
* Sets the Myrmidon home directory. Default is to use the current
* directory.
*
* @todo Autodetect myrmidon home, rather than using current directory
* as the default (which is a dud default).
*/
public void setHomeDirectory( final File homeDir )
{
m_homeDir = homeDir.getAbsoluteFile();
}

/**
* Sets the project file to execute. Default is 'build.ant'.
*/
public void setProjectFile( final String projectFile )
{
m_projectFile = projectFile;
m_project = null;
}

/**
* Sets the project file type. Ignored if {@link #setProject} is used.
* Set to null to use the default project type.
*/
public void setProjectType( final String projectType )
{
m_projectType = projectType;
}

/**
* Sets the project to execute. This method can be used instead of
* {@link #setProjectFile}, for projects models that are built
* programmatically.
*/
public void setProject( final Project project )
{
m_projectFile = null;
m_project = project;
}

/**
* Sets the name of the project listener to use. Set to null to disable
* the project listener.
*/
public void setProjectListener( final String listener )
{
m_listenerName = listener;
}

/**
* Adds a project listener.
*/
public void addProjectListener( final ProjectListener listener )
{
m_listeners.add( listener );
}

/**
* Sets a workspace property. These are inherited by all projects executed
* by this embeddor.
*/
public void setWorkspaceProperty( final String name, final Object value )
{
m_workspaceProperties.put( name, value );
}

/**
* Sets a project builder property. These are used by the project builder
* when it is parsing the project file.
*/
public void setBuilderProperty( final String name, final Object value )
{
// TODO - Make properties Objects, not Strings
m_builderProps.setParameter( name, value.toString() );
}

/**
* Sets a task engine property. These are used to configure the task engine.
*
* @todo Make this method actually work with objects...
*/
public void setEmbeddorProperty( final String name, final Object value )
{
m_embeddorParameters.put( name, value.toString() );
}

/**
* Sets the shared classloader, which is used as the parent classloader
* for all antlibs. Default is to use the context classloader.
*/
public void setSharedClassLoader( final ClassLoader classLoader )
{
m_sharedClassLoader = classLoader;
}

/**
* Executes a set of targets in the project. This method may be called
* multiple times.
*/
public void executeTargets( final String[] targets ) throws Exception
{
Map embeddorParameters = new HashMap( m_embeddorParameters );
setupPaths( embeddorParameters );

if( m_sharedClassLoader != null )
{
embeddorParameters.put( "myrmidon.shared.classloader", m_sharedClassLoader );
}

// Prepare the embeddor, and project model
final Embeddor embeddor = prepareEmbeddor( embeddorParameters );
final Project project = prepareProjectModel( embeddor );

// Create a new workspace
final Workspace workspace = embeddor.createWorkspace( m_workspaceProperties );
prepareListeners( embeddor, workspace );

//execute the project
executeTargets( workspace, project, targets );
}

/**
* Shuts down the task engine, after the project has been executed.
*/
public void stop() throws Exception
{
try
{
if( m_embeddor != null )
{
if( m_embeddor instanceof Startable )
{
( (Startable)m_embeddor ).stop();
}
if( m_embeddor instanceof Disposable )
{
( (Disposable)m_embeddor ).dispose();
}
}
}
finally
{
m_embeddor = null;
m_project = null;
m_listeners.clear();
}
}

/**
* Actually do the build.
*/
private void executeTargets( final Workspace workspace,
final Project project,
final String[] targets )
throws TaskException
{
//if we didn't specify a target, then choose default
if( targets == null || targets.length == 0 )
{
workspace.executeProject( project, project.getDefaultTargetName() );
}
else
{
for( int i = 0; i < targets.length; i++ )
{
workspace.executeProject( project, targets[ i ] );
}
}
}

/**
* Make sure myrmidon home directory has been specified, and is a
* directory. Set the paths that the embeddor expects.
*/
private void setupPaths( Map parameters ) throws Exception
{
if( m_homeDir == null )
{
m_homeDir = new File( "." ).getAbsoluteFile();
}
checkDirectory( m_homeDir, "home-dir.name" );
parameters.put( "myrmidon.home", m_homeDir );

if( getLogger().isInfoEnabled() )
{
final String message = REZ.getString( "homedir.notice", m_homeDir );
getLogger().info( message );
}

// Build the lib path
String path = (String)parameters.get( "myrmidon.lib.path" );
File[] dirs = buildPath( m_homeDir, path, "lib", "lib-dir.name" );
parameters.put( "myrmidon.lib.path", dirs );

// Build the antlib search path
path = (String)parameters.get( "myrmidon.antlib.path" );
dirs = buildPath( m_homeDir, path, "ext", "task-lib-dir.name" );
parameters.put( "myrmidon.antlib.path", dirs );

// Build the extension search path
path = (String)parameters.get( "myrmidon.ext.path" );
dirs = buildPath( m_homeDir, path, "ext", "ext-dir.name" );
parameters.put( "myrmidon.ext.path", dirs );
}

/**
* Prepares and returns the embeddor to use.
*/
private Embeddor prepareEmbeddor( final Map parameters )
throws Exception
{
if( m_embeddor == null )
{
m_embeddor = createEmbeddor();
setupLogger( m_embeddor );
if( m_embeddor instanceof Contextualizable )
{
final Context context = new DefaultContext( parameters );
( (Contextualizable)m_embeddor ).contextualize( context );
}
if( m_embeddor instanceof Initializable )
{
( (Initializable)m_embeddor ).initialize();
}
if( m_embeddor instanceof Startable )
{
( (Startable)m_embeddor ).start();
}
}
return m_embeddor;
}

/**
* Creates the embeddor.
*/
private Embeddor createEmbeddor()
throws Exception
{
final Class clazz = Class.forName( DEFAULT_EMBEDDOR_CLASS );
return (Embeddor)clazz.newInstance();
}

/**
* Prepares and returns the project listener to use.
*/
private void prepareListeners( final Embeddor embeddor,
final Workspace workspace )
throws Exception
{
if( m_listenerName != null )
{
final ProjectListener listener = embeddor.createListener( m_listenerName );
workspace.addProjectListener( listener );
}
final int count = m_listeners.size();
for( int i = 0; i < count; i++ )
{
final ProjectListener listener = (ProjectListener)m_listeners.get( i );
workspace.addProjectListener( listener );
}
}

/**
* Prepares and returns the project model.
*/
private Project prepareProjectModel( final Embeddor embeddor ) throws Exception
{
if( m_project == null )
{
final File buildFile = getProjectFile();
m_project = embeddor.createProject( buildFile.toString(), m_projectType, m_builderProps );
}
return m_project;
}

/**
* Locates the project file
*/
private File getProjectFile() throws Exception
{
final File projectFile = ( new File( m_projectFile ) ).getCanonicalFile();
if( !projectFile.isFile() )
{
final String message = REZ.getString( "bad-file.error", projectFile );
throw new Exception( message );
}

if( getLogger().isInfoEnabled() )
{
final String message = REZ.getString( "buildfile.notice", projectFile );
getLogger().info( message );
}

return projectFile;
}

/**
* Resolve a directory relative to another base directory.
*/
private File[] buildPath( final File baseDir,
final String path,
final String defaultPath,
final String name )
throws Exception
{
// Build the canonical list of files
final ArrayList files = new ArrayList();

// Add the default path
files.add( FileUtil.resolveFile( baseDir, defaultPath ) );

// Add the additional path
if( path != null )
{
final String[] split = StringUtil.split( path, File.pathSeparator );
for( int i = 0; i < split.length; i++ )
{
final String s = split[ i ];
final File file = new File( s ).getAbsoluteFile();
files.add( file );
}
}

// Check each one
for( int i = 0; i < files.size(); i++ )
{
File file = (File)files.get( i );
checkDirectory( file, name );
}

return (File[])files.toArray( new File[ files.size() ] );
}

/**
* Verify file is a directory else throw an exception.
*/
private void checkDirectory( final File file, final String name )
throws Exception
{
if( !file.exists() )
{
final String nameStr = REZ.getString( name );
final String message = REZ.getString( "file-no-exist.error", nameStr, file );
throw new Exception( message );
}
else if( !file.isDirectory() )
{
final String nameStr = REZ.getString( name );
final String message = REZ.getString( "file-not-dir.error", nameStr, file );
throw new Exception( message );
}
}
}

+ 0
- 35
proposal/myrmidon/src/java/org/apache/myrmidon/frontends/Resources.properties View File

@@ -1,35 +0,0 @@
error-message=Error: {0}.

help.opt=Display this help message.
file.opt=Specify the build file.
log-level.opt=Specify the verbosity level at which to log messages. (DEBUG|VERBOSE|INFO|WARN|ERROR).
quiet.opt=Equivalent to --log-level=ERROR.
verbose.opt=Equivalent to --log-level=VERBOSE.
debug.opt=Equivalent to --log-level=DEBUG.
listener.opt=Specify the listener for log events.
noprefix.opt=Do not prefix output with the task name. Equivalent to --listener noprefix.
version.opt=Display version.
tasklib.opt=Specify the path to use to search for antlib libraries.
extlib.opt=Specify the path to use to search for optional packages.
incremental.opt=Run in incremental mode.
home.opt=Specify Ant home directory.
define.opt=Define a property (ie -Dfoo=var).
build.opt=Define a builder parameter (ie -Bfoo=var).
dry-run.opt=Do not execute tasks - just print them out.
type.opt=Specify the project file type.

file-no-exist.error={0} {1} does not exist.
file-not-dir.error={0} {1} is not a directory.
bad-file.error=File {0} is not a file or doesn't exist.
bad-loglevel.error=Unknown log level - {0}.
build-failed.error=BUILD FAILED.
cause.error=\nReason: {0}

repeat.notice=Continue ? (Enter no to stop)

homedir.notice=Ant Home Directory: {0}
buildfile.notice=Ant Build File: {0}
home-dir.name=Ant home directory
lib-dir.name=Library directory
task-lib-dir.name=Antlib directory
ext-dir.name=Extension directory

+ 0
- 56
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/ComponentException.java View File

@@ -1,56 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces;

/**
* An exception thrown by a Myrmidon component. This is a convenience
* class, which can be sub-classes to create exceptions for specific components.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class ComponentException
extends Exception
{
/**
* The Throwable that caused this exception to be thrown.
*/
private final Throwable m_throwable;

/**
* Constructs a non-cascaded exception.
*
* @param message The detail message for this exception.
*/
public ComponentException( final String message )
{
this( message, null );
}

/**
* Constructs a cascaded exception.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public ComponentException( final String message, final Throwable throwable )
{
super( message );
m_throwable = throwable;
}

/**
* Retrieve root cause of the exception.
*
* @return the root cause
*/
public final Throwable getCause()
{
return m_throwable;
}
}

+ 0
- 59
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/aspect/AspectManager.java View File

@@ -1,59 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.aspect;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.aspects.AspectHandler;

/**
* Manage and propogate Aspects..
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public interface AspectManager
extends AspectHandler
{
/** Role name for this interface. */
String ROLE = AspectManager.class.getName();

/**
* @return The names of all AspectHandlers managed.
*/
String[] getNames();

/**
* Dispatches aspect settings to the named AspectHandler.
* @param name The name of the AspectHandler to recieve the settings.
* @param parameters The parameter settings.
* @param elements The nested Configuration settings.
* @throws TaskException if the named AspectHandler doesn't exist,
* or it cannot handle the settings.
*/
void dispatchAspectSettings( String name, Parameters parameters, Configuration[] elements )
throws TaskException;

/**
* Adds a named aspect handler to the manager.
* @param name The name used to lookup the aspect handler.
* @param handler The aspect handler to add.
* @throws TaskException If an error occurs.
*/
void addAspectHandler( String name, AspectHandler handler )
throws TaskException;

/**
* Removes a named aspect handler from the manager.
* @param name The name of the handler to remove.
* @throws TaskException If the named handler doesn't exist.
*/
void removeAspectHandler( String name )
throws TaskException;
}

+ 0
- 33
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/builder/ProjectBuilder.java View File

@@ -1,33 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.builder;

import org.apache.myrmidon.interfaces.model.Project;

/**
* Interface implemented by components that build projects from sources.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
* @ant:role shorthand="project-builder"
*/
public interface ProjectBuilder
{
/** Role name for this interface. */
String ROLE = ProjectBuilder.class.getName();

/**
* build a project from source.
*
* @param source the project file path.
* @return the constructed Project
* @exception ProjectException if an error occurs
*/
Project build( String source )
throws ProjectException;
}

+ 0
- 41
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/builder/ProjectException.java View File

@@ -1,41 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.builder;

import org.apache.myrmidon.interfaces.ComponentException;

/**
* A cascading exception thrown on a problem constructing a Project model.
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*/
public class ProjectException
extends ComponentException
{
/**
* Constructs a non-cascaded exception.
*
* @param message The detail message for this exception.
*/
public ProjectException( final String message )
{
super( message );
}

/**
* Constructs a cascaded exception.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public ProjectException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}

+ 0
- 41
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/classloader/ClassLoaderException.java View File

@@ -1,41 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.classloader;

import org.apache.myrmidon.interfaces.ComponentException;

/**
* An exception thrown by the ClassLoaderManager.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public class ClassLoaderException
extends ComponentException
{
/**
* Constructs a non-cascaded exception.
*
* @param message The detail message for this exception.
*/
public ClassLoaderException( final String message )
{
super( message );
}

/**
* Constructs a cascaded exception.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public ClassLoaderException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}

+ 0
- 55
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/classloader/ClassLoaderManager.java View File

@@ -1,55 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.classloader;

import java.io.File;

/**
* Manages a classloader hierarchy.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public interface ClassLoaderManager
{
/** Role name for this interface. */
String ROLE = ClassLoaderManager.class.getName();

/**
* Returns the ClassLoader for a Jar file. The ClassLoader is created,
* if necessary. The ClassLoader's parent will include the common
* ClassLoader, along with any extensions required by the Jar file.
* It is guaranteed that each extension will appear at most once in the
* ClassLoader hierarchy, so that classes from the extension can be
* shared across the ClassLoaders returned by this method.
*
* @param jar the jar file containing the classes to load
* @return the classloader
* @throws ClassLoaderException on error
*/
ClassLoader getClassLoader( File jar ) throws ClassLoaderException;

/**
* Creates a ClassLoader for a set of files. See {@link #getClassLoader}
* for details.
*
* @param jars The Jar/zip files to create the classloader for. Use null
* or an empty array to use the common classloader.
* @return the created ClassLoader
* @throws ClassLoaderException on error
*/
ClassLoader createClassLoader( File[] jars ) throws ClassLoaderException;

/**
* Returns the common ClassLoader, which is the parent of all classloaders
* built by this ClassLoaderManager.
*
* @return the common ClassLoader.
*/
ClassLoader getCommonClassLoader();
}

+ 0
- 98
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/configurer/Configurer.java View File

@@ -1,98 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.configurer;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.myrmidon.api.TaskContext;

/**
* Class used to configure tasks.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
* @ant:role shorthand="configurer"
*/
public interface Configurer
{
/** Role name for this interface. */
String ROLE = Configurer.class.getName();

/**
* Configure an object based on a configuration in a particular context.
* This configuring can be done in different ways for different
* configurers.
*
* @param object the object
* @param configuration the configuration
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
void configureElement( Object object, Configuration configuration, TaskContext context )
throws ConfigurationException;

/**
* Configure named attribute of object in a particular context.
* This configuring can be done in different ways for different
* configurers.
*
* @param object the object
* @param name the attribute name
* @param value the attribute value
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
void configureAttribute( Object object, String name, String value, TaskContext context )
throws ConfigurationException;

/**
* Configure an object based on a configuration in a particular context.
* This configuring can be done in different ways for different
* configurers.
*
* The implementation of this method should only use the methods
* specified by the supplied class. It is an error for the specified
* class not to be a base class or interface compatible with specified
* object.
*
* @param object the object
* @param clazz the Class object to use during configuration
* @param configuration the configuration
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
void configureElement( Object object,
Class clazz,
Configuration configuration,
TaskContext context )
throws ConfigurationException;

/**
* Configure named attribute of object in a particular context.
* This configuring can be done in different ways for different
* configurers.
*
* The implementation of this method should only use the methods
* specified by the supplied class. It is an error for the specified
* class not to be a base class or interface compatible with specified
* object.
*
* @param object the object
* @param clazz the Class object to use during configuration
* @param name the attribute name
* @param value the attribute value
* @param context the Context
* @exception ConfigurationException if an error occurs
*/
void configureAttribute( Object object,
Class clazz,
String name,
String value,
TaskContext context )
throws ConfigurationException;
}

+ 0
- 29
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/converter/ConverterRegistry.java View File

@@ -1,29 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.converter;

/**
* Interface for registry for ConverterInfos.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public interface ConverterRegistry
{
/** Role name for this interface. */
String ROLE = ConverterRegistry.class.getName();

/**
* Register a converter
*
* @param className the className of converter
* @param source the source classname
* @param destination the destination classname
*/
void registerConverter( String className, String source, String destination );
}

+ 0
- 54
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/deployer/ConverterDefinition.java View File

@@ -1,54 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.deployer;

/**
* A specialised TypeDefinition which defines a converter.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public class ConverterDefinition
extends TypeDefinition
{
private final String m_sourceType;
private final String m_destinationType;

/**
* Creates a converter definition.
* @param className the name of the implementing class
* @param sourceType the name of the types converted from
* @param destinationType the name of the type converted to
*/
public ConverterDefinition( final String className,
final String sourceType,
final String destinationType )
{
super( className, "converter", className );
m_sourceType = sourceType;
m_destinationType = destinationType;
}

/**
* Provides the name of the type which this converter can convert from.
* @return the converter's source type.
*/
public String getSourceType()
{
return m_sourceType;
}

/**
* Provides the name of the type which this converter can convert to.
* @return the converter's destination type.
*/
public String getDestinationType()
{
return m_destinationType;
}
}

+ 0
- 55
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/deployer/Deployer.java View File

@@ -1,55 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.deployer;

import java.io.File;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;

/**
* This class deploys type libraries into a registry.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public interface Deployer
{
/** Role name for this interface. */
String ROLE = Deployer.class.getName();

/**
* Returns the deployer for the type libraries contained in a ClassLoader,
* creating the deployer if necessary.
*
* @param loader The ClassLoader to get the deployer for.
* @return the deployer for this loader.
* @exception DeploymentException if an error occurs.
*/
TypeDeployer createDeployer( ClassLoader loader )
throws DeploymentException;

/**
* Returns the deployer for a type library, creating the deployer if
* necessary.
*
* @param file the file containing the type library.
* @return the deployer for this type library.
* @exception DeploymentException if an error occurs.
*/
TypeDeployer createDeployer( File file )
throws DeploymentException;

/**
* Creates a deployer which is a child of this deployer.
* @param componentManager the ServiceManager for this component.
* @return a child deployer.
* @throws ServiceException if an error occurs.
*/
Deployer createChildDeployer( ServiceManager componentManager )
throws ServiceException;
}

+ 0
- 41
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/deployer/DeploymentException.java View File

@@ -1,41 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.deployer;

import org.apache.myrmidon.interfaces.ComponentException;

/**
* Exception to indicate error deploying.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class DeploymentException
extends ComponentException
{
/**
* Constructs a non-cascaded exception.
*
* @param message The detail message for this exception.
*/
public DeploymentException( final String message )
{
super( message );
}

/**
* Constructs a cascaded exception.
*
* @param message The detail message for this exception.
* @param throwable the root cause of the exception
*/
public DeploymentException( final String message, final Throwable throwable )
{
super( message, throwable );
}
}

+ 0
- 60
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/deployer/TypeDefinition.java View File

@@ -1,60 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.deployer;

/**
* A general-purpose type definition.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public class TypeDefinition
{
private final String m_name;
private final String m_role;
private final String m_classname;

/**
* Creates a TypeDefinition
* @param name the name of the type
* @param roleShorthand the name of the role played by this type
* @param className the name of the class implementing this type
*/
public TypeDefinition( final String name,
final String roleShorthand,
final String className )
{
m_name = name;
m_role = roleShorthand;
m_classname = className;
}

/**
* @return the type's implementation class name.
*/
public final String getClassname()
{
return m_classname;
}

/**
* @return the type's role.
*/
public final String getRole()
{
return m_role;
}

/**
* @return the type's name.
*/
public String getName()
{
return m_name;
}
}

+ 0
- 54
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/deployer/TypeDeployer.java View File

@@ -1,54 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.deployer;

/**
* A deployer for a type library. Allows individual elements from a type
* library to be deployed.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public interface TypeDeployer
{
/**
* Deploys everything in the type library.
* @throws DeploymentException
* If the library cannot be deployed.
*/
void deployAll()
throws DeploymentException;

/**
* Deploys a single type from the type library. The type definition is
* read from the type library descriptor.
*
* @param roleShorthand
* The shorthand name for the role.
*
* @param typeName
* The type name.
*
* @throws DeploymentException
* If the type cannot be deployed.
*/
void deployType( String roleShorthand, String typeName )
throws DeploymentException;

/**
* Deploys a single type from the type library.
*
* @param typeDef
* The type definition.
*
* @throws DeploymentException
* If the type cannot be deployed.
*/
void deployType( TypeDefinition typeDef )
throws DeploymentException;
}

+ 0
- 65
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/embeddor/Embeddor.java View File

@@ -1,65 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.embeddor;

import org.apache.avalon.framework.parameters.Parameters;
import org.apache.myrmidon.interfaces.model.Project;
import org.apache.myrmidon.interfaces.workspace.Workspace;
import org.apache.myrmidon.listeners.ProjectListener;
import java.util.Map;

/**
* Interface through which you embed Myrmidon into applications.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public interface Embeddor
{
/** Role name for this interface. */
String ROLE = Embeddor.class.getName();

/**
* Creates a project from a project file.
*
* @param location The path to the project file.
* @param type The project file type. If null the type is inferred from the
* project file name.
* @param parameters The project builder parameters.
* @return the created Project
* @throws Exception If an error occurs creating the Project.
*
* @todo Should location be a URL or will it automatically assume file
* unless there is a protocol section like ftp:, file: etc
* @todo parameters needs more thought put into it.
*/
Project createProject( String location, String type, Parameters parameters )
throws Exception;

/**
* Creates a project listener.
*
* @param name The shorthand name of the listener.
* @return the listener.
* @throws Exception If the listener could not be created.
*/
ProjectListener createListener( String name )
throws Exception;

/**
* Creates a {@link Workspace} that can be used to execute projects.
*
* @param properties The properties to define in the workspace. These
* are added to the properties in the embeddor's
* root execution frame.
* @return the Workspace
* @throws Exception If the workspace could not be created.
*/
Workspace createWorkspace( Map properties )
throws Exception;
}

+ 0
- 23
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionContainer.java View File

@@ -1,23 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.executor;

/**
* This interface is used to supply a root execution frame to a container
* that executes tasks.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public interface ExecutionContainer
{
/**
* Sets the root execution frame for the container.
*/
void setRootExecutionFrame( ExecutionFrame frame ) throws Exception;
}

+ 0
- 46
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/ExecutionFrame.java View File

@@ -1,46 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.executor;

import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.myrmidon.interfaces.property.PropertyStore;

/**
* An Execution Frame represents the scope in which tasks are executed.
* The scope may include an entire workspace, a project, target, or
* individual task.
*
* <p>An Execution Frame bundles together all of the context required to
* execute tasks - that is, a set of properties, a set of services, and
* a logger.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public interface ExecutionFrame
{
/** Role name for this interface. */
String ROLE = ExecutionFrame.class.getName();

/**
* Returns the set of services to use to create, configure, and execute
* tasks.
*/
ServiceManager getServiceManager();

/**
* Returns the logger which is to be supplied to tasks.
*/
Logger getLogger();

/**
* Returns the set of properties to be supplied to tasks.
*/
PropertyStore getProperties();
}

+ 0
- 33
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/executor/Executor.java View File

@@ -1,33 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.executor;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.myrmidon.api.TaskException;

/**
* Engine inteface that should be implemented by all tasklet engines.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public interface Executor
{
/** Role name for this interface. */
String ROLE = Executor.class.getName();

/**
* execute a task.
*
* @param task the configruation data for task
* @param frame The frame in which the task is executed.
* @exception TaskException if an error occurs
*/
void execute( Configuration task, ExecutionFrame frame )
throws TaskException;
}

+ 0
- 31
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/extensions/ExtensionManager.java View File

@@ -1,31 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.extensions;

import org.apache.avalon.excalibur.extension.Extension;
import org.apache.avalon.excalibur.extension.OptionalPackage;

/**
* Maintains a set of optional packages.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public interface ExtensionManager
{
/** Role name for this interface. */
String ROLE = ExtensionManager.class.getName();

/**
* Locates the optional package which best matches a required extension.
*
* @param extension the extension to locate an optional package
* @return the optional package, or null if not found.
*/
OptionalPackage getOptionalPackage( Extension extension );
}

+ 0
- 356
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/DefaultNameValidator.java View File

@@ -1,356 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.model;

import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;

/**
* Simple helper class which determines the validity of names used
* in ant projects.
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*/
public class DefaultNameValidator
implements NameValidator
{
private static final Resources REZ =
ResourceManager.getPackageResources( DefaultNameValidator.class );

/**
* Determines whether the supplied name may include surrounding whitespace.
*/
private boolean m_allowSurroundingWhitespace;

// Settings for initial characters.
private boolean m_allowInitialDigit;
private String m_additionalInitialCharacters;

// Settings for internal characters.
private boolean m_allowInternalDigits;
private boolean m_allowInternalWhitespace;
private String m_additionalInternalCharacters;

/**
* Construct a default name validator.
* Letters, digits and "_" are permitted as initial character.
* Letters, digits, whitespace and "_-." are permitted as internal characters.
* Surrounding whitespace is not permitted.
*/
public DefaultNameValidator()
{
this( false, true, "_", true, true, "_-." );
}

/**
* Contstruct a NameValidator with the specified rules.
* @param allowSurroundingWhitespace
* specified if names are trimmed before checking
* @param allowInitialDigit
* specifies if digits are permitted as intial characters
* @param additionalInitialCharacters
* extra characters to allow as initial characters.
* @param allowInternalDigits
* specifies if digits are permitted as internal characters
* @param allowInternalWhitespace
* specifies if whitespace is permitted internally in names
* @param additionalInternalCharacters
* extra characters permitted in names
*/
public DefaultNameValidator( final boolean allowSurroundingWhitespace,
final boolean allowInitialDigit,
final String additionalInitialCharacters,
final boolean allowInternalDigits,
final boolean allowInternalWhitespace,
final String additionalInternalCharacters )
{
setAllowSurroundingWhitespace( allowSurroundingWhitespace );
setAllowInitialDigit( allowInitialDigit );
setAdditionalInitialCharacters( additionalInitialCharacters );
setAllowInternalDigits( allowInternalDigits );
setAllowInternalWhitespace( allowInternalWhitespace );
setAdditionalInternalCharacters( additionalInternalCharacters );
}

/**
* Creates a valid name based on the supplied string value, removing invalid
* characters. If no valid characters are present, an exception is thrown.
* @param baseName the name used to construct the valid name
* @return a valid name based on the supplied name.
* @throws Exception if no valid name could be constructed.
*/
public String makeValidName( final String baseName ) throws Exception
{
final StringBuffer buffer = new StringBuffer( baseName );
while( buffer.length() > 0 && !isValidInitialChar( buffer.charAt( 0 ) ) )
{
buffer.delete( 0, 1 );
}
if( buffer.length() == 0 )
{
final String message = REZ.getString( "name.could-not-create.error", baseName );
throw new Exception( message );
}

for( int i = 1; i < buffer.length(); )
{
if( !isValidInternalChar( buffer.charAt( i ) ) )
{
buffer.delete( i, i + 1 );
}
else
{
i++;
}
}

return buffer.toString();
}

/**
* @see NameValidator
*/
public void validate( final String name ) throws Exception
{
String testName = name;

// If surrounding whitespace is allowed, trim it. Otherwise, check.
if( m_allowSurroundingWhitespace )
{
testName = testName.trim();
}
else
{
checkSurroundingWhitespace( testName );
}

// Zero-length name is invalid.
if( testName.length() == 0 )
{
final String message = REZ.getString( "name.zero-char-name.error" );
throw new Exception( message );
}

// Check first character.
final char initial = testName.charAt( 0 );
checkInitialCharacter( initial, testName );

// Check the rest of the characters.
for( int i = 1; i < testName.length(); i++ )
{
final char internal = testName.charAt( i );
checkInternalCharacter( internal, testName );
}
}

/**
* Checks if the supplied character is permitted as an internal character.
* @throws Exception if the character is not permitted
*/
private void checkInternalCharacter( final char internal, final String name )
throws Exception
{
if( !isValidInternalChar( internal ) )
{
final String message = REZ.getString( "name.invalid-internal-char.error",
name,
describeValidInternalChars() );
throw new Exception( message );
}
}

/**
* Checks if the supplied character is permitted as an internal character.
* @throws Exception if the character is not permitted
*/
private void checkInitialCharacter( final char initial, final String name )
throws Exception
{
if( !isValidInitialChar( initial ) )
{
final String message = REZ.getString( "name.invalid-initial-char.error",
name,
describeValidInitialChars() );
throw new Exception( message );
}
}

/**
* Checks the name for surrounding whitespace
* @throws Exception if surrounding whitespace is found
*/
private void checkSurroundingWhitespace( final String testName )
throws Exception
{
if( testName.length() == 0 )
{
return;
}

if( Character.isWhitespace( testName.charAt( 0 ) ) ||
Character.isWhitespace( testName.charAt( testName.length() - 1 ) ) )
{
final String message =
REZ.getString( "name.enclosing-whitespace.error", testName );
throw new Exception( message );
}
}

/**
* Determines if a character is allowed as the first character in a name.
* Valid characters are Letters, Digits, and defined initial characters ("_").
* @param chr the character to be assessed
* @return <code>true</code> if the character can be the first character of a name
*/
protected boolean isValidInitialChar( final char chr )
{
if( Character.isLetter( chr ) )
{
return true;
}

if( m_allowInitialDigit
&& Character.isDigit( chr ) )
{
return true;
}

if( m_additionalInitialCharacters.indexOf( chr ) != -1 )
{
return true;
}

return false;
}

/**
* Determines if a character is allowed as a non-initial character in a name.
* Valid characters are Letters, Digits, whitespace, and defined
* internal characters ("_-.").
* @param chr the character to be assessed
* @return <code>true</code> if the character can be included in a name
*/
protected boolean isValidInternalChar( final char chr )
{
if( Character.isLetter( chr ) )
{
return true;
}

if( m_allowInternalDigits
&& Character.isDigit( chr ) )
{
return true;
}

if( m_allowInternalWhitespace
&& Character.isWhitespace( chr ) )
{
return true;
}

if( m_additionalInternalCharacters.indexOf( chr ) != -1 )
{
return true;
}

return false;
}

/**
* Builds a message detailing the valid initial characters.
*/
protected String describeValidInitialChars()
{
StringBuffer validChars = new StringBuffer( "letters" );
if( m_allowInitialDigit )
{
validChars.append( ", digits" );
}
validChars.append( ", and \"" );
validChars.append( m_additionalInitialCharacters );
validChars.append( "\"" );
return validChars.toString();
}

/**
* Builds a message detailing the valid internal characters.
*/
protected String describeValidInternalChars()
{
StringBuffer validChars = new StringBuffer( "letters" );
if( m_allowInternalDigits )
{
validChars.append( ", digits" );
}
if( m_allowInternalWhitespace )
{
validChars.append( ", whitespace" );
}
validChars.append( ", and \"" );
validChars.append( m_additionalInternalCharacters );
validChars.append( "\"" );
return validChars.toString();
}

/**
* @param allowSurroundingWhitespace
* specified if names are trimmed before checking
*/
public void setAllowSurroundingWhitespace( boolean allowSurroundingWhitespace )
{
m_allowSurroundingWhitespace = allowSurroundingWhitespace;
}

/**
* @param allowInitialDigit
* specifies if digits are permitted as intial characters
*/
public void setAllowInitialDigit( boolean allowInitialDigit )
{
m_allowInitialDigit = allowInitialDigit;
}

/**
* @param additionalInitialCharacters
* extra characters to allow as initial characters.
*/
public void setAdditionalInitialCharacters( String additionalInitialCharacters )
{
m_additionalInitialCharacters = additionalInitialCharacters;
}

/**
* @param allowInternalDigits
* specifies if digits are permitted as internal characters
*/
public void setAllowInternalDigits( boolean allowInternalDigits )
{
m_allowInternalDigits = allowInternalDigits;
}

/**
* @param allowInternalWhitespace
* specifies if whitespace is permitted internally in names
*/
public void setAllowInternalWhitespace( boolean allowInternalWhitespace )
{
m_allowInternalWhitespace = allowInternalWhitespace;
}

/**
* @param additionalInternalCharacters
* extra characters permitted in names
*/
public void setAdditionalInternalCharacters( String additionalInternalCharacters )
{
m_additionalInternalCharacters = additionalInternalCharacters;
}

}

+ 0
- 46
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/Dependency.java View File

@@ -1,46 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.model;

/**
* A dependency for a target.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public class Dependency
{
private final String m_projectName;
private final String m_targetName;

/**
* @param projectName The project containing the depended-on target.
* @param targetName The name of the depended-on target.
*/
public Dependency( final String projectName, final String targetName )
{
m_projectName = projectName;
m_targetName = targetName;
}

/**
* @return The name of the project containing the depended-on target.
*/
public String getProjectName()
{
return m_projectName;
}

/**
* @return The name of the depended-on target.
*/
public String getTargetName()
{
return m_targetName;
}
}

+ 0
- 26
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/NameValidator.java View File

@@ -1,26 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.model;

/**
* Determines the validity of names used in projects.
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*/
public interface NameValidator
{
/**
* Validates the supplied name, failing if it is not.
*
* @param name The name to be validated.
* @throws Exception is the supplied name is not valid.
*/
void validate( String name )
throws Exception;
}

+ 0
- 100
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/Project.java View File

@@ -1,100 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.model;

import java.io.File;

/**
* Abstraction used to interact with projects.
* Implementations may choose to structure it anyway they choose.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public interface Project
{
/** Role name for this interface. */
String ROLE = Project.class.getName();

/** Property which holds the name of currently executing project */
String PROJECT = "myrmidon.project.name";

// the name of currently executing project
//String PROJECT_FILE = "myrmidon.project.file";

// the name of currently executing target
//String TARGET = "myrmidon.target.name";

/**
* @return the project name.
*
* TODO: Determine if projects should carry their own name. Breaks IOC but
* Can be useful as project files embed own name (or should that be description).
*/
String getProjectName();

/**
* Get the imports for project.
*
* @return the imports
*/
TypeLib[] getTypeLibs();

/**
* Get names of projects referenced by this project.
*
* @return the names
*/
String[] getProjectNames();

/**
* Retrieve project referenced by this project.
*
* @param name the project name
* @return the Project or null if none by that name
*/
Project getProject( String name );

/**
* Get name of default target.
*
* @return the default target name
*/
String getDefaultTargetName();

/**
* Retrieve implicit target.
* The implicit target is top level tasks.
* Currently restricted to property tasks.
*
* @return the Target
*/
Target getImplicitTarget();

/**
* Retrieve a target by name.
*
* @param name the name of target
* @return the Target or null if no target exists with name
*/
Target getTarget( String name );

/**
* Retrieve names of all targets in project.
*
* @return the iterator of project names
*/
String[] getTargetNames();

/**
* Retrieve base directory of project.
*
* @return the projects base directory
*/
File getBaseDirectory();
}

+ 0
- 6
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/Resources.properties View File

@@ -1,6 +0,0 @@
# Name validation
name.zero-char-name.error=Name "" is invalid, as it contains no characters.
name.enclosing-whitespace.error=Name "{0}" is invalid, as it contains enclosing whitespace.
name.invalid-initial-char.error=Name "{0}" is invalid, as it begins with an illegal character. Names can start with {1}.
name.invalid-internal-char.error=Name "{0}" is invalid, as it contains an illegal character. Permitted name characters are {1}.
name.could-not-create.error=Could not valid name from "{0}".

+ 0
- 65
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/Target.java View File

@@ -1,65 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.model;

import java.util.ArrayList;
import org.apache.avalon.framework.configuration.Configuration;

/**
* Targets in build file.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class Target
{
private final ArrayList m_dependencies = new ArrayList();
private final ArrayList m_tasks = new ArrayList();

/**
* Constructs a target.
* @param tasks The task models for all tasks in this target.
* @param dependencies The dependencies for executing this target.
*/
public Target( final Configuration[] tasks,
final Dependency[] dependencies )
{
for( int i = 0; i < tasks.length; i++ )
{
m_tasks.add( tasks[ i ] );
}

if( null != dependencies )
{
for( int i = 0; i < dependencies.length; i++ )
{
m_dependencies.add( dependencies[ i ] );
}
}
}

/**
* Get dependencies of target
*
* @return the dependency list
*/
public final Dependency[] getDependencies()
{
return (Dependency[])m_dependencies.toArray( new Dependency[ 0 ] );
}

/**
* Get tasks in target
*
* @return the target list
*/
public final Configuration[] getTasks()
{
return (Configuration[])m_tasks.toArray( new Configuration[ 0 ] );
}
}

+ 0
- 93
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/model/TypeLib.java View File

@@ -1,93 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.model;

/**
* Imports in a build file.
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class TypeLib
{
//Name of library (this is location independent)
private final String m_library;

//Do we need this??
//private final String m_namespace;

//The role of object to be imported
private final String m_role;

//The name of type instance
private final String m_name;

/**
* Create a import for a complete library.
* @param library The name of the library to import.
*/
public TypeLib( final String library )
{
this( library, null, null );
}

/**
* Create an import for a single type from a library.
* @param library The library containing the type.
* @param role The role for the imported type.
* @param name The name of the imported type.
*/
public TypeLib( final String library, final String role, final String name )
{
m_library = library;
m_role = role;
m_name = name;

//If only one of name or type is null, throw an exception
if( null == m_role || null == m_name )
{
if( null != m_role || null != m_name )
{
throw new IllegalArgumentException( "Can not have an import that specifies " +
"only one of; name or role" );
}
}
}

/**
* Get role
*
* @return the role
*/
public final String getRole()
{
return m_role;
}

/**
* Get name of imported
*
* @return the name
*/
public final String getName()
{
return m_name;
}

/**
* Get name of library
*
* @return the library name
*/
public final String getLibrary()
{
return m_library;
}
}



+ 0
- 119
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/MapPropertyStore.java View File

@@ -1,119 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.property;

import java.util.Map;
import java.util.HashMap;
import org.apache.myrmidon.api.TaskException;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;

/**
* A simple unscoped, unsynchronized property store which is backed by a Map.
*
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
* @version $Revision$ $Date$
*/
public class MapPropertyStore
implements PropertyStore
{
private static final Resources REZ =
ResourceManager.getPackageResources( MapPropertyStore.class );

private final Map m_properties = new HashMap();

/**
* Creates an empty store.
*/
public MapPropertyStore()
{
}

/**
* Creates a store containing the given properties.
*/
public MapPropertyStore( final Map properties )
{
m_properties.putAll( properties );
}

/**
* Return <code>true</code> if the specified property is set.
*
* @param name the name of property
*/
public boolean isPropertySet( final String name )
{
return m_properties.containsKey( name );
}

/**
* Retrieve the value of specified property.
*
* @param name the name of the property
* @return the value of the property. Never returns null.
* @throws TaskException if there is no such property, or on error
* retrieving property, such as an invalid property name.
*/
public Object getProperty( final String name )
throws TaskException
{
final Object value = m_properties.get( name );
if( value == null )
{
final String message = REZ.getString( "unknown-property.error", name );
throw new TaskException( message );
}
return value;
}

/**
* Retrieve a copy of all the properties that are "in-scope"
* for store.
*
* @return a copy of all the properties that are "in-scope"
* for store.
* @throws TaskException if theres an error retrieving propertys
*/
public Map getProperties()
throws TaskException
{
return new HashMap( m_properties );
}

/**
* Set the property with specified name to specified value.
* The specific implementation will apply various rules
* before setting the property.
*
* @param name the name of property
* @param value the value of property
* @throws TaskException if property can not be set
*/
public void setProperty( String name, Object value )
throws TaskException
{
m_properties.put( name, value );
}

/**
* Return a child PropertyStore with specified name.
* This is to allow support for scoped stores. However a
* store may choose to be unscoped and just return a
* reference to itself.
*
* @param name the name of child store
* @return the child store
* @throws TaskException if theres an error creating child store
*/
public PropertyStore createChildStore( String name )
throws TaskException
{
return this;
}
}

+ 0
- 41
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/PropertyResolver.java View File

@@ -1,41 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.property;

import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.api.TaskContext;

/**
*
* Provides a service for the resolution of property identifiers within
* String content.
*
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a>
* @version $Revision$ $Date$
*
* @ant:role shorthand="property-resolver"
*/
public interface PropertyResolver
{
/** Role name for this interface. */
String ROLE = PropertyResolver.class.getName();

/**
* Resolve a string property. This evaluates all property
* substitutions based on specified contex.
* Rules used for property resolution are implementation dependent.
*
* @param value the value to resolve, which may contain property identifiers
* @param context the set of properties to resolve against.
* @return the resolved content
* @exception TaskException if an error occurs
*/
Object resolveProperties( final String value,
final TaskContext context )
throws TaskException;
}

+ 0
- 86
proposal/myrmidon/src/java/org/apache/myrmidon/interfaces/property/PropertyStore.java View File

@@ -1,86 +0,0 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.myrmidon.interfaces.property;

import java.util.Map;
import org.apache.myrmidon.api.TaskException;

/**
* This component stores and manages properties. It is also
* responsible for instituting the various policies regarding
* propertys. ie It will enforce rules regarding
*
* <ul>
* <li>Valid property names?</li>
* <li>Are propertys mutable?</li>
* <li>Are propertys scoped?</li>
* <li>Is mapping between name and value correct?</li>
* </ul>
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public interface PropertyStore
{
/** Role name for this interface. */
String ROLE = PropertyStore.class.getName();

/**
* Set the property with specified name to specified value.
* The specific implementation will apply various rules
* before setting the property.
*
* @param name the name of property
* @param value the value of property
* @throws TaskException if property can not be set
*/
void setProperty( String name, Object value )
throws TaskException;

/**
* Return <code>true</code> if the specified property is set.
*
* @param name the name of property
*/
boolean isPropertySet( String name );

/**
* Retrieve the value of specified property.
*
* @param name the name of the property
* @return the value of the property. Never returns null.
* @throws TaskException if there is no such property, or on error
* retrieving property, such as an invalid property name.
*/
Object getProperty( String name )
throws TaskException;

/**
* Retrieve a copy of all the properties that are "in-scope"
* for store.
*
* @return a copy of all the properties that are "in-scope"
* for store.
* @throws TaskException if theres an error retrieving propertys
*/
Map getProperties()
throws TaskException;

/**
* Return a child PropertyStore with specified name.
* This is to allow support for scoped stores. However a
* store may choose to be unscoped and just return a
* reference to itself.
*
* @param name the name of child store
* @return the child store
* @throws TaskException if theres an error creating child store
*/
PropertyStore createChildStore( String name )
throws TaskException;
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save