* Removed "if" and "unless" conditions from targets. * Moved parsing of "project->target" dependencies out of DefaultWorkspace, into DefaultProjectBuilder. * DefaultWorkspace now detects cycles in the target dependency graph. * DefaultWorkspace now executes the implicit target for referenced projects. * Changes to DefaultProjectBuilder error reporting. * Added a few more test cases for DefaultProjectBuilder. Unit Tests: * Moved AbstractComponentTest.getLogger() up to AbstractMyrmidonTest. * Removed AbstractComponentTest.setup(). Components are now created on demand. * Use BasicLogger in unit tests. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271835 13f79535-47bb-0310-9956-ffa450edef68master
@@ -0,0 +1,3 @@ | |||
<!-- Project with invalid version --> | |||
<project version="ant2"> | |||
</project> |
@@ -0,0 +1 @@ | |||
this ain't xml. |
@@ -0,0 +1,3 @@ | |||
<!-- Use all the defaults --> | |||
<project version="2.0"> | |||
</project> |
@@ -0,0 +1,3 @@ | |||
<!-- Project with mismatched version --> | |||
<project version="1.0.2"> | |||
</project> |
@@ -0,0 +1,3 @@ | |||
<!-- Project with no version attribute --> | |||
<project> | |||
</project> |
@@ -0,0 +1,3 @@ | |||
<!-- Project with a non-default base directory --> | |||
<project version="2.0" basedir="other-base-dir"> | |||
</project> |
@@ -0,0 +1,3 @@ | |||
<!-- Project with a non-default default target --> | |||
<project version="2.0" default="some-target"> | |||
</project> |
@@ -0,0 +1,3 @@ | |||
<!-- Project with non-default name --> | |||
<project name="some-project" version="2.0"> | |||
</project > |
@@ -8,8 +8,6 @@ | |||
package org.apache.myrmidon.components.builder; | |||
import java.io.File; | |||
import java.net.MalformedURLException; | |||
import java.net.URL; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import javax.xml.parsers.SAXParser; | |||
@@ -23,13 +21,10 @@ 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.framework.conditions.AndCondition; | |||
import org.apache.myrmidon.framework.conditions.Condition; | |||
import org.apache.myrmidon.framework.conditions.IsSetCondition; | |||
import org.apache.myrmidon.framework.conditions.NotCondition; | |||
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; | |||
@@ -78,31 +73,39 @@ public class DefaultProjectBuilder | |||
private Project build( final File file, final HashMap projects ) | |||
throws ProjectException | |||
{ | |||
final URL systemID = extractURL( file ); | |||
final Project result = (Project)projects.get( systemID.toString() ); | |||
if( null != result ) | |||
try | |||
{ | |||
return result; | |||
} | |||
// Parse the project file | |||
final Configuration configuration = parseProject( systemID ); | |||
// Check for cached project | |||
final String systemID = extractURL( file ); | |||
final Project result = (Project)projects.get( systemID ); | |||
if( null != result ) | |||
{ | |||
return result; | |||
} | |||
// Build the project model | |||
final DefaultProject project = buildProject( file, configuration ); | |||
// Parse the project file | |||
final Configuration configuration = parseProject( systemID ); | |||
projects.put( systemID.toString(), project ); | |||
// 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 ); | |||
// Build using all top-level attributes | |||
buildTopLevelProject( project, configuration, projects ); | |||
return project; | |||
return project; | |||
} | |||
catch( Exception e ) | |||
{ | |||
final String message = REZ.getString( "ant.project-build.error", file.getAbsolutePath() ); | |||
throw new ProjectException( message, e ); | |||
} | |||
} | |||
/** | |||
* Parses the project. | |||
*/ | |||
private Configuration parseProject( final URL systemID ) | |||
private Configuration parseProject( final String systemID ) | |||
throws ProjectException | |||
{ | |||
try | |||
@@ -117,13 +120,13 @@ public class DefaultProjectBuilder | |||
parser.setContentHandler( handler ); | |||
parser.setErrorHandler( handler ); | |||
parser.parse( systemID.toString() ); | |||
parser.parse( systemID ); | |||
return handler.getConfiguration(); | |||
} | |||
catch( Exception e ) | |||
{ | |||
String message = REZ.getString( "ant.project-parse.error" ); | |||
final String message = REZ.getString( "ant.project-parse.error" ); | |||
throw new ProjectException( message, e ); | |||
} | |||
} | |||
@@ -164,7 +167,7 @@ public class DefaultProjectBuilder | |||
File baseDirectory = file.getParentFile(); | |||
if( baseDirectoryName != null ) | |||
{ | |||
baseDirectory = new File( baseDirectory, baseDirectoryName ); | |||
baseDirectory = FileUtil.resolveFile( baseDirectory, baseDirectoryName ); | |||
} | |||
baseDirectory = baseDirectory.getAbsoluteFile(); | |||
@@ -257,7 +260,7 @@ public class DefaultProjectBuilder | |||
{ | |||
final String message = | |||
REZ.getString( "ant.malformed.version", versionString ); | |||
throw new ProjectException( message, e ); | |||
throw new ProjectException( message ); | |||
} | |||
} | |||
@@ -338,7 +341,7 @@ public class DefaultProjectBuilder | |||
final Configuration[] implicitTasks = | |||
(Configuration[])implicitTaskList.toArray( new Configuration[ 0 ] ); | |||
final Target implicitTarget = new Target( null, implicitTasks, null ); | |||
final Target implicitTarget = new Target( implicitTasks, null ); | |||
project.setImplicitTarget( implicitTarget ); | |||
} | |||
@@ -378,26 +381,30 @@ public class DefaultProjectBuilder | |||
// Build the URL of the referenced projects | |||
final File baseDirectory = project.getBaseDirectory(); | |||
final File file = FileUtil.resolveFile( baseDirectory, location ); | |||
final String systemID = extractURL( file ).toString(); | |||
// Locate the referenced project, building it if necessary | |||
Project other = (Project)projects.get( systemID ); | |||
if( null == other ) | |||
{ | |||
other = build( file, projects ); | |||
} | |||
final Project other = build( file, projects ); | |||
// Add the reference | |||
project.addProject( name, other ); | |||
} | |||
private URL extractURL( final File file ) throws ProjectException | |||
/** | |||
* 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.toURL(); | |||
return file.getCanonicalFile().toURL().toString(); | |||
} | |||
catch( MalformedURLException e ) | |||
catch( Exception e ) | |||
{ | |||
final String message = REZ.getString( "ant.project-unexpected.error" ); | |||
throw new ProjectException( message, e ); | |||
@@ -443,8 +450,6 @@ public class DefaultProjectBuilder | |||
{ | |||
final String name = target.getAttribute( "name", null ); | |||
final String depends = target.getAttribute( "depends", null ); | |||
final String ifCondition = target.getAttribute( "if", null ); | |||
final String unlessCondition = target.getAttribute( "unless", null ); | |||
verifyTargetName( name, target ); | |||
@@ -454,10 +459,8 @@ public class DefaultProjectBuilder | |||
getLogger().debug( message ); | |||
} | |||
final String[] dependencies = buildDependsList( depends, target ); | |||
final Condition condition = buildCondition( ifCondition, unlessCondition ); | |||
final Target defaultTarget = | |||
new Target( condition, target.getChildren(), dependencies ); | |||
final Dependency[] dependencies = buildDependsList( depends, target ); | |||
final Target defaultTarget = new Target( target.getChildren(), dependencies ); | |||
//add target to project | |||
project.addTarget( name, defaultTarget ); | |||
@@ -485,70 +488,54 @@ public class DefaultProjectBuilder | |||
} | |||
} | |||
private String[] buildDependsList( final String depends, final Configuration target ) | |||
private Dependency[] buildDependsList( final String depends, final Configuration target ) | |||
throws ProjectException | |||
{ | |||
String[] dependencies = null; | |||
//apply depends attribute | |||
if( null != depends ) | |||
if( null == depends ) | |||
{ | |||
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( 0 == dependency.length() ) | |||
{ | |||
final String message = REZ.getString( "ant.target-bad-dependency.error", | |||
target.getName(), | |||
target.getLocation() ); | |||
throw new ProjectException( message ); | |||
} | |||
if( getLogger().isDebugEnabled() ) | |||
{ | |||
final String message = REZ.getString( "ant.target-dependency.notice", dependency ); | |||
getLogger().debug( message ); | |||
} | |||
dependsList.add( dependency ); | |||
} | |||
dependencies = (String[])dependsList.toArray( new String[ 0 ] ); | |||
return null; | |||
} | |||
return dependencies; | |||
} | |||
private Condition buildCondition( final String ifCondition, | |||
final String unlessCondition ) | |||
{ | |||
final AndCondition condition = new AndCondition(); | |||
final String[] elements = StringUtil.split( depends, "," ); | |||
final ArrayList dependsList = new ArrayList(); | |||
// Add the 'if' condition | |||
if( null != ifCondition ) | |||
for( int i = 0; i < elements.length; i++ ) | |||
{ | |||
final String dependency = elements[ i ].trim(); | |||
if( getLogger().isDebugEnabled() ) | |||
{ | |||
final String message = REZ.getString( "ant.target-if.notice", ifCondition ); | |||
final String message = REZ.getString( "ant.target-dependency.notice", dependency ); | |||
getLogger().debug( message ); | |||
} | |||
condition.add( new IsSetCondition( ifCondition ) ); | |||
} | |||
// Add the 'unless' condition | |||
if( null != unlessCondition ) | |||
{ | |||
if( getLogger().isDebugEnabled() ) | |||
// Split project->target dependencies | |||
final int sep = dependency.indexOf( "->" ); | |||
final String projectName; | |||
final String targetName; | |||
if( sep != -1 ) | |||
{ | |||
final String message = REZ.getString( "ant.target-unless.notice", unlessCondition ); | |||
getLogger().debug( message ); | |||
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 ); | |||
} | |||
condition.add( new NotCondition( new IsSetCondition( unlessCondition ) ) ); | |||
dependsList.add( new Dependency( projectName, targetName ) ); | |||
} | |||
return condition; | |||
return (Dependency[])dependsList.toArray( new Dependency[dependsList.size() ] ); | |||
} | |||
} |
@@ -9,11 +9,10 @@ ati.attribue-unquoted.error=Expecting the value of attribute {0} to be enclosed | |||
ant.project-banner.notice=Project {0} base directory: {1}. | |||
ant.target-parse.notice=Parsing target: {0}. | |||
ant.target-if.notice=Target if condition: {0} | |||
ant.target-unless.notice=Target unless condition: {0} | |||
ant.target-dependency.notice=Target dependency: {0} | |||
ant.project-unexpected.error=Unexpected error building project. | |||
ant.project-parse.error=Error parsing 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. | |||
@@ -26,9 +25,10 @@ ant.import-malformed.error=Malformed import at {0}. If name or type attribute is | |||
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=Malformed version string "{0}" specified in version attribute of project. | |||
ant.version-missing.error=Missing version attribute from project. | |||
ant.bad-version.error=Incompatible build file version detected. Expected {0} but found {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. | |||
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,0 +1,3 @@ | |||
#AbstractPropertyResolver | |||
prop.mismatched-braces.error=Malformed property with mismatched }'s. | |||
prop.missing-value.error=Unable to find "{0}" to expand during property resolution. |
@@ -15,9 +15,9 @@ import org.apache.avalon.excalibur.i18n.Resources; | |||
import org.apache.avalon.excalibur.io.FileUtil; | |||
import org.apache.avalon.framework.context.Context; | |||
import org.apache.avalon.framework.context.ContextException; | |||
import org.apache.avalon.framework.logger.Logger; | |||
import org.apache.avalon.framework.service.ServiceException; | |||
import org.apache.avalon.framework.service.ServiceManager; | |||
import org.apache.avalon.framework.logger.Logger; | |||
import org.apache.myrmidon.api.TaskContext; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.interfaces.model.DefaultNameValidator; | |||
@@ -60,7 +60,6 @@ public class DefaultTaskContext | |||
m_parent = parent; | |||
m_serviceManager = serviceManager; | |||
m_logger = logger; | |||
//m_propertyResolver = (PropertyResolver)getService( PropertyResolver.class ); | |||
} | |||
/** | |||
@@ -26,12 +26,12 @@ 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.framework.conditions.Condition; | |||
import org.apache.myrmidon.interfaces.deployer.Deployer; | |||
import org.apache.myrmidon.interfaces.deployer.DeploymentException; | |||
import org.apache.myrmidon.interfaces.deployer.TypeDeployer; | |||
import org.apache.myrmidon.interfaces.executor.ExecutionFrame; | |||
import org.apache.myrmidon.interfaces.executor.Executor; | |||
import org.apache.myrmidon.interfaces.model.Dependency; | |||
import org.apache.myrmidon.interfaces.model.Project; | |||
import org.apache.myrmidon.interfaces.model.Target; | |||
import org.apache.myrmidon.interfaces.model.TypeLib; | |||
@@ -123,9 +123,7 @@ public class DefaultWorkspace | |||
m_listenerSupport.projectStarted( project.getProjectName() ); | |||
executeTarget( project, "<init>", project.getImplicitTarget(), entry.getFrame() ); | |||
execute( project, target, entry ); | |||
executeTarget( entry, target ); | |||
m_listenerSupport.projectFinished( project.getProjectName() ); | |||
} | |||
@@ -307,105 +305,130 @@ public class DefaultWorkspace | |||
/** | |||
* Helper method to execute a target. | |||
* | |||
* @param project the Project | |||
* @param targetName the name of the target | |||
* @param entry the context | |||
* @param entry the project to execute | |||
* @param targetName the name of the target to execute | |||
* @exception TaskException if an error occurs | |||
*/ | |||
private void execute( final Project project, | |||
final String targetName, | |||
final ProjectEntry entry ) | |||
private void executeTarget( final ProjectEntry entry, | |||
final String targetName ) | |||
throws TaskException | |||
{ | |||
final int index = targetName.indexOf( "->" ); | |||
if( -1 != index ) | |||
// Locate the target | |||
final Target target = entry.getProject().getTarget( targetName ); | |||
if( null == target ) | |||
{ | |||
final String name = targetName.substring( 0, index ); | |||
final String otherTargetName = targetName.substring( index + 2 ); | |||
final String message = REZ.getString( "no-target.error", targetName ); | |||
throw new TaskException( message ); | |||
} | |||
final Project otherProject = getProject( name, project ); | |||
final ProjectEntry otherEntry = getProjectEntry( otherProject ); | |||
executeTarget( entry, targetName, target ); | |||
} | |||
//Execute target in referenced project | |||
execute( otherProject, otherTargetName, otherEntry ); | |||
/** | |||
* 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; | |||
} | |||
final Target target = project.getTarget( targetName ); | |||
if( null == target ) | |||
if( state == TargetState.TRAVERSING ) | |||
{ | |||
final String message = REZ.getString( "no-target.error", targetName ); | |||
// Cycle in target dependencies | |||
final String message = REZ.getString( "target-dependency-cycle.error", name ); | |||
throw new TaskException( message ); | |||
} | |||
//add target to list of targets executed | |||
entry.completeTarget( targetName ); | |||
// 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() ); | |||
} | |||
//execute all dependencies | |||
final String[] dependencies = target.getDependencies(); | |||
// Named dependencies | |||
final Dependency[] dependencies = target.getDependencies(); | |||
for( int i = 0; i < dependencies.length; i++ ) | |||
{ | |||
if( !entry.isTargetCompleted( dependencies[ 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 | |||
{ | |||
execute( project, dependencies[ i ], entry ); | |||
// Dependency in this project | |||
executeTarget( entry, dependency.getTargetName() ); | |||
} | |||
} | |||
executeTarget( project, targetName, target, entry.getFrame() ); | |||
// Now execute the target itself | |||
executeTargetNoDeps( entry, name, target ); | |||
// Mark target as complete | |||
entry.setTargetState( target, TargetState.FINISHED ); | |||
} | |||
/** | |||
* Method to execute a particular target instance. | |||
* Executes a target. Does not check whether the target has been | |||
* executed already, and does not check that its dependencies have been | |||
* executed. | |||
* | |||
* @param name the name of target | |||
* @param target the target | |||
* @param frame the frame in which to execute | |||
* @exception TaskException if an error occurs | |||
* @param entry the project to execute the target in. | |||
* @param name the name of the target. | |||
* @param target the target itself | |||
*/ | |||
private void executeTarget( final Project project, | |||
final String name, | |||
final Target target, | |||
final ExecutionFrame frame ) | |||
private void executeTargetNoDeps( final ProjectEntry entry, | |||
final String name, | |||
final Target target ) | |||
throws TaskException | |||
{ | |||
//notify listeners | |||
final Project project = entry.getProject(); | |||
// Notify listeners | |||
m_listenerSupport.targetStarted( project.getProjectName(), name ); | |||
//check the condition associated with target. | |||
//if it is not satisfied then skip target | |||
final Condition condition = target.getCondition(); | |||
if( null != condition ) | |||
if( getLogger().isDebugEnabled() ) | |||
{ | |||
try | |||
{ | |||
final boolean result = condition.evaluate( frame.getContext() ); | |||
if( !result ) | |||
{ | |||
final String message = REZ.getString( "skip-target.notice", name ); | |||
getLogger().debug( message ); | |||
return; | |||
} | |||
} | |||
catch( final TaskException te ) | |||
{ | |||
final String message = REZ.getString( "condition-eval.error", name ); | |||
throw new TaskException( message, te ); | |||
} | |||
final String message = REZ.getString( "exec-target.notice", project.getProjectName(), name ); | |||
getLogger().debug( message ); | |||
} | |||
final String message = REZ.getString( "exec-target.notice", name ); | |||
getLogger().debug( message ); | |||
//frame.getContext().setProperty( Project.TARGET, target ); | |||
//execute all tasks assciated with target | |||
// Execute all tasks assciated with target | |||
final Configuration[] tasks = target.getTasks(); | |||
for( int i = 0; i < tasks.length; i++ ) | |||
{ | |||
executeTask( tasks[ i ], frame ); | |||
executeTask( tasks[ i ], entry.getFrame() ); | |||
} | |||
//notify listeners | |||
// Notify listeners | |||
m_listenerSupport.targetFinished(); | |||
} | |||
@@ -421,8 +444,11 @@ public class DefaultWorkspace | |||
{ | |||
final String name = task.getName(); | |||
final String message = REZ.getString( "exec-task.notice", name ); | |||
getLogger().debug( message ); | |||
if( getLogger().isDebugEnabled() ) | |||
{ | |||
final String message = REZ.getString( "exec-task.notice", name ); | |||
getLogger().debug( message ); | |||
} | |||
//is setting name even necessary ??? | |||
frame.getContext().setProperty( TaskContext.NAME, name ); | |||
@@ -7,12 +7,15 @@ | |||
*/ | |||
package org.apache.myrmidon.components.workspace; | |||
import java.util.ArrayList; | |||
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 detaisl for each project that is managed by ProjectManager. | |||
* 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$ | |||
@@ -21,7 +24,9 @@ final class ProjectEntry | |||
{ | |||
private final Project m_project; | |||
private final ExecutionFrame m_frame; | |||
private final ArrayList m_targetsCompleted = new ArrayList(); | |||
/** Map from Target -> TargetState for that target. */ | |||
private final Map m_targetState = new HashMap(); | |||
public ProjectEntry( final Project project, | |||
final ExecutionFrame frame ) | |||
@@ -40,13 +45,18 @@ final class ProjectEntry | |||
return m_frame; | |||
} | |||
public boolean isTargetCompleted( final String target ) | |||
public TargetState getTargetState( final Target target ) | |||
{ | |||
return m_targetsCompleted.contains( target ); | |||
TargetState state = (TargetState)m_targetState.get( target ); | |||
if( state == null ) | |||
{ | |||
state = TargetState.NOT_STARTED; | |||
} | |||
return state; | |||
} | |||
public void completeTarget( final String target ) | |||
public void setTargetState( final Target target, final TargetState state ) | |||
{ | |||
m_targetsCompleted.add( target ); | |||
m_targetState.put( target, state ); | |||
} | |||
} |
@@ -5,10 +5,9 @@ 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. | |||
skip-target.notice=Skipping target {0} as it does not satisfy condition. | |||
condition-eval.error=Error evaluating Condition for target {0}. | |||
exec-target.notice=Executing target {0}. | |||
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}. | |||
@@ -18,7 +17,3 @@ 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}. | |||
#AbstractPropertyResolver | |||
prop.mismatched-braces.error=Malformed property with mismatched }'s. | |||
prop.missing-value.error=Unable to find "{0}" to expand during property resolution. |
@@ -0,0 +1,34 @@ | |||
/* | |||
* 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 final static TargetState NOT_STARTED = new TargetState(); | |||
/** | |||
* Target has been started, and the dependencies of the target are being | |||
* traversed. | |||
*/ | |||
public final static TargetState TRAVERSING = new TargetState(); | |||
/** Target has been completed. */ | |||
public final static TargetState FINISHED = new TargetState(); | |||
} |
@@ -23,7 +23,7 @@ public interface ProjectBuilder | |||
/** | |||
* build a project from source. | |||
* | |||
* @param source the source | |||
* @param source the project file path. | |||
* @return the constructed Project | |||
* @exception ProjectException if an error occurs | |||
*/ | |||
@@ -0,0 +1,36 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.myrmidon.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; | |||
public Dependency( final String projectName, final String targetName ) | |||
{ | |||
m_projectName = projectName; | |||
m_targetName = targetName; | |||
} | |||
public String getProjectName() | |||
{ | |||
return m_projectName; | |||
} | |||
public String getTargetName() | |||
{ | |||
return m_targetName; | |||
} | |||
} |
@@ -9,7 +9,6 @@ package org.apache.myrmidon.interfaces.model; | |||
import java.util.ArrayList; | |||
import org.apache.avalon.framework.configuration.Configuration; | |||
import org.apache.myrmidon.framework.conditions.Condition; | |||
/** | |||
* Targets in build file. | |||
@@ -21,19 +20,13 @@ public class Target | |||
{ | |||
private final ArrayList m_dependencies = new ArrayList(); | |||
private final ArrayList m_tasks = new ArrayList(); | |||
private final Condition m_condition; | |||
/** | |||
* Constructor taking condition for target. | |||
* | |||
* @param condition the condition | |||
* Constructs a target. | |||
*/ | |||
public Target( final Condition condition, | |||
final Configuration[] tasks, | |||
final String[] dependencies ) | |||
public Target( final Configuration[] tasks, | |||
final Dependency[] dependencies ) | |||
{ | |||
m_condition = condition; | |||
for( int i = 0; i < tasks.length; i++ ) | |||
{ | |||
m_tasks.add( tasks[ i ] ); | |||
@@ -48,24 +41,14 @@ public class Target | |||
} | |||
} | |||
/** | |||
* Get condition under which target is executed. | |||
* | |||
* @return the condition for target or null | |||
*/ | |||
public final Condition getCondition() | |||
{ | |||
return m_condition; | |||
} | |||
/** | |||
* Get dependencies of target | |||
* | |||
* @return the dependency list | |||
*/ | |||
public final String[] getDependencies() | |||
public final Dependency[] getDependencies() | |||
{ | |||
return (String[])m_dependencies.toArray( new String[ 0 ] ); | |||
return (Dependency[])m_dependencies.toArray( new Dependency[ 0 ] ); | |||
} | |||
/** | |||
@@ -89,6 +89,14 @@ public abstract class AbstractFileSystemTest | |||
m_charContent = "This is a test file." + eol + "With 2 lines in it." + eol; | |||
} | |||
/** | |||
* Cleans-up test. | |||
*/ | |||
protected void tearDown() throws Exception | |||
{ | |||
m_manager.close(); | |||
} | |||
/** | |||
* Tests resolution of absolute URI. | |||
*/ | |||
@@ -11,13 +11,8 @@ import java.io.File; | |||
import java.io.IOException; | |||
import junit.framework.TestCase; | |||
import org.apache.avalon.framework.ExceptionUtil; | |||
import org.apache.avalon.framework.logger.LogKitLogger; | |||
import org.apache.avalon.framework.logger.Logger; | |||
import org.apache.log.Hierarchy; | |||
import org.apache.log.LogTarget; | |||
import org.apache.log.Priority; | |||
import org.apache.log.format.PatternFormatter; | |||
import org.apache.log.output.io.StreamTarget; | |||
import org.apache.myrmidon.frontends.BasicLogger; | |||
/** | |||
* A base class for Myrmidon tests. Provides utility methods for locating | |||
@@ -30,8 +25,7 @@ public abstract class AbstractMyrmidonTest | |||
{ | |||
private final File m_testBaseDir; | |||
private final File m_baseDir; | |||
private final static String PATTERN = "[%8.8{category}] %{message}\\n%{throwable}"; | |||
private Logger m_logger; | |||
public AbstractMyrmidonTest( String name ) | |||
{ | |||
@@ -49,10 +43,39 @@ public abstract class AbstractMyrmidonTest | |||
* Locates a test resource, and asserts that the resource exists | |||
*/ | |||
protected File getTestResource( final String name ) | |||
{ | |||
return getTestResource( name, true ); | |||
} | |||
/** | |||
* Locates a test resource. | |||
*/ | |||
protected File getTestResource( final String name, final boolean mustExist ) | |||
{ | |||
File file = new File( m_testBaseDir, name ); | |||
file = getCanonicalFile( file ); | |||
assertTrue( "Test file \"" + file + "\" does not exist.", file.exists() ); | |||
if( mustExist ) | |||
{ | |||
assertTrue( "Test file \"" + file + "\" does not exist.", file.exists() ); | |||
} | |||
else | |||
{ | |||
assertTrue( "Test file \"" + file + "\" should not exist.", !file.exists() ); | |||
} | |||
return file; | |||
} | |||
/** | |||
* Locates a test directory, creating it if it does not exist. | |||
*/ | |||
protected File getTestDirectory( final String name ) | |||
{ | |||
File file = new File( m_testBaseDir, name ); | |||
file = getCanonicalFile( file ); | |||
assertTrue( "Test directory \"" + file + "\" does not exist or is not a directory.", | |||
file.isDirectory() || file.mkdirs() ); | |||
return file; | |||
} | |||
@@ -83,18 +106,13 @@ public abstract class AbstractMyrmidonTest | |||
/** | |||
* Creates a logger. | |||
*/ | |||
protected Logger createLogger() | |||
protected Logger getLogger() | |||
{ | |||
// Setup a logger | |||
final Priority priority = Priority.WARN; | |||
final org.apache.log.Logger targetLogger = Hierarchy.getDefaultHierarchy().getLoggerFor( "myrmidon" ); | |||
final PatternFormatter formatter = new PatternFormatter( PATTERN ); | |||
final StreamTarget target = new StreamTarget( System.out, formatter ); | |||
targetLogger.setLogTargets( new LogTarget[]{target} ); | |||
targetLogger.setPriority( priority ); | |||
return new LogKitLogger( targetLogger ); | |||
if( m_logger == null ) | |||
{ | |||
m_logger = new BasicLogger( "[test]", BasicLogger.LEVEL_WARN ); | |||
} | |||
return m_logger; | |||
} | |||
/** | |||
@@ -105,6 +123,12 @@ public abstract class AbstractMyrmidonTest | |||
*/ | |||
protected void assertSameMessage( final String[] messages, final Throwable throwable ) | |||
{ | |||
//System.out.println( "exception:" ); | |||
//for( Throwable t = throwable; t != null; t = ExceptionUtil.getCause( t, true ) ) | |||
//{ | |||
// System.out.println( " " + t.getMessage() ); | |||
//} | |||
Throwable current = throwable; | |||
for( int i = 0; i < messages.length; i++ ) | |||
{ | |||
@@ -125,7 +149,7 @@ public abstract class AbstractMyrmidonTest | |||
*/ | |||
protected void assertSameMessage( final String message, final Throwable throwable ) | |||
{ | |||
assertEquals( message, throwable.getMessage() ); | |||
assertSameMessage( new String[] { message }, throwable ); | |||
} | |||
/** | |||
@@ -54,7 +54,7 @@ public class AbstractProjectTest | |||
// Need to set the context classloader - The default embeddor uses it | |||
Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); | |||
final Logger logger = createLogger(); | |||
final Logger logger = getLogger(); | |||
m_embeddor = new DefaultEmbeddor(); | |||
m_embeddor.enableLogging( logger ); | |||
@@ -14,7 +14,6 @@ import org.apache.aut.converter.Converter; | |||
import org.apache.avalon.framework.logger.LogEnabled; | |||
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.avalon.framework.service.Serviceable; | |||
import org.apache.myrmidon.AbstractMyrmidonTest; | |||
@@ -24,20 +23,19 @@ import org.apache.myrmidon.components.converter.DefaultConverterRegistry; | |||
import org.apache.myrmidon.components.converter.DefaultMasterConverter; | |||
import org.apache.myrmidon.components.deployer.DefaultDeployer; | |||
import org.apache.myrmidon.components.extensions.DefaultExtensionManager; | |||
import org.apache.myrmidon.components.property.DefaultPropertyResolver; | |||
import org.apache.myrmidon.components.role.DefaultRoleManager; | |||
import org.apache.myrmidon.components.type.DefaultTypeManager; | |||
import org.apache.myrmidon.components.property.DefaultPropertyResolver; | |||
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.extensions.ExtensionManager; | |||
import org.apache.myrmidon.interfaces.property.PropertyResolver; | |||
import org.apache.myrmidon.interfaces.role.RoleInfo; | |||
import org.apache.myrmidon.interfaces.role.RoleManager; | |||
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | |||
import org.apache.myrmidon.interfaces.type.TypeException; | |||
import org.apache.myrmidon.interfaces.type.TypeManager; | |||
import org.apache.myrmidon.interfaces.property.PropertyResolver; | |||
/** | |||
* A base class for tests for the default components. | |||
@@ -48,7 +46,6 @@ public abstract class AbstractComponentTest | |||
extends AbstractMyrmidonTest | |||
{ | |||
private DefaultServiceManager m_serviceManager; | |||
private Logger m_logger; | |||
public AbstractComponentTest( final String name ) | |||
{ | |||
@@ -58,95 +55,85 @@ public abstract class AbstractComponentTest | |||
/** | |||
* Returns the component manager containing the components to test. | |||
*/ | |||
protected final ServiceManager getServiceManager() | |||
{ | |||
return m_serviceManager; | |||
} | |||
protected final Logger getLogger() | |||
protected final ServiceManager getServiceManager() throws Exception | |||
{ | |||
return m_logger; | |||
} | |||
/** | |||
* Returns the type manager. | |||
*/ | |||
protected TypeManager getTypeManager() | |||
throws ServiceException | |||
{ | |||
return (TypeManager)getServiceManager().lookup( TypeManager.ROLE ); | |||
} | |||
/** | |||
* Setup the test case - prepares the set of components. | |||
*/ | |||
protected void setUp() | |||
throws Exception | |||
{ | |||
m_logger = createLogger(); | |||
if( m_serviceManager == null ) | |||
{ | |||
Logger logger = getLogger(); | |||
// Create the components | |||
m_serviceManager = new DefaultServiceManager(); | |||
List components = new ArrayList(); | |||
// Create the components | |||
m_serviceManager = new DefaultServiceManager(); | |||
List components = new ArrayList(); | |||
Object component = new DefaultMasterConverter(); | |||
m_serviceManager.put( Converter.ROLE, component ); | |||
components.add( component ); | |||
Object component = new DefaultMasterConverter(); | |||
m_serviceManager.put( Converter.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultConverterRegistry(); | |||
m_serviceManager.put( ConverterRegistry.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultConverterRegistry(); | |||
m_serviceManager.put( ConverterRegistry.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultTypeManager(); | |||
m_serviceManager.put( TypeManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultTypeManager(); | |||
m_serviceManager.put( TypeManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultConfigurer(); | |||
m_serviceManager.put( Configurer.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultConfigurer(); | |||
m_serviceManager.put( Configurer.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultDeployer(); | |||
m_serviceManager.put( Deployer.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultDeployer(); | |||
m_serviceManager.put( Deployer.ROLE, component ); | |||
components.add( component ); | |||
final DefaultClassLoaderManager classLoaderMgr = new DefaultClassLoaderManager(); | |||
classLoaderMgr.setBaseClassLoader( getClass().getClassLoader() ); | |||
m_serviceManager.put( ClassLoaderManager.ROLE, classLoaderMgr ); | |||
components.add( classLoaderMgr ); | |||
final DefaultClassLoaderManager classLoaderMgr = new DefaultClassLoaderManager(); | |||
classLoaderMgr.setBaseClassLoader( getClass().getClassLoader() ); | |||
m_serviceManager.put( ClassLoaderManager.ROLE, classLoaderMgr ); | |||
components.add( classLoaderMgr ); | |||
component = new DefaultExtensionManager(); | |||
m_serviceManager.put( ExtensionManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultExtensionManager(); | |||
m_serviceManager.put( ExtensionManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultRoleManager(); | |||
m_serviceManager.put( RoleManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultRoleManager(); | |||
m_serviceManager.put( RoleManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultPropertyResolver(); | |||
m_serviceManager.put( PropertyResolver.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultPropertyResolver(); | |||
m_serviceManager.put( PropertyResolver.ROLE, component ); | |||
components.add( component ); | |||
// Log enable the components | |||
for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | |||
{ | |||
Object obj = iterator.next(); | |||
if( obj instanceof LogEnabled ) | |||
// Log enable the components | |||
for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | |||
{ | |||
final LogEnabled logEnabled = (LogEnabled)obj; | |||
logEnabled.enableLogging( m_logger ); | |||
Object obj = iterator.next(); | |||
if( obj instanceof LogEnabled ) | |||
{ | |||
final LogEnabled logEnabled = (LogEnabled)obj; | |||
logEnabled.enableLogging( logger ); | |||
} | |||
} | |||
} | |||
// Compose the components | |||
for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | |||
{ | |||
Object obj = iterator.next(); | |||
if( obj instanceof Serviceable ) | |||
// Compose the components | |||
for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | |||
{ | |||
final Serviceable serviceable = (Serviceable)obj; | |||
serviceable.service( m_serviceManager ); | |||
Object obj = iterator.next(); | |||
if( obj instanceof Serviceable ) | |||
{ | |||
final Serviceable serviceable = (Serviceable)obj; | |||
serviceable.service( m_serviceManager ); | |||
} | |||
} | |||
} | |||
return m_serviceManager; | |||
} | |||
/** | |||
* Returns the type manager. | |||
*/ | |||
protected TypeManager getTypeManager() | |||
throws Exception | |||
{ | |||
return (TypeManager)getServiceManager().lookup( TypeManager.ROLE ); | |||
} | |||
/** | |||
@@ -179,7 +166,7 @@ public abstract class AbstractComponentTest | |||
protected void registerConverter( final Class converterClass, | |||
final Class sourceClass, | |||
final Class destClass ) | |||
throws ServiceException, TypeException | |||
throws Exception | |||
{ | |||
ConverterRegistry converterRegistry = (ConverterRegistry)getServiceManager().lookup( ConverterRegistry.ROLE ); | |||
converterRegistry.registerConverter( converterClass.getName(), sourceClass.getName(), destClass.getName() ); | |||
@@ -8,9 +8,13 @@ | |||
package org.apache.myrmidon.components.builder; | |||
import java.io.File; | |||
import java.util.Arrays; | |||
import org.apache.avalon.excalibur.i18n.ResourceManager; | |||
import org.apache.avalon.excalibur.i18n.Resources; | |||
import org.apache.avalon.excalibur.io.FileUtil; | |||
import org.apache.myrmidon.AbstractMyrmidonTest; | |||
import org.apache.myrmidon.interfaces.builder.ProjectException; | |||
import org.apache.myrmidon.interfaces.model.Project; | |||
/** | |||
* Test cases for {@link DefaultProjectBuilder}. | |||
@@ -22,7 +26,7 @@ public class DefaultProjectBuilderTest | |||
extends AbstractMyrmidonTest | |||
{ | |||
private final static Resources REZ | |||
= ResourceManager.getPackageResources( DefaultProjectBuilder.class ); | |||
= ResourceManager.getPackageResources( DefaultProjectBuilderTest.class ); | |||
private DefaultProjectBuilder m_builder; | |||
@@ -35,11 +39,227 @@ public class DefaultProjectBuilderTest | |||
{ | |||
super.setUp(); | |||
m_builder = new DefaultProjectBuilder(); | |||
m_builder.enableLogging( createLogger() ); | |||
m_builder.enableLogging( getLogger() ); | |||
} | |||
/** | |||
* Test validation of project and target names. | |||
* Creates a project, with default values set. | |||
*/ | |||
private DefaultProject createProject( final File projFile ) | |||
{ | |||
final DefaultProject project = new DefaultProject(); | |||
project.setProjectName( FileUtil.removeExtension( projFile.getName() ) ); | |||
project.setBaseDirectory( getTestDirectory( "." ) ); | |||
project.setDefaultTargetName( "main" ); | |||
return project; | |||
} | |||
/** | |||
* Tests bad project file name. | |||
*/ | |||
public void testProjectFileName() throws Exception | |||
{ | |||
// Test with a file that does not exist | |||
File projFile = getTestResource( "unknown.ant", false ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.no-project-file.error" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
// Test with a directory | |||
projFile = getTestDirectory( "some-dir" ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.no-project-file.error" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
} | |||
/** | |||
* Tests error reporting when the project file contains badly formed XML. | |||
*/ | |||
public void testBadlyFormedFile() throws Exception | |||
{ | |||
final File projFile = getTestResource( "bad-xml.ant" ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.project-parse.error" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
} | |||
/** | |||
* Tests building a project with default values for project name, base dir | |||
* and default target. | |||
*/ | |||
public void testDefaults() throws Exception | |||
{ | |||
// Build project | |||
final File projFile = getTestResource( "defaults.ant" ); | |||
Project project = m_builder.build( projFile.getAbsolutePath() ); | |||
// Compare against expected project | |||
DefaultProject expected = createProject( projFile ); | |||
assertSameProject( expected, project ); | |||
} | |||
/** | |||
* Tests setting the project name. | |||
*/ | |||
public void testProjectName() throws Exception | |||
{ | |||
// Build project | |||
final File projFile = getTestResource( "set-project-name.ant" ); | |||
Project project = m_builder.build( projFile.getAbsolutePath() ); | |||
// Compare against expected project | |||
DefaultProject expected = createProject( projFile ); | |||
expected.setProjectName( "some-project" ); | |||
assertSameProject( expected, project ); | |||
} | |||
/** | |||
* Tests setting the base directory. | |||
*/ | |||
public void testBaseDirectory() throws Exception | |||
{ | |||
// Build project | |||
final File projFile = getTestResource( "set-base-dir.ant" ); | |||
Project project = m_builder.build( projFile.getAbsolutePath() ); | |||
// Compare against expected project | |||
DefaultProject expected = createProject( projFile ); | |||
final File baseDir = getTestDirectory( "other-base-dir" ); | |||
expected.setBaseDirectory( baseDir ); | |||
assertSameProject( expected, project ); | |||
} | |||
/** | |||
* Tests setting the default target name. | |||
*/ | |||
public void testDefaultTarget() throws Exception | |||
{ | |||
// Build project | |||
final File projFile = getTestResource( "set-default-target.ant" ); | |||
Project project = m_builder.build( projFile.getAbsolutePath() ); | |||
// Compare against expected project | |||
DefaultProject expected = createProject( projFile ); | |||
expected.setDefaultTargetName( "some-target" ); | |||
assertSameProject( expected, project ); | |||
} | |||
/** | |||
* Tests missing, invalid and incompatible project version. | |||
*/ | |||
public void testProjectVersion() throws Exception | |||
{ | |||
// No version | |||
File projFile = getTestResource( "no-version.ant" ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.version-missing.error" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
// Badly formed version | |||
projFile = getTestResource( "bad-version.ant" ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.malformed.version", "ant2" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
// Incompatible version | |||
projFile = getTestResource( "mismatched-version.ant" ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.bad-version.error", "2.0.0", "1.0.2" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
} | |||
/** | |||
* Asserts that 2 projects are identical. | |||
*/ | |||
protected void assertSameProject( final Project expected, | |||
final Project project ) | |||
{ | |||
assertEquals( expected.getProjectName(), project.getProjectName() ); | |||
assertEquals( expected.getBaseDirectory(), project.getBaseDirectory() ); | |||
assertEquals( expected.getDefaultTargetName(), project.getDefaultTargetName() ); | |||
// TODO - make sure each of the projects are the same | |||
assertTrue( Arrays.equals( expected.getProjectNames(), project.getProjectNames() ) ); | |||
// TODO - make sure the implicit targets are the same | |||
// TODO - make sure each of the targets are the same | |||
assertTrue( Arrays.equals( expected.getTargetNames(), project.getTargetNames() ) ); | |||
// TODO - implement TypeLib.equals(), or use a comparator | |||
assertTrue( Arrays.equals( expected.getTypeLibs(), project.getTypeLibs() ) ); | |||
} | |||
/** | |||
* Tests validation of project and target names. | |||
*/ | |||
public void testNameValidation() throws Exception | |||
{ | |||
@@ -52,7 +272,12 @@ public class DefaultProjectBuilderTest | |||
} | |||
catch( Exception e ) | |||
{ | |||
assertSameMessage( REZ.getString( "ant.project-bad-name.error" ), e ); | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", badProjectFile.getAbsolutePath() ), | |||
REZ.getString( "ant.project-bad-name.error" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
// Check bad target name | |||
@@ -64,7 +289,13 @@ public class DefaultProjectBuilderTest | |||
} | |||
catch( Exception e ) | |||
{ | |||
// TODO - check error message | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", badTargetFile.getAbsolutePath() ), | |||
// TODO - check error message | |||
null | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
} | |||
} |
@@ -5,53 +5,51 @@ | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.myrmidon.components.workspace; | |||
package org.apache.myrmidon.components.property; | |||
import java.io.File; | |||
import java.util.Date; | |||
import org.apache.avalon.excalibur.i18n.ResourceManager; | |||
import org.apache.avalon.excalibur.i18n.Resources; | |||
import org.apache.avalon.framework.context.Context; | |||
import org.apache.myrmidon.AbstractMyrmidonTest; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.components.AbstractComponentTest; | |||
import org.apache.myrmidon.components.property.DefaultPropertyResolver; | |||
import org.apache.myrmidon.components.workspace.DefaultTaskContext; | |||
import org.apache.myrmidon.interfaces.property.PropertyResolver; | |||
/** | |||
* Functional tests for {@link DefaultPropertyResolver}. | |||
* General-purpose property resolver test cases. | |||
* | |||
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a> | |||
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||
* @version $Revision$ $Date$ | |||
*/ | |||
public class DefaultPropertyResolverTest | |||
extends AbstractComponentTest | |||
public abstract class AbstractPropertyResolverTest | |||
extends AbstractMyrmidonTest | |||
{ | |||
protected final static Resources REZ | |||
= ResourceManager.getPackageResources( DefaultPropertyResolver.class ); | |||
= ResourceManager.getPackageResources( AbstractPropertyResolverTest.class ); | |||
protected PropertyResolver m_resolver; | |||
protected DefaultTaskContext m_context; | |||
public DefaultPropertyResolverTest( String name ) | |||
public AbstractPropertyResolverTest( String name ) | |||
{ | |||
super( name ); | |||
} | |||
protected void setUp() throws Exception | |||
{ | |||
super.setUp(); | |||
m_resolver = createResolver(); | |||
m_context = new DefaultTaskContext( null, getServiceManager(), getLogger() ); | |||
m_context = new DefaultTaskContext( null, null, getLogger() ); | |||
m_context.setProperty( "intProp", new Integer( 333 ) ); | |||
m_context.setProperty( "stringProp", "String property" ); | |||
} | |||
protected PropertyResolver createResolver() | |||
{ | |||
return new DefaultPropertyResolver(); | |||
} | |||
/** | |||
* Creates the resolver to test. | |||
*/ | |||
protected abstract PropertyResolver createResolver(); | |||
/** | |||
* Test property resolution with various different typed properties. | |||
@@ -73,7 +71,7 @@ public class DefaultPropertyResolverTest | |||
throws Exception | |||
{ | |||
m_context.setProperty( "typedProp", propObject ); | |||
String propString = propObject.toString(); | |||
final String propString = propObject.toString(); | |||
doTestResolution( "${typedProp}", propObject, m_context ); | |||
doTestResolution( "${typedProp} with following text", | |||
@@ -96,23 +94,6 @@ public class DefaultPropertyResolverTest | |||
doTestResolution( "before ${prop2} between ${prop1} after", | |||
"before value2 between value1 after", m_context ); | |||
doTestResolution( "${prop1}-${int1}-${prop2}", "value1-123-value2", m_context ); | |||
} | |||
/** | |||
* Tests handing undefined property. | |||
*/ | |||
public void testUndefinedProp() throws Exception | |||
{ | |||
String undefinedProp = "undefinedProperty"; | |||
doTestFailure( "${" + undefinedProp + "}", | |||
REZ.getString( "prop.missing-value.error", undefinedProp ), | |||
m_context ); | |||
//TODO - "" should be disallowed as a property name | |||
doTestFailure( "${}", | |||
REZ.getString( "prop.missing-value.error", "" ), | |||
m_context ); | |||
} | |||
/** | |||
@@ -131,18 +112,17 @@ public class DefaultPropertyResolverTest | |||
/* TODO - need to handle these cases. */ | |||
// testFailure( "${bad${}", "", m_context ); | |||
// testFailure( "${ }", "", m_context ); | |||
} | |||
/** | |||
* Resolves the property using the supplied context, and checks the result. | |||
*/ | |||
protected void doTestResolution( String value, | |||
Object expected, | |||
Context context ) | |||
protected void doTestResolution( final String value, | |||
final Object expected, | |||
final Context context ) | |||
throws Exception | |||
{ | |||
Object resolved = m_resolver.resolveProperties( value, context ); | |||
final Object resolved = m_resolver.resolveProperties( value, context ); | |||
assertEquals( expected, resolved ); | |||
} | |||
@@ -151,9 +131,9 @@ public class DefaultPropertyResolverTest | |||
* Attempts to resolve the value using the supplied context, expecting to | |||
* fail with the supplied error message. | |||
*/ | |||
protected void doTestFailure( String value, | |||
String expectedErrorMessage, | |||
Context context ) | |||
protected void doTestFailure( final String value, | |||
final String expectedErrorMessage, | |||
final Context context ) | |||
{ | |||
try | |||
{ |
@@ -5,19 +5,18 @@ | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.myrmidon.components.workspace; | |||
package org.apache.myrmidon.components.property; | |||
import org.apache.myrmidon.interfaces.property.PropertyResolver; | |||
import org.apache.myrmidon.components.property.ClassicPropertyResolver; | |||
/** | |||
* A test for {@link ClassicPropertyResolver} | |||
* A test for {@link ClassicPropertyResolver}. | |||
* | |||
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a> | |||
* @version $Revision$ $Date$ | |||
*/ | |||
public class ClassicPropertyResolverTest | |||
extends DefaultPropertyResolverTest | |||
extends AbstractPropertyResolverTest | |||
{ | |||
public ClassicPropertyResolverTest( String name ) | |||
{ | |||
@@ -34,8 +33,7 @@ public class ClassicPropertyResolverTest | |||
*/ | |||
public void testUndefinedProp() throws Exception | |||
{ | |||
String undefinedProp = "undefinedProperty"; | |||
final String undefinedProp = "undefinedProperty"; | |||
final String propRef = "${" + undefinedProp + "}"; | |||
doTestResolution( propRef, propRef, m_context ); | |||
} |
@@ -0,0 +1,46 @@ | |||
/* | |||
* 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; | |||
/** | |||
* Functional tests for {@link DefaultPropertyResolver}. | |||
* | |||
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a> | |||
* @version $Revision$ $Date$ | |||
*/ | |||
public class DefaultPropertyResolverTest | |||
extends AbstractPropertyResolverTest | |||
{ | |||
public DefaultPropertyResolverTest( String name ) | |||
{ | |||
super( name ); | |||
} | |||
protected PropertyResolver createResolver() | |||
{ | |||
return new DefaultPropertyResolver(); | |||
} | |||
/** | |||
* Tests handing undefined property. | |||
*/ | |||
public void testUndefinedProp() throws Exception | |||
{ | |||
final String undefinedProp = "undefinedProperty"; | |||
doTestFailure( "${" + undefinedProp + "}", | |||
REZ.getString( "prop.missing-value.error", undefinedProp ), | |||
m_context ); | |||
//TODO - "" should be disallowed as a property name | |||
doTestFailure( "${}", | |||
REZ.getString( "prop.missing-value.error", "" ), | |||
m_context ); | |||
} | |||
} |
@@ -44,11 +44,9 @@ public class InstantiatingServiceManagerTest | |||
protected void setUp() | |||
throws Exception | |||
{ | |||
super.setUp(); | |||
// Set-up the service manager | |||
m_serviceManager = new InstantiatingServiceManager(); | |||
m_serviceManager.enableLogging( createLogger() ); | |||
m_serviceManager.enableLogging( getLogger() ); | |||
m_serviceManager.service( getServiceManager() ); | |||
m_serviceManager.parameterize( m_parameters ); | |||
} | |||
@@ -89,6 +89,14 @@ public abstract class AbstractFileSystemTest | |||
m_charContent = "This is a test file." + eol + "With 2 lines in it." + eol; | |||
} | |||
/** | |||
* Cleans-up test. | |||
*/ | |||
protected void tearDown() throws Exception | |||
{ | |||
m_manager.close(); | |||
} | |||
/** | |||
* Tests resolution of absolute URI. | |||
*/ | |||
@@ -11,13 +11,8 @@ import java.io.File; | |||
import java.io.IOException; | |||
import junit.framework.TestCase; | |||
import org.apache.avalon.framework.ExceptionUtil; | |||
import org.apache.avalon.framework.logger.LogKitLogger; | |||
import org.apache.avalon.framework.logger.Logger; | |||
import org.apache.log.Hierarchy; | |||
import org.apache.log.LogTarget; | |||
import org.apache.log.Priority; | |||
import org.apache.log.format.PatternFormatter; | |||
import org.apache.log.output.io.StreamTarget; | |||
import org.apache.myrmidon.frontends.BasicLogger; | |||
/** | |||
* A base class for Myrmidon tests. Provides utility methods for locating | |||
@@ -30,8 +25,7 @@ public abstract class AbstractMyrmidonTest | |||
{ | |||
private final File m_testBaseDir; | |||
private final File m_baseDir; | |||
private final static String PATTERN = "[%8.8{category}] %{message}\\n%{throwable}"; | |||
private Logger m_logger; | |||
public AbstractMyrmidonTest( String name ) | |||
{ | |||
@@ -49,10 +43,39 @@ public abstract class AbstractMyrmidonTest | |||
* Locates a test resource, and asserts that the resource exists | |||
*/ | |||
protected File getTestResource( final String name ) | |||
{ | |||
return getTestResource( name, true ); | |||
} | |||
/** | |||
* Locates a test resource. | |||
*/ | |||
protected File getTestResource( final String name, final boolean mustExist ) | |||
{ | |||
File file = new File( m_testBaseDir, name ); | |||
file = getCanonicalFile( file ); | |||
assertTrue( "Test file \"" + file + "\" does not exist.", file.exists() ); | |||
if( mustExist ) | |||
{ | |||
assertTrue( "Test file \"" + file + "\" does not exist.", file.exists() ); | |||
} | |||
else | |||
{ | |||
assertTrue( "Test file \"" + file + "\" should not exist.", !file.exists() ); | |||
} | |||
return file; | |||
} | |||
/** | |||
* Locates a test directory, creating it if it does not exist. | |||
*/ | |||
protected File getTestDirectory( final String name ) | |||
{ | |||
File file = new File( m_testBaseDir, name ); | |||
file = getCanonicalFile( file ); | |||
assertTrue( "Test directory \"" + file + "\" does not exist or is not a directory.", | |||
file.isDirectory() || file.mkdirs() ); | |||
return file; | |||
} | |||
@@ -83,18 +106,13 @@ public abstract class AbstractMyrmidonTest | |||
/** | |||
* Creates a logger. | |||
*/ | |||
protected Logger createLogger() | |||
protected Logger getLogger() | |||
{ | |||
// Setup a logger | |||
final Priority priority = Priority.WARN; | |||
final org.apache.log.Logger targetLogger = Hierarchy.getDefaultHierarchy().getLoggerFor( "myrmidon" ); | |||
final PatternFormatter formatter = new PatternFormatter( PATTERN ); | |||
final StreamTarget target = new StreamTarget( System.out, formatter ); | |||
targetLogger.setLogTargets( new LogTarget[]{target} ); | |||
targetLogger.setPriority( priority ); | |||
return new LogKitLogger( targetLogger ); | |||
if( m_logger == null ) | |||
{ | |||
m_logger = new BasicLogger( "[test]", BasicLogger.LEVEL_WARN ); | |||
} | |||
return m_logger; | |||
} | |||
/** | |||
@@ -105,6 +123,12 @@ public abstract class AbstractMyrmidonTest | |||
*/ | |||
protected void assertSameMessage( final String[] messages, final Throwable throwable ) | |||
{ | |||
//System.out.println( "exception:" ); | |||
//for( Throwable t = throwable; t != null; t = ExceptionUtil.getCause( t, true ) ) | |||
//{ | |||
// System.out.println( " " + t.getMessage() ); | |||
//} | |||
Throwable current = throwable; | |||
for( int i = 0; i < messages.length; i++ ) | |||
{ | |||
@@ -125,7 +149,7 @@ public abstract class AbstractMyrmidonTest | |||
*/ | |||
protected void assertSameMessage( final String message, final Throwable throwable ) | |||
{ | |||
assertEquals( message, throwable.getMessage() ); | |||
assertSameMessage( new String[] { message }, throwable ); | |||
} | |||
/** | |||
@@ -54,7 +54,7 @@ public class AbstractProjectTest | |||
// Need to set the context classloader - The default embeddor uses it | |||
Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); | |||
final Logger logger = createLogger(); | |||
final Logger logger = getLogger(); | |||
m_embeddor = new DefaultEmbeddor(); | |||
m_embeddor.enableLogging( logger ); | |||
@@ -14,7 +14,6 @@ import org.apache.aut.converter.Converter; | |||
import org.apache.avalon.framework.logger.LogEnabled; | |||
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.avalon.framework.service.Serviceable; | |||
import org.apache.myrmidon.AbstractMyrmidonTest; | |||
@@ -24,20 +23,19 @@ import org.apache.myrmidon.components.converter.DefaultConverterRegistry; | |||
import org.apache.myrmidon.components.converter.DefaultMasterConverter; | |||
import org.apache.myrmidon.components.deployer.DefaultDeployer; | |||
import org.apache.myrmidon.components.extensions.DefaultExtensionManager; | |||
import org.apache.myrmidon.components.property.DefaultPropertyResolver; | |||
import org.apache.myrmidon.components.role.DefaultRoleManager; | |||
import org.apache.myrmidon.components.type.DefaultTypeManager; | |||
import org.apache.myrmidon.components.property.DefaultPropertyResolver; | |||
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.extensions.ExtensionManager; | |||
import org.apache.myrmidon.interfaces.property.PropertyResolver; | |||
import org.apache.myrmidon.interfaces.role.RoleInfo; | |||
import org.apache.myrmidon.interfaces.role.RoleManager; | |||
import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | |||
import org.apache.myrmidon.interfaces.type.TypeException; | |||
import org.apache.myrmidon.interfaces.type.TypeManager; | |||
import org.apache.myrmidon.interfaces.property.PropertyResolver; | |||
/** | |||
* A base class for tests for the default components. | |||
@@ -48,7 +46,6 @@ public abstract class AbstractComponentTest | |||
extends AbstractMyrmidonTest | |||
{ | |||
private DefaultServiceManager m_serviceManager; | |||
private Logger m_logger; | |||
public AbstractComponentTest( final String name ) | |||
{ | |||
@@ -58,95 +55,85 @@ public abstract class AbstractComponentTest | |||
/** | |||
* Returns the component manager containing the components to test. | |||
*/ | |||
protected final ServiceManager getServiceManager() | |||
{ | |||
return m_serviceManager; | |||
} | |||
protected final Logger getLogger() | |||
protected final ServiceManager getServiceManager() throws Exception | |||
{ | |||
return m_logger; | |||
} | |||
/** | |||
* Returns the type manager. | |||
*/ | |||
protected TypeManager getTypeManager() | |||
throws ServiceException | |||
{ | |||
return (TypeManager)getServiceManager().lookup( TypeManager.ROLE ); | |||
} | |||
/** | |||
* Setup the test case - prepares the set of components. | |||
*/ | |||
protected void setUp() | |||
throws Exception | |||
{ | |||
m_logger = createLogger(); | |||
if( m_serviceManager == null ) | |||
{ | |||
Logger logger = getLogger(); | |||
// Create the components | |||
m_serviceManager = new DefaultServiceManager(); | |||
List components = new ArrayList(); | |||
// Create the components | |||
m_serviceManager = new DefaultServiceManager(); | |||
List components = new ArrayList(); | |||
Object component = new DefaultMasterConverter(); | |||
m_serviceManager.put( Converter.ROLE, component ); | |||
components.add( component ); | |||
Object component = new DefaultMasterConverter(); | |||
m_serviceManager.put( Converter.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultConverterRegistry(); | |||
m_serviceManager.put( ConverterRegistry.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultConverterRegistry(); | |||
m_serviceManager.put( ConverterRegistry.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultTypeManager(); | |||
m_serviceManager.put( TypeManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultTypeManager(); | |||
m_serviceManager.put( TypeManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultConfigurer(); | |||
m_serviceManager.put( Configurer.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultConfigurer(); | |||
m_serviceManager.put( Configurer.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultDeployer(); | |||
m_serviceManager.put( Deployer.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultDeployer(); | |||
m_serviceManager.put( Deployer.ROLE, component ); | |||
components.add( component ); | |||
final DefaultClassLoaderManager classLoaderMgr = new DefaultClassLoaderManager(); | |||
classLoaderMgr.setBaseClassLoader( getClass().getClassLoader() ); | |||
m_serviceManager.put( ClassLoaderManager.ROLE, classLoaderMgr ); | |||
components.add( classLoaderMgr ); | |||
final DefaultClassLoaderManager classLoaderMgr = new DefaultClassLoaderManager(); | |||
classLoaderMgr.setBaseClassLoader( getClass().getClassLoader() ); | |||
m_serviceManager.put( ClassLoaderManager.ROLE, classLoaderMgr ); | |||
components.add( classLoaderMgr ); | |||
component = new DefaultExtensionManager(); | |||
m_serviceManager.put( ExtensionManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultExtensionManager(); | |||
m_serviceManager.put( ExtensionManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultRoleManager(); | |||
m_serviceManager.put( RoleManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultRoleManager(); | |||
m_serviceManager.put( RoleManager.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultPropertyResolver(); | |||
m_serviceManager.put( PropertyResolver.ROLE, component ); | |||
components.add( component ); | |||
component = new DefaultPropertyResolver(); | |||
m_serviceManager.put( PropertyResolver.ROLE, component ); | |||
components.add( component ); | |||
// Log enable the components | |||
for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | |||
{ | |||
Object obj = iterator.next(); | |||
if( obj instanceof LogEnabled ) | |||
// Log enable the components | |||
for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | |||
{ | |||
final LogEnabled logEnabled = (LogEnabled)obj; | |||
logEnabled.enableLogging( m_logger ); | |||
Object obj = iterator.next(); | |||
if( obj instanceof LogEnabled ) | |||
{ | |||
final LogEnabled logEnabled = (LogEnabled)obj; | |||
logEnabled.enableLogging( logger ); | |||
} | |||
} | |||
} | |||
// Compose the components | |||
for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | |||
{ | |||
Object obj = iterator.next(); | |||
if( obj instanceof Serviceable ) | |||
// Compose the components | |||
for( Iterator iterator = components.iterator(); iterator.hasNext(); ) | |||
{ | |||
final Serviceable serviceable = (Serviceable)obj; | |||
serviceable.service( m_serviceManager ); | |||
Object obj = iterator.next(); | |||
if( obj instanceof Serviceable ) | |||
{ | |||
final Serviceable serviceable = (Serviceable)obj; | |||
serviceable.service( m_serviceManager ); | |||
} | |||
} | |||
} | |||
return m_serviceManager; | |||
} | |||
/** | |||
* Returns the type manager. | |||
*/ | |||
protected TypeManager getTypeManager() | |||
throws Exception | |||
{ | |||
return (TypeManager)getServiceManager().lookup( TypeManager.ROLE ); | |||
} | |||
/** | |||
@@ -179,7 +166,7 @@ public abstract class AbstractComponentTest | |||
protected void registerConverter( final Class converterClass, | |||
final Class sourceClass, | |||
final Class destClass ) | |||
throws ServiceException, TypeException | |||
throws Exception | |||
{ | |||
ConverterRegistry converterRegistry = (ConverterRegistry)getServiceManager().lookup( ConverterRegistry.ROLE ); | |||
converterRegistry.registerConverter( converterClass.getName(), sourceClass.getName(), destClass.getName() ); | |||
@@ -8,9 +8,13 @@ | |||
package org.apache.myrmidon.components.builder; | |||
import java.io.File; | |||
import java.util.Arrays; | |||
import org.apache.avalon.excalibur.i18n.ResourceManager; | |||
import org.apache.avalon.excalibur.i18n.Resources; | |||
import org.apache.avalon.excalibur.io.FileUtil; | |||
import org.apache.myrmidon.AbstractMyrmidonTest; | |||
import org.apache.myrmidon.interfaces.builder.ProjectException; | |||
import org.apache.myrmidon.interfaces.model.Project; | |||
/** | |||
* Test cases for {@link DefaultProjectBuilder}. | |||
@@ -22,7 +26,7 @@ public class DefaultProjectBuilderTest | |||
extends AbstractMyrmidonTest | |||
{ | |||
private final static Resources REZ | |||
= ResourceManager.getPackageResources( DefaultProjectBuilder.class ); | |||
= ResourceManager.getPackageResources( DefaultProjectBuilderTest.class ); | |||
private DefaultProjectBuilder m_builder; | |||
@@ -35,11 +39,227 @@ public class DefaultProjectBuilderTest | |||
{ | |||
super.setUp(); | |||
m_builder = new DefaultProjectBuilder(); | |||
m_builder.enableLogging( createLogger() ); | |||
m_builder.enableLogging( getLogger() ); | |||
} | |||
/** | |||
* Test validation of project and target names. | |||
* Creates a project, with default values set. | |||
*/ | |||
private DefaultProject createProject( final File projFile ) | |||
{ | |||
final DefaultProject project = new DefaultProject(); | |||
project.setProjectName( FileUtil.removeExtension( projFile.getName() ) ); | |||
project.setBaseDirectory( getTestDirectory( "." ) ); | |||
project.setDefaultTargetName( "main" ); | |||
return project; | |||
} | |||
/** | |||
* Tests bad project file name. | |||
*/ | |||
public void testProjectFileName() throws Exception | |||
{ | |||
// Test with a file that does not exist | |||
File projFile = getTestResource( "unknown.ant", false ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.no-project-file.error" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
// Test with a directory | |||
projFile = getTestDirectory( "some-dir" ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.no-project-file.error" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
} | |||
/** | |||
* Tests error reporting when the project file contains badly formed XML. | |||
*/ | |||
public void testBadlyFormedFile() throws Exception | |||
{ | |||
final File projFile = getTestResource( "bad-xml.ant" ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.project-parse.error" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
} | |||
/** | |||
* Tests building a project with default values for project name, base dir | |||
* and default target. | |||
*/ | |||
public void testDefaults() throws Exception | |||
{ | |||
// Build project | |||
final File projFile = getTestResource( "defaults.ant" ); | |||
Project project = m_builder.build( projFile.getAbsolutePath() ); | |||
// Compare against expected project | |||
DefaultProject expected = createProject( projFile ); | |||
assertSameProject( expected, project ); | |||
} | |||
/** | |||
* Tests setting the project name. | |||
*/ | |||
public void testProjectName() throws Exception | |||
{ | |||
// Build project | |||
final File projFile = getTestResource( "set-project-name.ant" ); | |||
Project project = m_builder.build( projFile.getAbsolutePath() ); | |||
// Compare against expected project | |||
DefaultProject expected = createProject( projFile ); | |||
expected.setProjectName( "some-project" ); | |||
assertSameProject( expected, project ); | |||
} | |||
/** | |||
* Tests setting the base directory. | |||
*/ | |||
public void testBaseDirectory() throws Exception | |||
{ | |||
// Build project | |||
final File projFile = getTestResource( "set-base-dir.ant" ); | |||
Project project = m_builder.build( projFile.getAbsolutePath() ); | |||
// Compare against expected project | |||
DefaultProject expected = createProject( projFile ); | |||
final File baseDir = getTestDirectory( "other-base-dir" ); | |||
expected.setBaseDirectory( baseDir ); | |||
assertSameProject( expected, project ); | |||
} | |||
/** | |||
* Tests setting the default target name. | |||
*/ | |||
public void testDefaultTarget() throws Exception | |||
{ | |||
// Build project | |||
final File projFile = getTestResource( "set-default-target.ant" ); | |||
Project project = m_builder.build( projFile.getAbsolutePath() ); | |||
// Compare against expected project | |||
DefaultProject expected = createProject( projFile ); | |||
expected.setDefaultTargetName( "some-target" ); | |||
assertSameProject( expected, project ); | |||
} | |||
/** | |||
* Tests missing, invalid and incompatible project version. | |||
*/ | |||
public void testProjectVersion() throws Exception | |||
{ | |||
// No version | |||
File projFile = getTestResource( "no-version.ant" ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.version-missing.error" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
// Badly formed version | |||
projFile = getTestResource( "bad-version.ant" ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.malformed.version", "ant2" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
// Incompatible version | |||
projFile = getTestResource( "mismatched-version.ant" ); | |||
try | |||
{ | |||
m_builder.build( projFile.getAbsolutePath() ); | |||
fail(); | |||
} | |||
catch( ProjectException e ) | |||
{ | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", projFile.getAbsolutePath() ), | |||
REZ.getString( "ant.bad-version.error", "2.0.0", "1.0.2" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
} | |||
/** | |||
* Asserts that 2 projects are identical. | |||
*/ | |||
protected void assertSameProject( final Project expected, | |||
final Project project ) | |||
{ | |||
assertEquals( expected.getProjectName(), project.getProjectName() ); | |||
assertEquals( expected.getBaseDirectory(), project.getBaseDirectory() ); | |||
assertEquals( expected.getDefaultTargetName(), project.getDefaultTargetName() ); | |||
// TODO - make sure each of the projects are the same | |||
assertTrue( Arrays.equals( expected.getProjectNames(), project.getProjectNames() ) ); | |||
// TODO - make sure the implicit targets are the same | |||
// TODO - make sure each of the targets are the same | |||
assertTrue( Arrays.equals( expected.getTargetNames(), project.getTargetNames() ) ); | |||
// TODO - implement TypeLib.equals(), or use a comparator | |||
assertTrue( Arrays.equals( expected.getTypeLibs(), project.getTypeLibs() ) ); | |||
} | |||
/** | |||
* Tests validation of project and target names. | |||
*/ | |||
public void testNameValidation() throws Exception | |||
{ | |||
@@ -52,7 +272,12 @@ public class DefaultProjectBuilderTest | |||
} | |||
catch( Exception e ) | |||
{ | |||
assertSameMessage( REZ.getString( "ant.project-bad-name.error" ), e ); | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", badProjectFile.getAbsolutePath() ), | |||
REZ.getString( "ant.project-bad-name.error" ) | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
// Check bad target name | |||
@@ -64,7 +289,13 @@ public class DefaultProjectBuilderTest | |||
} | |||
catch( Exception e ) | |||
{ | |||
// TODO - check error message | |||
final String[] messages = | |||
{ | |||
REZ.getString( "ant.project-build.error", badTargetFile.getAbsolutePath() ), | |||
// TODO - check error message | |||
null | |||
}; | |||
assertSameMessage( messages, e ); | |||
} | |||
} | |||
} |
@@ -5,53 +5,51 @@ | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.myrmidon.components.workspace; | |||
package org.apache.myrmidon.components.property; | |||
import java.io.File; | |||
import java.util.Date; | |||
import org.apache.avalon.excalibur.i18n.ResourceManager; | |||
import org.apache.avalon.excalibur.i18n.Resources; | |||
import org.apache.avalon.framework.context.Context; | |||
import org.apache.myrmidon.AbstractMyrmidonTest; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.myrmidon.components.AbstractComponentTest; | |||
import org.apache.myrmidon.components.property.DefaultPropertyResolver; | |||
import org.apache.myrmidon.components.workspace.DefaultTaskContext; | |||
import org.apache.myrmidon.interfaces.property.PropertyResolver; | |||
/** | |||
* Functional tests for {@link DefaultPropertyResolver}. | |||
* General-purpose property resolver test cases. | |||
* | |||
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a> | |||
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||
* @version $Revision$ $Date$ | |||
*/ | |||
public class DefaultPropertyResolverTest | |||
extends AbstractComponentTest | |||
public abstract class AbstractPropertyResolverTest | |||
extends AbstractMyrmidonTest | |||
{ | |||
protected final static Resources REZ | |||
= ResourceManager.getPackageResources( DefaultPropertyResolver.class ); | |||
= ResourceManager.getPackageResources( AbstractPropertyResolverTest.class ); | |||
protected PropertyResolver m_resolver; | |||
protected DefaultTaskContext m_context; | |||
public DefaultPropertyResolverTest( String name ) | |||
public AbstractPropertyResolverTest( String name ) | |||
{ | |||
super( name ); | |||
} | |||
protected void setUp() throws Exception | |||
{ | |||
super.setUp(); | |||
m_resolver = createResolver(); | |||
m_context = new DefaultTaskContext( null, getServiceManager(), getLogger() ); | |||
m_context = new DefaultTaskContext( null, null, getLogger() ); | |||
m_context.setProperty( "intProp", new Integer( 333 ) ); | |||
m_context.setProperty( "stringProp", "String property" ); | |||
} | |||
protected PropertyResolver createResolver() | |||
{ | |||
return new DefaultPropertyResolver(); | |||
} | |||
/** | |||
* Creates the resolver to test. | |||
*/ | |||
protected abstract PropertyResolver createResolver(); | |||
/** | |||
* Test property resolution with various different typed properties. | |||
@@ -73,7 +71,7 @@ public class DefaultPropertyResolverTest | |||
throws Exception | |||
{ | |||
m_context.setProperty( "typedProp", propObject ); | |||
String propString = propObject.toString(); | |||
final String propString = propObject.toString(); | |||
doTestResolution( "${typedProp}", propObject, m_context ); | |||
doTestResolution( "${typedProp} with following text", | |||
@@ -96,23 +94,6 @@ public class DefaultPropertyResolverTest | |||
doTestResolution( "before ${prop2} between ${prop1} after", | |||
"before value2 between value1 after", m_context ); | |||
doTestResolution( "${prop1}-${int1}-${prop2}", "value1-123-value2", m_context ); | |||
} | |||
/** | |||
* Tests handing undefined property. | |||
*/ | |||
public void testUndefinedProp() throws Exception | |||
{ | |||
String undefinedProp = "undefinedProperty"; | |||
doTestFailure( "${" + undefinedProp + "}", | |||
REZ.getString( "prop.missing-value.error", undefinedProp ), | |||
m_context ); | |||
//TODO - "" should be disallowed as a property name | |||
doTestFailure( "${}", | |||
REZ.getString( "prop.missing-value.error", "" ), | |||
m_context ); | |||
} | |||
/** | |||
@@ -131,18 +112,17 @@ public class DefaultPropertyResolverTest | |||
/* TODO - need to handle these cases. */ | |||
// testFailure( "${bad${}", "", m_context ); | |||
// testFailure( "${ }", "", m_context ); | |||
} | |||
/** | |||
* Resolves the property using the supplied context, and checks the result. | |||
*/ | |||
protected void doTestResolution( String value, | |||
Object expected, | |||
Context context ) | |||
protected void doTestResolution( final String value, | |||
final Object expected, | |||
final Context context ) | |||
throws Exception | |||
{ | |||
Object resolved = m_resolver.resolveProperties( value, context ); | |||
final Object resolved = m_resolver.resolveProperties( value, context ); | |||
assertEquals( expected, resolved ); | |||
} | |||
@@ -151,9 +131,9 @@ public class DefaultPropertyResolverTest | |||
* Attempts to resolve the value using the supplied context, expecting to | |||
* fail with the supplied error message. | |||
*/ | |||
protected void doTestFailure( String value, | |||
String expectedErrorMessage, | |||
Context context ) | |||
protected void doTestFailure( final String value, | |||
final String expectedErrorMessage, | |||
final Context context ) | |||
{ | |||
try | |||
{ |
@@ -5,19 +5,18 @@ | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.myrmidon.components.workspace; | |||
package org.apache.myrmidon.components.property; | |||
import org.apache.myrmidon.interfaces.property.PropertyResolver; | |||
import org.apache.myrmidon.components.property.ClassicPropertyResolver; | |||
/** | |||
* A test for {@link ClassicPropertyResolver} | |||
* A test for {@link ClassicPropertyResolver}. | |||
* | |||
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a> | |||
* @version $Revision$ $Date$ | |||
*/ | |||
public class ClassicPropertyResolverTest | |||
extends DefaultPropertyResolverTest | |||
extends AbstractPropertyResolverTest | |||
{ | |||
public ClassicPropertyResolverTest( String name ) | |||
{ | |||
@@ -34,8 +33,7 @@ public class ClassicPropertyResolverTest | |||
*/ | |||
public void testUndefinedProp() throws Exception | |||
{ | |||
String undefinedProp = "undefinedProperty"; | |||
final String undefinedProp = "undefinedProperty"; | |||
final String propRef = "${" + undefinedProp + "}"; | |||
doTestResolution( propRef, propRef, m_context ); | |||
} |
@@ -0,0 +1,46 @@ | |||
/* | |||
* 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; | |||
/** | |||
* Functional tests for {@link DefaultPropertyResolver}. | |||
* | |||
* @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a> | |||
* @version $Revision$ $Date$ | |||
*/ | |||
public class DefaultPropertyResolverTest | |||
extends AbstractPropertyResolverTest | |||
{ | |||
public DefaultPropertyResolverTest( String name ) | |||
{ | |||
super( name ); | |||
} | |||
protected PropertyResolver createResolver() | |||
{ | |||
return new DefaultPropertyResolver(); | |||
} | |||
/** | |||
* Tests handing undefined property. | |||
*/ | |||
public void testUndefinedProp() throws Exception | |||
{ | |||
final String undefinedProp = "undefinedProperty"; | |||
doTestFailure( "${" + undefinedProp + "}", | |||
REZ.getString( "prop.missing-value.error", undefinedProp ), | |||
m_context ); | |||
//TODO - "" should be disallowed as a property name | |||
doTestFailure( "${}", | |||
REZ.getString( "prop.missing-value.error", "" ), | |||
m_context ); | |||
} | |||
} |
@@ -44,11 +44,9 @@ public class InstantiatingServiceManagerTest | |||
protected void setUp() | |||
throws Exception | |||
{ | |||
super.setUp(); | |||
// Set-up the service manager | |||
m_serviceManager = new InstantiatingServiceManager(); | |||
m_serviceManager.enableLogging( createLogger() ); | |||
m_serviceManager.enableLogging( getLogger() ); | |||
m_serviceManager.service( getServiceManager() ); | |||
m_serviceManager.parameterize( m_parameters ); | |||
} | |||