From a88cd5374f3bc4b408456fbbeded1d06f050ba10 Mon Sep 17 00:00:00 2001 From: Conor MacNeill Date: Tue, 8 May 2001 16:04:13 +0000 Subject: [PATCH] My proposal for Ant2 - Mutant git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269017 13f79535-47bb-0310-9956-ffa450edef68 --- proposal/mutant/build.xml | 83 ++ .../apache/ant/bootstrap/BootstrapLoader.java | 298 ++++++ .../org/apache/ant/component/core/Echo.java | 162 ++++ .../core/EnumeratedAttributeConverter.java | 98 ++ .../ant/component/core/FileConverter.java | 89 ++ .../apache/ant/component/core/Property.java | 252 +++++ .../ant/component/core/URLConverter.java | 86 ++ .../org/apache/ant/component/core/antlib.xml | 8 + .../org/apache/ant/component/file/antlib.xml | 2 + .../ant/core/config/ComponentManager.java | 147 +++ .../ant/core/execution/AntConverter.java | 65 ++ .../apache/ant/core/execution/AntLibrary.java | 110 +++ .../apache/ant/core/execution/BuildEvent.java | 171 ++++ .../ant/core/execution/BuildEventSupport.java | 116 +++ .../ant/core/execution/BuildListener.java | 67 ++ .../ClassIntrospectionException.java | 144 +++ .../ant/core/execution/ClassIntrospector.java | 477 +++++++++ .../core/execution/ConversionException.java | 144 +++ .../apache/ant/core/execution/Converter.java | 67 ++ .../core/execution/ConverterDefinition.java | 144 +++ .../core/execution/ExecutionException.java | 125 +++ .../ant/core/execution/ExecutionFrame.java | 590 ++++++++++++ .../ant/core/execution/ExecutionManager.java | 317 ++++++ .../ant/core/execution/ExecutionTask.java | 150 +++ .../ant/core/execution/InputProvider.java | 77 ++ .../ant/core/execution/TaskContainer.java | 72 ++ .../ant/core/execution/TaskDefinition.java | 125 +++ .../apache/ant/core/model/BuildElement.java | 127 +++ .../org/apache/ant/core/model/Project.java | 267 ++++++ .../ant/core/model/ProjectModelException.java | 129 +++ .../org/apache/ant/core/model/Target.java | 136 +++ .../main/org/apache/ant/core/model/Task.java | 75 ++ .../apache/ant/core/model/TaskElement.java | 169 ++++ .../ant/core/support/AntClassLoader.java | 147 +++ .../apache/ant/core/support/AntException.java | 205 ++++ .../apache/ant/core/support/AntLocator.java | 331 +++++++ .../ant/core/support/ConfigException.java | 125 +++ .../apache/ant/core/support/Constants.java | 76 ++ .../org/apache/ant/core/support/Location.java | 166 ++++ .../ant/core/support/LocationException.java | 97 ++ .../ant/core/types/EnumeratedAttribute.java | 116 +++ .../org/apache/ant/core/xml/AntLibParser.java | 258 +++++ .../ant/core/xml/AttributeValidator.java | 112 +++ .../apache/ant/core/xml/ElementHandler.java | 109 +++ .../org/apache/ant/core/xml/RootHandler.java | 131 +++ .../apache/ant/core/xml/XMLProjectParser.java | 904 ++++++++++++++++++ .../org/apache/ant/frontend/BuildLogger.java | 94 ++ .../org/apache/ant/frontend/Commandline.java | 307 ++++++ .../apache/ant/frontend/DefaultLogger.java | 227 +++++ .../org/apache/ant/frontend/EmbedTest.java | 77 ++ .../org/apache/ant/frontend/Launcher.java | 89 ++ .../apache/ant/frontend/RemoteLauncher.java | 97 ++ .../org/apache/ant/frontend/eggmanifest.mf | 5 + .../main/org/apache/ant/frontend/manifest.mf | 5 + 54 files changed, 8767 insertions(+) create mode 100644 proposal/mutant/build.xml create mode 100644 proposal/mutant/src/bootstrap/org/apache/ant/bootstrap/BootstrapLoader.java create mode 100644 proposal/mutant/src/main/org/apache/ant/component/core/Echo.java create mode 100644 proposal/mutant/src/main/org/apache/ant/component/core/EnumeratedAttributeConverter.java create mode 100644 proposal/mutant/src/main/org/apache/ant/component/core/FileConverter.java create mode 100644 proposal/mutant/src/main/org/apache/ant/component/core/Property.java create mode 100644 proposal/mutant/src/main/org/apache/ant/component/core/URLConverter.java create mode 100644 proposal/mutant/src/main/org/apache/ant/component/core/antlib.xml create mode 100644 proposal/mutant/src/main/org/apache/ant/component/file/antlib.xml create mode 100644 proposal/mutant/src/main/org/apache/ant/core/config/ComponentManager.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/AntConverter.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/AntLibrary.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/BuildEvent.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/BuildEventSupport.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/BuildListener.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/ClassIntrospectionException.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/ClassIntrospector.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/ConversionException.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/Converter.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/ConverterDefinition.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionException.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionFrame.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionManager.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionTask.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/InputProvider.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/TaskContainer.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/TaskDefinition.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/model/BuildElement.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/model/Project.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/model/ProjectModelException.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/model/Target.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/model/Task.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/model/TaskElement.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/support/AntException.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/support/AntLocator.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/support/ConfigException.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/support/Constants.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/support/Location.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/support/LocationException.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/types/EnumeratedAttribute.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/xml/AntLibParser.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/xml/AttributeValidator.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/xml/ElementHandler.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/xml/RootHandler.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/xml/XMLProjectParser.java create mode 100644 proposal/mutant/src/main/org/apache/ant/frontend/BuildLogger.java create mode 100644 proposal/mutant/src/main/org/apache/ant/frontend/Commandline.java create mode 100644 proposal/mutant/src/main/org/apache/ant/frontend/DefaultLogger.java create mode 100644 proposal/mutant/src/main/org/apache/ant/frontend/EmbedTest.java create mode 100644 proposal/mutant/src/main/org/apache/ant/frontend/Launcher.java create mode 100644 proposal/mutant/src/main/org/apache/ant/frontend/RemoteLauncher.java create mode 100644 proposal/mutant/src/main/org/apache/ant/frontend/eggmanifest.mf create mode 100644 proposal/mutant/src/main/org/apache/ant/frontend/manifest.mf diff --git a/proposal/mutant/build.xml b/proposal/mutant/build.xml new file mode 100644 index 000000000..67a03633e --- /dev/null +++ b/proposal/mutant/build.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/proposal/mutant/src/bootstrap/org/apache/ant/bootstrap/BootstrapLoader.java b/proposal/mutant/src/bootstrap/org/apache/ant/bootstrap/BootstrapLoader.java new file mode 100644 index 000000000..d7432183c --- /dev/null +++ b/proposal/mutant/src/bootstrap/org/apache/ant/bootstrap/BootstrapLoader.java @@ -0,0 +1,298 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.bootstrap; + +import java.io.*; +import java.util.*; +import java.util.zip.*; +import java.lang.reflect.*; + +/** + * Bootstrap class to build the rest of ant with a minimum of user intervention + * + * The bootstrap class is able to act as a class loader to load new classes/jars + * into the VM in which it is running. + * + * @author Conor MacNeill + */ +public class BootstrapLoader extends ClassLoader { + static public final String RECURSION_GUARD = "ant.bootstrap.recursionGuard"; + static private final int BUFFER_SIZE = 1024; + + private String[] classpathElements; + + public BootstrapLoader(String classpath) { + StringTokenizer tokenizer = new StringTokenizer(classpath, File.pathSeparator); + classpathElements = new String[tokenizer.countTokens()]; + + for (int i = 0; tokenizer.hasMoreTokens(); ++i) { + classpathElements[i] = tokenizer.nextToken(); + } + } + + protected Class findClass(String name) + throws ClassNotFoundException { + String resourceName = name.replace('.', '/') + ".class"; + InputStream classStream = getResourceStream(resourceName); + + if (classStream == null) { + throw new ClassNotFoundException(); + } + + try { + return getClassFromStream(classStream, name); + } + catch (IOException ioe) { + ioe.printStackTrace(); + throw new ClassNotFoundException(); + } + } + + /** + * Get a stream to read the requested resource name. + * + * @param name the name of the resource for which a stream is required. + * + * @return a stream to the required resource or null if the resource cannot be + * found on the loader's classpath. + */ + private InputStream getResourceStream(String name) { + // we need to search the components of the path to see if we can find the + // class we want. + InputStream stream = null; + + for (int i = 0; i < classpathElements.length && stream == null; ++i) { + File pathComponent = new File(classpathElements[i]); + stream = getResourceStream(pathComponent, name); + } + + return stream; + } + + + + /** + * Get a stream to read the requested resource name. + * + * @param name the name of the resource for which a stream is required. + * + * @return a stream to the required resource or null if the resource cannot be + * found on the loader's classpath. + */ + public InputStream getResourceAsStream(String name) { + return getResourceStream(name); + } + + protected Class loadClass(String name, + boolean resolve) + throws ClassNotFoundException { + Class requestedClass = findLoadedClass(name); + try { + if (requestedClass == null) { + requestedClass = findClass(name); + if (resolve) { + resolveClass(requestedClass); + } + } + return requestedClass; + } + catch (ClassNotFoundException cnfe) { + return super.loadClass(name, resolve); + } + } + + /** + * Get an inputstream to a given resource in the given file which may + * either be a directory or a zip file. + * + * @param file the file (directory or jar) in which to search for the resource. + * @param resourceName the name of the resource for which a stream is required. + * + * @return a stream to the required resource or null if the resource cannot be + * found in the given file object + */ + private InputStream getResourceStream(File file, String resourceName) { + try { + if (!file.exists()) { + return null; + } + + if (file.isDirectory()) { + File resource = new File(file, resourceName); + + if (resource.exists()) { + return new FileInputStream(resource); + } + } + else { + ZipFile zipFile = null; + try { + zipFile = new ZipFile(file); + + ZipEntry entry = zipFile.getEntry(resourceName); + if (entry != null) { + // we need to read the entry out of the zip file into + // a baos and then + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[BUFFER_SIZE]; + int bytesRead; + InputStream stream = zipFile.getInputStream(entry); + while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) { + baos.write(buffer, 0, bytesRead); + } + return new ByteArrayInputStream(baos.toByteArray()); + } + } + finally { + if (zipFile != null) { + zipFile.close(); + } + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + /** + * Read a class definition from a stream. + * + * @param stream the stream from which the class is to be read. + * @param classname the class name of the class in the stream. + * + * @return the Class object read from the stream. + * + * @throws IOException if there is a problem reading the class from the + * stream. + */ + private Class getClassFromStream(InputStream stream, String classname) + throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int bytesRead = -1; + byte[] buffer = new byte[1024]; + + while ((bytesRead = stream.read(buffer, 0, 1024)) != -1) { + baos.write(buffer, 0, bytesRead); + } + + byte[] classData = baos.toByteArray(); + + return defineClass(classname, classData, 0, classData.length); + } + + + static private void buildAnt() { + System.out.println("Bootstrapping Ant ..."); + + } + + static private void runWithToolsJar(String[] args) { + try { + + 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 it to be in " + + toolsjar.getPath()); + return; + } + String newclasspath = toolsjar.getPath() + File.pathSeparator + + System.getProperty("java.class.path"); + + System.out.println("New Classpath is " + newclasspath); + + BootstrapLoader loader = new BootstrapLoader(newclasspath); + + Class newBootClass = loader.loadClass("org.apache.ant.bootstrap.BootstrapLoader", + true); + final Class[] param = { Class.forName("[Ljava.lang.String;") }; + final Method main = newBootClass.getMethod("main", param); + final Object[] argument = { args }; + main.invoke(null, argument); + } + catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Unable to run boot with tools.jar"); + } + } + + static public void main(String[] args) { + // check whether the tools.jar is already in the classpath. + try { + Class compilerClass = Class.forName("sun.tools.javac.Main"); + System.out.println("Compiler is available"); + } catch (ClassNotFoundException cnfe) { + if (System.getProperty(RECURSION_GUARD) != null) { + cnfe.printStackTrace(); + System.out.println("Unable to load compiler"); + return; + } + System.setProperty(RECURSION_GUARD, "yes"); + System.out.println("Compiler is not on classpath - locating ..."); + runWithToolsJar(args); + return; + } + + buildAnt(); + } +} + + diff --git a/proposal/mutant/src/main/org/apache/ant/component/core/Echo.java b/proposal/mutant/src/main/org/apache/ant/component/core/Echo.java new file mode 100644 index 000000000..03aa67d6e --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/component/core/Echo.java @@ -0,0 +1,162 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.component.core; + +import org.apache.ant.core.execution.*; +import org.apache.ant.core.types.*; +import java.io.*; + +/** + * Echo + * + * @author costin@dnt.ro + */ +public class Echo extends ExecutionTask { + protected String message = ""; // required + protected File file = null; + protected boolean append = false; + + // by default, messages are always displayed + protected int logLevel = BuildEvent.MSG_WARN; + + /** + * Does the work. + * + * @throws ExecutionException if someting goes wrong with the build + */ + public void execute() throws ExecutionException { + 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 ExecutionException(ioe); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException ioex) {} + } + } + } + } + + /** + * Sets the message variable. + * + * @param msg Sets the value for the message variable. + */ + public void setMessage(String msg) { + this.message = msg; + } + + /** + * Sets the file attribute. + */ + public void setFile(File file) { + this.file = file; + } + + /** + * Shall we append to an existing file? + */ + public void setAppend(boolean append) { + this.append = append; + } + + /** + * Set a multiline message. + */ + public void addText(String msg) { + message += msg; + } + + /** + * Set the logging level to one of + *
    + *
  • error
  • + *
  • warning
  • + *
  • info
  • + *
  • verbose
  • + *
  • debug
  • + *
      + *

      The default is "warning" to ensure that messages are + * displayed by default when using the -quiet command line option.

      + */ + public void setLevel(EchoLevel echoLevel) { + String option = echoLevel.getValue(); + if (option.equals("error")) { + logLevel = BuildEvent.MSG_ERR; + } else if (option.equals("warning")) { + logLevel = BuildEvent.MSG_WARN; + } else if (option.equals("info")) { + logLevel = BuildEvent.MSG_INFO; + } else if (option.equals("verbose")) { + logLevel = BuildEvent.MSG_VERBOSE; + } else { + // must be "debug" + logLevel = BuildEvent.MSG_DEBUG; + } + } + + public static class EchoLevel extends EnumeratedAttribute { + public String[] getValues() { + return new String[] {"error", "warning", "info", "verbose", "debug"}; + } + } +} diff --git a/proposal/mutant/src/main/org/apache/ant/component/core/EnumeratedAttributeConverter.java b/proposal/mutant/src/main/org/apache/ant/component/core/EnumeratedAttributeConverter.java new file mode 100644 index 000000000..3380906b4 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/component/core/EnumeratedAttributeConverter.java @@ -0,0 +1,98 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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.component.core; + +import org.apache.ant.core.execution.*; +import org.apache.ant.core.types.EnumeratedAttribute; + +/** + * Convert between a string and an enumeration + * + * @author Conor MacNeill + */ +public class EnumeratedAttributeConverter implements AntConverter { + private ExecutionFrame frame; + + public void init(ExecutionFrame frame) { + this.frame = frame; + } + + public Object convert(String value, Class type) throws ConversionException { + // The string represents a value + // get the frame's URL + try { + Object instance = type.newInstance(); + if (!(instance instanceof EnumeratedAttribute)) { + throw new ConversionException("The type " + type.getName() + + " is not a subclass of EnumeratedAttribute"); + } + EnumeratedAttribute enum = (EnumeratedAttribute)instance; + enum.setValue(value.trim()); + return enum; + } + catch (InstantiationException e) { + throw new ConversionException("Unable to instantiate the enumerated type " + + type.getName()); + } + catch (IllegalAccessException e) { + throw new ConversionException("Illegale access when instantiation enumerated type " + + type.getName()); + } + catch (ExecutionException e) { + throw new ConversionException("Unable to set the value of the enumerated type " + + type.getName() + ": " + e.getMessage()); + } + } +} diff --git a/proposal/mutant/src/main/org/apache/ant/component/core/FileConverter.java b/proposal/mutant/src/main/org/apache/ant/component/core/FileConverter.java new file mode 100644 index 000000000..c98c2e8a1 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/component/core/FileConverter.java @@ -0,0 +1,89 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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.component.core; + +import java.io.File; +import java.net.*; +import org.apache.ant.core.execution.*; + +/** + * Convert between a string and a data type + * + * @author Conor MacNeill + */ +public class FileConverter implements AntConverter { + private ExecutionFrame frame; + + public void init(ExecutionFrame frame) { + this.frame = frame; + } + + public Object convert(String value, Class type) throws ConversionException { + // The string represents a value + // get the frame's URL + try { + URL url = new URL(frame.getBaseURL(), value); + if (url.getProtocol().equals("file")) { + System.out.println("Converted URL to " + url); + return new File(url.getFile()); + } + return new File(value); + } + catch (MalformedURLException e) { + throw new ConversionException("Unable to convert " + value + + " into a File relative to the project's base"); + } + } +} diff --git a/proposal/mutant/src/main/org/apache/ant/component/core/Property.java b/proposal/mutant/src/main/org/apache/ant/component/core/Property.java new file mode 100644 index 000000000..7e1c72a98 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/component/core/Property.java @@ -0,0 +1,252 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.component.core; + +import java.util.*; +import java.io.*; +import org.apache.ant.core.execution.*; +import java.net.*; + +/** + * + */ +public class Property extends ExecutionTask { + private String name; + private String value; + private URL file; + private String resource; +// private Path classpath; + private String env; +// private Reference ref = null; + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setValue(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void setFile(URL file) { + this.file = file; + } + + public URL getFile() { + return file; + } + + public void setLocation(File location) { + setValue(location.getAbsolutePath()); + } + +// public void setRefid(Reference ref) { +// this.ref = ref; +// } +// +// public Reference getRefid() { +// return ref; +// } +// + public void setResource(String resource) { + this.resource = resource; + } + + public String getResource() { + return resource; + } + + public void setEnvironment(String env) { + this.env = env; + } + + public String getEnvironment() { + return env; + } + +// public void setClasspath(Path classpath) { +// if (this.classpath == null) { +// this.classpath = classpath; +// } else { +// this.classpath.append(classpath); +// } +// } +// +// public Path createClasspath() { +// if (this.classpath == null) { +// this.classpath = new Path(project); +// } +// return this.classpath.createPath(); +// } +// +// public void setClasspathRef(Reference r) { +// createClasspath().setRefid(r); +// } +// + + public void execute() throws ExecutionException { + ExecutionFrame frame = getExecutionFrame(); + if ((name != null) && (value != null)) { + frame.setDataValue(name, value); + } + + if (file != null) { + loadFile(file); + } + +// if (resource != null) loadResource(resource); +// +// if (env != null) loadEnvironment(env); +// +// if ((name != null) && (ref != null)) { +// Object obj = ref.getReferencedObject(getProject()); +// if (obj != null) { +// addProperty(name, obj.toString()); +// } +// } + } + + protected void loadFile (URL url) throws ExecutionException { + Properties props = new Properties(); + log("Loading " + url, BuildEvent.MSG_VERBOSE); + try { + InputStream stream = null; + if (url.getProtocol().equals("file")) { + File file = new File(url.getFile()); + + if (file.exists()) { + stream = new FileInputStream(file); + } + else { + throw new ExecutionException("Unable to find " + file.getAbsolutePath()); + } + } + else { + stream = url.openStream(); + } + + if (stream != null) { + try { + props.load(stream); + resolveAllProperties(props); + addProperties(props); + } finally { + stream.close(); + } + } + } catch (Exception ex) { + throw new ExecutionException("Unable to load property file: " + url, ex); + } + } + + protected void addProperties(Properties properties) throws ExecutionException { + ExecutionFrame frame = getExecutionFrame(); + for (Iterator i = properties.keySet().iterator(); i.hasNext();) { + String propertyName = (String)i.next(); + String propertyValue = properties.getProperty(propertyName); + frame.setDataValue(propertyName, frame.replacePropertyRefs(propertyValue)); + } + } + + private void resolveAllProperties(Properties props) throws ExecutionException { + for (Iterator propIterator = props.keySet().iterator(); propIterator.hasNext();) { + String name = (String)propIterator.next(); + String value = props.getProperty(name); + + boolean resolved = false; + while (!resolved) { + List fragments = new ArrayList(); + List propertyRefs = new ArrayList(); + ExecutionFrame.parsePropertyString(value, fragments, propertyRefs); + + resolved = true; + if (propertyRefs.size() != 0) { + 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 (propertyName.equals(name)) { + throw new ExecutionException("Property " + name + + " from " + file + + " was circularly defined."); + } + if (props.containsKey(propertyName)) { + fragment = props.getProperty(propertyName); + resolved = false; + } + else { + fragment = "${" + propertyName + "}"; + } + } + sb.append(fragment); + } + value = sb.toString(); + props.put(name, value); + } + } + } + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/component/core/URLConverter.java b/proposal/mutant/src/main/org/apache/ant/component/core/URLConverter.java new file mode 100644 index 000000000..896ea0809 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/component/core/URLConverter.java @@ -0,0 +1,86 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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.component.core; + +import org.apache.ant.core.execution.*; + +import java.net.*; +import java.io.File; + +/** + * Convert between a string and a URL, resolved to the ExecutionFrame's base + * + * @author Conor MacNeill + */ +public class URLConverter implements AntConverter { + private ExecutionFrame frame; + + public void init(ExecutionFrame frame) { + this.frame = frame; + } + + public Object convert(String value, Class type) throws ConversionException { + // The string represents a value + // get the frame's URL + try { + URL url = new URL(frame.getBaseURL(), value); + return url; + } + catch (MalformedURLException e) { + throw new ConversionException("Unable to convert " + value + + " into a URL relative to the project's base"); + } + } +} diff --git a/proposal/mutant/src/main/org/apache/ant/component/core/antlib.xml b/proposal/mutant/src/main/org/apache/ant/component/core/antlib.xml new file mode 100644 index 000000000..19d0b960a --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/component/core/antlib.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/proposal/mutant/src/main/org/apache/ant/component/file/antlib.xml b/proposal/mutant/src/main/org/apache/ant/component/file/antlib.xml new file mode 100644 index 000000000..df7f87c2e --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/component/file/antlib.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/proposal/mutant/src/main/org/apache/ant/core/config/ComponentManager.java b/proposal/mutant/src/main/org/apache/ant/core/config/ComponentManager.java new file mode 100644 index 000000000..e37358b12 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/config/ComponentManager.java @@ -0,0 +1,147 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.core.config; + +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.*; +import org.apache.ant.core.execution.*; +import org.apache.ant.core.support.*; +import org.apache.ant.core.xml.AntLibParser; +import org.xml.sax.SAXParseException; + +/** + * Manager for Ant components + * + * The component manager is responsible for locating and loading the + * components contained in Ant's lib/task directory. + * + * @author Conor MacNeill + */ +public class ComponentManager { + /** + * When Ant is run remotely, we need to look up the list of component + * libraries from the server. + */ + static public String COMPONENT_INDEX = "taskindex"; + + /** + * Create the component manager. When the component manager is created + * it will read the component definitions from the files in + * Ant's lib/task directory + */ + static public AntLibrary[] getComponents() throws LocationException, ConfigException { + try { + URL componentsLocation = new URL(AntLocator.getLibraryURL(), "task/"); + URL[] componentFiles = null; + if (componentsLocation.getProtocol().equals("file")) { + // component directory is local - we determine the + // component files by scanning the local directory + HashSet componentFilesTypes = new HashSet(); + componentFilesTypes.add(".tsk"); + componentFilesTypes.add(".jar"); + componentFilesTypes.add(".zip"); + File componentsDirectory = new File(componentsLocation.getFile()); + componentFiles = AntLocator.getDirectoryURLs(componentsDirectory, componentFilesTypes); + } + else { + // The component directory is remote - we determine the + // list of component files by reading a "known" list file. + URL componentListURL = new URL(componentsLocation, COMPONENT_INDEX); + BufferedReader reader = null; + List componentList = new ArrayList(); + try { + reader = new BufferedReader(new InputStreamReader(componentListURL.openStream())); + String line = null; + while ((line = reader.readLine()) != null) { + componentList.add(new URL(componentsLocation, line.trim())); + } + } + finally { + if (reader != null) { + reader.close(); + } + } + componentFiles = (URL[])componentList.toArray(new URL[0]); + } + + AntLibParser libdefParser = new AntLibParser(); + + List libraries = new ArrayList(); + + for (int i = 0; i < componentFiles.length; ++i) { + // We create a classloader for the component library + URL[] componentURLs = new URL[]{componentFiles[i]}; + AntClassLoader componentClassLoader + = new AntClassLoader(componentURLs, + ComponentManager.class.getClassLoader(), + componentFiles[i].toString()); + URL libDefinition = componentClassLoader.getResource("ANT-INF/antlib.xml"); + if (libDefinition != null) { + AntLibrary library + = libdefParser.parseAntLibrary(libDefinition, componentClassLoader); + libraries.add(library); + } + } + + return (AntLibrary[])libraries.toArray(new AntLibrary[0]); + } + catch (IOException e) { + throw new ConfigException(e); + } + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/AntConverter.java b/proposal/mutant/src/main/org/apache/ant/core/execution/AntConverter.java new file mode 100644 index 000000000..314e589a3 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/AntConverter.java @@ -0,0 +1,65 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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.core.execution; + +/** + * An AntConverter is a Converter which is initialised with the + * ExecutionFrame context in which it will perform its conversions + * + * @author Conor MacNeill + */ +public interface AntConverter extends Converter { + void init(ExecutionFrame frame); +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/AntLibrary.java b/proposal/mutant/src/main/org/apache/ant/core/execution/AntLibrary.java new file mode 100644 index 000000000..194b2403d --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/AntLibrary.java @@ -0,0 +1,110 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.execution; + +import java.util.*; +import java.net.URL; + +/** + * This object represents an Ant library definition. An Ant library + * is a set of plug-in for Ant consisting primarily of tasks but may include + * other ant components. + * + * @author Conor MacNeill + */ +public class AntLibrary { + /** + * The task definitions contained by this library + */ + private List taskDefinitions = new ArrayList(); + + /** + * The converter definitions contained by this library + */ + private List converterDefinitions = new ArrayList(); + + /** + * Add a task definition to this library + */ + public void addTaskDefinition(TaskDefinition taskDefinition) { + taskDefinitions.add(taskDefinition); + } + + /** + * Get the task definitions + * + * @return an iterator which returns TaskDefinition objects. + */ + public Iterator getTaskDefinitions() { + return taskDefinitions.iterator(); + } + + /** + * Add a converter definition to this library + */ + public void addConverterDefinition(ConverterDefinition converterDefinition) { + converterDefinitions.add(converterDefinition); + } + + /** + * Get the converter definitions + * + * @return an iterator which returns ConverterDefinition objects. + */ + public Iterator getConverterDefinitions() { + return converterDefinitions.iterator(); + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/BuildEvent.java b/proposal/mutant/src/main/org/apache/ant/core/execution/BuildEvent.java new file mode 100644 index 000000000..40cf6334c --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/BuildEvent.java @@ -0,0 +1,171 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999 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.core.execution; + +import java.util.EventObject; +import org.apache.ant.core.model.*; + +/* + * 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. + */ +public class BuildEvent extends EventObject { + public static final int MSG_ERR = 0; + public static final int MSG_WARN = 1; + public static final int MSG_INFO = 2; + public static final int MSG_VERBOSE = 3; + public static final int MSG_DEBUG = 4; + + public static final int BUILD_STARTED = 1; + public static final int BUILD_FINISHED = 2; + public static final int TARGET_STARTED = 3; + public static final int TARGET_FINISHED = 4; + public static final int TASK_STARTED = 5; + public static final int TASK_FINISHED = 6; + public static final int MESSAGE = 7; + + private int eventType; + private BuildElement buildElement = null; + private Throwable cause = null; + private String message = null; + private int messagePriority; + + /** + * Create a build event. + * + * @param soure the source of the build event. + * @param eventType the type of the buildEvent. + * @param buildElement the build element with which the event is associated. + */ + public BuildEvent(Object source, int eventType, BuildElement buildElement) { + super(source); + this.eventType = eventType; + this.buildElement = buildElement; + } + + /** + * Create a build event with an associated exception. + * + * @param soure the source of the build event. + * @param eventType the type of the buildEvent. + * @param buildElement the build element with which the event is associated. + */ + public BuildEvent(Object source, int eventType, BuildElement buildElement, + Throwable cause) { + this(source, eventType, buildElement); + this.cause = cause; + } + + /** + * Create a build event for a message + * + * @param soure the source of the build event. + * @param buildElement the build element with which the event is associated. + * @param message the message associated with this event + * @param priority the message priority + */ + public BuildEvent(Object source, BuildElement buildElement, String message, + int priority) { + this(source, MESSAGE, buildElement); + 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 BuildElement getBuildElement() { + return buildElement; + } + + /** + * Returns the logging message. This field will only be set + * for "messageLogged" events. + * + */ + public String getMessage() { + return message; + } + + /** + * Returns the priority of the logging message. This field will only + * be set for "messageLogged" events. + */ + 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. + */ + public Throwable getCause() { + return cause; + } +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/BuildEventSupport.java b/proposal/mutant/src/main/org/apache/ant/core/execution/BuildEventSupport.java new file mode 100644 index 000000000..c4fd5dbe5 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/BuildEventSupport.java @@ -0,0 +1,116 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999 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.core.execution; + +import java.util.*; +import org.apache.ant.core.model.*; + +/** + * BuildEventSupport is used by classes which which to send + * build events to the BuoldListeners + */ +public class BuildEventSupport { + private List listeners = new ArrayList(); + + public void addBuildListener(BuildListener listener) { + listeners.add(listener); + } + + public void removeBuildListener(BuildListener listener) { + listeners.remove(listener); + } + + public void forwardEvent(BuildEvent event) { + for (Iterator i = listeners.iterator(); i.hasNext();) { + BuildListener listener = (BuildListener)i.next(); + listener.processBuildEvent(event); + } + } + + public void fireBuildStarted(Object source, BuildElement element) { + BuildEvent event = new BuildEvent(source, BuildEvent.BUILD_STARTED, element); + forwardEvent(event); + } + + public void fireBuildFinished(Object source, BuildElement element, Throwable cause) { + BuildEvent event = new BuildEvent(source, BuildEvent.BUILD_FINISHED, element, cause); + forwardEvent(event); + } + + public void fireTargetStarted(Object source, BuildElement element) { + BuildEvent event = new BuildEvent(source, BuildEvent.TARGET_STARTED, element); + forwardEvent(event); + } + + public void fireTargetFinished(Object source, BuildElement element, Throwable cause) { + BuildEvent event = new BuildEvent(source, BuildEvent.TARGET_FINISHED, element, cause); + forwardEvent(event); + } + + public void fireTaskStarted(Object source, BuildElement element) { + BuildEvent event = new BuildEvent(source, BuildEvent.TASK_STARTED, element); + forwardEvent(event); + } + + public void fireTaskFinished(Object source, BuildElement element, Throwable cause) { + BuildEvent event = new BuildEvent(source, BuildEvent.TASK_FINISHED, element, cause); + forwardEvent(event); + } + + public void fireMessageLogged(Object source, BuildElement element, + String message, int priority) { + BuildEvent event = new BuildEvent(source, element, message, priority); + forwardEvent(event); + } +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/BuildListener.java b/proposal/mutant/src/main/org/apache/ant/core/execution/BuildListener.java new file mode 100644 index 000000000..a4071cd7e --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/BuildListener.java @@ -0,0 +1,67 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999 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.core.execution; + +import java.util.EventListener; + +/** + * Classes that implement this interface will be notified when + * things happend during a build. + * + * @see BuildEvent + */ +public interface BuildListener extends EventListener { + void processBuildEvent(BuildEvent event); +} \ No newline at end of file diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/ClassIntrospectionException.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ClassIntrospectionException.java new file mode 100644 index 000000000..3c1aaeaae --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/ClassIntrospectionException.java @@ -0,0 +1,144 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.core.execution; + + +import java.io.*; + +/** + * + * @author Conor MacNeill + */ +public class ClassIntrospectionException extends Exception { + /** + * Exception that might have caused this one. + */ + private Throwable cause = null; + + /** + * Constructs an exception with the given descriptive message. + * @param msg Description of or information about the exception. + */ + public ClassIntrospectionException(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 ClassIntrospectionException(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 ClassIntrospectionException(Throwable cause) { + super(cause.toString()); + this.cause = cause; + } + + /** + * Returns the nested exception. + * + * @return the underlying exception + */ + public Throwable getCause() { + return 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/main/org/apache/ant/core/execution/ClassIntrospector.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ClassIntrospector.java new file mode 100644 index 000000000..563523c20 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/ClassIntrospector.java @@ -0,0 +1,477 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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.core.execution; + +import java.lang.reflect.*; +import java.io.File; +import java.util.*; + +/** + * Introspects a class and builds a set of objects to assist in intospecting the + * class. + * + * @author Stefan Bodewig stefan.bodewig@megabit.net + * @author Conor MacNeill + */ +public class ClassIntrospector { + /** + * holds the types of the attributes that could be set. + */ + private Hashtable attributeTypes; + + /** + * holds the attribute setter methods. + */ + private Hashtable attributeSetters; + + /** + * Holds the types of nested elements that could be created. + */ + private Hashtable nestedTypes; + + /** + * Holds methods to create nested elements. + */ + private Hashtable nestedCreators; + + /** + * The method to add PCDATA stuff. + */ + private Method addText = null; + + /** + * The Class that's been introspected. + */ + private Class bean; + + /** + * returns the boolean equivalent of a string, which is considered true + * if either "on", "true", or "yes" is found, ignoring case. + */ + public static boolean toBoolean(String s) { + return (s.equalsIgnoreCase("on") || + s.equalsIgnoreCase("true") || + s.equalsIgnoreCase("yes")); + } + + public ClassIntrospector(final Class bean, Map converters) { + attributeTypes = new Hashtable(); + attributeSetters = new Hashtable(); + nestedTypes = new Hashtable(); + nestedCreators = new Hashtable(); + this.bean = bean; + + Method[] methods = bean.getMethods(); + for (int i=0; i. + */ +package org.apache.ant.core.execution; + + +import java.io.*; + +/** + * + * @author Conor MacNeill + */ +public class ConversionException extends Exception { + /** + * Exception that might have caused this one. + */ + private Throwable cause = null; + + /** + * 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 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); + this.cause = cause; + } + + /** + * 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.toString()); + this.cause = cause; + } + + /** + * Returns the nested exception. + * + * @return the underlying exception + */ + public Throwable getCause() { + return 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/main/org/apache/ant/core/execution/Converter.java b/proposal/mutant/src/main/org/apache/ant/core/execution/Converter.java new file mode 100644 index 000000000..11cc0d7c9 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/Converter.java @@ -0,0 +1,67 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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.core.execution; + +/** + * Convert between a string and a data type + * + * @author Conor MacNeill + */ +public interface Converter { + /** + * Convert a string from the value given to an instance of the given type. + */ + Object convert(String value, Class type) throws ConversionException; +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/ConverterDefinition.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ConverterDefinition.java new file mode 100644 index 000000000..99101bba7 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/ConverterDefinition.java @@ -0,0 +1,144 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.execution; + +import java.util.*; +import java.net.URL; + +/** + * A Converter definition defines a class which will convert + * a string into an instance of a particular type of class. Converters + * are typically only needed when some context information is + * required to perform the conversion. + * + * @author Conor MacNeill + */ +public class ConverterDefinition { + /** The URL of the library which defines this converter */ + private URL converterLibraryURL; + + /** The converter's class name */ + private String converterClassName; + + /** The converted class returned by this converter */ + private String targetClassName; + + /** The converter class loaded from the loader on demand. + */ + private Class converterClass = null; + + /** The class to which this converter converts. + */ + private Class targetClass = null; + + /** The converters's class loader. */ + private ClassLoader converterClassLoader; + + public ConverterDefinition(URL converterLibraryURL, String converterClassName, + String targetClassName, ClassLoader converterClassLoader) { + this.converterLibraryURL = converterLibraryURL; + this.converterClassName = converterClassName; + this.targetClassName = targetClassName; + this.converterClassLoader = converterClassLoader; + } + + /** + * Get the name of the class that this converter will return. + */ + public String getTargetClassName() { + return targetClassName; + } + + /** + * Get the classname of the converter that is being defined. + */ + public String getConverterClassName() { + return converterClassName; + } + + /** + * Get the URL where this converter was defined. + * + * @returns a URL of the lib defintion file + */ + public URL getLibraryURL() { + return converterLibraryURL; + } + + /** + * Get the converter class + * + * @return a class object for this converter + */ + public synchronized Class getConverterClass() throws ClassNotFoundException { + if (converterClass == null) { + converterClass = converterClassLoader.loadClass(converterClassName); + } + return converterClass; + } + + /** + * Get the converter class + * + * @return a class object for this converter + */ + public synchronized Class getTargetClass() throws ClassNotFoundException { + if (targetClass == null) { + targetClass = converterClassLoader.loadClass(targetClassName); + } + return targetClass; + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionException.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionException.java new file mode 100644 index 000000000..7b82e8c94 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionException.java @@ -0,0 +1,125 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.core.execution; + +import org.apache.ant.core.support.*; +import java.io.*; + +/** + * An ExecutiuonException indicates a problem during + * the execution of the build files tasks + * + * @author Conor MacNeill + */ +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/main/org/apache/ant/core/execution/ExecutionFrame.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionFrame.java new file mode 100644 index 000000000..59bb1d062 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionFrame.java @@ -0,0 +1,590 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.core.execution; + +import org.apache.ant.core.model.*; +import org.apache.ant.core.support.*; + +import java.util.*; +import java.net.*; + +/** + * An ExecutionFrame is 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 + */ +public class ExecutionFrame { + /** The Project that this execiton frame is processing */ + private Project project = null; + + /** The base URL for this frame. This is derived from the + Project's source URL and it's base attribute. */ + private URL baseURL = null; + + /** The task defs that this frame will use to process tasks */ + private Map taskDefs = new HashMap(); + + /** The imported frames of this frame. For each project imported by this frame's + project, a corresponding ExecutionFrame is created. */ + private Map importedFrames = new HashMap(); + + /** BuildEvent support used to fire events and manage listeners */ + private BuildEventSupport eventSupport = new BuildEventSupport(); + + /** The context of this execution. This contains all data object's + created by tasks that have been executed */ + private Map dataValues = new HashMap(); + + /** Introspector objects used to configure ExecutionTasks from the Task models.*/ + private Map introspectors = new HashMap(); + + /** Type converters for this executionFrame. Converters are used when configuring + Tasks to handle special type conversions. */ + private Map converters = new HashMap(); + + /** The namespace under which this execution frame lives in the hierarchical + project namespace - null for the root namespace */ + private String namespace; + + public ExecutionFrame(Project project, Map taskDefs, Map converterDefs, + String namespace) throws ConfigException { + this.project = project; + this.taskDefs = taskDefs; + this.namespace = namespace; + + try { + String base = project.getBase(); + if (base == null) { + baseURL = project.getSourceURL(); + } + else { + base = base.trim(); + if (!base.endsWith("/")) { + base += "/"; + } + baseURL = new URL(project.getSourceURL(), base); + } + } + catch (MalformedURLException e) { + throw new ConfigException("Project's base value \"" + project.getBase() + + "\" is not valid", e, project.getLocation()); + } + + // We create a set of converters from the converter definitions we + // have been given and initialise them. They should be AntConverters + setupConverters(converterDefs); + + for (Iterator i = project.getImportedProjectNames(); i.hasNext();) { + String importName = (String)i.next(); + Project importedProject = project.getImportedProject(importName); + String importNamespace + = namespace == null ? importName : namespace + ":" + importName; + ExecutionFrame importedFrame + = new ExecutionFrame(importedProject, taskDefs, converterDefs, importNamespace); + importedFrames.put(importName, importedFrame); + } + } + + public URL getBaseURL() { + return baseURL; + } + + private void setupConverters(Map converterDefs) throws ConfigException { + converters = new HashMap(); + for (Iterator i = converterDefs.values().iterator(); i.hasNext(); ) { + ConverterDefinition converterDef = (ConverterDefinition)i.next(); + boolean targetLoaded = false; + try { + Class targetClass = converterDef.getTargetClass(); + targetLoaded = false; + Class converterClass = converterDef.getConverterClass(); + Converter converter = (AntConverter)converterClass.newInstance(); + if (converter instanceof AntConverter) { + ((AntConverter)converter).init(this); + } + converters.put(targetClass, converter); + } + catch (ClassNotFoundException e) { + if (targetLoaded) { + throw new ConfigException("Unable to load converter class for " + + converterDef.getConverterClassName() + + " in converter from " + converterDef.getLibraryURL() + , e); + } + else { + throw new ConfigException("Unable to load target class " + + converterDef.getTargetClassName() + + " in converter from " + converterDef.getLibraryURL() + , e); + } + } + catch (InstantiationException e) { + throw new ConfigException("Unable to instantiate converter class " + + converterDef.getTargetClassName() + + " in converter from " + converterDef.getLibraryURL() + , e); + } + catch (IllegalAccessException e) { + throw new ConfigException("Unable to access converter class " + + converterDef.getTargetClassName() + + " in converter from " + converterDef.getLibraryURL() + , e); + } + } + } + + public void addBuildListener(BuildListener listener) { + eventSupport.addBuildListener(listener); + } + + public void removeBuildListener(BuildListener listener) { + eventSupport.removeBuildListener(listener); + } + + /** + * Get the project associated with this execution frame. + * + * @return the project associated iwth this execution frame. + */ + public Project getProject() { + return project; + } + + + /** + * Get the names of the frames representing imported projects. + * + * @return an iterator which returns the names of the imported frames. + */ + public Iterator getImportedFrameNames() { + return importedFrames.keySet().iterator(); + } + + + /** + * Get the frames representing imported projects. + * + * @return an iterator which returns the imported ExeuctionFrames.. + */ + public Iterator getImportedFrames() { + return importedFrames.values().iterator(); + } + + /** + * Get an imported frame by name + * + * @param importName the name under which the frame was imported. + * + * @return the ExecutionFrame asscociated with the given import name or null + * if there is no such project. + */ + public ExecutionFrame getImportedFrame(String importName) { + return (ExecutionFrame)importedFrames.get(importName); + } + + /** + * Get the location of this frame in the namespace hierarchy + * + * @return the location of this frame within the project import + * namespace hierarchy. + */ + public String getNamespace() { + return namespace; + } + + /** + * Get the fully qualified name of something with respect to this + * execution frame. + * + * @param name the unqualified name. + * + * @return the fully qualified version of the given name + */ + public String getQualifiedName(String name) { + return namespace == null ? name : namespace + ":" + name; + } + + /** + * Get the relative name of something with respect to this + * execution frame. + * + * @param fullname the fully qualified name. + * + * @return the relative version of the given name + */ + public String getRelativeName(String fullname) { + if (namespace == null) { + return fullname; + } + int index = fullname.indexOf(namespace); + if (index != 0) { + return fullname; + } + + return fullname.substring(namespace.length() + 1); + } + + /** + * Execute the given target's tasks + * + * @param the name of the target within this frame that is to be executed. + */ + public void executeTargetTasks(String targetName) throws ExecutionException, ConfigException { + Target target = project.getTarget(targetName); + try { + Iterator taskIterator = target.getTasks(); + eventSupport.fireTargetStarted(this, target); + executeTasks(taskIterator); + eventSupport.fireTargetFinished(this, target, null); + } + catch (RuntimeException e) { + eventSupport.fireTargetFinished(this, target, e); + throw e; + } + } + + /** + * Initialise the frame by executing the project level tasks if any + */ + public void initialise() throws ExecutionException, ConfigException { + Iterator taskIterator = project.getTasks(); + executeTasks(taskIterator); + } + + + private ExecutionTask getConfiguredExecutionTask(TaskElement model) + throws ConfigException, ExecutionException { + + String taskType = model.getType(); + TaskDefinition taskDefinition = (TaskDefinition)taskDefs.get(taskType); + if (taskDefinition == null) { + throw new ConfigException("There is no task defintion for tasks of type <" + + taskType + ">", model.getLocation()); + } + + try { + Class executionTaskClass = taskDefinition.getExecutionTaskClass(); + ExecutionTask executionTask = (ExecutionTask)executionTaskClass.newInstance(); + executionTask.setExecutionFrame(this); + executionTask.setBuildEventSupport(eventSupport); + executionTask.setBuildElement(model); + configureElement(executionTask, model); + return executionTask; + } + catch (ClassNotFoundException e) { + throw new ConfigException("Execution class " + taskDefinition.getTaskClassName() + + " was not found", e, model.getLocation()); + } + catch (InstantiationException e) { + throw new ConfigException("Unable to instantiate execution class " + + taskDefinition.getTaskClassName(), + e, model.getLocation()); + } + catch (IllegalAccessException e) { + throw new ConfigException("Unable to access execution class " + + taskDefinition.getTaskClassName(), + e, model.getLocation()); + } + } + + /** + * Run the tasks returned by the give iterator + * + * @param taskIterator the iterator giving the tasks to execute + */ + public void executeTasks(Iterator taskIterator) throws ExecutionException, ConfigException { + Task task = null; + try { + while (taskIterator.hasNext()) { + task = (Task)taskIterator.next(); + try { + ExecutionTask executionTask = getConfiguredExecutionTask(task); + eventSupport.fireTaskStarted(this, task); + executionTask.execute(); + } + catch (ExecutionException e) { + if (e.getLocation() == null || e.getLocation() == Location.UNKNOWN_LOCATION) { + e.setLocation(task.getLocation()); + } + throw e; + } + catch (ConfigException e) { + if (e.getLocation() == null || e.getLocation() == Location.UNKNOWN_LOCATION) { + e.setLocation(task.getLocation()); + } + throw e; + } + eventSupport.fireTaskFinished(this, task, null); + } + } + catch (RuntimeException e) { + eventSupport.fireTaskFinished(this, task, e); + throw e; + } + } + + private void configureElement(Object element, TaskElement model) + throws ExecutionException, ConfigException { + + try { + ClassIntrospector introspector = getIntrospector(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); + introspector.setAttribute(element, attributeName, + replacePropertyRefs(attributeValue)); + } + + String modelText = model.getText().trim(); + if (modelText.length() != 0) { + introspector.addText(element, replacePropertyRefs(modelText)); + } + + // now do the nested elements + for (Iterator i = model.getNestedElements(); i.hasNext();) { + TaskElement nestedElementModel = (TaskElement)i.next(); + if (element instanceof TaskContainer && + !introspector.supportsNestedElement(nestedElementModel.getType())) { + + ExecutionTask nestedExecutionTask + = getConfiguredExecutionTask(nestedElementModel); + + TaskContainer container = (TaskContainer)element; + container.addExecutionTask(nestedExecutionTask); + } + else { + Object nestedElement + = introspector.createElement(element, nestedElementModel.getType()); + configureElement(nestedElement, nestedElementModel); + } + } + } + catch (ClassIntrospectionException e) { + throw new ExecutionException(e, model.getLocation()); + } + catch (ConversionException e) { + throw new ExecutionException(e, model.getLocation()); + } + } + + private ClassIntrospector getIntrospector(Class c) { + if (introspectors.containsKey(c)) { + return (ClassIntrospector)introspectors.get(c); + } + ClassIntrospector introspector = new ClassIntrospector(c, converters); + introspectors.put(c, introspector); + return introspector; + } + + /** + * 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. + */ + 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(); + } + + + /** + * This method will parse a string containing ${value} style + * property values into two list. 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. + */ + static public 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)); + } + } + + /** + * Given a name of an object, get the frame relative from this frame that + * contains that object. + */ + private ExecutionFrame getRelativeFrame(String name) throws ExecutionException { + int index = name.lastIndexOf(":"); + if (index == -1) { + return this; + } + + ExecutionFrame currentFrame = this; + String relativeFrameName = name.substring(0, index); + StringTokenizer tokenizer = new StringTokenizer(relativeFrameName, ":"); + while (tokenizer.hasMoreTokens()) { + String frameName = tokenizer.nextToken(); + currentFrame = currentFrame.getImportedFrame(frameName); + if (currentFrame == null) { + throw new ExecutionException("The project " + frameName + " in " + + name + " was not found"); + } + } + + return currentFrame; + } + + /** + * Get the name of an object in its frame + */ + private String getNameInFrame(String name) { + int index = name.lastIndexOf(":"); + if (index == -1) { + return name; + } + return name.substring(index+1); + } + + /** + * Set a value in this frame or any of its imported frames + */ + public void setDataValue(String name, Object value) throws ExecutionException { + ExecutionFrame frame = getRelativeFrame(name); + frame.setDirectDataValue(getNameInFrame(name), value); + } + + /** + * Get a value from this frame or any imported frame + */ + private Object getDataValue(String name) throws ExecutionException { + ExecutionFrame frame = getRelativeFrame(name); + return frame.getDirectDataValue(getNameInFrame(name)); + } + + /** + * Set a value in this frame only + */ + private void setDirectDataValue(String name, Object value) { + dataValues.put(name, value); + } + + /** + * Get a value from this frame + */ + private Object getDirectDataValue(String name) { + return dataValues.get(name); + } + + /** + * Indicate if a data value has been set + */ + public boolean isDataValueSet(String name) throws ExecutionException { + ExecutionFrame frame = getRelativeFrame(name); + return frame.isDirectDataValueSet(getNameInFrame(name)); + } + + /** + * Indicate if a data value has been set in this frame + */ + private boolean isDirectDataValueSet(String name) { + return dataValues.containsKey(name); + } + +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionManager.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionManager.java new file mode 100644 index 000000000..dacca0edd --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionManager.java @@ -0,0 +1,317 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.core.execution; + + +import org.apache.ant.core.model.*; +import org.apache.ant.core.support.*; +import java.util.*; + +/** + * The ExecutionManager manages the execution of Ant. It will create + * ExecutionFrames to handle the various imported projects, the + * data values associated with those projects. Before the ExecutionManager + * can be used, it must be initialised with a set of Ant libraries. These + * will contain task definitions, aspect definitions, etc. + * + * @author Conor MacNeill + */ +public class ExecutionManager implements BuildListener { + private static final String VISITING = "VISITING"; + private static final String VISITED = "VISITED"; + + private HashMap taskDefs = new HashMap(); + private HashMap converterDefs = new HashMap(); + private Project project; + private ExecutionFrame mainFrame; + private Map namespaceMap = null; + private List frameInitOrder = null; + + private BuildEventSupport eventSupport = new BuildEventSupport(); + + public void addBuildListener(BuildListener listener) { + eventSupport.addBuildListener(listener); + } + + public void removeBuildListener(BuildListener listener) { + eventSupport.removeBuildListener(listener); + } + + /** + * Forward any events to our listeners. + */ + public void processBuildEvent(BuildEvent event) { + eventSupport.forwardEvent(event); + } + + public void addLibraries(AntLibrary[] libraries) throws ConfigException { + for (int i = 0; i < libraries.length; ++i) { + addLibrary(libraries[i]); + } + } + + public void addLibrary(AntLibrary library) throws ConfigException { + for (Iterator i = library.getTaskDefinitions(); i.hasNext(); ) { + TaskDefinition taskDefinition = (TaskDefinition)i.next(); + addTaskDefinition(taskDefinition); + } + for (Iterator i = library.getConverterDefinitions(); i.hasNext(); ) { + ConverterDefinition converterDef = (ConverterDefinition)i.next(); + addConverterDefinition(converterDef); + } + } + + public void addTaskDefinition(TaskDefinition taskDefinition) throws ConfigException { + String taskName = taskDefinition.getName(); + if (taskDefs.containsKey(taskName)) { + String message = "Task " + taskName + " is defined twice" + + ", in " + ((TaskDefinition)taskDefs.get(taskName)).getLibraryURL() + + " and " + taskDefinition.getLibraryURL(); + throw new ConfigException(message, new Location(taskDefinition.getLibraryURL().toString())); + } + taskDefs.put(taskName, taskDefinition); + } + + public void addConverterDefinition(ConverterDefinition converterDef) throws ConfigException { + String targetClassname = converterDef.getTargetClassName(); + if (converterDefs.containsKey(targetClassname)) { + String message = "Converter for " + targetClassname + " is defined twice" + + ", in " + ((ConverterDefinition)converterDefs.get(targetClassname)).getLibraryURL() + + " and " + converterDef.getLibraryURL(); + throw new ConfigException(message, new Location(converterDef.getLibraryURL().toString())); + } + converterDefs.put(targetClassname, converterDef); + } + + public void setProject(Project project) throws ConfigException { + this.project = project; + mainFrame = new ExecutionFrame(project, (Map)taskDefs.clone(), + (Map)converterDefs.clone(), null); + namespaceMap = new HashMap(); + frameInitOrder = new ArrayList(); + setupFrame(mainFrame); + + // We iterate through all nodes of all projects and make sure every node is OK + Map state = new HashMap(); + Stack visiting = new Stack(); + List dependencyOrder = new ArrayList(); + + checkFrameTargets(mainFrame, dependencyOrder, state, visiting); + } + + /** + * Check whether the targets in the given execution frame and its subframes are OK + */ + private void checkFrameTargets(ExecutionFrame frame, List dependencyOrder, + Map state, Stack visiting) + throws ConfigException { + // get the targets and just iterate through them. + for (Iterator i = frame.getProject().getTargets(); i.hasNext();) { + Target target = (Target)i.next(); + fillinDependencyOrder(frame, target.getName(), + dependencyOrder, state, visiting); + } + + // Now do the subframes. + for (Iterator i = frame.getImportedFrames(); i.hasNext();) { + ExecutionFrame importedFrame = (ExecutionFrame)i.next(); + checkFrameTargets(importedFrame, dependencyOrder, state, visiting); + } + } + + private void setupFrame(ExecutionFrame frame) { + frame.addBuildListener(this); + + String namespace = frame.getNamespace(); + if (namespace != null) { + namespaceMap.put(namespace, frame); + } + for (Iterator i = frame.getImportedFrameNames(); i.hasNext();) { + String importName = (String)i.next(); + setupFrame(frame.getImportedFrame(importName)); + } + frameInitOrder.add(frame); + } + + public void runBuild(List targetNames) throws AntException { + Throwable buildFailureCause = null; + try { + eventSupport.fireBuildStarted(this, project); + // we initialise each execution frame + for (Iterator i = frameInitOrder.iterator(); i.hasNext();) { + ExecutionFrame frame = (ExecutionFrame)i.next(); + frame.initialise(); + } + if (targetNames.isEmpty()) { + // we just execute the default target if any + String defaultTarget = project.getDefaultTarget(); + if (defaultTarget != null) { + executeTarget(defaultTarget); + } + } + else { + for (Iterator i = targetNames.iterator(); i.hasNext();) { + executeTarget((String)i.next()); + } + } + eventSupport.fireBuildFinished(this, project, null); + } + catch (RuntimeException e) { + buildFailureCause = e; + throw e; + } + catch (AntException e) { + buildFailureCause = e; + throw e; + } + finally { + eventSupport.fireBuildFinished(this, project, buildFailureCause); + } + } + + private ExecutionFrame getFrame(String name) { + int namespaceIndex = name.lastIndexOf(":"); + if (namespaceIndex == -1) { + return mainFrame; + } + return (ExecutionFrame)namespaceMap.get(name.substring(0, namespaceIndex)); + } + + public void executeTarget(String targetName) throws ExecutionException, ConfigException { + // to execute a target we must determine its dependencies and + // execute them in order. + Map state = new HashMap(); + Stack visiting = new Stack(); + List dependencyOrder = new ArrayList(); + ExecutionFrame startingFrame = getFrame(targetName); + fillinDependencyOrder(startingFrame, startingFrame.getRelativeName(targetName), + dependencyOrder, state, visiting); + + // Now tell each frame to execute the target + for (Iterator i = dependencyOrder.iterator(); i.hasNext();) { + String fullTargetName = (String)i.next(); + ExecutionFrame frame = getFrame(fullTargetName); + frame.executeTargetTasks(frame.getRelativeName(fullTargetName)); + } + } + + private void fillinDependencyOrder(ExecutionFrame frame, String targetName, + List dependencyOrder, Map state, + Stack visiting) throws ConfigException { + String fullTargetName = frame.getQualifiedName(targetName); + if (state.get(fullTargetName) == VISITED) { + return; + } + Target target = frame.getProject().getTarget(targetName); + if (target == null) { + StringBuffer sb = new StringBuffer("Target `"); + sb.append(targetName); + sb.append("' does not exist in this project. "); + if (!visiting.empty()) { + String parent = (String)visiting.peek(); + sb.append("It is used from target `"); + sb.append(parent); + sb.append("'."); + } + + throw new ConfigException(new String(sb), frame.getProject().getLocation()); + } + + state.put(fullTargetName, VISITING); + visiting.push(fullTargetName); + for (Iterator i = target.getDependencies(); i.hasNext(); ) { + String dependency = (String)i.next(); + String fullyQualifiedName = frame.getQualifiedName(dependency); + ExecutionFrame dependencyFrame = getFrame(fullyQualifiedName); + if (dependencyFrame == null) { + StringBuffer sb = new StringBuffer("Target `"); + sb.append(dependency); + sb.append("' does not exist in this project. "); + throw new ConfigException(new String(sb), target.getLocation()); + } + + String dependencyState = (String)state.get(fullyQualifiedName); + if (dependencyState == null) { + fillinDependencyOrder(dependencyFrame, dependencyFrame.getRelativeName(fullyQualifiedName), + dependencyOrder, state, visiting); + } + else if (dependencyState == VISITING) { + String circleDescription + = getCircularDesc(dependency, visiting); + throw new ConfigException(circleDescription, target.getLocation()); + } + } + + state.put(fullTargetName, VISITED); + String poppedNode = (String)visiting.pop(); + if (poppedNode != fullTargetName) { + throw new ConfigException("Problem determining dependencies " + + " - expecting '" + fullTargetName + + "' but got '" + poppedNode + "'"); + } + dependencyOrder.add(fullTargetName); + } + + private String getCircularDesc(String end, Stack visitingNodes) { + StringBuffer sb = new StringBuffer("Circular dependency: "); + sb.append(end); + String c; + do { + c = (String)visitingNodes.pop(); + sb.append(" <- "); + sb.append(c); + } while(!c.equals(end)); + return new String(sb); + } +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionTask.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionTask.java new file mode 100644 index 000000000..f3a190d2e --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionTask.java @@ -0,0 +1,150 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.execution; + +import org.apache.ant.core.model.*; +import org.apache.ant.core.support.*; +import java.util.*; +import java.net.URL; + +/** + * An ExecutionTask is the execution time equivalent of the Task + * object in the Ant project model. Subclasses of ExecutionTask are + * created by Task writers to implement particular, desired + * functionality + * + * An ExecutionTask subclass is created for a particular task type. + * The data from the task model is introspected into the ExecutionTask + * which is then executed. + * + * @author Conor MacNeill + */ +public abstract class ExecutionTask { + private ExecutionFrame frame = null; + private Location location = Location.UNKNOWN_LOCATION; + private BuildEventSupport eventSupport; + private BuildElement buildElement; + + void setExecutionFrame(ExecutionFrame frame) { + this.frame = frame; + } + + /** + * Get the ExecutionFrame in which this ExecutionTask is being executed. + * to which this task belongs + * + * @return the execution task's ExecutionFrame. + */ + public ExecutionFrame getExecutionFrame() { + return frame; + } + + /** + * Configure the event support to be used to fire events + */ + void setBuildEventSupport(BuildEventSupport eventSupport) { + this.eventSupport = eventSupport; + } + + /** + * Associate this ExecutionTask with a buildElement in the + * project model + */ + void setBuildElement(BuildElement buildElement) { + this.buildElement = buildElement; + } + + /** + * Log a message with the default (INFO) priority. + * + * @param msg the message to be logged. + */ + public void log(String msg) { + log(msg, BuildEvent.MSG_INFO); + } + + /** + * Log a mesage with the give priority. + * + * @param the message to be logged. + * @param msgLevel the message priority at which this message is to be logged. + */ + public void log(String msg, int msgLevel) { + eventSupport.fireMessageLogged(this, buildElement, msg, msgLevel); + } + + /** + * Called by the project to let the task initialize properly. + * + * @throws ExecutionException if someting goes wrong with the build + */ + public void init() throws ExecutionException {} + + /** + * Called by the frame to let the task do it's work. + * + * @throws ExecutionException if someting goes wrong with the build + */ + abstract public void execute() throws ExecutionException; + + /** + * Returns the file location where this task was defined. + */ + public Location getLocation() { + return buildElement.getLocation(); + } + +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/InputProvider.java b/proposal/mutant/src/main/org/apache/ant/core/execution/InputProvider.java new file mode 100644 index 000000000..21cb03613 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/InputProvider.java @@ -0,0 +1,77 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999 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.core.execution; + +/* + * An input provider is an object which is provided to Ant's core + * execution system to provide input from the user. Typically command + * line based clients will request input from the console whilst + * GUI clients may pop up an input dialog. Unattended operation may + * be able to source input from some form of script. + */ +public interface InputProvider { + /** + * Request input from the user + * + * @param prompt a string which is used to prompt the user for input. + * @param defaultInput the default value initially supplied to the user + * @param timeout a timeout in milliseconds which some clients may use + * to either accept the default or to fail. + * + * @return a string of the user's input if the user provided any. + * + * @throws ExecutionException if the no input could be obtained from the user + */ + String userInput(String prompt, String defaultInput) throws ExecutionException; +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/TaskContainer.java b/proposal/mutant/src/main/org/apache/ant/core/execution/TaskContainer.java new file mode 100644 index 000000000..947004ebf --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/TaskContainer.java @@ -0,0 +1,72 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.execution; + +import java.util.*; +import java.net.URL; + +/** + * A TaskContainer is an object which can contain and manage + * ExecutionTasks. + * + * @author Conor MacNeill + */ +public interface TaskContainer { + /** + * Add a task to the container. + */ + void addExecutionTask(ExecutionTask executionTask) throws ExecutionException; +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/TaskDefinition.java b/proposal/mutant/src/main/org/apache/ant/core/execution/TaskDefinition.java new file mode 100644 index 000000000..a7b349ec9 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/execution/TaskDefinition.java @@ -0,0 +1,125 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.execution; + +import java.util.*; +import java.net.URL; + +/** + * A Task definition provides the information necessary to execute + * a task implementation. + * + * @author Conor MacNeill + */ +public class TaskDefinition { + /** The URL of the library which defines this task */ + private URL taskLibraryURL; + + /** The task's name */ + private String taskName; + + /** The task's class */ + private String taskClassName; + + /** The task's class loaded from the loader on demand. */ + private Class taskClass = null; + + /** The task's class loader. */ + private ClassLoader taskClassLoader; + + public TaskDefinition(URL taskLibraryURL, String taskName, String taskClassName, + ClassLoader taskClassLoader) { + this.taskLibraryURL = taskLibraryURL; + this.taskName = taskName; + this.taskClassName = taskClassName; + this.taskClassLoader = taskClassLoader; + } + + /** + * Get the name of the task that is being defined. + */ + public String getName() { + return taskName; + } + + /** + * Get the classname of the task that is being defined. + */ + public String getTaskClassName() { + return taskClassName; + } + + /** + * Get the URL where this task was defined. + * + * @returns a URL of the lib defintion file + */ + public URL getLibraryURL() { + return taskLibraryURL; + } + + /** + * Get the task class for this task + * + * @return a class object for this task + */ + public synchronized Class getExecutionTaskClass() throws ClassNotFoundException { + if (taskClass == null) { + taskClass = taskClassLoader.loadClass(taskClassName); + } + return taskClass; + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/model/BuildElement.java b/proposal/mutant/src/main/org/apache/ant/core/model/BuildElement.java new file mode 100644 index 000000000..62f463e09 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/model/BuildElement.java @@ -0,0 +1,127 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.core.model; + +import java.util.*; +import org.apache.ant.core.support.*; + +/** + * A BuildElement is an element of a build file and has a location + * within that file. + * + * @author Conor MacNeill + */ +public class BuildElement { + /** + * The aspects defined for this element. + */ + private Map aspects; + + /** + * The location of this element + */ + private Location location; + + /** + * A comment associated with this element, if any + * + */ + private String comment; + + /** + * Create a build element giving its location. + * + * @param location identifies where this element is defined + */ + public BuildElement(Location location) { + this.location = location; + } + + /** + * Get the location of the source where this element is defined + * + * @return the element's location + */ + public Location getLocation() { + return 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; + } + + /** + * Get the comment associated with this element. + * + * @return the element's comment which may be null. + */ + public String getComment() { + return comment; + } + + /** + * Set the aspects of this element + * + * @param aspects a Map of apects that relate to this build element. + */ + public void setAspects(Map aspects) { + this.aspects = aspects; + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/model/Project.java b/proposal/mutant/src/main/org/apache/ant/core/model/Project.java new file mode 100644 index 000000000..d9b37f0ae --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/model/Project.java @@ -0,0 +1,267 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.model; + +import org.apache.ant.core.support.*; +import java.util.*; +import java.net.URL; + +/** + * A project is a collection of targets and global tasks. A project + * may reference objects in other projects using named references of + * the form project:object + * + * @author Conor MacNeill + */ +public class Project extends BuildElement { + /** 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 imported into this project. Each imported project is + * given a name which is used to identify access to that project's + * elements. + */ + private Map importedProjects = 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; + } + + /** + * Get the URL where this project is defined + * + * @return the project source URL + */ + public URL getSourceURL() { + return sourceURL; + } + + /** + * Add a target to the project. + * + * @param target the Target to be added + * + * @throws ProjectModelException if a target with the same name already exists. + */ + public void addTarget(Target target) throws ProjectModelException { + if (targets.containsKey(target.getName())) { + throw new ProjectModelException("A target with name '" + target.getName() + + "' has already been defined in this project", + target.getLocation()); + } + targets.put(target.getName(), target); + } + + /** + * 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; + } + + /** + * 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; + } + + /** + * Set the base URL for this project. + * + * @param base the baseURL for this project. + */ + public void setBase(String base) { + this.base = base; + } + + /** + * Get the base URL for this project. + * + * @return the baseURL for this project as a string. + */ + public String getBase() { + return base; + } + + /** + * Set the name of this project. + * + * @param name the name for this project. + */ + public void setName(String name) { + this.name = name; + } + + + /** + * 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(Task task) { + tasks.add(task); + } + + /** + * Import a project to be referenced using the given name. + * + * @param importName the name under which the project will be referenced. + * @param project the imported project. + * + * @throws ProjectModelException if an existing project has already + * been imported with that name. + */ + public void importProject(String importName, Project project) + throws ProjectModelException { + if (importedProjects.containsKey(importName)) { + throw new ProjectModelException("A project has already been imported with name '" + + importName + "'"); + } + importedProjects.put(importName, project); + } + + /** + * 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 name sof the imported projects. + * + * @return an iterator which returns the name sof the imported projects. + */ + public Iterator getImportedProjectNames() { + return importedProjects.keySet().iterator(); + } + + /** + * Get an imported project by name + * + * @param importName the name under which the project was imported. + * + * @return the project asscociated with the given import name or null + * if there is no such project. + */ + public Project getImportedProject(String importName) { + return (Project)importedProjects.get(importName); + } + + /** + * Get the initialisation tasks for this project + * + * @return an iterator over the set of tasks for this project. + */ + public Iterator getTasks() { + return tasks.iterator(); + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/model/ProjectModelException.java b/proposal/mutant/src/main/org/apache/ant/core/model/ProjectModelException.java new file mode 100644 index 000000000..68cc9a8a4 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/model/ProjectModelException.java @@ -0,0 +1,129 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.model; + +import org.apache.ant.core.support.*; +import java.util.*; +import java.net.URL; + +/** + * A project model exception is thrown when an operation is attempted + * which would violate the integrity of the Project/Target/Task object + * model + * + * @author Conor MacNeill + */ +public class ProjectModelException extends AntException { + /** + * Constructs an exception with the given descriptive message. + * + * @param msg Description of or information about the exception. + */ + public ProjectModelException(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 ProjectModelException(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 ProjectModelException(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 ProjectModelException(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 ProjectModelException(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 ProjectModelException(Throwable cause, Location location) { + super(cause, location); + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/model/Target.java b/proposal/mutant/src/main/org/apache/ant/core/model/Target.java new file mode 100644 index 000000000..7590ff7cc --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/model/Target.java @@ -0,0 +1,136 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.model; + +import java.util.*; +import org.apache.ant.core.support.*; + +/** + * A Target is a collection of tasks. It may have + * dependencies on other targets + * @author Conor MacNeill + */ +public class Target extends BuildElement { + private List dependencies = new ArrayList(); + + /** + * This target's list of tasks + */ + private List tasks = new ArrayList(); + + /** + * The target's name. + */ + private String name; + + /** + * 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; + } + + /** + * Get this target's name. + * + * @return the target's name. + */ + public String getName() { + return name; + } + + /** + * Add a task to this target + * + * @param task the task to be added to the target. + */ + public void addTask(Task 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); + } + + /** + * 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(); + } + +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/model/Task.java b/proposal/mutant/src/main/org/apache/ant/core/model/Task.java new file mode 100644 index 000000000..d9148a11b --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/model/Task.java @@ -0,0 +1,75 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.core.model; + +import org.apache.ant.core.support.*; +import java.util.*; + +/** + * A Task is a holder for Task information (attributes and elements) + * + * @author Conor MacNeill + */ +public class Task extends TaskElement { + /** + * Create a Task of the given type + * + * @param location the location of the element + * @param type the task's type + */ + public Task(Location location, String type) { + super(location, type); + } + +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/model/TaskElement.java b/proposal/mutant/src/main/org/apache/ant/core/model/TaskElement.java new file mode 100644 index 000000000..7c0b73851 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/model/TaskElement.java @@ -0,0 +1,169 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.core.model; + +import java.util.*; +import org.apache.ant.core.support.*; + +/** + * A TaskElement is a holder for Task configuration information. + * TaskElements may be grouped into a hierarchy to capture + * any level of Task element nesting. + * + * @author Conor MacNeill + */ +public class TaskElement extends BuildElement { + /** The attributes of this task element */ + private Map attributes = new HashMap(); + + /** + * The task's name or type + */ + private String type; + + /** + * The task elements that make up this task. + */ + private List taskElements = new ArrayList(); + + /** The content (text) of this task */ + private String text = ""; + + /** + * Create a Task of the given type + * + * @param location the location of the element + * @param type the task element's type + */ + public TaskElement(Location location, String type) { + super(location); + this.type = type; + } + + /** + * Add text to this task. + * + * @param text the element text to add. + */ + public void addText(String text) { + this.text += text; + } + + /** + * Get the text of this task + * + * @return the task's text. + */ + public String getText() { + return text; + } + + /** + * Add a task element to this task + * + * @param taskElement the task element to be added. + */ + public void addTaskElement(TaskElement taskElement) { + taskElements.add(taskElement); + } + + /** + * Get an iterator over this element's nexted elements + * + * @return an iterator which provides TaskElement instances + */ + public Iterator getNestedElements() { + return taskElements.iterator(); + } + + /** + * Get the type of this task element + * + * @return the element's type + */ + public String getType() { + return type; + } + + /** + * Add an attribute to this task 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); + } + + /** + * Get an iterator over the task'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); + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java b/proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java new file mode 100644 index 000000000..b8bf13acb --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java @@ -0,0 +1,147 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.support; + +import java.util.*; +import java.net.*; +import java.io.*; + +/** + * A ReverseURLclassLoader is a type of URL classloader which reverse the standard + * lookup order to load things from the URLs first and then to use the parent class + * loader only if the class does not exist in the URLs. + * + * @author Conor MacNeill + */ +public class AntClassLoader extends URLClassLoader { + private String debugLabel = null; + private boolean debug = false; + + private void dumpURLs() { + if (debug && debugLabel != null) { + System.out.println(debugLabel + ": loader URLs"); + URL[] urls = getURLs(); + for (int i = 0; i < urls.length; ++i) { + System.out.println(debugLabel + ": URL: " + urls[i]); + } + } + } + + public AntClassLoader(URL[] urls) { + super(urls); + } + + public AntClassLoader(URL[] urls, String debugLabel) { + super(urls); + this.debugLabel = debugLabel; + } + + public AntClassLoader(URL[] urls, + ClassLoader parent) { + super(urls, parent); + } + + public AntClassLoader(URL[] urls, + ClassLoader parent, String debugLabel) { + super(urls, parent); + this.debugLabel = debugLabel; + } + + public void setDebug(boolean debug) { + this.debug = debug; + dumpURLs(); + } + + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + if (debug && debugLabel != null) { + System.out.println(debugLabel + ": Trying to load class " + name); + } + + Class c = findLoadedClass(name); + if (c == null) { + try { + c = findClass(name); + if (debug && debugLabel != null) { + System.out.println(debugLabel + ": Found class " + name + " in this loader"); + } + } catch (ClassNotFoundException e) { + c = super.loadClass(name, resolve); + if (debug && debugLabel != null) { + System.out.println(debugLabel + ": Found class " + name + " in parent loader"); + } + return c; + } + } + if (resolve) { + resolveClass(c); + } + return c; + } + + public void addURL(URL url) { + super.addURL(url); + } + + public URL getResource(String name) { + URL url = findResource(name); + if (url == null) { + url = super.getResource(name); + } + + return url; + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/support/AntException.java b/proposal/mutant/src/main/org/apache/ant/core/support/AntException.java new file mode 100644 index 000000000..89ba0a900 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/support/AntException.java @@ -0,0 +1,205 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.core.support; + + +import java.io.*; + +/** + * 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 + */ +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.toString()); + 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); + } + + /** + * Returns the nested exception. + * + * @return the underlying exception + */ + public Throwable getCause() { + return cause; + } + + /** + * Sets the file location where the error occured. + */ + public void setLocation(Location location) { + if (location == null) { + this.location = Location.UNKNOWN_LOCATION; + } + else { + this.location = location; + } + } + + /** + * Returns the file location where the error occured. + */ + 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) { + 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/main/org/apache/ant/core/support/AntLocator.java b/proposal/mutant/src/main/org/apache/ant/core/support/AntLocator.java new file mode 100644 index 000000000..859a6354e --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/support/AntLocator.java @@ -0,0 +1,331 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.support; + +import java.util.*; +import java.net.*; +import java.io.*; + +/** + * The Ant Locator is used to find various Ant components without + * requiring the user to maintain environment properties. + * + * @author Conor MacNeill + */ +public class AntLocator { + private AntLocator() {} + + /** + * 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 LocationException if the class' URL cannot be constructed. + */ + static public URL getClassLocationURL(Class theClass) + throws LocationException { + String className = theClass.getName().replace('.', '/') + ".class"; + URL classRawURL = theClass.getClassLoader().getResource(className); + + try { + 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; + } + } + catch (MalformedURLException e) { + throw new LocationException(e); + } + } + + + /** + * Get the location of AntHome + * + * @return the URL containing AntHome. + * + * @throws LocationException if Ant's home cannot be determined. + */ + static public URL getAntHome() throws LocationException { + try { + URL libraryURL = getLibraryURL(); + if (libraryURL != null) { + return new URL(libraryURL, ".."); + } + else { + return null; + } + } + catch (MalformedURLException e) { + e.printStackTrace(); + return null; + } + } + + /** + * Get a URL to the Ant core jar. Other jars can be located + * from this as relative URLs + * + * @return a URL containing the Ant core or null if the core cannot be determined. + * + * @throws LocationException if the URL of the core.jar cannot be determined. + */ + static public URL getCoreURL() throws LocationException { + return getClassLocationURL(AntLocator.class); + } + + /** + * Get a URL to the Ant Library directory. + * + * @throws LocationException if the location of the Ant library directory cannot + * be determined + */ + static public URL getLibraryURL() throws LocationException { + URL coreURL = getCoreURL(); + + try { + if (coreURL.getProtocol().equals("file") && + coreURL.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 coreClassDirectory = new File(coreURL.getFile()); + File libDirectory = coreClassDirectory.getParentFile().getParentFile(); + if (!libDirectory.exists()) { + throw new LocationException("Ant library directory " + libDirectory + + " does not exist"); + } + return (new File(libDirectory, "lib")).toURL(); + } + else { + String coreURLString = coreURL.toString(); + int index = coreURLString.lastIndexOf("/"); + if (index != -1) { + coreURLString = coreURLString.substring(0, index+1); + } + return new URL(coreURLString); + } + } + catch (MalformedURLException e) { + throw new LocationException(e); + } + } + + /** + * Get a classloader with which to load the SAX parser + * + * @return the classloader to use to load Ant's XML parser + * + * @throws LocationException if the location of the parser jars + * could not be determined. + */ + static public ClassLoader getParserClassLoader(Properties properties) + throws LocationException { + // we look for the parser directory based on a system property first + String parserURLString = properties.getProperty(Constants.PropertyNames.PARSER_URL); + URL parserURL = null; + if (parserURLString != null) { + try { + parserURL = new URL(parserURLString); + } + catch (MalformedURLException e) { + throw new LocationException("XML Parser URL " + parserURLString + + " is malformed.", e); + } + } + else { + try { + parserURL = new URL(getLibraryURL(), "parser/"); + } + catch (Exception e) { + // ignore - we will just use the default class loader. + } + } + + if (parserURL != null) { + try { + URL[] parserURLs = null; + if (parserURL.getProtocol().equals("file")) { + // build up the URLs for each jar file in the + // parser directory + parserURLs = getDirectoryJarURLs(new File(parserURL.getFile())); + } + else { + // we can't search the URL so we look for a known parser relative to + // that URL + String defaultParser = properties.getProperty(Constants.PropertyNames.DEFAULT_PARSER); + if (defaultParser == null) { + defaultParser = Constants.Defaults.DEFAULT_PARSER; + } + + parserURLs = new URL[1]; + parserURLs[0] = new URL(parserURL, defaultParser); + + } + + return new AntClassLoader(parserURLs, "parser"); + } + catch (MalformedURLException e) { + throw new LocationException(e); + } + } + + return AntLocator.class.getClassLoader(); + } + + /** + * Get an array of URLs for each file matching the given set of extensions + * + * @param directory the local directory + * @param extensions the set of extensions to be returned + * + * @return an array of URLs for the file found in the directory. + */ + static public URL[] getDirectoryURLs(File directory, final Set extensions) { + URL[] urls = new URL[0]; + + if (!directory.exists()) { + return urls; + } + + File[] jars = directory.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + int extensionIndex = name.lastIndexOf("."); + if (extensionIndex == -1) { + return false; + } + String extension = name.substring(extensionIndex); + return extensions.contains(extension); + } + }); + urls = new URL[jars.length]; + for (int i = 0; i < jars.length; ++i) { + try { + urls[i] = jars[i].toURL(); + } + catch (MalformedURLException e) { + // just ignore + } + } + return urls; + } + + + + + /** + * Get an array of URLs for each jar file in a local directory. + * + * @param directory the local directory + * + * @return an array of URLs for the jars found in the directory. + */ + static private URL[] getDirectoryJarURLs(File directory) { + HashSet extensions = new HashSet(); + extensions.add(".jar"); + return getDirectoryURLs(directory, extensions); + } + + /** + * Get the Core Class Loader. The core requires a SAX parser which must come from the + * given classloader + * + * @throws LocationException if the location of the core ant classes could + * not be determined + */ + static public AntClassLoader getCoreClassLoader(Properties properties) + throws LocationException { + URL[] coreURL = new URL[1]; + coreURL[0] = getCoreURL(); + AntClassLoader coreLoader + = new AntClassLoader(coreURL, getParserClassLoader(properties), "core"); + URL libraryURL = getLibraryURL(); + if (libraryURL != null && libraryURL.getProtocol().equals("file")) { + // we can search this + + URL[] optionalURLs = getDirectoryJarURLs(new File(libraryURL.getFile(), "optional")); + for (int i = 0; i < optionalURLs.length; ++i) { + coreLoader.addURL(optionalURLs[i]); + } + + } + + return coreLoader; + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/support/ConfigException.java b/proposal/mutant/src/main/org/apache/ant/core/support/ConfigException.java new file mode 100644 index 000000000..c4863de74 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/support/ConfigException.java @@ -0,0 +1,125 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.core.support; + +import java.io.*; + +/** + * A ConfigException indicates a problem with + * Ant's configuration. + * + * @author Conor MacNeill + */ +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/main/org/apache/ant/core/support/Constants.java b/proposal/mutant/src/main/org/apache/ant/core/support/Constants.java new file mode 100644 index 000000000..1be623dca --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/support/Constants.java @@ -0,0 +1,76 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.support; + +import java.util.*; +import java.net.*; +import java.io.*; + +/** + * Constants used by the Ant core + * + * @author Conor MacNeill + */ +public class Constants { + static public class PropertyNames { + static public final String PARSER_URL = "ant.parser.url"; + static public final String DEFAULT_PARSER = "ant.parser.default"; + } + + static public class Defaults { + static public final String DEFAULT_PARSER = "crimson.jar"; + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/support/Location.java b/proposal/mutant/src/main/org/apache/ant/core/support/Location.java new file mode 100644 index 000000000..9e55bdd53 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/support/Location.java @@ -0,0 +1,166 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.support; + +/** + * Stores the file name and line number in a file. + */ +public class 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 locatin within the source + */ + private int columnNumber; + + /** + * Standard unknown location constant; + */ + public static final Location UNKNOWN_LOCATION = new Location(); + + /** + * Creates an "unknown" location. + */ + private Location() { + this(null, 0, 0); + } + + /** + * 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; + } + + /** + * 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(); + } + + /** + * 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; + } +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/support/LocationException.java b/proposal/mutant/src/main/org/apache/ant/core/support/LocationException.java new file mode 100644 index 000000000..c3a32aa22 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/support/LocationException.java @@ -0,0 +1,97 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.support; + +import java.util.*; +import java.net.URL; + +/** + * A LocationException is thrown when there is a problem determining + * the location of an Ant component. + * + * @author Conor MacNeill + */ +public class LocationException extends AntException { + /** + * Constructs an exception with the given descriptive message. + * + * @param msg Description of or information about the exception. + */ + public LocationException(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 LocationException(String msg, Throwable cause) { + super(msg, cause); + } + + /** + * Constructs an exception with the given exception as a root cause. + * + * @param cause Exception that might have caused this one. + */ + public LocationException(Throwable cause) { + super(cause); + } + +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/types/EnumeratedAttribute.java b/proposal/mutant/src/main/org/apache/ant/core/types/EnumeratedAttribute.java new file mode 100644 index 000000000..ffe03baba --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/types/EnumeratedAttribute.java @@ -0,0 +1,116 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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.core.types; + +import org.apache.ant.core.execution.*; + +/** + * Helper class for attributes that can only take one of a fixed list + * of values. + * + * @author Stefan Bodewig + */ +public abstract class EnumeratedAttribute { + + /** The value of this attribute. */ + private String value; + + /** + * This is the only method a subclass needs to implement. + * + * @return an array holding all possible values of the enumeration. + */ + public abstract String[] getValues(); + + /** + * Set the value of the enumeration. + * + * Invoked by {@link org.apache.ant.core.execution.IntrospectionHelper IntrospectionHelper}. + * + * @param value the value of the enumeration + * + * @throws ExecutionException if the value is not value + */ + public final void setValue(String value) throws ExecutionException { + if (!containsValue(value)) { + throw new ExecutionException(value + " is not a legal value for this attribute"); + } + this.value = value; + } + + /** + * Is this value included in the enumeration? + */ + public final boolean containsValue(String value) { + String[] values = getValues(); + if (values == null || value == null) { + return false; + } + + for (int i = 0; i < values.length; i++) { + if (value.equals(values[i])) { + return true; + } + } + return false; + } + + /** + * Retrieves the value. + */ + public final String getValue() { + return value; + } +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/xml/AntLibParser.java b/proposal/mutant/src/main/org/apache/ant/core/xml/AntLibParser.java new file mode 100644 index 000000000..43c2f9bb3 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/xml/AntLibParser.java @@ -0,0 +1,258 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.xml; + +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; +import javax.xml.parsers.*; +import org.apache.ant.core.support.*; +import org.apache.ant.core.execution.*; +import org.xml.sax.*; +import org.xml.sax.helpers.DefaultHandler; + +/** + * Parses the TASK-INF/antlib.xml file of an ant library + * component. An Ant library may contains tasks, apsects and + * other ant plug in components + */ +public class AntLibParser { + public static final String TASK_ELEMENT = "taskdef"; + public static final String CONVERTER_ELEMENT = "converter"; + + /** + * The factory used to create SAX parsers. + */ + private SAXParserFactory parserFactory; + + /** + * Parse the library definition + * + * @param libSource the URL from where the library XML is read. + * + * @throws SAXParseException if there is a problem parsing the task definitions + */ + public AntLibrary parseAntLibrary(URL libSource, ClassLoader componentLoader) + throws ConfigException { + try { + parserFactory = SAXParserFactory.newInstance(); + SAXParser saxParser = parserFactory.newSAXParser(); + XMLReader xmlReader = saxParser.getXMLReader(); + + AntLibRootHandler rootHandler = new AntLibRootHandler(libSource, xmlReader, componentLoader); + saxParser.parse(libSource.toString(), rootHandler); + return rootHandler.getAntLibrary(); + } + catch (SAXParseException e) { + throw new ConfigException(e.getMessage(), e, + new Location(libSource.toString(), + e.getLineNumber(), e.getColumnNumber())); + } + catch (ParserConfigurationException e) { + throw new ConfigException("Unable to parse Ant library component", e, + new Location(libSource.toString())); + } + catch (SAXException e) { + throw new ConfigException("Unable to parse Ant library component", e, + new Location(libSource.toString())); + } + catch (IOException e) { + throw new ConfigException("Unable to parse Ant library component", e, + new Location(libSource.toString())); + } + } + + /** + * The root handler handles the antlib element. An ant lib may + * contain a number of different types of elements + *
        + *
      • taskdef
      • + *
      • aspect
      • + *
      • converter
      • + *
      + */ + private class AntLibRootHandler extends RootHandler { + static private final int STATE_LOOKING_FOR_ROOT = 1; + static private final int STATE_ROOT_SEEN = 2; + static private final int STATE_FINISHED = 3; + + private int state = STATE_LOOKING_FOR_ROOT; + + /** + * The AntLibrary that will be defined by parsing the library's definition + * file. + */ + private AntLibrary library = null; + + private ClassLoader componentLoader = null; + + /** + * Create an Ant Library Root Handler. + * + * @param taskdefSource the URL from where the task definitions exist + * @param reader the XML parser. + */ + public AntLibRootHandler(URL taskdefSource, XMLReader reader, ClassLoader componentLoader) { + super(taskdefSource, reader); + this.componentLoader = componentLoader; + } + + /** + * Get the library which has been parsed. + * + * @return an AntLibary with the library definitions + */ + public AntLibrary getAntLibrary() { + return library; + } + + /** + * Start a new element in the root. This must be a taskdefs 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 { + switch (state) { + case STATE_LOOKING_FOR_ROOT: + if (qualifiedName.equals("antlib")) { + state = STATE_ROOT_SEEN; + library = new AntLibrary(); + } + else { + throw new SAXParseException("An Ant library component must start with an " + + " element and not with <" + + qualifiedName + ">", getLocator()); + } + break; + case STATE_ROOT_SEEN: + if (qualifiedName.equals(TASK_ELEMENT)) { + createTaskDef(attributes); + } + else if (qualifiedName.equals(CONVERTER_ELEMENT)) { + createConverterDef(attributes); + } + else { + throw new SAXParseException("Unrecognized element <" + + qualifiedName + "> in Ant library definition", getLocator()); + } + break; + } + } + + + public void createTaskDef(Attributes attributes) throws SAXParseException { + Set validAttributes = new HashSet(); + validAttributes.add("name"); + validAttributes.add("classname"); + Map attributeValues + = AttributeValidator.validateAttributes(TASK_ELEMENT, attributes, + validAttributes, getLocator()); + String taskName = (String)attributeValues.get("name"); + String className = (String)attributeValues.get("classname"); + if (taskName == null) { + throw new SAXParseException("'name' attribute is required in a <" + + TASK_ELEMENT + "> element", + getLocator()); + } + if (className == null) { + throw new SAXParseException("'classname' attribute is required in a " + + "<" + TASK_ELEMENT + "> element", getLocator()); + } + + System.out.println("Adding taskdef for " + taskName); + TaskDefinition taskdef = new TaskDefinition(getSourceURL(), taskName, className, componentLoader); + library.addTaskDefinition(taskdef); + } + + public void createConverterDef(Attributes attributes) throws SAXParseException { + Set validAttributes = new HashSet(); + validAttributes.add("target"); + validAttributes.add("classname"); + Map attributeValues + = AttributeValidator.validateAttributes("convert", attributes, + validAttributes, getLocator()); + String targetClassName = (String)attributeValues.get("target"); + String className = (String)attributeValues.get("classname"); + if (targetClassName == null) { + throw new SAXParseException("'target' attribute is required in a <" + + CONVERTER_ELEMENT + "> element", + getLocator()); + } + if (className == null) { + throw new SAXParseException("'classname' attribute is required in a " + + "<" + CONVERTER_ELEMENT + "> element", getLocator()); + } + + ConverterDefinition converterDef + = new ConverterDefinition(getSourceURL(), className, targetClassName, componentLoader); + library.addConverterDefinition(converterDef); + } + + public void endElement(String namespaceURI, String localName, String qName) { + if (state == STATE_ROOT_SEEN && qName.equals("antlib")) { + state = STATE_FINISHED; + } + } + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/xml/AttributeValidator.java b/proposal/mutant/src/main/org/apache/ant/core/xml/AttributeValidator.java new file mode 100644 index 000000000..7c8b0bd28 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/xml/AttributeValidator.java @@ -0,0 +1,112 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.xml; + +import org.xml.sax.helpers.DefaultHandler; +import org.xml.sax.*; +import java.util.*; + + +/** + * Validates and extracts attribute values from a set of element attributes. + * + * @author Conor MacNeill + */ +public abstract class AttributeValidator { + static public Map validateAttributes(String elementName, Attributes attributes, + Set validAttributes, Locator locator) + throws SAXParseException { + + return validateAttributes(elementName, attributes, null, validAttributes, locator); + } + + static public Map validateAttributes(String elementName, Attributes attributes, Map aspects, + Set validAttributes, Locator locator) + throws SAXParseException { + + Map attributeValues = new HashMap(); + Set invalidAttributes = new HashSet(); + for (int i = 0; i < attributes.getLength(); ++i) { + String attributeName = attributes.getQName(i); + String attributeValue = attributes.getValue(i); + if (validAttributes.contains(attributeName)) { + attributeValues.put(attributeName, attributeValue); + } + else if (aspects != null && attributeName.indexOf(":") != -1) { + aspects.put(attributeName, attributeValue); + } + else { + invalidAttributes.add(attributeName); + } + } + + if (invalidAttributes.size() != 0) { + StringBuffer message = new StringBuffer(); + boolean justOne = invalidAttributes.size() == 1; + message.append(justOne ? "The attribute " : "The attributes "); + for (Iterator i = invalidAttributes.iterator(); i.hasNext();) { + String attributeName = (String)i.next(); + message.append(attributeName + " "); + } + message.append(justOne ? "is " : "are "); + message.append("not valid for the <" + elementName + "> element."); + + throw new SAXParseException(message.toString(), locator); + } + + return attributeValues; + } + +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/xml/ElementHandler.java b/proposal/mutant/src/main/org/apache/ant/core/xml/ElementHandler.java new file mode 100644 index 000000000..00c5c738b --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/xml/ElementHandler.java @@ -0,0 +1,109 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.xml; + +import org.xml.sax.helpers.DefaultHandler; +import org.xml.sax.*; + +/** + * 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. + */ +public abstract class ElementHandler extends DefaultHandler { + private XMLReader reader; + private ContentHandler parent; + private Locator locator; + + public ElementHandler(XMLReader reader, ContentHandler parent, + Locator locator) { + this.reader = reader; + this.parent = parent; + this.locator = locator; + reader.setContentHandler(this); + } + + /** + * This element is finished - complete any necessary processing. + */ + protected void finish() { + } + + /** + * Get the XML Reader being used to parse the XML. + * + * @return the XML Reader. + */ + protected XMLReader getXMLReader() { + return reader; + } + + /** + * 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; + } + + public void endElement(String namespaceURI, String localName, String qName) { + finish(); + reader.setContentHandler(parent); + } +} diff --git a/proposal/mutant/src/main/org/apache/ant/core/xml/RootHandler.java b/proposal/mutant/src/main/org/apache/ant/core/xml/RootHandler.java new file mode 100644 index 000000000..a2a39e2c6 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/xml/RootHandler.java @@ -0,0 +1,131 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.xml; + +import org.xml.sax.helpers.DefaultHandler; +import org.xml.sax.*; +import java.net.URL; + +/** + * Handle the root of a XML parse + */ +public abstract class RootHandler extends DefaultHandler { + /** + * 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; + + /** + * Create a Root Handler. + * + * @param sourceURL the URL containing the XML source + * @param reader the XML parser. + */ + public RootHandler(URL sourceURL, XMLReader reader) { + this.sourceURL = sourceURL; + this.reader = reader; + } + + /** + * 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; + } + + /** + * Get the XML Reader being used to parse the XML. + * + * @return the XML Reader. + */ + protected XMLReader getXMLReader() { + return reader; + } + + /** + * 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; + } + + /** + * Get the source URL + * + * @return a URL identifiying from where the XML is being read. + */ + public URL getSourceURL() { + return sourceURL; + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/core/xml/XMLProjectParser.java b/proposal/mutant/src/main/org/apache/ant/core/xml/XMLProjectParser.java new file mode 100644 index 000000000..454a16aed --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/core/xml/XMLProjectParser.java @@ -0,0 +1,904 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.core.xml; + +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; +import javax.xml.parsers.*; +import org.apache.ant.core.model.*; +import org.apache.ant.core.support.*; +import org.xml.sax.*; +import org.xml.sax.helpers.DefaultHandler; + +/** + * Parses a project from an XML source using a SAX Parser. + * + * @author Conor MacNeill + */ +public class XMLProjectParser { + private Stack recursionCheck = new Stack(); + + /** + * The factory used to create SAX parsers. + */ + private SAXParserFactory parserFactory; + + static private Location getLocation(Locator locator) { + return new Location(locator.getSystemId(), locator.getLineNumber(), + locator.getColumnNumber()); + } + + /** + * Parse a build file form the given URL. + * + * @param buildSource the URL from where the build source may be read. + * + * @throws SAXParseException if there is a problem parsing the build file. + */ + public Project parseBuildFile(URL buildSource) + throws ConfigException { + try { + parserFactory = SAXParserFactory.newInstance(); + SAXParser saxParser = parserFactory.newSAXParser(); + XMLReader xmlReader = saxParser.getXMLReader(); + + recursionCheck.push(buildSource); + ProjectRootHandler projectRootHandler + = new ProjectRootHandler(buildSource, xmlReader); + saxParser.parse(buildSource.toString(), projectRootHandler); + return projectRootHandler.getProject(); + } + catch (SAXParseException e) { + throw new ConfigException(e.getMessage(), e, + new Location(buildSource.toString(), + e.getLineNumber(), e.getColumnNumber())); + } + catch (NoProjectReadException e) { + throw new ConfigException("No project defined in build source", e, + new Location(buildSource.toString())); + } + catch (ParserConfigurationException e) { + throw new ConfigException("Unable to parse project: " + e.getMessage(), e, + new Location(buildSource.toString())); + } + catch (SAXException e) { + throw new ConfigException("Unable to parse project: " + e.getMessage(), e, + new Location(buildSource.toString())); + } + catch (IOException e) { + throw new ConfigException("Unable to parse project: " + e.getMessage(), e, + new Location(buildSource.toString())); + } + } + + /** + * The root handler handles the start of parsing. This element looks for the + * root element which must be a project element. It then delegates handling of the + * project element to a project handler from which it extracts the parsed project. + */ + private class ProjectRootHandler extends RootHandler { + /** + * The project handler created to parse the project element. + */ + ProjectHandler projectHandler; + + /** + * Create a Root Handler. + * + * @param buildSource the URL containing the build definition + * @param reader the XML parser. + */ + public ProjectRootHandler(URL buildSource, XMLReader reader) { + super(buildSource, reader); + } + + /** + * 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 { + if (qualifiedName.equals("project")) { + projectHandler = new ProjectHandler(getXMLReader(), this, + getLocator(), attributes, getSourceURL()); + } else { + throw new SAXParseException("Build file should start with a element not <" + + qualifiedName + ">", getLocator()); + } + } + + /** + * Get the project that has been parsed from the element + * + * @return the project that has been parsed from the build osurce + * + * @throws NoProjectReadException thrown if no project was read in. + */ + public Project getProject() throws NoProjectReadException { + if (projectHandler == null) { + throw new NoProjectReadException(); + } + return projectHandler.getProject(); + } + } + + /** + * Root Handler for include elements. + * + * Includes must contain either a project (which is being extended) or + * a fragment element which contains the fragment to be included. + */ + private class IncludeRootHandler extends RootHandler { + /** + * The project into which the fragment is to be included. + */ + private Project project; + + /** + * Create an Include Root Handler. + * + * @param buildSource the URL containing the fragment definition + * @param reader the XML parser. + * @param project the project into which the fragment's elements will be included. + */ + public IncludeRootHandler(URL buildSource, XMLReader reader, Project project) { + super(buildSource, reader); + this.project = project; + } + + /** + * Start a new element in the include root. This must be a project element + * or a fragment 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 { + if (qualifiedName.equals("project") || + qualifiedName.equals("fragment")) { + // if it is a fragment, it must have no attributes + // any project attributes are ignored + if (qualifiedName.equals("fragment") && attributes.getLength() != 0) { + throw new SAXParseException(" element may not have any attributes", + getLocator()); + } + new ProjectHandler(getXMLReader(), this, getLocator(), + getSourceURL(), project); + } else { + throw new SAXParseException("An included file should contain either a " + + " or element and not a <" + + qualifiedName + "> element", getLocator()); + } + } + } + + /** + * Element to parse the project element. + * + * The project handler creates a number of different handlers to which it + * delegates processing of child elements. + */ + private class ProjectHandler extends ElementHandler { + /** + * The project being parsed. + */ + private Project project; + + /** + * The sourceURL for the current content being added to the project. + */ + private URL sourceURL; + + /** + * Create a ProjectHandler to read in a complete project. + * + * @param xmlReader the XML parser being used to parse the project element. + * @param parent the parent element handler. + * @param locator the SAX locator object used to associate elements with source + * locations. + * @param attributes the project element's attributes. + * @param projectSource the URL from which the XML source is being parsed. + */ + public ProjectHandler(XMLReader xmlReader, ContentHandler parent, + Locator locator, Attributes attributes, URL projectSource) + throws SAXParseException { + + super(xmlReader, parent, locator); + this.sourceURL = projectSource; + project = new Project(projectSource, getLocation(locator)); + + String base = null; + String defaultTarget = null; + String projectName = null; + + Map aspects = new HashMap(); + for (int i = 0; i < attributes.getLength(); ++i) { + String attributeName = attributes.getQName(i); + String attributeValue = attributes.getValue(i); + if (attributeName.equals("base")) { + base = attributeValue; + } + else if (attributeName.equals("default")) { + defaultTarget = attributeValue; + } + else if (attributeName.equals("name")) { + projectName = attributeValue; + } + else if (attributeName.indexOf(":") != -1) { + // potential aspect attribute + aspects.put(attributeName, attributeValue); + } + else { + throw new SAXParseException("The attribute '" + attributeName + "' is not " + + "supported by the element", getLocator()); + } + } + + project.setDefaultTarget(defaultTarget); + project.setBase(base); + project.setName(projectName); + project.setAspects(aspects); + } + + /** + * Create a Project handler for an included fragment. The elements + * from the fragment are added to the given project. + * + * @param xmlReader the XML parser being used to parse the project element. + * @param parent the parent element handler. + * @param locator the SAX locator object used to associate elements with source + * locations. + * @param includeSource the URL from which the XML source is being included. + * @param project the project to which the included fragments elements are added. + */ + public ProjectHandler(XMLReader xmlReader, ContentHandler parent, + Locator locator, URL includeSource, Project project) { + super(xmlReader, parent, locator); + this.sourceURL = includeSource; + this.project = project; + } + + /** + * Start a new element in the project. Project currently handle the + * following elements + *
        + *
      • import
      • + *
      • 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("import")) { + ImportHandler importHandler + = new ImportHandler(getXMLReader(), this, getLocator(), + attributes, sourceURL); + try { + project.importProject(importHandler.getImportName(), + importHandler.getImportedProject()); + } + catch (ProjectModelException e) { + throw new SAXParseException(e.getMessage(), getLocator(), e); + } + } + else if (qualifiedName.equals("include")) { + IncludeHandler includeHandler + = new IncludeHandler(getXMLReader(), this, getLocator(), + attributes, sourceURL, project); + } + else if (qualifiedName.equals("target")) { + TargetHandler targetHandler + = new TargetHandler(getXMLReader(), this, getLocator(), attributes); + try { + project.addTarget(targetHandler.getTarget()); + } + catch (ProjectModelException e) { + throw new SAXParseException(e.getMessage(), getLocator(), e); + } + } + else { + // everything else is a task + TaskHandler taskHandler + = new TaskHandler(getXMLReader(), this, getLocator(), + attributes, qualifiedName); + project.addTask(taskHandler.getTask()); + } + } + + /** + * Get the project that has been parsed from the XML source + * + * @return the project model of the parsed project. + */ + public Project getProject() { + return project; + } + } + + /** + * The import handler handles the importing of one project into another. + * + * The project to be imported is parsed with a new parser and then added to the + * current project under the given import name + */ + private class ImportHandler extends ElementHandler { + /** + * The attribute used to name the import. + */ + static public final String IMPORT_NAME_ATTR = "name"; + + /** + * The attribute name used to locate the project to be imported. + */ + static public final String IMPORT_SYSTEMID_ATTR = "project"; + + /** + * The project that has been imported. + */ + private Project importedProject; + + /** + * The name under which the project is being imported. + */ + private String importName; + + /** + * The systemId (URL) where the project is to be imported from. + */ + private String projectSystemId; + + /** + * Create an import handler to import a project. + * + * @param xmlReader the XML parser being used to parse the import element. + * @param parent the parent element handler. + * @param locator the SAX locator object used to associate elements with source + * locations. + * @param attributes attributes of the import statement. + * @param importingSource the URL of the importing source. + */ + public ImportHandler(XMLReader xmlReader, ContentHandler parent, + Locator locator, Attributes attributes, URL importingSource) + throws SAXParseException { + super(xmlReader, parent, locator); + for (int i = 0; i < attributes.getLength(); ++i) { + String attributeName = attributes.getQName(i); + String attributeValue = attributes.getValue(i); + if (attributeName.equals(IMPORT_NAME_ATTR)) { + importName = attributeValue; + } + else if (attributeName.equals(IMPORT_SYSTEMID_ATTR)) { + projectSystemId = attributeValue; + } + else { + throw new SAXParseException("Attribute " + attributeName + + " is not allowed in an element", getLocator()); + } + } + + if (importName == null) { + throw new SAXParseException("Attribute " + IMPORT_NAME_ATTR + + " is required in an element", getLocator()); + } + + if (projectSystemId == null) { + throw new SAXParseException("Attribute " + IMPORT_SYSTEMID_ATTR + + " is required in an element", getLocator()); + } + + // create a new parser to read this project relative to the + // project's URI + try { + URL importURL = new URL(importingSource, projectSystemId); + SAXParser importSAXParser = parserFactory.newSAXParser(); + XMLReader importXMLReader = importSAXParser.getXMLReader(); + + + if (recursionCheck.contains(importURL)) { + throw new SAXParseException("Circular import detected when importing '" + + importURL + "'", getLocator()); + } + recursionCheck.push(importURL); + ProjectRootHandler importRootHandler = new ProjectRootHandler(importURL, importXMLReader); + importSAXParser.parse(importURL.toString(), importRootHandler); + if (recursionCheck.pop() != importURL) { + throw new RuntimeException("Failure to pop expected element off recursion stack"); + } + importedProject = importRootHandler.getProject(); + } + catch (SAXParseException e) { + throw e; + } + catch (NoProjectReadException e) { + throw new SAXParseException("No project was imported from " + projectSystemId, + getLocator()); + } + catch (MalformedURLException e) { + throw new SAXParseException("Unable to import project from " + projectSystemId + + ": " + e.getMessage(), + getLocator()); + } + catch (ParserConfigurationException e) { + throw new SAXParseException("Unable to parse project imported from " + projectSystemId + + ": " + e.getMessage(), + getLocator()); + } + catch (SAXException e) { + throw new SAXParseException("Unable to parse project imported from " + projectSystemId + + ": " + e.getMessage(), + getLocator()); + } + catch (IOException e) { + throw new SAXParseException("Error reading project imported from " + projectSystemId + + ": " + e.getMessage(), + getLocator()); + } + } + + /** + * Import does not support nested elements. This method will always throw an + * exception + * @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 always. + */ + public void startElement(String uri, String localName, String qualifiedName, + Attributes attributes) throws SAXParseException { + // everything is a task + throw new SAXParseException(" does not support nested elements", getLocator()); + } + + /** + * Get the project imported. + * + * @return an imported Project. + */ + public Project getImportedProject() { + return importedProject; + } + + /** + * Get the name under which the project is imported. + * + * @return the import name of the project + */ + public String getImportName() { + return importName; + } + } + + /** + * The include handler is used to read in included projects or + * fragments into a project. + */ + private class IncludeHandler extends ElementHandler { + /** + * The attribute name which identifies the fragment to be included + */ + static public final String INCLUDE_SYSTEMID_ATTR = "fragment"; + + /** + * The system id of the fragment to be included. + */ + private String includeSystemId; + + /** + * Create an IncludeHandler to include an element into the + * current project + * + * @param xmlReader the XML parser being used to parse the include element. + * @param parent the parent element handler. + * @param locator the SAX locator object used to associate elements with source + * locations. + * @param attributes attributes of the include statement. + * @param includingSource the URL of the including source. + * @param project the project into which the included elements are added. + */ + public IncludeHandler(XMLReader xmlReader, ContentHandler parent, + Locator locator, Attributes attributes, URL includingSource, + Project project) + throws SAXParseException { + super(xmlReader, parent, locator); + for (int i = 0; i < attributes.getLength(); ++i) { + String attributeName = attributes.getQName(i); + String attributeValue = attributes.getValue(i); + if (attributeName.equals(INCLUDE_SYSTEMID_ATTR)) { + includeSystemId = attributeValue; + } + else { + throw new SAXParseException("Attribute " + attributeName + + " is not allowed in an element", getLocator()); + } + } + + if (includeSystemId == null) { + throw new SAXParseException("Attribute " + INCLUDE_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(includingSource, includeSystemId); + SAXParser includeSAXParser = parserFactory.newSAXParser(); + XMLReader includeXMLReader = includeSAXParser.getXMLReader(); + + if (recursionCheck.contains(includeURL)) { + throw new SAXParseException("Circular include detected when including '" + + includeURL + "'", getLocator()); + } + recursionCheck.push(includeURL); + IncludeRootHandler includeRootHandler + = new IncludeRootHandler(includeURL, includeXMLReader, project); + includeSAXParser.parse(includeURL.toString(), includeRootHandler); + if (recursionCheck.pop() != includeURL) { + throw new RuntimeException("Failure to pop expected element off recursion stack"); + } + } + catch (SAXParseException e) { + throw e; + } + catch (MalformedURLException e) { + throw new SAXParseException("Unable to include " + includeSystemId + + ": " + e.getMessage(), + getLocator()); + } + catch (ParserConfigurationException e) { + throw new SAXParseException("Unable to parse include " + includeSystemId + + ": " + e.getMessage(), + getLocator()); + } + catch (SAXException e) { + throw new SAXParseException("Unable to parse include " + includeSystemId + + ": " + e.getMessage(), + getLocator()); + } + catch (IOException e) { + throw new SAXParseException("Error reading include " + includeSystemId + + ": " + e.getMessage(), + getLocator()); + } + } + + /** + * Include does not support nested elements. This method will always throw an + * exception + * + * @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 always. + */ + public void startElement(String uri, String localName, String qualifiedName, + Attributes attributes) throws SAXParseException { + // everything is a task + throw new SAXParseException(" does not support nested elements", getLocator()); + } + + } + + /** + * A TargetHandler process the Target element. + */ + private class TargetHandler extends ElementHandler { + /** + * The target being configured. + */ + private Target target; + + /** + * Create a Target handler. Event element in a target is + * considered to be a task + * + * @param xmlReader the XML parser being used to parse the target element. + * @param parent the parent element handler. + * @param locator the SAX locator object used to associate elements with source + * locations. + * @param attributes attributes of the target + */ + public TargetHandler(XMLReader xmlReader, ContentHandler parent, + Locator locator, Attributes attributes) + throws SAXParseException { + super(xmlReader, parent, locator); + String targetName = null; + String depends = null; + Map aspects = new HashMap(); + for (int i = 0; i < attributes.getLength(); ++i) { + String attributeName = attributes.getQName(i); + String attributeValue = attributes.getValue(i); + if (attributeName.equals("name")) { + targetName = attributeValue; + } + else if (attributeName.equals("depends")) { + depends = attributeValue; + } + else if (attributeName.indexOf(":") != -1) { + // potential aspect attribute + aspects.put(attributeName, attributeValue); + } + else { + throw new SAXParseException("The attribute '" + attributeName + "' is not " + + "supported by the element", getLocator()); + } + } + if (targetName == null) { + throw new SAXParseException("Targets must have a name attribute", locator); + } + target = new Target(getLocation(locator), targetName); + target.setAspects(aspects); + + 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 + TaskHandler taskHandler + = new TaskHandler(getXMLReader(), this, getLocator(), + attributes, qualifiedName); + target.addTask(taskHandler.getTask()); + } + + /** + * Get the target parsed by this handler. + * + * @return the Target model object parsed by this handler. + */ + public Target getTarget() { + return target; + } + } + + /** + * A Task Handler is used to parse tasks. + */ + private class TaskHandler extends ElementHandler { + /** + * The task being parsed by this handler. + */ + private Task task; + + /** + * Create a task handler to parse the Task element + * + * @param xmlReader the XML parser being used to parse the task element. + * @param parent the parent element handler. + * @param locator the SAX locator object used to associate elements with source + * locations. + * @param attributes attributes of the task + * @param taskTagName the name of the task. + */ + public TaskHandler(XMLReader xmlReader, ContentHandler parent, Locator locator, + Attributes attributes, String taskTagName) { + super(xmlReader, parent, locator); + task = new Task(getLocation(locator), taskTagName); + + Map aspects = new HashMap(); + for (int i = 0; i < attributes.getLength(); ++i) { + String attributeName = attributes.getQName(i); + String attributeValue = attributes.getValue(i); + if (attributeName.indexOf(":") != -1) { + // potential aspect attribute + aspects.put(attributeName, attributeValue); + } + else { + task.addAttribute(attributeName, attributeValue); + } + } + task.setAspects(aspects); + } + + /* + * Process a nested element within this task. All nested elements within + * the task are treated as taskelements. + * + * @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 is a task element + TaskElementHandler taskElementHandler + = new TaskElementHandler(getXMLReader(), this, getLocator(), + attributes, qualifiedName); + task.addTaskElement(taskElementHandler.getTaskElement()); + } + + public void characters(char[] buf, int start, int end) throws SAXParseException { + task.addText(new String(buf, start, end)); + } + + /** + * Get the task that is being parsed + * + * @return the task being parsed by this task handler. + */ + public Task getTask() { + return task; + } + } + + /** + * A Task Element Handler parses the nested elements of tasks. + */ + private class TaskElementHandler extends ElementHandler { + /** + * The task element being parsed by this handler. + */ + private TaskElement taskElement; + + /** + * Create a task element handler to parse a task element + * + * @param xmlReader the XML parser being used to parse the task element. + * @param parent the parent element handler. + * @param locator the SAX locator object used to associate elements with source + * locations. + * @param attributes attributes of the task element + * @param elementTagName the name of the task element. + */ + public TaskElementHandler(XMLReader xmlReader, ContentHandler parent, Locator locator, + Attributes attributes, String elementTagName) { + super(xmlReader, parent, locator); + taskElement + = new TaskElement(getLocation(locator), elementTagName); + + Map aspects = new HashMap(); + for (int i = 0; i < attributes.getLength(); ++i) { + String attributeName = attributes.getQName(i); + String attributeValue = attributes.getValue(i); + if (attributeName.indexOf(":") != -1) { + // potential aspect attribute + aspects.put(attributeName, attributeValue); + } + else { + taskElement.addAttribute(attributeName, attributeValue); + } + } + taskElement.setAspects(aspects); + } + + /** + * Process a nested element of this task element. All nested elements + * of a taskElement are themselves taskElements. + * + * @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 + TaskElementHandler taskElementHandler + = new TaskElementHandler(getXMLReader(), this, getLocator(), + attributes, qualifiedName); + taskElement.addTaskElement(taskElementHandler.getTaskElement()); + } + + public void characters(char[] buf, int start, int end) throws SAXParseException { + taskElement.addText(new String(buf, start, end)); + } + + /** + * Get the task element being parsed by this handler. + * + * @return the TaskElement being parsed. + */ + public TaskElement getTaskElement() { + return taskElement; + } + } + + /** + * A NoProjectReadException is used to indicate that a project + * was not read from the particular source. This will happen + * if the source is empty. + */ + private class NoProjectReadException extends Exception { + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/frontend/BuildLogger.java b/proposal/mutant/src/main/org/apache/ant/frontend/BuildLogger.java new file mode 100644 index 000000000..8a654c885 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/frontend/BuildLogger.java @@ -0,0 +1,94 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999 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.frontend; + +import org.apache.ant.core.execution.*; + +import java.io.*; + +/** + * 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 + */ +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/main/org/apache/ant/frontend/Commandline.java b/proposal/mutant/src/main/org/apache/ant/frontend/Commandline.java new file mode 100644 index 000000000..461080d57 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/frontend/Commandline.java @@ -0,0 +1,307 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.frontend; + +import java.io.*; +import java.net.*; +import java.util.*; +import javax.xml.parsers.*; +import org.xml.sax.SAXParseException; +import java.lang.reflect.*; + +import org.apache.ant.core.execution.*; +import org.apache.ant.core.support.*; +import org.apache.ant.core.xml.*; +import org.apache.ant.core.config.*; +import org.apache.ant.core.model.*; + +/** + * This is the command line front end to end. It drives the core + * + * @author Conor MacNeill + */ +public class Commandline { + /** The default build file name */ + static public final String DEFAULT_BUILD_FILENAME = "build.ant"; + + /** 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); + + /** Our current message output status. Follows Project.MSG_XXX */ + private int messageOutputLevel = BuildEvent.MSG_VERBOSE; + + /** + * 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; + + public static void start(String[] args) { + // create a command line and use it to run ant + Commandline commandline = new Commandline(); + commandline.runAnt(args); + } + + public void runAnt(String[] args) { + ExecutionManager executionManager = null; + try { + parseArguments(args); + Project project = getProject(); + for (Iterator i = project.getTargets(); i.hasNext();) { + Target target = (Target)i.next(); + } + + // Get the list of library components + AntLibrary[] libraries = ComponentManager.getComponents(); + executionManager = new ExecutionManager(); + executionManager.addLibraries(libraries); + executionManager.setProject(project); + addBuildListeners(executionManager); + } + catch (AntException e) { + Location location = e.getLocation(); + Throwable cause = e.getCause(); + if (location != null && location != Location.UNKNOWN_LOCATION) { + System.out.print(location); + } + System.out.print(e.getMessage()); + + if (cause != null) { + System.out.println(); + System.out.print("Root cause: " + cause.getClass().getName() + ": " + cause.getMessage()); + } + System.out.println(); + + System.exit(1); + } + + try { + executionManager.runBuild(targets); + System.exit(0); + } + catch (Exception e) { + System.exit(1); + } + } + + protected void addBuildListeners(ExecutionManager executionManager) + throws ConfigException { + + // Add the default listener + executionManager.addBuildListener(createLogger()); + + for (Iterator i = listeners.iterator(); i.hasNext(); ) { + String className = (String) i.next(); + try { + BuildListener listener = + (BuildListener) Class.forName(className).newInstance(); + executionManager.addBuildListener(listener); + } + catch(Exception exc) { + throw new ConfigException("Unable to instantiate listener " + className, exc); + } + } + } + + /** + * Creates the default build logger for sending build events to the ant log. + */ + private BuildLogger createLogger() throws ConfigException { + BuildLogger logger = null; + if (loggerClassname != null) { + try { + logger = (BuildLogger)(Class.forName(loggerClassname).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; + } + + + /** + * Parse the command line arguments. + */ + 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) { + File file = new File(url); + String uri = "file:" + file.getAbsolutePath().replace('\\', '/'); + for (int index = uri.indexOf('#'); index != -1; index = uri.indexOf('#')) { + uri = uri.substring(0, index) + "%23" + uri.substring(index+1); + } + buildFileURL = new URL(uri); + // We convert any hash characters to their URL escape. + } + 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("-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 argument: " + 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 = defaultBuildFile.toURL(); + } + catch (MalformedURLException e) { + System.err.println("Buildfile is not valid: " + e.getMessage()); + throw new ConfigException("Build file is not valid", e); + } + } + } + + private Project getProject() throws ConfigException { + XMLProjectParser parser = new XMLProjectParser(); + Project project = parser.parseBuildFile(buildFileURL); + return project; + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/frontend/DefaultLogger.java b/proposal/mutant/src/main/org/apache/ant/frontend/DefaultLogger.java new file mode 100644 index 000000000..076fff869 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/frontend/DefaultLogger.java @@ -0,0 +1,227 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999 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.frontend; + +import org.apache.ant.core.support.*; +import org.apache.ant.core.model.*; +import org.apache.ant.core.execution.*; +import java.io.*; + +/** + * Writes build event to a PrintStream. Currently, it + * only writes which targets are being executed, and + * any messages that get logged. + */ +public class DefaultLogger implements BuildLogger { + private static int LEFT_COLUMN_SIZE = 12; + + protected PrintStream out; + protected PrintStream err; + protected int msgOutputLevel = BuildEvent.MSG_ERR; + private long startTime = System.currentTimeMillis(); + + protected static String lSep = System.getProperty("line.separator"); + + protected boolean emacsMode = false; + + /** + * 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. + *

      + * 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.msgOutputLevel = 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; + } + + 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.print(e.getMessage()); + + if (cause != null) { + out.println(); + out.print("Root cause: " + cause.getClass().getName() + ": " + cause.getMessage()); + } + out.println(); + } + else { + t.printStackTrace(err); + } + } + + 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 (BuildEvent.MSG_INFO <= msgOutputLevel) { + Target target = (Target)event.getBuildElement(); + 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() == BuildEvent.MSG_ERR ? err : out; + + // Filter out messages based on priority + if (event.getPriority() <= msgOutputLevel) { + + // Print out the name of the task if we're in one + Object buildElement = event.getBuildElement(); + if (buildElement instanceof Task) { + Task task = (Task)buildElement; + String name = task.getType(); + + if (!emacsMode) { + String msg = "[" + name + "] "; + for (int i = 0; i < (LEFT_COLUMN_SIZE - msg.length()); i++) { + logTo.print(" "); + } + logTo.print(msg); + } + } + + // Print the message + logTo.println(event.getMessage()); + } + break; + default: + err.println("Unrecognized event type = " + event.getEventType()); + break; + } + } + + protected static String formatTime(long millis) { + long seconds = millis / 1000; + long minutes = seconds / 60; + + + if (minutes > 0) { + return Long.toString(minutes) + " minute" + + (minutes == 1 ? " " : "s ") + + Long.toString(seconds%60) + " second" + + (seconds%60 == 1 ? "" : "s"); + } + else { + return Long.toString(seconds) + " second" + + (seconds%60 == 1 ? "" : "s"); + } + + } + +} diff --git a/proposal/mutant/src/main/org/apache/ant/frontend/EmbedTest.java b/proposal/mutant/src/main/org/apache/ant/frontend/EmbedTest.java new file mode 100644 index 000000000..10f001885 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/frontend/EmbedTest.java @@ -0,0 +1,77 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.frontend; + +import java.io.*; +import java.net.*; +import java.util.*; +import javax.xml.parsers.*; +import org.xml.sax.SAXParseException; +import java.lang.reflect.*; + +import org.apache.ant.core.support.*; +import org.apache.ant.core.xml.*; +import org.apache.ant.core.config.*; + +/** + * This class illustrates the use of the ExecutionFrame class + * standalone to execute tasks + * + * @author Conor MacNeill + */ +public class EmbedTest { + +} + diff --git a/proposal/mutant/src/main/org/apache/ant/frontend/Launcher.java b/proposal/mutant/src/main/org/apache/ant/frontend/Launcher.java new file mode 100644 index 000000000..ccc024848 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/frontend/Launcher.java @@ -0,0 +1,89 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.frontend; + +import java.io.*; +import java.net.*; +import javax.xml.parsers.*; +import java.lang.reflect.*; + +import org.apache.ant.core.support.*; + +/** + * This is the command line front end to end. It drives the core + * + * @author Conor MacNeill + */ +public class Launcher { + public static void main(String[] args) throws Exception { + + // we need to find the parser jars and makre sure we are going to use + // those in preference to anything else that may be lying about in the + // user's classpath + AntClassLoader coreClassLoader = AntLocator.getCoreClassLoader(System.getProperties()); + + URL frontEndURL = AntLocator.getClassLocationURL(Launcher.class); + coreClassLoader.addURL(frontEndURL); + + Class commandLineClass = Class.forName("org.apache.ant.frontend.Commandline", true, coreClassLoader); + + final Class[] param = {Class.forName("[Ljava.lang.String;")}; + Class target = null; + final Method startMethod = commandLineClass.getMethod("start", param); + final Object[] argument = {args}; + startMethod.invoke(null, argument); + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/frontend/RemoteLauncher.java b/proposal/mutant/src/main/org/apache/ant/frontend/RemoteLauncher.java new file mode 100644 index 000000000..63cea5ab9 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/frontend/RemoteLauncher.java @@ -0,0 +1,97 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.ant.frontend; + +import java.io.*; +import java.net.*; +import javax.xml.parsers.*; +import java.lang.reflect.*; + +import org.apache.ant.core.support.*; + +/** + * Command line to run Ant core from a remote server + * + * @author Conor MacNeill + */ +public class RemoteLauncher { + public static void main(String[] args) throws Exception { + + String antHome = args[0]; + String parserHome = args[1]; + + URL[] remoteCore = new URL[3]; + remoteCore[0] = new URL(antHome + "/lib/core.jar"); + remoteCore[1] = new URL(antHome + "/lib/frontend.jar"); + remoteCore[2] = new URL(parserHome); + AntClassLoader coreClassLoader = new AntClassLoader(remoteCore); + + String[] realArgs = new String[args.length - 2]; + System.arraycopy(args, 2, realArgs, 0, realArgs.length); + + + System.out.print("Loading remote Ant ... "); + Class launcher = Class.forName("org.apache.ant.frontend.Commandline", true, coreClassLoader); + + final Class[] param = { Class.forName("[Ljava.lang.String;") }; + Class target = null; + final Method startMethod = launcher.getMethod("start", param); + final Object[] argument = {realArgs}; + System.out.println("Done"); + System.out.println("Starting remote Ant"); + startMethod.invoke(null, argument); + } +} + diff --git a/proposal/mutant/src/main/org/apache/ant/frontend/eggmanifest.mf b/proposal/mutant/src/main/org/apache/ant/frontend/eggmanifest.mf new file mode 100644 index 000000000..99001c238 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/frontend/eggmanifest.mf @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Created-By: Ant 2.0alpha +Main-Class: org.apache.ant.frontend.RemoteLauncher +Class-Path: core.jar +Sealed: true \ No newline at end of file diff --git a/proposal/mutant/src/main/org/apache/ant/frontend/manifest.mf b/proposal/mutant/src/main/org/apache/ant/frontend/manifest.mf new file mode 100644 index 000000000..bffb78055 --- /dev/null +++ b/proposal/mutant/src/main/org/apache/ant/frontend/manifest.mf @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Created-By: Ant 2.0alpha +Main-Class: org.apache.ant.frontend.Launcher +Class-Path: core.jar +Sealed: true \ No newline at end of file