diff --git a/proposal/mutant/build.xml b/proposal/mutant/build.xml
index fd162a827..cd52693aa 100644
--- a/proposal/mutant/build.xml
+++ b/proposal/mutant/build.xml
@@ -1,6 +1,170 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibDefinition.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibDefinition.java
new file mode 100755
index 000000000..21975af2d
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibDefinition.java
@@ -0,0 +1,115 @@
+/*
+ * 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.antlib;
+
+/**
+ * This class represents a definition in an AntLibrary.
+ *
+ * @author Conor MacNeill
+ * @created 19 January 2002
+ */
+public class AntLibDefinition {
+ /** The tpye of element being defined int his definition */
+ private int definitionType;
+ /** The default name for the defintion */
+ private String definitionName;
+ /** The classname associated with the object */
+ private String definitionClassName;
+
+ /**
+ * Create a definition
+ *
+ * @param definitionName the default name of this definition when it is
+ * imported
+ * @param definitionClassName the name of the class which is being
+ * defined
+ * @param definitionType the type of the definition (taskdef, typedef,
+ * etc)
+ */
+ public AntLibDefinition(int definitionType, String definitionName,
+ String definitionClassName) {
+ this.definitionName = definitionName;
+ this.definitionType = definitionType;
+ this.definitionClassName = definitionClassName;
+ }
+
+ /**
+ * Get the type of this definition
+ *
+ * @return the definition type
+ * @see AntLibrary for values
+ */
+ public int getDefinitionType() {
+ return definitionType;
+ }
+
+ /**
+ * Get the default name for this definition
+ *
+ * @return the default name for this definition
+ */
+ public String getDefinitionName() {
+ return definitionName;
+ }
+
+ /**
+ * Get the classname being defined
+ *
+ * @return the classname of this definition
+ */
+ public String getClassName() {
+ return definitionClassName;
+ }
+}
+
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
new file mode 100755
index 000000000..c83b64a66
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibHandler.java
@@ -0,0 +1,195 @@
+/*
+ * 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.antlib;
+import org.apache.ant.antcore.util.ConfigException;
+
+import org.apache.ant.antcore.xml.ElementHandler;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXParseException;
+
+/**
+ * XML Element Handler for Ant library definitions
+ *
+ * @author Conor MacNeill
+ * @created 13 January 2002
+ */
+public class AntLibHandler extends ElementHandler {
+ /** The library identifier attribute name */
+ public final static String LIBID_ATTR = "libid";
+ /** The home attribute name */
+ public final static String HOME_ATTR = "home";
+ /**
+ * The name of the attribute which indicates if Ant's XML parser is to
+ * be made available
+ */
+ public final static String REQXML_ATTR = "reqxml";
+ /** The extends attribute name */
+ public final static String EXTENDS_ATTR = "extends";
+ /** The name of the attribute which indicates tools jar is required */
+ public final static String REQTOOLS_ATTR = "reqtools";
+ /** The extends attribute name */
+ public final static String ISOLATED_ATTR = "isolated";
+
+ /** The list of allowed Attributes */
+ public final static String[] ALLOWED_ATTRIBUTES
+ = {LIBID_ATTR, HOME_ATTR, REQXML_ATTR, REQTOOLS_ATTR,
+ EXTENDS_ATTR, ISOLATED_ATTR};
+
+ /** The Ant Library definition being parsed. */
+ private AntLibrarySpec antLibrarySpec;
+
+ /**
+ * Gets the parsed antLibrary specification
+ *
+ * @return the parsed antLibrary
+ */
+ public AntLibrarySpec getAntLibrarySpec() {
+ return antLibrarySpec;
+ }
+
+ /**
+ * Process the antlib element
+ *
+ * @param elementName the name of the element
+ * @exception SAXParseException if there is a problem parsing the
+ * element
+ */
+ public void processElement(String elementName)
+ throws SAXParseException {
+ antLibrarySpec = new AntLibrarySpec();
+
+ if (getAttribute(LIBID_ATTR) == null) {
+ throw new SAXParseException("antlib must have an libid sttribute",
+ getLocator());
+ }
+ antLibrarySpec.setLibraryId(getAttribute(LIBID_ATTR));
+ antLibrarySpec.setHome(getAttribute(HOME_ATTR));
+ antLibrarySpec.setExtendsLibraryId(getAttribute(EXTENDS_ATTR));
+ antLibrarySpec.setIsolated(getBooleanAttribute(ISOLATED_ATTR));
+ antLibrarySpec.setAntXML(getBooleanAttribute(REQXML_ATTR));
+ antLibrarySpec.setToolsJarRequired(getBooleanAttribute(REQTOOLS_ATTR));
+ }
+
+ /**
+ * Start a new element in the antlibrary.
+ *
+ * @param uri The Namespace URI.
+ * @param localName The local name (without prefix).
+ * @param qualifiedName The qualified name (with prefix)
+ * @param attributes The attributes attached to the element.
+ * @throws SAXParseException if there is a parsing problem.
+ */
+ public void startElement(String uri, String localName, String qualifiedName,
+ Attributes attributes)
+ throws SAXParseException {
+ try {
+ if (qualifiedName.equals("taskdef")
+ || qualifiedName.equals("typedef")) {
+ DefinitionHandler defnHandler
+ = new DefinitionHandler(qualifiedName);
+ defnHandler.start(getParseContext(), getXMLReader(),
+ this, getLocator(), attributes, getElementSource(),
+ qualifiedName);
+ antLibrarySpec.addDefinition(defnHandler.getDefinitionType(),
+ defnHandler.getName(), defnHandler.getClassName());
+ } else if (qualifiedName.equals("converter")) {
+ ConverterHandler converterHandler
+ = new ConverterHandler();
+ converterHandler.start(getParseContext(), getXMLReader(),
+ this, getLocator(), attributes, getElementSource(),
+ qualifiedName);
+ antLibrarySpec.addConverter(converterHandler.getClassName());
+ }
+ else {
+ super.startElement(uri, localName, qualifiedName, attributes);
+ }
+ } catch (ConfigException e) {
+ throw new SAXParseException(e.getMessage(), getLocator());
+ }
+ }
+
+ /**
+ * Validate that the given attribute and value are valid.
+ *
+ * @param attributeName The name of the attributes
+ * @param attributeValue The value of the attributes
+ * @exception SAXParseException if the attribute is not allowed on the
+ * element.
+ */
+ protected void validateAttribute(String attributeName,
+ String attributeValue)
+ throws SAXParseException {
+ for (int i = 0; i < ALLOWED_ATTRIBUTES.length; ++i) {
+ if (attributeName.equals(ALLOWED_ATTRIBUTES[i])) {
+ return;
+ }
+ }
+ throwInvalidAttribute(attributeName);
+ }
+
+
+ /**
+ * Get an attribute as a boolean value
+ *
+ * @param attributeName the name of the attribute
+ * @return the attribute value as a boolean
+ */
+ private boolean getBooleanAttribute(String attributeName) {
+ String value = getAttribute(attributeName);
+ return value != null && (value.equalsIgnoreCase("true")
+ || value.equalsIgnoreCase("yes"));
+ }
+}
+
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrary.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrary.java
new file mode 100755
index 000000000..1c742a905
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrary.java
@@ -0,0 +1,208 @@
+/*
+ * 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.antlib;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class represents the Ant library.
+ *
+ * @author Conor MacNeill
+ * @created 14 January 2002
+ */
+public class AntLibrary {
+ /** constant indicating a taskdef definition */
+ public final static int TASKDEF = 1;
+ /** constant indicating a typedef definition */
+ public final static int TYPEDEF = 2;
+
+ /**
+ * This is the globally unique name of this library. It uses the same
+ * conventions as the Java package space - i.e. reverse order DNS names
+ * This name is used when importing tasks from this library
+ */
+ private String libraryId;
+ /**
+ * The URLs to use when contructing a classloader for the components in
+ * this library.
+ */
+ private List libraryURLs = new ArrayList();
+
+ /** The list of converter classnames defined in this library */
+ private List converterClassNames = new ArrayList();
+
+ /** The parent classloader to use when contructing classloaders */
+ private ClassLoader parentLoader;
+
+ /** The library which this library extends, if any */
+ private AntLibrary extendsLibrary;
+
+ /** Indicates if each Task Instance should use its own classloader */
+ private boolean isolated = false;
+
+ /** The classloader for this library if it can be reused */
+ private ClassLoader loader = null;
+
+ /** The definitions in the library */
+ private Map definitions = null;
+
+ /**
+ * Constructor for the AntLibrary object
+ *
+ * @param spec the specification from which this library is created.
+ */
+ public AntLibrary(AntLibrarySpec spec) {
+ this.libraryId = spec.getLibraryId();
+ this.definitions = spec.getDefinitions();
+ this.isolated = spec.isIsolated();
+ this.converterClassNames.addAll(spec.getConverterClassNames());
+ }
+
+ /**
+ * Sets the Library which this library extends
+ *
+ * @param extendsLibrary The new ExtendsLibrary value
+ */
+ public void setExtendsLibrary(AntLibrary extendsLibrary) {
+ this.extendsLibrary = extendsLibrary;
+ }
+
+ /**
+ * Sets the ParentLoader of the AntLibrary
+ *
+ * @param parentLoader The new ParentLoader value
+ */
+ public void setParentLoader(ClassLoader parentLoader) {
+ this.parentLoader = parentLoader;
+ }
+
+ /**
+ * Gets the libraryId of the AntLibrary
+ *
+ * @return the libraryId value
+ */
+ public String getLibraryId() {
+ return libraryId;
+ }
+
+ /**
+ * Gets the ClassLoader of the AntLibrary
+ *
+ * @return The ClassLoader value
+ */
+ public ClassLoader getClassLoader() {
+ if (isolated) {
+ return createLoader();
+ } else if (loader == null) {
+ loader = createLoader();
+ }
+ return loader;
+ }
+
+ /**
+ * Gets the definitions (taskdefs and typedefs) of the AntLibrary
+ *
+ * @return the definitions map
+ */
+ public Map getDefinitions() {
+ return definitions;
+ }
+
+ /**
+ * Gets an the converter class names of the AntLibrary
+ *
+ * @return an iterator over a list of String class names
+ */
+ public Iterator getConverterClassNames() {
+ return converterClassNames.iterator();
+ }
+
+ /**
+ * Indicate whether this library has any converters defined
+ *
+ * @return true if any converters have been defined
+ */
+ public boolean hasConverters() {
+ return !converterClassNames.isEmpty();
+ }
+
+ /**
+ * Add a library to path to this AntLibrary definition
+ *
+ * @param libraryURL the URL to the library to be added
+ */
+ public void addLibraryURL(URL libraryURL) {
+ libraryURLs.add(libraryURL);
+ }
+
+ /**
+ * Create classloader which can be used to load the classes of this ant
+ * library
+ *
+ * @return the classloader for this ant library
+ */
+ private ClassLoader createLoader() {
+ ClassLoader ourParent
+ = extendsLibrary == null ? parentLoader
+ : extendsLibrary.getClassLoader();
+ return new URLClassLoader((URL[])libraryURLs.toArray(new URL[0]),
+ ourParent);
+ }
+
+}
+
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
new file mode 100755
index 000000000..da8afdb5b
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrarySpec.java
@@ -0,0 +1,292 @@
+/*
+ * 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.antlib;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+import org.apache.ant.antcore.util.ConfigException;
+
+/**
+ * This class represents the specification of an Ant library. It is merely
+ * the internal representation of the antlib XML definition. An instance of
+ * this class is used to contruct an AntLibrary instance.
+ *
+ * @author Conor MacNeill
+ * @created 13 January 2002
+ */
+public class AntLibrarySpec {
+ /**
+ * This is the globally unique name of this library. It uses the same
+ * conventions as the Java package space - i.e. reverse order DNS names
+ * This name is used when importing tasks from this library
+ */
+ private String libraryId;
+
+ /**
+ * This string identifies the location where the library is maintained.
+ * It is usually a URL to the location from which the library may be
+ * downloaded or purchased
+ */
+ private String libraryHome;
+
+ /** The list of converter classnames defined in this library */
+ private List converterClassNames = new ArrayList();
+
+ /**
+ * This is the optional id of another Ant library upon which this
+ * library depends.
+ */
+ private String extendsLibraryId;
+
+ /** This is the URL from which this library has been loaded */
+ private URL libraryURL;
+
+ /** This is the list of definitions */
+ private Map definitions = new HashMap();
+
+ /** Indicates if each Task Instance should use its own classloader */
+ private boolean isolated = false;
+
+ /** Flag which indicates if tools.jar is required */
+ private boolean toolsJarRequired = false;
+
+ /**
+ * This flag indicates that this task processes XML and wishes to use
+ * the XML parser packaged with Ant
+ */
+ private boolean requiresAntXMLParser = false;
+
+ /**
+ * Set the library that this library extends, if any
+ *
+ * @param extendsLibraryId The new ExtendsLibraryId value
+ */
+ public void setExtendsLibraryId(String extendsLibraryId) {
+ this.extendsLibraryId = extendsLibraryId;
+ }
+
+ /**
+ * Indicate that this library requires a separate classloader per task
+ * instance
+ *
+ * @param isolated The new Isolated value
+ */
+ public void setIsolated(boolean isolated) {
+ this.isolated = isolated;
+ }
+
+ /**
+ * Sets the home of the AntLibrary
+ *
+ * @param home The new home value
+ */
+ public void setHome(String home) {
+ this.libraryHome = libraryHome;
+ }
+
+ /**
+ * Sets the libraryId of the AntLibrary
+ *
+ * @param libraryId The new libraryId value
+ */
+ public void setLibraryId(String libraryId) {
+ this.libraryId = libraryId;
+ }
+
+
+ /**
+ * Indicate that this library uses the Sun tools.jar
+ *
+ * @param toolsJarRequired The new ToolsJarRequired value
+ */
+ public void setToolsJarRequired(boolean toolsJarRequired) {
+ this.toolsJarRequired = toolsJarRequired;
+ }
+
+
+ /**
+ * Sets the libraryURL of the AntLibrary
+ *
+ * @param libraryURL The new libraryURL value
+ */
+ public void setLibraryURL(URL libraryURL) {
+ this.libraryURL = libraryURL;
+ }
+
+ /**
+ * Indicates that this library uses Ant's XML parser libraries
+ *
+ * @param requiresAntXMLParser true if this library uses Ant's XML
+ * parser libraries
+ */
+ public void setAntXML(boolean requiresAntXMLParser) {
+ this.requiresAntXMLParser = requiresAntXMLParser;
+ }
+
+ /**
+ * Get the list of converter classnames defined in this library spec
+ *
+ * @return the converter classnames list
+ */
+ public List getConverterClassNames() {
+ return converterClassNames;
+ }
+
+ /**
+ * Indicate whether this AntLibrary requires the Sun tools.jar
+ *
+ * @return The ToolsJarRequired value
+ */
+ public boolean isToolsJarRequired() {
+ return toolsJarRequired;
+ }
+
+ /**
+ * Get the id of the library that this library extends if any.
+ *
+ * @return The ExtendsLibraryId value
+ */
+ public String getExtendsLibraryId() {
+ return extendsLibraryId;
+ }
+
+ /**
+ * Indicate if this library required an classloader per instance
+ *
+ * @return true if a separate classloader should be used per instance.
+ */
+ public boolean isIsolated() {
+ return isolated;
+ }
+
+
+ /**
+ * Gets the libraryId of the AntLibrary
+ *
+ * @return The libraryId value
+ */
+ public String getLibraryId() {
+ return libraryId;
+ }
+
+ /**
+ * Gets the libraryURL of the AntLibrary
+ *
+ * @return The libraryURL value
+ */
+ public URL getLibraryURL() {
+ return libraryURL;
+ }
+
+
+ /**
+ * Gets the definitions of the AntLibrarySpec
+ *
+ * @return the definitions map
+ */
+ public Map getDefinitions() {
+ return definitions;
+ }
+
+ /**
+ * Add a converter to this library sec
+ *
+ * @param className the name of the converter class
+ */
+ public void addConverter(String className) {
+ converterClassNames.add(className);
+ }
+
+ /**
+ * Indicates if this library requires Ant's XML parser
+ *
+ * @return true if this library requires Ant's XML parser
+ */
+ public boolean usesAntXML() {
+ return requiresAntXMLParser;
+ }
+
+ /**
+ * Adds a definition to the Ant Library
+ *
+ * @param name the name of the library definition
+ * @param classname the name of the class implementing the element
+ * @param definitionTypeName the name of the definition type. This is
+ * converted to its symbolic value
+ * @exception ConfigException if the definition has already been defined
+ */
+ public void addDefinition(String definitionTypeName, String name,
+ String classname)
+ throws ConfigException {
+ if (definitions.containsKey(name)) {
+ throw new ConfigException("More than one definition "
+ + "in library for " + name);
+ }
+ int definitionType = 0;
+
+ if (definitionTypeName.equals("typedef")) {
+ definitionType = AntLibrary.TYPEDEF;
+ } else if (definitionTypeName.equals("taskdef")) {
+ definitionType = AntLibrary.TASKDEF;
+ } else {
+ throw new ConfigException("Unknown type of definition "
+ + definitionTypeName);
+ }
+ definitions.put(name,
+ new AntLibDefinition(definitionType, name, classname));
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/ConverterHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/ConverterHandler.java
new file mode 100755
index 000000000..5b4e5abb9
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/ConverterHandler.java
@@ -0,0 +1,109 @@
+/*
+ * 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.antlib;
+
+import org.apache.ant.antcore.xml.ElementHandler;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Handler for converter definition within an Ant Library
+ *
+ * @author Conor MacNeill
+ */
+public class ConverterHandler extends ElementHandler {
+ /** The classname attribute name */
+ public final static String CLASSNAME_ATTR = "classname";
+
+ /**
+ * Gets the className of the Converter
+ *
+ * @return the className value
+ */
+ public String getClassName() {
+ return getAttribute(CLASSNAME_ATTR);
+ }
+
+ /**
+ * Process the definition element
+ *
+ * @param elementName the name of the element
+ * @exception SAXParseException if there is a problem parsing the
+ * element
+ */
+ public void processElement(String elementName)
+ throws SAXParseException {
+ if (getClassName() == null) {
+ throw new SAXParseException(CLASSNAME_ATTR + " must be "
+ + "specified for a converter", getLocator());
+ }
+ }
+
+ /**
+ * Validate that the given attribute and value are valid.
+ *
+ * @param attributeName The name of the attributes
+ * @param attributeValue The value of the attributes
+ * @exception SAXParseException if the attribute is not allowed on the
+ * element.
+ */
+ protected void validateAttribute(String attributeName,
+ String attributeValue)
+ throws SAXParseException {
+ if (!attributeName.equals(CLASSNAME_ATTR)) {
+ throwInvalidAttribute(attributeName);
+ }
+ }
+}
+
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/DefinitionHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/DefinitionHandler.java
new file mode 100755
index 000000000..97ec9a92c
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/DefinitionHandler.java
@@ -0,0 +1,144 @@
+/*
+ * 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.antlib;
+
+import org.apache.ant.antcore.xml.ElementHandler;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Handler for definition within an Ant Library
+ *
+ * @author Conor MacNeill
+ * @created 13 January 2002
+ */
+public class DefinitionHandler extends ElementHandler {
+ /** The name attribute name */
+ public final static String NAME_ATTR = "name";
+
+ /** The classname attribute name */
+ public final static String CLASSNAME_ATTR = "classname";
+
+ /** the type of the definition */
+ private String definitionType;
+
+ /**
+ * Create a definition handler to handle a specific type of definition
+ *
+ * @param definitionType the type of the definition being handled
+ */
+ public DefinitionHandler(String definitionType) {
+ this.definitionType = definitionType;
+ }
+
+ /**
+ * Get the type of definition being handled
+ *
+ * @return the type of the definition
+ */
+ public String getDefinitionType() {
+ return definitionType;
+ }
+
+ /**
+ * Gets the name of the TaskdefHandler
+ *
+ * @return the name value
+ */
+ public String getName() {
+ return getAttribute(NAME_ATTR);
+ }
+
+ /**
+ * Gets the className of the TaskdefHandler
+ *
+ * @return the className value
+ */
+ public String getClassName() {
+ return getAttribute(CLASSNAME_ATTR);
+ }
+
+ /**
+ * Process the definition element
+ *
+ * @param elementName the name of the element
+ * @exception SAXParseException if there is a problem parsing the
+ * element
+ */
+ public void processElement(String elementName)
+ throws SAXParseException {
+ if (getName() == null || getClassName() == null) {
+ throw new SAXParseException("name and classname must be "
+ + "specified for a " + definitionType, getLocator());
+ }
+ }
+
+ /**
+ * Validate that the given attribute and value are valid.
+ *
+ * @param attributeName The name of the attributes
+ * @param attributeValue The value of the attributes
+ * @exception SAXParseException if the attribute is not allowed on the
+ * element.
+ */
+ protected void validateAttribute(String attributeName,
+ String attributeValue)
+ throws SAXParseException {
+ if (!attributeName.equals(NAME_ATTR) &&
+ !attributeName.equals(CLASSNAME_ATTR)) {
+ throwInvalidAttribute(attributeName);
+ }
+ }
+}
+
+
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
new file mode 100755
index 000000000..5e877fc21
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfig.java
@@ -0,0 +1,198 @@
+/*
+ * 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.config;
+import java.io.File;
+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.common.util.PathTokenizer;
+import org.apache.ant.antcore.util.ConfigException;
+import org.apache.ant.init.InitUtils;
+
+/**
+ * An AntConfig is the java class representation of the antconfig.xml files
+ * used to configure Ant.
+ *
+ * @author Conor MacNeill
+ * @created 20 January 2002
+ */
+public class AntConfig {
+ /** The list of additional directories to be searched for Ant libraries */
+ private List taskDirLocations = new ArrayList();
+
+ /**
+ * A list of additional paths for each ant library, indexed on the
+ * library id
+ */
+ private Map libPaths = new HashMap();
+
+ /**
+ * Get the task dir locations.
+ *
+ * @return an iterator over the task dir locations
+ */
+ public Iterator getTaskDirLocations() {
+ return taskDirLocations.iterator();
+ }
+
+ /**
+ * Get the list of additional path components for a given path
+ *
+ * @param libraryId the identifier for the library
+ * @return the list of URLs for the additional paths for the given
+ * library
+ */
+ public List getLibraryPathList(String libraryId) {
+ List libraryPathList = (List)libPaths.get(libraryId);
+ if (libraryPathList == null) {
+ libraryPathList = new ArrayList();
+ libPaths.put(libraryId, libraryPathList);
+ }
+ return libraryPathList;
+ }
+
+ /**
+ * Gets the libraryIds of the AntConfig
+ *
+ * @return an interator over the library identifiers for which there is
+ * additional path information
+ */
+ public Iterator getLibraryIds() {
+ return libPaths.keySet().iterator();
+ }
+
+ /**
+ * Add an additional set of paths for the given library.
+ *
+ * @param libraryId The library id for which the additional class path
+ * is being specified
+ * @param libraryPath the classpath style string for the library's
+ * additonal paths
+ * @exception ConfigException if the appropriate URLs cannot be formed.
+ */
+ public void addLibPath(String libraryId, String libraryPath)
+ throws ConfigException {
+ try {
+ List libraryPathList = getLibraryPathList(libraryId);
+ PathTokenizer p = new PathTokenizer(libraryPath);
+ while (p.hasMoreTokens()) {
+ String pathElement = p.nextToken();
+ File pathElementFile = new File(pathElement);
+ URL pathElementURL = InitUtils.getFileURL(pathElementFile);
+ libraryPathList.add(pathElementURL);
+ }
+ } catch (MalformedURLException e) {
+ throw new ConfigException("Unable to process libraryPath '"
+ + libraryPath + "' for library '" + libraryId + "'", e);
+ }
+ }
+
+ /**
+ * Add an additional URL for the library's classpath
+ *
+ * @param libraryId the library's unique Id
+ * @param libraryURL a string which points to the additonal path
+ * @exception ConfigException if the URL could not be formed
+ */
+ public void addLibURL(String libraryId, String libraryURL)
+ throws ConfigException {
+ try {
+ List libraryPathList = getLibraryPathList(libraryId);
+ libraryPathList.add(new URL(libraryURL));
+ } catch (MalformedURLException e) {
+ throw new ConfigException("Unable to process libraryURL '"
+ + libraryURL + "' for library '" + libraryId + "'", e);
+ }
+
+ }
+
+ /**
+ * Merge in another ocnfiguration. The configuration being merged in
+ * takes precedence
+ *
+ * @param otherConfig the other AntConfig to be merged.
+ */
+ public void merge(AntConfig otherConfig) {
+ // merge by
+ List currentTaskDirs = taskDirLocations;
+ taskDirLocations = new ArrayList();
+ taskDirLocations.addAll(otherConfig.taskDirLocations);
+ taskDirLocations.addAll(currentTaskDirs);
+
+ Iterator i = otherConfig.libPaths.keySet().iterator();
+ while (i.hasNext()) {
+ String libraryId = (String)i.next();
+ List currentList = getLibraryPathList(libraryId);
+ List combined = new ArrayList();
+ combined.addAll(otherConfig.getLibraryPathList(libraryId));
+ combined.addAll(currentList);
+ libPaths.put(libraryId, combined);
+ }
+ }
+
+ /**
+ * Add a new task directory to be searched for additional Ant libraries
+ *
+ * @param taskDirLocation the location (can be a file or a URL) where
+ * the libraries may be loaded from.
+ */
+ public void addTaskDir(String taskDirLocation) {
+ taskDirLocations.add(taskDirLocation);
+ }
+}
+
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
new file mode 100755
index 000000000..6b8c12afe
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfigHandler.java
@@ -0,0 +1,141 @@
+/*
+ * 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.config;
+import org.apache.ant.antcore.util.ConfigException;
+import org.apache.ant.antcore.xml.ElementHandler;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXParseException;
+
+/**
+ * XML Element Handler for Ant config files
+ *
+ * @author Conor MacNeill
+ * @created 20 January 2002
+ */
+public class AntConfigHandler extends ElementHandler {
+ /**
+ * The config object which is contructed from the XML representation of
+ * the config
+ */
+ private AntConfig config;
+
+ /**
+ * Get the Ant Config read in by this handler
+ *
+ * @return the AntConfig instance
+ */
+ public AntConfig getAntConfig() {
+ return config;
+ }
+
+ /**
+ * Process the antlib element
+ *
+ * @param elementName the name of the element
+ * @exception SAXParseException if there is a problem parsing the
+ * element
+ */
+ public void processElement(String elementName)
+ throws SAXParseException {
+ config = new AntConfig();
+ }
+
+ /**
+ * Start a new element in the ant config.
+ *
+ * @param uri The Namespace URI.
+ * @param localName The local name (without prefix).
+ * @param qualifiedName The qualified name (with prefix)
+ * @param attributes The attributes attached to the element.
+ * @throws SAXParseException if there is a parsing problem.
+ */
+ public void startElement(String uri, String localName, String qualifiedName,
+ Attributes attributes)
+ throws SAXParseException {
+
+ try {
+ if (qualifiedName.equals("taskdir")) {
+ TaskDirHandler taskDirHandler
+ = new TaskDirHandler();
+ taskDirHandler.start(getParseContext(), getXMLReader(),
+ this, getLocator(), attributes, getElementSource(),
+ qualifiedName);
+ config.addTaskDir(taskDirHandler.getTaskDirLocation());
+ } else if (qualifiedName.equals("libpath")) {
+ LibPathHandler libPathHandler
+ = new LibPathHandler();
+ libPathHandler.start(getParseContext(), getXMLReader(),
+ this, getLocator(), attributes, getElementSource(),
+ qualifiedName);
+
+ if (libPathHandler.getLibraryPath() != null) {
+ config.addLibPath(libPathHandler.getLibraryId(),
+ libPathHandler.getLibraryPath());
+ } else {
+ config.addLibURL(libPathHandler.getLibraryId(),
+ libPathHandler.getLibraryURL());
+ }
+
+ } else {
+ super.startElement(uri, localName, qualifiedName, attributes);
+ }
+ } catch (ConfigException e) {
+ throw new SAXParseException("Unable to process config",
+ getLocator(), e);
+ }
+ }
+
+}
+
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/LibPathHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/LibPathHandler.java
new file mode 100755
index 000000000..7659a06e1
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/LibPathHandler.java
@@ -0,0 +1,141 @@
+/*
+ * 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.config;
+
+import org.apache.ant.antcore.xml.ElementHandler;
+import org.xml.sax.SAXParseException;
+
+/**
+ * An XML Handler for the libpath element in an Ant config file
+ *
+ * @author Conor MacNeill
+ * @created 20 January 2002
+ */
+public class LibPathHandler extends ElementHandler {
+ /** The library identifier attribute name */
+ public final static String LIBID_ATTR = "libid";
+ /** The path attribute name */
+ public final static String PATH_ATTR = "path";
+ /** The path attribute name */
+ public final static String URL_ATTR = "url";
+
+ /**
+ * Get the libraryId for which the additional path is being defined
+ *
+ * @return the library's unique id
+ */
+ public String getLibraryId() {
+ return getAttribute(LIBID_ATTR);
+ }
+
+ /**
+ * Get the additional path being defined fro the library
+ *
+ * @return the libraryPath value, may be null
+ */
+ public String getLibraryPath() {
+ return getAttribute(PATH_ATTR);
+ }
+
+ /**
+ * Get the URL (as a string) containing the additional path for the
+ * library.
+ *
+ * @return the libraryURL value
+ */
+ public String getLibraryURL() {
+ return getAttribute(URL_ATTR);
+ }
+
+
+ /**
+ * Process the libpath element
+ *
+ * @param elementName the name of the element
+ * @exception SAXParseException if there is a problem parsing the
+ * element
+ */
+ public void processElement(String elementName)
+ throws SAXParseException {
+ if (getLibraryId() == null
+ || (getLibraryPath() == null && getLibraryURL() == null)
+ || (getLibraryPath() != null && getLibraryURL() != null)) {
+ throw new SAXParseException("The " + LIBID_ATTR
+ + " attribute and only one of "
+ + PATH_ATTR + " or " + URL_ATTR
+ + " attributes must be specified for a libpath element",
+ getLocator());
+ }
+ }
+
+ /**
+ * Validate that the given attribute and value are valid.
+ *
+ * @param attributeName The name of the attributes
+ * @param attributeValue The value of the attributes
+ * @exception SAXParseException if the attribute is not allowed on the
+ * element.
+ */
+ protected void validateAttribute(String attributeName,
+ String attributeValue)
+ throws SAXParseException {
+ if (!attributeName.equals(LIBID_ATTR) &&
+ !attributeName.equals(PATH_ATTR) &&
+ !attributeName.equals(URL_ATTR)) {
+ throwInvalidAttribute(attributeName);
+ }
+ }
+}
+
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/TaskDirHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/TaskDirHandler.java
new file mode 100755
index 000000000..827a88513
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/TaskDirHandler.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.config;
+
+import org.apache.ant.antcore.xml.ElementHandler;
+import org.xml.sax.SAXParseException;
+
+/**
+ * An XML handler to handle the taskdir element of an AntConfig file.
+ *
+ * @author Conor MacNeill
+ * @created 20 January 2002
+ */
+public class TaskDirHandler extends ElementHandler {
+ /** The location attribute name */
+ public final static String LOCATION_ATTR = "location";
+
+ /**
+ * Get the location of the additional search directory
+ *
+ * @return the additional directory to be searched for Ant libraries.
+ */
+ public String getTaskDirLocation() {
+ return getAttribute(LOCATION_ATTR);
+ }
+
+ /**
+ * Process the taskdir element
+ *
+ * @param elementName the name of the element
+ * @exception SAXParseException if there is a problem parsing the
+ * element
+ */
+ public void processElement(String elementName)
+ throws SAXParseException {
+ if (getLocation() == null) {
+ throw new SAXParseException(LOCATION_ATTR
+ + " must be specified for a taskdir element", getLocator());
+ }
+ }
+
+ /**
+ * Validate that the given attribute and value are valid.
+ *
+ * @param attributeName The name of the attributes
+ * @param attributeValue The value of the attributes
+ * @exception SAXParseException if the attribute is not allowed on the
+ * element.
+ */
+ protected void validateAttribute(String attributeName,
+ String attributeValue)
+ throws SAXParseException {
+ if (!attributeName.equals(LOCATION_ATTR)) {
+ throwInvalidAttribute(attributeName);
+ }
+ }
+}
+
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEvent.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEvent.java
new file mode 100755
index 000000000..aec2fd0e1
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEvent.java
@@ -0,0 +1,182 @@
+/*
+ * 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.event;
+
+import java.util.EventObject;
+import org.apache.ant.antcore.model.ModelElement;
+
+/**
+ * A BuildEvent indicates the occurence of a significant event in the build.
+ * All build events come from an ExecutionFrame or an ExecutionManager.
+ * There are a number of different types of event and they will generally be
+ * associated with some build element from the build model.
+ *
+ * @author Conor MacNeill
+ * @created 15 January 2002
+ */
+public class BuildEvent extends EventObject {
+
+ /** Build Started Event type */
+ public final static int BUILD_STARTED = 1;
+ /** Build Finished Event Type */
+ public final static int BUILD_FINISHED = 2;
+ /** Start of target event type */
+ public final static int TARGET_STARTED = 3;
+ /** Target finished event type */
+ public final static int TARGET_FINISHED = 4;
+ /** Start of task event type */
+ public final static int TASK_STARTED = 5;
+ /** end of task event type */
+ public final static int TASK_FINISHED = 6;
+ /** message event type */
+ public final static int MESSAGE = 7;
+
+ /** The type of this event */
+ private int eventType;
+ /** The cause of this event if appropriate */
+ private Throwable cause = null;
+ /** message associated wuth this event */
+ private String message = null;
+ /** The priority of this message */
+ private int messagePriority;
+
+ /**
+ * Create a build event.
+ *
+ * @param eventType the type of the buildEvent.
+ * @param modelElement the element with which this event is associated
+ */
+ public BuildEvent(ModelElement modelElement, int eventType) {
+ super(modelElement);
+ this.eventType = eventType;
+ }
+
+ /**
+ * Create a build event with an associated exception.
+ *
+ * @param eventType the type of the buildEvent.
+ * @param cause An exception if associated with the event
+ * @param modelElement the element with which this event is associated
+ */
+ public BuildEvent(ModelElement modelElement, int eventType,
+ Throwable cause) {
+ this(modelElement, eventType);
+ this.cause = cause;
+ }
+
+ /**
+ * Create a build event for a message
+ *
+ * @param modelElement the build element with which the event is
+ * associated.
+ * @param message the message associated with this event
+ * @param priority the message priority
+ */
+ public BuildEvent(ModelElement modelElement, String message,
+ int priority) {
+ this(modelElement, MESSAGE);
+ this.message = message;
+ this.messagePriority = priority;
+ }
+
+ /**
+ * Get the type of this event
+ *
+ * @return the event type
+ */
+ public int getEventType() {
+ return eventType;
+ }
+
+ /**
+ * Get the build element involved in this event.
+ *
+ * @return the build element to which this event is associated.
+ */
+ public ModelElement getModelElement() {
+ return (ModelElement)getSource();
+ }
+
+ /**
+ * Returns the logging message. This field will only be set for
+ * "messageLogged" events.
+ *
+ * @return the message value
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /**
+ * Returns the priority of the logging message. This field will only be
+ * set for "messageLogged" events.
+ *
+ * @return the priority value
+ */
+ public int getPriority() {
+ return messagePriority;
+ }
+
+ /**
+ * Returns the exception that was thrown, if any. This field will only
+ * be set for "taskFinished", "targetFinished", and "buildFinished"
+ * events.
+ *
+ * @return the cause value
+ */
+ public Throwable getCause() {
+ return cause;
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEventSupport.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEventSupport.java
new file mode 100755
index 000000000..a5d6d55c2
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEventSupport.java
@@ -0,0 +1,197 @@
+/*
+ * 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.event;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import java.util.List;
+import org.apache.ant.antcore.model.ModelElement;
+
+/**
+ * BuildEventSupport is used by classes which which to send build events to
+ * the BuildListeners
+ *
+ * @author Conor MacNeill
+ * @created 15 January 2002
+ */
+public class BuildEventSupport {
+ /**
+ * The listeners attached to the object which contains this support
+ * object
+ */
+ private List listeners = new ArrayList();
+
+ /**
+ * Gets the listeners of the BuildEventSupport
+ *
+ * @return the listeners value
+ */
+ public Iterator getListeners() {
+ return listeners.iterator();
+ }
+
+ /**
+ * Add a listener
+ *
+ * @param listener the listener to be added
+ */
+ public void addBuildListener(BuildListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * Remove a listener
+ *
+ * @param listener the listener to be removed
+ */
+ public void removeBuildListener(BuildListener listener) {
+ 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
+ *
+ * @param element the build element with which the event is associated
+ */
+ public void fireBuildStarted(ModelElement element) {
+ BuildEvent event = new BuildEvent(element, BuildEvent.BUILD_STARTED);
+ forwardEvent(event);
+ }
+
+ /**
+ * Fir a build finished event
+ *
+ * @param element the build element with which the event is associated
+ * @param cause an exception if there was a failure in the build
+ */
+ public void fireBuildFinished(ModelElement element,
+ Throwable cause) {
+ BuildEvent event = new BuildEvent(element, BuildEvent.BUILD_FINISHED,
+ cause);
+ forwardEvent(event);
+ }
+
+ /**
+ * fire a target started event
+ *
+ * @param element the build element with which the event is associated
+ */
+ public void fireTargetStarted(ModelElement element) {
+ BuildEvent event = new BuildEvent(element, BuildEvent.TARGET_STARTED);
+ forwardEvent(event);
+ }
+
+ /**
+ * fire a target finished event
+ *
+ * @param element the build element with which the event is associated
+ * @param cause an exception if there was a failure in the target's task
+ */
+ public void fireTargetFinished(ModelElement element,
+ Throwable cause) {
+ BuildEvent event = new BuildEvent(element, BuildEvent.TARGET_FINISHED,
+ cause);
+ forwardEvent(event);
+ }
+
+ /**
+ * fire a task started event
+ *
+ * @param element the build element with which the event is associated
+ */
+ public void fireTaskStarted(ModelElement element) {
+ BuildEvent event = new BuildEvent(element, BuildEvent.TASK_STARTED);
+ forwardEvent(event);
+ }
+
+ /**
+ * fire a task finished event
+ *
+ * @param element the build element with which the event is associated
+ * @param cause an exception if there was a failure in the task
+ */
+ public void fireTaskFinished(ModelElement element,
+ Throwable cause) {
+ BuildEvent event = new BuildEvent(element, BuildEvent.TASK_FINISHED,
+ cause);
+ forwardEvent(event);
+ }
+
+ /**
+ * Send a message event
+ *
+ * @param element the build element with which the event is associated
+ * @param message the message to be sent
+ * @param priority the priority of the message
+ */
+ public void fireMessageLogged(ModelElement element,
+ String message, int priority) {
+ BuildEvent event = new BuildEvent(element, message, priority);
+ forwardEvent(event);
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildListener.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildListener.java
new file mode 100755
index 000000000..6e23c2b54
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildListener.java
@@ -0,0 +1,74 @@
+/*
+ * 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.event;
+
+import java.util.EventListener;
+
+/**
+ * Classes that implement this interface will be notified when things
+ * happend during a build.
+ *
+ * @author Conor MacNeill
+ * @created 15 January 2002
+ * @see BuildEvent
+ */
+public interface BuildListener extends EventListener {
+ /**
+ * Process an incoming build event
+ *
+ * @param event the event to be processed.
+ */
+ void processBuildEvent(BuildEvent 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
new file mode 100755
index 000000000..2a402225c
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ClassIntrospector.java
@@ -0,0 +1,132 @@
+/*
+ * 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.lang.reflect.Method;
+import java.util.Map;
+
+/**
+ * Introspects a class and builds a reflector for setting values on
+ * instances of the class
+ *
+ * @author Conor MacNeill
+ * @created 19 January 2002
+ */
+public class ClassIntrospector {
+ /** The reflector that this introspector populates */
+ private Reflector reflector;
+
+ /**
+ * Create a introspector for the bean
+ *
+ * @param bean the class which is introspected
+ * @param converters a collection of converters for converting values
+ * from strings
+ */
+ public ClassIntrospector(final Class bean, Map converters) {
+ reflector = new Reflector();
+
+ Method[] methods = bean.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ final Method m = methods[i];
+ final String name = m.getName();
+ Class returnType = m.getReturnType();
+ Class[] args = m.getParameterTypes();
+
+ if (name.equals("addText")
+ && returnType.equals(Void.TYPE)
+ && args.length == 1
+ && args[0].equals(String.class)) {
+ reflector.setAddTextMethod(m);
+ } else if (name.startsWith("set")
+ && name.length() > 3
+ && returnType.equals(Void.TYPE)
+ && args.length == 1
+ && !args[0].isArray()) {
+ reflector.addAttributeMethod(m, getPropertyName(name, "set"),
+ converters);
+ } else if (name.startsWith("add")
+ && name.length() > 3
+ && returnType.equals(Void.TYPE)
+ && args.length == 1
+ && !args[0].equals(String.class)
+ && !args[0].isArray()
+ && !args[0].isPrimitive()) {
+ reflector.addElementMethod(m, getPropertyName(name, "add"));
+ }
+ }
+ }
+
+ /**
+ * Gets the reflector associed with the class we are introspecting
+ *
+ * @return the reflector
+ */
+ public Reflector getReflector() {
+ return reflector;
+ }
+
+ /**
+ * extract the name of a property from a method name - subtracting a
+ * given prefix.
+ *
+ * @param methodName the name of the method
+ * @param prefix the prefix to be ignored
+ * @return the property name
+ */
+ private String getPropertyName(String methodName, String prefix) {
+ int start = prefix.length();
+ return methodName.substring(start).toLowerCase();
+ }
+}
+
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
new file mode 100755
index 000000000..9ac6b29bf
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java
@@ -0,0 +1,134 @@
+/*
+ * 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.URL;
+import org.apache.ant.common.context.AntContext;
+import org.apache.ant.common.util.AntException;
+import org.apache.ant.common.util.FileUtils;
+import org.apache.ant.antcore.event.BuildEventSupport;
+import org.apache.ant.antcore.model.ModelElement;
+
+/**
+ * This is the core's implementation of the AntContext for all core objects.
+ * Specific subclasses handle types and tasks
+ *
+ * @author Conor MacNeill
+ * @created 20 January 2002
+ */
+public class ExecutionContext extends AntContext {
+ /** The ExecutionFrame containing this context */
+ private ExecutionFrame executionFrame;
+ /** the event support instance used to manage build events */
+ private BuildEventSupport eventSupport;
+
+ /** the model in the build model with which this context is associated */
+ private ModelElement modelElement;
+
+ /** General file utilities */
+ private FileUtils fileUtils = new FileUtils();
+
+ /**
+ * Set the model element associated with this context
+ *
+ * @param modelElement the model element associated with this context
+ */
+ public void setModelElement(ModelElement modelElement) {
+ this.modelElement = modelElement;
+ }
+
+ /**
+ * Initilaise this context's environment
+ *
+ * @param executionFrame the frame containing this context
+ * @param eventSupport the event support instance used to send build
+ * events
+ */
+ public void initEnvironment(ExecutionFrame executionFrame,
+ BuildEventSupport eventSupport) {
+ this.executionFrame = executionFrame;
+ this.eventSupport = eventSupport;
+ }
+
+ /**
+ * 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(modelElement, message, level);
+ }
+
+ /**
+ * Resolve a file according to the base directory of the project
+ * associated with this context
+ *
+ * @param fileName the file name to be resolved.
+ * @return the file resolved to the project's base dir
+ * @exception AntException if the file cannot be resolved
+ */
+ public File resolveFile(String fileName) throws AntException {
+ URL baseURL = executionFrame.getBaseURL();
+ if (!baseURL.getProtocol().equals("file")) {
+ throw new ExecutionException("Cannot resolve name " + fileName
+ + " to a file because the project basedir is not a file: "
+ + baseURL);
+ }
+
+ return fileUtils.resolveFile(fileUtils.normalize(baseURL.getFile()),
+ fileName);
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionException.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionException.java
new file mode 100755
index 000000000..9ede1e711
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionException.java
@@ -0,0 +1,136 @@
+/*
+ * 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.common.util.AntException;
+import org.apache.ant.common.util.Location;
+
+/**
+ * An ExecutionException indicates a problem while executing tasks in a
+ * build
+ *
+ * @author Conor MacNeill
+ * @created 20 January 2002
+ */
+public class ExecutionException extends AntException {
+ /**
+ * Constructs an exception with the given descriptive message.
+ *
+ * @param msg Description of or information about the exception.
+ */
+ public ExecutionException(String msg) {
+ super(msg);
+ }
+
+
+ /**
+ * Constructs an exception with the given descriptive message and a
+ * location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param location Location in the project file where the error occured.
+ */
+ public ExecutionException(String msg, Location location) {
+ super(msg, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Throwable that might have cause this one.
+ */
+ public ExecutionException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause and a location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public ExecutionException(String msg, Throwable cause, Location location) {
+ super(msg, cause, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause.
+ *
+ * @param cause Exception that might have caused this one.
+ */
+ public ExecutionException(Throwable cause) {
+ super(cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause and
+ * a location in a file.
+ *
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public ExecutionException(Throwable cause, Location location) {
+ super(cause, location);
+ }
+
+}
+
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
new file mode 100755
index 000000000..c0d029a32
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFrame.java
@@ -0,0 +1,1017 @@
+/*
+ * 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.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 java.util.StringTokenizer;
+import org.apache.ant.common.converter.Converter;
+import org.apache.ant.common.task.DataType;
+import org.apache.ant.common.task.Task;
+import org.apache.ant.common.task.TaskContainer;
+import org.apache.ant.common.task.TaskException;
+import org.apache.ant.common.util.Location;
+import org.apache.ant.antcore.antlib.AntLibDefinition;
+import org.apache.ant.antcore.antlib.AntLibrary;
+import org.apache.ant.antcore.event.BuildEventSupport;
+import org.apache.ant.antcore.event.BuildListener;
+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;
+
+/**
+ * An ExecutionFrame maintains the state of a project during an execution.
+ * The ExecutionFrame contains the data values set by Ant tasks as they are
+ * executed, including task definitions, property values, etc.
+ *
+ * @author Conor MacNeill
+ * @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();
+ }
+
+ }
+
+ /** 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 expressed as a URL */
+ private URL baseURL;
+
+ /** The Project that this execution frame is processing */
+ private Project project = null;
+
+ /** The referenced frames corresponding to the referenced projects */
+ private Map referencedFrames = new HashMap();
+
+ /** Reflector objects used to configure Tasks from the Task models. */
+ private Map reflectors = new HashMap();
+
+ /**
+ * The context of this execution. This contains all data object's
+ * created by tasks that have been executed
+ */
+ private Map dataValues = new HashMap();
+
+ /**
+ * The available libraries from which taskdefs, typedefs, etc may be
+ * imported
+ */
+ 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();
+
+ /**
+ * Create an Execution Frame for the given project
+ *
+ * @param antLibraries The libraries of tasks and types available to
+ * this frame
+ * @exception ConfigException if a component of the library cannot be
+ * imported
+ */
+ public ExecutionFrame(Map antLibraries) throws ConfigException {
+ this.antLibraries = antLibraries;
+
+ // 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);
+ }
+ }
+ }
+
+ /**
+ * This method will parse a string containing ${value} style property
+ * values into two lists. The first list is a collection of text
+ * fragments, while the other is a set of string property names. Null
+ * entries in the first list indicate a property reference from the
+ * second list.
+ *
+ * @param value the string to be parsed
+ * @param fragments the fragments parsed out of the string
+ * @param propertyRefs the property refs to be replaced
+ * @exception ExecutionException if there is a problem getting property
+ * values
+ */
+ public static void parsePropertyString(String value, List fragments,
+ List propertyRefs)
+ throws ExecutionException {
+ int prev = 0;
+ int pos;
+ while ((pos = value.indexOf("$", prev)) >= 0) {
+ if (pos > 0) {
+ fragments.add(value.substring(prev, pos));
+ }
+
+ if (pos == (value.length() - 1)) {
+ fragments.add("$");
+ prev = pos + 1;
+ } else if (value.charAt(pos + 1) != '{') {
+ fragments.add(value.substring(pos + 1, pos + 2));
+ prev = pos + 2;
+ } else {
+ int endName = value.indexOf('}', pos);
+ if (endName < 0) {
+ throw new ExecutionException("Syntax error in property: "
+ + value);
+ }
+ String propertyName = value.substring(pos + 2, endName);
+ fragments.add(null);
+ propertyRefs.add(propertyName);
+ prev = endName + 1;
+ }
+ }
+
+ if (prev < value.length()) {
+ fragments.add(value.substring(prev));
+ }
+ }
+
+ /**
+ * Set the context loader of the current thread and returns the existing
+ * classloader
+ *
+ * @param newLoader the new context loader
+ * @return the old context loader
+ */
+ private static ClassLoader setContextLoader(ClassLoader newLoader) {
+ Thread thread = Thread.currentThread();
+ ClassLoader currentLoader = thread.getContextClassLoader();
+ thread.setContextClassLoader(newLoader);
+ return currentLoader;
+ }
+
+ /**
+ * Sets the Project of the ExecutionFrame
+ *
+ * @param project The new Project value
+ * @exception ConfigException if any required sub-frames cannot be
+ * created and configured
+ */
+ public void setProject(Project project) throws ConfigException {
+ try {
+ this.project = project;
+ baseURL = new URL(project.getSourceURL(), project.getBase());
+ } catch (MalformedURLException e) {
+ throw new ConfigException("Unable to determine project base dir",
+ e, project.getLocation());
+ }
+
+ referencedFrames = new HashMap();
+
+ for (Iterator i = project.getReferencedProjectNames(); i.hasNext(); ) {
+ String referenceName = (String)i.next();
+ Project referencedProject
+ = project.getReferencedProject(referenceName);
+ ExecutionFrame referencedFrame
+ = new ExecutionFrame(antLibraries);
+ referencedFrame.setProject(referencedProject);
+ referencedFrames.put(referenceName, referencedFrame);
+
+ for (Iterator j = eventSupport.getListeners(); j.hasNext(); ) {
+ BuildListener listener = (BuildListener)j.next();
+ referencedFrame.addBuildListener(listener);
+ }
+ }
+ }
+
+ /**
+ * Set a value in this frame or any of its imported frames
+ *
+ * @param name the name of the value
+ * @param value the actual value
+ * @exception ExecutionException if the value name is invalid
+ */
+ public void setDataValue(String name, Object value)
+ throws ExecutionException {
+ ExecutionFrame frame = getContainingFrame(name);
+ if (frame == this) {
+ dataValues.put(name, value);
+ } else {
+ frame.setDataValue(getNameInFrame(name), value);
+ }
+ }
+
+ /**
+ * Gets the baseURL of the ExecutionFrame
+ *
+ * @return the baseURL value
+ */
+ public URL getBaseURL() {
+ return baseURL;
+ }
+
+ /**
+ * Get a referenced frame by its reference name
+ *
+ * @param referenceName the name under which the frame was imported.
+ * @return the ExecutionFrame asscociated with the given reference name
+ * or null if there is no such project.
+ */
+ public ExecutionFrame getReferencedFrame(String referenceName) {
+ return (ExecutionFrame)referencedFrames.get(referenceName);
+ }
+
+ /**
+ * Get the frames representing referenced projects.
+ *
+ * @return an iterator which returns the referenced ExeuctionFrames..
+ */
+ public Iterator getReferencedFrames() {
+ return referencedFrames.values().iterator();
+ }
+
+ /**
+ * Get the name of an object in its frame
+ *
+ * @param fullname The name of the object
+ * @return the name of the object within its containing frame
+ */
+ public String getNameInFrame(String fullname) {
+ int index = fullname.lastIndexOf(Project.REF_DELIMITER);
+ if (index == -1) {
+ return fullname;
+ }
+ return fullname.substring(index + Project.REF_DELIMITER.length());
+ }
+
+ /**
+ * Get a value from this frame or any imported frame
+ *
+ * @param name the name of the data value - may contain reference
+ * delimiters
+ * @return the data value fetched from the appropriate frame
+ * @exception ExecutionException if the value is not defined
+ */
+ public Object getDataValue(String name) throws ExecutionException {
+ ExecutionFrame frame = getContainingFrame(name);
+ if (frame == this) {
+ return dataValues.get(name);
+ } else {
+ return frame.getDataValue(getNameInFrame(name));
+ }
+ }
+
+ /**
+ * Indicate if a data value has been set
+ *
+ * @param name the name of the data value - may contain reference
+ * delimiters
+ * @return true if the value exists
+ * @exception ExecutionException if the containing frame for the value
+ * does not exist
+ */
+ public boolean isDataValueSet(String name) throws ExecutionException {
+ ExecutionFrame frame = getContainingFrame(name);
+ if (frame == null) {
+ return dataValues.containsKey(name);
+ } else {
+ return frame.isDataValueSet(getNameInFrame(name));
+ }
+ }
+
+ /**
+ * Add a build listener to this execution frame
+ *
+ * @param listener the listener to be added to the frame
+ */
+ public void addBuildListener(BuildListener listener) {
+ for (Iterator i = getReferencedFrames(); i.hasNext(); ) {
+ ExecutionFrame referencedFrame = (ExecutionFrame)i.next();
+ referencedFrame.addBuildListener(listener);
+ }
+ eventSupport.addBuildListener(listener);
+ }
+
+ /**
+ * Remove a build listener from the execution
+ *
+ * @param listener the listener to be removed
+ */
+ public void removeBuildListener(BuildListener listener) {
+ for (Iterator i = getReferencedFrames(); i.hasNext(); ) {
+ ExecutionFrame subFrame = (ExecutionFrame)i.next();
+ subFrame.removeBuildListener(listener);
+ }
+ eventSupport.removeBuildListener(listener);
+ }
+
+ /**
+ * Run the given list of targets
+ *
+ * @param targets a list of target names which are to be evaluated
+ * @exception ExecutionException if there is a problem in the build
+ */
+ public void runBuild(List targets) throws ExecutionException {
+ initialize();
+ if (targets.isEmpty()) {
+ // we just execute the default target if any
+ String defaultTarget = project.getDefaultTarget();
+ if (defaultTarget != null) {
+ executeTarget(defaultTarget);
+ }
+ } else {
+ for (Iterator i = targets.iterator(); i.hasNext(); ) {
+ executeTarget((String)i.next());
+ }
+ }
+ }
+
+ /**
+ * Execute the tasks of a target in this frame with the given name
+ *
+ * @param targetName the name of the target whose tasks will be
+ * evaluated
+ * @exception ExecutionException if there is a problem executing the
+ * tasks of the target
+ */
+ public void executeTarget(String targetName) throws ExecutionException {
+ // 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 {
+ List dependencyOrder = project.getTargetDependencies(targetName);
+ for (Iterator i = dependencyOrder.iterator(); i.hasNext(); ) {
+ String fullTargetName = (String)i.next();
+ ExecutionFrame frame = getContainingFrame(fullTargetName);
+ String localTargetName = getNameInFrame(fullTargetName);
+ frame.executeTargetTasks(localTargetName);
+ }
+ } catch (ConfigException e) {
+ throw new ExecutionException(e);
+ }
+ }
+
+ /**
+ * Run the tasks returned by the given iterator
+ *
+ * @param taskIterator the iterator giving the tasks to execute
+ * @exception ExecutionException if there is execution problem while
+ * executing tasks
+ */
+ public void executeTasks(Iterator taskIterator) throws ExecutionException {
+ while (taskIterator.hasNext()) {
+ Throwable failureCause = null;
+ BuildElement model = (BuildElement)taskIterator.next();
+ // what sort of element is this.
+ ImportInfo importInfo
+ = (ImportInfo)definitions.get(model.getType());
+ if (importInfo == null) {
+ throw new ExecutionException("There is no definition for the "
+ + model.getType() + " element", model.getLocation());
+ }
+
+ try {
+ if (importInfo.getDefinitionType() == AntLibrary.TASKDEF) {
+ TaskContext taskContext = configureTask(model);
+ eventSupport.fireTaskStarted(model);
+
+ ClassLoader currentLoader
+ = setContextLoader(taskContext.getLoader());
+ taskContext.execute();
+ setContextLoader(currentLoader);
+ releaseTaskContext(taskContext);
+ } else {
+ // typedef
+ String typeId = model.getAspectValue(ANT_ASPECT, "id");
+ Object typeInstance = configureType(model.getType(), model);
+ if (typeId != null) {
+ setDataValue(typeId, typeInstance);
+ }
+ }
+
+ } catch (TaskException te) {
+ ExecutionException e
+ = new ExecutionException(te, te.getLocation());
+ if (e.getLocation() == null
+ || e.getLocation() == Location.UNKNOWN_LOCATION) {
+ e.setLocation(model.getLocation());
+ }
+ failureCause = e;
+ throw e;
+ } catch (RuntimeException e) {
+ failureCause = e;
+ throw e;
+ } finally {
+ eventSupport.fireTaskFinished(model, failureCause);
+ }
+ }
+
+ }
+
+ /**
+ * Execute the given target's tasks. The target must be local to this
+ * frame's project
+ *
+ * @param targetName the name of the target within this frame that is to
+ * be executed.
+ * @exception ExecutionException if there is a problem executing tasks
+ */
+ public void executeTargetTasks(String targetName)
+ throws ExecutionException {
+ Throwable failureCause = null;
+ Target target = project.getTarget(targetName);
+ try {
+ Iterator taskIterator = target.getTasks();
+ eventSupport.fireTargetStarted(target);
+ executeTasks(taskIterator);
+ } catch (ExecutionException e) {
+ if (e.getLocation() == null
+ || e.getLocation() == Location.UNKNOWN_LOCATION) {
+ e.setLocation(target.getLocation());
+ }
+ failureCause = e;
+ throw e;
+ } catch (RuntimeException e) {
+ failureCause = e;
+ throw e;
+ } finally {
+ eventSupport.fireTargetFinished(target, failureCause);
+ }
+ }
+
+
+ /**
+ * Initialize the frame by executing the project level tasks if any
+ *
+ * @exception ExecutionException if the top level tasks of the frame
+ * failed
+ */
+ public void initialize() throws ExecutionException {
+ for (Iterator i = getReferencedFrames(); i.hasNext(); ) {
+ ExecutionFrame referencedFrame = (ExecutionFrame)i.next();
+ referencedFrame.initialize();
+ }
+// Iterator taskIterator = project.getTasks();
+// executeTopLevelTasks(taskIterator);
+ }
+
+ /**
+ * Replace ${} style constructions in the given value with the string
+ * value of the corresponding data types.
+ *
+ * @param value the string to be scanned for property references.
+ * @return the string with all property references replaced
+ * @exception ExecutionException if any of the properties do not exist
+ */
+ public String replacePropertyRefs(String value) throws ExecutionException {
+ if (value == null) {
+ return null;
+ }
+
+ List fragments = new ArrayList();
+ List propertyRefs = new ArrayList();
+ parsePropertyString(value, fragments, propertyRefs);
+
+ StringBuffer sb = new StringBuffer();
+ Iterator i = fragments.iterator();
+ Iterator j = propertyRefs.iterator();
+ while (i.hasNext()) {
+ String fragment = (String)i.next();
+ if (fragment == null) {
+ String propertyName = (String)j.next();
+ if (!isDataValueSet(propertyName)) {
+ throw new ExecutionException("Property " + propertyName
+ + " has not been set");
+ }
+ fragment = getDataValue(propertyName).toString();
+ }
+ sb.append(fragment);
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Gets the reflector for the given class
+ *
+ * @param c the class for which the reflector is desired
+ * @return the reflector
+ */
+ private Reflector getReflector(Class c) {
+ if (reflectors.containsKey(c)) {
+ return (Reflector)reflectors.get(c);
+ }
+ ClassIntrospector introspector = new ClassIntrospector(c, converters);
+ Reflector reflector = introspector.getReflector();
+ reflectors.put(c, reflector);
+ return reflector;
+ }
+
+
+ /**
+ * Get the execution frame which contains, directly, the named target
+ * where the name is relative to this frame
+ *
+ * @param targetName The name of the target
+ * @return the execution frame for the project that contains the given
+ * target
+ */
+ private ExecutionFrame getContainingFrame(String targetName) {
+ int index = targetName.lastIndexOf(Project.REF_DELIMITER);
+ if (index == -1) {
+ return this;
+ }
+
+ ExecutionFrame currentFrame = this;
+ String relativeName = targetName.substring(0, index);
+ StringTokenizer tokenizer
+ = new StringTokenizer(relativeName, Project.REF_DELIMITER);
+ while (tokenizer.hasMoreTokens()) {
+ String refName = tokenizer.nextToken();
+ currentFrame = currentFrame.getReferencedFrame(refName);
+ if (currentFrame == null) {
+ return null;
+ }
+ }
+
+ return currentFrame;
+ }
+
+ /**
+ * Add the converters from the given library to those managed by this
+ * frame.
+ *
+ * @param library the library from which the converters are required
+ * @exception ConfigException if a converter defined in the library
+ * cannot be instantiated
+ */
+ private void addLibraryConverters(AntLibrary library)
+ throws ConfigException {
+ if (!library.hasConverters()) {
+ return;
+ }
+
+ String className = null;
+ try {
+ 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 ConfigException("The converter class "
+ + converterClass.getName()
+ + " does not implement the Converter interface");
+ }
+ Converter converter = (Converter)converterClass.newInstance();
+ ExecutionContext context = new ExecutionContext();
+ context.initEnvironment(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 ConfigException("Converter Class " + className
+ + " was not found", e);
+ } catch (NoClassDefFoundError e) {
+ throw new ConfigException("Could not load a dependent class ("
+ + e.getMessage() + ") for converter " + className);
+ } catch (InstantiationException e) {
+ throw new ConfigException("Unable to instantiate converter class "
+ + className, e);
+ } catch (IllegalAccessException e) {
+ throw new ConfigException("Unable to access converter class "
+ + className, e);
+ }
+ }
+
+ /**
+ * Configure an element according to the given model.
+ *
+ * @param element the object to be configured
+ * @param model the BuildElement describing the object in the build file
+ * @exception ExecutionException if the element cannot be configured
+ * @exception TaskException if a nested task has a problem
+ */
+ private void configureElement(Object element, BuildElement model)
+ throws ExecutionException, TaskException {
+
+ Reflector reflector = getReflector(element.getClass());
+
+ // start by setting the attributes of this element
+ for (Iterator i = model.getAttributeNames(); i.hasNext(); ) {
+ String attributeName = (String)i.next();
+ String attributeValue = model.getAttributeValue(attributeName);
+ reflector.setAttribute(element, attributeName,
+ replacePropertyRefs(attributeValue));
+ }
+ String modelText = model.getText().trim();
+ if (modelText.length() != 0) {
+ reflector.addText(element, replacePropertyRefs(modelText));
+ }
+
+ // now do the nested elements
+ for (Iterator i = model.getNestedElements(); i.hasNext(); ) {
+ BuildElement nestedElementModel = (BuildElement)i.next();
+ String nestedElementName = nestedElementModel.getType();
+
+ ImportInfo info = (ImportInfo)definitions.get(nestedElementName);
+ if (element instanceof TaskContainer
+ && info != null
+ && info.getDefinitionType() == AntLibrary.TASKDEF
+ && !reflector.supportsNestedElement(nestedElementName)) {
+ // it is a nested task
+ TaskContext nestedContext
+ = configureTask(nestedElementModel);
+ TaskContainer container = (TaskContainer)element;
+ // XXX what should we be adding - need to understand container
+ // method of executing tasks
+ container.addTask(nestedContext.getTask());
+ } else {
+ Object nestedElement = createNestedElement(reflector, element,
+ nestedElementModel);
+ reflector.addElement(element, nestedElementName, nestedElement);
+ }
+ }
+ }
+
+ /**
+ * Create a nested element
+ *
+ * @param reflector The reflector instance for the container element
+ * @param element the container element in which the nested element will
+ * be created
+ * @param model the model of the nested element
+ * @return a configured nested element
+ * @exception ExecutionException if the nested element cannot be created
+ * @exception TaskException if the nested element has a problem
+ */
+ private Object createNestedElement(Reflector reflector, Object element,
+ BuildElement model)
+ throws ExecutionException, TaskException {
+
+ String nestedElementName = model.getType();
+ if (!reflector.supportsNestedElement(nestedElementName)) {
+ throw new ExecutionException("The element name " + nestedElementName
+ + " is not a supported nested element of "
+ + element.getClass().getName());
+ }
+ Class nestedType = reflector.getType(nestedElementName);
+
+ // is there a polymorph indicator - look in Ant aspects
+ String typeName = model.getAspectValue(ANT_ASPECT, "type");
+ String refId = model.getAspectValue(ANT_ASPECT, "refid");
+ if (refId != null && typeName != null) {
+ throw new ExecutionException("Only one of " + ANT_ASPECT
+ + ":type and " + ANT_ASPECT
+ + ":refid may be specified at a time", model.getLocation());
+ }
+
+ Object typeInstance = null;
+ if (typeName != null) {
+ // the build file has specified the actual type of the element.
+ // we need to look up that type and use it
+ typeInstance = configureType(typeName, model);
+ } else if (refId != null) {
+ // We have a reference to an existing instance. Need to check if
+ // it is compatible with the type expected by the nested element's
+ // adder method
+ typeInstance = getDataValue(refId);
+ if (model.getAttributeNames().hasNext() ||
+ model.getNestedElements().hasNext() ||
+ model.getText().length() != 0) {
+ throw new ExecutionException("Element <" + nestedElementName
+ + "> is defined by reference and hence may not specify "
+ + "any attributes, nested elements or content",
+ model.getLocation());
+ }
+ if (typeInstance == null) {
+ throw new ExecutionException("The given ant:refid value '"
+ + refId + "' is not defined", model.getLocation());
+ }
+ } else {
+ // We need to create an instance of the class expected by the nested
+ // element's adder method if that is possible
+ if (nestedType.isInterface()) {
+ throw new ExecutionException("No element can be created for "
+ + "nested element <" + nestedElementName + ">. Please "
+ + "provide a value by reference or specify the value type",
+ model.getLocation());
+ }
+
+ typeInstance = createTypeInstance(nestedType, model);
+ }
+
+ // is the typeInstance compatible with the type expected
+ // by the element's add method
+ if (!nestedType.isInstance(typeInstance)) {
+ if (refId != null) {
+ throw new ExecutionException("The value specified by refId "
+ + refId + " is not compatible with the <"
+ + nestedElementName + "> nested element",
+ model.getLocation());
+ } else if (typeName != null) {
+ throw new ExecutionException("The type "
+ + typeName + " is not compatible with the <"
+ + nestedElementName + "> nested element",
+ model.getLocation());
+ }
+ }
+ return typeInstance;
+ }
+
+
+ /**
+ * Create a Task and configure it according to the given model.
+ *
+ * @param model the model for the task from the build file
+ * @return an execution context for managing the task
+ * @exception ExecutionException if there is a problem configuring the
+ * task
+ * @exception TaskException if the task or a nested task has a problem
+ */
+ private TaskContext configureTask(BuildElement model)
+ throws ExecutionException, TaskException {
+
+ String taskType = model.getType();
+ ImportInfo taskDefInfo = (ImportInfo)definitions.get(taskType);
+ if (taskDefInfo == null
+ || taskDefInfo.getDefinitionType() != AntLibrary.TASKDEF) {
+ throw new ExecutionException("There is no defintion for a "
+ + "task of type <" + taskType + ">", model.getLocation());
+ }
+
+ String className = taskDefInfo.getClassName();
+ AntLibrary antLibrary = taskDefInfo.getAntLibrary();
+
+ try {
+ ClassLoader taskClassLoader = antLibrary.getClassLoader();
+ Class elementClass
+ = Class.forName(className, true, taskClassLoader);
+ Object element = elementClass.newInstance();
+ Task task = null;
+ if (element instanceof Task) {
+ // create a Task context for the Task
+ task = (Task)element;
+ } else {
+ task = new TaskAdapter(taskType, element);
+ }
+
+ // set the context loader while configuring the element
+ ClassLoader currentLoader = setContextLoader(taskClassLoader);
+ TaskContext taskContext = allocateTaskContext();
+ taskContext.init(taskClassLoader, task, model);
+ configureElement(element, model);
+ setContextLoader(currentLoader);
+ return taskContext;
+ } catch (ClassNotFoundException e) {
+ throw new ExecutionException("Class " + className
+ + " for task <" + taskType + "> was not found", e,
+ model.getLocation());
+ } catch (NoClassDefFoundError e) {
+ throw new ExecutionException("Could not load a dependent class ("
+ + e.getMessage() + ") for task " + taskType);
+ } catch (InstantiationException e) {
+ throw new ExecutionException("Unable to instantiate task class "
+ + className + " for task <" + taskType + ">",
+ e, model.getLocation());
+ } catch (IllegalAccessException e) {
+ throw new ExecutionException("Unable to access task class "
+ + className + " for task <" + taskType + ">",
+ e, model.getLocation());
+ }
+ }
+
+ /**
+ * Configure a type instance from the given build model. The name given
+ * may not match the name in the model type value. This allows the
+ * caller to provide a polymorphic type for the type model
+ *
+ * @param typeName the name of the type which should be created
+ * @param model the model describing the type
+ * @return an instance of the type, configured from the model
+ * @exception ExecutionException if the type could not be created
+ * @exception TaskException there was a problem within the type
+ */
+ private Object configureType(String typeName, BuildElement model)
+ throws ExecutionException, TaskException {
+ ImportInfo typeDefInfo = (ImportInfo)definitions.get(typeName);
+ if (typeDefInfo == null
+ || typeDefInfo.getDefinitionType() != AntLibrary.TYPEDEF) {
+ throw new ExecutionException("There is no defintion for a "
+ + "type <" + typeName + ">", model.getLocation());
+ }
+
+ String className = typeDefInfo.getClassName();
+ AntLibrary antLibrary = typeDefInfo.getAntLibrary();
+
+ try {
+ ClassLoader typeClassLoader = antLibrary.getClassLoader();
+ Class typeClass
+ = Class.forName(className, true, typeClassLoader);
+
+ ClassLoader currentLoader = setContextLoader(typeClassLoader);
+ Object typeInstance = createTypeInstance(typeClass, model);
+ setContextLoader(currentLoader);
+
+ return typeInstance;
+ } catch (ClassNotFoundException e) {
+ throw new ExecutionException("Class " + className
+ + " for type <" + typeName + "> was not found", e,
+ model.getLocation());
+ } catch (NoClassDefFoundError e) {
+ throw new ExecutionException("Could not load a dependent class ("
+ + e.getMessage() + ") for type " + typeName);
+ }
+ }
+
+ /**
+ * Create an instance of a type given its required class
+ *
+ * @param typeClass the class from which the instance should be created
+ * @param model the model describing the required configuration of the
+ * instance
+ * @return an instance of the given class appropriately configured
+ * @exception ExecutionException if there is a problem creating the type
+ * instance
+ * @exception TaskException if there is a problem configuring the type
+ * instance.
+ */
+ private Object createTypeInstance(Class typeClass, BuildElement model)
+ throws ExecutionException, TaskException {
+ try {
+ Object typeInstance = typeClass.newInstance();
+ if (typeInstance instanceof DataType) {
+ DataType dataType = (DataType)typeInstance;
+ TypeContext typeContext = new TypeContext();
+ typeContext.initEnvironment(this, eventSupport);
+ typeContext.init(dataType, model);
+ }
+ configureElement(typeInstance, model);
+ return typeInstance;
+ } catch (InstantiationException e) {
+ throw new ExecutionException("Unable to instantiate type class "
+ + typeClass.getName() + " for type <" + model.getType() + ">",
+ e, model.getLocation());
+ } catch (IllegalAccessException e) {
+ throw new ExecutionException("Unable to access type class "
+ + typeClass.getName() + " for type <" + model.getType() + ">",
+ e, model.getLocation());
+ }
+ }
+
+
+ /**
+ * Allocate a context for use
+ *
+ * @return ExecutionContext for use
+ */
+ private TaskContext allocateTaskContext() {
+ TaskContext context = new TaskContext();
+ context.initEnvironment(this, eventSupport);
+ return context;
+ }
+
+ /**
+ * Release a context. Any associated tasks are destroyed.
+ *
+ * @param context the cotext to be released
+ */
+ private void releaseTaskContext(TaskContext context) {
+ context.destroy();
+ }
+
+
+ /**
+ * Import a complete library into this frame
+ *
+ * @param libraryId The id of the library to be imported
+ * @exception ConfigException if the library cannot be imported
+ */
+ private void importLibrary(String libraryId) throws ConfigException {
+ AntLibrary library = (AntLibrary)antLibraries.get(libraryId);
+ 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);
+ }
+}
+
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
new file mode 100755
index 000000000..18e07a296
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java
@@ -0,0 +1,417 @@
+/*
+ * 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.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ant.common.util.AntException;
+import org.apache.ant.antcore.antlib.AntLibHandler;
+import org.apache.ant.antcore.antlib.AntLibrary;
+import org.apache.ant.antcore.antlib.AntLibrarySpec;
+import org.apache.ant.antcore.config.AntConfig;
+import org.apache.ant.antcore.config.AntConfigHandler;
+import org.apache.ant.antcore.event.BuildEventSupport;
+import org.apache.ant.antcore.event.BuildListener;
+import org.apache.ant.antcore.model.Project;
+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.init.InitUtils;
+import org.apache.ant.init.InitConfig;
+import org.apache.ant.init.LoaderUtils;
+
+/**
+ * The ExecutionManager is used to manage the execution of a build. The
+ * Execution manager is responsible for loading the Ant task libraries,
+ * creating ExecutionFrames for each project that is part of the build and
+ * then executing the tasks within those Execution Frames.
+ *
+ * @author Conor MacNeill
+ * @created 12 January 2002
+ */
+public class ExecutionManager {
+ /** The AntLibraries built from Ant's Populated Task Libraries. */
+ private Map antLibraries = new HashMap();
+
+ /** BuildEvent support used to fire events and manage listeners */
+ private BuildEventSupport eventSupport = new BuildEventSupport();
+
+ /** The Execution Frame for the top level project being executed */
+ private ExecutionFrame mainFrame;
+
+ /**
+ * Create an ExecutionManager. When an ExecutionManager is created, it
+ * loads the ant libraries which are installed in the Ant lib/task
+ * directory.
+ *
+ * @param initConfig Ant's configuration - classloaders etc
+ * @exception ConfigException if there is a problem with one of Ant's
+ * tasks
+ */
+ public ExecutionManager(InitConfig initConfig)
+ throws ConfigException {
+ Map librarySpecs = new HashMap();
+
+ AntConfig userConfig = getAntConfig(initConfig.getUserConfigArea());
+ AntConfig systemConfig = getAntConfig(initConfig.getSystemConfigArea());
+
+ AntConfig config = systemConfig;
+ if (config == null) {
+ config = userConfig;
+ } else if (userConfig != null) {
+ config.merge(userConfig);
+ }
+
+ try {
+ // start by loading the task libraries
+ URL taskBaseURL = new URL(initConfig.getLibraryURL(), "antlibs");
+ addAntLibraries(librarySpecs, taskBaseURL);
+
+ if (config != null) {
+ // Now add in any found in the dirs specified in
+ // the config files
+ for (Iterator i = config.getTaskDirLocations(); i.hasNext(); ) {
+ // try file first
+ String taskDirString = (String)i.next();
+ File taskDir = new File(taskDirString);
+ if (!taskDir.exists()) {
+ URL taskDirURL = new URL(taskDirString);
+ addAntLibraries(librarySpecs, taskDirURL);
+ } else {
+ addAntLibraries(librarySpecs,
+ InitUtils.getFileURL(taskDir));
+ }
+ }
+ }
+
+ configLibraries(initConfig, librarySpecs);
+
+ if (config != null) {
+ // now add any additional library Paths specified by the config
+ for (Iterator i = config.getLibraryIds(); i.hasNext(); ) {
+ String libraryId = (String)i.next();
+ if (antLibraries.containsKey(libraryId)) {
+ AntLibrary antLib
+ = (AntLibrary)antLibraries.get(libraryId);
+ List pathList = config.getLibraryPathList(libraryId);
+ for (Iterator j = pathList.iterator(); j.hasNext(); ) {
+ URL pathElementURL = (URL)j.next();
+ antLib.addLibraryURL(pathElementURL);
+ }
+ }
+ }
+ }
+
+ mainFrame = new ExecutionFrame(antLibraries);
+ } catch (MalformedURLException e) {
+ throw new ConfigException("Unable to load Ant libraries", e);
+ }
+ }
+
+ /**
+ * Run a build, executing each of the targets on the given project
+ *
+ * @param project The project model on which to run the build
+ * @param targets The list of target names
+ */
+ public void runBuild(Project project, List targets) {
+ Throwable buildFailureCause = null;
+ try {
+ // start by validating the project we have been given.
+ project.validate(null);
+ mainFrame.setProject(project);
+
+ eventSupport.fireBuildStarted(project);
+ mainFrame.runBuild(targets);
+ } catch (RuntimeException e) {
+ buildFailureCause = e;
+ throw e;
+ } catch (AntException e) {
+ buildFailureCause = e;
+ } finally {
+ eventSupport.fireBuildFinished(project, buildFailureCause);
+ }
+ }
+
+ /**
+ * Add a build listener to the build
+ *
+ * @param listener the listener to be added to the build
+ */
+ public void addBuildListener(BuildListener listener) {
+ eventSupport.addBuildListener(listener);
+ mainFrame.addBuildListener(listener);
+ }
+
+ /**
+ * Remove a build listener from the execution
+ *
+ * @param listener the listener to be removed
+ */
+ public void removeBuildListener(BuildListener listener) {
+ eventSupport.removeBuildListener(listener);
+ mainFrame.removeBuildListener(listener);
+ }
+
+ /**
+ * Get the AntConfig from the given config area if it is available
+ *
+ * @param configArea the config area from which the config may be read
+ * @return the AntConfig instance representing the config info read in
+ * from the config area. May be null if the AntConfig is not
+ * present
+ * @exception ConfigException if the URL for the config file cannotbe
+ * formed.
+ */
+ private AntConfig getAntConfig(URL configArea) throws ConfigException {
+ try {
+ URL configFileURL = new URL(configArea, "antconfig.xml");
+
+ ParseContext context = new ParseContext();
+ AntConfigHandler configHandler = new AntConfigHandler();
+
+ context.parse(configFileURL, "antconfig", configHandler);
+
+ return configHandler.getAntConfig();
+ } catch (MalformedURLException e) {
+ throw new ConfigException("Unable to form URL to read config from "
+ + configArea, e);
+ } catch (XMLParseException e) {
+ if (!(e.getCause() instanceof FileNotFoundException)) {
+ throw new ConfigException("Unable to parse config file from "
+ + configArea, e);
+ }
+ // ignore missing config files
+ return null;
+ }
+ }
+
+ /**
+ * Add all the Ant libraries that can be found at the given URL
+ *
+ * @param librarySpecs A map to which additional library specifications
+ * are added.
+ * @param taskBaseURL 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
+ */
+ private void addAntLibraries(Map librarySpecs, URL taskBaseURL)
+ throws MalformedURLException, ConfigException {
+ URL[] taskURLs = LoaderUtils.getLoaderURLs(taskBaseURL, null,
+ new String[]{".tsk", ".jar", ".zip"});
+
+ if (taskURLs == null) {
+ return;
+ }
+
+ // parse each task library to get its library definition
+ for (int i = 0; i < taskURLs.length; ++i) {
+ URL libURL = new URL("jar:" + taskURLs[i]
+ + "!/META-INF/antlib.xml");
+ try {
+ AntLibrarySpec antLibrarySpec = parseLibraryDef(libURL);
+ if (antLibrarySpec != null) {
+ String libraryId = antLibrarySpec.getLibraryId();
+ if (librarySpecs.containsKey(libraryId)) {
+ throw new ConfigException("Found more than one "
+ + "copy of library with id = " + libraryId +
+ " (" + taskURLs[i] + ")");
+ }
+ antLibrarySpec.setLibraryURL(taskURLs[i]);
+ librarySpecs.put(libraryId, antLibrarySpec);
+ }
+ } catch (XMLParseException e) {
+ Throwable t = e.getCause();
+ // 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 "
+ + taskURLs[i], e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Configures the Ant Libraries. Configuration of an Ant Library
+ * involves resolving any dependencies between libraries and then
+ * creating the class loaders for the library
+ *
+ * @param initConfig the Ant initialized config
+ * @param librarySpecs the loaded specifications of the Ant libraries
+ * @exception ConfigException if a library cannot be configured from the
+ * given specification
+ */
+ private void configLibraries(InitConfig initConfig, Map librarySpecs)
+ throws ConfigException {
+ Set configured = new HashSet();
+ CircularDependencyChecker configuring
+ = new CircularDependencyChecker("configuring Ant libraries");
+ for (Iterator i = librarySpecs.keySet().iterator(); i.hasNext(); ) {
+ String libraryId = (String)i.next();
+ if (!configured.contains(libraryId)) {
+ configLibrary(initConfig, librarySpecs, libraryId,
+ configured, configuring);
+ }
+ }
+ }
+
+ /**
+ * Configure a library from a specification and the Ant init config.
+ *
+ * @param initConfig Ant's init config passed in from the front end.
+ * @param librarySpecs the library specs from which this library is to
+ * be configured.
+ * @param libraryId the global identifier for the library
+ * @param configured the set of libraries which have been configured
+ * already
+ * @param configuring A circualr dependency chcker for library
+ * dependencies.
+ * @exception ConfigException if the library cannot be configured.
+ */
+ private void configLibrary(InitConfig initConfig, Map librarySpecs,
+ String libraryId, Set configured,
+ CircularDependencyChecker configuring)
+ throws ConfigException {
+
+ try {
+
+ configuring.visitNode(libraryId);
+
+ AntLibrarySpec librarySpec
+ = (AntLibrarySpec)librarySpecs.get(libraryId);
+ String extendsId = librarySpec.getExtendsLibraryId();
+ if (extendsId != null) {
+ if (!configured.contains(extendsId)) {
+ if (!librarySpecs.containsKey(extendsId)) {
+ throw new ConfigException("Could not find library, "
+ + extendsId + ", upon which library "
+ + libraryId + " depends");
+ }
+ configLibrary(initConfig, librarySpecs, extendsId,
+ configured, configuring);
+ }
+ }
+
+ // now create the library for the specification
+ AntLibrary antLibrary = new AntLibrary(librarySpec);
+
+ // determine the URLs required for this task. These are the
+ // task URL itself, the XML parser URLs if required, the
+ // tools jar URL if required
+ List urlsList = new ArrayList();
+
+ if (librarySpec.getLibraryURL() != null) {
+ urlsList.add(librarySpec.getLibraryURL());
+ }
+ if (librarySpec.isToolsJarRequired()
+ && initConfig.getToolsJarURL() != null) {
+ urlsList.add(initConfig.getToolsJarURL());
+ }
+
+ URL[] parserURLs = initConfig.getParserURLs();
+ if (librarySpec.usesAntXML()) {
+ for (int i = 0; i < parserURLs.length; ++i) {
+ urlsList.add(parserURLs[i]);
+ }
+ }
+
+ for (Iterator i = urlsList.iterator(); i.hasNext(); ) {
+ antLibrary.addLibraryURL((URL)i.next());
+ }
+ if (extendsId != null) {
+ AntLibrary extendsLibrary
+ = (AntLibrary)antLibraries.get(extendsId);
+ antLibrary.setExtendsLibrary(extendsLibrary);
+ }
+ antLibrary.setParentLoader(initConfig.getCommonLoader());
+ antLibraries.put(libraryId, antLibrary);
+ configuring.leaveNode(libraryId);
+ } catch (CircularDependencyException e) {
+ throw new ConfigException(e);
+ }
+ }
+
+
+ /**
+ * Read an Ant library definition from a URL
+ *
+ * @param antlibURL the URL of the library definition
+ * @return the AntLibrary specification read from the library XML
+ * definition
+ * @exception XMLParseException if the library cannot be parsed
+ */
+ private AntLibrarySpec parseLibraryDef(URL antlibURL)
+ throws XMLParseException {
+ ParseContext context = new ParseContext();
+ AntLibHandler libHandler = new AntLibHandler();
+
+ context.parse(antlibURL, "antlib", libHandler);
+
+ return libHandler.getAntLibrarySpec();
+ }
+
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Reflector.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Reflector.java
new file mode 100755
index 000000000..17168526b
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Reflector.java
@@ -0,0 +1,344 @@
+/*
+ * 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.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.ant.common.converter.ConversionException;
+import org.apache.ant.common.converter.Converter;
+import org.apache.ant.common.task.TaskException;
+
+/**
+ * A reflector is used to set attributes and add nested elements to an
+ * instance of an object using reflection. It is the result of class
+ * introspection.
+ *
+ * @author Conor MacNeill
+ * @created 19 January 2002
+ */
+public class Reflector {
+
+ /**
+ * AttributeSetter classes are created at introspection time for each
+ * setter method a class provides and for which a conversion from a
+ * String value is available.
+ *
+ * @author Conor MacNeill
+ * @created 19 January 2002
+ */
+ private interface AttributeSetter {
+ /**
+ * Set the attribute value on an object
+ *
+ * @param obj the object on which the set method is to be invoked
+ * @param value the string representation of the value
+ * @exception InvocationTargetException if the method cannot be
+ * invoked
+ * @exception IllegalAccessException if the method cannot be invoked
+ * @exception ExecutionException if the conversion of the value
+ * fails
+ * @exception ConversionException if the string value cannot be
+ * converted to the required type
+ */
+ void set(Object obj, String value)
+ throws InvocationTargetException, IllegalAccessException,
+ ExecutionException, ConversionException;
+ }
+
+ /**
+ * An element adder is used to add an instance of an element to an of an
+ * object. The object being added will have been fully configured by Ant
+ * prior to calling this method.
+ *
+ * @author Conor MacNeill
+ * @created 19 January 2002
+ */
+ private interface ElementAdder {
+ /**
+ * Add an object to the this container object
+ *
+ * @param container the object to which the element is the be added
+ * @param obj an instance of the nested element
+ * @exception InvocationTargetException if the method cannot be
+ * invoked
+ * @exception IllegalAccessException if the method cannot be invoked
+ */
+ void add(Object container, Object obj)
+ throws InvocationTargetException, IllegalAccessException;
+ }
+
+
+ /** The method used to add content to the element */
+ private Method addTextMethod;
+
+ /** the list of attribute setters indexed by their property name */
+ private Map attributeSetters = new HashMap();
+
+ /**
+ * A list of the Java class or interface accetpted by each element adder
+ * indexed by the element name
+ */
+ private Map elementTypes = new HashMap();
+
+ /** the list of element adders indexed by their element names */
+ private Map elementAdders = new HashMap();
+
+ /**
+ * Set an attribute value on an object
+ *
+ * @param obj the object on which the value is being set
+ * @param attributeName the name of the attribute
+ * @param value the string represenation of the attribute's value
+ * @exception ExecutionException if the object does not support the
+ * attribute
+ * @exception TaskException if the object has a problem setting the
+ * value
+ */
+ public void setAttribute(Object obj, String attributeName,
+ String value)
+ throws ExecutionException, TaskException {
+ AttributeSetter as
+ = (AttributeSetter)attributeSetters.get(attributeName);
+ if (as == null) {
+ throw new ExecutionException("Class " + obj.getClass().getName() +
+ " doesn't support the \"" + attributeName + "\" attribute");
+ }
+ try {
+ as.set(obj, value);
+ } catch (IllegalAccessException e) {
+ // impossible as getMethods should only return public methods
+ throw new ExecutionException(e);
+ } catch (ConversionException e) {
+ throw new ExecutionException(e);
+ } catch (InvocationTargetException ite) {
+ Throwable t = ite.getTargetException();
+ if (t instanceof TaskException) {
+ throw (TaskException)t;
+ }
+ throw new ExecutionException(t);
+ }
+ }
+
+ /**
+ * Set the method used to add content to the element
+ *
+ * @param addTextMethod the new addTextMethod value
+ */
+ public void setAddTextMethod(Method addTextMethod) {
+ this.addTextMethod = addTextMethod;
+ }
+
+ /**
+ * Get the type of the given nested element
+ *
+ * @param elementName the nested element whose type is desired
+ * @return the class instance representing the type of the element adder
+ */
+ public Class getType(String elementName) {
+ return (Class)elementTypes.get(elementName);
+ }
+
+ /**
+ * Adds PCDATA to the element
+ *
+ * @param obj the instance whose content is being provided
+ * @param text the required content
+ * @exception ExecutionException if the object does not support content
+ * @exception TaskException if the object has a problem setting the
+ * content
+ */
+ public void addText(Object obj, String text)
+ throws ExecutionException, TaskException {
+
+ if (addTextMethod == null) {
+ throw new ExecutionException("Class " + obj.getClass().getName() +
+ " doesn't support content");
+ }
+ try {
+ addTextMethod.invoke(obj, new String[]{text});
+ } catch (IllegalAccessException ie) {
+ // impossible as getMethods should only return public methods
+ throw new ExecutionException(ie);
+ } catch (InvocationTargetException ite) {
+ Throwable t = ite.getTargetException();
+ if (t instanceof TaskException) {
+ throw (TaskException)t;
+ }
+ throw new ExecutionException(t);
+ }
+ }
+
+ /**
+ * Add an element to the given object
+ *
+ * @param obj The object to which the element is being added
+ * @param elementName the name of the element
+ * @param value the object to be added - the nested element
+ * @exception ExecutionException if the object does not support content
+ * @exception TaskException if the object has a problem setting the
+ * content
+ */
+ public void addElement(Object obj, String elementName, Object value)
+ throws ExecutionException, TaskException {
+ ElementAdder ea = (ElementAdder)elementAdders.get(elementName);
+ if (ea == null) {
+ throw new ExecutionException("Class " + obj.getClass().getName() +
+ " doesn't support the \"" + elementName + "\" nested element");
+ }
+ try {
+ ea.add(obj, value);
+ } catch (IllegalAccessException ie) {
+ // impossible as getMethods should only return public methods
+ throw new ExecutionException(ie);
+ } catch (InvocationTargetException ite) {
+ Throwable t = ite.getTargetException();
+ if (t instanceof TaskException) {
+ throw (TaskException)t;
+ }
+ throw new ExecutionException(t);
+ }
+
+ }
+
+ /**
+ * Determine if the class associated with this reflector supports a
+ * particular nested element
+ *
+ * @param elementName the name of the element
+ * @return true if the class supports addition of that element
+ */
+ public boolean supportsNestedElement(String elementName) {
+ return elementAdders.containsKey(elementName);
+ }
+
+ /**
+ * Add a method to the reflector for setting an attribute value
+ *
+ * @param m the method, obtained by introspection.
+ * @param propertyName the property name the method will set.
+ * @param converters A map of converter classes used to convert strings
+ * to different types.
+ */
+ public void addAttributeMethod(final Method m, String propertyName,
+ Map converters) {
+ final Class type = m.getParameterTypes()[0];
+
+ if (converters != null && converters.containsKey(type)) {
+ // we have a converter to use to convert the String
+ // value into something the set method expects.
+ final Converter converter = (Converter)converters.get(type);
+ attributeSetters.put(propertyName,
+ new AttributeSetter() {
+ public void set(Object obj, String value)
+ throws InvocationTargetException, ExecutionException,
+ IllegalAccessException, ConversionException {
+ Object convertedValue = converter.convert(value, type);
+ m.invoke(obj, new Object[]{convertedValue});
+ }
+ });
+ } else if (type.equals(String.class)) {
+ attributeSetters.put(propertyName,
+ new AttributeSetter() {
+ public void set(Object parent, String value)
+ throws InvocationTargetException,
+ IllegalAccessException {
+ m.invoke(parent, new String[]{value});
+ }
+ });
+ } else {
+ try {
+ final Constructor c =
+ type.getConstructor(new Class[]{java.lang.String.class});
+ attributeSetters.put(propertyName,
+ new AttributeSetter() {
+ public void set(Object parent, String value)
+ throws InvocationTargetException,
+ IllegalAccessException, ExecutionException {
+ try {
+ Object newValue
+ = c.newInstance(new String[]{value});
+ m.invoke(parent, new Object[]{newValue});
+ } catch (InstantiationException ie) {
+ throw new ExecutionException(ie);
+ }
+ }
+ });
+ } catch (NoSuchMethodException nme) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Add an element adder method to the list of element adders in the
+ * reflector
+ *
+ * @param m the adder method
+ * @param elementName The name of the element for which this adder works
+ */
+ public void addElementMethod(final Method m, String elementName) {
+ final Class type = m.getParameterTypes()[0];
+ elementTypes.put(elementName, type);
+ elementAdders.put(elementName,
+ new ElementAdder() {
+ public void add(Object container, Object obj)
+ throws InvocationTargetException, IllegalAccessException {
+ m.invoke(container, new Object[]{obj});
+ }
+ });
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskAdapter.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskAdapter.java
new file mode 100755
index 000000000..2361eaae6
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskAdapter.java
@@ -0,0 +1,114 @@
+/*
+ * 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.lang.reflect.Method;
+
+import org.apache.ant.common.task.AbstractTask;
+import org.apache.ant.common.task.TaskException;
+
+/**
+ * Use introspection to "adapt" an arbitrary Bean (not extending Task, but
+ * with similar patterns).
+ *
+ * @author Conor MacNeill
+ * @created 16 January 2002
+ */
+public class TaskAdapter extends AbstractTask {
+
+ /** The real object that is performing the work */
+ private Object worker;
+
+ /** the execute method of the real object */
+ private Method executeMethod = null;
+
+ /**
+ * Create an adapter for an arbitraty bean
+ *
+ * @param taskType the name of the task
+ * @param worker an instance of the actual object that does the work
+ * @exception ExecutionException if the worker object does not support
+ * an execute method
+ */
+ public TaskAdapter(String taskType, Object worker)
+ throws ExecutionException {
+ this.worker = worker;
+ try {
+ Class workerClass = worker.getClass();
+ executeMethod = workerClass.getMethod("execute", new Class[0]);
+ if (executeMethod == null) {
+ throw new ExecutionException("No execute method in the class"
+ + " for the <" + taskType + "> task.");
+ }
+ } catch (NoSuchMethodException e) {
+ throw new ExecutionException(e);
+ }
+ }
+
+
+ /**
+ * Standard Task execute method. This invokes the execute method of the
+ * worker instance
+ *
+ * @exception TaskException if there is an exception in the
+ * worker's execute method
+ */
+ public void execute() throws TaskException {
+ try {
+ executeMethod.invoke(worker, null);
+ } catch (Exception ex) {
+ throw new TaskException(ex);
+ }
+ }
+}
+
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
new file mode 100755
index 000000000..f2bcc9643
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java
@@ -0,0 +1,127 @@
+/*
+ * 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.common.task.Task;
+import org.apache.ant.common.task.TaskException;
+import org.apache.ant.antcore.model.ModelElement;
+/**
+ * This is the core's implementation of the AntContext for Tasks.
+ *
+ * @author Conor MacNeill
+ * @created 17 January 2002
+ */
+public class TaskContext extends ExecutionContext {
+
+ /** The task being managed by this context */
+ private Task task;
+
+ /**
+ * the loader used to load this task. Note that this is not necessarily
+ * the loader which is used to load the Task class as loading may have
+ * been delegated to a parent loader.
+ */
+ private ClassLoader loader;
+
+ /**
+ * Get the task associated with this context
+ *
+ * @return the task instance
+ */
+ public Task getTask() {
+ return task;
+ }
+
+ /**
+ * Gets the loader for this task
+ *
+ * @return the task's loader
+ */
+ public ClassLoader getLoader() {
+ return loader;
+ }
+
+ /**
+ * Associate a task with this context
+ *
+ * @param task the task to be manager
+ * @param loader the classloader
+ * @param modelElement the model element associated with this context
+ */
+ public void init(ClassLoader loader, Task task, ModelElement modelElement) {
+ this.task = task;
+ this.loader = loader;
+ setModelElement(modelElement);
+ task.init(this);
+ }
+
+ /**
+ * execute this context's task
+ *
+ * @exception TaskException if the task cannot execute properly
+ */
+ public void execute() throws TaskException {
+ task.execute();
+ }
+
+ /**
+ * Destroy this context. The context can be reused for another task
+ * after this one
+ */
+ public void destroy() {
+ task.destroy();
+ task = null;
+ loader = null;
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TypeContext.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TypeContext.java
new file mode 100755
index 000000000..b7ceadcb2
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TypeContext.java
@@ -0,0 +1,91 @@
+/*
+ * 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.common.task.DataType;
+import org.apache.ant.antcore.model.ModelElement;
+
+/**
+ * This is the core's implementation of the AntContext for Types
+ *
+ * @author Conor MacNeill
+ * @created 20 January 2002
+ */
+public class TypeContext extends ExecutionContext {
+ /** The task being managed by this context */
+ private DataType typeInstance;
+
+ /**
+ * get the DataType instance associated with this context.
+ *
+ * @return the DataType instance
+ */
+ public DataType getInstance() {
+ return typeInstance;
+ }
+
+ /**
+ * Initilaise the context and associate it with the given DataType
+ * instance
+ *
+ * @param typeInstance the DataType instance
+ * @param modelElement the model element associated with this context
+ */
+ public void init(DataType typeInstance, ModelElement modelElement) {
+ this.typeInstance = typeInstance;
+ setModelElement(modelElement);
+ typeInstance.init(this);
+ }
+
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/BuildElement.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/BuildElement.java
new file mode 100755
index 000000000..442e73bad
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/BuildElement.java
@@ -0,0 +1,170 @@
+/*
+ * 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.model;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ant.common.util.Location;
+
+/**
+ * A BuildElement is a holder configuration information for an element of
+ * the build. BuildElements may be grouped into a hierarchy to capture any
+ * level of element nesting.
+ *
+ * @author Conor MacNeill
+ * @created 20 January 2002
+ */
+public class BuildElement extends ModelElement {
+ /** The attributes of this build element */
+ private Map attributes = new HashMap();
+
+ /** The element's name or type */
+ private String type;
+
+ /** The nested task elements that make up this task element. */
+ private List nestedElements = new ArrayList();
+
+ /** The content (text) of this element */
+ private String text = "";
+
+ /**
+ * Create a Build Element of the given type
+ *
+ * @param location the location of the element
+ * @param type the element's type
+ */
+ public BuildElement(Location location, String type) {
+ super(location);
+ this.type = type;
+ }
+
+ /**
+ * Get the text of this element
+ *
+ * @return the elements's text.
+ */
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Get an iterator over this element's nested elements
+ *
+ * @return an iterator which provides BuildElement instances
+ */
+ public Iterator getNestedElements() {
+ return nestedElements.iterator();
+ }
+
+ /**
+ * Get the type of this element
+ *
+ * @return the element's type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Get an iterator over the elements's attributes
+ *
+ * @return an iterator which provide's attribute names
+ */
+ public Iterator getAttributeNames() {
+ return attributes.keySet().iterator();
+ }
+
+ /**
+ * Get the value of an attribute.
+ *
+ * @param attributeName the name of the attribute
+ * @return the value of the attribute or null if there is no such
+ * attribute.
+ */
+ public String getAttributeValue(String attributeName) {
+ return (String)attributes.get(attributeName);
+ }
+
+ /**
+ * Add text to this element.
+ *
+ * @param text the element text to add.
+ */
+ public void addText(String text) {
+ this.text += text;
+ }
+
+ /**
+ * Add a nested element to this element
+ *
+ * @param nestedElement the build element to be added.
+ */
+ public void addNestedElement(BuildElement nestedElement) {
+ nestedElements.add(nestedElement);
+ }
+
+ /**
+ * Add an attribute to this element
+ *
+ * @param attributeName the name of the attribute
+ * @param attributeValue the attribute's value.
+ */
+ public void addAttribute(String attributeName, String attributeValue) {
+ attributes.put(attributeName, attributeValue);
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelElement.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelElement.java
new file mode 100755
index 000000000..a8845e17d
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelElement.java
@@ -0,0 +1,176 @@
+/*
+ * 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.model;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.ant.common.util.Location;
+
+/**
+ * A ModelElement is an element of a build model. A location may be
+ * associated with the model element for error reporting and debugging
+ * purposes.
+ *
+ * @author Conor MacNeill
+ * @created 11 January 2002
+ */
+public abstract class ModelElement {
+ /** The aspects defined for this element. */
+ private Map aspectMaps;
+
+ /** The location of this element */
+ private Location location;
+
+ /** A comment associated with this element, if any */
+ private String comment;
+
+ /**
+ * Create a model element giving its location.
+ *
+ * @param location identifies where this element is defined
+ */
+ public ModelElement(Location location) {
+ this.location = location;
+ }
+
+ /**
+ * Set a comment associated with this element
+ *
+ * @param comment the comment to be associated with this element.
+ */
+ public void setComment(String comment) {
+ this.comment = comment;
+ }
+
+ /**
+ * Set the aspects of this element
+ *
+ * @param aspects a Map of apects that relate to this model element.
+ */
+ public void setAspects(Map aspects) {
+ aspectMaps = new HashMap();
+ for (Iterator i = aspects.keySet().iterator(); i.hasNext(); ) {
+ String aspectName = (String)i.next();
+ int separator = aspectName.indexOf(":");
+ if (separator != -1) {
+ String prefix = aspectName.substring(0, separator);
+ String name = aspectName.substring(separator + 1);
+ if (prefix.length() != 0 && name.length() != 0) {
+ Map prefixMap = (Map)aspectMaps.get(prefix);
+ if (prefixMap == null) {
+ prefixMap = new HashMap();
+ aspectMaps.put(prefix, prefixMap);
+ }
+ prefixMap.put(name, aspects.get(aspectName));
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the location of the source where this element is defined
+ *
+ * @return the element's location
+ */
+ public Location getLocation() {
+ return location;
+ }
+
+ /**
+ * Get the comment associated with this element.
+ *
+ * @return the element's comment which may be null.
+ */
+ public String getComment() {
+ return comment;
+ }
+
+ /**
+ * Get an iterator on the aspects which have been given values on this
+ * element
+ *
+ * @return an iterator of Strings , being the aspects which have been
+ * given values on this element.
+ */
+ public Iterator getAspectNames() {
+ return aspectMaps.keySet().iterator();
+ }
+
+ /**
+ * Get the set of attribute values related to the given aspect
+ *
+ * @param aspectPrefix the aspect identifier
+ * @return a map of the attribute values for the given aspect.
+ */
+ public Map getAspectAttributes(String aspectPrefix) {
+ return (Map)aspectMaps.get(aspectPrefix);
+ }
+
+ /**
+ * Get the value of a single aspect attribute
+ *
+ * @param aspectPrefix the prefix which identifies the aspectr
+ * @param keyName the attribute name
+ * @return the aspect value
+ */
+ public String getAspectValue(String aspectPrefix, String keyName) {
+ Map aspectAttributes = getAspectAttributes(aspectPrefix);
+ if (aspectAttributes == null) {
+ return null;
+ }
+ return (String)aspectAttributes.get(keyName);
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelException.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelException.java
new file mode 100755
index 000000000..924aaa6b3
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/ModelException.java
@@ -0,0 +1,131 @@
+/*
+ * 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.model;
+
+import org.apache.ant.common.util.AntException;
+import org.apache.ant.common.util.Location;
+
+/**
+ * A model exception is thrown when an operation is attempted which would
+ * violate the integrity of the Project/Target/Task object model
+ *
+ * @author Conor MacNeill
+ * @created 16 January 2002
+ */
+public class ModelException extends AntException {
+ /**
+ * Constructs an exception with the given descriptive message.
+ *
+ * @param msg Description of or information about the exception.
+ */
+ public ModelException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs an exception with the given descriptive message and a
+ * location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param location Location in the project file where the error occured.
+ */
+ public ModelException(String msg, Location location) {
+ super(msg, location);
+ }
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Throwable that might have cause this one.
+ */
+ public ModelException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause and a location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public ModelException(String msg, Throwable cause,
+ Location location) {
+ super(msg, cause, location);
+ }
+
+ /**
+ * Constructs an exception with the given exception as a root cause.
+ *
+ * @param cause Exception that might have caused this one.
+ */
+ public ModelException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs an exception with the given exception as a root cause and
+ * a location in a file.
+ *
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public ModelException(Throwable cause, Location location) {
+ super(cause, location);
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Project.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Project.java
new file mode 100755
index 000000000..a173f7700
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Project.java
@@ -0,0 +1,520 @@
+/*
+ * 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.model;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+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
+ * reference objects in other projects using named references of the form
+ * refname:object
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class Project extends ModelElement {
+ /**
+ * The delimiter used to separate reference names in target names, data
+ * values, etc
+ */
+ public final static String REF_DELIMITER = ":";
+
+ /** The default target in this project. */
+ private String defaultTarget = null;
+
+ /**
+ * The base URL of this project. Relative locations are relative to this
+ * base.
+ */
+ private String base;
+
+ /**
+ * The name of this project when referenced by a script within this
+ * project.
+ */
+ private String name;
+
+ /**
+ * These are the targets which belong to the project. They will have
+ * interdependencies which are used to determine which targets need to
+ * be executed before a given target.
+ */
+ private Map targets = new HashMap();
+
+ /**
+ * The global tasks for this project. These are the tasks that will get
+ * executed whenever an execution context is associated with this
+ * project.
+ */
+ private List tasks = new ArrayList();
+
+ /**
+ * The projects referenced into this project. Each referenced project is
+ * given a name which is used to identify access to that project's
+ * elements.
+ */
+ private Map referencedProjects = new HashMap();
+
+ /** The URL where the project is defined. */
+ private URL sourceURL;
+
+
+ /**
+ * Create a Project
+ *
+ * @param sourceURL the URL where the project is defined.
+ * @param location the location of this element within the source.
+ */
+ public Project(URL sourceURL, Location location) {
+ super(location);
+ this.sourceURL = sourceURL;
+ }
+
+
+ /**
+ * Set the defautl target of this project.
+ *
+ * @param defaultTarget the name of the defaultTarget of this project.
+ */
+ public void setDefaultTarget(String defaultTarget) {
+ this.defaultTarget = defaultTarget;
+ }
+
+
+ /**
+ * Set the base URL for this project.
+ *
+ * @param base the baseURL for this project.
+ */
+ public void setBase(String base) {
+ this.base = base;
+ }
+
+
+ /**
+ * Set the name of this project.
+ *
+ * @param name the name for this project.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+ /**
+ * Get the URL where this project is defined
+ *
+ * @return the project source URL
+ */
+ public URL getSourceURL() {
+ return sourceURL;
+ }
+
+
+ /**
+ * Get the Project's default Target, if any
+ *
+ * @return the project's defautl target or null if there is no default.
+ */
+ public String getDefaultTarget() {
+ return defaultTarget;
+ }
+
+
+ /**
+ * Get the base URL for this project.
+ *
+ * @return the baseURL for this project as a string.
+ */
+ public String getBase() {
+ return base;
+ }
+
+
+ /**
+ * Get the targets in this project.
+ *
+ * @return an iterator returning Target objects.
+ */
+ public Iterator getTargets() {
+ return targets.values().iterator();
+ }
+
+
+ /**
+ * Get the target with the given name
+ *
+ * @param targetName the name of the desired target.
+ * @return the target with the given name or null if there is no such
+ * target.
+ */
+ public Target getTarget(String targetName) {
+ return (Target)targets.get(targetName);
+ }
+
+
+ /**
+ * Get the names of the referenced projects.
+ *
+ * @return an iterator which returns the name sof the referenced
+ * projects.
+ */
+ public Iterator getReferencedProjectNames() {
+ return referencedProjects.keySet().iterator();
+ }
+
+
+ /**
+ * Get a referenced project by name
+ *
+ * @param alias the name under which the project was referenced.
+ * @return the project asscociated with the given reference alias or
+ * null if there is no such project.
+ */
+ public Project getReferencedProject(String alias) {
+ return (Project)referencedProjects.get(alias);
+ }
+
+
+ /**
+ * Get the initialisation tasks for this project
+ *
+ * @return an iterator over the set of tasks for this project.
+ */
+ public Iterator getTasks() {
+ return tasks.iterator();
+ }
+
+ /**
+ * Get a target by its reference name - references may span multiple
+ * references.
+ *
+ * @param fullTargetName The name of the target relative to this project
+ * @return the Target object with the given name
+ */
+ public Target getRefTarget(String fullTargetName) {
+ Project containingProject = getRefProject(fullTargetName);
+ if (containingProject == this) {
+ return getTarget(fullTargetName);
+ }
+
+ int index = fullTargetName.lastIndexOf(REF_DELIMITER);
+ String targetName
+ = fullTargetName.substring(index + REF_DELIMITER.length());
+
+ return containingProject.getTarget(targetName);
+ }
+
+ /**
+ * Get the project which directly contains the target specified by its
+ * full name.
+ *
+ * @param fullTargetName the full name of the target for which the
+ * containing project is required.
+ * @return The RefProject value
+ */
+ public Project getRefProject(String fullTargetName) {
+ int index = fullTargetName.lastIndexOf(REF_DELIMITER);
+ if (index == -1) {
+ return this;
+ }
+
+ Project currentProject = this;
+ String relativeName = fullTargetName.substring(0, index);
+ StringTokenizer tokenizer
+ = new StringTokenizer(relativeName, REF_DELIMITER);
+ while (tokenizer.hasMoreTokens()) {
+ String refName = tokenizer.nextToken();
+ currentProject = currentProject.getReferencedProject(refName);
+ if (currentProject == null) {
+ return null;
+ }
+ }
+
+ return currentProject;
+ }
+
+ /**
+ * get the list of dependent targets which must be evaluated for the
+ * given target.
+ *
+ * @param fullTargetName the full name (in reference space) of the
+ * target
+ * @return the flattened list of targets
+ * @exception ConfigException if the given target could not be found
+ */
+ public List getTargetDependencies(String fullTargetName)
+ throws ConfigException {
+ try {
+ List flattenedList = new ArrayList();
+ flattenDependency(flattenedList, fullTargetName);
+ flattenedList.add(fullTargetName);
+ return flattenedList;
+ } catch (ConfigException e) {
+ throw new ConfigException(fullTargetName
+ + " does not exist in project");
+ }
+ }
+
+
+ /**
+ * Add a target to the project.
+ *
+ * @param target the Target to be added
+ * @throws ModelException if a target with the same name already exists.
+ */
+ public void addTarget(Target target) throws ModelException {
+ if (targets.containsKey(target.getName())) {
+ throw new ModelException("A target with name '"
+ + target.getName() +
+ "' has already been defined in this project",
+ target.getLocation());
+ }
+ targets.put(target.getName(), target);
+ }
+
+
+ /**
+ * Add a task to the list of global tasks for this project.
+ *
+ * @param task a task to be executed when an execution context is
+ * associated with the Project (a non-target task)
+ */
+ public void addTask(BuildElement task) {
+ tasks.add(task);
+ }
+
+
+ /**
+ * Reference a project using the given name.
+ *
+ * @param referenceName the name under which the project will be
+ * referenced.
+ * @param project the referenced project.
+ * @throws ModelException if an existing project has already been
+ * referenced with that name.
+ */
+ public void referenceProject(String referenceName, Project project)
+ throws ModelException {
+ if (referencedProjects.containsKey(referenceName)) {
+ throw new ModelException("A project has already been "
+ + "introduced with name '" + referenceName + "'");
+ }
+ referencedProjects.put(referenceName, 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
+ */
+ public void validate(String globalName) throws ModelException {
+ if (defaultTarget == null) {
+ throw new ModelException("Project must have a default "
+ + "attribute", getLocation());
+ }
+
+ 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);
+ }
+ }
+
+ /**
+ * Determine target dependency order within this porject and verify that
+ * references to targets in other projects are valid
+ *
+ * @param globalName The global name of this project
+ * @param target The target being examined
+ * @param dependencyOrder The dependency order of targets
+ * @param visited Set of targets in this project already visited.
+ * @param checker A circular dependency checker
+ * @exception ModelException if the dependencies of the project's
+ * targets are not valid.
+ */
+ public void fillinDependencyOrder(String globalName, Target target,
+ List dependencyOrder, Set visited,
+ CircularDependencyChecker checker)
+ throws ModelException {
+ if (visited.contains(target.getName())) {
+ return;
+ }
+
+ try {
+ String targetName = target.getName();
+ String targetGlobalName = targetName;
+ if (globalName != null) {
+ targetGlobalName = globalName + REF_DELIMITER + targetName;
+ }
+ checker.visitNode(targetGlobalName);
+ for (Iterator i = target.getDependencies(); i.hasNext(); ) {
+ String dependency = (String)i.next();
+ boolean localTarget = (dependency.indexOf(REF_DELIMITER) == -1);
+ Target dependencyTarget
+ = localTarget ? getTarget(dependency)
+ : getRefTarget(dependency);
+
+ if (dependencyTarget == null) {
+ StringBuffer sb = new StringBuffer("Target '");
+ if (globalName != null) {
+ sb.append(globalName + REF_DELIMITER);
+ }
+ sb.append(dependency);
+ sb.append("' does not exist in this project. ");
+ throw new ModelException(new String(sb),
+ target.getLocation());
+ }
+
+ if (localTarget) {
+ // need to check the targets we depend on
+ fillinDependencyOrder(globalName, dependencyTarget,
+ dependencyOrder, visited, checker);
+ }
+ }
+
+ visited.add(targetName);
+ checker.leaveNode(targetGlobalName);
+ dependencyOrder.add(targetName);
+ } catch (CircularDependencyException e) {
+ throw new ModelException(e.getMessage(),
+ target.getLocation());
+ }
+ }
+
+ /**
+ * Given a fully qualified target name, this method simply returns the
+ * fully qualified name of the project
+ *
+ * @param fullTargetName the full qualified target name
+ * @return the full name of the containing project
+ */
+ private String getFullProjectName(String fullTargetName) {
+ int index = fullTargetName.lastIndexOf(REF_DELIMITER);
+ if (index == -1) {
+ return null;
+ }
+
+ return fullTargetName.substring(0, index);
+ }
+
+ /**
+ * Flatten the dependencies to the given target
+ *
+ * @param flattenedList the List of targets that must be executed before
+ * the given target
+ * @param fullTargetName the fully qualified name of the target
+ * @exception ConfigException if the given target does not exist in the
+ * project hierarchy
+ */
+ private void flattenDependency(List flattenedList, String fullTargetName)
+ throws ConfigException {
+ if (flattenedList.contains(fullTargetName)) {
+ return;
+ }
+ Project containingProject = getRefProject(fullTargetName);
+ String fullProjectName = getFullProjectName(fullTargetName);
+ Target target = getRefTarget(fullTargetName);
+ if (target == null) {
+ throw new ConfigException("Target " + fullTargetName
+ + " does not exist");
+ }
+ for (Iterator i = target.getDependencies(); i.hasNext(); ) {
+ String localDependencyName = (String)i.next();
+ String fullDependencyName
+ = fullProjectName == null ? localDependencyName
+ : fullProjectName + REF_DELIMITER + localDependencyName;
+ flattenDependency(flattenedList, fullDependencyName);
+ flattenedList.add(fullDependencyName);
+ }
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Target.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Target.java
new file mode 100755
index 000000000..0386a0af6
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Target.java
@@ -0,0 +1,168 @@
+/*
+ * 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.model;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.ant.common.util.Location;
+
+/**
+ * A Target is a collection of tasks. It may have dependencies on other
+ * targets
+ *
+ * @author Conor MacNeill
+ * @created 12 January 2002
+ */
+public class Target extends ModelElement {
+ /** This target's dependencies on other targets, if any */
+ private List dependencies = new ArrayList();
+
+ /** This target's list of tasks */
+ private List tasks = new ArrayList();
+
+ /** The target's name. */
+ private String name;
+
+ /** The Target's description */
+ private String description;
+
+ /**
+ * Construct the target, given its name
+ *
+ * @param location the location of the element
+ * @param name the target's name.
+ */
+ public Target(Location location, String name) {
+ super(location);
+ this.name = name;
+ }
+
+ /**
+ * Sets the Target's description
+ *
+ * @param description The new description value
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Get this target's name.
+ *
+ * @return the target's name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the Target's description
+ *
+ * @return The description value
+ */
+ public String getDescription() {
+ return description;
+ }
+
+
+ /**
+ * Get this target's dependencies.
+ *
+ * @return an iterator over the target's dependencies.
+ */
+ public Iterator getDependencies() {
+ return dependencies.iterator();
+ }
+
+ /**
+ * Get the tasks for this target
+ *
+ * @return an iterator over the set of tasks for this target.
+ */
+ public Iterator getTasks() {
+ return tasks.iterator();
+ }
+
+ /**
+ * Add a task to this target
+ *
+ * @param task the task to be added to the target.
+ */
+ public void addTask(BuildElement task) {
+ tasks.add(task);
+ }
+
+ /**
+ * Add a dependency to this target
+ *
+ * @param dependency the name of a target upon which this target depends
+ */
+ public void addDependency(String dependency) {
+ dependencies.add(dependency);
+ }
+
+ /**
+ * Validate that this build element is configured correctly
+ *
+ * @exception ModelException if the element is invalid
+ */
+ public void validate() throws ModelException {
+ if (name == null) {
+ throw new ModelException("Target must have a name",
+ getLocation());
+ }
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyChecker.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyChecker.java
new file mode 100755
index 000000000..bdea4889c
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyChecker.java
@@ -0,0 +1,133 @@
+/*
+ * 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.util;
+import java.util.Stack;
+
+/**
+ * Checks for circular dependencies when visiting nodes of an object
+ * hierarchy
+ *
+ * @author Conor MacNeill
+ * @created 14 January 2002
+ */
+public class CircularDependencyChecker {
+ /**
+ * The activity being undertaken which checking for circular
+ * redundancies. This is used for reporting exceptions
+ */
+ private String activity;
+
+ /** The nodes which we are currently visiting */
+ private Stack nodes = new Stack();
+
+ /**
+ * Constructor for the CircularDependencyChecker object
+ *
+ * @param activity the activity being undertaken
+ */
+ public CircularDependencyChecker(String activity) {
+ this.activity = activity;
+ }
+
+ /**
+ * Visit a Node to check its relationships to other nodes
+ *
+ * @param node an object which is being visited and analyzed
+ * @exception CircularDependencyException if this node is alreay being
+ * visited.
+ */
+ public void visitNode(Object node) throws CircularDependencyException {
+ if (nodes.contains(node)) {
+ throw new CircularDependencyException(getDescription(node));
+ }
+ nodes.push(node);
+ }
+
+ /**
+ * Complete the examination of the node and leave.
+ *
+ * @param node an object for which the examination of relationships has
+ * been completed
+ * @exception CircularDependencyException if the given node was not
+ * expected.
+ */
+ public void leaveNode(Object node) throws CircularDependencyException {
+ if (!nodes.pop().equals(node)) {
+ throw new CircularDependencyException("Internal error: popped " +
+ "element was unexpected");
+ }
+ }
+
+ /**
+ * Gets the description of the circular dependency
+ *
+ * @param endNode the node which was revisited and where the circular
+ * dependency was detected
+ * @return the description of the circular dependency
+ */
+ private String getDescription(Object endNode) {
+ StringBuffer sb = new StringBuffer("Circular dependency while "
+ + activity + ": ");
+ sb.append(endNode);
+ Object o = null;
+ do {
+ o = nodes.pop();
+ sb.append(" <- ");
+ sb.append(o.toString());
+ } while (!(o.equals(endNode)));
+
+ return new String(sb);
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyException.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyException.java
new file mode 100755
index 000000000..af96186bc
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/CircularDependencyException.java
@@ -0,0 +1,137 @@
+/*
+ * 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.util;
+
+import org.apache.ant.common.util.AntException;
+import org.apache.ant.common.util.Location;
+
+/**
+ * A CircularDependencyException indicates that a circular dependency has
+ * been detected
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class CircularDependencyException extends AntException {
+ /**
+ * Constructs an exception with the given descriptive message.
+ *
+ * @param msg Description of or information about the exception.
+ */
+ public CircularDependencyException(String msg) {
+ super(msg);
+ }
+
+
+ /**
+ * Constructs an exception with the given descriptive message and a
+ * location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param location Location in the project file where the error occured.
+ */
+ public CircularDependencyException(String msg, Location location) {
+ super(msg, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Throwable that might have cause this one.
+ */
+ public CircularDependencyException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause and a location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public CircularDependencyException(String msg, Throwable cause,
+ Location location) {
+ super(msg, cause, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause.
+ *
+ * @param cause Exception that might have caused this one.
+ */
+ public CircularDependencyException(Throwable cause) {
+ super(cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause and
+ * a location in a file.
+ *
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public CircularDependencyException(Throwable cause, Location location) {
+ super(cause, location);
+ }
+
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/ConfigException.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/ConfigException.java
new file mode 100755
index 000000000..fd26d211e
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/util/ConfigException.java
@@ -0,0 +1,136 @@
+/*
+ * 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.util;
+
+import org.apache.ant.common.util.AntException;
+import org.apache.ant.common.util.Location;
+
+/**
+ * A ConfigException indicates a problem with Ant's configuration or the
+ * commandline used to start Ant.
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class ConfigException extends AntException {
+ /**
+ * Constructs an exception with the given descriptive message.
+ *
+ * @param msg Description of or information about the exception.
+ */
+ public ConfigException(String msg) {
+ super(msg);
+ }
+
+
+ /**
+ * Constructs an exception with the given descriptive message and a
+ * location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param location Location in the project file where the error occured.
+ */
+ public ConfigException(String msg, Location location) {
+ super(msg, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Throwable that might have cause this one.
+ */
+ public ConfigException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause and a location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public ConfigException(String msg, Throwable cause, Location location) {
+ super(msg, cause, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause.
+ *
+ * @param cause Exception that might have caused this one.
+ */
+ public ConfigException(Throwable cause) {
+ super(cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause and
+ * a location in a file.
+ *
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public ConfigException(Throwable cause, Location location) {
+ super(cause, location);
+ }
+
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ElementHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ElementHandler.java
new file mode 100755
index 000000000..67517d312
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ElementHandler.java
@@ -0,0 +1,357 @@
+/*
+ * 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.xml;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.ant.common.util.Location;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * An Element Handler is a handler which handles a single element by
+ * becoming the handler for the parser while processing the element. Any sub
+ * elements must be delegated to separate handlers. When this element is
+ * finished, control returns to the parent handler.
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public abstract class ElementHandler extends DefaultHandler {
+ /** The parsing context for parsing this element */
+ private ParseContext context;
+
+ /**
+ * Locator used to identify where in the build source particular
+ * elements occur.
+ */
+ private Locator locator;
+
+ /** The actual XML parser used to parse the build source */
+ private XMLReader reader;
+
+ /** The parent element handler */
+ private ContentHandler parent;
+
+ /** The URL from which we are reading source */
+ private URL source;
+
+ /** The name of this element */
+ private String elementName;
+
+ /** The attributes read from this element */
+ private Map elementAttributes;
+
+ /** The aspect attributes read from the element definition */
+ private Map aspects;
+
+ /** The content of this element */
+ private String content;
+
+ /**
+ * Get the source which contains this element
+ *
+ * @return the URL from which this element is being read
+ */
+ public URL getElementSource() {
+ return source;
+ }
+
+ /**
+ * Gets the attributeValue attribute of the ElementHandler object
+ *
+ * @param attributeName th name of the attribute
+ * @return The corresponding attribute value or null if the attribute wa
+ * snot defined.
+ */
+ public String getAttribute(String attributeName) {
+ return (String)elementAttributes.get(attributeName);
+ }
+
+ /**
+ * Get an iterator to this elements attributes
+ *
+ * @return an iterator over the attribute names
+ */
+ public Iterator getAttributes() {
+ return elementAttributes.keySet().iterator();
+ }
+
+ /**
+ * Get the aspect attributes of this element.
+ *
+ * @return The aspect attributes.
+ */
+ public Map getAspects() {
+ return aspects;
+ }
+
+ /**
+ * Gets the content of the element
+ *
+ * @return The content value
+ */
+ public String getContent() {
+ return content;
+ }
+
+
+ /**
+ * Start this element handler.
+ *
+ * @param parent the element handler for the element which contains this
+ * one.
+ * @param locator the locator is used to get location information from
+ * elements.
+ * @param attributes the element's attributes.
+ * @param source the URL from which the XML source is being parsed.
+ * @param xmlReader the parser being used
+ * @param context the parser context for this element
+ * @param elementName the actual element Name for this element in the
+ * XML
+ * @exception SAXParseException if there is a problem parsing the
+ * element
+ */
+ public final void start(ParseContext context, XMLReader xmlReader,
+ ContentHandler parent, Locator locator,
+ Attributes attributes, URL source,
+ String elementName)
+ throws SAXParseException {
+ this.context = context;
+ this.reader = xmlReader;
+ this.parent = parent;
+ this.locator = locator;
+ this.source = source;
+ this.elementName = elementName;
+ processAttributes(attributes);
+ processElement(elementName);
+ reader.setContentHandler(this);
+ }
+
+
+ /**
+ * By default an element handler does not support nested elements. This
+ * method will always throw an exception. Subclasses should override
+ * this method to support their own nested elements
+ *
+ * @param uri The Namespace URI.
+ * @param localName The local name (without prefix).
+ * @param qualifiedName The qualified name (with prefix)
+ * @param attributes The attributes attached to the element.
+ * @throws SAXParseException if there is a problem parsng the subelement
+ */
+ public void startElement(String uri, String localName, String qualifiedName,
+ Attributes attributes)
+ throws SAXParseException {
+ // everything is a task
+ throw new SAXParseException("<" + elementName + "> does not support a <"
+ + qualifiedName + "> nested element", getLocator());
+ }
+
+
+ /**
+ * Handle the end of this element by making the parent element handler
+ * the current content handler
+ *
+ * @param localName The local name (without prefix).
+ * @param namespaceURI The Namespace URI.
+ * @param qName the qualified name of the element
+ */
+ public final void endElement(String namespaceURI, String localName,
+ String qName) {
+ finish();
+ reader.setContentHandler(parent);
+ }
+
+ /**
+ * Record content of this element
+ *
+ * @param buf the buffer containing the content to be added
+ * @param start start position in the buffer
+ * @param end end position in the buffer
+ * @exception SAXParseException if there is a parsing error.
+ * @see org.xml.sax.ContentHandler.characters()
+ */
+ public void characters(char[] buf, int start, int end)
+ throws SAXParseException {
+ if (content == null) {
+ content = "";
+ }
+ content += new String(buf, start, end);
+ }
+
+
+ /**
+ * Get the current parsing location
+ *
+ * @return a location instance representing the current parse position
+ */
+ protected Location getLocation() {
+ return new Location(locator.getSystemId(), locator.getLineNumber(),
+ locator.getColumnNumber());
+ }
+
+
+ /**
+ * Get the XML Reader being used to parse the XML.
+ *
+ * @return the XML Reader.
+ */
+ protected XMLReader getXMLReader() {
+ return reader;
+ }
+
+
+ /**
+ * Get the parsing context
+ *
+ * @return the parsing context of this element
+ */
+ protected ParseContext getParseContext() {
+ return context;
+ }
+
+
+ /**
+ * Get the locator used to locate elements in the XML source as they are
+ * parsed.
+ *
+ * @return the locator object which can be used to determine an elements
+ * location within the XML source
+ */
+ protected Locator getLocator() {
+ return locator;
+ }
+
+
+ /**
+ * Process the element.
+ *
+ * @param elementName the name of the element
+ * @exception SAXParseException if there is a problem parsing the
+ * element
+ */
+ protected abstract void processElement(String elementName)
+ throws SAXParseException;
+
+
+ /**
+ * Process all of the attributes of the element into maps, one for
+ * aspects and one for other attributes
+ *
+ * @param attributes The SAX attributes collection for the element
+ * @exception SAXParseException if there is a problem reading the
+ * attributes
+ */
+ protected final void processAttributes(Attributes attributes)
+ throws SAXParseException {
+ aspects = new HashMap();
+ elementAttributes = new HashMap();
+ for (int i = 0; i < attributes.getLength(); ++i) {
+ String attributeName = attributes.getQName(i);
+ String attributeValue = attributes.getValue(i);
+ if (attributeName.indexOf(":") != -1) {
+ aspects.put(attributeName, attributeValue);
+ } else {
+ validateAttribute(attributeName, attributeValue);
+ elementAttributes.put(attributeName, attributeValue);
+ }
+ }
+ }
+
+ /**
+ * Validate that the given attribute and value are valid. By default all
+ * attributes are considered invalid. This method should be overrider by
+ * subclasses to allow specific attributes
+ *
+ * @param attributeName The name of the attributes
+ * @param attributeValue The value of the attributes
+ * @exception SAXParseException if the attribute is not allowed on the
+ * element.
+ */
+ protected void validateAttribute(String attributeName,
+ String attributeValue)
+ throws SAXParseException {
+ throwInvalidAttribute(attributeName);
+ }
+
+ /**
+ * Throws an invalid attribute exception
+ *
+ * @param attributeName The name of the invalid attribute
+ * @exception SAXParseException always - indicating attribute is invalid
+ */
+ protected final void throwInvalidAttribute(String attributeName)
+ throws SAXParseException {
+ throw new SAXParseException("The attribute '" + attributeName
+ + "' is not " + "supported by the <" + elementName
+ + "> element", getLocator());
+ }
+
+
+ /**
+ * This method is called when this element is finished being processed.
+ * This is a template method allowing subclasses to complete any
+ * necessary processing.
+ */
+ protected void finish() {
+ }
+}
+
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
new file mode 100755
index 000000000..18c542fec
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ParseContext.java
@@ -0,0 +1,146 @@
+/*
+ * 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.xml;
+
+import java.io.IOException;
+import java.net.URL;
+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.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+
+/**
+ * Holds the current parsing context.
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class ParseContext {
+ /**
+ * Used to check if we are trying to parse a build file within its own
+ * context.
+ */
+ private CircularDependencyChecker checker
+ = new CircularDependencyChecker("parsing XML");
+
+ /** The factory used to create SAX parsers. */
+ private SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+
+
+ /**
+ * Parse a URL using the given root handler
+ *
+ * @param source The URL to the source to be parsed
+ * @param rootElementName The required root element name
+ * @param rootElementHandler The handler for the root element
+ * @exception XMLParseException if the element cannot be parsed
+ */
+ public void parse(URL source, String rootElementName,
+ ElementHandler rootElementHandler)
+ throws XMLParseException {
+ parse(source, new String[]{rootElementName}, rootElementHandler);
+ }
+
+
+ /**
+ * Parse a URL using the given root handler
+ *
+ * @param source The URL to the source to be parsed
+ * @param rootElementNames The allowable root element names
+ * @param rootElementHandler The handler for the root element
+ * @exception XMLParseException if the element cannot be parsed
+ */
+ public void parse(URL source, String[] rootElementNames,
+ ElementHandler rootElementHandler)
+ throws XMLParseException {
+ try {
+ checker.visitNode(source);
+
+ // create a parser for this source
+ SAXParser saxParser = parserFactory.newSAXParser();
+ XMLReader xmlReader = saxParser.getXMLReader();
+
+ // create a root handler for this
+ RootHandler rootHandler = new RootHandler(this, source, xmlReader,
+ rootElementNames, rootElementHandler);
+ saxParser.parse(source.toString(), rootHandler);
+
+ checker.leaveNode(source);
+ } catch (ParserConfigurationException e) {
+ throw new XMLParseException(e);
+ } catch (SAXParseException e) {
+ Location location = new Location(e.getSystemId(),
+ e.getLineNumber(), e.getColumnNumber());
+ if (e.getException() != null) {
+ throw new XMLParseException("XML Parsing Exception",
+ e.getException(), location);
+ } else {
+ throw new XMLParseException("XML Parsing Exception",
+ e, location);
+ }
+ } catch (SAXException e) {
+ throw new XMLParseException(e);
+ } catch (IOException e) {
+ throw new XMLParseException(e);
+ } catch (CircularDependencyException e) {
+ throw new XMLParseException(e);
+ }
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/RootHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/RootHandler.java
new file mode 100755
index 000000000..d54e7c68c
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/RootHandler.java
@@ -0,0 +1,154 @@
+/*
+ * 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.xml;
+
+import java.net.URL;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Handle the root of an XML parse. This class recognizes the root document
+ * element and then passes control to the handler for that root element.
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class RootHandler extends DefaultHandler {
+ /** The parsing context for this document */
+ private ParseContext context;
+
+ /**
+ * Locator used to identify where in the build source particular
+ * elements occur.
+ */
+ private Locator locator;
+
+ /** The actual XML parser used to parse the build source */
+ private XMLReader reader;
+
+ /** The URL from which the XML source is being read. */
+ private URL sourceURL;
+
+ /** The allowed names of the root element in this document */
+ private String[] allowedRootNames;
+
+ /** The handler for the root element */
+ private ElementHandler rootElementHandler;
+
+
+ /**
+ * Handler to handle the document root.
+ *
+ * @param context The Parser context for this parse operation
+ * @param sourceURL URL of the source containing the XML definition
+ * @param reader XML parser
+ * @param allowedRootNames An array of allowed element names
+ * @param rootElementHandler The element handler for the root element
+ */
+ public RootHandler(ParseContext context, URL sourceURL, XMLReader reader,
+ String[] allowedRootNames,
+ ElementHandler rootElementHandler) {
+ this.context = context;
+ this.sourceURL = sourceURL;
+ this.reader = reader;
+ this.allowedRootNames = allowedRootNames;
+ this.rootElementHandler = rootElementHandler;
+ }
+
+
+ /**
+ * Set the locator to use when parsing elements. This is passed onto
+ * child elements.
+ *
+ * @param locator the locator for locating elements in the build source.
+ */
+ public void setDocumentLocator(Locator locator) {
+ this.locator = locator;
+ }
+
+
+ /**
+ * Start a new element in the root. This must be a project element All
+ * other elements are invalid.
+ *
+ * @param uri The Namespace URI.
+ * @param localName The local name (without prefix).
+ * @param qualifiedName The qualified name (with prefix)
+ * @param attributes The attributes attached to the element.
+ * @throws SAXParseException if there is a parsing problem.
+ */
+ public void startElement(String uri, String localName, String qualifiedName,
+ Attributes attributes)
+ throws SAXParseException {
+ boolean allowed = false;
+ for (int i = 0; i < allowedRootNames.length; ++i) {
+ if (qualifiedName.equals(allowedRootNames[i])) {
+ allowed = true;
+ break;
+ }
+ }
+
+ if (allowed) {
+ rootElementHandler.start(context, reader, this,
+ locator, attributes, sourceURL, qualifiedName);
+ } else {
+ throw new SAXParseException("<" + qualifiedName
+ + "> element was not expected as the root element", locator);
+ }
+ }
+}
+
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/XMLParseException.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/XMLParseException.java
new file mode 100755
index 000000000..5fd0c6ef9
--- /dev/null
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/XMLParseException.java
@@ -0,0 +1,130 @@
+/*
+ * 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.xml;
+
+import org.apache.ant.common.util.AntException;
+import org.apache.ant.common.util.Location;
+
+/**
+ * An XMLParseException is thrown when there is an error parsing the XML
+ * representation of an Ant build file.
+ *
+ * @author Conor MacNeill
+ * @created 11 January 2002
+ */
+public class XMLParseException extends AntException {
+ /**
+ * Constructs an exception with the given descriptive message.
+ *
+ * @param msg Description of or information about the exception.
+ */
+ public XMLParseException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs an exception with the given descriptive message and a
+ * location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param location Location in the project file where the error occured.
+ */
+ public XMLParseException(String msg, Location location) {
+ super(msg, location);
+ }
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Throwable that might have cause this one.
+ */
+ public XMLParseException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause and a location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public XMLParseException(String msg, Throwable cause, Location location) {
+ super(msg, cause, location);
+ }
+
+ /**
+ * Constructs an exception with the given exception as a root cause.
+ *
+ * @param cause Exception that might have caused this one.
+ */
+ public XMLParseException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs an exception with the given exception as a root cause and
+ * a location in a file.
+ *
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public XMLParseException(Throwable cause, Location location) {
+ super(cause, location);
+ }
+}
+
diff --git a/proposal/mutant/src/java/antlibs/file/antlib.xml b/proposal/mutant/src/java/antlibs/file/antlib.xml
new file mode 100755
index 000000000..b545e73a1
--- /dev/null
+++ b/proposal/mutant/src/java/antlibs/file/antlib.xml
@@ -0,0 +1,6 @@
+
+
+
diff --git a/proposal/mutant/src/java/antlibs/io/antlib.xml b/proposal/mutant/src/java/antlibs/io/antlib.xml
new file mode 100755
index 000000000..67b5b729b
--- /dev/null
+++ b/proposal/mutant/src/java/antlibs/io/antlib.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/Echo.java b/proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/Echo.java
new file mode 100755
index 000000000..c3ee9f37a
--- /dev/null
+++ b/proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/Echo.java
@@ -0,0 +1,163 @@
+/*
+ * 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.taskdef.io;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import org.apache.ant.common.task.AbstractTask;
+import org.apache.ant.common.task.TaskException;
+import org.apache.ant.common.util.MessageLevel;
+
+/**
+ * Basic Echo Tast for testing
+ *
+ * @author Conor MacNeill
+ * @created 16 January 2002
+ */
+public class Echo extends AbstractTask {
+ /** The message to be echoed */
+ private String message = "";
+ /** the file to which output is sent if any */
+ private File file = null;
+ /** indicates if the fileoutput is to be appended to an existing file */
+ private boolean append = false;
+
+ // by default, messages are always displayed
+ /** the log level to be used when echoing - defaults to Warning level */
+ private int logLevel = MessageLevel.MSG_WARN;
+
+ /**
+ * Sets the message variable.
+ *
+ * @param msg Sets the value for the message variable.
+ */
+ public void setMessage(String msg) {
+ this.message = msg;
+ }
+
+ /**
+ * Set the file to which output is to be sent
+ *
+ * @param file the new file value
+ */
+ public void setFile(File file) {
+ this.file = file;
+ }
+
+ /**
+ * Indicate if output is to be appended to the file
+ *
+ * @param append true if output should be appended
+ */
+ public void setAppend(boolean append) {
+ this.append = append;
+ }
+
+ /**
+ * Does the work.
+ *
+ * @throws TaskException if cannot output message
+ */
+ public void execute() throws TaskException {
+ if (file == null) {
+ log(message, logLevel);
+ } else {
+ FileWriter out = null;
+ try {
+ out = new FileWriter(file.getAbsolutePath(), append);
+ out.write(message, 0, message.length());
+ } catch (IOException ioe) {
+ throw new TaskException(ioe);
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException ioex) {
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Set a multiline message.
+ *
+ * @param msg the message
+ */
+ public void addText(String msg) {
+ message += msg;
+ }
+
+ /**
+ * testing only
+ *
+ * @param frame testing
+ */
+ public void addFrame(java.awt.Frame frame) {
+ log("Adding frame " + frame, MessageLevel.MSG_WARN);
+ }
+
+ /**
+ * testing
+ *
+ * @param runnable testing
+ */
+ public void addRun(Runnable runnable) {
+ log("Adding runnable of type "
+ + runnable.getClass().getName(), MessageLevel.MSG_WARN);
+ }
+
+}
+
diff --git a/proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/FileConverter.java b/proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/FileConverter.java
new file mode 100755
index 000000000..e535c1223
--- /dev/null
+++ b/proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/FileConverter.java
@@ -0,0 +1,99 @@
+/*
+ * 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.taskdef.io;
+
+import java.io.File;
+import org.apache.ant.common.converter.AbstractConverter;
+import org.apache.ant.common.converter.ConversionException;
+import org.apache.ant.common.util.AntException;
+
+/**
+ * A converter to convert to File objects, resolving against the
+ * project's basedir
+ *
+ * @author Conor MacNeill
+ * @created 21 January 2002
+ */
+public class FileConverter extends AbstractConverter {
+
+ /**
+ * Get the list of classes this converter is able to convert to.
+ *
+ * @return an array of Class objects representing the classes this
+ * converter handles.
+ */
+ public Class[] getTypes() {
+ return new Class[]{File.class};
+ }
+
+ /**
+ * Convert a string from the value given to an instance of the given
+ * type.
+ *
+ * @param value The value to be converted
+ * @param type the desired type of the converted object
+ * @return the value of the converted object
+ * @exception ConversionException if the conversion cannot be made
+ */
+ public Object convert(String value, Class type) throws ConversionException {
+ try {
+ return getContext().resolveFile(value);
+ }
+ catch (AntException e) {
+ throw new ConversionException("Unable to resolve file: "
+ + value, e);
+ }
+ }
+}
+
diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/BuildLogger.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/BuildLogger.java
new file mode 100755
index 000000000..e02360255
--- /dev/null
+++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/BuildLogger.java
@@ -0,0 +1,92 @@
+/*
+ * 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.cli;
+
+import java.io.PrintStream;
+import org.apache.ant.antcore.event.BuildListener;
+
+/**
+ * Interface used by Ant to log the build output. A build logger is a build
+ * listener which has the 'right' to send output to the ant log, which is
+ * usually System.out unles redirected by the -logfile option.
+ *
+ * @author Conor MacNeill
+ * @created 15 January 2002
+ */
+public interface BuildLogger extends BuildListener {
+ /**
+ * Set the msgOutputLevel 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.
+ *
+ * @param level the logging level for the logger.
+ */
+ public void setMessageOutputLevel(int level);
+
+ /**
+ * Set the output stream to which this logger is to send its output.
+ *
+ * @param output the output stream for the logger.
+ */
+ public void setOutputPrintStream(PrintStream output);
+
+ /**
+ * Set the output stream to which this logger is to send error messages.
+ *
+ * @param err the error stream for the logger.
+ */
+ public void setErrorPrintStream(PrintStream err);
+
+}
+
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
new file mode 100755
index 000000000..d17afdb0b
--- /dev/null
+++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java
@@ -0,0 +1,351 @@
+/*
+ * 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.cli;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ant.cli.xml.XMLProjectParser;
+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.antcore.event.BuildListener;
+import org.apache.ant.antcore.execution.ExecutionManager;
+import org.apache.ant.antcore.model.Project;
+import org.apache.ant.antcore.util.ConfigException;
+import org.apache.ant.antcore.xml.XMLParseException;
+import org.apache.ant.init.InitUtils;
+import org.apache.ant.init.InitConfig;
+
+/**
+ * This is the command line front end to end. It drives the core
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class Commandline {
+ /** The default build file name */
+ public final static String DEFAULT_BUILD_FILENAME = "build.ant";
+
+ /** The initialisation configuration for Ant */
+ private InitConfig config;
+
+ /** Stream that we are using for logging */
+ private PrintStream out = System.out;
+
+ /** Stream that we are using for logging error messages */
+ private PrintStream err = System.err;
+
+ /** Names of classes to add as listeners to project */
+ private List listeners = new ArrayList(2);
+
+ /** The list of targets to be evaluated in this invocation */
+ private List targets = new ArrayList(4);
+
+ /**
+ * This is the build file to run. By default it is a file: type URL but
+ * other URL protocols can be used.
+ */
+ private URL buildFileURL;
+
+ /**
+ * The Ant logger class. There may be only one logger. It will have the
+ * right to use the 'out' PrintStream. The class must implements the
+ * BuildLogger interface
+ */
+ private String loggerClassname = null;
+
+ /** Our current message output status. Follows MessageLevel values */
+ private int messageOutputLevel = MessageLevel.MSG_VERBOSE;
+
+ /**
+ * Start the command line front end for mutant.
+ *
+ * @param args the commandline arguments
+ * @param config the initialisation configuration
+ */
+ public static void start(String[] args, InitConfig config) {
+ // create a command line and use it to run ant
+ Commandline commandline = new Commandline();
+ commandline.process(args, config);
+ }
+
+ /**
+ * Adds a feature to the BuildListeners attribute of the Commandline
+ * object
+ *
+ * @param execManager The feature to be added to the BuildListeners
+ * attribute
+ * @exception ConfigException if the necessary listener instances could
+ * not be created
+ */
+ protected void addBuildListeners(ExecutionManager execManager)
+ throws ConfigException {
+
+ // Add the default listener
+ execManager.addBuildListener(createLogger());
+
+ for (Iterator i = listeners.iterator(); i.hasNext(); ) {
+ String className = (String)i.next();
+ try {
+ BuildListener listener =
+ (BuildListener)Class.forName(className).newInstance();
+ execManager.addBuildListener(listener);
+ } catch (ClassCastException e) {
+ System.err.println("The specified listener class "
+ + className +
+ " does not implement the Listener interface");
+ throw new ConfigException("Unable to instantiate listener "
+ + className, e);
+ } catch (Exception e) {
+ System.err.println("Unable to instantiate specified listener "
+ + "class " + className + " : "
+ + e.getClass().getName());
+ throw new ConfigException("Unable to instantiate listener "
+ + className, e);
+ }
+ }
+ }
+
+
+ /**
+ * Start the command line front end for mutant.
+ *
+ * @param args the commandline arguments
+ * @param config the initialisation configuration
+ */
+ private void process(String[] args, InitConfig config) {
+ this.config = config;
+ try {
+ parseArguments(args);
+ Project project = parseProject();
+
+ // create the execution manager to execute the build
+ ExecutionManager executionManager = new ExecutionManager(config);
+ addBuildListeners(executionManager);
+ executionManager.runBuild(project, targets);
+ } catch (AntException e) {
+ Location location = e.getLocation();
+ Throwable cause = e.getCause();
+ System.out.println(e.getMessage());
+
+ if (cause != null) {
+ System.out.print("Root cause: " + cause.getClass().getName());
+ if (!cause.getMessage().equals(e.getMessage())) {
+ System.out.print(": " + cause.getMessage());
+ }
+ System.out.println();
+ }
+
+ e.printStackTrace();
+
+ System.exit(1);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Use the XML parser to parse the build file into a project model
+ *
+ * @return a project model representation of the project file
+ * @exception XMLParseException if the project cannot be parsed
+ */
+ private Project parseProject()
+ throws XMLParseException {
+ XMLProjectParser parser = new XMLProjectParser();
+ Project project = parser.parseBuildFile(buildFileURL);
+ return project;
+ }
+
+ /**
+ * Parse the command line arguments.
+ *
+ * @param args the command line arguments
+ * @exception ConfigException thrown when the command line contains some
+ * sort of error.
+ */
+ private void parseArguments(String[] args)
+ throws ConfigException {
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
+
+ if (arg.equals("-buildfile") || arg.equals("-file")
+ || arg.equals("-f")) {
+ try {
+ String url = args[i + 1];
+ if (url.indexOf(":") == -1) {
+ // We convert any hash characters to their URL escape.
+ buildFileURL = InitUtils.getFileURL(new File(url));
+ } else {
+ buildFileURL = new URL(url);
+ }
+ i++;
+ } catch (MalformedURLException e) {
+ System.err.println("Buildfile is not valid: " +
+ e.getMessage());
+ throw new ConfigException("Build file is not valid", e);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ System.err.println("You must specify a buildfile when " +
+ "using the -buildfile argument");
+ return;
+ }
+ } else if (arg.equals("-logfile") || arg.equals("-l")) {
+ try {
+ File logFile = new File(args[i + 1]);
+ i++;
+ out = new PrintStream(new FileOutputStream(logFile));
+ err = out;
+ } catch (IOException ioe) {
+ System.err.println("Cannot write on the specified log " +
+ "file. Make sure the path exists and " +
+ "you have write permissions.");
+ return;
+ } catch (ArrayIndexOutOfBoundsException aioobe) {
+ System.err.println("You must specify a log file when " +
+ "using the -log argument");
+ return;
+ }
+ } else if (arg.equals("-quiet") || arg.equals("-q")) {
+ messageOutputLevel = MessageLevel.MSG_WARN;
+ } else if (arg.equals("-verbose") || arg.equals("-v")) {
+ // printVersion();
+ messageOutputLevel = MessageLevel.MSG_VERBOSE;
+ } else if (arg.equals("-listener")) {
+ try {
+ listeners.add(args[i + 1]);
+ i++;
+ } catch (ArrayIndexOutOfBoundsException aioobe) {
+ System.err.println("You must specify a classname when " +
+ "using the -listener argument");
+ return;
+ }
+ } else if (arg.equals("-logger")) {
+ if (loggerClassname != null) {
+ System.err.println("Only one logger class may be " +
+ "specified.");
+ return;
+ }
+ try {
+ loggerClassname = args[++i];
+ } catch (ArrayIndexOutOfBoundsException aioobe) {
+ System.err.println("You must specify a classname when " +
+ "using the -logger argument");
+ return;
+ }
+ } else if (arg.startsWith("-")) {
+ // we don't have any more args to recognize!
+ System.out.println("Unknown option: " + arg);
+ return;
+ } else {
+ // if it's no other arg, it must be a target
+ targets.add(arg);
+ }
+ }
+
+ if (buildFileURL == null) {
+ File defaultBuildFile = new File(DEFAULT_BUILD_FILENAME);
+ try {
+ buildFileURL = InitUtils.getFileURL(defaultBuildFile);
+ } catch (MalformedURLException e) {
+ System.err.println("Buildfile is not valid: " + e.getMessage());
+ throw new ConfigException("Build file is not valid", e);
+ }
+ }
+ }
+
+ /**
+ * Creates the default build logger for sending build events to the ant
+ * log.
+ *
+ * @return the logger instance to be used for the build
+ * @exception ConfigException if the logger cannot be instantiatd
+ */
+ private BuildLogger createLogger() throws ConfigException {
+ BuildLogger logger = null;
+ if (loggerClassname != null) {
+ try {
+ Class loggerClass = Class.forName(loggerClassname);
+ logger = (BuildLogger)(loggerClass.newInstance());
+ } catch (ClassCastException e) {
+ System.err.println("The specified logger class "
+ + loggerClassname +
+ " does not implement the BuildLogger interface");
+ throw new ConfigException("Unable to instantiate logger "
+ + loggerClassname, e);
+ } catch (Exception e) {
+ System.err.println("Unable to instantiate specified logger "
+ + "class " + loggerClassname + " : "
+ + e.getClass().getName());
+ throw new ConfigException("Unable to instantiate logger "
+ + loggerClassname, e);
+ }
+ } else {
+ logger = new DefaultLogger();
+ }
+
+ logger.setMessageOutputLevel(messageOutputLevel);
+ logger.setOutputPrintStream(out);
+ logger.setErrorPrintStream(err);
+
+ return logger;
+ }
+}
+
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
new file mode 100755
index 000000000..2bdc977eb
--- /dev/null
+++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java
@@ -0,0 +1,253 @@
+/*
+ * 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.cli;
+
+import java.io.PrintStream;
+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.antcore.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.
+ *
+ * @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 */
+ private PrintStream out;
+ /** The stream to where errors should be written */
+ private PrintStream err;
+ /** The level of messages which should be let through */
+ private int messageOutputLevel = MessageLevel.MSG_ERR;
+
+ /** Controls whether adornments are added */
+ private boolean emacsMode = false;
+ /** 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");
+ }
+
+ }
+
+ /**
+ * 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.
+ *
+ * @param level the logging level for the logger.
+ */
+ public void setMessageOutputLevel(int level) {
+ this.messageOutputLevel = level;
+ }
+
+
+ /**
+ * Set the output stream to which this logger is to send its output.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @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) {
+ this.emacsMode = emacsMode;
+ }
+
+ /**
+ * Report an exception
+ *
+ * @param t The exception to be reported.
+ */
+ public void reportException(Throwable t) {
+ if (t instanceof AntException) {
+ AntException e = (AntException)t;
+ Location location = e.getLocation();
+ Throwable cause = e.getCause();
+ if (location != null && location != Location.UNKNOWN_LOCATION) {
+ out.print(location);
+ }
+ out.println(e.getMessage());
+
+ if (messageOutputLevel >= MessageLevel.MSG_VERBOSE) {
+ t.printStackTrace();
+ }
+
+ if (cause != null) {
+ out.println("Root cause: " + cause.toString());
+ }
+ } else {
+ t.printStackTrace(err);
+ }
+ }
+
+ /**
+ * Process an incoming build event
+ *
+ * @param event the build event to be processed
+ */
+ 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);
+ }
+
+ out.println(lSep + "Total time: "
+ + formatTime(System.currentTimeMillis() - startTime));
+ break;
+ case BuildEvent.TARGET_STARTED:
+ if (MessageLevel.MSG_INFO <= messageOutputLevel) {
+ Target target = (Target)event.getModelElement();
+ 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.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(" ");
+ }
+ logTo.print(msg);
+ }
+
+ // Print the message
+ logTo.println(event.getMessage());
+ }
+ break;
+ default:
+ err.println("Unrecognized event type = " +
+ event.getEventType());
+ break;
+ }
+ }
+
+}
+
diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/BuildElementHandler.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/BuildElementHandler.java
new file mode 100755
index 000000000..2526c32ad
--- /dev/null
+++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/BuildElementHandler.java
@@ -0,0 +1,145 @@
+/*
+ * 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.cli.xml;
+import java.util.Iterator;
+
+import org.apache.ant.antcore.model.BuildElement;
+import org.apache.ant.antcore.xml.ElementHandler;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXParseException;
+
+/**
+ * A BuildElementHandler parses the task elements of a build. Task elements
+ * include tasks themselves plus all their nested elements to any depth.
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class BuildElementHandler extends ElementHandler {
+ /** The task element being parsed by this handler. */
+ private BuildElement buildElement;
+
+ /**
+ * Get the task element being parsed by this handler.
+ *
+ * @return the BuildElement being parsed.
+ */
+ public BuildElement getBuildElement() {
+ return buildElement;
+ }
+
+ /**
+ * Create a task element handler to parse a task element
+ *
+ * @param elementName the name of the element - always target
+ */
+ public void processElement(String elementName) {
+ buildElement
+ = new BuildElement(getLocation(), elementName);
+
+ for (Iterator i = getAttributes(); i.hasNext(); ) {
+ String attributeName = (String)i.next();
+ buildElement.addAttribute(attributeName,
+ getAttribute(attributeName));
+ }
+ buildElement.setAspects(getAspects());
+ }
+
+
+ /**
+ * Process a nested element of this task element. All nested elements of
+ * a buildElement are themselves buildElements.
+ *
+ * @param uri The Namespace URI.
+ * @param localName The local name (without prefix).
+ * @param qualifiedName The qualified name (with prefix)
+ * @param attributes The attributes attached to the element.
+ * @throws SAXParseException if there is a parsing problem.
+ */
+ public void startElement(String uri, String localName, String qualifiedName,
+ Attributes attributes)
+ throws SAXParseException {
+ // everything within a task element is also a task element
+ BuildElementHandler nestedHandler
+ = new BuildElementHandler();
+ nestedHandler.start(getParseContext(), getXMLReader(),
+ this, getLocator(), attributes, getElementSource(), qualifiedName);
+ buildElement.addNestedElement(nestedHandler.getBuildElement());
+ }
+
+
+ /**
+ * This method is called when this element is finished being processed.
+ * This is a template method allowing subclasses to complete any
+ * necessary processing.
+ */
+ protected void finish() {
+ String content = getContent();
+ if (content != null && content.trim().length() != 0) {
+ buildElement.addText(getContent());
+ }
+ }
+
+ /**
+ * Validate that the given attribute and value are valid.
+ *
+ * @param attributeName The name of the attributes
+ * @param attributeValue The value of the attributes
+ */
+ protected void validateAttribute(String attributeName,
+ String attributeValue) {
+ // do nothing - all attributes are OK by default.
+ }
+}
+
diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/IncludeHandler.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/IncludeHandler.java
new file mode 100755
index 000000000..42832ebfc
--- /dev/null
+++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/IncludeHandler.java
@@ -0,0 +1,139 @@
+/*
+ * 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.cli.xml;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.apache.ant.antcore.model.Project;
+import org.apache.ant.antcore.xml.ElementHandler;
+import org.apache.ant.antcore.xml.XMLParseException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * The include handler is used to read in included projects or fragments
+ * into a project.
+ *
+ * @author Conor MacNeill
+ * @created 11 January 2002
+ */
+public class IncludeHandler extends ElementHandler {
+ /** The attribute name which identifies the fragment to be included */
+ public final static String SYSTEMID_ATTR = "fragment";
+
+ /** The including project */
+ private Project project;
+
+
+ /**
+ * Create an IncludeHandler.
+ *
+ * @param project the project into which the include fragment is to be
+ * placed
+ */
+ public IncludeHandler(Project project) {
+ this.project = project;
+ }
+
+
+ /**
+ * Process the element.
+ *
+ * @param elementName the name of the element
+ * @exception SAXParseException if there is a problem parsing the
+ * element
+ */
+ public void processElement(String elementName)
+ throws SAXParseException {
+
+ String includeSystemId = getAttribute(SYSTEMID_ATTR);
+ if (includeSystemId == null) {
+ throw new SAXParseException("Attribute " + SYSTEMID_ATTR +
+ " is required in an element", getLocator());
+ }
+
+ // create a new parser to read this project relative to the
+ // project's URI
+ try {
+ URL includeURL = new URL(getElementSource(), includeSystemId);
+ ProjectHandler includedProjectHandler = new ProjectHandler(project);
+ getParseContext().parse(includeURL,
+ new String[]{"project", "fragment"},
+ includedProjectHandler);
+ } catch (MalformedURLException e) {
+ throw new SAXParseException("Unable to include " + includeSystemId
+ + ": " + e.getMessage(), getLocator());
+ } catch (XMLParseException e) {
+ throw new SAXParseException("Error parsing included project "
+ + includeSystemId + ": " + e.getMessage(), getLocator());
+ }
+ }
+
+ /**
+ * Validate that the given attribute and value are valid.
+ *
+ * @param attributeName The name of the attributes
+ * @param attributeValue The value of the attributes
+ * @exception SAXParseException if the attribute is not allowed on the
+ * element.
+ */
+ protected void validateAttribute(String attributeName,
+ String attributeValue)
+ throws SAXParseException {
+ if (!attributeName.equals(SYSTEMID_ATTR)) {
+ throwInvalidAttribute(attributeName);
+ }
+ }
+}
+
+
diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/NoProjectReadException.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/NoProjectReadException.java
new file mode 100755
index 000000000..5940dc25c
--- /dev/null
+++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/NoProjectReadException.java
@@ -0,0 +1,65 @@
+/*
+ * 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.cli.xml;
+
+/**
+ * A NoProjectReadException is used to indicate that a project was not read
+ * from the particular source. This will happen if the source is empty.
+ *
+ * @author Conor MacNeill
+ * @created 15 January 2002
+ */
+public class NoProjectReadException extends Exception {
+}
+
diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/ProjectHandler.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/ProjectHandler.java
new file mode 100755
index 000000000..1b955b696
--- /dev/null
+++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/ProjectHandler.java
@@ -0,0 +1,206 @@
+/*
+ * 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.cli.xml;
+import org.apache.ant.antcore.model.ModelException;
+import org.apache.ant.antcore.model.Project;
+import org.apache.ant.antcore.xml.ElementHandler;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Element to parse the project element. The project handler creates a
+ * number of different handlers to which it delegates processing of child
+ * elements.
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class ProjectHandler extends ElementHandler {
+ /** The basedir attribute tag */
+ public final static String BASEDIR_ATTR = "basedir";
+
+ /** The name attribute */
+ public final static String NAME_ATTR = "name";
+
+ /** The default attribute name */
+ public final static String DEFAULT_ATTR = "default";
+
+ /** The project being parsed. */
+ private Project project;
+
+ /** Constructor parsing a new project */
+ public ProjectHandler() {
+ project = null;
+ }
+
+ /**
+ * Constructor for including a project or fragment into an existing
+ * project
+ *
+ * @param project The project to be configured by the handler
+ */
+ public ProjectHandler(Project project) {
+ this.project = project;
+ }
+
+ /**
+ * Get the project that has been parsed from the element
+ *
+ * @return the project that has been parsed from the build source
+ * @throws NoProjectReadException thrown if no project was read in.
+ */
+ public Project getProject()
+ throws NoProjectReadException {
+ if (project == null) {
+ throw new NoProjectReadException();
+ }
+ return project;
+ }
+
+
+ /**
+ * Process the project element
+ *
+ * @param elementName the name of the element
+ * @exception SAXParseException if there is a problem parsing the
+ * element
+ */
+ public void processElement(String elementName)
+ throws SAXParseException {
+ if (project == null) {
+ project = new Project(getElementSource(), getLocation());
+
+ project.setDefaultTarget(getAttribute(DEFAULT_ATTR));
+ project.setBase(getAttribute(BASEDIR_ATTR));
+ project.setName(getAttribute(NAME_ATTR));
+ project.setAspects(getAspects());
+ }
+ }
+
+
+ /**
+ * Start a new element in the project. Project currently handles the
+ * following elements
+ *
+ * - ref
+ * - include
+ * - target
+ *
+ * Everything else is treated as a task.
+ *
+ * @param uri The Namespace URI.
+ * @param localName The local name (without prefix).
+ * @param qualifiedName The qualified name (with prefix)
+ * @param attributes The attributes attached to the element.
+ * @throws SAXParseException if there is a parsing problem.
+ */
+ public void startElement(String uri, String localName, String qualifiedName,
+ Attributes attributes)
+ throws SAXParseException {
+ if (qualifiedName.equals("ref")) {
+ RefHandler refHandler = new RefHandler();
+ refHandler.start(getParseContext(), getXMLReader(), this,
+ getLocator(), attributes, getElementSource(),
+ qualifiedName);
+ try {
+ project.referenceProject(refHandler.getRefName(),
+ refHandler.getReferencedProject());
+ } catch (ModelException e) {
+ throw new SAXParseException(e.getMessage(), getLocator(), e);
+ }
+ } else if (qualifiedName.equals("include")) {
+ IncludeHandler includeHandler = new IncludeHandler(project);
+ includeHandler.start(getParseContext(), getXMLReader(),
+ this, getLocator(), attributes, getElementSource(),
+ qualifiedName);
+ } else if (qualifiedName.equals("target")) {
+ TargetHandler targetHandler = new TargetHandler();
+ targetHandler.start(getParseContext(), getXMLReader(),
+ this, getLocator(), attributes,
+ getElementSource(), qualifiedName);
+ try {
+ project.addTarget(targetHandler.getTarget());
+ } catch (ModelException e) {
+ throw new SAXParseException(e.getMessage(), getLocator(), e);
+ }
+ } else {
+ // everything else is a task
+ BuildElementHandler buildElementHandler = new BuildElementHandler();
+ buildElementHandler.start(getParseContext(), getXMLReader(),
+ this, getLocator(), attributes, getElementSource(),
+ qualifiedName);
+ project.addTask(buildElementHandler.getBuildElement());
+ }
+ }
+
+ /**
+ * Validate that the given attribute and value are valid.
+ *
+ * @param attributeName The name of the attributes
+ * @param attributeValue The value of the attributes
+ * @exception SAXParseException if the attribute is not allowed on the
+ * element.
+ */
+ protected void validateAttribute(String attributeName,
+ String attributeValue)
+ throws SAXParseException {
+ if (!attributeName.equals(BASEDIR_ATTR) &&
+ !attributeName.equals(NAME_ATTR) &&
+ !attributeName.equals(DEFAULT_ATTR)) {
+ throwInvalidAttribute(attributeName);
+ }
+ }
+}
+
+
diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/RefHandler.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/RefHandler.java
new file mode 100755
index 000000000..3e7d45e0d
--- /dev/null
+++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/RefHandler.java
@@ -0,0 +1,161 @@
+/*
+ * 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.cli.xml;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.apache.ant.antcore.model.Project;
+import org.apache.ant.antcore.xml.ElementHandler;
+import org.apache.ant.antcore.xml.XMLParseException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * The Ref handler handles the reference of one project to another. The
+ * project to be references is parsed with a new parser and then added to
+ * the current project under the given alias
+ *
+ * @author Conor MacNeill
+ * @created 10 January 2002
+ */
+public class RefHandler extends ElementHandler {
+ /** The attribute used to name the ref. */
+ public final static String NAME_ATTR = "name";
+
+ /** The attribute name used to locate the project to be referenced. */
+ public final static String SYSTEMID_ATTR = "project";
+
+ /** The project that has been referenced. */
+ private Project referencedProject;
+
+ /**
+ * Get the project referenced.
+ *
+ * @return an referenced Project.
+ */
+ public Project getReferencedProject() {
+ return referencedProject;
+ }
+
+
+ /**
+ * Get the name under which the project is referenced.
+ *
+ * @return the ref name of the project
+ */
+ public String getRefName() {
+ return getAttribute(NAME_ATTR);
+ }
+
+
+ /**
+ * Create an ref handler to reference a project.
+ *
+ * @param elementName the name of the ref element
+ * @exception SAXParseException if the ref element could not be parsed
+ */
+ public void processElement(String elementName)
+ throws SAXParseException {
+ String refName = getAttribute(NAME_ATTR);
+ if (refName == null) {
+ throw new SAXParseException("Attribute " + NAME_ATTR +
+ " is required in a [ element", getLocator());
+ }
+
+ String projectSystemId = getAttribute(SYSTEMID_ATTR);
+ if (projectSystemId == null) {
+ throw new SAXParseException("Attribute " + SYSTEMID_ATTR +
+ " is required in a ][ element", getLocator());
+ }
+
+ // create a new parser to read this project relative to the
+ // project's URI
+ try {
+ URL refURL = new URL(getElementSource(), projectSystemId);
+ ProjectHandler referencedProjectHandler = new ProjectHandler();
+ getParseContext().parse(refURL, "project",
+ referencedProjectHandler);
+
+ referencedProject = referencedProjectHandler.getProject();
+ } catch (XMLParseException e) {
+ throw new SAXParseException("Error parsing referenced project "
+ + projectSystemId + ": " + e.getMessage(), getLocator());
+ } catch (NoProjectReadException e) {
+ throw new SAXParseException("No project found in the reference: "
+ + projectSystemId, getLocator());
+ } catch (MalformedURLException e) {
+ throw new SAXParseException("Unable to reference project "
+ + projectSystemId + ": " + e.getMessage(),
+ getLocator());
+ }
+ }
+
+ /**
+ * Validate that the given attribute and value are valid.
+ *
+ * @param attributeName The name of the attributes
+ * @param attributeValue The value of the attributes
+ * @exception SAXParseException if the attribute is not allowed on the
+ * element.
+ */
+ protected void validateAttribute(String attributeName,
+ String attributeValue)
+ throws SAXParseException {
+ if (!attributeName.equals(SYSTEMID_ATTR) &&
+ !attributeName.equals(NAME_ATTR)) {
+ throwInvalidAttribute(attributeName);
+ }
+ }
+}
+
+
diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/TargetHandler.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/TargetHandler.java
new file mode 100755
index 000000000..250ddd65c
--- /dev/null
+++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/TargetHandler.java
@@ -0,0 +1,155 @@
+/*
+ * 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.cli.xml;
+import java.util.StringTokenizer;
+
+import org.apache.ant.antcore.model.Target;
+import org.apache.ant.antcore.xml.ElementHandler;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Element handler for the target element
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class TargetHandler extends ElementHandler {
+ /** The name attribute */
+ public final static String NAME_ATTR = "name";
+
+ /** The depends attribute name */
+ public final static String DEPENDS_ATTR = "depends";
+
+ /** The depends attribute name */
+ public final static String DESC_ATTR = "description";
+
+ /** The target being configured. */
+ private Target target;
+
+ /**
+ * Get the target parsed by this handler.
+ *
+ * @return the Target model object parsed by this handler.
+ */
+ public Target getTarget() {
+ return target;
+ }
+
+
+ /**
+ * Process the target element.
+ *
+ * @param elementName the name of the element
+ * @exception SAXParseException if there is a problem parsing the
+ * element
+ */
+ public void processElement(String elementName)
+ throws SAXParseException {
+ String targetName = null;
+ target = new Target(getLocation(), getAttribute(NAME_ATTR));
+ target.setDescription(getAttribute(DESC_ATTR));
+ target.setAspects(getAspects());
+
+ String depends = getAttribute(DEPENDS_ATTR);
+ if (depends != null) {
+ StringTokenizer tokenizer = new StringTokenizer(depends, ",");
+ while (tokenizer.hasMoreTokens()) {
+ String dependency = tokenizer.nextToken();
+ target.addDependency(dependency);
+ }
+ }
+ }
+
+
+ /**
+ * Process an element within this target. All elements within the target
+ * are treated as tasks.
+ *
+ * @param uri The Namespace URI.
+ * @param localName The local name (without prefix).
+ * @param qualifiedName The qualified name (with prefix)
+ * @param attributes The attributes attached to the element.
+ * @throws SAXParseException if there is a parsing problem.
+ */
+ public void startElement(String uri, String localName, String qualifiedName,
+ Attributes attributes)
+ throws SAXParseException {
+ // everything is a task
+ BuildElementHandler taskHandler = new BuildElementHandler();
+ taskHandler.start(getParseContext(), getXMLReader(), this, getLocator(),
+ attributes, getElementSource(), qualifiedName);
+ target.addTask(taskHandler.getBuildElement());
+ }
+
+ /**
+ * Validate that the given attribute and value are valid.
+ *
+ * @param attributeName The name of the attributes
+ * @param attributeValue The value of the attributes
+ * @exception SAXParseException if the attribute is not allowed on the
+ * element.
+ */
+ protected void validateAttribute(String attributeName,
+ String attributeValue)
+ throws SAXParseException {
+ if (!attributeName.equals(NAME_ATTR) &&
+ !attributeName.equals(DEPENDS_ATTR) &&
+ !attributeName.equals(DESC_ATTR)) {
+ throwInvalidAttribute(attributeName);
+ }
+ }
+}
+
+
diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/XMLProjectParser.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/XMLProjectParser.java
new file mode 100755
index 000000000..f9ceaf58a
--- /dev/null
+++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/XMLProjectParser.java
@@ -0,0 +1,92 @@
+/*
+ * 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.cli.xml;
+import java.net.URL;
+
+import org.apache.ant.common.util.Location;
+import org.apache.ant.antcore.model.Project;
+import org.apache.ant.antcore.xml.ParseContext;
+import org.apache.ant.antcore.xml.XMLParseException;
+
+/**
+ * Parses an Ant project model from an XML source using a SAX Parser.
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class XMLProjectParser {
+ /**
+ * Parse a build file from the given URL.
+ *
+ * @param buildSource the URL from where the build source may be read.
+ * @return a project model representing the project
+ * @exception XMLParseException if there is an problem parsing the XML
+ * representation
+ */
+ public Project parseBuildFile(URL buildSource)
+ throws XMLParseException {
+ try {
+ ParseContext context = new ParseContext();
+ ProjectHandler projectHandler = new ProjectHandler();
+
+ context.parse(buildSource, "project", projectHandler);
+
+ return projectHandler.getProject();
+ } catch (NoProjectReadException e) {
+ throw new XMLParseException("No project defined in build source ",
+ e, new Location(buildSource.toString()));
+ }
+ }
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/context/AntContext.java b/proposal/mutant/src/java/common/org/apache/ant/common/context/AntContext.java
new file mode 100755
index 000000000..cd62184c0
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/context/AntContext.java
@@ -0,0 +1,85 @@
+/*
+ * 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.context;
+
+import java.io.File;
+import org.apache.ant.common.util.AntException;
+
+/**
+ * The TaskContext is the interface through which the Ant Task container and
+ * the Task instances communicate
+ *
+ * @author Conor MacNeill
+ * @created 14 January 2002
+ */
+public abstract class AntContext {
+ /**
+ * Log a message
+ *
+ * @param message the message to be logged
+ * @param level the priority level of the message
+ */
+ public abstract void log(String message, int level);
+
+ /**
+ * Resolve a file according to the base directory of the project
+ * associated with this context
+ *
+ * @param fileName the file name to be resolved.
+ * @return the file resolved to the project's base dir
+ * @exception AntException if the file cannot be resolved
+ */
+ public abstract File resolveFile(String fileName) throws AntException;
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/converter/AbstractConverter.java b/proposal/mutant/src/java/common/org/apache/ant/common/converter/AbstractConverter.java
new file mode 100755
index 000000000..e1e07db78
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/converter/AbstractConverter.java
@@ -0,0 +1,86 @@
+/*
+ * 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.converter;
+
+import org.apache.ant.common.context.AntContext;
+
+/**
+ * Abstract implementation of the Converter interface
+ *
+ * @author Conor MacNeill
+ */
+public abstract class AbstractConverter implements Converter {
+ /** The converters's context */
+ private AntContext context;
+
+ /**
+ * Initialise the converter. The converter may use the AntContext to request
+ * services from the Ant core.
+ *
+ * @param context the Converter's context
+ */
+ public void init(AntContext context) {
+ this.context = context;
+ }
+
+ /**
+ * Get this converter's context
+ *
+ * @return the converter context
+ */
+ protected AntContext getContext() {
+ return context;
+ }
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/converter/ConversionException.java b/proposal/mutant/src/java/common/org/apache/ant/common/converter/ConversionException.java
new file mode 100755
index 000000000..b92185b36
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/converter/ConversionException.java
@@ -0,0 +1,135 @@
+/*
+ * 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.converter;
+
+import org.apache.ant.common.util.AntException;
+import org.apache.ant.common.util.Location;
+
+/**
+ * Exception class for problems when converting values
+ *
+ * @author Conor MacNeill
+ * @created 20 January 2002
+ */
+public class ConversionException extends AntException {
+ /**
+ * Constructs an exception with the given descriptive message.
+ *
+ * @param msg Description of or information about the exception.
+ */
+ public ConversionException(String msg) {
+ super(msg);
+ }
+
+
+ /**
+ * Constructs an exception with the given descriptive message and a
+ * location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param location Location in the project file where the error occured.
+ */
+ public ConversionException(String msg, Location location) {
+ super(msg, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Throwable that might have cause this one.
+ */
+ public ConversionException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause and a location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public ConversionException(String msg, Throwable cause, Location location) {
+ super(msg, cause, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause.
+ *
+ * @param cause Exception that might have caused this one.
+ */
+ public ConversionException(Throwable cause) {
+ super(cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause and
+ * a location in a file.
+ *
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public ConversionException(Throwable cause, Location location) {
+ super(cause, location);
+ }
+
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/converter/Converter.java b/proposal/mutant/src/java/common/org/apache/ant/common/converter/Converter.java
new file mode 100755
index 000000000..07c4f4548
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/converter/Converter.java
@@ -0,0 +1,92 @@
+/*
+ * 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.converter;
+
+import org.apache.ant.common.context.AntContext;
+
+/**
+ * Convert between a string and a data type
+ *
+ * @author Conor MacNeill
+ * @created 19 January 2002
+ */
+public interface Converter {
+ /**
+ * Convert a string from the value given to an instance of the given
+ * type.
+ *
+ * @param value The value to be converted
+ * @param type the desired type of the converted object
+ * @return the value of the converted object
+ * @exception ConversionException if the conversion cannot be made
+ */
+ Object convert(String value, Class type) throws ConversionException;
+
+ /**
+ * Initialise the converter. The converter may use the AntContext to
+ * request services from the Ant core.
+ *
+ * @param context the Converter's AntContext
+ */
+ void init(AntContext context);
+
+ /**
+ * Get the list of classes this converter is able to convert to.
+ *
+ * @return an array of Class objects representing the classes this
+ * converter handles.
+ */
+ Class[] getTypes();
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/task/AbstractTask.java b/proposal/mutant/src/java/common/org/apache/ant/common/task/AbstractTask.java
new file mode 100755
index 000000000..c0e488e38
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/task/AbstractTask.java
@@ -0,0 +1,101 @@
+/*
+ * 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.task;
+import org.apache.ant.common.context.AntContext;
+
+/**
+ * Abstract implementation of the Task interface
+ *
+ * @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;
+ }
+
+ /** 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/task/DataType.java b/proposal/mutant/src/java/common/org/apache/ant/common/task/DataType.java
new file mode 100755
index 000000000..256e154a6
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/task/DataType.java
@@ -0,0 +1,74 @@
+/*
+ * 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.task;
+import org.apache.ant.common.context.AntContext;
+
+/**
+ * This is the interface used to descibe Ant types. A class used as a
+ * datatype which implements this interface will be given an AntContext
+ * instance through which it may interact with the Ant core.
+ *
+ * @author Conor MacNeill
+ * @created 20 January 2002
+ */
+public interface DataType {
+ /**
+ * Initialise the type instance. The type instance may use the
+ * AntContext to request services from the Ant core.
+ *
+ * @param context the type's context
+ */
+ void init(AntContext context);
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/task/Task.java b/proposal/mutant/src/java/common/org/apache/ant/common/task/Task.java
new file mode 100755
index 000000000..1bb2c41f4
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/task/Task.java
@@ -0,0 +1,82 @@
+/*
+ * 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.task;
+import org.apache.ant.common.context.AntContext;
+
+/**
+ * The Task interface defines the methods that a Task must implement.
+ *
+ * @author Conor MacNeill
+ * @created 16 January 2002
+ */
+public interface Task {
+ /**
+ * Initialise the task. The task may use the AntContext to request
+ * services from the Ant core.
+ *
+ * @param context the Task's context
+ */
+ void init(AntContext context);
+
+ /**
+ * Execute the task.
+ *
+ * @exception TaskException if the task has a problem executing.
+ */
+ void execute() throws TaskException;
+
+ /** Task is about to be cleaned up */
+ void destroy();
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/task/TaskContainer.java b/proposal/mutant/src/java/common/org/apache/ant/common/task/TaskContainer.java
new file mode 100755
index 000000000..2397dce02
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/task/TaskContainer.java
@@ -0,0 +1,71 @@
+/*
+ * 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.task;
+
+/**
+ * A TaskContainer is an object which can contain and manage ExecutionTasks.
+ *
+ * @author Conor MacNeill
+ * @created 19 January 2002
+ */
+public interface TaskContainer {
+ /**
+ * Add a task to the container.
+ *
+ * @param task the task tobe added
+ * @exception TaskException if the container cannot add the task
+ */
+ void addTask(Task task) throws TaskException;
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/task/TaskException.java b/proposal/mutant/src/java/common/org/apache/ant/common/task/TaskException.java
new file mode 100755
index 000000000..20b0d0c83
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/task/TaskException.java
@@ -0,0 +1,135 @@
+/*
+ * 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.task;
+
+import org.apache.ant.common.util.AntException;
+import org.apache.ant.common.util.Location;
+
+/**
+ * An TaskException indicates a problem while executing tasks in a build
+ *
+ * @author Conor MacNeill
+ * @created 16 January 2002
+ */
+public class TaskException extends AntException {
+ /**
+ * Constructs an exception with the given descriptive message.
+ *
+ * @param msg Description of or information about the exception.
+ */
+ public TaskException(String msg) {
+ super(msg);
+ }
+
+
+ /**
+ * Constructs an exception with the given descriptive message and a
+ * location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param location Location in the project file where the error occured.
+ */
+ public TaskException(String msg, Location location) {
+ super(msg, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Throwable that might have cause this one.
+ */
+ public TaskException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause and a location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public TaskException(String msg, Throwable cause, Location location) {
+ super(msg, cause, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause.
+ *
+ * @param cause Exception that might have caused this one.
+ */
+ public TaskException(Throwable cause) {
+ super(cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause and
+ * a location in a file.
+ *
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public TaskException(Throwable cause, Location location) {
+ super(cause, location);
+ }
+
+}
+
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
new file mode 100755
index 000000000..bd5f3610d
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/AntException.java
@@ -0,0 +1,213 @@
+/*
+ * 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.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * An AntException indicates some exceptional case has been encountered in
+ * the processing of Ant. AntExceptions may accept a Throwable as a cause
+ * allowing exceptions to be nested
+ *
+ * @author Conor MacNeill
+ * @created 15 January 2002
+ */
+public abstract class AntException extends Exception {
+ /** Exception that might have caused this one. */
+ private Throwable cause = null;
+
+ /**
+ * The location of the element which is associated with this exception
+ * if known.
+ */
+ private Location location = Location.UNKNOWN_LOCATION;
+
+ /**
+ * Constructs an exception with the given descriptive message.
+ *
+ * @param msg Description of or information about the exception.
+ */
+ public AntException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Throwable that might have cause this one.
+ */
+ public AntException(String msg, Throwable cause) {
+ super(msg);
+ this.cause = cause;
+ }
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause and a location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public AntException(String msg, Throwable cause, Location location) {
+ this(msg, cause);
+ setLocation(location);
+ }
+
+ /**
+ * Constructs an exception with the given exception as a root cause.
+ *
+ * @param cause Exception that might have caused this one.
+ */
+ public AntException(Throwable cause) {
+ super(cause.getMessage());
+ this.cause = cause;
+ }
+
+ /**
+ * Constructs an exception with the given descriptive message and a
+ * location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param location Location in the project file where the error occured.
+ */
+ public AntException(String msg, Location location) {
+ super(msg);
+ setLocation(location);
+ }
+
+ /**
+ * Constructs an exception with the given exception as a root cause and
+ * a location in a file.
+ *
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public AntException(Throwable cause, Location location) {
+ this(cause);
+ setLocation(location);
+ }
+
+ /**
+ * Sets the file location where the error occured.
+ *
+ * @param location the new location value
+ */
+ public void setLocation(Location location) {
+ if (location == null) {
+ this.location = Location.UNKNOWN_LOCATION;
+ } else {
+ this.location = location;
+ }
+ }
+
+ /**
+ * Returns the nested exception.
+ *
+ * @return the underlying exception
+ */
+ public Throwable getCause() {
+ return cause;
+ }
+
+ /**
+ * Returns the file location where the error occured.
+ *
+ * @return the location value
+ */
+ public Location getLocation() {
+ return location;
+ }
+
+ /** Print the stack trace to System.err */
+ public void printStackTrace() {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * Print the stack trace to the given PrintStream
+ *
+ * @param ps the PrintStream onto which the stack trace of this
+ * exception is to be printed
+ */
+ public void printStackTrace(PrintStream ps) {
+ synchronized (ps) {
+ super.printStackTrace(ps);
+ if (cause != null) {
+ ps.println("--- Nested Exception ---");
+ cause.printStackTrace(ps);
+ }
+ }
+ }
+
+ /**
+ * Print the stack trace to the given PrintWriter
+ *
+ * @param pw the PrintWriter onto which the stack trace of this
+ * exception is to be printed
+ */
+ public void printStackTrace(PrintWriter pw) {
+ synchronized (pw) {
+ super.printStackTrace(pw);
+ if (cause != null) {
+ pw.println("--- Nested Exception ---");
+ cause.printStackTrace(pw);
+ }
+ }
+ }
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/FileUtils.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/FileUtils.java
new file mode 100644
index 000000000..bfe62ae18
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/FileUtils.java
@@ -0,0 +1,243 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001-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.util;
+
+import java.io.File;
+import java.util.Stack;
+import java.util.StringTokenizer;
+
+/**
+ * This class encapsulates methods which allow Files to be refered to using
+ * abstract path names which are translated to native system file paths at
+ * runtime as well as copying files or setting there last modification time.
+ *
+ * @author duncan@x180.com
+ * @author Conor MacNeill
+ * @author Stefan Bodewig
+ * @created 21 January 2002
+ */
+public class FileUtils {
+ /**
+ * Interpret the filename as a file relative to the given file - unless
+ * the filename already represents an absolute filename.
+ *
+ * @param file the "reference" file for relative paths. This instance
+ * must be an absolute file and must not contain "./" or
+ * "../" sequences (same for \ instead of /). If it is
+ * null, this call is equivalent to
+ * ]new java.io.File(filename)
+ * .
+ * @param filename a file name
+ * @return an absolute file that doesn't contain "./" or
+ * "../" sequences and uses the correct separator for the
+ * current platform.
+ * @exception GeneralAntException if the file cannot be resolved
+ */
+ public File resolveFile(File file, String filename)
+ throws GeneralAntException {
+ filename = filename.replace('/', File.separatorChar)
+ .replace('\\', File.separatorChar);
+
+ // deal with absolute files
+ if (filename.startsWith(File.separator) ||
+ (filename.length() >= 2 &&
+ Character.isLetter(filename.charAt(0)) &&
+ filename.charAt(1) == ':')
+ ) {
+ return normalize(filename);
+ }
+
+ if (file == null) {
+ return new File(filename);
+ }
+
+ File helpFile = new File(file.getAbsolutePath());
+ StringTokenizer tok = new StringTokenizer(filename, File.separator);
+ while (tok.hasMoreTokens()) {
+ String part = tok.nextToken();
+ if (part.equals("..")) {
+ helpFile = helpFile.getParentFile();
+ if (helpFile == null) {
+ String msg = "The file or path you specified ("
+ + filename + ") is invalid relative to "
+ + file.getPath();
+ throw new GeneralAntException(msg);
+ }
+ } else if (part.equals(".")) {
+ // Do nothing here
+ } else {
+ helpFile = new File(helpFile, part);
+ }
+ }
+
+ return new File(helpFile.getAbsolutePath());
+ }
+
+ /**
+ * "normalize" the given absolute path.
+ *
+ * This includes:
+ *
+ * - Uppercase the drive letter if there is one.
+ * - Remove redundant slashes after the drive spec.
+ * - resolve all ./, .\, ../ and ..\ sequences.
+ * - DOS style paths that start with a drive letter will have \ as
+ * the separator.
+ *
+ *
+ *
+ * @param path the path to be normalized
+ * @return the normalized path
+ * @exception GeneralAntException if there is a problem with the path
+ * @throws NullPointerException if the file path is equal to null.
+ */
+ public File normalize(String path)
+ throws NullPointerException, GeneralAntException {
+ String orig = path;
+
+ path = path.replace('/', File.separatorChar)
+ .replace('\\', File.separatorChar);
+
+ // make sure we are dealing with an absolute path
+ if (!path.startsWith(File.separator) &&
+ !(path.length() >= 2 &&
+ Character.isLetter(path.charAt(0)) &&
+ path.charAt(1) == ':')
+ ) {
+ String msg = path + " is not an absolute path";
+ throw new GeneralAntException(msg);
+ }
+
+ boolean dosWithDrive = false;
+ String root = null;
+ // Eliminate consecutive slashes after the drive spec
+ if (path.length() >= 2 &&
+ Character.isLetter(path.charAt(0)) &&
+ path.charAt(1) == ':') {
+
+ dosWithDrive = true;
+
+ char[] ca = path.replace('/', '\\').toCharArray();
+ StringBuffer sb = new StringBuffer();
+ sb.append(Character.toUpperCase(ca[0])).append(':');
+
+ for (int i = 2; i < ca.length; i++) {
+ if ((ca[i] != '\\') ||
+ (ca[i] == '\\' && ca[i - 1] != '\\')
+ ) {
+ sb.append(ca[i]);
+ }
+ }
+
+ path = sb.toString().replace('\\', File.separatorChar);
+ if (path.length() == 2) {
+ root = path;
+ path = "";
+ } else {
+ root = path.substring(0, 3);
+ path = path.substring(3);
+ }
+
+ } else {
+ if (path.length() == 1) {
+ root = File.separator;
+ path = "";
+ } else if (path.charAt(1) == File.separatorChar) {
+ // UNC drive
+ root = File.separator + File.separator;
+ path = path.substring(2);
+ } else {
+ root = File.separator;
+ path = path.substring(1);
+ }
+ }
+
+ Stack s = new Stack();
+ s.push(root);
+ StringTokenizer tok = new StringTokenizer(path, File.separator);
+ while (tok.hasMoreTokens()) {
+ String thisToken = tok.nextToken();
+ if (".".equals(thisToken)) {
+ continue;
+ } else if ("..".equals(thisToken)) {
+ if (s.size() < 2) {
+ throw new GeneralAntException("Cannot resolve path "
+ + orig);
+ } else {
+ s.pop();
+ }
+ } else {// plain component
+ s.push(thisToken);
+ }
+ }
+
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.size(); i++) {
+ if (i > 1) {
+ // not before the filesystem root and not after it, since root
+ // already contains one
+ sb.append(File.separatorChar);
+ }
+ sb.append(s.elementAt(i));
+ }
+
+ path = sb.toString();
+ if (dosWithDrive) {
+ path = path.replace('/', '\\');
+ }
+ return new File(path);
+ }
+
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/GeneralAntException.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/GeneralAntException.java
new file mode 100755
index 000000000..c930d8299
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/GeneralAntException.java
@@ -0,0 +1,133 @@
+/*
+ * 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.util;
+
+/**
+ * An GeneralAntException is used to for any exception case for which there
+ * is no specific AntException subclass which is appropriate
+ *
+ * @author Conor MacNeill
+ * @created 21 January 2002
+ */
+public class GeneralAntException extends AntException {
+ /**
+ * Constructs an exception with the given descriptive message.
+ *
+ * @param msg Description of or information about the exception.
+ */
+ public GeneralAntException(String msg) {
+ super(msg);
+ }
+
+
+ /**
+ * Constructs an exception with the given descriptive message and a
+ * location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param location Location in the project file where the error occured.
+ */
+ public GeneralAntException(String msg, Location location) {
+ super(msg, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Throwable that might have cause this one.
+ */
+ public GeneralAntException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause and a location in a file.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public GeneralAntException(String msg, Throwable cause, Location location) {
+ super(msg, cause, location);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause.
+ *
+ * @param cause Exception that might have caused this one.
+ */
+ public GeneralAntException(Throwable cause) {
+ super(cause);
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause and
+ * a location in a file.
+ *
+ * @param cause Exception that might have cause this one.
+ * @param location Location in the project file where the error occured.
+ */
+ public GeneralAntException(Throwable cause, Location location) {
+ super(cause, location);
+ }
+
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/Location.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/Location.java
new file mode 100755
index 000000000..bdda5a012
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/Location.java
@@ -0,0 +1,159 @@
+/*
+ * 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.util;
+
+/**
+ * Stores the file name and line number in a file.
+ *
+ * @author Conor MacNeill
+ * @created 16 January 2002
+ */
+public class Location {
+
+ /** Standard unknown location constant; */
+ public final static Location UNKNOWN_LOCATION = new Location();
+ /** The source URL to which this location relates. */
+ private String source;
+
+ /** The line number of this location within the source */
+ private int lineNumber;
+
+ /** The column number of this location within the source */
+ private int columnNumber;
+
+ /**
+ * Creates a location consisting of a source location but no line
+ * number.
+ *
+ * @param source the source (URL) to which this location is associated.
+ */
+ public Location(String source) {
+ this(source, 1, 1);
+ }
+
+ /**
+ * Creates a location consisting of a source location and co-ordinates
+ * within that source
+ *
+ * @param source the source (URL) to which this location is associated.
+ * @param lineNumber the line number of this location
+ * @param columnNumber the column number of this location
+ */
+ public Location(String source, int lineNumber, int columnNumber) {
+ this.source = source;
+ this.lineNumber = lineNumber;
+ this.columnNumber = columnNumber;
+ }
+
+ /** Creates an "unknown" location. */
+ private Location() {
+ this(null, 0, 0);
+ }
+
+ /**
+ * Get the source URL for this location
+ *
+ * @return a URL string
+ */
+ public String getSourceURL() {
+ return source;
+ }
+
+ /**
+ * Get the line number of this location
+ *
+ * @return an integer line number
+ */
+ public int getLineNumber() {
+ return lineNumber;
+ }
+
+ /**
+ * Get the column number of this location
+ *
+ * @return an integer column number
+ */
+ public int getColumnNumber() {
+ return columnNumber;
+ }
+
+ /**
+ * Returns the source name, line number and a trailing space. An error
+ * message can be appended easily. For unknown locations, returns an
+ * empty string.
+ *
+ * @return a suitable string representation of the location
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+
+ if (source != null) {
+ if (source.startsWith("file:")) {
+ buf.append(source.substring(5));
+ } else {
+ buf.append(source);
+ }
+
+ if (lineNumber != 0) {
+ buf.append(":");
+ buf.append(lineNumber);
+ }
+
+ buf.append(": ");
+ }
+
+ return buf.toString();
+ }
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/MessageLevel.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/MessageLevel.java
new file mode 100755
index 000000000..bdcdc673f
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/MessageLevel.java
@@ -0,0 +1,74 @@
+/*
+ * 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.util;
+
+/**
+ * The levels at which a log message may be sent.
+ *
+ * @author Conor MacNeill
+ * @created 16 January 2002
+ */
+public class MessageLevel {
+ /** Error message level */
+ public final static int MSG_ERR = 0;
+ /** Warnign message level */
+ public final static int MSG_WARN = 1;
+ /** Informational message level */
+ public final static int MSG_INFO = 2;
+ /** Verbose message level */
+ public final static int MSG_VERBOSE = 3;
+ /** Debug Message level */
+ public final static int MSG_DEBUG = 4;
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/PathTokenizer.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/PathTokenizer.java
new file mode 100755
index 000000000..e3a3b45bd
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/PathTokenizer.java
@@ -0,0 +1,144 @@
+/*
+ * 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.util;
+import java.io.File;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+/**
+ * A Path tokenizer takes a path and returns the components that make up
+ * that path. The path can use path separators of either ':' or ';' and file
+ * separators of either '/' or '\'
+ *
+ * @author Conor MacNeill (conor@ieee.org)
+ * @created 20 January 2002
+ */
+public class PathTokenizer {
+ /**
+ * A tokenizer to break the string up based on the ':' or ';'
+ * separators.
+ */
+ private StringTokenizer tokenizer;
+
+ /**
+ * A String which stores any path components which have been read ahead.
+ */
+ private String lookahead = null;
+
+ /**
+ * Flag to indicate whether we are running on a platform with a DOS
+ * style filesystem
+ */
+ private boolean dosStyleFilesystem;
+
+ /**
+ * Create a path tokenizer to access the components of the path
+ *
+ * @param path the path to be tokenized
+ */
+ public PathTokenizer(String path) {
+ tokenizer = new StringTokenizer(path, ":;", false);
+ dosStyleFilesystem = File.pathSeparatorChar == ';';
+ }
+
+ /**
+ * Indicate if there are more tokens available
+ *
+ * @return true if there are more tokens available
+ */
+ public boolean hasMoreTokens() {
+ if (lookahead != null) {
+ return true;
+ }
+
+ return tokenizer.hasMoreTokens();
+ }
+
+ /**
+ * Get the next token from the path's list of components
+ *
+ * @return the path component
+ * @exception NoSuchElementException if there are no more components
+ * available.
+ */
+ public String nextToken() throws NoSuchElementException {
+ String token = null;
+ if (lookahead != null) {
+ token = lookahead;
+ lookahead = null;
+ } else {
+ token = tokenizer.nextToken().trim();
+ }
+
+ if (token.length() == 1 && Character.isLetter(token.charAt(0))
+ && dosStyleFilesystem
+ && tokenizer.hasMoreTokens()) {
+ // we are on a dos style system so this path could be a drive
+ // spec. We look at the next token
+ String nextToken = tokenizer.nextToken().trim();
+ if (nextToken.startsWith("\\") || nextToken.startsWith("/")) {
+ // we know we are on a DOS style platform and the next path
+ // starts with a slash or backslash, so we know this is a
+ // drive spec
+ token += ":" + nextToken;
+ } else {
+ // store the token just read for next time
+ lookahead = nextToken;
+ }
+ }
+
+ return token;
+ }
+}
+
diff --git a/proposal/mutant/src/java/init/org/apache/ant/init/ClassLocator.java b/proposal/mutant/src/java/init/org/apache/ant/init/ClassLocator.java
new file mode 100755
index 000000000..52f0eae7e
--- /dev/null
+++ b/proposal/mutant/src/java/init/org/apache/ant/init/ClassLocator.java
@@ -0,0 +1,107 @@
+/*
+ * 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.init;
+import java.net.MalformedURLException;
+
+import java.net.URL;
+
+/**
+ * The ClassLocator is a utility class which is used to determine the URL
+ * from which a class was loaded.
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class ClassLocator {
+ /**
+ * Get the URL for the given class's load location.
+ *
+ * @param theClass the class whose loadURL is desired.
+ * @return a URL which identifies the component from which this class
+ * was loaded.
+ * @throws MalformedURLException if the class' URL cannot be
+ * constructed.
+ */
+ public static URL getClassLocationURL(Class theClass)
+ throws MalformedURLException {
+ String className = theClass.getName().replace('.', '/') + ".class";
+ URL classRawURL = theClass.getClassLoader().getResource(className);
+
+ String fileComponent = classRawURL.getFile();
+ if (classRawURL.getProtocol().equals("file")) {
+ // Class comes from a directory of class files rather than
+ // from a jar.
+ int classFileIndex = fileComponent.lastIndexOf(className);
+ if (classFileIndex != -1) {
+ fileComponent = fileComponent.substring(0, classFileIndex);
+ }
+
+ return new URL("file:" + fileComponent);
+ } else if (classRawURL.getProtocol().equals("jar")) {
+ // Class is coming from a jar. The file component of the URL
+ // is actually the URL of the jar file
+ int classSeparatorIndex = fileComponent.lastIndexOf("!");
+ if (classSeparatorIndex != -1) {
+ fileComponent = fileComponent.substring(0, classSeparatorIndex);
+ }
+
+ return new URL(fileComponent);
+ } else {
+ // its running out of something besides a jar.
+ // We just return the Raw URL as a best guess
+ return classRawURL;
+ }
+ }
+}
+
diff --git a/proposal/mutant/src/java/init/org/apache/ant/init/InitConfig.java b/proposal/mutant/src/java/init/org/apache/ant/init/InitConfig.java
new file mode 100755
index 000000000..7d259f7ac
--- /dev/null
+++ b/proposal/mutant/src/java/init/org/apache/ant/init/InitConfig.java
@@ -0,0 +1,271 @@
+/*
+ * 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.init;
+
+import java.net.URL;
+
+/**
+ * InitConfig is the initialization configuration created to start Ant. This
+ * is passed to the front end when Ant is started.
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class InitConfig {
+ /** The system classloader */
+ private ClassLoader systemLoader;
+
+ /**
+ * The common class loader loads components which are common to tasks
+ * and the core
+ */
+ private ClassLoader commonLoader;
+
+ /**
+ * The core loader is the loader which loads classes which are
+ * exclusively used by the Ant core
+ */
+ private ClassLoader coreLoader;
+
+ /**
+ * The tools.jar URL is available for things which require the Sun tools
+ * jar
+ */
+ private URL toolsJarURL;
+
+ /**
+ * The URLs to the Ant XML parser. These are available to allow tasks
+ * which require XML support to use the standard parser rather than
+ * having to supply their own
+ */
+ private URL[] parserURLs;
+
+ /**
+ * The location of the Ant library directory from which tasks may be
+ * loaded
+ */
+ private URL libraryURL;
+
+ /** The location of the system configuration file */
+ private URL systemConfigArea;
+
+ /** The location of ANT_HOME */
+ private URL antHome;
+
+ /** The location of the user config file */
+ private URL userConfigArea;
+
+ /**
+ * Sets the location of the user configuration files
+ *
+ * @param userConfigArea the new user config area
+ */
+ public void setUserConfigArea(URL userConfigArea) {
+ this.userConfigArea = userConfigArea;
+ }
+
+ /**
+ * Set the location of ANT_HOME
+ *
+ * @param antHome the new value of ANT_HOME
+ */
+ public void setAntHome(URL antHome) {
+ this.antHome = antHome;
+ }
+
+ /**
+ * Sets the location of the system configuration files
+ *
+ * @param systemConfigArea the new system config area
+ */
+ public void setSystemConfigArea(URL systemConfigArea) {
+ this.systemConfigArea = systemConfigArea;
+ }
+
+ /**
+ * Sets the systemLoader of the InitConfig
+ *
+ * @param systemLoader the new systemLoader value
+ */
+ public void setSystemLoader(ClassLoader systemLoader) {
+ this.systemLoader = systemLoader;
+ }
+
+ /**
+ * Sets the commonLoader of the InitConfig
+ *
+ * @param commonLoader the new commonLoader value
+ */
+ public void setCommonLoader(ClassLoader commonLoader) {
+ this.commonLoader = commonLoader;
+ }
+
+ /**
+ * Sets the coreLoader of the InitConfig
+ *
+ * @param coreLoader the new coreLoader value
+ */
+ public void setCoreLoader(ClassLoader coreLoader) {
+ this.coreLoader = coreLoader;
+ }
+
+ /**
+ * Sets the toolsJarURL of the InitConfig
+ *
+ * @param toolsJarURL the new toolsJarURL value
+ */
+ public void setToolsJarURL(URL toolsJarURL) {
+ this.toolsJarURL = toolsJarURL;
+ }
+
+ /**
+ * Sets the parserURLs of the InitConfig
+ *
+ * @param parserURLs the new parserURLs value
+ */
+ public void setParserURLs(URL[] parserURLs) {
+ this.parserURLs = parserURLs;
+ }
+
+ /**
+ * Sets the libraryURL of the InitConfig
+ *
+ * @param libraryURL the new libraryURL value
+ */
+ public void setLibraryURL(URL libraryURL) {
+ this.libraryURL = libraryURL;
+ }
+
+ /**
+ * Get the location of the user's config files
+ *
+ * @return the location of the user's Ant config files
+ */
+ public URL getUserConfigArea() {
+ return userConfigArea;
+ }
+
+ /**
+ * Get the location of Ant's home area
+ *
+ * @return the location of ANT_HOME
+ */
+ public URL getAntHome() {
+ return antHome;
+ }
+
+ /**
+ * Get the location of the system config files
+ *
+ * @return the location of the system Ant config files
+ */
+ public URL getSystemConfigArea() {
+ return systemConfigArea;
+ }
+
+ /**
+ * Gets the systemLoader of the InitConfig
+ *
+ * @return the systemLoader value
+ */
+ public ClassLoader getSystemLoader() {
+ return systemLoader;
+ }
+
+ /**
+ * Gets the commonLoader of the InitConfig
+ *
+ * @return the commonLoader value
+ */
+ public ClassLoader getCommonLoader() {
+ return commonLoader;
+ }
+
+ /**
+ * Gets the coreLoader of the InitConfig
+ *
+ * @return the coreLoader value
+ */
+ public ClassLoader getCoreLoader() {
+ return coreLoader;
+ }
+
+ /**
+ * Gets the toolsJarURL of the InitConfig
+ *
+ * @return the toolsJarURL value
+ */
+ public URL getToolsJarURL() {
+ return toolsJarURL;
+ }
+
+ /**
+ * Gets the parserURLs of the InitConfig
+ *
+ * @return the parserURLs value
+ */
+ public URL[] getParserURLs() {
+ return parserURLs;
+ }
+
+ /**
+ * Gets the libraryURL of the InitConfig
+ *
+ * @return the libraryURL value
+ */
+ public URL getLibraryURL() {
+ return libraryURL;
+ }
+}
+
diff --git a/proposal/mutant/src/java/init/org/apache/ant/init/InitException.java b/proposal/mutant/src/java/init/org/apache/ant/init/InitException.java
new file mode 100755
index 000000000..d3edc6a0c
--- /dev/null
+++ b/proposal/mutant/src/java/init/org/apache/ant/init/InitException.java
@@ -0,0 +1,145 @@
+/*
+ * 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.init;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * An InitException is an exception which occurs during Ant initialization
+ * phase. Such exceptions are usually fatal because Ant cannot be
+ * sufficiently initialised to properly handle the exception.
+ *
+ * @author Conor MacNeill
+ * @created 11 January 2002
+ */
+public class InitException extends Exception {
+
+ /** Nested Exception if any. */
+ private Throwable cause = null;
+
+ /**
+ * Constructs an exception with the given descriptive message.
+ *
+ * @param msg Description of or information about the exception.
+ */
+ public InitException(String msg) {
+ super(msg);
+ }
+
+
+ /**
+ * Constructs an exception with the given message and exception as a
+ * root cause.
+ *
+ * @param msg Description of or information about the exception.
+ * @param cause Throwable that might have cause this one.
+ */
+ public InitException(String msg, Throwable cause) {
+ super(msg);
+ this.cause = cause;
+ }
+
+
+ /**
+ * Constructs an exception with the given exception as a root cause.
+ *
+ * @param cause Exception that might have caused this one.
+ */
+ public InitException(Throwable cause) {
+ super(cause.getMessage());
+ this.cause = cause;
+ }
+
+
+ /** Print the stack trace to System.err */
+ public void printStackTrace() {
+ printStackTrace(System.err);
+ }
+
+
+ /**
+ * Print the stack trace to the given PrintStream
+ *
+ * @param ps the PrintStream onto which the stack trace of this
+ * exception is to be printed
+ */
+ public void printStackTrace(PrintStream ps) {
+ synchronized (ps) {
+ ps.println(this);
+ if (cause != null) {
+ ps.println("--- Nested Exception ---");
+ cause.printStackTrace(ps);
+ }
+ }
+ }
+
+
+ /**
+ * Print the stack trace to the given PrintWriter
+ *
+ * @param pw the PrintWriter onto which the stack trace of this
+ * exception is to be printed
+ */
+ public void printStackTrace(PrintWriter pw) {
+ synchronized (pw) {
+ pw.println(this);
+ if (cause != null) {
+ pw.println("--- Nested Exception ---");
+ cause.printStackTrace(pw);
+ }
+ }
+ }
+}
+
diff --git a/proposal/mutant/src/java/init/org/apache/ant/init/InitUtils.java b/proposal/mutant/src/java/init/org/apache/ant/init/InitUtils.java
new file mode 100755
index 000000000..2013957e1
--- /dev/null
+++ b/proposal/mutant/src/java/init/org/apache/ant/init/InitUtils.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.init;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * A set of utility methods required during initialisation and beyond
+ *
+ * @author Conor MacNeill
+ * @created 20 January 2002
+ */
+public class InitUtils {
+ /**
+ * Get the URL for a file taking into account # characters
+ *
+ * @param file the file whose URL representation is required.
+ * @return The FileURL value
+ * @throws MalformedURLException if the URL representation cannot be
+ * formed.
+ */
+ public static URL getFileURL(File file) throws MalformedURLException {
+ String uri = "file:" + file.getAbsolutePath().replace('\\', '/');
+ for (int i = uri.indexOf('#'); i != -1; i = uri.indexOf('#')) {
+ uri = uri.substring(0, i) + "%23" + uri.substring(i + 1);
+ }
+ if (file.isDirectory()) {
+ uri += "/";
+ }
+ return new URL(uri);
+ }
+
+}
+
diff --git a/proposal/mutant/src/java/init/org/apache/ant/init/LoaderUtils.java b/proposal/mutant/src/java/init/org/apache/ant/init/LoaderUtils.java
new file mode 100755
index 000000000..db88b3ec8
--- /dev/null
+++ b/proposal/mutant/src/java/init/org/apache/ant/init/LoaderUtils.java
@@ -0,0 +1,220 @@
+/*
+ * 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.init;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * LoaderUtils is a utility class with methods for configuring a class
+ * loader from a URL.
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class LoaderUtils {
+
+ /**
+ * This is the file that is consulted on remote systems to specify
+ * available jars
+ */
+ public final static String LIST_FILE = "file.list";
+
+
+ /**
+ * Get the URLs to create class loader from the jars in a given location
+ *
+ * @param baseURL the baeURL is the location of the libs directory
+ * @param defaultFile default file if none can be found
+ * @return an array of URLs for the relevant jars
+ * @exception MalformedURLException the URLs cannot be created
+ */
+ public static URL[] getLoaderURLs(URL baseURL, String defaultFile)
+ throws MalformedURLException {
+ return getLoaderURLs(baseURL, defaultFile, new String[]{".jar"});
+ }
+
+ /**
+ * Get the URLs for a class loader
+ *
+ * @param baseURL the baeURL is the location of the libs directory
+ * @param extensions array of allowable file extensions
+ * @param defaultFile default file if none can be found
+ * @return an array of URLs for the relevant jars
+ * @exception MalformedURLException if the URL to the jars could not be
+ * formed
+ */
+ public static URL[] getLoaderURLs(URL baseURL, String defaultFile,
+ String[] extensions)
+ throws MalformedURLException {
+ URL[] urls = null;
+ if (baseURL.getProtocol().equals("file")) {
+ // URL is local filesystem.
+ urls = getDirectoryURLs(new File(baseURL.getFile()), extensions);
+ } else {
+ // URL is remote - try to read a file with the list of jars
+ URL jarListURL = new URL(baseURL, LIST_FILE);
+ BufferedReader reader = null;
+ List jarList = new ArrayList();
+ try {
+ InputStreamReader isr
+ = new InputStreamReader(jarListURL.openStream());
+ reader = new BufferedReader(isr);
+ String line = null;
+ while ((line = reader.readLine().trim()) != null) {
+ for (int i = 0; i < extensions.length; ++i) {
+ if (line.endsWith(extensions[i])) {
+ jarList.add(new URL(baseURL, line));
+ break;
+ }
+ }
+ }
+ urls = (URL[])jarList.toArray(new URL[0]);
+ } catch (IOException e) {
+ // use the default location
+ if (defaultFile != null) {
+ urls = new URL[]{new URL(baseURL, defaultFile)};
+ }
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ return urls;
+ }
+
+
+ /**
+ * Debug method to dump a class loader hierarchy to a PrintStream
+ * URLClassLoaders dump their URLs
+ *
+ * @param loader the class loaders whose configuration is dumped
+ * @param ps PrintStream to which info is sent
+ */
+ public static void dumpLoader(PrintStream ps, ClassLoader loader) {
+ if (loader instanceof URLClassLoader) {
+ URLClassLoader urlLoader = (URLClassLoader)loader;
+ URL[] urls = urlLoader.getURLs();
+ if (urls.length == 0) {
+ ps.println(" No URLs");
+ } else {
+ for (int i = 0; i < urls.length; ++i) {
+ ps.println(" URL: " + urls[i]);
+ }
+ }
+ } else {
+ ps.println("Class Loader: " + loader.getClass().getName());
+ }
+ ps.println();
+
+ ClassLoader parentLoader = loader.getParent();
+ if (parentLoader != null) {
+ ps.println("Parent Loader:");
+ dumpLoader(ps, parentLoader);
+ }
+ }
+
+
+ /**
+ * Get an array of URLs for each jar file in the directory
+ *
+ * @param directory the local directory
+ * @param extensions an array of file extensions to be considered in the
+ * search
+ * @return an array of URLs for the file found in the directory.
+ * @exception MalformedURLException if the URLs to the jars cannot be
+ * formed
+ */
+ private static URL[] getDirectoryURLs(File directory,
+ final String[] extensions)
+ throws MalformedURLException {
+ URL[] urls = new URL[0];
+
+ if (!directory.exists()) {
+ return urls;
+ }
+
+ File[] jars = directory.listFiles(
+ new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ for (int i = 0; i < extensions.length; ++i) {
+ if (name.endsWith(extensions[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+ });
+ urls = new URL[jars.length];
+ for (int i = 0; i < jars.length; ++i) {
+ urls[i] = InitUtils.getFileURL(jars[i]);
+ // ps.println("Adding URL " + urls[i]);
+ }
+ return urls;
+ }
+}
+
diff --git a/proposal/mutant/src/java/start/org/apache/ant/start/Main.java b/proposal/mutant/src/java/start/org/apache/ant/start/Main.java
new file mode 100755
index 000000000..bcb2ad352
--- /dev/null
+++ b/proposal/mutant/src/java/start/org/apache/ant/start/Main.java
@@ -0,0 +1,260 @@
+/*
+ * 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.start;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import org.apache.ant.init.ClassLocator;
+import org.apache.ant.init.InitUtils;
+import org.apache.ant.init.InitConfig;
+import org.apache.ant.init.InitException;
+import org.apache.ant.init.LoaderUtils;
+
+/**
+ * This is the main startup class for the command line interface of Ant. It
+ * establishes the classloaders used by the other components of Ant.
+ *
+ * @author Conor MacNeill
+ * @created 9 January 2002
+ */
+public class Main {
+ /** The actual class that implements the command line front end. */
+ public final static String COMMANDLINE_CLASS
+ = "org.apache.ant.cli.Commandline";
+
+
+ /**
+ * Get a URL to the Ant Library directory.
+ *
+ * @return the URL for the Ant library directory
+ * @throws InitException if there is a problem constructing the library
+ * URL
+ */
+ public static URL getLibraryURL()
+ throws InitException {
+ try {
+ URL cliURL = ClassLocator.getClassLocationURL(Main.class);
+
+ if (cliURL.getProtocol().equals("file")
+ && cliURL.getFile().endsWith("/")) {
+ // we are running from a set of classes. This should only
+ // happen in an Ant build situation. We use some embedded
+ // knowledge to locate the lib directory
+ File classesDirectory = new File(cliURL.getFile());
+ File libDirectory = new File(classesDirectory.getParent(),
+ "lib");
+ if (!libDirectory.exists()) {
+ throw new RuntimeException("Ant library directory "
+ + libDirectory + " does not exist");
+ }
+ return InitUtils.getFileURL(libDirectory);
+ } else {
+ String cliURLString = cliURL.toString();
+ int index = cliURLString.lastIndexOf("/");
+ if (index != -1) {
+ cliURLString = cliURLString.substring(0, index + 1);
+ }
+ return new URL(cliURLString);
+ }
+ } catch (MalformedURLException e) {
+ throw new InitException(e);
+ }
+ }
+
+
+ /**
+ * Entry point for starting command line Ant
+ *
+ * @param args commandline arguments
+ */
+ public static void main(String[] args) {
+ Main main = new Main();
+ main.start(args);
+ }
+
+
+ /**
+ * Get the URLs necessary to load the Sun compiler tools. In some JVMs
+ * this is available in the VM's system loader, in others we have to
+ * find it ourselves
+ *
+ * @return the URL to the tools jar if available, null otherwise
+ * @throws InitException if the URL to the tools jar cannot be formed.
+ */
+ private URL getToolsJarURL()
+ throws InitException {
+ try {
+ Class compilerClass = Class.forName("sun.tools.javac.Main");
+ // tools jar is on system classpath - no need for URL
+ return null;
+ } catch (ClassNotFoundException cnfe) {
+ try {
+ // couldn't find compiler - try to find tools.jar
+ // based on java.home setting
+ String javaHome = System.getProperty("java.home");
+ if (javaHome.endsWith("jre")) {
+ javaHome = javaHome.substring(0, javaHome.length() - 4);
+ }
+ File toolsjar = new File(javaHome + "/lib/tools.jar");
+ if (!toolsjar.exists()) {
+ System.out.println("Unable to locate tools.jar. "
+ + "Expected to find it in " + toolsjar.getPath());
+ return null;
+ }
+ URL toolsJarURL = InitUtils.getFileURL(toolsjar);
+ return toolsJarURL;
+ } catch (MalformedURLException e) {
+ throw new InitException(e);
+ }
+ }
+ }
+
+
+ /**
+ * Get the location of AntHome
+ *
+ * @return the URL containing AntHome.
+ * @throws InitException if Ant's home cannot be determined or properly
+ * contructed.
+ */
+ private URL getAntHome()
+ throws InitException {
+ try {
+ URL libraryURL = getLibraryURL();
+ if (libraryURL != null) {
+ return new URL(libraryURL, "..");
+ }
+ } catch (MalformedURLException e) {
+ throw new InitException(e);
+ }
+ throw new InitException("Unable to determine Ant Home");
+ }
+
+
+ /**
+ * Internal start method used to initialise front end
+ *
+ * @param args commandline arguments
+ */
+ private void start(String[] args) {
+ try {
+ InitConfig config = new InitConfig();
+
+ URL libraryURL = getLibraryURL();
+ config.setLibraryURL(libraryURL);
+
+ URL antHome = getAntHome();
+ config.setAntHome(antHome);
+ config.setSystemConfigArea(new URL(antHome, "conf/"));
+ File userConfigArea
+ = new File(System.getProperty("user.home"), ".ant/conf");
+ config.setUserConfigArea(InitUtils.getFileURL(userConfigArea));
+
+ // set up the class loaders that will be used when running Ant
+ ClassLoader systemLoader = getClass().getClassLoader();
+ config.setSystemLoader(systemLoader);
+ URL toolsJarURL = getToolsJarURL();
+ config.setToolsJarURL(toolsJarURL);
+
+ URL commonJarLib = new URL(libraryURL, "common");
+ ClassLoader commonLoader
+ = new URLClassLoader(LoaderUtils.getLoaderURLs(commonJarLib,
+ "common.jar"), systemLoader);
+ config.setCommonLoader(commonLoader);
+
+ // core needs XML parser for parsing various XML components.
+ URL[] parserURLs
+ = LoaderUtils.getLoaderURLs(new URL(libraryURL, "parser"),
+ "crimson.jar");
+ config.setParserURLs(parserURLs);
+
+ URL[] coreURLs
+ = LoaderUtils.getLoaderURLs(new URL(libraryURL, "antcore"),
+ "antcore.jar");
+ URL[] combinedURLs = new URL[parserURLs.length + coreURLs.length];
+ System.arraycopy(coreURLs, 0, combinedURLs, 0, coreURLs.length);
+ System.arraycopy(parserURLs, 0, combinedURLs, coreURLs.length,
+ parserURLs.length);
+ ClassLoader coreLoader = new URLClassLoader(combinedURLs,
+ commonLoader);
+ config.setCoreLoader(coreLoader);
+
+ URL cliJarLib = new URL(libraryURL, "cli");
+ ClassLoader frontEndLoader
+ = new URLClassLoader(LoaderUtils.getLoaderURLs(cliJarLib,
+ "cli.jar"), coreLoader);
+
+ // System.out.println("Front End Loader config");
+ // LoaderUtils.dumpLoader(System.out, frontEndLoader);
+
+ // Now start the front end by reflection.
+ Class commandLineClass = Class.forName(COMMANDLINE_CLASS, true,
+ frontEndLoader);
+
+ final Class[] param = {Class.forName("[Ljava.lang.String;"),
+ InitConfig.class};
+ final Method startMethod
+ = commandLineClass.getMethod("start", param);
+ final Object[] argument = {args, config};
+ startMethod.invoke(null, argument);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+