diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibHandler.java index 82570ba2e..89872dc3b 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibHandler.java @@ -52,8 +52,7 @@ * . */ package org.apache.ant.antcore.antlib; -import org.apache.ant.antcore.util.ConfigException; - +import org.apache.ant.common.util.ConfigException; import org.apache.ant.antcore.xml.ElementHandler; import org.xml.sax.Attributes; import org.xml.sax.SAXParseException; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibManager.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibManager.java index 0304f2935..b380fac2f 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibManager.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibManager.java @@ -60,11 +60,11 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.ant.antcore.util.CircularDependencyChecker; -import org.apache.ant.antcore.util.CircularDependencyException; -import org.apache.ant.antcore.util.ConfigException; import org.apache.ant.antcore.xml.ParseContext; import org.apache.ant.antcore.xml.XMLParseException; +import org.apache.ant.common.util.CircularDependencyChecker; +import org.apache.ant.common.util.CircularDependencyException; +import org.apache.ant.common.util.ExecutionException; import org.apache.ant.init.InitConfig; import org.apache.ant.init.InitUtils; import org.apache.ant.init.LoaderUtils; @@ -102,10 +102,10 @@ public class AntLibManager { * @param libURL the URL from which Ant libraries are to be loaded * @exception MalformedURLException if the URL for the individual * library components cannot be formed - * @exception ConfigException if the library specs cannot be parsed + * @exception ExecutionException if the library specs cannot be parsed */ public void addAntLibraries(Map librarySpecs, URL libURL) - throws MalformedURLException, ConfigException { + throws MalformedURLException, ExecutionException { URL[] libURLs = LoaderUtils.getLocationURLs(libURL, libURL.toString(), ANTLIB_EXTENSIONS); @@ -122,7 +122,7 @@ public class AntLibManager { if (antLibrarySpec != null) { String libraryId = antLibrarySpec.getLibraryId(); if (librarySpecs.containsKey(libraryId)) { - throw new ConfigException("Found more than one " + throw new ExecutionException("Found more than one " + "copy of library with id = " + libraryId + " (" + libURLs[i] + ")"); } @@ -134,7 +134,7 @@ public class AntLibManager { // ignore file not found exceptions - means the // jar does not provide META-INF/antlib.xml if (!(t instanceof FileNotFoundException)) { - throw new ConfigException("Unable to parse Ant library " + throw new ExecutionException("Unable to parse Ant library " + libURLs[i], e); } } @@ -149,12 +149,12 @@ public class AntLibManager { * @param librarySpecs the loaded specifications of the Ant libraries * @param initConfig the Ant initialization configuration * @param libraries the collection of libraries already configured - * @exception ConfigException if a library cannot be configured from the - * given specification + * @exception ExecutionException if a library cannot be configured from + * the given specification */ public void configLibraries(InitConfig initConfig, Map librarySpecs, Map libraries) - throws ConfigException { + throws ExecutionException { // check if any already defined for (Iterator i = librarySpecs.keySet().iterator(); i.hasNext(); ) { @@ -162,7 +162,7 @@ public class AntLibManager { if (libraries.containsKey(libraryId)) { AntLibrary currentVersion = (AntLibrary)libraries.get(libraryId); - throw new ConfigException("Ant Library \"" + libraryId + throw new ExecutionException("Ant Library \"" + libraryId + "\" is already loaded from " + currentVersion.getDefinitionURL()); } @@ -185,12 +185,12 @@ public class AntLibManager { * @param libLocationString URL or file where libraries can be found * @param librarySpecs A collection of library specs which will be * populated with the libraries found - * @exception ConfigException if the libraries cannot be loaded + * @exception ExecutionException if the libraries cannot be loaded * @exception MalformedURLException if the library's location cannot be * formed */ public void loadLib(Map librarySpecs, String libLocationString) - throws ConfigException, MalformedURLException { + throws ExecutionException, MalformedURLException { File libLocation = new File(libLocationString); if (!libLocation.exists()) { @@ -198,7 +198,7 @@ public class AntLibManager { URL libLocationURL = new URL(libLocationString); if (!libLocationURL.getProtocol().equals("file") && !remoteAllowed) { - throw new ConfigException("The config library " + throw new ExecutionException("The config library " + "location \"" + libLocationString + "\" cannot be used because config does " + "not allow remote libraries"); @@ -223,13 +223,13 @@ public class AntLibManager { * dependencies. * @param libraries the collection of libraries which have already been * configured - * @exception ConfigException if the library cannot be configured. + * @exception ExecutionException if the library cannot be configured. */ private void configLibrary(InitConfig initConfig, Map librarySpecs, String libraryId, CircularDependencyChecker configuring, Map libraries) - throws ConfigException { + throws ExecutionException { try { configuring.visitNode(libraryId); @@ -240,7 +240,7 @@ public class AntLibManager { if (extendsId != null) { if (!libraries.containsKey(extendsId)) { if (!librarySpecs.containsKey(extendsId)) { - throw new ConfigException("Could not find library, " + throw new ExecutionException("Could not find library, " + extendsId + ", upon which library " + libraryId + " depends"); } @@ -284,7 +284,7 @@ public class AntLibManager { libraries.put(libraryId, antLibrary); configuring.leaveNode(libraryId); } catch (CircularDependencyException e) { - throw new ConfigException(e); + throw new ExecutionException(e); } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrarySpec.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrarySpec.java index f5e8acc4c..c3c270d4f 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrarySpec.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrarySpec.java @@ -57,7 +57,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.ant.antcore.util.ConfigException; +import org.apache.ant.common.util.ConfigException; /** * This class represents the specification of an Ant library. It is merely diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfig.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfig.java index 4c6aa4613..18dd2f623 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfig.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfig.java @@ -60,7 +60,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.ant.antcore.util.ConfigException; +import org.apache.ant.common.util.ConfigException; import org.apache.ant.common.util.PathTokenizer; import org.apache.ant.init.InitUtils; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfigHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfigHandler.java index f1b7e2545..b2c1cdf39 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfigHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfigHandler.java @@ -52,7 +52,7 @@ * . */ package org.apache.ant.antcore.config; -import org.apache.ant.antcore.util.ConfigException; +import org.apache.ant.common.util.ConfigException; import org.apache.ant.antcore.xml.ElementHandler; import org.xml.sax.Attributes; import org.xml.sax.SAXParseException; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java index 4e0a02ee6..e586a3743 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java @@ -56,7 +56,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.apache.ant.antcore.model.ModelElement; +import org.apache.ant.common.model.ModelElement; import org.apache.ant.common.event.BuildListener; import org.apache.ant.common.event.BuildEvent; @@ -101,19 +101,6 @@ public class BuildEventSupport { listeners.remove(listener); } - /** - * Forward the given event to the subscibed listeners - * - * @param event the event to be forwarded to the listeners - */ - public void forwardEvent(BuildEvent event) { - for (Iterator i = listeners.iterator(); i.hasNext(); ) { - BuildListener listener = (BuildListener)i.next(); - - listener.processBuildEvent(event); - } - } - /** * Fire a build started event * @@ -121,7 +108,10 @@ public class BuildEventSupport { */ public void fireBuildStarted(ModelElement element) { BuildEvent event = new BuildEvent(element, BuildEvent.BUILD_STARTED); - forwardEvent(event); + for (Iterator i = listeners.iterator(); i.hasNext(); ) { + BuildListener listener = (BuildListener)i.next(); + listener.buildStarted(event); + } } /** @@ -134,7 +124,10 @@ public class BuildEventSupport { Throwable cause) { BuildEvent event = new BuildEvent(element, BuildEvent.BUILD_FINISHED, cause); - forwardEvent(event); + for (Iterator i = listeners.iterator(); i.hasNext(); ) { + BuildListener listener = (BuildListener)i.next(); + listener.buildFinished(event); + } } /** @@ -144,7 +137,10 @@ public class BuildEventSupport { */ public void fireTargetStarted(ModelElement element) { BuildEvent event = new BuildEvent(element, BuildEvent.TARGET_STARTED); - forwardEvent(event); + for (Iterator i = listeners.iterator(); i.hasNext(); ) { + BuildListener listener = (BuildListener)i.next(); + listener.targetStarted(event); + } } /** @@ -157,7 +153,10 @@ public class BuildEventSupport { Throwable cause) { BuildEvent event = new BuildEvent(element, BuildEvent.TARGET_FINISHED, cause); - forwardEvent(event); + for (Iterator i = listeners.iterator(); i.hasNext(); ) { + BuildListener listener = (BuildListener)i.next(); + listener.targetFinished(event); + } } /** @@ -167,7 +166,10 @@ public class BuildEventSupport { */ public void fireTaskStarted(ModelElement element) { BuildEvent event = new BuildEvent(element, BuildEvent.TASK_STARTED); - forwardEvent(event); + for (Iterator i = listeners.iterator(); i.hasNext(); ) { + BuildListener listener = (BuildListener)i.next(); + listener.taskStarted(event); + } } /** @@ -180,7 +182,10 @@ public class BuildEventSupport { Throwable cause) { BuildEvent event = new BuildEvent(element, BuildEvent.TASK_FINISHED, cause); - forwardEvent(event); + for (Iterator i = listeners.iterator(); i.hasNext(); ) { + BuildListener listener = (BuildListener)i.next(); + listener.taskFinished(event); + } } /** @@ -193,7 +198,10 @@ public class BuildEventSupport { public void fireMessageLogged(ModelElement element, String message, int priority) { BuildEvent event = new BuildEvent(element, message, priority); - forwardEvent(event); + for (Iterator i = listeners.iterator(); i.hasNext(); ) { + BuildListener listener = (BuildListener)i.next(); + listener.messageLogged(event); + } } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ClassIntrospector.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ClassIntrospector.java index 9b1ad68a9..c9c8c01e7 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ClassIntrospector.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ClassIntrospector.java @@ -95,7 +95,16 @@ public class ClassIntrospector { && !args[0].isArray()) { reflector.addAttributeMethod(m, getPropertyName(name, "set"), converters); - } else if (name.startsWith("add") + } else if (name.startsWith("addConfigured") + && name.length() > 13 + && returnType.equals(Void.TYPE) + && args.length == 1 + && !args[0].equals(String.class) + && !args[0].isArray() + && !args[0].isPrimitive()) { + reflector.addElementMethod(m, + getPropertyName(name, "addConfigured")); + } else if (name.startsWith("add") && name.length() > 3 && returnType.equals(Void.TYPE) && args.length == 1 @@ -103,7 +112,7 @@ public class ClassIntrospector { && !args[0].isArray() && !args[0].isPrimitive()) { reflector.addElementMethod(m, getPropertyName(name, "add")); - } else if (name.startsWith("create") + } else if (name.startsWith("create") && name.length() > 6 && !returnType.isArray() && !returnType.isPrimitive() diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java new file mode 100644 index 000000000..d1aca6a53 --- /dev/null +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java @@ -0,0 +1,358 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antcore.execution; +import java.io.File; +import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.apache.ant.antcore.antlib.AntLibDefinition; +import org.apache.ant.antcore.antlib.AntLibManager; +import org.apache.ant.antcore.antlib.AntLibrary; +import org.apache.ant.antcore.modelparser.XMLProjectParser; +import org.apache.ant.antcore.xml.XMLParseException; +import org.apache.ant.common.antlib.AntLibFactory; +import org.apache.ant.common.antlib.Converter; +import org.apache.ant.common.antlib.StandardLibFactory; +import org.apache.ant.common.model.Project; +import org.apache.ant.common.service.ComponentService; +import org.apache.ant.common.util.ExecutionException; +import org.apache.ant.init.InitUtils; + +/** + * The instance of the ComponentServices made available by the core to the + * ant libraries. + * + * @author Conor MacNeill + * @created 27 January 2002 + */ +public class ComponentManager implements ComponentService { + /** The prefix for library ids that are automatically imported */ + public final static String ANT_LIB_PREFIX = "ant."; + + /** + * Type converters for this executionFrame. Converters are used when + * configuring Tasks to handle special type conversions. + */ + private Map converters = new HashMap(); + + /** The factory objects for each library, indexed by the library Id */ + private Map libFactories = new HashMap(); + + /** The ExecutionFrame this service instance is working for */ + private ExecutionFrame frame; + + /** The library manager instance used to configure libraries. */ + private AntLibManager libManager; + + /** + * These are AntLibraries which have been loaded into this component + * manager + */ + private Map antLibraries; + /** The definitions which have been imported into this frame. */ + private Map definitions = new HashMap(); + + /** + * Constructor + * + * @param executionFrame the frame containing this context + * @param allowRemoteLibs true if remote libraries can be loaded though + * this service. + */ + protected ComponentManager(ExecutionFrame executionFrame, + boolean allowRemoteLibs) { + this.frame = executionFrame; + libManager = new AntLibManager(allowRemoteLibs); + } + + /** + * Load a library or set of libraries from a location making them + * available for use + * + * @param libLocation the file or URL of the library location + * @param importAll if true all tasks are imported as the library is + * loaded + * @exception ExecutionException if the library cannot be loaded + */ + public void loadLib(String libLocation, boolean importAll) + throws ExecutionException { + try { + Map librarySpecs = new HashMap(); + libManager.loadLib(librarySpecs, libLocation); + libManager.configLibraries(frame.getInitConfig(), librarySpecs, + antLibraries); + + if (importAll) { + Iterator i = librarySpecs.keySet().iterator(); + while (i.hasNext()) { + String libraryId = (String)i.next(); + importLibrary(libraryId); + } + } + } catch (MalformedURLException e) { + throw new ExecutionException("Unable to load libraries from " + + libLocation, e); + } + } + + /** + * Run a sub-build. + * + * @param antFile the file containing the XML description of the model + * @param targets A list of targets to be run + * @param properties the initiali properties to be used in the build + * @exception ExecutionException if the subbuild cannot be run + */ + public void runBuild(File antFile, Map properties, List targets) + throws ExecutionException { + try { + // Parse the build file into a project + XMLProjectParser parser = new XMLProjectParser(); + Project project + = parser.parseBuildFile(InitUtils.getFileURL(antFile)); + runBuild(project, properties, targets); + } catch (MalformedURLException e) { + throw new ExecutionException(e); + } catch (XMLParseException e) { + throw new ExecutionException(e); + } + } + + /** + * Run a sub-build. + * + * @param model the project model to be used for the build + * @param targets A list of targets to be run + * @param properties the initiali properties to be used in the build + * @exception ExecutionException if the subbuild cannot be run + */ + public void runBuild(Project model, Map properties, List targets) + throws ExecutionException { + ExecutionFrame newFrame = frame.createFrame(model); + newFrame.setInitialProperties(properties); + newFrame.runBuild(targets); + } + + /** + * Run a sub-build using the current frame's project model + * + * @param targets A list of targets to be run + * @param properties the initiali properties to be used in the build + * @exception ExecutionException if the subbuild cannot be run + */ + public void callTarget(Map properties, List targets) + throws ExecutionException { + runBuild(frame.getProject(), properties, targets); + } + + /** + * Set the standard libraries (i.e. those which are independent of the + * build files) to be used in this component manager + * + * @param standardLibs A collection of AntLibrary objects indexed by + * their libraryId + * @exception ExecutionException if the components cannot be imported + * form the libraries fro which such importing is automatic. + */ + protected void setStandardLibraries(Map standardLibs) + throws ExecutionException { + antLibraries = new HashMap(standardLibs); + + // go through the libraries and import all standard ant libraries + for (Iterator i = antLibraries.keySet().iterator(); i.hasNext(); ) { + String libraryId = (String)i.next(); + if (libraryId.startsWith(ANT_LIB_PREFIX)) { + // standard library - import whole library + importLibrary(libraryId); + } + } + } + + /** + * Get the collection ov converters currently configured + * + * @return A map of converter instances indexed on the class they can + * convert + */ + protected Map getConverters() { + return converters; + } + + /** + * Get the collection of Ant Libraries defined for this frame + * + * @return a map of Ant Libraries indexed by thier library Id + */ + protected Map getAntLibraries() { + return antLibraries; + } + + /** + * Gets the factory object for the given library + * + * @param antLibrary the library for which the factory is required + * @return the library's factory object + * @exception ExecutionException if the factory cannot be initialised + */ + protected AntLibFactory getLibFactory(AntLibrary antLibrary) + throws ExecutionException { + String libraryId = antLibrary.getLibraryId(); + if (libFactories.containsKey(libraryId)) { + return (AntLibFactory)libFactories.get(libraryId); + } + AntLibFactory libFactory = antLibrary.getFactory(); + if (libFactory == null) { + libFactory = new StandardLibFactory(); + } + libFactories.put(libraryId, libFactory); + libFactory.init(new ExecutionContext(frame)); + return libFactory; + } + + /** + * Get an imported definition from the component manager + * + * @param name the name under which the component has been imported + * @return the ImportInfo object detailing the import's library and + * other details + */ + protected ImportInfo getDefinition(String name) { + return (ImportInfo)definitions.get(name); + } + + /** + * Import a complete library into this frame + * + * @param libraryId The id of the library to be imported + * @exception ExecutionException if the library cannot be imported + */ + protected void importLibrary(String libraryId) throws ExecutionException { + AntLibrary library = (AntLibrary)antLibraries.get(libraryId); + if (library == null) { + throw new ExecutionException("Unable to import library " + libraryId + + " as it has not been loaded"); + } + Map libDefs = library.getDefinitions(); + for (Iterator i = libDefs.keySet().iterator(); i.hasNext(); ) { + String defName = (String)i.next(); + AntLibDefinition libdef + = (AntLibDefinition)libDefs.get(defName); + definitions.put(defName, new ImportInfo(library, libdef)); + } + addLibraryConverters(library); + } + + /** + * Add the converters from the given library to those managed by this + * frame. + * + * @param library the library from which the converters are required + * @exception ExecutionException if a converter defined in the library + * cannot be instantiated + */ + private void addLibraryConverters(AntLibrary library) + throws ExecutionException { + if (!library.hasConverters()) { + return; + } + + String className = null; + try { + AntLibFactory libFactory = getLibFactory(library); + ClassLoader converterLoader = library.getClassLoader(); + for (Iterator i = library.getConverterClassNames(); i.hasNext(); ) { + className = (String)i.next(); + Class converterClass + = Class.forName(className, true, converterLoader); + if (!Converter.class.isAssignableFrom(converterClass)) { + throw new ExecutionException("In Ant library \"" + + library.getLibraryId() + "\" the converter class " + + converterClass.getName() + + " does not implement the Converter interface"); + } + Converter converter + = libFactory.createConverter(converterClass); + ExecutionContext context + = new ExecutionContext(frame); + converter.init(context); + Class[] converterTypes = converter.getTypes(); + for (int j = 0; j < converterTypes.length; ++j) { + converters.put(converterTypes[j], converter); + } + } + } catch (ClassNotFoundException e) { + throw new ExecutionException("In Ant library \"" + + library.getLibraryId() + "\" converter class " + + className + " was not found", e); + } catch (NoClassDefFoundError e) { + throw new ExecutionException("In Ant library \"" + + library.getLibraryId() + + "\" could not load a dependent class (" + + e.getMessage() + ") for converter " + className); + } catch (InstantiationException e) { + throw new ExecutionException("In Ant library \"" + + library.getLibraryId() + + "\" unable to instantiate converter class " + + className, e); + } catch (IllegalAccessException e) { + throw new ExecutionException("In Ant library \"" + + library.getLibraryId() + + "\" unable to access converter class " + + className, e); + } + } +} + diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java index 6e4c75573..d71190ce8 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java @@ -53,11 +53,10 @@ */ package org.apache.ant.antcore.execution; import java.io.File; -import org.apache.ant.antcore.model.ModelElement; import org.apache.ant.common.antlib.AntContext; +import org.apache.ant.common.model.ModelElement; import org.apache.ant.common.util.ExecutionException; import org.apache.ant.common.util.FileUtils; -import org.apache.ant.common.util.Location; /** * This is the core's implementation of the AntContext for all core objects. @@ -83,13 +82,10 @@ public class ExecutionContext implements AntContext { * Initilaise this context's environment * * @param frame the frame containing this context - * @param eventSupport the event support instance used to send build - * events */ - public ExecutionContext(ExecutionFrame frame, - BuildEventSupport eventSupport) { + public ExecutionContext(ExecutionFrame frame) { this.frame = frame; - this.eventSupport = eventSupport; + this.eventSupport = frame.getEventSupport(); } /** @@ -116,15 +112,17 @@ public class ExecutionContext implements AntContext { } /** - * Get the build fiel location with which this context is associated + * Get the model element associated with this context. If the context is + * not associated with any particular model element, the project model + * is returned. * - * @return the associated location object. + * @return the model element. */ - public Location getLocation() { - if (modelElement != null) { - return modelElement.getLocation(); + public ModelElement getModelElement() { + if (modelElement == null) { + return frame.getProject(); } - return Location.UNKNOWN_LOCATION; + return modelElement; } /** diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionDataService.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionDataService.java index 727ea51f6..02e2a45b2 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionDataService.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionDataService.java @@ -131,6 +131,18 @@ public class ExecutionDataService implements DataService { return frame.isDataValueSet(name); } + /** + * Get all the properties from the frame and any references frames. This + * is an expensive operation since it must clone all of the property + * stores in all frames + * + * @return a Map containing the frames properties indexed by their full + * name. + */ + public Map getAllProperties() { + return frame.getAllProperties(); + } + /** * Replace ${} style constructions in the given value with the string * value of the corresponding data values in the frame @@ -157,8 +169,8 @@ public class ExecutionDataService implements DataService { if (fragment == null) { String propertyName = (String)j.next(); if (!isDataValueSet(propertyName)) { - throw new ExecutionException("Property " + propertyName - + " has not been set"); + throw new ExecutionException("Property \"" + propertyName + + "\" has not been set"); } fragment = getDataValue(propertyName).toString(); } @@ -207,16 +219,5 @@ public class ExecutionDataService implements DataService { return sb.toString(); } - - /** - * Get all the properties from the frame and any references frames. This - * is an expensive operation since it must clone all of the property - * stores in all frames - * - * @return a Map containing the frames properties indexed by their full name. - */ - public Map getAllProperties() { - return frame.getAllProperties(); - } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFrame.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFrame.java index fd2e7e8a0..6ed9212cf 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFrame.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFrame.java @@ -59,25 +59,23 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; -import org.apache.ant.antcore.antlib.AntLibDefinition; import org.apache.ant.antcore.antlib.AntLibrary; import org.apache.ant.antcore.config.AntConfig; -import org.apache.ant.antcore.model.BuildElement; -import org.apache.ant.antcore.model.Project; -import org.apache.ant.antcore.model.Target; -import org.apache.ant.antcore.util.ConfigException; import org.apache.ant.common.antlib.AntLibFactory; -import org.apache.ant.common.antlib.Converter; import org.apache.ant.common.antlib.ExecutionComponent; -import org.apache.ant.common.antlib.StandardLibFactory; import org.apache.ant.common.antlib.Task; import org.apache.ant.common.antlib.TaskContainer; import org.apache.ant.common.event.BuildListener; +import org.apache.ant.common.model.BuildElement; +import org.apache.ant.common.model.Project; +import org.apache.ant.common.model.Target; import org.apache.ant.common.service.ComponentService; import org.apache.ant.common.service.DataService; import org.apache.ant.common.service.FileService; import org.apache.ant.common.util.AntException; +import org.apache.ant.common.util.ConfigException; import org.apache.ant.common.util.ExecutionException; +import org.apache.ant.common.util.FileUtils; import org.apache.ant.common.util.Location; import org.apache.ant.common.util.MessageLevel; import org.apache.ant.init.InitConfig; @@ -91,74 +89,18 @@ import org.apache.ant.init.InitConfig; * @created 14 January 2002 */ public class ExecutionFrame { - - /** - * This class is used to maintain information about imports - * - * @author Conor MacNeill - * @created 16 January 2002 - */ - private static class ImportInfo { - /** the ant library from which the import is made */ - private AntLibrary library; - /** the library definition information */ - private AntLibDefinition libDefinition; - - /** - * ImportInfo records what has been imported from an Ant Library - * - * @param library The library from which the import was made - * @param libDefinition the library definition information - */ - public ImportInfo(AntLibrary library, AntLibDefinition libDefinition) { - this.library = library; - this.libDefinition = libDefinition; - } - - /** - * Get the classname that has been imported - * - * @return the classname that was imported. - */ - public String getClassName() { - return libDefinition.getClassName(); - } - - /** - * Get the library from which the import was made - * - * @return the library from which the import was made - */ - public AntLibrary getAntLibrary() { - return library; - } - - /** - * Get the type of the definition that was imported - * - * @return the type of definition - */ - public int getDefinitionType() { - return libDefinition.getDefinitionType(); - } - - } + /** A magic property which sets the execution base directory */ + public final static String BASEDIR_PROP = "basedir"; /** The Ant aspect used to identify Ant metadata */ public final static String ANT_ASPECT = "ant"; - /** The prefix for library ids that are automatically imported */ - public final static String ANT_LIB_PREFIX = "ant."; - /** the base dir of the project */ private File baseDir; /** The Project that this execution frame is processing */ private Project project = null; - /** The factory objects for each library, indexed by the library Id */ - private Map libFactories = new HashMap(); - /** The referenced frames corresponding to the referenced projects */ private Map referencedFrames = new HashMap(); @@ -183,24 +125,9 @@ public class ExecutionFrame { */ private Map standardLibs; - /** - * These are AntLibraries which have been loaded in this - * ExecutionFrame's build file. - */ - private Map antLibraries; - - /** The definitions which have been imported into this frame. */ - private Map definitions = new HashMap(); - /** BuildEvent support used to fire events and manage listeners */ private BuildEventSupport eventSupport = new BuildEventSupport(); - /** - * Type converters for this executionFrame. Converters are used when - * configuring Tasks to handle special type conversions. - */ - private Map converters = new HashMap(); - /** * The services map is a map of service interface classes to instances * which provide the service. @@ -218,6 +145,15 @@ public class ExecutionFrame { */ private DataService dataService; + /** The execution file service instance */ + private FileService fileService; + + /** + * the Component Manager used to manage the importing of library + * components from the Ant libraries + */ + private ComponentManager componentManager; + /** * Create an Execution Frame for the given project * @@ -225,32 +161,17 @@ public class ExecutionFrame { * this frame * @param config the user config to use for this execution of Ant * @param initConfig Ant's initialisation config - * @exception ConfigException if a component of the library cannot be + * @exception ExecutionException if a component of the library cannot be * imported */ protected ExecutionFrame(Map standardLibs, InitConfig initConfig, - AntConfig config) throws ConfigException { + AntConfig config) throws ExecutionException { this.standardLibs = standardLibs; this.config = config; this.initConfig = initConfig; configureServices(); - - antLibraries = new HashMap(standardLibs); - - try { - // go through the libraries and import all standard ant libraries - for (Iterator i = antLibraries.keySet().iterator(); i.hasNext(); ) { - String libraryId = (String)i.next(); - if (libraryId.startsWith(ANT_LIB_PREFIX)) { - // standard library - import whole library - importLibrary(libraryId); - } - } - } catch (ExecutionException e) { - throw new ConfigException(e); - } - + componentManager.setStandardLibraries(standardLibs); } /** @@ -267,88 +188,24 @@ public class ExecutionFrame { return currentLoader; } - /** - * Gets the project model this frame is working with - * - * @return the project model - */ - public Project getProject() { - return project; - } - - - /** - * Get all the properties from the frame and any references frames. This - * is an expensive operation since it must clone all of the property - * stores in all frames - * - * @return a Map containing the frames properties indexed by their full name. - */ - public Map getAllProperties() { - Map allProperties = new HashMap(dataValues); - Iterator i = referencedFrames.keySet().iterator(); - while (i.hasNext()) { - String refName = (String)i.next(); - ExecutionFrame refFrame = getReferencedFrame(refName); - Map refProperties = refFrame.getAllProperties(); - Iterator j = refProperties.keySet().iterator(); - while (j.hasNext()) { - String name = (String)j.next(); - Object value = refProperties.get(name); - allProperties.put(refName + Project.REF_DELIMITER + name, - value); - } - } - - return allProperties; - } - - /** - * Log a message as a build event - * - * @param message the message to be logged - * @param level the priority level of the message - */ - public void log(String message, int level) { - eventSupport.fireMessageLogged(project, message, level); - } - /** * Sets the Project of the ExecutionFrame * * @param project The new Project value - * @exception ConfigException if any required sub-frames cannot be + * @exception ExecutionException if any required sub-frames cannot be * created and configured */ - protected void setProject(Project project) throws ConfigException { + protected void setProject(Project project) throws ExecutionException { this.project = project; - URL projectURL = project.getSourceURL(); - if (projectURL.getProtocol().equals("file")) { - File projectFile = new File(projectURL.getFile()); - String base = project.getBase(); - if (base == null) { - base = "."; - } - baseDir = new File(projectFile.getParentFile(), base); - } else { - baseDir = new File("."); - } - referencedFrames = new HashMap(); for (Iterator i = project.getReferencedProjectNames(); i.hasNext(); ) { String referenceName = (String)i.next(); Project referencedProject = project.getReferencedProject(referenceName); - ExecutionFrame referencedFrame - = new ExecutionFrame(standardLibs, initConfig, config); - referencedFrame.setProject(referencedProject); + ExecutionFrame referencedFrame = createFrame(referencedProject); referencedFrames.put(referenceName, referencedFrame); - for (Iterator j = eventSupport.getListeners(); j.hasNext(); ) { - BuildListener listener = (BuildListener)j.next(); - referencedFrame.addBuildListener(listener); - } } } @@ -376,12 +233,59 @@ public class ExecutionFrame { } /** - * Get the collection of Ant Libraries defined for this frame + * Set the initial properties to be used when the frame starts execution + * + * @param properties a Map of named properties which may in fact be any + * object + * @exception ExecutionException if the properties cannot be set + */ + protected void setInitialProperties(Map properties) + throws ExecutionException { + if (properties == null) { + return; + } + for (Iterator i = properties.keySet().iterator(); i.hasNext(); ) { + String name = (String)i.next(); + Object value = properties.get(name); + setDataValue(name, value, false); + } + } + + /** + * Gets the project model this frame is working with + * + * @return the project model + */ + protected Project getProject() { + return project; + } + + + /** + * Get all the properties from the frame and any references frames. This + * is an expensive operation since it must clone all of the property + * stores in all frames * - * @return a map of Ant Libraries indexed by thier library Id + * @return a Map containing the frames properties indexed by their full + * name. */ - protected Map getAntLibraries() { - return antLibraries; + protected Map getAllProperties() { + Map allProperties = new HashMap(dataValues); + Iterator i = referencedFrames.keySet().iterator(); + while (i.hasNext()) { + String refName = (String)i.next(); + ExecutionFrame refFrame = getReferencedFrame(refName); + Map refProperties = refFrame.getAllProperties(); + Iterator j = refProperties.keySet().iterator(); + while (j.hasNext()) { + String name = (String)j.next(); + Object value = refProperties.get(name); + allProperties.put(refName + Project.REF_DELIMITER + name, + value); + } + } + + return allProperties; } /** @@ -422,6 +326,16 @@ public class ExecutionFrame { return service; } + /** + * Get the EventSupport instance for this frame. This tracks the build + * listeners on this frame + * + * @return the EventSupport instance + */ + protected BuildEventSupport getEventSupport() { + return eventSupport; + } + /** * Gets the baseDir of the ExecutionFrame * @@ -500,6 +414,35 @@ public class ExecutionFrame { } } + /** + * Create a new frame for a given project + * + * @param project the project model the frame will deal with + * @return an ExecutionFrame ready to build the project + * @exception ExecutionException if the frame cannot be created. + */ + protected ExecutionFrame createFrame(Project project) + throws ExecutionException { + ExecutionFrame newFrame + = new ExecutionFrame(standardLibs, initConfig, config); + newFrame.setProject(project); + for (Iterator j = eventSupport.getListeners(); j.hasNext(); ) { + BuildListener listener = (BuildListener)j.next(); + newFrame.addBuildListener(listener); + } + return newFrame; + } + + /** + * Log a message as a build event + * + * @param message the message to be logged + * @param level the priority level of the message + */ + protected void log(String message, int level) { + eventSupport.fireMessageLogged(project, message, level); + } + /** * Add a build listener to this execution frame * @@ -533,9 +476,9 @@ public class ExecutionFrame { * @exception ExecutionException if there is a problem in the build */ protected void runBuild(List targets) throws ExecutionException { - System.out.println("Initilizing frame"); + determineBaseDirs(); + initialize(); - log("Initialized", MessageLevel.MSG_DEBUG); if (targets.isEmpty()) { // we just execute the default target if any String defaultTarget = project.getDefaultTarget(); @@ -565,8 +508,8 @@ public class ExecutionFrame { // to execute a target we must determine its dependencies and // execute them in order. - // firstly build a list of fully qualified target names to execute. try { + // firstly build a list of fully qualified target names to execute. List dependencyOrder = project.getTargetDependencies(targetName); for (Iterator i = dependencyOrder.iterator(); i.hasNext(); ) { String fullTargetName = (String)i.next(); @@ -577,6 +520,7 @@ public class ExecutionFrame { } catch (ConfigException e) { throw new ExecutionException(e); } + } /** @@ -593,7 +537,7 @@ public class ExecutionFrame { BuildElement model = (BuildElement)taskIterator.next(); // what sort of element is this. ImportInfo importInfo - = (ImportInfo)definitions.get(model.getType()); + = componentManager.getDefinition(model.getType()); if (importInfo == null) { throw new ExecutionException("There is no definition for the <" + model.getType() + "> element", model.getLocation()); @@ -620,10 +564,7 @@ public class ExecutionFrame { } catch (AntException te) { ExecutionException e = new ExecutionException(te, te.getLocation()); - if (e.getLocation() == null - || e.getLocation() == Location.UNKNOWN_LOCATION) { - e.setLocation(model.getLocation()); - } + e.setLocation(model.getLocation(), false); failureCause = e; throw e; } catch (RuntimeException e) { @@ -653,12 +594,7 @@ public class ExecutionFrame { eventSupport.fireTargetStarted(target); executeTasks(taskIterator); } catch (ExecutionException e) { - System.out.println("Exception location is " + e.getLocation()); - if (e.getLocation() == null - || e.getLocation() == Location.UNKNOWN_LOCATION) { - e.setLocation(target.getLocation()); - } - System.out.println("Exception location is now " + e.getLocation()); + e.setLocation(target.getLocation(), false); failureCause = e; throw e; } catch (RuntimeException e) { @@ -686,28 +622,6 @@ public class ExecutionFrame { } - /** - * Import a complete library into this frame - * - * @param libraryId The id of the library to be imported - * @exception ExecutionException if the library cannot be imported - */ - protected void importLibrary(String libraryId) throws ExecutionException { - AntLibrary library = (AntLibrary)antLibraries.get(libraryId); - if (library == null) { - throw new ExecutionException("Unable to import library " + libraryId - + " as it has not been loaded"); - } - Map libDefs = library.getDefinitions(); - for (Iterator i = libDefs.keySet().iterator(); i.hasNext(); ) { - String defName = (String)i.next(); - AntLibDefinition libdef - = (AntLibDefinition)libDefs.get(defName); - definitions.put(defName, new ImportInfo(library, libdef)); - } - addLibraryConverters(library); - } - /** * Gets the reflector for the given class * @@ -718,7 +632,8 @@ public class ExecutionFrame { if (reflectors.containsKey(c)) { return (Reflector)reflectors.get(c); } - ClassIntrospector introspector = new ClassIntrospector(c, converters); + ClassIntrospector introspector + = new ClassIntrospector(c, componentManager.getConverters()); Reflector reflector = introspector.getReflector(); reflectors.put(c, reflector); return reflector; @@ -755,27 +670,36 @@ public class ExecutionFrame { } /** - * Gets the factory object for the given library + * Determine the base directory for each frame in the frame hierarchy * - * @param antLibrary the library for which the factory instance is - * required. - * @return the library;s factory object - * @exception ExecutionException the factory object for the library - * cannot be created. + * @exception ExecutionException if the base directories cannot be + * determined */ - private AntLibFactory getLibFactory(AntLibrary antLibrary) - throws ExecutionException { - String libraryId = antLibrary.getLibraryId(); - if (libFactories.containsKey(libraryId)) { - return (AntLibFactory)libFactories.get(libraryId); + private void determineBaseDirs() throws ExecutionException { + if (isDataValueSet(BASEDIR_PROP)) { + baseDir = new File(getDataValue(BASEDIR_PROP).toString()); + } else { + URL projectURL = project.getSourceURL(); + if (projectURL.getProtocol().equals("file")) { + File projectFile = new File(projectURL.getFile()); + File projectFileParent = projectFile.getParentFile(); + String base = project.getBase(); + if (base == null) { + baseDir = projectFileParent; + } else { + FileUtils fileUtils = new FileUtils(); + baseDir = fileUtils.resolveFile(projectFileParent, base); + } + } else { + baseDir = new File("."); + } + setDataValue(BASEDIR_PROP, baseDir.getPath(), true); } - AntLibFactory libFactory = antLibrary.getFactory(); - if (libFactory == null) { - libFactory = new StandardLibFactory(); + + for (Iterator i = getReferencedFrames(); i.hasNext(); ) { + ExecutionFrame refFrame = (ExecutionFrame)i.next(); + refFrame.determineBaseDirs(); } - libFactories.put(libraryId, libFactory); - libFactory.init(new ExecutionContext(this, eventSupport)); - return libFactory; } /** @@ -784,71 +708,14 @@ public class ExecutionFrame { */ private void configureServices() { // create services and make them available in our services map - services.put(FileService.class, new ExecutionFileService(this)); - services.put(ComponentService.class, - new ExecutionComponentService(this, config.isRemoteLibAllowed())); + fileService = new ExecutionFileService(this); + componentManager + = new ComponentManager(this, config.isRemoteLibAllowed()); dataService = new ExecutionDataService(this); - services.put(DataService.class, dataService); - } - - /** - * Add the converters from the given library to those managed by this - * frame. - * - * @param library the library from which the converters are required - * @exception ExecutionException if a converter defined in the library - * cannot be instantiated - */ - private void addLibraryConverters(AntLibrary library) - throws ExecutionException { - if (!library.hasConverters()) { - return; - } - String className = null; - try { - AntLibFactory libFactory = getLibFactory(library); - ClassLoader converterLoader = library.getClassLoader(); - for (Iterator i = library.getConverterClassNames(); i.hasNext(); ) { - className = (String)i.next(); - Class converterClass - = Class.forName(className, true, converterLoader); - if (!Converter.class.isAssignableFrom(converterClass)) { - throw new ExecutionException("In Ant library \"" - + library.getLibraryId() + "\" the converter class " - + converterClass.getName() - + " does not implement the Converter interface"); - } - Converter converter - = libFactory.createConverter(converterClass); - ExecutionContext context - = new ExecutionContext(this, eventSupport); - converter.init(context); - Class[] converterTypes = converter.getTypes(); - for (int j = 0; j < converterTypes.length; ++j) { - converters.put(converterTypes[j], converter); - } - } - } catch (ClassNotFoundException e) { - throw new ExecutionException("In Ant library \"" - + library.getLibraryId() + "\" converter class " - + className + " was not found", e); - } catch (NoClassDefFoundError e) { - throw new ExecutionException("In Ant library \"" - + library.getLibraryId() - + "\" could not load a dependent class (" - + e.getMessage() + ") for converter " + className); - } catch (InstantiationException e) { - throw new ExecutionException("In Ant library \"" - + library.getLibraryId() - + "\" unable to instantiate converter class " - + className, e); - } catch (IllegalAccessException e) { - throw new ExecutionException("In Ant library \"" - + library.getLibraryId() - + "\" unable to access converter class " - + className, e); - } + services.put(FileService.class, fileService); + services.put(ComponentService.class, componentManager); + services.put(DataService.class, dataService); } /** @@ -890,7 +757,7 @@ public class ExecutionFrame { BuildElement nestedElementModel = (BuildElement)i.next(); String nestedElementName = nestedElementModel.getType(); - ImportInfo info = (ImportInfo)definitions.get(nestedElementName); + ImportInfo info = componentManager.getDefinition(nestedElementName); if (element instanceof TaskContainer && info != null && info.getDefinitionType() == AntLibrary.TASKDEF @@ -937,18 +804,21 @@ public class ExecutionFrame { String nestedElementName = model.getType(); Object nestedElement = reflector.createElement(element, nestedElementName); - if (nestedElement instanceof ExecutionComponent) { - ExecutionComponent component = (ExecutionComponent)nestedElement; - ExecutionContext context - = new ExecutionContext(this, eventSupport); - context.setModelElement(model); - component.init(context); - } - try { - configureElement(nestedElement, model); + if (nestedElement instanceof ExecutionComponent) { + ExecutionComponent component + = (ExecutionComponent)nestedElement; + ExecutionContext context + = new ExecutionContext(this); + context.setModelElement(model); + component.init(context); + configureElement(nestedElement, model); + component.validateComponent(); + } else { + configureElement(nestedElement, model); + } } catch (ExecutionException e) { - e.setLocation(model.getLocation()); + e.setLocation(model.getLocation(), false); throw e; } } @@ -1045,7 +915,7 @@ public class ExecutionFrame { throws ExecutionException { String taskType = model.getType(); - ImportInfo taskDefInfo = (ImportInfo)definitions.get(taskType); + ImportInfo taskDefInfo = componentManager.getDefinition(taskType); if (taskDefInfo == null || taskDefInfo.getDefinitionType() != AntLibrary.TASKDEF) { throw new ExecutionException("There is no defintion for a " @@ -1059,7 +929,8 @@ public class ExecutionFrame { ClassLoader taskClassLoader = antLibrary.getClassLoader(); Class elementClass = Class.forName(className, true, taskClassLoader); - AntLibFactory libFactory = getLibFactory(antLibrary); + AntLibFactory libFactory + = componentManager.getLibFactory(antLibrary); Object element = libFactory.createTaskInstance(elementClass); Task task = null; @@ -1072,9 +943,10 @@ public class ExecutionFrame { // set the context loader while configuring the element ClassLoader currentLoader = setContextLoader(taskClassLoader); - TaskContext taskContext = new TaskContext(this, eventSupport); + TaskContext taskContext = new TaskContext(this); taskContext.init(taskClassLoader, task, model); configureElement(element, model); + task.validateComponent(); setContextLoader(currentLoader); return taskContext; } catch (ClassNotFoundException e) { @@ -1094,7 +966,7 @@ public class ExecutionFrame { + className + " for task <" + taskType + ">", e, model.getLocation()); } catch (ExecutionException e) { - e.setLocation(model.getLocation()); + e.setLocation(model.getLocation(), false); throw e; } } @@ -1112,7 +984,7 @@ public class ExecutionFrame { */ private Object configureType(String typeName, BuildElement model) throws ExecutionException { - ImportInfo typeDefInfo = (ImportInfo)definitions.get(typeName); + ImportInfo typeDefInfo = componentManager.getDefinition(typeName); if (typeDefInfo == null || typeDefInfo.getDefinitionType() != AntLibrary.TYPEDEF) { throw new ExecutionException("There is no defintion for a " @@ -1128,7 +1000,8 @@ public class ExecutionFrame { = Class.forName(className, true, typeClassLoader); ClassLoader currentLoader = setContextLoader(typeClassLoader); - AntLibFactory libFactory = getLibFactory(antLibrary); + AntLibFactory libFactory + = componentManager.getLibFactory(antLibrary); Object typeInstance = createTypeInstance(typeClass, libFactory, model); setContextLoader(currentLoader); @@ -1169,12 +1042,14 @@ public class ExecutionFrame { if (typeInstance instanceof ExecutionComponent) { ExecutionComponent component = (ExecutionComponent)typeInstance; ExecutionContext context - = new ExecutionContext(this, eventSupport); + = new ExecutionContext(this); context.setModelElement(model); component.init(context); + configureElement(typeInstance, model); + component.validateComponent(); + } else { + configureElement(typeInstance, model); } - - configureElement(typeInstance, model); return typeInstance; } catch (InstantiationException e) { throw new ExecutionException("Unable to instantiate type class " @@ -1185,10 +1060,9 @@ public class ExecutionFrame { + typeClass.getName() + " for type <" + model.getType() + ">", e, model.getLocation()); } catch (ExecutionException e) { - e.setLocation(model.getLocation()); + e.setLocation(model.getLocation(), false); throw e; } } - } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java index 8006d01be..1f4e5aefb 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java @@ -61,10 +61,10 @@ import java.util.Map; import org.apache.ant.antcore.antlib.AntLibManager; import org.apache.ant.antcore.antlib.AntLibrary; import org.apache.ant.antcore.config.AntConfig; -import org.apache.ant.antcore.model.Project; -import org.apache.ant.antcore.util.ConfigException; import org.apache.ant.common.event.BuildListener; +import org.apache.ant.common.model.Project; import org.apache.ant.common.util.AntException; +import org.apache.ant.common.util.ExecutionException; import org.apache.ant.init.InitConfig; /** @@ -105,11 +105,11 @@ public class ExecutionManager { * * @param initConfig Ant's configuration - classloaders etc * @param config The user config to use - may be null - * @exception ConfigException if there is a problem with one of Ant's + * @exception ExecutionException if there is a problem with one of Ant's * tasks */ public ExecutionManager(InitConfig initConfig, AntConfig config) - throws ConfigException { + throws ExecutionException { this.config = config; this.initConfig = initConfig; @@ -140,7 +140,7 @@ public class ExecutionManager { mainFrame = new ExecutionFrame(antLibraries, initConfig, config); } catch (MalformedURLException e) { - throw new ConfigException("Unable to load Ant libraries", e); + throw new ExecutionException("Unable to load Ant libraries", e); } } @@ -149,13 +149,17 @@ public class ExecutionManager { * * @param project the project model to be used for the build * @param targets a list of target names to be executed. + * @param commandProperties the properties defined by the front end to + * control the build */ - public void runBuild(Project project, List targets) { + public void runBuild(Project project, List targets, Map commandProperties) { Throwable buildFailureCause = null; try { // start by validating the project we have been given. - project.validate(null); + project.validate(); + mainFrame.setProject(project); + mainFrame.setInitialProperties(commandProperties); eventSupport.fireBuildStarted(project); mainFrame.runBuild(targets); @@ -193,10 +197,10 @@ public class ExecutionManager { * Add the library paths from the AntConfig instance to the Ant * Libraries. * - * @exception ConfigException if remote libraries are not allowed. + * @exception ExecutionException if remote libraries are not allowed. */ private void addConfigLibPaths() - throws ConfigException { + throws ExecutionException { if (config == null) { return; } @@ -212,7 +216,7 @@ public class ExecutionManager { URL pathElementURL = (URL)j.next(); if (!pathElementURL.getProtocol().equals("file") && !config.isRemoteLibAllowed()) { - throw new ConfigException("Remote libpaths are not" + throw new ExecutionException("Remote libpaths are not" + " allowed: " + pathElementURL); } antLib.addLibraryURL(pathElementURL); diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ImportInfo.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ImportInfo.java new file mode 100644 index 000000000..00c7c86f2 --- /dev/null +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ImportInfo.java @@ -0,0 +1,110 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antcore.execution; + +import org.apache.ant.antcore.antlib.AntLibDefinition; +import org.apache.ant.antcore.antlib.AntLibrary; + +/** + * This class is used to maintain information about imports + * + * @author Conor MacNeill + * @created 16 January 2002 + */ +public class ImportInfo { + /** the ant library from which the import is made */ + private AntLibrary library; + /** the library definition information */ + private AntLibDefinition libDefinition; + + /** + * ImportInfo records what has been imported from an Ant Library + * + * @param library The library from which the import was made + * @param libDefinition the library definition information + */ + public ImportInfo(AntLibrary library, AntLibDefinition libDefinition) { + this.library = library; + this.libDefinition = libDefinition; + } + + /** + * Get the classname that has been imported + * + * @return the classname that was imported. + */ + public String getClassName() { + return libDefinition.getClassName(); + } + + /** + * Get the library from which the import was made + * + * @return the library from which the import was made + */ + public AntLibrary getAntLibrary() { + return library; + } + + /** + * Get the type of the definition that was imported + * + * @return the type of definition + */ + public int getDefinitionType() { + return libDefinition.getDefinitionType(); + } + +} + diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java index 331299167..50c1c58d6 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java @@ -52,8 +52,8 @@ * . */ package org.apache.ant.antcore.execution; -import org.apache.ant.antcore.model.ModelElement; import org.apache.ant.common.antlib.Task; +import org.apache.ant.common.model.ModelElement; import org.apache.ant.common.util.ExecutionException; /** * This is the core's implementation of the AntContext for Tasks. @@ -77,12 +77,9 @@ public class TaskContext extends ExecutionContext { * Initilaise this context's environment * * @param frame the frame containing this context - * @param eventSupport the event support instance used to send build - * events */ - public TaskContext(ExecutionFrame frame, - BuildEventSupport eventSupport) { - super(frame, eventSupport); + public TaskContext(ExecutionFrame frame) { + super(frame); } /** @@ -109,7 +106,7 @@ public class TaskContext extends ExecutionContext { * @param task the task to be manager * @param loader the classloader * @param modelElement the model element associated with this context - * @exception ExecutionException if the task cannot be initialized + * @exception ExecutionException if the task cannot be initialized */ public void init(ClassLoader loader, Task task, ModelElement modelElement) throws ExecutionException { @@ -122,7 +119,8 @@ public class TaskContext extends ExecutionContext { /** * execute this context's task * - * @exception ExecutionException if there is a problem executing the task + * @exception ExecutionException if there is a problem executing the + * task */ public void execute() throws ExecutionException { task.execute(); diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/BuildElementHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/BuildElementHandler.java similarity index 98% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/BuildElementHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/BuildElementHandler.java index 077e6b9d5..b968640a2 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/BuildElementHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/BuildElementHandler.java @@ -51,10 +51,10 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model.xmlparser; +package org.apache.ant.antcore.modelparser; import java.util.Iterator; -import org.apache.ant.antcore.model.BuildElement; +import org.apache.ant.common.model.BuildElement; import org.apache.ant.antcore.xml.ElementHandler; import org.xml.sax.Attributes; import org.xml.sax.SAXParseException; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/IncludeHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/IncludeHandler.java similarity index 98% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/IncludeHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/IncludeHandler.java index 353359d48..453a78b3c 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/IncludeHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/IncludeHandler.java @@ -51,11 +51,11 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model.xmlparser; +package org.apache.ant.antcore.modelparser; import java.net.MalformedURLException; import java.net.URL; -import org.apache.ant.antcore.model.Project; +import org.apache.ant.common.model.Project; import org.apache.ant.antcore.xml.ElementHandler; import org.apache.ant.antcore.xml.XMLParseException; import org.xml.sax.SAXParseException; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/NoProjectReadException.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/NoProjectReadException.java similarity index 98% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/NoProjectReadException.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/NoProjectReadException.java index 0b9e22c6d..770ba83fb 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/NoProjectReadException.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/NoProjectReadException.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model.xmlparser; +package org.apache.ant.antcore.modelparser; /** * A NoProjectReadException is used to indicate that a project was not read diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/ProjectHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java similarity index 98% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/ProjectHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java index a73f8ded8..4fbbc7e24 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/ProjectHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java @@ -51,9 +51,9 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model.xmlparser; -import org.apache.ant.antcore.model.ModelException; -import org.apache.ant.antcore.model.Project; +package org.apache.ant.antcore.modelparser; +import org.apache.ant.common.model.ModelException; +import org.apache.ant.common.model.Project; import org.apache.ant.antcore.xml.ElementHandler; import org.xml.sax.Attributes; import org.xml.sax.SAXParseException; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/RefHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/RefHandler.java similarity index 96% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/RefHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/RefHandler.java index 197f3a7c9..a2100c6bd 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/RefHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/RefHandler.java @@ -51,11 +51,11 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model.xmlparser; +package org.apache.ant.antcore.modelparser; import java.net.MalformedURLException; import java.net.URL; -import org.apache.ant.antcore.model.Project; +import org.apache.ant.common.model.Project; import org.apache.ant.antcore.xml.ElementHandler; import org.apache.ant.antcore.xml.XMLParseException; import org.xml.sax.SAXParseException; @@ -129,14 +129,14 @@ public class RefHandler extends ElementHandler { referencedProject = referencedProjectHandler.getProject(); } catch (XMLParseException e) { throw new SAXParseException("Error parsing referenced project " - + projectSystemId + ": " + e.getMessage(), getLocator()); + + projectSystemId + ": " + e.getMessage(), getLocator(), e); } catch (NoProjectReadException e) { throw new SAXParseException("No project found in the reference: " - + projectSystemId, getLocator()); + + projectSystemId, getLocator(), e); } catch (MalformedURLException e) { throw new SAXParseException("Unable to reference project " + projectSystemId + ": " + e.getMessage(), - getLocator()); + getLocator(), e); } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/TargetHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/TargetHandler.java similarity index 90% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/TargetHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/TargetHandler.java index 5c1c40cf2..8ee9efd3c 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/TargetHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/TargetHandler.java @@ -51,10 +51,10 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model.xmlparser; +package org.apache.ant.antcore.modelparser; import java.util.StringTokenizer; -import org.apache.ant.antcore.model.Target; +import org.apache.ant.common.model.Target; import org.apache.ant.antcore.xml.ElementHandler; import org.xml.sax.Attributes; import org.xml.sax.SAXParseException; @@ -75,6 +75,12 @@ public class TargetHandler extends ElementHandler { /** The depends attribute name */ public final static String DESC_ATTR = "description"; + /** The if attribute name */ + public final static String IF_ATTR = "if"; + + /** The unless attribute name */ + public final static String UNLESS_ATTR = "unless"; + /** The target being configured. */ private Target target; @@ -105,7 +111,7 @@ public class TargetHandler extends ElementHandler { if (depends != null) { StringTokenizer tokenizer = new StringTokenizer(depends, ","); while (tokenizer.hasMoreTokens()) { - String dependency = tokenizer.nextToken(); + String dependency = tokenizer.nextToken().trim(); target.addDependency(dependency); } } @@ -143,9 +149,11 @@ public class TargetHandler extends ElementHandler { protected void validateAttribute(String attributeName, String attributeValue) throws SAXParseException { - if (!attributeName.equals(NAME_ATTR) && - !attributeName.equals(DEPENDS_ATTR) && - !attributeName.equals(DESC_ATTR)) { + if (!attributeName.equals(NAME_ATTR) + && !attributeName.equals(DEPENDS_ATTR) + && !attributeName.equals(DESC_ATTR) + && !attributeName.equals(IF_ATTR) + && !attributeName.equals(UNLESS_ATTR)) { throwInvalidAttribute(attributeName); } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/XMLProjectParser.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/XMLProjectParser.java similarity index 97% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/XMLProjectParser.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/XMLProjectParser.java index 911d654f0..a3d7c7b30 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/XMLProjectParser.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/XMLProjectParser.java @@ -51,11 +51,11 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model.xmlparser; +package org.apache.ant.antcore.modelparser; import java.net.URL; import org.apache.ant.common.util.Location; -import org.apache.ant.antcore.model.Project; +import org.apache.ant.common.model.Project; import org.apache.ant.antcore.xml.ParseContext; import org.apache.ant.antcore.xml.XMLParseException; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ParseContext.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ParseContext.java index 8fd28c5bc..eda682eb4 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ParseContext.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ParseContext.java @@ -59,8 +59,9 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.ant.common.util.Location; -import org.apache.ant.antcore.util.CircularDependencyChecker; -import org.apache.ant.antcore.util.CircularDependencyException; +import org.apache.ant.common.util.CircularDependencyChecker; +import org.apache.ant.common.util.CircularDependencyException; +import org.apache.ant.common.util.AntException; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; @@ -128,7 +129,11 @@ public class ParseContext { Location location = new Location(e.getSystemId(), e.getLineNumber(), e.getColumnNumber()); if (e.getException() != null) { - throw new XMLParseException(e.getException(), location); + Throwable nestedException = e.getException(); + if (nestedException instanceof AntException) { + location = ((AntException)nestedException).getLocation(); + } + throw new XMLParseException(nestedException, location); } else { throw new XMLParseException(e, location); } diff --git a/proposal/mutant/src/java/antlibs/ant1compat/antlib.xml b/proposal/mutant/src/java/antlibs/ant1compat/antlib.xml index fd2bed73b..46a38f4b8 100644 --- a/proposal/mutant/src/java/antlibs/ant1compat/antlib.xml +++ b/proposal/mutant/src/java/antlibs/ant1compat/antlib.xml @@ -4,20 +4,149 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/AntClassLoader.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/AntClassLoader.java index 53298a28f..b3e23f3ac 100644 --- a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/AntClassLoader.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/AntClassLoader.java @@ -136,7 +136,7 @@ public class AntClassLoader extends URLClassLoader /** * Initialize the given class * - * @param theClass XXX Description of Parameter + * @param theClass the class to be initialised */ public static void initializeClass(Class theClass) { // do nothing in Ant2 @@ -188,14 +188,6 @@ public class AntClassLoader extends URLClassLoader public void cleanup() { } - /** - * New build listener interface - * - * @param be the build event to be processed - */ - public void processBuildEvent(BuildEvent be) { - } - /** * Force a class to be loaded by this loader * @@ -219,7 +211,64 @@ public class AntClassLoader extends URLClassLoader } /** - * Add a path tot his loader + * build started event + * + * @param event build started event + */ + public void buildStarted(BuildEvent event) { + } + + /** + * build finished event + * + * @param event build finished event + */ + public void buildFinished(BuildEvent event) { + cleanup(); + } + + /** + * target started event. + * + * @param event target started event. + */ + public void targetStarted(BuildEvent event) { + } + + /** + * target finished event + * + * @param event target finished event + */ + public void targetFinished(BuildEvent event) { + } + + /** + * task started event + * + * @param event task started event + */ + public void taskStarted(BuildEvent event) { + } + + /** + * task finished event + * + * @param event task finished event + */ + public void taskFinished(BuildEvent event) { + } + + /** + * message logged event + * + * @param event message logged event + */ + public void messageLogged(BuildEvent event) { + } + + /** + * Add a path to this loader * * @param path the path to be added to this loader */ diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildEvent.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildEvent.java index 699e22a8b..745ab6bc2 100644 --- a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildEvent.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildEvent.java @@ -66,7 +66,7 @@ public class BuildEvent extends org.apache.ant.common.event.BuildEvent { * @param task the task that emitted the event. */ public BuildEvent(Task task) { - super(task, MESSAGE); + super(task.getContext().getModelElement(), MESSAGE); } } diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java index 621df2769..3e3ed5824 100644 --- a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java @@ -629,7 +629,7 @@ public class Project { public Hashtable getProperties() { Map properties = dataService.getAllProperties(); Hashtable result = new Hashtable(); - for (Iterator i = properties.keySet().iterator(); i.hasNext();) { + for (Iterator i = properties.keySet().iterator(); i.hasNext(); ) { String name = (String)i.next(); Object value = properties.get(name); if (value instanceof String) { @@ -655,7 +655,7 @@ public class Project { public Hashtable getReferences() { Map properties = dataService.getAllProperties(); Hashtable result = new Hashtable(); - for (Iterator i = properties.keySet().iterator(); i.hasNext();) { + for (Iterator i = properties.keySet().iterator(); i.hasNext(); ) { String name = (String)i.next(); Object value = properties.get(name); if (!(value instanceof String)) { diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectComponent.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectComponent.java index cbfbefaa3..c30671e27 100644 --- a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectComponent.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectComponent.java @@ -117,7 +117,7 @@ public abstract class ProjectComponent { public void init(AntContext context) throws ExecutionException { this.context = context; org.apache.ant.common.util.Location contextLocation - = context.getLocation(); + = context.getModelElement().getLocation(); if (contextLocation == org.apache.ant.common.util.Location.UNKNOWN_LOCATION) { @@ -153,5 +153,14 @@ public abstract class ProjectComponent { context.log(message, Project.MSG_INFO); } + + /** + * Get the context associated with this component + * + * @return the AntContext + */ + protected AntContext getContext() { + return context; + } } diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java index 284949b68..c2fa2ed1f 100644 --- a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java @@ -121,12 +121,18 @@ public abstract class Task extends ProjectComponent /** * Gets the description of the Task * - * @return the task's description + * @return the task's description */ public String getDescription() { return description; } + + /** Validate this component */ + public void validateComponent() { + // no default validation for Ant1 tasks + } + /** * Handle output captured for this task * @@ -153,6 +159,5 @@ public abstract class Task extends ProjectComponent void setTaskType(String type) { this.taskType = type; } - } diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/types/DataType.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/types/DataType.java index 9815b0356..7c276f764 100644 --- a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/types/DataType.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/types/DataType.java @@ -132,6 +132,12 @@ public abstract class DataType extends ProjectComponent return ref != null; } + /** Validate this component */ + public void validateComponent() { + // no default validation for Ant1 types + } + + /** * Performs the check for circular references and returns the referenced * object. diff --git a/proposal/mutant/src/java/antlibs/system/antlib.xml b/proposal/mutant/src/java/antlibs/system/antlib.xml index 8cac5324f..a26812c14 100644 --- a/proposal/mutant/src/java/antlibs/system/antlib.xml +++ b/proposal/mutant/src/java/antlibs/system/antlib.xml @@ -7,6 +7,9 @@ + + + diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionComponentService.java b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Ant.java similarity index 55% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionComponentService.java rename to proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Ant.java index 14b0d9db8..5a0739ef1 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionComponentService.java +++ b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Ant.java @@ -51,73 +51,69 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.execution; -import java.net.MalformedURLException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import org.apache.ant.antcore.antlib.AntLibManager; -import org.apache.ant.antcore.util.ConfigException; +package org.apache.ant.antlib.system; +import java.io.File; import org.apache.ant.common.service.ComponentService; import org.apache.ant.common.util.ExecutionException; /** - * The instance of the ComponentServices made available by the core to the - * ant libraries. + * The Ant task - used to execute a different build file * * @author Conor MacNeill - * @created 27 January 2002 + * @created 4 February 2002 */ -public class ExecutionComponentService implements ComponentService { - /** The ExecutionFrame this service instance is working for */ - private ExecutionFrame frame; +public class Ant extends AntBase { + /** The ant file to be run */ + private File antFile; + /** the base directory to use for the run */ + private File baseDir; + /** File to capture any output */ + private File outputFile; - /** The library manager instance used to configure libraries. */ - private AntLibManager libManager; + /** + * sets the file containing the XML representation model to build + * + * @param antFile the file to build + */ + public void setAntFile(File antFile) { + this.antFile = antFile; + } /** - * Constructor + * Set the base directory for the execution of the build * - * @param executionFrame the frame containing this context - * @param allowRemoteLibs true if remote libraries can be loaded though - * this service. + * @param baseDir the base directory for the build */ - public ExecutionComponentService(ExecutionFrame executionFrame, - boolean allowRemoteLibs) { - this.frame = executionFrame; - libManager = new AntLibManager(allowRemoteLibs); + public void setBaseDir(File baseDir) { + this.baseDir = baseDir; } /** - * Load a library or set of libraries from a location making them - * available for use + * The output file for capturing the build output * - * @param libLocation the file or URL of the library location - * @param importAll if true all tasks are imported as the library is - * loaded - * @exception ExecutionException if the library cannot be loaded + * @param outputFile the output file for capturing the build output */ - public void loadLib(String libLocation, boolean importAll) - throws ExecutionException { - try { - Map librarySpecs = new HashMap(); - libManager.loadLib(librarySpecs, libLocation); - libManager.configLibraries(frame.getInitConfig(), librarySpecs, - frame.getAntLibraries()); + public void setOutput(File outputFile) { + this.outputFile = outputFile; + } - if (importAll) { - Iterator i = librarySpecs.keySet().iterator(); - while (i.hasNext()) { - String libraryId = (String)i.next(); - frame.importLibrary(libraryId); - } - } - } catch (MalformedURLException e) { - throw new ExecutionException("Unable to load libraries from " - + libLocation, e); - } catch (ConfigException e) { - throw new ExecutionException(e); + /** + * Run the sub-build + * + * @exception ExecutionException if the build can't be run + */ + public void execute() throws ExecutionException { + if (baseDir == null) { + baseDir = getContext().getBaseDir(); + } + if (antFile == null) { + antFile = new File(baseDir, "build.ant"); } + + ComponentService componentService + = (ComponentService)getCoreService(ComponentService.class); + + componentService.runBuild(antFile, getProperties(), getTargets()); } } diff --git a/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/AntBase.java b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/AntBase.java new file mode 100644 index 000000000..524a44d02 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/AntBase.java @@ -0,0 +1,293 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antlib.system; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.ant.common.antlib.AbstractTask; +import org.apache.ant.common.antlib.AntContext; +import org.apache.ant.common.antlib.AbstractComponent; +import org.apache.ant.common.service.DataService; +import org.apache.ant.common.util.ExecutionException; + +/** + * Common Base class for the Ant and AntCall tasks + * + * @author Conor MacNeill + * @created 4 February 2002 + */ +public abstract class AntBase extends AbstractTask { + + /** + * Simple Property value storing class + * + * @author Conor MacNeill + * @created 5 February 2002 + */ + public static class Property extends AbstractComponent { + /** The property name */ + private String name; + + /** The property value*/ + private String value; + + + /** + * Sets the name of the Property + * + * @param name the new name value + */ + public void setName(String name) { + this.name = name; + } + + /** + * Sets the value of the Property + * + * @param value the new value value + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Gets the name of the Property + * + * @return the name value + */ + public String getName() { + return name; + } + + /** + * Gets the value of the Property + * + * @return the value value + */ + public String getValue() { + return value; + } + + public void validateComponent() throws ExecutionException { + if (name == null) { + throw new ExecutionException("\"name\" attribute of must be supplied"); + } + if (value == null) { + throw new ExecutionException("\"value\" attribute of must be supplied"); + } + } + } + + /** + * A simple class to store information about references being passed + * + * @author Conor MacNeill + * @created 5 February 2002 + */ + public static class Reference extends AbstractComponent { + /** The id of the reference to be passed */ + private String refId; + /** The id to be used in the sub-build for this reference */ + private String toId; + + /** + * Sets the refId of the Reference + * + * @param refId the new refId value + */ + public void setRefId(String refId) { + this.refId = refId; + } + + /** + * Sets the toId of the Reference + * + * @param toId the new toId value + */ + public void setToId(String toId) { + this.toId = toId; + } + + /** + * Gets the refId of the Reference + * + * @return the refId value + */ + public String getRefId() { + return refId; + } + + /** + * Gets the toId of the Reference + * + * @return the toId value + */ + public String getToId() { + return toId; + } + + public void validateComponent() throws ExecutionException { + if (refId == null) { + throw new ExecutionException("\"refid\" attribute of must be supplied"); + } + } + } + + /** The name of the target to be evaluated in the sub-build */ + private String targetName; + + /** flag which indicates if all current properties should be passed to the subbuild */ + private boolean inheritAll = true; + + /** flag which indicates if all current references should be passed to the subbuild */ + private boolean inheritRefs = false; + + /** The properties which will be passed to the sub-build */ + private Map properties = new HashMap(); + + /** The core's data service for manipulating the properties */ + private DataService dataService; + + /** + * Sets the target to be executed in the subbuild + * + * @param targetName the name of the target to build + */ + public void setTarget(String targetName) { + this.targetName = targetName; + } + + /** + * Indicate if all properties should be passed + * + * @param inheritAll true if all properties should be passed + */ + public void setInheritAll(boolean inheritAll) { + this.inheritAll = inheritAll; + } + + /** + * Indicate if all references are to be passed to the subbuild + * + * @param inheritRefs true if the sub-build should be given all the current references + */ + public void setInheritRefs(boolean inheritRefs) { + this.inheritRefs = inheritRefs; + } + + /** + * Initialise this task + * + * @param context core's context + * @exception ExecutionException if we can't access the data service + */ + public void init(AntContext context) throws ExecutionException { + super.init(context); + dataService = (DataService)getCoreService(DataService.class); + } + + /** + * Add a property to be passed to the subbuild + * + * @param property descriptor for the property to be passed + */ + public void addProperty(Property property) { + properties.put(property.getName(), property.getValue()); + } + + /** + * Add a reference to be passed + * + * @param reference the descriptor of the reference to be passed + * @exception ExecutionException if the reference does not reference a valid object + */ + public void addReference(Reference reference) throws ExecutionException { + String refId = reference.getRefId(); + if (!dataService.isDataValueSet(refId)) { + throw new ExecutionException("RefId \"" + refId + "\" is not set"); + } + Object value = dataService.getDataValue(refId); + String toId = reference.getToId(); + if (toId == null) { + toId = refId; + } + + properties.put(toId, value); + } + + /** + * Get the list of targets to be executed + * + * @return A List of string target names. + */ + protected List getTargets() { + List targets = new ArrayList(); + if (targetName != null) { + targets.add(targetName); + } + return targets; + } + + /** + * Get the properties to be used with the sub-build + * + * @return the properties the sub-build will start with + */ + protected Map getProperties() { + return properties; + } + +} + diff --git a/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/AntCall.java b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/AntCall.java new file mode 100644 index 000000000..0df3fbd29 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/AntCall.java @@ -0,0 +1,87 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antlib.system; +import org.apache.ant.common.service.ComponentService; +import org.apache.ant.common.util.ExecutionException; + +/** + * The Ant task - used to execute a different build file + * + * @author Conor MacNeill + * @created 4 February 2002 + */ +public class AntCall extends AntBase { + /** + * Execute the sub-build + * + * @exception ExecutionException if the build fails + */ + public void execute() throws ExecutionException { + ComponentService componentService + = (ComponentService)getCoreService(ComponentService.class); + + componentService.callTarget(getProperties(), getTargets()); + } + + /** + * Alias to add a property to the sub-build + * + * @param param descriptor for the property to be passed + */ + public void addParam(Property param) { + super.addProperty(param); + } + +} + diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java index 6f762e350..c77291c24 100755 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java +++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java @@ -60,18 +60,20 @@ import java.io.PrintStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import org.apache.ant.antcore.config.AntConfig; import org.apache.ant.antcore.config.AntConfigHandler; import org.apache.ant.antcore.execution.ExecutionManager; -import org.apache.ant.antcore.model.Project; -import org.apache.ant.antcore.model.xmlparser.XMLProjectParser; -import org.apache.ant.antcore.util.ConfigException; +import org.apache.ant.antcore.modelparser.XMLProjectParser; import org.apache.ant.antcore.xml.ParseContext; import org.apache.ant.antcore.xml.XMLParseException; import org.apache.ant.common.event.BuildListener; +import org.apache.ant.common.model.Project; import org.apache.ant.common.util.AntException; +import org.apache.ant.common.util.ConfigException; import org.apache.ant.common.util.Location; import org.apache.ant.common.util.MessageLevel; import org.apache.ant.init.InitConfig; @@ -87,6 +89,9 @@ public class Commandline { /** The default build file name */ public final static String DEFAULT_BUILD_FILENAME = "build.ant"; + /** The default build file name */ + public final static String DEFAULT_ANT1_FILENAME = "build.xml"; + /** The initialisation configuration for Ant */ private InitConfig config; @@ -102,6 +107,9 @@ public class Commandline { /** The list of targets to be evaluated in this invocation */ private List targets = new ArrayList(4); + /** The command line properties */ + private Map definedProperties = new HashMap(); + /** * This is the build file to run. By default it is a file: type URL but * other URL protocols can be used. @@ -237,7 +245,7 @@ public class Commandline { ExecutionManager executionManager = new ExecutionManager(initConfig, config); addBuildListeners(executionManager); - executionManager.runBuild(project, targets); + executionManager.runBuild(project, targets, definedProperties); } catch (Throwable t) { if (t instanceof AntException) { AntException e = (AntException)t; @@ -329,6 +337,9 @@ public class Commandline { } else if (arg.equals("-verbose") || arg.equals("-v")) { // printVersion(); messageOutputLevel = MessageLevel.MSG_VERBOSE; + } else if (arg.equals("-debug")) { + // printVersion(); + messageOutputLevel = MessageLevel.MSG_DEBUG; } else if (arg.equals("-listener")) { try { listeners.add(args[i++]); @@ -350,6 +361,17 @@ public class Commandline { "using the -logger argument"); return; } + } else if (arg.startsWith("-D")) { + String name = arg.substring(2, arg.length()); + String value = null; + int posEq = name.indexOf("="); + if (posEq > 0) { + value = name.substring(posEq + 1); + name = name.substring(0, posEq); + } else if (i < args.length - 1) { + value = args[++i]; + } + definedProperties.put(name, value); } else if (arg.startsWith("-")) { // we don't have any more args to recognize! System.out.println("Unknown option: " + arg); @@ -362,6 +384,12 @@ public class Commandline { if (buildFileURL == null) { File defaultBuildFile = new File(DEFAULT_BUILD_FILENAME); + if (!defaultBuildFile.exists()) { + File ant1BuildFile = new File(DEFAULT_ANT1_FILENAME); + if (ant1BuildFile.exists()) { + defaultBuildFile = ant1BuildFile; + } + } try { buildFileURL = InitUtils.getFileURL(defaultBuildFile); } catch (MalformedURLException e) { diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java index c3bc61f8f..31ab9c56b 100755 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java +++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java @@ -1,125 +1,103 @@ /* - * The Apache Software License, Version 1.1 + * The Apache Software License, Version 1.1 * - * Copyright (c) 2002 The Apache Software Foundation. All rights - * reserved. + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. * - * 3. The end-user documentation included with the redistribution, if - * any, must include the following acknowlegement: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowlegement may appear in the software itself, - * if and wherever such third-party acknowlegements normally appear. + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. * - * 4. The names "The Jakarta Project", "Ant", and "Apache Software - * Foundation" must not be used to endorse or promote products derived - * from this software without prior written permission. For written - * permission, please contact apache@apache.org. + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. * - * 5. Products derived from this software may not be called "Apache" - * nor may "Apache" appear in their names without prior written - * permission of the Apache Group. + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . */ package org.apache.ant.cli; import java.io.PrintStream; +import org.apache.ant.common.model.BuildElement; +import org.apache.ant.common.model.Target; +import org.apache.ant.common.event.BuildEvent; import org.apache.ant.common.util.AntException; import org.apache.ant.common.util.Location; import org.apache.ant.common.util.MessageLevel; -import org.apache.ant.common.event.BuildEvent; -import org.apache.ant.antcore.model.BuildElement; -import org.apache.ant.antcore.model.Target; /** - * Writes build event to a PrintStream. Currently, it only writes which - * targets are being executed, and any messages that get logged. + * Writes build event to a PrintStream. Currently, it only writes which + * targets are being executed, and any messages that get logged. * - * @author Conor MacNeill - * @created 15 January 2002 + * @author Conor MacNeill + * @created 15 January 2002 */ public class DefaultLogger implements BuildLogger { - /** Standard field separator */ - private static String lSep = System.getProperty("line.separator"); - /** spacing to allow for task tags */ - private final static int LEFT_COLUMN_SIZE = 12; - - /** The stream where output should be written */ + /** The stream where output should be written */ private PrintStream out; - /** The stream to where errors should be written */ + /** The stream to where errors should be written */ private PrintStream err; - /** The level of messages which should be let through */ + /** The level of messages which should be let through */ private int messageOutputLevel = MessageLevel.MSG_ERR; - /** Controls whether adornments are added */ + /** Controls whether adornments are added */ private boolean emacsMode = false; - /** The time at which the build started */ + /** The time at which the build started */ private long startTime = System.currentTimeMillis(); - /** - * Format the time into something readable - * - * @param millis Java millis value - * @return the formatted time - */ - protected static String formatTime(long millis) { - long seconds = millis / 1000; - long minutes = seconds / 60; - - if (minutes > 0) { - return Long.toString(minutes) + " minute" - + (minutes == 1 ? " " : "s ") - + Long.toString(seconds % 60) + " second" - + (seconds % 60 == 1 ? "" : "s"); - } else { - return Long.toString(seconds) + " second" - + (seconds % 60 == 1 ? "" : "s"); - } - - } + /** Standard field separator */ + private static String lSep = System.getProperty("line.separator"); + /** spacing to allow for task tags */ + private final static int LEFT_COLUMN_SIZE = 12; /** - * Set the messageOutputLevel this logger is to respond to. Only - * messages with a message level lower than or equal to the given level - * are output to the log.

+ * Set the messageOutputLevel this logger is to respond to. Only + * messages with a message level lower than or equal to the given level + * are output to the log.

* - * Constants for the message levels are in Project.java. The order of - * the levels, from least to most verbose, is MSG_ERR, MSG_WARN, - * MSG_INFO, MSG_VERBOSE, MSG_DEBUG. The default message level for - * DefaultLogger is Project.MSG_ERR. + * Constants for the message levels are in Project.java. The order of + * the levels, from least to most verbose, is MSG_ERR, MSG_WARN, + * MSG_INFO, MSG_VERBOSE, MSG_DEBUG. The default message level for + * DefaultLogger is Project.MSG_ERR. * - * @param level the logging level for the logger. + * @param level the logging level for the logger. */ public void setMessageOutputLevel(int level) { this.messageOutputLevel = level; @@ -127,27 +105,28 @@ public class DefaultLogger implements BuildLogger { /** - * Set the output stream to which this logger is to send its output. + * Set the output stream to which this logger is to send its output. * - * @param output the output stream for the logger. + * @param output the output stream for the logger. */ public void setOutputPrintStream(PrintStream output) { this.out = output; } /** - * Set the output stream to which this logger is to send error messages. + * Set the output stream to which this logger is to send error + * messages. * - * @param err the error stream for the logger. + * @param err the error stream for the logger. */ public void setErrorPrintStream(PrintStream err) { this.err = err; } /** - * Set this logger to produce emacs (and other editor) friendly output. + * Set this logger to produce emacs (and other editor) friendly output. * - * @param emacsMode true if output is to be unadorned so that emacs and + * @param emacsMode true if output is to be unadorned so that emacs and * other editors can parse files names, etc. */ public void setEmacsMode(boolean emacsMode) { @@ -155,9 +134,9 @@ public class DefaultLogger implements BuildLogger { } /** - * Report an exception + * Report an exception * - * @param t The exception to be reported. + * @param t The exception to be reported. */ public void reportException(Throwable t) { if (t instanceof AntException) { @@ -182,72 +161,121 @@ public class DefaultLogger implements BuildLogger { } /** - * Process an incoming build event + * Description of the Method * - * @param event the build event to be processed + * @param event Description of Parameter */ - public void processBuildEvent(BuildEvent event) { - switch (event.getEventType()) { - case BuildEvent.BUILD_STARTED: - startTime = System.currentTimeMillis(); - break; - case BuildEvent.BUILD_FINISHED: - Throwable cause = event.getCause(); - - if (cause == null) { - out.println(lSep + "BUILD SUCCESSFUL"); - } else { - err.println(lSep + "BUILD FAILED" + lSep); - - reportException(cause); - } + public void buildStarted(BuildEvent event) { + startTime = System.currentTimeMillis(); + } - out.println(lSep + "Total time: " - + formatTime(System.currentTimeMillis() - startTime)); - break; - case BuildEvent.TARGET_STARTED: - if (MessageLevel.MSG_INFO <= messageOutputLevel) { - Target target = (Target)event.getSource(); - out.println(lSep + target.getName() + ":"); - } - break; - case BuildEvent.TARGET_FINISHED: - break; - case BuildEvent.TASK_STARTED: - break; - case BuildEvent.TASK_FINISHED: - break; - case BuildEvent.MESSAGE: - PrintStream logTo - = event.getPriority() == MessageLevel.MSG_ERR ? err : out; - - // Filter out messages based on priority - if (event.getPriority() <= messageOutputLevel - && event.getSource() instanceof BuildElement) { - // Print out the name of the task if we're in one - BuildElement buildElement - = (BuildElement)event.getSource(); - String name = buildElement.getType(); - - if (!emacsMode) { - String msg = "[" + name + "] "; - int indentSize = LEFT_COLUMN_SIZE - msg.length(); - for (int i = 0; i < indentSize; i++) { - logTo.print(" "); - } - logTo.print(msg); - } - - // Print the message - logTo.println(event.getMessage()); + /** + * Description of the Method + * + * @param event Description of Parameter + */ + public void buildFinished(BuildEvent event) { + Throwable cause = event.getCause(); + + if (cause == null) { + out.println(lSep + "BUILD SUCCESSFUL"); + } else { + err.println(lSep + "BUILD FAILED" + lSep); + + reportException(cause); + } + + out.println(lSep + "Total time: " + + formatTime(System.currentTimeMillis() - startTime)); + } + + /** + * Description of the Method + * + * @param event Description of Parameter + */ + public void targetStarted(BuildEvent event) { + if (MessageLevel.MSG_INFO <= messageOutputLevel) { + Target target = (Target)event.getSource(); + out.println(lSep + target.getName() + ":"); + } + } + + /** + * Description of the Method + * + * @param event Description of Parameter + */ + public void targetFinished(BuildEvent event) { + } + + /** + * Description of the Method + * + * @param event Description of Parameter + */ + public void taskStarted(BuildEvent event) { + } + + /** + * Description of the Method + * + * @param event Description of Parameter + */ + public void taskFinished(BuildEvent event) { + } + + /** + * Description of the Method + * + * @param event Description of Parameter + */ + public void messageLogged(BuildEvent event) { + PrintStream logTo + = event.getPriority() == MessageLevel.MSG_ERR ? err : out; + + // Filter out messages based on priority + if (event.getPriority() <= messageOutputLevel + && event.getModelElement() instanceof BuildElement) { + // Print out the name of the task if we're in one + BuildElement buildElement + = (BuildElement)event.getModelElement(); + String name = buildElement.getType(); + + if (!emacsMode) { + String msg = "[" + name + "] "; + int indentSize = LEFT_COLUMN_SIZE - msg.length(); + for (int i = 0; i < indentSize; i++) { + logTo.print(" "); } - break; - default: - err.println("Unrecognized event type = " + - event.getEventType()); - break; + logTo.print(msg); + } + + // Print the message + logTo.println(event.getMessage()); } } + /** + * Format the time into something readable + * + * @param millis Java millis value + * @return the formatted time + */ + protected static String formatTime(long millis) { + long seconds = millis / 1000; + long minutes = seconds / 60; + + if (minutes > 0) { + return Long.toString(minutes) + " minute" + + (minutes == 1 ? " " : "s ") + + Long.toString(seconds % 60) + " second" + + (seconds % 60 == 1 ? "" : "s"); + } else { + return Long.toString(seconds) + " second" + + (seconds % 60 == 1 ? "" : "s"); + } + + } } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractComponent.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractComponent.java new file mode 100644 index 000000000..ecb390833 --- /dev/null +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractComponent.java @@ -0,0 +1,122 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.common.antlib; + +import org.apache.ant.common.util.ExecutionException; + +/** + * Abstract implementation of the ExecutionComponent + * + * @author Conor MacNeill + * @created 5 February 2002 + */ +public abstract class AbstractComponent implements ExecutionComponent { + /** The components's context */ + private AntContext context; + + /** + * Initialise the component. The component may use the AntContext to + * request services from the Ant core. + * + * @param context the component's context + * @exception ExecutionException if initialisation fails + */ + public void init(AntContext context) throws ExecutionException { + this.context = context; + } + + /** + * Validate the component. This is called after the element has been + * configured from its build model. The element may perform validation + * of its configuration + + * + * @exception ExecutionException if validation fails + */ + public void validateComponent() throws ExecutionException { + // no validation by default + } + + /** + * Get this component's context + * + * @return the component context + */ + protected AntContext getContext() { + return context; + } + + /** + * Short cut to get a core service instance + * + * @param serviceClass the required interface of which an instance is required + * @return the core's instance of the requested service + * @exception ExecutionException if the core does not support the requested service + */ + protected Object getCoreService(Class serviceClass) + throws ExecutionException { + return context.getCoreService(serviceClass); + } + + /** + * Log a message as a build event + * + * @param message the message to be logged + * @param level the priority level of the message + */ + protected void log(String message, int level) { + context.log(message, level); + } +} + diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java index 6c8e705a3..eb1449f21 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java @@ -59,42 +59,10 @@ package org.apache.ant.common.antlib; * @author Conor MacNeill * @created 16 January 2002 */ -public abstract class AbstractTask implements Task { - /** The task's context */ - private AntContext context; - - /** - * Initialise the task. The task may use the AntContext to request - * services from the Ant core. - * - * @param context the Task's context - */ - public void init(AntContext context) { - this.context = context; - } - +public abstract class AbstractTask extends AbstractComponent implements Task { /** Task is about to be cleaned up */ public void destroy() { // do nothing here } - - /** - * Get this task's context - * - * @return the task context - */ - protected AntContext getContext() { - return context; - } - - /** - * Log a message as a build event - * - * @param message the message to be logged - * @param level the priority level of the message - */ - protected void log(String message, int level) { - context.log(message, level); - } } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java index 67d475c81..b16f36e1b 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java @@ -53,9 +53,9 @@ */ package org.apache.ant.common.antlib; import java.io.File; +import org.apache.ant.common.model.ModelElement; import org.apache.ant.common.util.ExecutionException; -import org.apache.ant.common.util.Location; /** * The AntContext is the interface through which the Ant container and the @@ -88,17 +88,17 @@ public interface AntContext { throws ExecutionException; /** - * Get the build file location with which this context is associated. + * Get the basedir for the current execution * - * @return the associated build file location + * @return the base directory for this execution of Ant */ - Location getLocation(); + File getBaseDir(); /** - * Get the basedir for the current execution + * Get the model element associated with this context * - * @return the base directory for this execution of Ant + * @return the modelElement associated with this context */ - File getBaseDir(); + ModelElement getModelElement(); } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/ExecutionComponent.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/ExecutionComponent.java index e80392f52..ba524a23d 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/ExecutionComponent.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/ExecutionComponent.java @@ -55,8 +55,8 @@ package org.apache.ant.common.antlib; import org.apache.ant.common.util.ExecutionException; /** - * An execution component is a component from an AntLibrary which is used in the - * execution of an Ant build. A component can have a context. + * An execution component is a component from an AntLibrary which is used in + * the execution of an Ant build. A component can have a context. * * @author Conor MacNeill * @created 1 February 2002 @@ -70,5 +70,14 @@ public interface ExecutionComponent { * @exception ExecutionException if the component cannot be initialised */ void init(AntContext context) throws ExecutionException; + + /** + * Validate the component. This is called after the element has been + * configured from its build model. The element may perform validation + * of its configuration + * + * @exception ExecutionException if the component is not validly configured + */ + void validateComponent() throws ExecutionException; } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildEvent.java b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildEvent.java index 281deead3..33864a414 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildEvent.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildEvent.java @@ -54,6 +54,7 @@ package org.apache.ant.common.event; import java.util.EventObject; +import org.apache.ant.common.model.ModelElement; /** * A BuildEvent indicates the occurence of a significant event in the build. @@ -96,7 +97,7 @@ public class BuildEvent extends EventObject { * @param eventType the type of the buildEvent. * @param source the element with which this event is associated */ - public BuildEvent(Object source, int eventType) { + public BuildEvent(ModelElement source, int eventType) { super(source); this.eventType = eventType; } @@ -108,7 +109,7 @@ public class BuildEvent extends EventObject { * @param cause An exception if associated with the event * @param source the object with which this event is associated */ - public BuildEvent(Object source, int eventType, + public BuildEvent(ModelElement source, int eventType, Throwable cause) { this(source, eventType); this.cause = cause; @@ -117,12 +118,11 @@ public class BuildEvent extends EventObject { /** * Create a build event for a message * - * @param source the object with which the event is - * associated. + * @param source the object with which the event is associated. * @param message the message associated with this event * @param priority the message priority */ - public BuildEvent(Object source, String message, + public BuildEvent(ModelElement source, String message, int priority) { this(source, MESSAGE); this.message = message; @@ -168,5 +168,14 @@ public class BuildEvent extends EventObject { public Throwable getCause() { return cause; } + + /** + * Gets the modelElement of the BuildEvent + * + * @return the model element this event is associated with + */ + public ModelElement getModelElement() { + return (ModelElement)getSource(); + } } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildListener.java b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildListener.java index 86d830f85..781ac89e0 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildListener.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildListener.java @@ -65,10 +65,55 @@ import java.util.EventListener; */ public interface BuildListener extends EventListener { /** - * Process an incoming build event + * Fired before any targets are started. * - * @param event the event to be processed. + * @param event the build event for this notification */ - void processBuildEvent(BuildEvent event); + void buildStarted(BuildEvent event); + + /** + * Fired after the last target has finished. This event will still be + * thrown if an error occured during the build. + * + * @param event the build event for this notification + */ + void buildFinished(BuildEvent event); + + /** + * Fired when a target is started. + * + * @param event the build event for this notification + */ + void targetStarted(BuildEvent event); + + /** + * Fired when a target has finished. This event will still be thrown if + * an error occured during the build. + * + * @param event the build event for this notification + */ + void targetFinished(BuildEvent event); + + /** + * Fired when a task is started. + * + * @param event the build event for this notification + */ + void taskStarted(BuildEvent event); + + /** + * Fired when a task has finished. This event will still be throw if an + * error occured during the build. + * + * @param event the build event for this notification + */ + void taskFinished(BuildEvent event); + + /** + * Fired whenever a message is logged. + * + * @param event the build event for this notification + */ + void messageLogged(BuildEvent event); } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/BuildElement.java b/proposal/mutant/src/java/common/org/apache/ant/common/model/BuildElement.java old mode 100755 new mode 100644 similarity index 99% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/BuildElement.java rename to proposal/mutant/src/java/common/org/apache/ant/common/model/BuildElement.java index 442e73bad..ee88b7d7a --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/BuildElement.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/model/BuildElement.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model; +package org.apache.ant.common.model; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelElement.java b/proposal/mutant/src/java/common/org/apache/ant/common/model/ModelElement.java old mode 100755 new mode 100644 similarity index 99% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelElement.java rename to proposal/mutant/src/java/common/org/apache/ant/common/model/ModelElement.java index a8845e17d..71a4fdc76 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelElement.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/model/ModelElement.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model; +package org.apache.ant.common.model; import java.util.HashMap; import java.util.Iterator; import java.util.Map; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelException.java b/proposal/mutant/src/java/common/org/apache/ant/common/model/ModelException.java old mode 100755 new mode 100644 similarity index 99% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelException.java rename to proposal/mutant/src/java/common/org/apache/ant/common/model/ModelException.java index 924aaa6b3..f676897cb --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelException.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/model/ModelException.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model; +package org.apache.ant.common.model; import org.apache.ant.common.util.AntException; import org.apache.ant.common.util.Location; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Project.java b/proposal/mutant/src/java/common/org/apache/ant/common/model/Project.java old mode 100755 new mode 100644 similarity index 96% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Project.java rename to proposal/mutant/src/java/common/org/apache/ant/common/model/Project.java index 1516384be..c09715994 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Project.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/model/Project.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model; +package org.apache.ant.common.model; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; @@ -61,10 +61,10 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; +import org.apache.ant.common.util.CircularDependencyChecker; +import org.apache.ant.common.util.CircularDependencyException; +import org.apache.ant.common.util.ConfigException; import org.apache.ant.common.util.Location; -import org.apache.ant.antcore.util.CircularDependencyChecker; -import org.apache.ant.antcore.util.CircularDependencyException; -import org.apache.ant.antcore.util.ConfigException; /** * A project is a collection of targets and global tasks. A project may @@ -366,42 +366,12 @@ public class Project extends ModelElement { } /** - * Validate that this build element is configured correctly + * Validate this project * - * @param globalName The name of this project in the reference name - * space - * @exception ModelException if the element is invalid + * @exception ModelException if the project is not valid */ - public void validate(String globalName) throws ModelException { - Set keys = referencedProjects.keySet(); - for (Iterator i = keys.iterator(); i.hasNext(); ) { - String refName = (String)i.next(); - Project referencedProject - = (Project)referencedProjects.get(refName); - String refGlobalName = refName; - if (globalName != null) { - refGlobalName = globalName + REF_DELIMITER + refName; - } - referencedProject.validate(refGlobalName); - } - - // we now check whether all of dependencies for our targets - // exist in the model - - // visited contains the targets we have already visited and verified - Set visited = new HashSet(); - // checker records the targets we are currently visiting - CircularDependencyChecker checker - = new CircularDependencyChecker("checking target dependencies"); - // dependency order is purely recorded for debug purposes - List dependencyOrder = new ArrayList(); - - for (Iterator i = getTargets(); i.hasNext(); ) { - Target target = (Target)i.next(); - target.validate(); - fillinDependencyOrder(globalName, target, dependencyOrder, - visited, checker); - } + public void validate() throws ModelException { + validate(null); } /** @@ -466,8 +436,47 @@ public class Project extends ModelElement { } /** - * Given a fully qualified target name, this method simply returns the - * fully qualified name of the project + * Validate that this build element is configured correctly + * + * @param globalName The name of this project in the reference name + * space + * @exception ModelException if the element is invalid + */ + protected void validate(String globalName) throws ModelException { + Set keys = referencedProjects.keySet(); + for (Iterator i = keys.iterator(); i.hasNext(); ) { + String refName = (String)i.next(); + Project referencedProject + = (Project)referencedProjects.get(refName); + String refGlobalName = refName; + if (globalName != null) { + refGlobalName = globalName + REF_DELIMITER + refName; + } + referencedProject.validate(refGlobalName); + } + + // we now check whether all of dependencies for our targets + // exist in the model + + // visited contains the targets we have already visited and verified + Set visited = new HashSet(); + // checker records the targets we are currently visiting + CircularDependencyChecker checker + = new CircularDependencyChecker("checking target dependencies"); + // dependency order is purely recorded for debug purposes + List dependencyOrder = new ArrayList(); + + for (Iterator i = getTargets(); i.hasNext(); ) { + Target target = (Target)i.next(); + target.validate(); + fillinDependencyOrder(globalName, target, dependencyOrder, + visited, checker); + } + } + + /** + * Given a fully qualified target name, this method returns the fully + * qualified name of the project * * @param fullTargetName the full qualified target name * @return the full name of the containing project diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Target.java b/proposal/mutant/src/java/common/org/apache/ant/common/model/Target.java old mode 100755 new mode 100644 similarity index 99% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Target.java rename to proposal/mutant/src/java/common/org/apache/ant/common/model/Target.java index 0386a0af6..11347cd8f --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Target.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/model/Target.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.model; +package org.apache.ant.common.model; import java.util.ArrayList; import java.util.Iterator; import java.util.List; diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java b/proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java index 8599b12c8..4bb4816ff 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java @@ -52,6 +52,10 @@ * . */ package org.apache.ant.common.service; +import java.io.File; +import java.util.List; +import java.util.Map; +import org.apache.ant.common.model.Project; import org.apache.ant.common.util.ExecutionException; /** @@ -80,5 +84,37 @@ public interface ComponentService { */ void loadLib(String libLocation, boolean importAll) throws ExecutionException; + + /** + * Run a sub-build. + * + * @param antFile the file containing the XML description of the model + * @param targets A list of targets to be run + * @param properties the initiali properties to be used in the build + * @exception ExecutionException if the subbuild cannot be run + */ + void runBuild(File antFile, Map properties, List targets) + throws ExecutionException; + + /** + * Run a sub-build. + * + * @param model the project model to be used for the build + * @param targets A list of targets to be run + * @param properties the initiali properties to be used in the build + * @exception ExecutionException if the subbuild cannot be run + */ + void runBuild(Project model, Map properties, List targets) + throws ExecutionException; + + /** + * Run a sub-build using the current frame's project model + * + * @param targets A list of targets to be run + * @param properties the initiali properties to be used in the build + * @exception ExecutionException if the subbuild cannot be run + */ + void callTarget(Map properties, List targets) + throws ExecutionException; } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/service/DataService.java b/proposal/mutant/src/java/common/org/apache/ant/common/service/DataService.java index 681031702..47e778398 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/service/DataService.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/service/DataService.java @@ -133,9 +133,10 @@ public interface DataService { * is an expensive operation since it must clone all of the property * stores in all frames * - * @return a Map containing the frames properties indexed by their full name. + * @return a Map containing the frames properties indexed by their full + * name. */ - Map getAllProperties(); - + Map getAllProperties(); + } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/AntException.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/AntException.java index bd5f3610d..11964d6bc 100755 --- a/proposal/mutant/src/java/common/org/apache/ant/common/util/AntException.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/AntException.java @@ -105,7 +105,7 @@ public abstract class AntException extends Exception { */ public AntException(String msg, Throwable cause, Location location) { this(msg, cause); - setLocation(location); + setLocation(location, true); } /** @@ -127,7 +127,7 @@ public abstract class AntException extends Exception { */ public AntException(String msg, Location location) { super(msg); - setLocation(location); + setLocation(location, true); } /** @@ -139,19 +139,22 @@ public abstract class AntException extends Exception { */ public AntException(Throwable cause, Location location) { this(cause); - setLocation(location); + setLocation(location, true); } /** * Sets the file location where the error occured. * - * @param location the new location value + * @param newLocation the new location value + * @param override true if the location should override any currently set location */ - public void setLocation(Location location) { - if (location == null) { - this.location = Location.UNKNOWN_LOCATION; - } else { - this.location = location; + public void setLocation(Location newLocation, boolean override) { + if (override || location == Location.UNKNOWN_LOCATION) { + if (newLocation == null) { + this.location = Location.UNKNOWN_LOCATION; + } else { + this.location = newLocation; + } } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyChecker.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/CircularDependencyChecker.java old mode 100755 new mode 100644 similarity index 99% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyChecker.java rename to proposal/mutant/src/java/common/org/apache/ant/common/util/CircularDependencyChecker.java index bdea4889c..826282620 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyChecker.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/CircularDependencyChecker.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.util; +package org.apache.ant.common.util; import java.util.Stack; /** diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyException.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/CircularDependencyException.java old mode 100755 new mode 100644 similarity index 97% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyException.java rename to proposal/mutant/src/java/common/org/apache/ant/common/util/CircularDependencyException.java index af96186bc..e6d3a2576 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyException.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/CircularDependencyException.java @@ -51,10 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.util; - -import org.apache.ant.common.util.AntException; -import org.apache.ant.common.util.Location; +package org.apache.ant.common.util; /** * A CircularDependencyException indicates that a circular dependency has diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/ConfigException.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/ConfigException.java old mode 100755 new mode 100644 similarity index 97% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/ConfigException.java rename to proposal/mutant/src/java/common/org/apache/ant/common/util/ConfigException.java index fd26d211e..adc4413c6 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/ConfigException.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/ConfigException.java @@ -51,10 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.util; - -import org.apache.ant.common.util.AntException; -import org.apache.ant.common.util.Location; +package org.apache.ant.common.util; /** * A ConfigException indicates a problem with Ant's configuration or the diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/StringUtils.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/StringUtils.java new file mode 100644 index 000000000..f04d6c503 --- /dev/null +++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/StringUtils.java @@ -0,0 +1,140 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.common.util; +import java.io.PrintWriter; + +import java.io.StringWriter; +import java.util.List; +import java.util.ArrayList; + +/** + * A set of helper methods related to string manipulation. + * + * @author Stephane Bailliez + */ +public final class StringUtils { + + /** the line separator for this OS */ + public final static String LINE_SEP = System.getProperty("line.separator"); + + /** + * Convenient method to retrieve the full stacktrace from a given + * exception. + * + * @param t the exception to get the stacktrace from. + * @return the stacktrace from the given exception. + */ + public static String getStackTrace(Throwable t) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw, true); + t.printStackTrace(pw); + pw.flush(); + pw.close(); + return sw.toString(); + } + + /** + * Splits up a string into a list of lines. It is equivalent to + * split(data, '\n') . + * + * @param data the string to split up into lines. + * @return the list of lines available in the string. + */ + public static List lineSplit(String data) { + return split(data, '\n'); + } + + /** + * Splits up a string where elements are separated by a specific + * character and return all elements. + * + * @param data the string to split up. + * @param ch the separator character. + * @return the list of elements. + */ + public static List split(String data, int ch) { + List elems = new ArrayList(); + int pos = -1; + int i = 0; + while ((pos = data.indexOf(ch, i)) != -1) { + String elem = data.substring(i, pos); + elems.add(elem); + i = pos + 1; + } + elems.add(data.substring(i)); + return elems; + } + + /** + * Replace occurrences into a string. + * + * @param data the string to replace occurrences into + * @param from the occurrence to replace. + * @param to the occurrence to be used as a replacement. + * @return the new string with replaced occurrences. + */ + public static String replace(String data, String from, String to) { + StringBuffer buf = new StringBuffer(data.length()); + int pos = -1; + int i = 0; + while ((pos = data.indexOf(from, i)) != -1) { + buf.append(data.substring(i, pos)).append(to); + i = pos + from.length(); + } + buf.append(data.substring(i)); + return buf.toString(); + } + +} +