* 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; | package org.apache.myrmidon.components.builder; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.net.MalformedURLException; | |||||
| import java.net.URL; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.HashMap; | import java.util.HashMap; | ||||
| import javax.xml.parsers.SAXParser; | 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.ConfigurationException; | ||||
| import org.apache.avalon.framework.configuration.SAXConfigurationHandler; | import org.apache.avalon.framework.configuration.SAXConfigurationHandler; | ||||
| import org.apache.avalon.framework.logger.AbstractLogEnabled; | 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.ProjectBuilder; | ||||
| import org.apache.myrmidon.interfaces.builder.ProjectException; | import org.apache.myrmidon.interfaces.builder.ProjectException; | ||||
| import org.apache.myrmidon.interfaces.model.DefaultNameValidator; | 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.Project; | ||||
| import org.apache.myrmidon.interfaces.model.Target; | import org.apache.myrmidon.interfaces.model.Target; | ||||
| import org.apache.myrmidon.interfaces.model.TypeLib; | import org.apache.myrmidon.interfaces.model.TypeLib; | ||||
| @@ -78,31 +73,39 @@ public class DefaultProjectBuilder | |||||
| private Project build( final File file, final HashMap projects ) | private Project build( final File file, final HashMap projects ) | ||||
| throws ProjectException | 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. | * Parses the project. | ||||
| */ | */ | ||||
| private Configuration parseProject( final URL systemID ) | |||||
| private Configuration parseProject( final String systemID ) | |||||
| throws ProjectException | throws ProjectException | ||||
| { | { | ||||
| try | try | ||||
| @@ -117,13 +120,13 @@ public class DefaultProjectBuilder | |||||
| parser.setContentHandler( handler ); | parser.setContentHandler( handler ); | ||||
| parser.setErrorHandler( handler ); | parser.setErrorHandler( handler ); | ||||
| parser.parse( systemID.toString() ); | |||||
| parser.parse( systemID ); | |||||
| return handler.getConfiguration(); | return handler.getConfiguration(); | ||||
| } | } | ||||
| catch( Exception e ) | 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 ); | throw new ProjectException( message, e ); | ||||
| } | } | ||||
| } | } | ||||
| @@ -164,7 +167,7 @@ public class DefaultProjectBuilder | |||||
| File baseDirectory = file.getParentFile(); | File baseDirectory = file.getParentFile(); | ||||
| if( baseDirectoryName != null ) | if( baseDirectoryName != null ) | ||||
| { | { | ||||
| baseDirectory = new File( baseDirectory, baseDirectoryName ); | |||||
| baseDirectory = FileUtil.resolveFile( baseDirectory, baseDirectoryName ); | |||||
| } | } | ||||
| baseDirectory = baseDirectory.getAbsoluteFile(); | baseDirectory = baseDirectory.getAbsoluteFile(); | ||||
| @@ -257,7 +260,7 @@ public class DefaultProjectBuilder | |||||
| { | { | ||||
| final String message = | final String message = | ||||
| REZ.getString( "ant.malformed.version", versionString ); | 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 = | final Configuration[] implicitTasks = | ||||
| (Configuration[])implicitTaskList.toArray( new Configuration[ 0 ] ); | (Configuration[])implicitTaskList.toArray( new Configuration[ 0 ] ); | ||||
| final Target implicitTarget = new Target( null, implicitTasks, null ); | |||||
| final Target implicitTarget = new Target( implicitTasks, null ); | |||||
| project.setImplicitTarget( implicitTarget ); | project.setImplicitTarget( implicitTarget ); | ||||
| } | } | ||||
| @@ -378,26 +381,30 @@ public class DefaultProjectBuilder | |||||
| // Build the URL of the referenced projects | // Build the URL of the referenced projects | ||||
| final File baseDirectory = project.getBaseDirectory(); | final File baseDirectory = project.getBaseDirectory(); | ||||
| final File file = FileUtil.resolveFile( baseDirectory, location ); | final File file = FileUtil.resolveFile( baseDirectory, location ); | ||||
| final String systemID = extractURL( file ).toString(); | |||||
| // Locate the referenced project, building it if necessary | // 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 | // Add the reference | ||||
| project.addProject( name, other ); | 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 | try | ||||
| { | { | ||||
| return file.toURL(); | |||||
| return file.getCanonicalFile().toURL().toString(); | |||||
| } | } | ||||
| catch( MalformedURLException e ) | |||||
| catch( Exception e ) | |||||
| { | { | ||||
| final String message = REZ.getString( "ant.project-unexpected.error" ); | final String message = REZ.getString( "ant.project-unexpected.error" ); | ||||
| throw new ProjectException( message, e ); | throw new ProjectException( message, e ); | ||||
| @@ -443,8 +450,6 @@ public class DefaultProjectBuilder | |||||
| { | { | ||||
| final String name = target.getAttribute( "name", null ); | final String name = target.getAttribute( "name", null ); | ||||
| final String depends = target.getAttribute( "depends", 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 ); | verifyTargetName( name, target ); | ||||
| @@ -454,10 +459,8 @@ public class DefaultProjectBuilder | |||||
| getLogger().debug( message ); | 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 | //add target to project | ||||
| project.addTarget( name, defaultTarget ); | 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 | throws ProjectException | ||||
| { | { | ||||
| String[] dependencies = null; | |||||
| //apply depends attribute | //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() ) | 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 ); | 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.project-banner.notice=Project {0} base directory: {1}. | ||||
| ant.target-parse.notice=Parsing target: {0}. | 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.target-dependency.notice=Target dependency: {0} | ||||
| ant.project-unexpected.error=Unexpected error building project. | 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.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.unknown-toplevel-element.error=Unknown top-level element {0} at {1}. | ||||
| ant.project-bad-name.error=Invalid project name. | 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-noname.error=Discovered un-named target at {0}. | ||||
| ant.target-bad-name.error=Target with an invalid name 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.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-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}. | 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.excalibur.io.FileUtil; | ||||
| import org.apache.avalon.framework.context.Context; | import org.apache.avalon.framework.context.Context; | ||||
| import org.apache.avalon.framework.context.ContextException; | 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.ServiceException; | ||||
| import org.apache.avalon.framework.service.ServiceManager; | 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.TaskContext; | ||||
| import org.apache.myrmidon.api.TaskException; | import org.apache.myrmidon.api.TaskException; | ||||
| import org.apache.myrmidon.interfaces.model.DefaultNameValidator; | import org.apache.myrmidon.interfaces.model.DefaultNameValidator; | ||||
| @@ -60,7 +60,6 @@ public class DefaultTaskContext | |||||
| m_parent = parent; | m_parent = parent; | ||||
| m_serviceManager = serviceManager; | m_serviceManager = serviceManager; | ||||
| m_logger = logger; | 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.avalon.framework.service.Serviceable; | ||||
| import org.apache.myrmidon.api.TaskContext; | import org.apache.myrmidon.api.TaskContext; | ||||
| import org.apache.myrmidon.api.TaskException; | 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.Deployer; | ||||
| import org.apache.myrmidon.interfaces.deployer.DeploymentException; | import org.apache.myrmidon.interfaces.deployer.DeploymentException; | ||||
| import org.apache.myrmidon.interfaces.deployer.TypeDeployer; | import org.apache.myrmidon.interfaces.deployer.TypeDeployer; | ||||
| import org.apache.myrmidon.interfaces.executor.ExecutionFrame; | import org.apache.myrmidon.interfaces.executor.ExecutionFrame; | ||||
| import org.apache.myrmidon.interfaces.executor.Executor; | 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.Project; | ||||
| import org.apache.myrmidon.interfaces.model.Target; | import org.apache.myrmidon.interfaces.model.Target; | ||||
| import org.apache.myrmidon.interfaces.model.TypeLib; | import org.apache.myrmidon.interfaces.model.TypeLib; | ||||
| @@ -123,9 +123,7 @@ public class DefaultWorkspace | |||||
| m_listenerSupport.projectStarted( project.getProjectName() ); | m_listenerSupport.projectStarted( project.getProjectName() ); | ||||
| executeTarget( project, "<init>", project.getImplicitTarget(), entry.getFrame() ); | |||||
| execute( project, target, entry ); | |||||
| executeTarget( entry, target ); | |||||
| m_listenerSupport.projectFinished( project.getProjectName() ); | m_listenerSupport.projectFinished( project.getProjectName() ); | ||||
| } | } | ||||
| @@ -307,105 +305,130 @@ public class DefaultWorkspace | |||||
| /** | /** | ||||
| * Helper method to execute a target. | * 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 | * @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 | 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; | 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 ); | 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++ ) | 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 | throws TaskException | ||||
| { | { | ||||
| //notify listeners | |||||
| final Project project = entry.getProject(); | |||||
| // Notify listeners | |||||
| m_listenerSupport.targetStarted( project.getProjectName(), name ); | 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 ); | //frame.getContext().setProperty( Project.TARGET, target ); | ||||
| //execute all tasks assciated with target | |||||
| // Execute all tasks assciated with target | |||||
| final Configuration[] tasks = target.getTasks(); | final Configuration[] tasks = target.getTasks(); | ||||
| for( int i = 0; i < tasks.length; i++ ) | for( int i = 0; i < tasks.length; i++ ) | ||||
| { | { | ||||
| executeTask( tasks[ i ], frame ); | |||||
| executeTask( tasks[ i ], entry.getFrame() ); | |||||
| } | } | ||||
| //notify listeners | |||||
| // Notify listeners | |||||
| m_listenerSupport.targetFinished(); | m_listenerSupport.targetFinished(); | ||||
| } | } | ||||
| @@ -421,8 +444,11 @@ public class DefaultWorkspace | |||||
| { | { | ||||
| final String name = task.getName(); | 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 ??? | //is setting name even necessary ??? | ||||
| frame.getContext().setProperty( TaskContext.NAME, name ); | frame.getContext().setProperty( TaskContext.NAME, name ); | ||||
| @@ -7,12 +7,15 @@ | |||||
| */ | */ | ||||
| package org.apache.myrmidon.components.workspace; | 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.executor.ExecutionFrame; | ||||
| import org.apache.myrmidon.interfaces.model.Project; | 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> | * @author <a href="mailto:peter@apache.org">Peter Donald</a> | ||||
| * @version $Revision$ $Date$ | * @version $Revision$ $Date$ | ||||
| @@ -21,7 +24,9 @@ final class ProjectEntry | |||||
| { | { | ||||
| private final Project m_project; | private final Project m_project; | ||||
| private final ExecutionFrame m_frame; | 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, | public ProjectEntry( final Project project, | ||||
| final ExecutionFrame frame ) | final ExecutionFrame frame ) | ||||
| @@ -40,13 +45,18 @@ final class ProjectEntry | |||||
| return m_frame; | 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. | bad-frame.error=Error setting up ExecutionFrame. | ||||
| no-project.error=Project {0} not found. | no-project.error=Project {0} not found. | ||||
| no-target.error=Target {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}. | exec-task.notice=Executing task {0}. | ||||
| target-dependency-cycle.error=Cycle in dependencies for target {0}. | |||||
| #DefaultTaskContext | #DefaultTaskContext | ||||
| unknown-prop.error=Unknown property {0}. | 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-resolve.error=Unable to resolve value "{0}". | ||||
| bad-find-service.error=Could not find service "{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}. | 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. | * build a project from source. | ||||
| * | * | ||||
| * @param source the source | |||||
| * @param source the project file path. | |||||
| * @return the constructed Project | * @return the constructed Project | ||||
| * @exception ProjectException if an error occurs | * @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 java.util.ArrayList; | ||||
| import org.apache.avalon.framework.configuration.Configuration; | import org.apache.avalon.framework.configuration.Configuration; | ||||
| import org.apache.myrmidon.framework.conditions.Condition; | |||||
| /** | /** | ||||
| * Targets in build file. | * Targets in build file. | ||||
| @@ -21,19 +20,13 @@ public class Target | |||||
| { | { | ||||
| private final ArrayList m_dependencies = new ArrayList(); | private final ArrayList m_dependencies = new ArrayList(); | ||||
| private final ArrayList m_tasks = 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++ ) | for( int i = 0; i < tasks.length; i++ ) | ||||
| { | { | ||||
| m_tasks.add( tasks[ 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 | * Get dependencies of target | ||||
| * | * | ||||
| * @return the dependency list | * @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; | 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. | * Tests resolution of absolute URI. | ||||
| */ | */ | ||||
| @@ -11,13 +11,8 @@ import java.io.File; | |||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
| import org.apache.avalon.framework.ExceptionUtil; | import org.apache.avalon.framework.ExceptionUtil; | ||||
| import org.apache.avalon.framework.logger.LogKitLogger; | |||||
| import org.apache.avalon.framework.logger.Logger; | 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 | * 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_testBaseDir; | ||||
| private final File m_baseDir; | private final File m_baseDir; | ||||
| private final static String PATTERN = "[%8.8{category}] %{message}\\n%{throwable}"; | |||||
| private Logger m_logger; | |||||
| public AbstractMyrmidonTest( String name ) | public AbstractMyrmidonTest( String name ) | ||||
| { | { | ||||
| @@ -49,10 +43,39 @@ public abstract class AbstractMyrmidonTest | |||||
| * Locates a test resource, and asserts that the resource exists | * Locates a test resource, and asserts that the resource exists | ||||
| */ | */ | ||||
| protected File getTestResource( final String name ) | 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 file = new File( m_testBaseDir, name ); | ||||
| file = getCanonicalFile( file ); | 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; | return file; | ||||
| } | } | ||||
| @@ -83,18 +106,13 @@ public abstract class AbstractMyrmidonTest | |||||
| /** | /** | ||||
| * Creates a logger. | * 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 ) | 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; | Throwable current = throwable; | ||||
| for( int i = 0; i < messages.length; i++ ) | 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 ) | 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 | // Need to set the context classloader - The default embeddor uses it | ||||
| Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); | Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); | ||||
| final Logger logger = createLogger(); | |||||
| final Logger logger = getLogger(); | |||||
| m_embeddor = new DefaultEmbeddor(); | m_embeddor = new DefaultEmbeddor(); | ||||
| m_embeddor.enableLogging( logger ); | 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.LogEnabled; | ||||
| import org.apache.avalon.framework.logger.Logger; | import org.apache.avalon.framework.logger.Logger; | ||||
| import org.apache.avalon.framework.service.DefaultServiceManager; | 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.ServiceManager; | ||||
| import org.apache.avalon.framework.service.Serviceable; | import org.apache.avalon.framework.service.Serviceable; | ||||
| import org.apache.myrmidon.AbstractMyrmidonTest; | 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.converter.DefaultMasterConverter; | ||||
| import org.apache.myrmidon.components.deployer.DefaultDeployer; | import org.apache.myrmidon.components.deployer.DefaultDeployer; | ||||
| import org.apache.myrmidon.components.extensions.DefaultExtensionManager; | 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.role.DefaultRoleManager; | ||||
| import org.apache.myrmidon.components.type.DefaultTypeManager; | 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.classloader.ClassLoaderManager; | ||||
| import org.apache.myrmidon.interfaces.configurer.Configurer; | import org.apache.myrmidon.interfaces.configurer.Configurer; | ||||
| import org.apache.myrmidon.interfaces.converter.ConverterRegistry; | import org.apache.myrmidon.interfaces.converter.ConverterRegistry; | ||||
| import org.apache.myrmidon.interfaces.deployer.Deployer; | import org.apache.myrmidon.interfaces.deployer.Deployer; | ||||
| import org.apache.myrmidon.interfaces.extensions.ExtensionManager; | 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.RoleInfo; | ||||
| import org.apache.myrmidon.interfaces.role.RoleManager; | import org.apache.myrmidon.interfaces.role.RoleManager; | ||||
| import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | 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.type.TypeManager; | ||||
| import org.apache.myrmidon.interfaces.property.PropertyResolver; | |||||
| /** | /** | ||||
| * A base class for tests for the default components. | * A base class for tests for the default components. | ||||
| @@ -48,7 +46,6 @@ public abstract class AbstractComponentTest | |||||
| extends AbstractMyrmidonTest | extends AbstractMyrmidonTest | ||||
| { | { | ||||
| private DefaultServiceManager m_serviceManager; | private DefaultServiceManager m_serviceManager; | ||||
| private Logger m_logger; | |||||
| public AbstractComponentTest( final String name ) | public AbstractComponentTest( final String name ) | ||||
| { | { | ||||
| @@ -58,95 +55,85 @@ public abstract class AbstractComponentTest | |||||
| /** | /** | ||||
| * Returns the component manager containing the components to test. | * 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, | protected void registerConverter( final Class converterClass, | ||||
| final Class sourceClass, | final Class sourceClass, | ||||
| final Class destClass ) | final Class destClass ) | ||||
| throws ServiceException, TypeException | |||||
| throws Exception | |||||
| { | { | ||||
| ConverterRegistry converterRegistry = (ConverterRegistry)getServiceManager().lookup( ConverterRegistry.ROLE ); | ConverterRegistry converterRegistry = (ConverterRegistry)getServiceManager().lookup( ConverterRegistry.ROLE ); | ||||
| converterRegistry.registerConverter( converterClass.getName(), sourceClass.getName(), destClass.getName() ); | converterRegistry.registerConverter( converterClass.getName(), sourceClass.getName(), destClass.getName() ); | ||||
| @@ -8,9 +8,13 @@ | |||||
| package org.apache.myrmidon.components.builder; | package org.apache.myrmidon.components.builder; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.Arrays; | |||||
| import org.apache.avalon.excalibur.i18n.ResourceManager; | import org.apache.avalon.excalibur.i18n.ResourceManager; | ||||
| import org.apache.avalon.excalibur.i18n.Resources; | import org.apache.avalon.excalibur.i18n.Resources; | ||||
| import org.apache.avalon.excalibur.io.FileUtil; | |||||
| import org.apache.myrmidon.AbstractMyrmidonTest; | import org.apache.myrmidon.AbstractMyrmidonTest; | ||||
| import org.apache.myrmidon.interfaces.builder.ProjectException; | |||||
| import org.apache.myrmidon.interfaces.model.Project; | |||||
| /** | /** | ||||
| * Test cases for {@link DefaultProjectBuilder}. | * Test cases for {@link DefaultProjectBuilder}. | ||||
| @@ -22,7 +26,7 @@ public class DefaultProjectBuilderTest | |||||
| extends AbstractMyrmidonTest | extends AbstractMyrmidonTest | ||||
| { | { | ||||
| private final static Resources REZ | private final static Resources REZ | ||||
| = ResourceManager.getPackageResources( DefaultProjectBuilder.class ); | |||||
| = ResourceManager.getPackageResources( DefaultProjectBuilderTest.class ); | |||||
| private DefaultProjectBuilder m_builder; | private DefaultProjectBuilder m_builder; | ||||
| @@ -35,11 +39,227 @@ public class DefaultProjectBuilderTest | |||||
| { | { | ||||
| super.setUp(); | super.setUp(); | ||||
| m_builder = new DefaultProjectBuilder(); | 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 | public void testNameValidation() throws Exception | ||||
| { | { | ||||
| @@ -52,7 +272,12 @@ public class DefaultProjectBuilderTest | |||||
| } | } | ||||
| catch( Exception e ) | 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 | // Check bad target name | ||||
| @@ -64,7 +289,13 @@ public class DefaultProjectBuilderTest | |||||
| } | } | ||||
| catch( Exception e ) | 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 | * version 1.1, a copy of which has been included with this distribution in | ||||
| * the LICENSE.txt file. | * the LICENSE.txt file. | ||||
| */ | */ | ||||
| package org.apache.myrmidon.components.workspace; | |||||
| package org.apache.myrmidon.components.property; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.Date; | import java.util.Date; | ||||
| import org.apache.avalon.excalibur.i18n.ResourceManager; | import org.apache.avalon.excalibur.i18n.ResourceManager; | ||||
| import org.apache.avalon.excalibur.i18n.Resources; | import org.apache.avalon.excalibur.i18n.Resources; | ||||
| import org.apache.avalon.framework.context.Context; | import org.apache.avalon.framework.context.Context; | ||||
| import org.apache.myrmidon.AbstractMyrmidonTest; | |||||
| import org.apache.myrmidon.api.TaskException; | 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; | 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$ | * @version $Revision$ $Date$ | ||||
| */ | */ | ||||
| public class DefaultPropertyResolverTest | |||||
| extends AbstractComponentTest | |||||
| public abstract class AbstractPropertyResolverTest | |||||
| extends AbstractMyrmidonTest | |||||
| { | { | ||||
| protected final static Resources REZ | protected final static Resources REZ | ||||
| = ResourceManager.getPackageResources( DefaultPropertyResolver.class ); | |||||
| = ResourceManager.getPackageResources( AbstractPropertyResolverTest.class ); | |||||
| protected PropertyResolver m_resolver; | protected PropertyResolver m_resolver; | ||||
| protected DefaultTaskContext m_context; | protected DefaultTaskContext m_context; | ||||
| public DefaultPropertyResolverTest( String name ) | |||||
| public AbstractPropertyResolverTest( String name ) | |||||
| { | { | ||||
| super( name ); | super( name ); | ||||
| } | } | ||||
| protected void setUp() throws Exception | protected void setUp() throws Exception | ||||
| { | { | ||||
| super.setUp(); | |||||
| m_resolver = createResolver(); | 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( "intProp", new Integer( 333 ) ); | ||||
| m_context.setProperty( "stringProp", "String property" ); | 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. | * Test property resolution with various different typed properties. | ||||
| @@ -73,7 +71,7 @@ public class DefaultPropertyResolverTest | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| m_context.setProperty( "typedProp", propObject ); | m_context.setProperty( "typedProp", propObject ); | ||||
| String propString = propObject.toString(); | |||||
| final String propString = propObject.toString(); | |||||
| doTestResolution( "${typedProp}", propObject, m_context ); | doTestResolution( "${typedProp}", propObject, m_context ); | ||||
| doTestResolution( "${typedProp} with following text", | doTestResolution( "${typedProp} with following text", | ||||
| @@ -96,23 +94,6 @@ public class DefaultPropertyResolverTest | |||||
| doTestResolution( "before ${prop2} between ${prop1} after", | doTestResolution( "before ${prop2} between ${prop1} after", | ||||
| "before value2 between value1 after", m_context ); | "before value2 between value1 after", m_context ); | ||||
| doTestResolution( "${prop1}-${int1}-${prop2}", "value1-123-value2", 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. */ | /* TODO - need to handle these cases. */ | ||||
| // testFailure( "${bad${}", "", m_context ); | // testFailure( "${bad${}", "", m_context ); | ||||
| // testFailure( "${ }", "", m_context ); | // testFailure( "${ }", "", m_context ); | ||||
| } | } | ||||
| /** | /** | ||||
| * Resolves the property using the supplied context, and checks the result. | * 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 | throws Exception | ||||
| { | { | ||||
| Object resolved = m_resolver.resolveProperties( value, context ); | |||||
| final Object resolved = m_resolver.resolveProperties( value, context ); | |||||
| assertEquals( expected, resolved ); | assertEquals( expected, resolved ); | ||||
| } | } | ||||
| @@ -151,9 +131,9 @@ public class DefaultPropertyResolverTest | |||||
| * Attempts to resolve the value using the supplied context, expecting to | * Attempts to resolve the value using the supplied context, expecting to | ||||
| * fail with the supplied error message. | * 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 | try | ||||
| { | { | ||||
| @@ -5,19 +5,18 @@ | |||||
| * version 1.1, a copy of which has been included with this distribution in | * version 1.1, a copy of which has been included with this distribution in | ||||
| * the LICENSE.txt file. | * 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.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> | * @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a> | ||||
| * @version $Revision$ $Date$ | * @version $Revision$ $Date$ | ||||
| */ | */ | ||||
| public class ClassicPropertyResolverTest | public class ClassicPropertyResolverTest | ||||
| extends DefaultPropertyResolverTest | |||||
| extends AbstractPropertyResolverTest | |||||
| { | { | ||||
| public ClassicPropertyResolverTest( String name ) | public ClassicPropertyResolverTest( String name ) | ||||
| { | { | ||||
| @@ -34,8 +33,7 @@ public class ClassicPropertyResolverTest | |||||
| */ | */ | ||||
| public void testUndefinedProp() throws Exception | public void testUndefinedProp() throws Exception | ||||
| { | { | ||||
| String undefinedProp = "undefinedProperty"; | |||||
| final String undefinedProp = "undefinedProperty"; | |||||
| final String propRef = "${" + undefinedProp + "}"; | final String propRef = "${" + undefinedProp + "}"; | ||||
| doTestResolution( propRef, propRef, m_context ); | 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() | protected void setUp() | ||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| super.setUp(); | |||||
| // Set-up the service manager | // Set-up the service manager | ||||
| m_serviceManager = new InstantiatingServiceManager(); | m_serviceManager = new InstantiatingServiceManager(); | ||||
| m_serviceManager.enableLogging( createLogger() ); | |||||
| m_serviceManager.enableLogging( getLogger() ); | |||||
| m_serviceManager.service( getServiceManager() ); | m_serviceManager.service( getServiceManager() ); | ||||
| m_serviceManager.parameterize( m_parameters ); | 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; | 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. | * Tests resolution of absolute URI. | ||||
| */ | */ | ||||
| @@ -11,13 +11,8 @@ import java.io.File; | |||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
| import org.apache.avalon.framework.ExceptionUtil; | import org.apache.avalon.framework.ExceptionUtil; | ||||
| import org.apache.avalon.framework.logger.LogKitLogger; | |||||
| import org.apache.avalon.framework.logger.Logger; | 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 | * 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_testBaseDir; | ||||
| private final File m_baseDir; | private final File m_baseDir; | ||||
| private final static String PATTERN = "[%8.8{category}] %{message}\\n%{throwable}"; | |||||
| private Logger m_logger; | |||||
| public AbstractMyrmidonTest( String name ) | public AbstractMyrmidonTest( String name ) | ||||
| { | { | ||||
| @@ -49,10 +43,39 @@ public abstract class AbstractMyrmidonTest | |||||
| * Locates a test resource, and asserts that the resource exists | * Locates a test resource, and asserts that the resource exists | ||||
| */ | */ | ||||
| protected File getTestResource( final String name ) | 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 file = new File( m_testBaseDir, name ); | ||||
| file = getCanonicalFile( file ); | 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; | return file; | ||||
| } | } | ||||
| @@ -83,18 +106,13 @@ public abstract class AbstractMyrmidonTest | |||||
| /** | /** | ||||
| * Creates a logger. | * 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 ) | 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; | Throwable current = throwable; | ||||
| for( int i = 0; i < messages.length; i++ ) | 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 ) | 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 | // Need to set the context classloader - The default embeddor uses it | ||||
| Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); | Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); | ||||
| final Logger logger = createLogger(); | |||||
| final Logger logger = getLogger(); | |||||
| m_embeddor = new DefaultEmbeddor(); | m_embeddor = new DefaultEmbeddor(); | ||||
| m_embeddor.enableLogging( logger ); | 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.LogEnabled; | ||||
| import org.apache.avalon.framework.logger.Logger; | import org.apache.avalon.framework.logger.Logger; | ||||
| import org.apache.avalon.framework.service.DefaultServiceManager; | 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.ServiceManager; | ||||
| import org.apache.avalon.framework.service.Serviceable; | import org.apache.avalon.framework.service.Serviceable; | ||||
| import org.apache.myrmidon.AbstractMyrmidonTest; | 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.converter.DefaultMasterConverter; | ||||
| import org.apache.myrmidon.components.deployer.DefaultDeployer; | import org.apache.myrmidon.components.deployer.DefaultDeployer; | ||||
| import org.apache.myrmidon.components.extensions.DefaultExtensionManager; | 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.role.DefaultRoleManager; | ||||
| import org.apache.myrmidon.components.type.DefaultTypeManager; | 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.classloader.ClassLoaderManager; | ||||
| import org.apache.myrmidon.interfaces.configurer.Configurer; | import org.apache.myrmidon.interfaces.configurer.Configurer; | ||||
| import org.apache.myrmidon.interfaces.converter.ConverterRegistry; | import org.apache.myrmidon.interfaces.converter.ConverterRegistry; | ||||
| import org.apache.myrmidon.interfaces.deployer.Deployer; | import org.apache.myrmidon.interfaces.deployer.Deployer; | ||||
| import org.apache.myrmidon.interfaces.extensions.ExtensionManager; | 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.RoleInfo; | ||||
| import org.apache.myrmidon.interfaces.role.RoleManager; | import org.apache.myrmidon.interfaces.role.RoleManager; | ||||
| import org.apache.myrmidon.interfaces.type.DefaultTypeFactory; | 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.type.TypeManager; | ||||
| import org.apache.myrmidon.interfaces.property.PropertyResolver; | |||||
| /** | /** | ||||
| * A base class for tests for the default components. | * A base class for tests for the default components. | ||||
| @@ -48,7 +46,6 @@ public abstract class AbstractComponentTest | |||||
| extends AbstractMyrmidonTest | extends AbstractMyrmidonTest | ||||
| { | { | ||||
| private DefaultServiceManager m_serviceManager; | private DefaultServiceManager m_serviceManager; | ||||
| private Logger m_logger; | |||||
| public AbstractComponentTest( final String name ) | public AbstractComponentTest( final String name ) | ||||
| { | { | ||||
| @@ -58,95 +55,85 @@ public abstract class AbstractComponentTest | |||||
| /** | /** | ||||
| * Returns the component manager containing the components to test. | * 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, | protected void registerConverter( final Class converterClass, | ||||
| final Class sourceClass, | final Class sourceClass, | ||||
| final Class destClass ) | final Class destClass ) | ||||
| throws ServiceException, TypeException | |||||
| throws Exception | |||||
| { | { | ||||
| ConverterRegistry converterRegistry = (ConverterRegistry)getServiceManager().lookup( ConverterRegistry.ROLE ); | ConverterRegistry converterRegistry = (ConverterRegistry)getServiceManager().lookup( ConverterRegistry.ROLE ); | ||||
| converterRegistry.registerConverter( converterClass.getName(), sourceClass.getName(), destClass.getName() ); | converterRegistry.registerConverter( converterClass.getName(), sourceClass.getName(), destClass.getName() ); | ||||
| @@ -8,9 +8,13 @@ | |||||
| package org.apache.myrmidon.components.builder; | package org.apache.myrmidon.components.builder; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.Arrays; | |||||
| import org.apache.avalon.excalibur.i18n.ResourceManager; | import org.apache.avalon.excalibur.i18n.ResourceManager; | ||||
| import org.apache.avalon.excalibur.i18n.Resources; | import org.apache.avalon.excalibur.i18n.Resources; | ||||
| import org.apache.avalon.excalibur.io.FileUtil; | |||||
| import org.apache.myrmidon.AbstractMyrmidonTest; | import org.apache.myrmidon.AbstractMyrmidonTest; | ||||
| import org.apache.myrmidon.interfaces.builder.ProjectException; | |||||
| import org.apache.myrmidon.interfaces.model.Project; | |||||
| /** | /** | ||||
| * Test cases for {@link DefaultProjectBuilder}. | * Test cases for {@link DefaultProjectBuilder}. | ||||
| @@ -22,7 +26,7 @@ public class DefaultProjectBuilderTest | |||||
| extends AbstractMyrmidonTest | extends AbstractMyrmidonTest | ||||
| { | { | ||||
| private final static Resources REZ | private final static Resources REZ | ||||
| = ResourceManager.getPackageResources( DefaultProjectBuilder.class ); | |||||
| = ResourceManager.getPackageResources( DefaultProjectBuilderTest.class ); | |||||
| private DefaultProjectBuilder m_builder; | private DefaultProjectBuilder m_builder; | ||||
| @@ -35,11 +39,227 @@ public class DefaultProjectBuilderTest | |||||
| { | { | ||||
| super.setUp(); | super.setUp(); | ||||
| m_builder = new DefaultProjectBuilder(); | 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 | public void testNameValidation() throws Exception | ||||
| { | { | ||||
| @@ -52,7 +272,12 @@ public class DefaultProjectBuilderTest | |||||
| } | } | ||||
| catch( Exception e ) | 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 | // Check bad target name | ||||
| @@ -64,7 +289,13 @@ public class DefaultProjectBuilderTest | |||||
| } | } | ||||
| catch( Exception e ) | 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 | * version 1.1, a copy of which has been included with this distribution in | ||||
| * the LICENSE.txt file. | * the LICENSE.txt file. | ||||
| */ | */ | ||||
| package org.apache.myrmidon.components.workspace; | |||||
| package org.apache.myrmidon.components.property; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.Date; | import java.util.Date; | ||||
| import org.apache.avalon.excalibur.i18n.ResourceManager; | import org.apache.avalon.excalibur.i18n.ResourceManager; | ||||
| import org.apache.avalon.excalibur.i18n.Resources; | import org.apache.avalon.excalibur.i18n.Resources; | ||||
| import org.apache.avalon.framework.context.Context; | import org.apache.avalon.framework.context.Context; | ||||
| import org.apache.myrmidon.AbstractMyrmidonTest; | |||||
| import org.apache.myrmidon.api.TaskException; | 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; | 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$ | * @version $Revision$ $Date$ | ||||
| */ | */ | ||||
| public class DefaultPropertyResolverTest | |||||
| extends AbstractComponentTest | |||||
| public abstract class AbstractPropertyResolverTest | |||||
| extends AbstractMyrmidonTest | |||||
| { | { | ||||
| protected final static Resources REZ | protected final static Resources REZ | ||||
| = ResourceManager.getPackageResources( DefaultPropertyResolver.class ); | |||||
| = ResourceManager.getPackageResources( AbstractPropertyResolverTest.class ); | |||||
| protected PropertyResolver m_resolver; | protected PropertyResolver m_resolver; | ||||
| protected DefaultTaskContext m_context; | protected DefaultTaskContext m_context; | ||||
| public DefaultPropertyResolverTest( String name ) | |||||
| public AbstractPropertyResolverTest( String name ) | |||||
| { | { | ||||
| super( name ); | super( name ); | ||||
| } | } | ||||
| protected void setUp() throws Exception | protected void setUp() throws Exception | ||||
| { | { | ||||
| super.setUp(); | |||||
| m_resolver = createResolver(); | 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( "intProp", new Integer( 333 ) ); | ||||
| m_context.setProperty( "stringProp", "String property" ); | 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. | * Test property resolution with various different typed properties. | ||||
| @@ -73,7 +71,7 @@ public class DefaultPropertyResolverTest | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| m_context.setProperty( "typedProp", propObject ); | m_context.setProperty( "typedProp", propObject ); | ||||
| String propString = propObject.toString(); | |||||
| final String propString = propObject.toString(); | |||||
| doTestResolution( "${typedProp}", propObject, m_context ); | doTestResolution( "${typedProp}", propObject, m_context ); | ||||
| doTestResolution( "${typedProp} with following text", | doTestResolution( "${typedProp} with following text", | ||||
| @@ -96,23 +94,6 @@ public class DefaultPropertyResolverTest | |||||
| doTestResolution( "before ${prop2} between ${prop1} after", | doTestResolution( "before ${prop2} between ${prop1} after", | ||||
| "before value2 between value1 after", m_context ); | "before value2 between value1 after", m_context ); | ||||
| doTestResolution( "${prop1}-${int1}-${prop2}", "value1-123-value2", 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. */ | /* TODO - need to handle these cases. */ | ||||
| // testFailure( "${bad${}", "", m_context ); | // testFailure( "${bad${}", "", m_context ); | ||||
| // testFailure( "${ }", "", m_context ); | // testFailure( "${ }", "", m_context ); | ||||
| } | } | ||||
| /** | /** | ||||
| * Resolves the property using the supplied context, and checks the result. | * 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 | throws Exception | ||||
| { | { | ||||
| Object resolved = m_resolver.resolveProperties( value, context ); | |||||
| final Object resolved = m_resolver.resolveProperties( value, context ); | |||||
| assertEquals( expected, resolved ); | assertEquals( expected, resolved ); | ||||
| } | } | ||||
| @@ -151,9 +131,9 @@ public class DefaultPropertyResolverTest | |||||
| * Attempts to resolve the value using the supplied context, expecting to | * Attempts to resolve the value using the supplied context, expecting to | ||||
| * fail with the supplied error message. | * 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 | try | ||||
| { | { | ||||
| @@ -5,19 +5,18 @@ | |||||
| * version 1.1, a copy of which has been included with this distribution in | * version 1.1, a copy of which has been included with this distribution in | ||||
| * the LICENSE.txt file. | * 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.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> | * @author <a href="mailto:darrell@apache.org">Darrell DeBoer</a> | ||||
| * @version $Revision$ $Date$ | * @version $Revision$ $Date$ | ||||
| */ | */ | ||||
| public class ClassicPropertyResolverTest | public class ClassicPropertyResolverTest | ||||
| extends DefaultPropertyResolverTest | |||||
| extends AbstractPropertyResolverTest | |||||
| { | { | ||||
| public ClassicPropertyResolverTest( String name ) | public ClassicPropertyResolverTest( String name ) | ||||
| { | { | ||||
| @@ -34,8 +33,7 @@ public class ClassicPropertyResolverTest | |||||
| */ | */ | ||||
| public void testUndefinedProp() throws Exception | public void testUndefinedProp() throws Exception | ||||
| { | { | ||||
| String undefinedProp = "undefinedProperty"; | |||||
| final String undefinedProp = "undefinedProperty"; | |||||
| final String propRef = "${" + undefinedProp + "}"; | final String propRef = "${" + undefinedProp + "}"; | ||||
| doTestResolution( propRef, propRef, m_context ); | 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() | protected void setUp() | ||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| super.setUp(); | |||||
| // Set-up the service manager | // Set-up the service manager | ||||
| m_serviceManager = new InstantiatingServiceManager(); | m_serviceManager = new InstantiatingServiceManager(); | ||||
| m_serviceManager.enableLogging( createLogger() ); | |||||
| m_serviceManager.enableLogging( getLogger() ); | |||||
| m_serviceManager.service( getServiceManager() ); | m_serviceManager.service( getServiceManager() ); | ||||
| m_serviceManager.parameterize( m_parameters ); | m_serviceManager.parameterize( m_parameters ); | ||||
| } | } | ||||