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(); + } + } +} +