From b7e43ad8c5906ae2b6d6b42f8b2715dc7d2e7a16 Mon Sep 17 00:00:00 2001 From: Conor MacNeill Date: Sat, 2 Feb 2002 14:50:34 +0000 Subject: [PATCH] mutant mutation An1 compatability - sort of git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271078 13f79535-47bb-0310-9956-ffa450edef68 --- proposal/mutant/build.xml | 33 +- .../ant/antcore/antlib/AntLibHandler.java | 24 +- .../ant/antcore/antlib/AntLibManager.java | 310 +++++++++ .../apache/ant/antcore/antlib/AntLibrary.java | 62 +- .../ant/antcore/antlib/AntLibrarySpec.java | 32 +- ...rterHandler.java => ClassNameHandler.java} | 4 +- .../apache/ant/antcore/config/AntConfig.java | 50 +- .../ant/antcore/config/AntConfigHandler.java | 10 +- ...askDirHandler.java => LoadLibHandler.java} | 8 +- .../BuildEventSupport.java | 4 +- .../antcore/execution/ClassIntrospector.java | 6 + .../execution/ExecutionComponentService.java | 123 ++++ .../antcore/execution/ExecutionContext.java | 87 ++- .../execution/ExecutionDataService.java | 212 ++++++ .../execution/ExecutionFileService.java | 97 +++ .../ant/antcore/execution/ExecutionFrame.java | 598 ++++++++++------- .../antcore/execution/ExecutionManager.java | 307 ++------- .../ant/antcore/execution/Reflector.java | 298 +++++++-- .../ant/antcore/execution/TaskAdapter.java | 13 +- .../ant/antcore/execution/TaskContext.java | 24 +- .../org/apache/ant/antcore/model/Project.java | 6 - .../model/xmlparser}/BuildElementHandler.java | 2 +- .../model/xmlparser}/IncludeHandler.java | 2 +- .../xmlparser}/NoProjectReadException.java | 2 +- .../model/xmlparser}/ProjectHandler.java | 3 +- .../antcore/model/xmlparser}/RefHandler.java | 2 +- .../model/xmlparser}/TargetHandler.java | 3 +- .../model/xmlparser}/XMLProjectParser.java | 2 +- .../ant/antcore/xml/ElementHandler.java | 14 +- .../apache/ant/antcore/xml/ParseContext.java | 6 +- .../src/java/antlibs/ant1compat/antlib.xml | 23 + .../org/apache/tools/ant/Ant1Converter.java | 136 ++++ .../org/apache/tools/ant/Ant1Factory.java | 189 ++++++ .../org/apache/tools/ant/AntClassLoader.java | 280 ++++++++ .../org/apache/tools/ant/BuildEvent.java | 72 ++ .../org/apache/tools/ant/BuildListener.java | 65 ++ .../org/apache/tools/ant/Project.java | 622 ++++++++++++++++++ .../apache/tools/ant/ProjectComponent.java} | 126 ++-- .../org/apache/tools/ant/ProjectHelper.java | 135 ++++ .../org/apache/tools/ant/Target.java | 64 ++ .../org/apache/tools/ant/Task.java} | 103 +-- .../org/apache/tools/ant/TaskContainer.java | 64 ++ .../org/apache/tools/ant/types/DataType.java | 234 +++++++ .../mutant/src/java/antlibs/file/antlib.xml | 6 - .../mutant/src/java/antlibs/io/antlib.xml | 8 - .../mutant/src/java/antlibs/system/antlib.xml | 13 + .../ant/antlib/system}/FileConverter.java | 17 +- .../org/apache/ant/antlib/system/Import.java | 74 +++ .../org/apache/ant/antlib/system/LibPath.java | 72 ++ .../org/apache/ant/antlib/system/LoadLib.java | 162 +++++ .../ant/antlib/system/PrimitiveConverter.java | 113 ++++ .../org/apache/ant/antlib/system/Taskdef.java | 69 ++ .../org/apache/ant/antlib/system/Typedef.java | 69 ++ .../ant/antlib/system/URLConverter.java} | 47 +- .../cli/org/apache/ant/cli/BuildLogger.java | 2 +- .../cli/org/apache/ant/cli/Commandline.java | 132 +++- .../cli/org/apache/ant/cli/DefaultLogger.java | 10 +- .../AbstractConverter.java | 17 +- .../common/{task => antlib}/AbstractTask.java | 3 +- .../apache/ant/common/antlib/AntContext.java | 104 +++ .../ant/common/antlib/AntLibFactory.java | 116 ++++ .../{converter => antlib}/Converter.java | 20 +- .../ant/common/{task => antlib}/DataType.java | 12 +- .../ExecutionComponent.java} | 24 +- .../StandardLibFactory.java} | 99 ++- .../org/apache/ant/common/antlib/Task.java | 74 +++ .../{task => antlib}/TaskContainer.java | 7 +- .../apache/ant/common}/event/BuildEvent.java | 30 +- .../ant/common}/event/BuildListener.java | 2 +- .../ant/common/service/ComponentService.java | 84 +++ .../ant/common/service/DataService.java | 132 ++++ .../FileService.java} | 24 +- ...Exception.java => ExecutionException.java} | 20 +- .../org/apache/ant/common/util/FileUtils.java | 90 ++- .../org/apache/ant/common/util/Location.java | 8 +- .../apache/ant/common/util/PropertyUtils.java | 126 ++++ .../init/org/apache/ant/init/InitConfig.java | 13 +- .../init/org/apache/ant/init/LoaderUtils.java | 54 +- .../org/apache/ant/remote/RemoteMain.java | 48 ++ .../java/start/org/apache/ant/start/Main.java | 23 +- 80 files changed, 5315 insertions(+), 1066 deletions(-) create mode 100644 proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibManager.java rename proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/{ConverterHandler.java => ClassNameHandler.java} (97%) mode change 100755 => 100644 rename proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/{TaskDirHandler.java => LoadLibHandler.java} (95%) mode change 100755 => 100644 rename proposal/mutant/src/java/antcore/org/apache/ant/antcore/{event => execution}/BuildEventSupport.java (97%) mode change 100755 => 100644 create mode 100644 proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionComponentService.java create mode 100644 proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionDataService.java create mode 100644 proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFileService.java rename proposal/mutant/src/java/{cli/org/apache/ant/cli/xml => antcore/org/apache/ant/antcore/model/xmlparser}/BuildElementHandler.java (99%) mode change 100755 => 100644 rename proposal/mutant/src/java/{cli/org/apache/ant/cli/xml => antcore/org/apache/ant/antcore/model/xmlparser}/IncludeHandler.java (99%) mode change 100755 => 100644 rename proposal/mutant/src/java/{cli/org/apache/ant/cli/xml => antcore/org/apache/ant/antcore/model/xmlparser}/NoProjectReadException.java (98%) mode change 100755 => 100644 rename proposal/mutant/src/java/{cli/org/apache/ant/cli/xml => antcore/org/apache/ant/antcore/model/xmlparser}/ProjectHandler.java (99%) mode change 100755 => 100644 rename proposal/mutant/src/java/{cli/org/apache/ant/cli/xml => antcore/org/apache/ant/antcore/model/xmlparser}/RefHandler.java (99%) mode change 100755 => 100644 rename proposal/mutant/src/java/{cli/org/apache/ant/cli/xml => antcore/org/apache/ant/antcore/model/xmlparser}/TargetHandler.java (98%) mode change 100755 => 100644 rename proposal/mutant/src/java/{cli/org/apache/ant/cli/xml => antcore/org/apache/ant/antcore/model/xmlparser}/XMLProjectParser.java (98%) mode change 100755 => 100644 create mode 100644 proposal/mutant/src/java/antlibs/ant1compat/antlib.xml create mode 100644 proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Converter.java create mode 100644 proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Factory.java create mode 100644 proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/AntClassLoader.java create mode 100644 proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildEvent.java create mode 100644 proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildListener.java create mode 100644 proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java rename proposal/mutant/src/java/antlibs/{io/code/org/apache/ant/taskdef/io/Echo.java => ant1compat/org/apache/tools/ant/ProjectComponent.java} (54%) mode change 100755 => 100644 create mode 100644 proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectHelper.java create mode 100644 proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Target.java rename proposal/mutant/src/java/{common/org/apache/ant/common/task/TaskException.java => antlibs/ant1compat/org/apache/tools/ant/Task.java} (56%) mode change 100755 => 100644 create mode 100644 proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/TaskContainer.java create mode 100644 proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/types/DataType.java delete mode 100755 proposal/mutant/src/java/antlibs/file/antlib.xml delete mode 100755 proposal/mutant/src/java/antlibs/io/antlib.xml create mode 100644 proposal/mutant/src/java/antlibs/system/antlib.xml rename proposal/mutant/src/java/antlibs/{io/code/org/apache/ant/taskdef/io => system/code/org/apache/ant/antlib/system}/FileConverter.java (85%) mode change 100755 => 100644 create mode 100644 proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Import.java create mode 100644 proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/LibPath.java create mode 100644 proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/LoadLib.java create mode 100644 proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/PrimitiveConverter.java create mode 100644 proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Taskdef.java create mode 100644 proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Typedef.java rename proposal/mutant/src/java/{antcore/org/apache/ant/antcore/execution/TypeContext.java => antlibs/system/code/org/apache/ant/antlib/system/URLConverter.java} (70%) mode change 100755 => 100644 rename proposal/mutant/src/java/common/org/apache/ant/common/{converter => antlib}/AbstractConverter.java (85%) mode change 100755 => 100644 rename proposal/mutant/src/java/common/org/apache/ant/common/{task => antlib}/AbstractTask.java (97%) mode change 100755 => 100644 create mode 100644 proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java create mode 100644 proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntLibFactory.java rename proposal/mutant/src/java/common/org/apache/ant/common/{converter => antlib}/Converter.java (83%) mode change 100755 => 100644 rename proposal/mutant/src/java/common/org/apache/ant/common/{task => antlib}/DataType.java (89%) mode change 100755 => 100644 rename proposal/mutant/src/java/common/org/apache/ant/common/{task/Task.java => antlib/ExecutionComponent.java} (85%) mode change 100755 => 100644 rename proposal/mutant/src/java/common/org/apache/ant/common/{converter/ConversionException.java => antlib/StandardLibFactory.java} (54%) mode change 100755 => 100644 create mode 100644 proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java rename proposal/mutant/src/java/common/org/apache/ant/common/{task => antlib}/TaskContainer.java (92%) mode change 100755 => 100644 rename proposal/mutant/src/java/{antcore/org/apache/ant/antcore => common/org/apache/ant/common}/event/BuildEvent.java (86%) mode change 100755 => 100644 rename proposal/mutant/src/java/{antcore/org/apache/ant/antcore => common/org/apache/ant/common}/event/BuildListener.java (98%) mode change 100755 => 100644 create mode 100644 proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java create mode 100644 proposal/mutant/src/java/common/org/apache/ant/common/service/DataService.java rename proposal/mutant/src/java/common/org/apache/ant/common/{context/AntContext.java => service/FileService.java} (82%) mode change 100755 => 100644 rename proposal/mutant/src/java/common/org/apache/ant/common/util/{GeneralAntException.java => ExecutionException.java} (88%) mode change 100755 => 100644 create mode 100644 proposal/mutant/src/java/common/org/apache/ant/common/util/PropertyUtils.java create mode 100644 proposal/mutant/src/java/remote/org/apache/ant/remote/RemoteMain.java diff --git a/proposal/mutant/build.xml b/proposal/mutant/build.xml index cd52693aa..cfde59f55 100644 --- a/proposal/mutant/build.xml +++ b/proposal/mutant/build.xml @@ -11,6 +11,15 @@ + + + + + + + + + @@ -102,6 +111,25 @@ + + + + + + + + + + + + + + + + + + + @@ -111,6 +139,9 @@ + + + @@ -132,7 +163,7 @@ - + diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibHandler.java index c83b64a66..82570ba2e 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibHandler.java @@ -81,6 +81,7 @@ public class AntLibHandler extends ElementHandler { /** The extends attribute name */ public final static String ISOLATED_ATTR = "isolated"; + /** The list of allowed Attributes */ public final static String[] ALLOWED_ATTRIBUTES = {LIBID_ATTR, HOME_ATTR, REQXML_ATTR, REQTOOLS_ATTR, @@ -144,12 +145,20 @@ public class AntLibHandler extends ElementHandler { antLibrarySpec.addDefinition(defnHandler.getDefinitionType(), defnHandler.getName(), defnHandler.getClassName()); } else if (qualifiedName.equals("converter")) { - ConverterHandler converterHandler - = new ConverterHandler(); + ClassNameHandler converterHandler + = new ClassNameHandler(); converterHandler.start(getParseContext(), getXMLReader(), this, getLocator(), attributes, getElementSource(), qualifiedName); antLibrarySpec.addConverter(converterHandler.getClassName()); + } else if (qualifiedName.equals("factory")) { + ClassNameHandler factoryHandler + = new ClassNameHandler(); + factoryHandler.start(getParseContext(), getXMLReader(), + this, getLocator(), attributes, getElementSource(), + qualifiedName); + String factoryClass = factoryHandler.getClassName(); + antLibrarySpec.setFactory(factoryClass); } else { super.startElement(uri, localName, qualifiedName, attributes); @@ -179,17 +188,6 @@ public class AntLibHandler extends ElementHandler { } - /** - * Get an attribute as a boolean value - * - * @param attributeName the name of the attribute - * @return the attribute value as a boolean - */ - private boolean getBooleanAttribute(String attributeName) { - String value = getAttribute(attributeName); - return value != null && (value.equalsIgnoreCase("true") - || value.equalsIgnoreCase("yes")); - } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibManager.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibManager.java new file mode 100644 index 000000000..0304f2935 --- /dev/null +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibManager.java @@ -0,0 +1,310 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antcore.antlib; +import java.io.File; +import java.io.FileNotFoundException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.apache.ant.antcore.util.CircularDependencyChecker; +import org.apache.ant.antcore.util.CircularDependencyException; +import org.apache.ant.antcore.util.ConfigException; +import org.apache.ant.antcore.xml.ParseContext; +import org.apache.ant.antcore.xml.XMLParseException; +import org.apache.ant.init.InitConfig; +import org.apache.ant.init.InitUtils; +import org.apache.ant.init.LoaderUtils; + +/** + * This class manages the configuration of Ant Libraries + * + * @author Conor MacNeill + * @created 29 January 2002 + */ +public class AntLibManager { + + /** The list of extensions which are examined for ant libraries */ + public final static String[] ANTLIB_EXTENSIONS + = new String[]{".tsk", ".jar", ".zip"}; + + /** Flag which indicates whether non-file URLS are used */ + private boolean remoteAllowed; + + /** + * Constructor for the AntLibManager object + * + * @param remoteAllowed true if remote libraries can be used and + * configured + */ + public AntLibManager(boolean remoteAllowed) { + this.remoteAllowed = remoteAllowed; + } + + /** + * Add all the Ant libraries that can be found at the given URL + * + * @param librarySpecs A map to which additional library specifications + * are added. + * @param libURL the URL from which Ant libraries are to be loaded + * @exception MalformedURLException if the URL for the individual + * library components cannot be formed + * @exception ConfigException if the library specs cannot be parsed + */ + public void addAntLibraries(Map librarySpecs, URL libURL) + throws MalformedURLException, ConfigException { + URL[] libURLs = LoaderUtils.getLocationURLs(libURL, libURL.toString(), + ANTLIB_EXTENSIONS); + + if (libURLs == null) { + return; + } + + // parse each task library to get its library definition + for (int i = 0; i < libURLs.length; ++i) { + URL antLibraryURL = new URL("jar:" + libURLs[i] + + "!/META-INF/antlib.xml"); + try { + AntLibrarySpec antLibrarySpec = parseLibraryDef(antLibraryURL); + if (antLibrarySpec != null) { + String libraryId = antLibrarySpec.getLibraryId(); + if (librarySpecs.containsKey(libraryId)) { + throw new ConfigException("Found more than one " + + "copy of library with id = " + libraryId + + " (" + libURLs[i] + ")"); + } + antLibrarySpec.setLibraryURL(libURLs[i]); + librarySpecs.put(libraryId, antLibrarySpec); + } + } catch (XMLParseException e) { + Throwable t = e.getCause(); + // ignore file not found exceptions - means the + // jar does not provide META-INF/antlib.xml + if (!(t instanceof FileNotFoundException)) { + throw new ConfigException("Unable to parse Ant library " + + libURLs[i], e); + } + } + } + } + + /** + * Configures the Ant Libraries. Configuration of an Ant Library + * involves resolving any dependencies between libraries and then + * creating the class loaders for the library + * + * @param librarySpecs the loaded specifications of the Ant libraries + * @param initConfig the Ant initialization configuration + * @param libraries the collection of libraries already configured + * @exception ConfigException if a library cannot be configured from the + * given specification + */ + public void configLibraries(InitConfig initConfig, Map librarySpecs, + Map libraries) + throws ConfigException { + + // check if any already defined + for (Iterator i = librarySpecs.keySet().iterator(); i.hasNext(); ) { + String libraryId = (String)i.next(); + if (libraries.containsKey(libraryId)) { + AntLibrary currentVersion + = (AntLibrary)libraries.get(libraryId); + throw new ConfigException("Ant Library \"" + libraryId + + "\" is already loaded from " + + currentVersion.getDefinitionURL()); + } + } + + CircularDependencyChecker configuring + = new CircularDependencyChecker("configuring Ant libraries"); + for (Iterator i = librarySpecs.keySet().iterator(); i.hasNext(); ) { + String libraryId = (String)i.next(); + if (!libraries.containsKey(libraryId)) { + configLibrary(initConfig, librarySpecs, libraryId, + configuring, libraries); + } + } + } + + /** + * Load either a set of libraries or a single library. + * + * @param libLocationString URL or file where libraries can be found + * @param librarySpecs A collection of library specs which will be + * populated with the libraries found + * @exception ConfigException if the libraries cannot be loaded + * @exception MalformedURLException if the library's location cannot be + * formed + */ + public void loadLib(Map librarySpecs, String libLocationString) + throws ConfigException, MalformedURLException { + + File libLocation = new File(libLocationString); + if (!libLocation.exists()) { + try { + URL libLocationURL = new URL(libLocationString); + if (!libLocationURL.getProtocol().equals("file") + && !remoteAllowed) { + throw new ConfigException("The config library " + + "location \"" + libLocationString + + "\" cannot be used because config does " + + "not allow remote libraries"); + } + addAntLibraries(librarySpecs, libLocationURL); + } catch (MalformedURLException e) { + // XXX + } + } else { + addAntLibraries(librarySpecs, InitUtils.getFileURL(libLocation)); + } + } + + /** + * Configure a library from a specification and the Ant init config. + * + * @param initConfig Ant's init config passed in from the front end. + * @param librarySpecs the library specs from which this library is to + * be configured. + * @param libraryId the global identifier for the library + * @param configuring A circualr dependency chcker for library + * dependencies. + * @param libraries the collection of libraries which have already been + * configured + * @exception ConfigException if the library cannot be configured. + */ + private void configLibrary(InitConfig initConfig, Map librarySpecs, + String libraryId, + CircularDependencyChecker configuring, + Map libraries) + throws ConfigException { + + try { + configuring.visitNode(libraryId); + + AntLibrarySpec librarySpec + = (AntLibrarySpec)librarySpecs.get(libraryId); + String extendsId = librarySpec.getExtendsLibraryId(); + if (extendsId != null) { + if (!libraries.containsKey(extendsId)) { + if (!librarySpecs.containsKey(extendsId)) { + throw new ConfigException("Could not find library, " + + extendsId + ", upon which library " + + libraryId + " depends"); + } + configLibrary(initConfig, librarySpecs, extendsId, + configuring, libraries); + } + } + + // now create the library for the specification + AntLibrary antLibrary = new AntLibrary(librarySpec); + + // determine the URLs required for this task. These are the + // task URL itself, the XML parser URLs if required, the + // tools jar URL if required + List urlsList = new ArrayList(); + + if (librarySpec.getLibraryURL() != null) { + urlsList.add(librarySpec.getLibraryURL()); + } + if (librarySpec.isToolsJarRequired() + && initConfig.getToolsJarURL() != null) { + urlsList.add(initConfig.getToolsJarURL()); + } + + URL[] parserURLs = initConfig.getParserURLs(); + if (librarySpec.usesAntXML()) { + for (int i = 0; i < parserURLs.length; ++i) { + urlsList.add(parserURLs[i]); + } + } + + for (Iterator i = urlsList.iterator(); i.hasNext(); ) { + antLibrary.addLibraryURL((URL)i.next()); + } + if (extendsId != null) { + AntLibrary extendsLibrary + = (AntLibrary)libraries.get(extendsId); + antLibrary.setExtendsLibrary(extendsLibrary); + } + antLibrary.setParentLoader(initConfig.getCommonLoader()); + libraries.put(libraryId, antLibrary); + configuring.leaveNode(libraryId); + } catch (CircularDependencyException e) { + throw new ConfigException(e); + } + } + + /** + * Read an Ant library definition from a URL + * + * @param antlibURL the URL of the library definition + * @return the AntLibrary specification read from the library XML + * definition + * @exception XMLParseException if the library cannot be parsed + */ + private AntLibrarySpec parseLibraryDef(URL antlibURL) + throws XMLParseException { + ParseContext context = new ParseContext(); + AntLibHandler libHandler = new AntLibHandler(); + + context.parse(antlibURL, "antlib", libHandler); + + return libHandler.getAntLibrarySpec(); + } + +} + diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrary.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrary.java index 1c742a905..bee388aff 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrary.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrary.java @@ -58,6 +58,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; +import org.apache.ant.common.antlib.AntLibFactory; +import org.apache.ant.common.util.ExecutionException; /** * This class represents the Ant library. @@ -77,6 +79,10 @@ public class AntLibrary { * This name is used when importing tasks from this library */ private String libraryId; + + /** THe URL of the antlib.xml library spec which defines this library */ + private URL definitionURL; + /** * The URLs to use when contructing a classloader for the components in * this library. @@ -86,6 +92,9 @@ public class AntLibrary { /** The list of converter classnames defined in this library */ private List converterClassNames = new ArrayList(); + /** The class name of this library's factory class, if any */ + private String factoryClassName; + /** The parent classloader to use when contructing classloaders */ private ClassLoader parentLoader; @@ -110,7 +119,9 @@ public class AntLibrary { this.libraryId = spec.getLibraryId(); this.definitions = spec.getDefinitions(); this.isolated = spec.isIsolated(); - this.converterClassNames.addAll(spec.getConverterClassNames()); + this.converterClassNames.addAll(spec.getConverters()); + this.factoryClassName = spec.getFactory(); + this.definitionURL = spec.getLibraryURL(); } /** @@ -172,6 +183,54 @@ public class AntLibrary { return converterClassNames.iterator(); } + /** + * Get the URL to where the library was loaded from + * + * @return the library's URL + */ + public URL getDefinitionURL() { + return definitionURL; + } + + + /** + * Gat an instance of a factory object for creating objects in this + * library. + * + * @return an instance of the factory, or null if this library does not + * support a factory + * @exception ExecutionException if the factory cannot be created + */ + public AntLibFactory getFactory() throws ExecutionException { + try { + AntLibFactory libFactory = null; + if (factoryClassName != null) { + Class factoryClass = Class.forName(factoryClassName, + true, getClassLoader()); + libFactory + = (AntLibFactory)factoryClass.newInstance(); + } + return libFactory; + } catch (ClassNotFoundException e) { + throw new ExecutionException("Unable to create factory " + + factoryClassName + " for the \"" + libraryId + + "\" Ant library", e); + } catch (NoClassDefFoundError e) { + throw new ExecutionException("Could not load a dependent class (" + + e.getMessage() + ") to create the factory " + + factoryClassName + " for the \"" + libraryId + + "\" Ant library", e); + } catch (InstantiationException e) { + throw new ExecutionException("Unable to instantiate factory " + + factoryClassName + " for the \"" + libraryId + + "\" Ant library", e); + } catch (IllegalAccessException e) { + throw new ExecutionException("Unable to access factory " + + factoryClassName + " for the \"" + libraryId + + "\" Ant library", e); + } + } + /** * Indicate whether this library has any converters defined * @@ -190,6 +249,7 @@ public class AntLibrary { libraryURLs.add(libraryURL); } + /** * Create classloader which can be used to load the classes of this ant * library diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrarySpec.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrarySpec.java index da8afdb5b..f5e8acc4c 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrarySpec.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/AntLibrarySpec.java @@ -53,10 +53,10 @@ */ package org.apache.ant.antcore.antlib; import java.net.URL; +import java.util.ArrayList; import java.util.HashMap; -import java.util.Map; import java.util.List; -import java.util.ArrayList; +import java.util.Map; import org.apache.ant.antcore.util.ConfigException; /** @@ -85,6 +85,9 @@ public class AntLibrarySpec { /** The list of converter classnames defined in this library */ private List converterClassNames = new ArrayList(); + /** The name of the factory class for this library */ + private String factoryClassName; + /** * This is the optional id of another Ant library upon which this * library depends. @@ -103,6 +106,9 @@ public class AntLibrarySpec { /** Flag which indicates if tools.jar is required */ private boolean toolsJarRequired = false; + /** Flag which indicates that this library is a system library */ + private boolean systemLibrary = false; + /** * This flag indicates that this task processes XML and wishes to use * the XML parser packaged with Ant @@ -118,6 +124,15 @@ public class AntLibrarySpec { this.extendsLibraryId = extendsLibraryId; } + /** + * Sets the name of the factory class of the AntLibrarySpec + * + * @param className the new factory classname + */ + public void setFactory(String className) { + this.factoryClassName = className; + } + /** * Indicate that this library requires a separate classloader per task * instance @@ -156,7 +171,6 @@ public class AntLibrarySpec { this.toolsJarRequired = toolsJarRequired; } - /** * Sets the libraryURL of the AntLibrary * @@ -181,10 +195,19 @@ public class AntLibrarySpec { * * @return the converter classnames list */ - public List getConverterClassNames() { + public List getConverters() { return converterClassNames; } + /** + * Gets the factory classname of the AntLibrarySpec + * + * @return the factory classname + */ + public String getFactory() { + return factoryClassName; + } + /** * Indicate whether this AntLibrary requires the Sun tools.jar * @@ -288,5 +311,6 @@ public class AntLibrarySpec { definitions.put(name, new AntLibDefinition(definitionType, name, classname)); } + } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/ConverterHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/ClassNameHandler.java old mode 100755 new mode 100644 similarity index 97% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/ConverterHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/ClassNameHandler.java index 5b4e5abb9..868b96964 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/ConverterHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/antlib/ClassNameHandler.java @@ -57,11 +57,11 @@ import org.apache.ant.antcore.xml.ElementHandler; import org.xml.sax.SAXParseException; /** - * Handler for converter definition within an Ant Library + * Handler for elements which specify a class * * @author Conor MacNeill */ -public class ConverterHandler extends ElementHandler { +public class ClassNameHandler extends ElementHandler { /** The classname attribute name */ public final static String CLASSNAME_ATTR = "classname"; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfig.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfig.java index 5e877fc21..4c6aa4613 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfig.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfig.java @@ -60,8 +60,8 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.ant.common.util.PathTokenizer; import org.apache.ant.antcore.util.ConfigException; +import org.apache.ant.common.util.PathTokenizer; import org.apache.ant.init.InitUtils; /** @@ -73,7 +73,7 @@ import org.apache.ant.init.InitUtils; */ public class AntConfig { /** The list of additional directories to be searched for Ant libraries */ - private List taskDirLocations = new ArrayList(); + private List libraryLocations = new ArrayList(); /** * A list of additional paths for each ant library, indexed on the @@ -81,13 +81,37 @@ public class AntConfig { */ private Map libPaths = new HashMap(); + /** Indicates if remote libraries may be used */ + private boolean allowRemoteLibs = false; + + /** Indicates if remote projects may be used */ + private boolean allowRemoteProjects = false; + + /** + * Indicate if the use of remote library's is allowe dby this config. + * + * @return true if this config allows the use of remote libraries, + */ + public boolean isRemoteLibAllowed() { + return allowRemoteLibs; + } + + /** + * Indicate if this config allows the execution of a remote project + * + * @return true if remote projects are allowed + */ + public boolean isRemoteProjectAllowed() { + return allowRemoteProjects; + } + /** - * Get the task dir locations. + * Get the additional locations in which to search for Ant Libraries * - * @return an iterator over the task dir locations + * @return an iterator over the library locations */ - public Iterator getTaskDirLocations() { - return taskDirLocations.iterator(); + public Iterator getLibraryLocations() { + return libraryLocations.iterator(); } /** @@ -169,10 +193,10 @@ public class AntConfig { */ public void merge(AntConfig otherConfig) { // merge by - List currentTaskDirs = taskDirLocations; - taskDirLocations = new ArrayList(); - taskDirLocations.addAll(otherConfig.taskDirLocations); - taskDirLocations.addAll(currentTaskDirs); + List currentLibraryLocations = libraryLocations; + libraryLocations = new ArrayList(); + libraryLocations.addAll(otherConfig.libraryLocations); + libraryLocations.addAll(currentLibraryLocations); Iterator i = otherConfig.libPaths.keySet().iterator(); while (i.hasNext()) { @@ -188,11 +212,11 @@ public class AntConfig { /** * Add a new task directory to be searched for additional Ant libraries * - * @param taskDirLocation the location (can be a file or a URL) where + * @param libraryLocation the location (can be a file or a URL) where * the libraries may be loaded from. */ - public void addTaskDir(String taskDirLocation) { - taskDirLocations.add(taskDirLocation); + public void addAntLibraryLocation(String libraryLocation) { + libraryLocations.add(libraryLocation); } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfigHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfigHandler.java index 6b8c12afe..f1b7e2545 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfigHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/AntConfigHandler.java @@ -105,13 +105,13 @@ public class AntConfigHandler extends ElementHandler { throws SAXParseException { try { - if (qualifiedName.equals("taskdir")) { - TaskDirHandler taskDirHandler - = new TaskDirHandler(); - taskDirHandler.start(getParseContext(), getXMLReader(), + if (qualifiedName.equals("loadlib")) { + LoadLibHandler loadlibHandler + = new LoadLibHandler(); + loadlibHandler.start(getParseContext(), getXMLReader(), this, getLocator(), attributes, getElementSource(), qualifiedName); - config.addTaskDir(taskDirHandler.getTaskDirLocation()); + config.addAntLibraryLocation(loadlibHandler.getLibLocation()); } else if (qualifiedName.equals("libpath")) { LibPathHandler libPathHandler = new LibPathHandler(); diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/TaskDirHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/LoadLibHandler.java old mode 100755 new mode 100644 similarity index 95% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/TaskDirHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/LoadLibHandler.java index 827a88513..3d3f5ff13 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/TaskDirHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/config/LoadLibHandler.java @@ -57,12 +57,12 @@ import org.apache.ant.antcore.xml.ElementHandler; import org.xml.sax.SAXParseException; /** - * An XML handler to handle the taskdir element of an AntConfig file. + * An XML handler to handle the loadlib element of an AntConfig file. * * @author Conor MacNeill * @created 20 January 2002 */ -public class TaskDirHandler extends ElementHandler { +public class LoadLibHandler extends ElementHandler { /** The location attribute name */ public final static String LOCATION_ATTR = "location"; @@ -71,12 +71,12 @@ public class TaskDirHandler extends ElementHandler { * * @return the additional directory to be searched for Ant libraries. */ - public String getTaskDirLocation() { + public String getLibLocation() { return getAttribute(LOCATION_ATTR); } /** - * Process the taskdir element + * Process the loadlibs element * * @param elementName the name of the element * @exception SAXParseException if there is a problem parsing the diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEventSupport.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java old mode 100755 new mode 100644 similarity index 97% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEventSupport.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java index a5d6d55c2..4e0a02ee6 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEventSupport.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java @@ -51,12 +51,14 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.event; +package org.apache.ant.antcore.execution; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.ant.antcore.model.ModelElement; +import org.apache.ant.common.event.BuildListener; +import org.apache.ant.common.event.BuildEvent; /** * BuildEventSupport is used by classes which which to send build events to diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ClassIntrospector.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ClassIntrospector.java index 2a402225c..9b1ad68a9 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ClassIntrospector.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ClassIntrospector.java @@ -103,6 +103,12 @@ public class ClassIntrospector { && !args[0].isArray() && !args[0].isPrimitive()) { reflector.addElementMethod(m, getPropertyName(name, "add")); + } else if (name.startsWith("create") + && name.length() > 6 + && !returnType.isArray() + && !returnType.isPrimitive() + && args.length == 0) { + reflector.addCreateMethod(m, getPropertyName(name, "create")); } } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionComponentService.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionComponentService.java new file mode 100644 index 000000000..14b0d9db8 --- /dev/null +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionComponentService.java @@ -0,0 +1,123 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antcore.execution; +import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.apache.ant.antcore.antlib.AntLibManager; +import org.apache.ant.antcore.util.ConfigException; +import org.apache.ant.common.service.ComponentService; +import org.apache.ant.common.util.ExecutionException; + +/** + * The instance of the ComponentServices made available by the core to the + * ant libraries. + * + * @author Conor MacNeill + * @created 27 January 2002 + */ +public class ExecutionComponentService implements ComponentService { + /** The ExecutionFrame this service instance is working for */ + private ExecutionFrame frame; + + /** The library manager instance used to configure libraries. */ + private AntLibManager libManager; + + /** + * Constructor + * + * @param executionFrame the frame containing this context + * @param allowRemoteLibs true if remote libraries can be loaded though + * this service. + */ + public ExecutionComponentService(ExecutionFrame executionFrame, + boolean allowRemoteLibs) { + this.frame = executionFrame; + libManager = new AntLibManager(allowRemoteLibs); + } + + /** + * Load a library or set of libraries from a location making them + * available for use + * + * @param libLocation the file or URL of the library location + * @param importAll if true all tasks are imported as the library is + * loaded + * @exception ExecutionException if the library cannot be loaded + */ + public void loadLib(String libLocation, boolean importAll) + throws ExecutionException { + try { + Map librarySpecs = new HashMap(); + libManager.loadLib(librarySpecs, libLocation); + libManager.configLibraries(frame.getInitConfig(), librarySpecs, + frame.getAntLibraries()); + + if (importAll) { + Iterator i = librarySpecs.keySet().iterator(); + while (i.hasNext()) { + String libraryId = (String)i.next(); + frame.importLibrary(libraryId); + } + } + } catch (MalformedURLException e) { + throw new ExecutionException("Unable to load libraries from " + + libLocation, e); + } catch (ConfigException e) { + throw new ExecutionException(e); + } + } +} + diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java index 9ac6b29bf..6e4c75573 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java @@ -53,12 +53,11 @@ */ package org.apache.ant.antcore.execution; import java.io.File; -import java.net.URL; -import org.apache.ant.common.context.AntContext; -import org.apache.ant.common.util.AntException; -import org.apache.ant.common.util.FileUtils; -import org.apache.ant.antcore.event.BuildEventSupport; import org.apache.ant.antcore.model.ModelElement; +import org.apache.ant.common.antlib.AntContext; +import org.apache.ant.common.util.ExecutionException; +import org.apache.ant.common.util.FileUtils; +import org.apache.ant.common.util.Location; /** * This is the core's implementation of the AntContext for all core objects. @@ -67,9 +66,10 @@ import org.apache.ant.antcore.model.ModelElement; * @author Conor MacNeill * @created 20 January 2002 */ -public class ExecutionContext extends AntContext { +public class ExecutionContext implements AntContext { /** The ExecutionFrame containing this context */ - private ExecutionFrame executionFrame; + private ExecutionFrame frame; + /** the event support instance used to manage build events */ private BuildEventSupport eventSupport; @@ -79,6 +79,19 @@ public class ExecutionContext extends AntContext { /** General file utilities */ private FileUtils fileUtils = new FileUtils(); + /** + * Initilaise this context's environment + * + * @param frame the frame containing this context + * @param eventSupport the event support instance used to send build + * events + */ + public ExecutionContext(ExecutionFrame frame, + BuildEventSupport eventSupport) { + this.frame = frame; + this.eventSupport = eventSupport; + } + /** * Set the model element associated with this context * @@ -89,46 +102,52 @@ public class ExecutionContext extends AntContext { } /** - * Initilaise this context's environment + * Get an implementation of one of the core's service interfaces * - * @param executionFrame the frame containing this context - * @param eventSupport the event support instance used to send build - * events + * @param serviceInterfaceClass the interface class for which an + * implementation is required + * @return the core's implementation of the interface. + * @exception ExecutionException if there is a problem finding the + * interface */ - public void initEnvironment(ExecutionFrame executionFrame, - BuildEventSupport eventSupport) { - this.executionFrame = executionFrame; - this.eventSupport = eventSupport; + public Object getCoreService(Class serviceInterfaceClass) + throws ExecutionException { + return frame.getCoreService(serviceInterfaceClass); } /** - * Log a message as a build event + * Get the build fiel location with which this context is associated * - * @param message the message to be logged - * @param level the priority level of the message + * @return the associated location object. */ - public void log(String message, int level) { - eventSupport.fireMessageLogged(modelElement, message, level); + public Location getLocation() { + if (modelElement != null) { + return modelElement.getLocation(); + } + return Location.UNKNOWN_LOCATION; } /** - * Resolve a file according to the base directory of the project - * associated with this context + * Get the base directory for this execution of this frame * - * @param fileName the file name to be resolved. - * @return the file resolved to the project's base dir - * @exception AntException if the file cannot be resolved + * @return the base directory */ - public File resolveFile(String fileName) throws AntException { - URL baseURL = executionFrame.getBaseURL(); - if (!baseURL.getProtocol().equals("file")) { - throw new ExecutionException("Cannot resolve name " + fileName - + " to a file because the project basedir is not a file: " - + baseURL); - } + public File getBaseDir() { + return frame.getBaseDir(); + } - return fileUtils.resolveFile(fileUtils.normalize(baseURL.getFile()), - fileName); + /** + * Log a message as a build event + * + * @param message the message to be logged + * @param level the priority level of the message + */ + public void log(String message, int level) { + ModelElement source = modelElement; + if (modelElement == null) { + source = frame.getProject(); + } + eventSupport.fireMessageLogged(source, message, level); } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionDataService.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionDataService.java new file mode 100644 index 000000000..9bd323952 --- /dev/null +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionDataService.java @@ -0,0 +1,212 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antcore.execution; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.apache.ant.common.service.DataService; +import org.apache.ant.common.util.ExecutionException; +import org.apache.ant.common.util.PropertyUtils; + +/** + * This is the core's implementation of the DataService service interface. + * It gives Ant libraries access to property values maintained in the + * ExecutionFrame. + * + * @author Conor MacNeill + * @created 31 January 2002 + */ +public class ExecutionDataService implements DataService { + /** The ExecutionFrame this service instance is working for */ + private ExecutionFrame frame; + + /** + * Constructor + * + * @param frame the frame containing this context + */ + public ExecutionDataService(ExecutionFrame frame) { + this.frame = frame; + } + + /** + * Set a data value. If an existing data value exists, associated with + * the given name, the value will not be changed + * + * @param valueName the name of the data value + * @param value the value to be associated with the name + * @exception ExecutionException if the value cannot be set + */ + public void setDataValue(String valueName, Object value) + throws ExecutionException { + frame.setDataValue(valueName, value, false); + } + + /** + * Set a data value which can be overwritten + * + * @param valueName the name of the data value + * @param value the value to be associated with the name + * @exception ExecutionException if the value cannot be set + */ + public void setMutableDataValue(String valueName, Object value) + throws ExecutionException { + frame.setDataValue(valueName, value, true); + } + + /** + * Get a data value + * + * @param valueName the name of the data value + * @return the current object associated with the name or null if no + * value is currently associated with the name + * @exception ExecutionException if the value cannot be retrieved. + */ + public Object getDataValue(String valueName) throws ExecutionException { + return frame.getDataValue(valueName); + } + + /** + * Indicate if a data value has been set + * + * @param name the name of the data value - may contain reference + * delimiters + * @return true if the value exists + * @exception ExecutionException if the containing frame for the value + * does not exist + */ + public boolean isDataValueSet(String name) throws ExecutionException { + return frame.isDataValueSet(name); + } + + /** + * Replace ${} style constructions in the given value with the string + * value of the corresponding data values in the frame + * + * @param value the string to be scanned for property references. + * @return the string with all property references replaced + * @exception ExecutionException if any of the properties do not exist + */ + public String replacePropertyRefs(String value) + throws ExecutionException { + if (value == null) { + return null; + } + + List fragments = new ArrayList(); + List propertyRefs = new ArrayList(); + PropertyUtils.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(); + } + + /** + * Replace ${} style constructions in the given value with the string + * value of the objects in the given map. Any values which are not found + * are left unchanged. + * + * @param value the string to be scanned for property references. + * @param replacementValues the collection of replacement values + * @return the string with all property references replaced + * @exception ExecutionException if any of the properties do not exist + */ + public String replacePropertyRefs(String value, Map replacementValues) + throws ExecutionException { + if (value == null) { + return null; + } + + List fragments = new ArrayList(); + List propertyRefs = new ArrayList(); + PropertyUtils.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 (!replacementValues.containsKey(propertyName)) { + fragment = "${" + propertyName + "}"; + } else { + fragment + = replacementValues.get(propertyName).toString(); + } + } + sb.append(fragment); + } + + return sb.toString(); + } + +} + diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFileService.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFileService.java new file mode 100644 index 000000000..e46503762 --- /dev/null +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFileService.java @@ -0,0 +1,97 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antcore.execution; +import java.io.File; +import org.apache.ant.common.service.FileService; +import org.apache.ant.common.util.ExecutionException; +import org.apache.ant.common.util.FileUtils; + +/** + * The core's implementation of the File Service. The File Service is used + * by Ant Library components to perform operations on the local file system + * + * @author Conor MacNeill + * @created 27 January 2002 + */ +public class ExecutionFileService implements FileService { + /** The ExecutionFrame this service instance is working for */ + private ExecutionFrame executionFrame; + + /** General file utilities */ + private FileUtils fileUtils = new FileUtils(); + + /** + * Constructor + * + * @param executionFrame the frame containing this context + */ + public ExecutionFileService(ExecutionFrame executionFrame) { + this.executionFrame = executionFrame; + } + + /** + * Resolve a file according to the base directory of the project + * associated with this context + * + * @param fileName the file name to be resolved. + * @return the file resolved to the project's base dir + * @exception ExecutionException if the file cannot be resolved. + */ + public File resolveFile(String fileName) throws ExecutionException { + File base = executionFrame.getBaseDir(); + return fileUtils.resolveFile(fileUtils.normalize(base.getPath()), + fileName); + } +} + diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFrame.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFrame.java index c0d029a32..9bfc072a3 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFrame.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionFrame.java @@ -52,28 +52,35 @@ * . */ package org.apache.ant.antcore.execution; -import java.net.MalformedURLException; +import java.io.File; import java.net.URL; -import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; -import org.apache.ant.common.converter.Converter; -import org.apache.ant.common.task.DataType; -import org.apache.ant.common.task.Task; -import org.apache.ant.common.task.TaskContainer; -import org.apache.ant.common.task.TaskException; -import org.apache.ant.common.util.Location; import org.apache.ant.antcore.antlib.AntLibDefinition; import org.apache.ant.antcore.antlib.AntLibrary; -import org.apache.ant.antcore.event.BuildEventSupport; -import org.apache.ant.antcore.event.BuildListener; +import org.apache.ant.antcore.config.AntConfig; import org.apache.ant.antcore.model.BuildElement; import org.apache.ant.antcore.model.Project; import org.apache.ant.antcore.model.Target; import org.apache.ant.antcore.util.ConfigException; +import org.apache.ant.common.antlib.AntLibFactory; +import org.apache.ant.common.antlib.Converter; +import org.apache.ant.common.antlib.ExecutionComponent; +import org.apache.ant.common.antlib.StandardLibFactory; +import org.apache.ant.common.antlib.Task; +import org.apache.ant.common.antlib.TaskContainer; +import org.apache.ant.common.event.BuildListener; +import org.apache.ant.common.service.ComponentService; +import org.apache.ant.common.service.DataService; +import org.apache.ant.common.service.FileService; +import org.apache.ant.common.util.AntException; +import org.apache.ant.common.util.ExecutionException; +import org.apache.ant.common.util.Location; +import org.apache.ant.common.util.MessageLevel; +import org.apache.ant.init.InitConfig; /** * An ExecutionFrame maintains the state of a project during an execution. @@ -143,12 +150,15 @@ public class ExecutionFrame { /** The prefix for library ids that are automatically imported */ public final static String ANT_LIB_PREFIX = "ant."; - /** the base dir of the project expressed as a URL */ - private URL baseURL; + /** the base dir of the project */ + private File baseDir; /** The Project that this execution frame is processing */ private Project project = null; + /** The factory objects for each library, indexed by the library Id */ + private Map libFactories = new HashMap(); + /** The referenced frames corresponding to the referenced projects */ private Map referencedFrames = new HashMap(); @@ -162,8 +172,20 @@ public class ExecutionFrame { private Map dataValues = new HashMap(); /** - * The available libraries from which taskdefs, typedefs, etc may be - * imported + * Ant's initialization configuration with information on the location + * of Ant and its libraries. + */ + private InitConfig initConfig; + + /** + * These are the standard libraries from which taskdefs, typedefs, etc + * may be imported. + */ + private Map standardLibs; + + /** + * These are AntLibraries which have been loaded in this + * ExecutionFrame's build file. */ private Map antLibraries; @@ -179,72 +201,56 @@ public class ExecutionFrame { */ private Map converters = new HashMap(); + /** + * The services map is a map of service interface classes to instances + * which provide the service. + */ + private Map services = new HashMap(); + + /** + * The configuration to be used in this execution of Ant. It is formed + * from the system, user and any runtime configs. + */ + private AntConfig config; + + /** + * The Data Service instance used by the frame for data management + */ + private DataService dataService; + /** * Create an Execution Frame for the given project * - * @param antLibraries The libraries of tasks and types available to + * @param standardLibs The libraries of tasks and types available to * this frame + * @param config the user config to use for this execution of Ant + * @param initConfig Ant's initialisation config * @exception ConfigException if a component of the library cannot be * imported */ - public ExecutionFrame(Map antLibraries) throws ConfigException { - this.antLibraries = antLibraries; - - // go through the libraries and import all standard ant libraries - for (Iterator i = antLibraries.keySet().iterator(); i.hasNext(); ) { - String libraryId = (String)i.next(); - if (libraryId.startsWith(ANT_LIB_PREFIX)) { - // standard library - import whole library - importLibrary(libraryId); - } - } - } + protected ExecutionFrame(Map standardLibs, InitConfig initConfig, + AntConfig config) throws ConfigException { + this.standardLibs = standardLibs; + this.config = config; + this.initConfig = initConfig; - /** - * This method will parse a string containing ${value} style property - * values into two lists. The first list is a collection of text - * fragments, while the other is a set of string property names. Null - * entries in the first list indicate a property reference from the - * second list. - * - * @param value the string to be parsed - * @param fragments the fragments parsed out of the string - * @param propertyRefs the property refs to be replaced - * @exception ExecutionException if there is a problem getting property - * values - */ - public static void parsePropertyString(String value, List fragments, - List propertyRefs) - throws ExecutionException { - int prev = 0; - int pos; - while ((pos = value.indexOf("$", prev)) >= 0) { - if (pos > 0) { - fragments.add(value.substring(prev, pos)); - } + configureServices(); + + antLibraries = new HashMap(standardLibs); - 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); + try { + // go through the libraries and import all standard ant libraries + for (Iterator i = antLibraries.keySet().iterator(); i.hasNext(); ) { + String libraryId = (String)i.next(); + if (libraryId.startsWith(ANT_LIB_PREFIX)) { + // standard library - import whole library + importLibrary(libraryId); } - String propertyName = value.substring(pos + 2, endName); - fragments.add(null); - propertyRefs.add(propertyName); - prev = endName + 1; } + } catch (ExecutionException e) { + throw new ConfigException(e); } - if (prev < value.length()) { - fragments.add(value.substring(prev)); - } } /** @@ -261,6 +267,25 @@ public class ExecutionFrame { return currentLoader; } + /** + * Gets the project model this frame is working with + * + * @return the project model + */ + public Project getProject() { + return project; + } + + /** + * Log a message as a build event + * + * @param message the message to be logged + * @param level the priority level of the message + */ + public void log(String message, int level) { + eventSupport.fireMessageLogged(project, message, level); + } + /** * Sets the Project of the ExecutionFrame * @@ -268,13 +293,18 @@ public class ExecutionFrame { * @exception ConfigException if any required sub-frames cannot be * created and configured */ - public void setProject(Project project) throws ConfigException { - try { - this.project = project; - baseURL = new URL(project.getSourceURL(), project.getBase()); - } catch (MalformedURLException e) { - throw new ConfigException("Unable to determine project base dir", - e, project.getLocation()); + protected void setProject(Project project) throws ConfigException { + this.project = project; + URL projectURL = project.getSourceURL(); + if (projectURL.getProtocol().equals("file")) { + File projectFile = new File(projectURL.getFile()); + String base = project.getBase(); + if (base == null) { + base = "."; + } + baseDir = new File(projectFile.getParentFile(), base); + } else { + baseDir = new File("."); } referencedFrames = new HashMap(); @@ -284,7 +314,7 @@ public class ExecutionFrame { Project referencedProject = project.getReferencedProject(referenceName); ExecutionFrame referencedFrame - = new ExecutionFrame(antLibraries); + = new ExecutionFrame(standardLibs, initConfig, config); referencedFrame.setProject(referencedProject); referencedFrames.put(referenceName, referencedFrame); @@ -296,29 +326,82 @@ public class ExecutionFrame { } /** - * Set a value in this frame or any of its imported frames + * Set a value in this frame or any of its imported frames. * * @param name the name of the value * @param value the actual value + * @param mutable if true, existing values can be changed * @exception ExecutionException if the value name is invalid */ - public void setDataValue(String name, Object value) + protected void setDataValue(String name, Object value, boolean mutable) throws ExecutionException { ExecutionFrame frame = getContainingFrame(name); if (frame == this) { - dataValues.put(name, value); + if (dataValues.containsKey(name) && !mutable) { + log("Ignoring oveeride for data value " + name, + MessageLevel.MSG_VERBOSE); + } else { + dataValues.put(name, value); + } } else { - frame.setDataValue(getNameInFrame(name), value); + frame.setDataValue(getNameInFrame(name), value, mutable); } } /** - * Gets the baseURL of the ExecutionFrame + * Get the collection of Ant Libraries defined for this frame * - * @return the baseURL value + * @return a map of Ant Libraries indexed by thier library Id */ - public URL getBaseURL() { - return baseURL; + protected Map getAntLibraries() { + return antLibraries; + } + + /** + * Get the Ant initialization configuration for this frame. + * + * @return Ant's initialization configuration + */ + protected InitConfig getInitConfig() { + return initConfig; + } + + + /** + * Get the config instance being used by this frame. + * + * @return the config associated with this frame. + */ + protected AntConfig getConfig() { + return config; + } + + /** + * Get the core's implementation of the given service interface. + * + * @param serviceInterfaceClass the service interface for which an + * implementation is require + * @return the core's implementation of the service interface + * @exception ExecutionException if the core does not provide an + * implementatin of the requested interface + */ + protected Object getCoreService(Class serviceInterfaceClass) + throws ExecutionException { + Object service = services.get(serviceInterfaceClass); + if (service == null) { + throw new ExecutionException("No service of interface class " + + serviceInterfaceClass); + } + return service; + } + + /** + * Gets the baseDir of the ExecutionFrame + * + * @return the baseDir value + */ + protected File getBaseDir() { + return baseDir; } /** @@ -328,7 +411,7 @@ public class ExecutionFrame { * @return the ExecutionFrame asscociated with the given reference name * or null if there is no such project. */ - public ExecutionFrame getReferencedFrame(String referenceName) { + protected ExecutionFrame getReferencedFrame(String referenceName) { return (ExecutionFrame)referencedFrames.get(referenceName); } @@ -337,7 +420,7 @@ public class ExecutionFrame { * * @return an iterator which returns the referenced ExeuctionFrames.. */ - public Iterator getReferencedFrames() { + protected Iterator getReferencedFrames() { return referencedFrames.values().iterator(); } @@ -347,7 +430,7 @@ public class ExecutionFrame { * @param fullname The name of the object * @return the name of the object within its containing frame */ - public String getNameInFrame(String fullname) { + protected String getNameInFrame(String fullname) { int index = fullname.lastIndexOf(Project.REF_DELIMITER); if (index == -1) { return fullname; @@ -363,7 +446,7 @@ public class ExecutionFrame { * @return the data value fetched from the appropriate frame * @exception ExecutionException if the value is not defined */ - public Object getDataValue(String name) throws ExecutionException { + protected Object getDataValue(String name) throws ExecutionException { ExecutionFrame frame = getContainingFrame(name); if (frame == this) { return dataValues.get(name); @@ -381,9 +464,9 @@ public class ExecutionFrame { * @exception ExecutionException if the containing frame for the value * does not exist */ - public boolean isDataValueSet(String name) throws ExecutionException { + protected boolean isDataValueSet(String name) throws ExecutionException { ExecutionFrame frame = getContainingFrame(name); - if (frame == null) { + if (frame == this) { return dataValues.containsKey(name); } else { return frame.isDataValueSet(getNameInFrame(name)); @@ -395,7 +478,7 @@ public class ExecutionFrame { * * @param listener the listener to be added to the frame */ - public void addBuildListener(BuildListener listener) { + protected void addBuildListener(BuildListener listener) { for (Iterator i = getReferencedFrames(); i.hasNext(); ) { ExecutionFrame referencedFrame = (ExecutionFrame)i.next(); referencedFrame.addBuildListener(listener); @@ -408,7 +491,7 @@ public class ExecutionFrame { * * @param listener the listener to be removed */ - public void removeBuildListener(BuildListener listener) { + protected void removeBuildListener(BuildListener listener) { for (Iterator i = getReferencedFrames(); i.hasNext(); ) { ExecutionFrame subFrame = (ExecutionFrame)i.next(); subFrame.removeBuildListener(listener); @@ -422,17 +505,23 @@ public class ExecutionFrame { * @param targets a list of target names which are to be evaluated * @exception ExecutionException if there is a problem in the build */ - public void runBuild(List targets) throws ExecutionException { + protected void runBuild(List targets) throws ExecutionException { + System.out.println("Initilizing frame"); initialize(); + log("Initialized", MessageLevel.MSG_DEBUG); if (targets.isEmpty()) { // we just execute the default target if any String defaultTarget = project.getDefaultTarget(); if (defaultTarget != null) { + log("Executing default target: " + defaultTarget, + MessageLevel.MSG_DEBUG); executeTarget(defaultTarget); } } else { for (Iterator i = targets.iterator(); i.hasNext(); ) { - executeTarget((String)i.next()); + String targetName = (String)i.next(); + log("Executing target: " + targetName, MessageLevel.MSG_DEBUG); + executeTarget(targetName); } } } @@ -445,7 +534,7 @@ public class ExecutionFrame { * @exception ExecutionException if there is a problem executing the * tasks of the target */ - public void executeTarget(String targetName) throws ExecutionException { + protected void executeTarget(String targetName) throws ExecutionException { // to execute a target we must determine its dependencies and // execute them in order. @@ -470,7 +559,8 @@ public class ExecutionFrame { * @exception ExecutionException if there is execution problem while * executing tasks */ - public void executeTasks(Iterator taskIterator) throws ExecutionException { + protected void executeTasks(Iterator taskIterator) + throws ExecutionException { while (taskIterator.hasNext()) { Throwable failureCause = null; BuildElement model = (BuildElement)taskIterator.next(); @@ -478,8 +568,8 @@ public class ExecutionFrame { ImportInfo importInfo = (ImportInfo)definitions.get(model.getType()); if (importInfo == null) { - throw new ExecutionException("There is no definition for the " - + model.getType() + " element", model.getLocation()); + throw new ExecutionException("There is no definition for the <" + + model.getType() + "> element", model.getLocation()); } try { @@ -491,17 +581,16 @@ public class ExecutionFrame { = setContextLoader(taskContext.getLoader()); taskContext.execute(); setContextLoader(currentLoader); - releaseTaskContext(taskContext); + taskContext.destroy(); } else { // typedef String typeId = model.getAspectValue(ANT_ASPECT, "id"); Object typeInstance = configureType(model.getType(), model); if (typeId != null) { - setDataValue(typeId, typeInstance); + setDataValue(typeId, typeInstance, true); } } - - } catch (TaskException te) { + } catch (AntException te) { ExecutionException e = new ExecutionException(te, te.getLocation()); if (e.getLocation() == null @@ -528,7 +617,7 @@ public class ExecutionFrame { * be executed. * @exception ExecutionException if there is a problem executing tasks */ - public void executeTargetTasks(String targetName) + protected void executeTargetTasks(String targetName) throws ExecutionException { Throwable failureCause = null; Target target = project.getTarget(targetName); @@ -537,10 +626,12 @@ public class ExecutionFrame { eventSupport.fireTargetStarted(target); executeTasks(taskIterator); } catch (ExecutionException e) { + System.out.println("Exception location is " + e.getLocation()); if (e.getLocation() == null || e.getLocation() == Location.UNKNOWN_LOCATION) { e.setLocation(target.getLocation()); } + System.out.println("Exception location is now " + e.getLocation()); failureCause = e; throw e; } catch (RuntimeException e) { @@ -558,49 +649,36 @@ public class ExecutionFrame { * @exception ExecutionException if the top level tasks of the frame * failed */ - public void initialize() throws ExecutionException { + protected void initialize() throws ExecutionException { for (Iterator i = getReferencedFrames(); i.hasNext(); ) { ExecutionFrame referencedFrame = (ExecutionFrame)i.next(); referencedFrame.initialize(); } -// Iterator taskIterator = project.getTasks(); -// executeTopLevelTasks(taskIterator); + Iterator taskIterator = project.getTasks(); + executeTasks(taskIterator); } + /** - * Replace ${} style constructions in the given value with the string - * value of the corresponding data types. + * Import a complete library into this frame * - * @param value the string to be scanned for property references. - * @return the string with all property references replaced - * @exception ExecutionException if any of the properties do not exist + * @param libraryId The id of the library to be imported + * @exception ExecutionException if the library cannot be imported */ - public String replacePropertyRefs(String value) throws ExecutionException { - if (value == null) { - return null; + protected void importLibrary(String libraryId) throws ExecutionException { + AntLibrary library = (AntLibrary)antLibraries.get(libraryId); + if (library == null) { + throw new ExecutionException("Unable to import library " + libraryId + + " as it has not been loaded"); } - - 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); + Map libDefs = library.getDefinitions(); + for (Iterator i = libDefs.keySet().iterator(); i.hasNext(); ) { + String defName = (String)i.next(); + AntLibDefinition libdef + = (AntLibDefinition)libDefs.get(defName); + definitions.put(defName, new ImportInfo(library, libdef)); } - - return sb.toString(); + addLibraryConverters(library); } /** @@ -649,35 +727,75 @@ public class ExecutionFrame { return currentFrame; } + /** + * Gets the factory object for the given library + * + * @param antLibrary the library for which the factory instance is + * required. + * @return the library;s factory object + * @exception ExecutionException the factory object for the library + * cannot be created. + */ + private AntLibFactory getLibFactory(AntLibrary antLibrary) + throws ExecutionException { + String libraryId = antLibrary.getLibraryId(); + if (libFactories.containsKey(libraryId)) { + return (AntLibFactory)libFactories.get(libraryId); + } + AntLibFactory libFactory = antLibrary.getFactory(); + if (libFactory == null) { + libFactory = new StandardLibFactory(); + } + libFactories.put(libraryId, libFactory); + libFactory.init(new ExecutionContext(this, eventSupport)); + return libFactory; + } + + /** + * Configure the services that the frame makes available to its library + * components + */ + private void configureServices() { + // create services and make them available in our services map + services.put(FileService.class, new ExecutionFileService(this)); + services.put(ComponentService.class, + new ExecutionComponentService(this, config.isRemoteLibAllowed())); + dataService = new ExecutionDataService(this); + services.put(DataService.class, dataService); + } + /** * Add the converters from the given library to those managed by this * frame. * * @param library the library from which the converters are required - * @exception ConfigException if a converter defined in the library + * @exception ExecutionException if a converter defined in the library * cannot be instantiated */ private void addLibraryConverters(AntLibrary library) - throws ConfigException { + throws ExecutionException { if (!library.hasConverters()) { return; } String className = null; try { + AntLibFactory libFactory = getLibFactory(library); ClassLoader converterLoader = library.getClassLoader(); for (Iterator i = library.getConverterClassNames(); i.hasNext(); ) { className = (String)i.next(); Class converterClass = Class.forName(className, true, converterLoader); if (!Converter.class.isAssignableFrom(converterClass)) { - throw new ConfigException("The converter class " + throw new ExecutionException("In Ant library \"" + + library.getLibraryId() + "\" the converter class " + converterClass.getName() + " does not implement the Converter interface"); } - Converter converter = (Converter)converterClass.newInstance(); - ExecutionContext context = new ExecutionContext(); - context.initEnvironment(this, eventSupport); + Converter converter + = libFactory.createConverter(converterClass); + ExecutionContext context + = new ExecutionContext(this, eventSupport); converter.init(context); Class[] converterTypes = converter.getTypes(); for (int j = 0; j < converterTypes.length; ++j) { @@ -685,16 +803,23 @@ public class ExecutionFrame { } } } catch (ClassNotFoundException e) { - throw new ConfigException("Converter Class " + className - + " was not found", e); + throw new ExecutionException("In Ant library \"" + + library.getLibraryId() + "\" converter class " + + className + " was not found", e); } catch (NoClassDefFoundError e) { - throw new ConfigException("Could not load a dependent class (" + throw new ExecutionException("In Ant library \"" + + library.getLibraryId() + + "\" could not load a dependent class (" + e.getMessage() + ") for converter " + className); } catch (InstantiationException e) { - throw new ConfigException("Unable to instantiate converter class " + throw new ExecutionException("In Ant library \"" + + library.getLibraryId() + + "\" unable to instantiate converter class " + className, e); } catch (IllegalAccessException e) { - throw new ConfigException("Unable to access converter class " + throw new ExecutionException("In Ant library \"" + + library.getLibraryId() + + "\" unable to access converter class " + className, e); } } @@ -705,10 +830,9 @@ public class ExecutionFrame { * @param element the object to be configured * @param model the BuildElement describing the object in the build file * @exception ExecutionException if the element cannot be configured - * @exception TaskException if a nested task has a problem */ private void configureElement(Object element, BuildElement model) - throws ExecutionException, TaskException { + throws ExecutionException { Reflector reflector = getReflector(element.getClass()); @@ -716,12 +840,22 @@ public class ExecutionFrame { for (Iterator i = model.getAttributeNames(); i.hasNext(); ) { String attributeName = (String)i.next(); String attributeValue = model.getAttributeValue(attributeName); + if (!reflector.supportsAttribute(attributeName)) { + throw new ExecutionException(model.getType() + + " does not support the \"" + attributeName + + "\" attribute", model.getLocation()); + } reflector.setAttribute(element, attributeName, - replacePropertyRefs(attributeValue)); + dataService.replacePropertyRefs(attributeValue)); } String modelText = model.getText().trim(); if (modelText.length() != 0) { - reflector.addText(element, replacePropertyRefs(modelText)); + if (!reflector.supportsText()) { + throw new ExecutionException(model.getType() + + " does not support content", model.getLocation()); + } + reflector.addText(element, + dataService.replacePropertyRefs(modelText)); } // now do the nested elements @@ -742,34 +876,71 @@ public class ExecutionFrame { // method of executing tasks container.addTask(nestedContext.getTask()); } else { - Object nestedElement = createNestedElement(reflector, element, - nestedElementModel); - reflector.addElement(element, nestedElementName, nestedElement); + if (reflector.supportsNestedAdder(nestedElementName)) { + addNestedElement(reflector, element, nestedElementModel); + } else if (reflector.supportsNestedCreator(nestedElementName)) { + createNestedElement(reflector, element, nestedElementModel); + } else { + throw new ExecutionException(model.getType() + + " does not support the \"" + nestedElementName + + "\" nested element", + nestedElementModel.getLocation()); + } } } + + } + + /** + * Create a nested element for the given object according to the model. + * + * @param reflector the reflector instance of the container object + * @param element the container object for which a nested element is + * required. + * @param model the build model for the nestd element + * @exception ExecutionException if the nested element cannot be + * created. + */ + private void createNestedElement(Reflector reflector, Object element, + BuildElement model) + throws ExecutionException { + log("The use of create methods is deprecated - class: " + + element.getClass().getName(), MessageLevel.MSG_INFO); + + String nestedElementName = model.getType(); + Object nestedElement + = reflector.createElement(element, nestedElementName); + if (nestedElement instanceof ExecutionComponent) { + ExecutionComponent component = (ExecutionComponent)nestedElement; + ExecutionContext context + = new ExecutionContext(this, eventSupport); + context.setModelElement(model); + component.init(context); + } + + try { + configureElement(nestedElement, model); + } catch (ExecutionException e) { + e.setLocation(model.getLocation()); + throw e; + } } + /** - * Create a nested element + * Create and add a nested element * * @param reflector The reflector instance for the container element * @param element the container element in which the nested element will * be created * @param model the model of the nested element - * @return a configured nested element * @exception ExecutionException if the nested element cannot be created - * @exception TaskException if the nested element has a problem */ - private Object createNestedElement(Reflector reflector, Object element, - BuildElement model) - throws ExecutionException, TaskException { + private void addNestedElement(Reflector reflector, Object element, + BuildElement model) + throws ExecutionException { String nestedElementName = model.getType(); - if (!reflector.supportsNestedElement(nestedElementName)) { - throw new ExecutionException("The element name " + nestedElementName - + " is not a supported nested element of " - + element.getClass().getName()); - } Class nestedType = reflector.getType(nestedElementName); // is there a polymorph indicator - look in Ant aspects @@ -800,8 +971,8 @@ public class ExecutionFrame { model.getLocation()); } if (typeInstance == null) { - throw new ExecutionException("The given ant:refid value '" - + refId + "' is not defined", model.getLocation()); + throw new ExecutionException("The given ant:refid value '" + + refId + "' is not defined", model.getLocation()); } } else { // We need to create an instance of the class expected by the nested @@ -813,7 +984,7 @@ public class ExecutionFrame { model.getLocation()); } - typeInstance = createTypeInstance(nestedType, model); + typeInstance = createTypeInstance(nestedType, null, model); } // is the typeInstance compatible with the type expected @@ -831,7 +1002,7 @@ public class ExecutionFrame { model.getLocation()); } } - return typeInstance; + reflector.addElement(element, nestedElementName, typeInstance); } @@ -842,10 +1013,9 @@ public class ExecutionFrame { * @return an execution context for managing the task * @exception ExecutionException if there is a problem configuring the * task - * @exception TaskException if the task or a nested task has a problem */ private TaskContext configureTask(BuildElement model) - throws ExecutionException, TaskException { + throws ExecutionException { String taskType = model.getType(); ImportInfo taskDefInfo = (ImportInfo)definitions.get(taskType); @@ -862,7 +1032,9 @@ public class ExecutionFrame { ClassLoader taskClassLoader = antLibrary.getClassLoader(); Class elementClass = Class.forName(className, true, taskClassLoader); - Object element = elementClass.newInstance(); + AntLibFactory libFactory = getLibFactory(antLibrary); + Object element = libFactory.createTaskInstance(elementClass); + Task task = null; if (element instanceof Task) { // create a Task context for the Task @@ -873,7 +1045,7 @@ public class ExecutionFrame { // set the context loader while configuring the element ClassLoader currentLoader = setContextLoader(taskClassLoader); - TaskContext taskContext = allocateTaskContext(); + TaskContext taskContext = new TaskContext(this, eventSupport); taskContext.init(taskClassLoader, task, model); configureElement(element, model); setContextLoader(currentLoader); @@ -884,7 +1056,8 @@ public class ExecutionFrame { model.getLocation()); } catch (NoClassDefFoundError e) { throw new ExecutionException("Could not load a dependent class (" - + e.getMessage() + ") for task " + taskType); + + e.getMessage() + ") for task " + taskType, + e, model.getLocation()); } catch (InstantiationException e) { throw new ExecutionException("Unable to instantiate task class " + className + " for task <" + taskType + ">", @@ -893,9 +1066,13 @@ public class ExecutionFrame { throw new ExecutionException("Unable to access task class " + className + " for task <" + taskType + ">", e, model.getLocation()); + } catch (ExecutionException e) { + e.setLocation(model.getLocation()); + throw e; } } + /** * Configure a type instance from the given build model. The name given * may not match the name in the model type value. This allows the @@ -905,10 +1082,9 @@ public class ExecutionFrame { * @param model the model describing the type * @return an instance of the type, configured from the model * @exception ExecutionException if the type could not be created - * @exception TaskException there was a problem within the type */ private Object configureType(String typeName, BuildElement model) - throws ExecutionException, TaskException { + throws ExecutionException { ImportInfo typeDefInfo = (ImportInfo)definitions.get(typeName); if (typeDefInfo == null || typeDefInfo.getDefinitionType() != AntLibrary.TYPEDEF) { @@ -925,7 +1101,9 @@ public class ExecutionFrame { = Class.forName(className, true, typeClassLoader); ClassLoader currentLoader = setContextLoader(typeClassLoader); - Object typeInstance = createTypeInstance(typeClass, model); + AntLibFactory libFactory = getLibFactory(antLibrary); + Object typeInstance + = createTypeInstance(typeClass, libFactory, model); setContextLoader(currentLoader); return typeInstance; @@ -945,22 +1123,30 @@ public class ExecutionFrame { * @param typeClass the class from which the instance should be created * @param model the model describing the required configuration of the * instance + * @param libFactory the factory object of the typeClass's Ant library * @return an instance of the given class appropriately configured * @exception ExecutionException if there is a problem creating the type * instance - * @exception TaskException if there is a problem configuring the type - * instance. */ - private Object createTypeInstance(Class typeClass, BuildElement model) - throws ExecutionException, TaskException { + private Object createTypeInstance(Class typeClass, AntLibFactory libFactory, + BuildElement model) + throws ExecutionException { try { - Object typeInstance = typeClass.newInstance(); - if (typeInstance instanceof DataType) { - DataType dataType = (DataType)typeInstance; - TypeContext typeContext = new TypeContext(); - typeContext.initEnvironment(this, eventSupport); - typeContext.init(dataType, model); + Object typeInstance = null; + if (libFactory == null) { + typeInstance = typeClass.newInstance(); + } else { + typeInstance = libFactory.createTypeInstance(typeClass); + } + + if (typeInstance instanceof ExecutionComponent) { + ExecutionComponent component = (ExecutionComponent)typeInstance; + ExecutionContext context + = new ExecutionContext(this, eventSupport); + context.setModelElement(model); + component.init(context); } + configureElement(typeInstance, model); return typeInstance; } catch (InstantiationException e) { @@ -971,47 +1157,11 @@ public class ExecutionFrame { throw new ExecutionException("Unable to access type class " + typeClass.getName() + " for type <" + model.getType() + ">", e, model.getLocation()); + } catch (ExecutionException e) { + e.setLocation(model.getLocation()); + throw e; } } - - /** - * Allocate a context for use - * - * @return ExecutionContext for use - */ - private TaskContext allocateTaskContext() { - TaskContext context = new TaskContext(); - context.initEnvironment(this, eventSupport); - return context; - } - - /** - * Release a context. Any associated tasks are destroyed. - * - * @param context the cotext to be released - */ - private void releaseTaskContext(TaskContext context) { - context.destroy(); - } - - - /** - * Import a complete library into this frame - * - * @param libraryId The id of the library to be imported - * @exception ConfigException if the library cannot be imported - */ - private void importLibrary(String libraryId) throws ConfigException { - AntLibrary library = (AntLibrary)antLibraries.get(libraryId); - Map libDefs = library.getDefinitions(); - for (Iterator i = libDefs.keySet().iterator(); i.hasNext(); ) { - String defName = (String)i.next(); - AntLibDefinition libdef - = (AntLibDefinition)libDefs.get(defName); - definitions.put(defName, new ImportInfo(library, libdef)); - } - addLibraryConverters(library); - } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java index 18e07a296..8006d01be 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java @@ -52,34 +52,20 @@ * . */ package org.apache.ant.antcore.execution; -import java.io.File; -import java.io.FileNotFoundException; import java.net.MalformedURLException; import java.net.URL; -import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; -import org.apache.ant.common.util.AntException; -import org.apache.ant.antcore.antlib.AntLibHandler; +import org.apache.ant.antcore.antlib.AntLibManager; import org.apache.ant.antcore.antlib.AntLibrary; -import org.apache.ant.antcore.antlib.AntLibrarySpec; import org.apache.ant.antcore.config.AntConfig; -import org.apache.ant.antcore.config.AntConfigHandler; -import org.apache.ant.antcore.event.BuildEventSupport; -import org.apache.ant.antcore.event.BuildListener; import org.apache.ant.antcore.model.Project; -import org.apache.ant.antcore.util.CircularDependencyChecker; -import org.apache.ant.antcore.util.CircularDependencyException; import org.apache.ant.antcore.util.ConfigException; -import org.apache.ant.antcore.xml.ParseContext; -import org.apache.ant.antcore.xml.XMLParseException; -import org.apache.ant.init.InitUtils; +import org.apache.ant.common.event.BuildListener; +import org.apache.ant.common.util.AntException; import org.apache.ant.init.InitConfig; -import org.apache.ant.init.LoaderUtils; /** * The ExecutionManager is used to manage the execution of a build. The @@ -100,70 +86,59 @@ public class ExecutionManager { /** The Execution Frame for the top level project being executed */ private ExecutionFrame mainFrame; + /** + * The configuration to be used in this execution of Ant. It is formed + * from the system, user and any runtime configs. + */ + private AntConfig config; + + /** + * Ant's initialization configuration with information on the location + * of Ant and its libraries. + */ + private InitConfig initConfig; + /** * Create an ExecutionManager. When an ExecutionManager is created, it * loads the ant libraries which are installed in the Ant lib/task * directory. * * @param initConfig Ant's configuration - classloaders etc + * @param config The user config to use - may be null * @exception ConfigException if there is a problem with one of Ant's * tasks */ - public ExecutionManager(InitConfig initConfig) + public ExecutionManager(InitConfig initConfig, AntConfig config) throws ConfigException { - Map librarySpecs = new HashMap(); - - AntConfig userConfig = getAntConfig(initConfig.getUserConfigArea()); - AntConfig systemConfig = getAntConfig(initConfig.getSystemConfigArea()); - - AntConfig config = systemConfig; - if (config == null) { - config = userConfig; - } else if (userConfig != null) { - config.merge(userConfig); - } + this.config = config; + this.initConfig = initConfig; + Map librarySpecs = new HashMap(10); try { // start by loading the task libraries - URL taskBaseURL = new URL(initConfig.getLibraryURL(), "antlibs"); - addAntLibraries(librarySpecs, taskBaseURL); + URL standardLibsURL + = new URL(initConfig.getLibraryURL(), "antlibs/"); - if (config != null) { - // Now add in any found in the dirs specified in - // the config files - for (Iterator i = config.getTaskDirLocations(); i.hasNext(); ) { - // try file first - String taskDirString = (String)i.next(); - File taskDir = new File(taskDirString); - if (!taskDir.exists()) { - URL taskDirURL = new URL(taskDirString); - addAntLibraries(librarySpecs, taskDirURL); - } else { - addAntLibraries(librarySpecs, - InitUtils.getFileURL(taskDir)); - } - } - } + AntLibManager libManager + = new AntLibManager(config.isRemoteLibAllowed()); - configLibraries(initConfig, librarySpecs); + libManager.addAntLibraries(librarySpecs, standardLibsURL); + libManager.configLibraries(initConfig, librarySpecs, antLibraries); + librarySpecs.clear(); + // add any additional libraries. if (config != null) { - // now add any additional library Paths specified by the config - for (Iterator i = config.getLibraryIds(); i.hasNext(); ) { - String libraryId = (String)i.next(); - if (antLibraries.containsKey(libraryId)) { - AntLibrary antLib - = (AntLibrary)antLibraries.get(libraryId); - List pathList = config.getLibraryPathList(libraryId); - for (Iterator j = pathList.iterator(); j.hasNext(); ) { - URL pathElementURL = (URL)j.next(); - antLib.addLibraryURL(pathElementURL); - } - } + for (Iterator i = config.getLibraryLocations(); i.hasNext(); ) { + // try file first + String libLocation = (String)i.next(); + libManager.loadLib(librarySpecs, libLocation); } } + libManager.configLibraries(initConfig, librarySpecs, antLibraries); + + addConfigLibPaths(); - mainFrame = new ExecutionFrame(antLibraries); + mainFrame = new ExecutionFrame(antLibraries, initConfig, config); } catch (MalformedURLException e) { throw new ConfigException("Unable to load Ant libraries", e); } @@ -172,8 +147,8 @@ public class ExecutionManager { /** * Run a build, executing each of the targets on the given project * - * @param project The project model on which to run the build - * @param targets The list of target names + * @param project the project model to be used for the build + * @param targets a list of target names to be executed. */ public void runBuild(Project project, List targets) { Throwable buildFailureCause = null; @@ -215,203 +190,35 @@ public class ExecutionManager { } /** - * Get the AntConfig from the given config area if it is available + * Add the library paths from the AntConfig instance to the Ant + * Libraries. * - * @param configArea the config area from which the config may be read - * @return the AntConfig instance representing the config info read in - * from the config area. May be null if the AntConfig is not - * present - * @exception ConfigException if the URL for the config file cannotbe - * formed. + * @exception ConfigException if remote libraries are not allowed. */ - private AntConfig getAntConfig(URL configArea) throws ConfigException { - try { - URL configFileURL = new URL(configArea, "antconfig.xml"); - - ParseContext context = new ParseContext(); - AntConfigHandler configHandler = new AntConfigHandler(); - - context.parse(configFileURL, "antconfig", configHandler); - - return configHandler.getAntConfig(); - } catch (MalformedURLException e) { - throw new ConfigException("Unable to form URL to read config from " - + configArea, e); - } catch (XMLParseException e) { - if (!(e.getCause() instanceof FileNotFoundException)) { - throw new ConfigException("Unable to parse config file from " - + configArea, e); - } - // ignore missing config files - return null; - } - } - - /** - * Add all the Ant libraries that can be found at the given URL - * - * @param librarySpecs A map to which additional library specifications - * are added. - * @param taskBaseURL the URL from which Ant libraries are to be loaded - * @exception MalformedURLException if the URL for the individual - * library components cannot be formed - * @exception ConfigException if the library specs cannot be parsed - */ - private void addAntLibraries(Map librarySpecs, URL taskBaseURL) - throws MalformedURLException, ConfigException { - URL[] taskURLs = LoaderUtils.getLoaderURLs(taskBaseURL, null, - new String[]{".tsk", ".jar", ".zip"}); - - if (taskURLs == null) { + private void addConfigLibPaths() + throws ConfigException { + if (config == null) { return; } - // parse each task library to get its library definition - for (int i = 0; i < taskURLs.length; ++i) { - URL libURL = new URL("jar:" + taskURLs[i] - + "!/META-INF/antlib.xml"); - try { - AntLibrarySpec antLibrarySpec = parseLibraryDef(libURL); - if (antLibrarySpec != null) { - String libraryId = antLibrarySpec.getLibraryId(); - if (librarySpecs.containsKey(libraryId)) { - throw new ConfigException("Found more than one " - + "copy of library with id = " + libraryId + - " (" + taskURLs[i] + ")"); - } - antLibrarySpec.setLibraryURL(taskURLs[i]); - librarySpecs.put(libraryId, antLibrarySpec); - } - } catch (XMLParseException e) { - Throwable t = e.getCause(); - // ignore file not found exceptions - means the - // jar does not provide META-INF/antlib.xml - if (!(t instanceof FileNotFoundException)) { - throw new ConfigException("Unable to parse Ant library " - + taskURLs[i], e); - } - } - } - } - - /** - * Configures the Ant Libraries. Configuration of an Ant Library - * involves resolving any dependencies between libraries and then - * creating the class loaders for the library - * - * @param initConfig the Ant initialized config - * @param librarySpecs the loaded specifications of the Ant libraries - * @exception ConfigException if a library cannot be configured from the - * given specification - */ - private void configLibraries(InitConfig initConfig, Map librarySpecs) - throws ConfigException { - Set configured = new HashSet(); - CircularDependencyChecker configuring - = new CircularDependencyChecker("configuring Ant libraries"); - for (Iterator i = librarySpecs.keySet().iterator(); i.hasNext(); ) { + // now add any additional library Paths specified by the config + for (Iterator i = config.getLibraryIds(); i.hasNext(); ) { String libraryId = (String)i.next(); - if (!configured.contains(libraryId)) { - configLibrary(initConfig, librarySpecs, libraryId, - configured, configuring); - } - } - } - - /** - * Configure a library from a specification and the Ant init config. - * - * @param initConfig Ant's init config passed in from the front end. - * @param librarySpecs the library specs from which this library is to - * be configured. - * @param libraryId the global identifier for the library - * @param configured the set of libraries which have been configured - * already - * @param configuring A circualr dependency chcker for library - * dependencies. - * @exception ConfigException if the library cannot be configured. - */ - private void configLibrary(InitConfig initConfig, Map librarySpecs, - String libraryId, Set configured, - CircularDependencyChecker configuring) - throws ConfigException { - - try { - - configuring.visitNode(libraryId); - - AntLibrarySpec librarySpec - = (AntLibrarySpec)librarySpecs.get(libraryId); - String extendsId = librarySpec.getExtendsLibraryId(); - if (extendsId != null) { - if (!configured.contains(extendsId)) { - if (!librarySpecs.containsKey(extendsId)) { - throw new ConfigException("Could not find library, " - + extendsId + ", upon which library " - + libraryId + " depends"); + if (antLibraries.containsKey(libraryId)) { + AntLibrary antLib + = (AntLibrary)antLibraries.get(libraryId); + List pathList = config.getLibraryPathList(libraryId); + for (Iterator j = pathList.iterator(); j.hasNext(); ) { + URL pathElementURL = (URL)j.next(); + if (!pathElementURL.getProtocol().equals("file") + && !config.isRemoteLibAllowed()) { + throw new ConfigException("Remote libpaths are not" + + " allowed: " + pathElementURL); } - configLibrary(initConfig, librarySpecs, extendsId, - configured, configuring); + antLib.addLibraryURL(pathElementURL); } } - - // now create the library for the specification - AntLibrary antLibrary = new AntLibrary(librarySpec); - - // determine the URLs required for this task. These are the - // task URL itself, the XML parser URLs if required, the - // tools jar URL if required - List urlsList = new ArrayList(); - - if (librarySpec.getLibraryURL() != null) { - urlsList.add(librarySpec.getLibraryURL()); - } - if (librarySpec.isToolsJarRequired() - && initConfig.getToolsJarURL() != null) { - urlsList.add(initConfig.getToolsJarURL()); - } - - URL[] parserURLs = initConfig.getParserURLs(); - if (librarySpec.usesAntXML()) { - for (int i = 0; i < parserURLs.length; ++i) { - urlsList.add(parserURLs[i]); - } - } - - for (Iterator i = urlsList.iterator(); i.hasNext(); ) { - antLibrary.addLibraryURL((URL)i.next()); - } - if (extendsId != null) { - AntLibrary extendsLibrary - = (AntLibrary)antLibraries.get(extendsId); - antLibrary.setExtendsLibrary(extendsLibrary); - } - antLibrary.setParentLoader(initConfig.getCommonLoader()); - antLibraries.put(libraryId, antLibrary); - configuring.leaveNode(libraryId); - } catch (CircularDependencyException e) { - throw new ConfigException(e); } } - - - /** - * Read an Ant library definition from a URL - * - * @param antlibURL the URL of the library definition - * @return the AntLibrary specification read from the library XML - * definition - * @exception XMLParseException if the library cannot be parsed - */ - private AntLibrarySpec parseLibraryDef(URL antlibURL) - throws XMLParseException { - ParseContext context = new ParseContext(); - AntLibHandler libHandler = new AntLibHandler(); - - context.parse(antlibURL, "antlib", libHandler); - - return libHandler.getAntLibrarySpec(); - } - } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Reflector.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Reflector.java index 17168526b..3aa991094 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Reflector.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Reflector.java @@ -56,10 +56,10 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; -import org.apache.ant.common.converter.ConversionException; -import org.apache.ant.common.converter.Converter; -import org.apache.ant.common.task.TaskException; +import org.apache.ant.common.antlib.Converter; +import org.apache.ant.common.util.ExecutionException; /** * A reflector is used to set attributes and add nested elements to an @@ -90,12 +90,10 @@ public class Reflector { * @exception IllegalAccessException if the method cannot be invoked * @exception ExecutionException if the conversion of the value * fails - * @exception ConversionException if the string value cannot be - * converted to the required type */ void set(Object obj, String value) throws InvocationTargetException, IllegalAccessException, - ExecutionException, ConversionException; + ExecutionException; } /** @@ -120,6 +118,33 @@ public class Reflector { throws InvocationTargetException, IllegalAccessException; } + /** + * Element Creator's a factory method provided by an Ant Library + * Component for creating its own nested element instances. These + * methods are now deprecated. It is better to use the add style methods + * and support polymorphic interfaces. + * + * @author Conor MacNeill + * @created 31 January 2002 + */ + private interface ElementCreator { + /** + * Create a nested element object for the given container object + * + * @param container the object in which the nested element is to be + * created. + * @return the nested element. + * @exception InvocationTargetException if the create method fails + * @exception IllegalAccessException if the create method cannot be + * accessed + * @exception InstantiationException if the nested element instance + * cannot be created. + */ + Object create(Object container) + throws InvocationTargetException, IllegalAccessException, + InstantiationException; + } + /** The method used to add content to the element */ private Method addTextMethod; @@ -133,9 +158,12 @@ public class Reflector { */ private Map elementTypes = new HashMap(); - /** the list of element adders indexed by their element names */ + /** the collection of element adders indexed by their element names */ private Map elementAdders = new HashMap(); + /** the collection of element creators indexed by their element names */ + private Map elementCreators = new HashMap(); + /** * Set an attribute value on an object * @@ -143,30 +171,27 @@ public class Reflector { * @param attributeName the name of the attribute * @param value the string represenation of the attribute's value * @exception ExecutionException if the object does not support the - * attribute - * @exception TaskException if the object has a problem setting the - * value + * attribute or the object has a problem setting the value */ public void setAttribute(Object obj, String attributeName, String value) - throws ExecutionException, TaskException { + throws ExecutionException { + String name = attributeName.toLowerCase(); AttributeSetter as - = (AttributeSetter)attributeSetters.get(attributeName); + = (AttributeSetter)attributeSetters.get(name); if (as == null) { - throw new ExecutionException("Class " + obj.getClass().getName() + - " doesn't support the \"" + attributeName + "\" attribute"); + throw new ExecutionException("Class " + obj.getClass().getName() + + " doesn't support the \"" + attributeName + "\" attribute"); } try { as.set(obj, value); } catch (IllegalAccessException e) { // impossible as getMethods should only return public methods throw new ExecutionException(e); - } catch (ConversionException e) { - throw new ExecutionException(e); } catch (InvocationTargetException ite) { Throwable t = ite.getTargetException(); - if (t instanceof TaskException) { - throw (TaskException)t; + if (t instanceof ExecutionException) { + throw (ExecutionException)t; } throw new ExecutionException(t); } @@ -196,12 +221,11 @@ public class Reflector { * * @param obj the instance whose content is being provided * @param text the required content - * @exception ExecutionException if the object does not support content - * @exception TaskException if the object has a problem setting the - * content + * @exception ExecutionException if the object does not support + * contentor the object has a problem setting the content */ public void addText(Object obj, String text) - throws ExecutionException, TaskException { + throws ExecutionException { if (addTextMethod == null) { throw new ExecutionException("Class " + obj.getClass().getName() + @@ -214,8 +238,8 @@ public class Reflector { throw new ExecutionException(ie); } catch (InvocationTargetException ite) { Throwable t = ite.getTargetException(); - if (t instanceof TaskException) { - throw (TaskException)t; + if (t instanceof ExecutionException) { + throw (ExecutionException)t; } throw new ExecutionException(t); } @@ -228,40 +252,123 @@ public class Reflector { * @param elementName the name of the element * @param value the object to be added - the nested element * @exception ExecutionException if the object does not support content - * @exception TaskException if the object has a problem setting the - * content + * or the object has a problem setting the content */ public void addElement(Object obj, String elementName, Object value) - throws ExecutionException, TaskException { - ElementAdder ea = (ElementAdder)elementAdders.get(elementName); - if (ea == null) { - throw new ExecutionException("Class " + obj.getClass().getName() + - " doesn't support the \"" + elementName + "\" nested element"); + throws ExecutionException { + String name = elementName.toLowerCase(); + ElementAdder adder = (ElementAdder)elementAdders.get(name); + if (adder == null) { + throw new ExecutionException("Class " + obj.getClass().getName() + + " doesn't support the \"" + elementName + + "\" nested element"); } try { - ea.add(obj, value); + adder.add(obj, value); } catch (IllegalAccessException ie) { // impossible as getMethods should only return public methods throw new ExecutionException(ie); } catch (InvocationTargetException ite) { Throwable t = ite.getTargetException(); - if (t instanceof TaskException) { - throw (TaskException)t; + if (t instanceof ExecutionException) { + throw (ExecutionException)t; + } + throw new ExecutionException(t); + } + + } + + /** + * Create a nested element using the object's element factory method. + * + * @param container the object in which the nested element is required. + * @param elementName the name of the nested element + * @return the new instance of the nested element + * @exception ExecutionException if the nested element cannot be + * created. + */ + public Object createElement(Object container, String elementName) + throws ExecutionException { + + ElementCreator creator + = (ElementCreator)elementCreators.get(elementName.toLowerCase()); + if (creator == null) { + throw new ExecutionException("Class " + + container.getClass().getName() + + " doesn't support the \"" + elementName + + "\" nested element"); + } + + try { + return creator.create(container); + } catch (IllegalAccessException e) { + // impossible as getMethods should only return public methods + throw new ExecutionException(e); + } catch (InstantiationException e) { + // impossible as getMethods should only return public methods + throw new ExecutionException(e); + } catch (InvocationTargetException e) { + Throwable t = e.getTargetException(); + if (t instanceof ExecutionException) { + throw (ExecutionException)t; } throw new ExecutionException(t); } + } + /** + * Indicate if the class assocated with this reflector supports the + * addition of text content. + * + * @return true if the class supports an addText method + */ + public boolean supportsText() { + return addTextMethod != null; + } + + /** + * Indicate if the class assocated with this reflector supports the + * given attribute + * + * @param attributeName the name of the attribute + * @return true if the given attribute is supported + */ + public boolean supportsAttribute(String attributeName) { + return attributeSetters.containsKey(attributeName.toLowerCase()); } /** * Determine if the class associated with this reflector supports a - * particular nested element + * particular nested element via a create factory method + * + * @param elementName the name of the element + * @return true if the class supports creation of that element + */ + public boolean supportsNestedCreator(String elementName) { + return elementCreators.containsKey(elementName.toLowerCase()); + } + + /** + * Determine if the class associated with this reflector supports a + * particular nested element via an add method * * @param elementName the name of the element * @return true if the class supports addition of that element */ + public boolean supportsNestedAdder(String elementName) { + return elementAdders.containsKey(elementName.toLowerCase()); + } + + /** + * Determine if the class associated with this reflector supports a + * particular nested element + * + * @param elementName the name of the element + * @return true if the class supports the given type of nested element + */ public boolean supportsNestedElement(String elementName) { - return elementAdders.containsKey(elementName); + return supportsNestedAdder(elementName) + || supportsNestedCreator(elementName); } /** @@ -279,18 +386,13 @@ public class Reflector { if (converters != null && converters.containsKey(type)) { // we have a converter to use to convert the String // value into something the set method expects. - final Converter converter = (Converter)converters.get(type); - attributeSetters.put(propertyName, - new AttributeSetter() { - public void set(Object obj, String value) - throws InvocationTargetException, ExecutionException, - IllegalAccessException, ConversionException { - Object convertedValue = converter.convert(value, type); - m.invoke(obj, new Object[]{convertedValue}); - } - }); - } else if (type.equals(String.class)) { - attributeSetters.put(propertyName, + Converter converter = (Converter)converters.get(type); + addConvertingSetter(m, propertyName, converter, type); + return; + } + + if (type.equals(String.class)) { + attributeSetters.put(propertyName.toLowerCase(), new AttributeSetter() { public void set(Object parent, String value) throws InvocationTargetException, @@ -298,26 +400,45 @@ public class Reflector { m.invoke(parent, new String[]{value}); } }); - } else { - try { - final Constructor c = - type.getConstructor(new Class[]{java.lang.String.class}); - attributeSetters.put(propertyName, - new AttributeSetter() { - public void set(Object parent, String value) - throws InvocationTargetException, - IllegalAccessException, ExecutionException { - try { - Object newValue - = c.newInstance(new String[]{value}); - m.invoke(parent, new Object[]{newValue}); - } catch (InstantiationException ie) { - throw new ExecutionException(ie); - } + return; + } + + try { + final Constructor c = + type.getConstructor(new Class[]{java.lang.String.class}); + attributeSetters.put(propertyName.toLowerCase(), + new AttributeSetter() { + public void set(Object parent, String value) + throws InvocationTargetException, + IllegalAccessException, ExecutionException { + try { + Object newValue + = c.newInstance(new String[]{value}); + m.invoke(parent, new Object[]{newValue}); + } catch (InstantiationException ie) { + throw new ExecutionException(ie); } - }); - } catch (NoSuchMethodException nme) { - // ignore + } + }); + return; + } catch (NoSuchMethodException nme) { + // ignore + } + + if (converters != null) { + // desparate by now - try top find a converter which handles a super + // class of this type and which supports subclass instantiation + for (Iterator i = converters.keySet().iterator(); i.hasNext(); ) { + Class converterType = (Class)i.next(); + if (converterType.isAssignableFrom(type)) { + // could be a candidate + Converter converter + = (Converter)converters.get(converterType); + if (converter.canConvertSubType(type)) { + addConvertingSetter(m, propertyName, converter, type); + return; + } + } } } } @@ -332,7 +453,7 @@ public class Reflector { public void addElementMethod(final Method m, String elementName) { final Class type = m.getParameterTypes()[0]; elementTypes.put(elementName, type); - elementAdders.put(elementName, + elementAdders.put(elementName.toLowerCase(), new ElementAdder() { public void add(Object container, Object obj) throws InvocationTargetException, IllegalAccessException { @@ -340,5 +461,46 @@ public class Reflector { } }); } + + + /** + * Add a create factory method. + * + * @param m the create method + * @param elementName the name of the nested element the create method + * supports. + */ + public void addCreateMethod(final Method m, String elementName) { + elementCreators.put(elementName.toLowerCase(), + new ElementCreator() { + public Object create(Object container) + throws InvocationTargetException, IllegalAccessException { + return m.invoke(container, new Object[]{}); + } + }); + } + + /** + * Add an attribute setter with an associated converter + * + * @param m the attribute setter method + * @param propertyName the name of the attribute this method supports + * @param converter the converter to be used to construct the value + * expected by the method. + * @param type the type expected by the method. + */ + private void addConvertingSetter(final Method m, String propertyName, + final Converter converter, + final Class type) { + attributeSetters.put(propertyName.toLowerCase(), + new AttributeSetter() { + public void set(Object obj, String value) + throws InvocationTargetException, ExecutionException, + IllegalAccessException { + Object convertedValue = converter.convert(value, type); + m.invoke(obj, new Object[]{convertedValue}); + } + }); + } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskAdapter.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskAdapter.java index 2361eaae6..e6737c70d 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskAdapter.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskAdapter.java @@ -54,8 +54,8 @@ package org.apache.ant.antcore.execution; import java.lang.reflect.Method; -import org.apache.ant.common.task.AbstractTask; -import org.apache.ant.common.task.TaskException; +import org.apache.ant.common.antlib.AbstractTask; +import org.apache.ant.common.util.ExecutionException; /** * Use introspection to "adapt" an arbitrary Bean (not extending Task, but @@ -100,14 +100,13 @@ public class TaskAdapter extends AbstractTask { * Standard Task execute method. This invokes the execute method of the * worker instance * - * @exception TaskException if there is an exception in the - * worker's execute method + * @exception ExecutionException if the proxied object throws an exception */ - public void execute() throws TaskException { + public void execute() throws ExecutionException { try { executeMethod.invoke(worker, null); - } catch (Exception ex) { - throw new TaskException(ex); + } catch (Throwable t) { + throw new ExecutionException(t); } } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java index f2bcc9643..331299167 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java @@ -52,9 +52,9 @@ * . */ package org.apache.ant.antcore.execution; -import org.apache.ant.common.task.Task; -import org.apache.ant.common.task.TaskException; import org.apache.ant.antcore.model.ModelElement; +import org.apache.ant.common.antlib.Task; +import org.apache.ant.common.util.ExecutionException; /** * This is the core's implementation of the AntContext for Tasks. * @@ -73,6 +73,18 @@ public class TaskContext extends ExecutionContext { */ private ClassLoader loader; + /** + * Initilaise this context's environment + * + * @param frame the frame containing this context + * @param eventSupport the event support instance used to send build + * events + */ + public TaskContext(ExecutionFrame frame, + BuildEventSupport eventSupport) { + super(frame, eventSupport); + } + /** * Get the task associated with this context * @@ -97,8 +109,10 @@ public class TaskContext extends ExecutionContext { * @param task the task to be manager * @param loader the classloader * @param modelElement the model element associated with this context + * @exception ExecutionException if the task cannot be initialized */ - public void init(ClassLoader loader, Task task, ModelElement modelElement) { + public void init(ClassLoader loader, Task task, ModelElement modelElement) + throws ExecutionException { this.task = task; this.loader = loader; setModelElement(modelElement); @@ -108,9 +122,9 @@ public class TaskContext extends ExecutionContext { /** * execute this context's task * - * @exception TaskException if the task cannot execute properly + * @exception ExecutionException if there is a problem executing the task */ - public void execute() throws TaskException { + public void execute() throws ExecutionException { task.execute(); } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Project.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Project.java index a173f7700..1516384be 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Project.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/Project.java @@ -373,11 +373,6 @@ public class Project extends ModelElement { * @exception ModelException if the element is invalid */ public void validate(String globalName) throws ModelException { - if (defaultTarget == null) { - throw new ModelException("Project must have a default " - + "attribute", getLocation()); - } - Set keys = referencedProjects.keySet(); for (Iterator i = keys.iterator(); i.hasNext(); ) { String refName = (String)i.next(); @@ -500,7 +495,6 @@ public class Project extends ModelElement { if (flattenedList.contains(fullTargetName)) { return; } - Project containingProject = getRefProject(fullTargetName); String fullProjectName = getFullProjectName(fullTargetName); Target target = getRefTarget(fullTargetName); if (target == null) { diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/BuildElementHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/BuildElementHandler.java old mode 100755 new mode 100644 similarity index 99% rename from proposal/mutant/src/java/cli/org/apache/ant/cli/xml/BuildElementHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/BuildElementHandler.java index 2526c32ad..077e6b9d5 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/BuildElementHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/BuildElementHandler.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.cli.xml; +package org.apache.ant.antcore.model.xmlparser; import java.util.Iterator; import org.apache.ant.antcore.model.BuildElement; diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/IncludeHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/IncludeHandler.java old mode 100755 new mode 100644 similarity index 99% rename from proposal/mutant/src/java/cli/org/apache/ant/cli/xml/IncludeHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/IncludeHandler.java index 42832ebfc..353359d48 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/IncludeHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/IncludeHandler.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.cli.xml; +package org.apache.ant.antcore.model.xmlparser; import java.net.MalformedURLException; import java.net.URL; diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/NoProjectReadException.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/NoProjectReadException.java old mode 100755 new mode 100644 similarity index 98% rename from proposal/mutant/src/java/cli/org/apache/ant/cli/xml/NoProjectReadException.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/NoProjectReadException.java index 5940dc25c..0b9e22c6d --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/NoProjectReadException.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/NoProjectReadException.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.cli.xml; +package org.apache.ant.antcore.model.xmlparser; /** * A NoProjectReadException is used to indicate that a project was not read diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/ProjectHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/ProjectHandler.java old mode 100755 new mode 100644 similarity index 99% rename from proposal/mutant/src/java/cli/org/apache/ant/cli/xml/ProjectHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/ProjectHandler.java index 1b955b696..a73f8ded8 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/ProjectHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/ProjectHandler.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.cli.xml; +package org.apache.ant.antcore.model.xmlparser; import org.apache.ant.antcore.model.ModelException; import org.apache.ant.antcore.model.Project; import org.apache.ant.antcore.xml.ElementHandler; @@ -148,6 +148,7 @@ public class ProjectHandler extends ElementHandler { public void startElement(String uri, String localName, String qualifiedName, Attributes attributes) throws SAXParseException { + if (qualifiedName.equals("ref")) { RefHandler refHandler = new RefHandler(); refHandler.start(getParseContext(), getXMLReader(), this, diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/RefHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/RefHandler.java old mode 100755 new mode 100644 similarity index 99% rename from proposal/mutant/src/java/cli/org/apache/ant/cli/xml/RefHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/RefHandler.java index 3e7d45e0d..197f3a7c9 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/RefHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/RefHandler.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.cli.xml; +package org.apache.ant.antcore.model.xmlparser; import java.net.MalformedURLException; import java.net.URL; diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/TargetHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/TargetHandler.java old mode 100755 new mode 100644 similarity index 98% rename from proposal/mutant/src/java/cli/org/apache/ant/cli/xml/TargetHandler.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/TargetHandler.java index 250ddd65c..5c1c40cf2 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/TargetHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/TargetHandler.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.cli.xml; +package org.apache.ant.antcore.model.xmlparser; import java.util.StringTokenizer; import org.apache.ant.antcore.model.Target; @@ -97,7 +97,6 @@ public class TargetHandler extends ElementHandler { */ public void processElement(String elementName) throws SAXParseException { - String targetName = null; target = new Target(getLocation(), getAttribute(NAME_ATTR)); target.setDescription(getAttribute(DESC_ATTR)); target.setAspects(getAspects()); diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/XMLProjectParser.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/XMLProjectParser.java old mode 100755 new mode 100644 similarity index 98% rename from proposal/mutant/src/java/cli/org/apache/ant/cli/xml/XMLProjectParser.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/XMLProjectParser.java index f9ceaf58a..911d654f0 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/xml/XMLProjectParser.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/model/xmlparser/XMLProjectParser.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.cli.xml; +package org.apache.ant.antcore.model.xmlparser; import java.net.URL; import org.apache.ant.common.util.Location; diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ElementHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ElementHandler.java index 67517d312..6ebfb19c3 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ElementHandler.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ElementHandler.java @@ -64,6 +64,7 @@ import org.xml.sax.Locator; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; +import org.apache.ant.common.util.PropertyUtils; /** * An Element Handler is a handler which handles a single element by @@ -125,6 +126,16 @@ public abstract class ElementHandler extends DefaultHandler { return (String)elementAttributes.get(attributeName); } + /** + * Get an attribute as a boolean value + * + * @param attributeName the name of the attribute + * @return the attribute value as a boolean + */ + protected boolean getBooleanAttribute(String attributeName) { + return PropertyUtils.toBoolean(getAttribute(attributeName)); + } + /** * Get an iterator to this elements attributes * @@ -304,7 +315,8 @@ public abstract class ElementHandler extends DefaultHandler { throws SAXParseException { aspects = new HashMap(); elementAttributes = new HashMap(); - for (int i = 0; i < attributes.getLength(); ++i) { + int length = attributes.getLength(); + for (int i = 0; i < length; ++i) { String attributeName = attributes.getQName(i); String attributeValue = attributes.getValue(i); if (attributeName.indexOf(":") != -1) { diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ParseContext.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ParseContext.java index 18c542fec..8fd28c5bc 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ParseContext.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ParseContext.java @@ -128,11 +128,9 @@ public class ParseContext { Location location = new Location(e.getSystemId(), e.getLineNumber(), e.getColumnNumber()); if (e.getException() != null) { - throw new XMLParseException("XML Parsing Exception", - e.getException(), location); + throw new XMLParseException(e.getException(), location); } else { - throw new XMLParseException("XML Parsing Exception", - e, location); + throw new XMLParseException(e, location); } } catch (SAXException e) { throw new XMLParseException(e); diff --git a/proposal/mutant/src/java/antlibs/ant1compat/antlib.xml b/proposal/mutant/src/java/antlibs/ant1compat/antlib.xml new file mode 100644 index 000000000..fd2bed73b --- /dev/null +++ b/proposal/mutant/src/java/antlibs/ant1compat/antlib.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Converter.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Converter.java new file mode 100644 index 000000000..b7eaaa754 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Converter.java @@ -0,0 +1,136 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant; + +import org.apache.ant.common.antlib.AbstractConverter; +import org.apache.ant.common.util.ExecutionException; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.Path; + +/** + * A converter to convert to the types supported by the Ant1 Ant library + * + * @author Conor MacNeill + * @created 1 February 2002 + */ +public class Ant1Converter extends AbstractConverter { + + /** The project instance for this converter */ + private Project project; + + /** + * Constructor for the Ant1Converter object + * + * @param project the project for this converter. It is used in the + * conversion of some of the supported types. + */ + public Ant1Converter(Project project) { + this.project = project; + } + + /** + * Get the list of classes this converter is able to convert to. + * + * @return an array of Class objects representing the classes this + * converter handles. + */ + public Class[] getTypes() { + return new Class[]{Path.class, EnumeratedAttribute.class}; + } + + /** + * Convert a string from the value given to an instance of the given + * type. + * + * @param value The value to be converted + * @param type the desired type of the converted object + * @return the value of the converted object + * @exception ExecutionException if the conversion cannot be made + */ + public Object convert(String value, Class type) throws ExecutionException { + if (type.equals(Path.class)) { + return new Path(project, value); + } else if (EnumeratedAttribute.class.isAssignableFrom(type)) { + try { + EnumeratedAttribute ea + = (EnumeratedAttribute)type.newInstance(); + ea.setValue(value); + return ea; + } catch (InstantiationException e) { + throw new ExecutionException(e); + } catch (IllegalAccessException e) { + throw new ExecutionException(e); + } + + } else { + throw new ExecutionException("This converter does not handle " + + type.getName()); + } + } + + /** + * This method allows a converter to indicate whether it can create the + * given type which is a sub-type of one of the converter's main types + * indicated in getTypes. Most converters can return false here. + * + * @param subType the sub-type + * @return true if this converter can convert a string representation to + * the given subclass of one of its main class + */ + public boolean canConvertSubType(Class subType) { + return EnumeratedAttribute.class.isAssignableFrom(subType); + } + +} + diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Factory.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Factory.java new file mode 100644 index 000000000..fd7815a63 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Factory.java @@ -0,0 +1,189 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant; +import org.apache.ant.common.antlib.AntContext; +import org.apache.ant.common.antlib.Converter; +import org.apache.ant.common.antlib.StandardLibFactory; +import org.apache.ant.common.util.ExecutionException; + +/** + * The factory object for the Ant1 compatability Ant library + * + * @author Conor MacNeill + * @created 31 January 2002 + */ +public class Ant1Factory extends StandardLibFactory { + /** + * A Project instance associated with the factory - used in the creation + * of tasks and types + */ + private Project project; + /** The Ant context for this factory */ + private AntContext context; + + /** + * Initialise the factory + * + * @param context the context for this factory to use to access core + * services. + * @exception ExecutionException if the factory cannot be initialised. + */ + public void init(AntContext context) throws ExecutionException { + this.context = context; + project = new Project(); + project.init(context); + } + + /** + * Create an instance of the requested type class + * + * @param typeClass the class from which an instance is required + * @return an instance of the requested class + * @exception ExecutionException the instance could not be created. + * @exception InstantiationException if the type cannot be instantiated + * @exception IllegalAccessException if the type cannot be accessed + */ + public Object createTypeInstance(Class typeClass) + throws InstantiationException, IllegalAccessException, + ExecutionException { + try { + java.lang.reflect.Constructor ctor = null; + // DataType can have a "no arg" constructor or take a single + // Project argument. + Object o = null; + try { + ctor = typeClass.getConstructor(new Class[0]); + o = ctor.newInstance(new Object[0]); + } catch (NoSuchMethodException nse) { + ctor = typeClass.getConstructor(new Class[]{Project.class}); + o = ctor.newInstance(new Object[]{project}); + } + + if (o instanceof ProjectComponent) { + ((ProjectComponent)o).setProject(project); + } + return o; + } catch (java.lang.reflect.InvocationTargetException ite) { + Throwable t = ite.getTargetException(); + String msg = "Could not create datatype of type: " + + typeClass.getName() + " due to " + t; + throw new ExecutionException(msg, t); + } catch (NoSuchMethodException e) { + throw new ExecutionException("Unable to find an appropriate " + + "constructor for type " + typeClass.getName(), e); + } + } + + /** + * Create an instance of the requested task class + * + * @param taskClass the class from which an instance is required + * @return an instance of the requested class + * @exception InstantiationException if the task cannot be instantiated + * @exception IllegalAccessException if the task cannot be accessed + */ + public Object createTaskInstance(Class taskClass) + throws InstantiationException, IllegalAccessException { + Object o = taskClass.newInstance(); + if (o instanceof ProjectComponent) { + ((ProjectComponent)o).setProject(project); + } + + // XXX task.setTaskType(taskType); + + // set default value, can be changed by the user + // XXX task.setTaskName(taskType); + + return o; + } + + /** + * Create a converter. + * + * @param converterClass the class of the converter. + * @return an instance of the requested converter class + * @exception InstantiationException if the converter cannot be + * instantiated + * @exception IllegalAccessException if the converter cannot be accessed + * @exception ExecutionException if the converter cannot be created + */ + public Converter createConverter(Class converterClass) + throws InstantiationException, IllegalAccessException, + ExecutionException { + + java.lang.reflect.Constructor c = null; + + Converter converter = null; + try { + try { + c = converterClass.getConstructor(new Class[0]); + converter = (Converter)c.newInstance(new Object[0]); + } catch (NoSuchMethodException nse) { + c = converterClass.getConstructor(new Class[]{Project.class}); + converter = (Converter)c.newInstance(new Object[]{project}); + } + + return converter; + } catch (java.lang.reflect.InvocationTargetException ite) { + Throwable t = ite.getTargetException(); + String msg = "Could not create converter of type: " + + converterClass.getName() + " due to " + t; + throw new ExecutionException(msg, t); + } catch (NoSuchMethodException e) { + throw new ExecutionException("Unable to find an appropriate " + + "constructor for converter " + converterClass.getName(), e); + } + } +} + diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/AntClassLoader.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/AntClassLoader.java new file mode 100644 index 000000000..53298a28f --- /dev/null +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/AntClassLoader.java @@ -0,0 +1,280 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import org.apache.ant.common.event.BuildEvent; +import org.apache.ant.init.InitUtils; +import org.apache.tools.ant.types.Path; + +/** + * AntClassLoader facade + * + * @author Conor MacNeill + * @created 2 February 2002 + */ +public class AntClassLoader extends URLClassLoader + implements BuildListener { + /** + * The context loader saved when setting the thread's current context + * loader. + */ + private ClassLoader savedContextLoader = null; + + /** + * Flag which indicates if this loader is currently set as the thread's + * context loader + */ + private boolean isContextLoaderSaved = false; + + /** + * indicates this loader should load classes by delegating to the parent + * loader first + */ + private boolean parentFirst = true; + + /** label used in debugging messages */ + private String debugLabel = null; + + /** flag to indicate of debugging is turned on */ + private boolean debug = false; + + /** + * Create an AntClassLoader + * + * @param project Project instance this loader is associated with + * @param classpath the classpath to use in searching for classes + */ + public AntClassLoader(Project project, Path classpath) { + super(new URL[0]); + addPath(classpath); + } + + /** + * Constructor for the AntClassLoader object + * + * @param project Project instance this loader is associated with + * @param classpath the classpath to use in searching for classes + * @param parentFirst true if this loader should delagate to its parent + * loader + */ + public AntClassLoader(Project project, Path classpath, + boolean parentFirst) { + this(project, classpath); + this.parentFirst = parentFirst; + } + + /** + * Constructor for the AntClassLoader object + * + * @param parent the parent classloader + * @param project Project instance this loader is associated with + * @param classpath the classpath to use in searching for classes + * @param parentFirst true if this loader should delagate to its parent + * loader + */ + public AntClassLoader(ClassLoader parent, Project project, Path classpath, + boolean parentFirst) { + super(new URL[0], parent); + addPath(classpath); + this.parentFirst = parentFirst; + } + + /** + * Initialize the given class + * + * @param theClass XXX Description of Parameter + */ + public static void initializeClass(Class theClass) { + // do nothing in Ant2 + } + + /** + * Set this classloader to operate in isolated mode + * + * @param isolated true if this loader should isolate it from other + * classes in the VM + */ + public void setIsolated(boolean isolated) { + } + + /** + * Set the current thread's context loader to this classloader, storing + * the current loader value for later resetting + */ + public void setThreadContextLoader() { + if (isContextLoaderSaved) { + throw new BuildException("Context loader has not been reset"); + } + Thread currentThread = Thread.currentThread(); + savedContextLoader = currentThread.getContextClassLoader(); + currentThread.setContextClassLoader(this); + isContextLoaderSaved = true; + } + + /** + * sets this loader to debug mode + * + * @param debug true if loads should be debugged + */ + public void setDebug(boolean debug) { + this.debug = debug; + dumpURLs(); + } + + /** + * Sets the debugLabel of the AntClassLoader + * + * @param debugLabel the label to use in debug statements + */ + public void setDebugLabel(String debugLabel) { + this.debugLabel = debugLabel; + } + + /** Cleanup this loader */ + public void cleanup() { + } + + /** + * New build listener interface + * + * @param be the build event to be processed + */ + public void processBuildEvent(BuildEvent be) { + } + + /** + * Force a class to be loaded by this loader + * + * @param classname the name of the class to be loaded + * @return an instance of the requested class + * @exception ClassNotFoundException if the class cannot be found + */ + public Class forceLoadClass(String classname) + throws ClassNotFoundException { + return super.loadClass(classname); + } + + /** Reset the thread's class loader to its original value */ + public void resetThreadContextLoader() { + if (!isContextLoaderSaved) { + throw new BuildException("Context loader is not currently set"); + } + Thread currentThread = Thread.currentThread(); + currentThread.setContextClassLoader(savedContextLoader); + isContextLoaderSaved = false; + } + + /** + * Add a path tot his loader + * + * @param path the path to be added to this loader + */ + private void addPath(Path path) { + try { + String[] pathElements = path.list(); + for (int i = 0; i < pathElements.length; ++i) { + File elementFile = new File(pathElements[i]); + URL elementURL = InitUtils.getFileURL(elementFile); + addURL(elementURL); + } + } catch (MalformedURLException e) { + throw new BuildException(e); + } + } + + /** Dump the URLs being used for this loader */ + 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]); + } + } + } + + /* + 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; + } +*/ +} + diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildEvent.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildEvent.java new file mode 100644 index 000000000..699e22a8b --- /dev/null +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildEvent.java @@ -0,0 +1,72 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant; + +/** + * BuildEvent facade + * + * @author Conor MacNeill + * @created 31 January 2002 + */ +public class BuildEvent extends org.apache.ant.common.event.BuildEvent { + /** + * Construct a BuildEvent for a task level event + * + * @param task the task that emitted the event. + */ + public BuildEvent(Task task) { + super(task, MESSAGE); + } +} + diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildListener.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildListener.java new file mode 100644 index 000000000..983b010cc --- /dev/null +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/BuildListener.java @@ -0,0 +1,65 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant; + +/** + * BuildListener facade + * + * @author Conor MacNeill + * @created 31 January 2002 + */ +public interface BuildListener + extends org.apache.ant.common.event.BuildListener { +} + diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java new file mode 100644 index 000000000..41c99b91f --- /dev/null +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java @@ -0,0 +1,622 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant; +import java.io.File; +import java.io.IOException; +import org.apache.ant.common.antlib.AntContext; +import org.apache.ant.common.service.DataService; +import org.apache.ant.common.service.FileService; +import org.apache.ant.common.util.ExecutionException; +import org.apache.ant.common.util.PropertyUtils; +import org.apache.ant.common.util.MessageLevel; +import org.apache.tools.ant.taskdefs.ExecTask; +import org.apache.tools.ant.taskdefs.Java; +import org.apache.tools.ant.types.FilterSet; +import org.apache.tools.ant.types.FilterSetCollection; +import org.apache.tools.ant.util.FileUtils; + +/** + * Project facade + * + * @author Conor MacNeill + * @created 30 January 2002 + */ +public class Project { + + /** String which indicates Java version 1.0 */ + public final static String JAVA_1_0 = "1.0"; + /** String which indicates Java version 1.1 */ + public final static String JAVA_1_1 = "1.1"; + /** String which indicates Java version 1.2 */ + public final static String JAVA_1_2 = "1.2"; + /** String which indicates Java version 1.3 */ + public final static String JAVA_1_3 = "1.3"; + /** String which indicates Java version 1.4 */ + public final static String JAVA_1_4 = "1.4"; + + /** + * @see MessageLevel.MSG_ERR + */ + public final static int MSG_ERR = MessageLevel.MSG_ERR; + /** + * @see MessageLevel.MSG_WARN + */ + public final static int MSG_WARN = MessageLevel.MSG_WARN; + /** + * @see MessageLevel.MSG_INFO + */ + public final static int MSG_INFO = MessageLevel.MSG_INFO; + /** + * @see MessageLevel.MSG_VERBOSE + */ + public final static int MSG_VERBOSE = MessageLevel.MSG_VERBOSE; + /** + * @see MessageLevel.MSG_DEBUG + */ + public final static int MSG_DEBUG = MessageLevel.MSG_DEBUG; + + /** The java version detected that Ant is running on */ + private static String javaVersion; + + /** The project description */ + private String description; + + /** The global filters of this project */ + private FilterSet globalFilterSet = new FilterSet(); + + /** The AntContext that is used to access core services */ + private AntContext context; + + /** The core's FileService instance */ + private FileService fileService; + + /** The core's DataService instance */ + private DataService dataService; + + /** Ant1 FileUtils instance fro manipulating files */ + private FileUtils fileUtils; + /** The collection of global filters */ + private FilterSetCollection globalFilters + = new FilterSetCollection(globalFilterSet); + + static { + + // Determine the Java version by looking at available classes + // java.lang.StrictMath was introduced in JDK 1.3 + // java.lang.ThreadLocal was introduced in JDK 1.2 + // java.lang.Void was introduced in JDK 1.1 + // Count up version until a NoClassDefFoundError ends the try + + try { + javaVersion = JAVA_1_0; + Class.forName("java.lang.Void"); + javaVersion = JAVA_1_1; + Class.forName("java.lang.ThreadLocal"); + javaVersion = JAVA_1_2; + Class.forName("java.lang.StrictMath"); + javaVersion = JAVA_1_3; + Class.forName("java.lang.CharSequence"); + javaVersion = JAVA_1_4; + } catch (ClassNotFoundException cnfe) { + // swallow as we've hit the max class version that + // we have + } + } + + /** Create the project */ + public Project() { + fileUtils = FileUtils.newFileUtils(); + } + + /** + * static query of the java version + * + * @return a string indicating the Java version + */ + public static String getJavaVersion() { + return javaVersion; + } + + /** + * returns the boolean equivalent of a string, which is considered true + * if either "on", "true", or "yes" is found, ignoring case. + * + * @param s the string value to be interpreted at a boolean + * @return the value of s as a boolean + */ + public static boolean toBoolean(String s) { + return PropertyUtils.toBoolean(s); + } + + /** + * Translate a path into its native (platform specific) format.

+ * + * This method uses the PathTokenizer class to separate the input path + * into its components. This handles DOS style paths in a relatively + * sensible way. The file separators are then converted to their + * platform specific versions. + * + * @param to_process the path to be converted + * @return the native version of to_process or an empty string if + * to_process is null or empty + */ + public static String translatePath(String to_process) { + if (to_process == null || to_process.length() == 0) { + return ""; + } + + StringBuffer path = new StringBuffer(to_process.length() + 50); + PathTokenizer tokenizer = new PathTokenizer(to_process); + while (tokenizer.hasMoreTokens()) { + String pathComponent = tokenizer.nextToken(); + pathComponent = pathComponent.replace('/', File.separatorChar); + pathComponent = pathComponent.replace('\\', File.separatorChar); + if (path.length() != 0) { + path.append(File.pathSeparatorChar); + } + path.append(pathComponent); + } + + return path.toString(); + } + + /** + * set the project description + * + * @param description text + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * Set a project property + * + * @param name the property name + * @param value the property value + */ + public void setProperty(String name, String value) { + try { + dataService.setMutableDataValue(name, value); + } catch (ExecutionException e) { + throw new BuildException(e); + } + } + + /** + * Set a property which must be a new value + * + * @param name the property name + * @param value the property value + */ + public void setNewProperty(String name, String value) { + try { + dataService.setDataValue(name, value); + } catch (ExecutionException e) { + throw new BuildException(e); + } + } + + /** + * Sets a userProperty of the Project. Note under Ant2, there is no + * distinction between user and system properties + * + * @param name the property name + * @param value the property value + */ + public void setUserProperty(String name, String value) { + try { + dataService.setMutableDataValue(name, value); + } catch (ExecutionException e) { + throw new BuildException(e); + } + } + + /** + * Gets the AntContext of the Project + * + * @return the AntContext + */ + public AntContext getContext() { + return context; + } + + /** + * get the project description + * + * @return description or null if no description has been set + */ + public String getDescription() { + return description; + } + + /** + * Get a project property + * + * @param name the property name + * @return the value of the property + */ + public String getProperty(String name) { + try { + Object value = dataService.getDataValue(name); + return value == null ? null : value.toString(); + } catch (ExecutionException e) { + throw new BuildException(e); + } + } + + /** + * Get a project property. Ant2 does not distinguish between User and + * system proerties + * + * @param name the property name + * @return the value of the property + */ + public String getUserProperty(String name) { + try { + return dataService.getDataValue(name).toString(); + } catch (ExecutionException e) { + throw new BuildException(e); + } + } + + /** + * Get a reference to a project property. Note that in Ant2, properties + * and references occupy the same namespace. + * + * @param refId the reference Id + * @return the object specified by the reference id + */ + public Object getReference(String refId) { + try { + return dataService.getDataValue(refId); + } catch (ExecutionException e) { + throw new BuildException(e); + } + } + + /** + * Gets the globalFilterSet of the Project + * + * @return the globalFilterSet + */ + public FilterSet getGlobalFilterSet() { + return globalFilterSet; + } + + /** + * Gets the baseDir of the Project + * + * @return the baseDir + */ + public File getBaseDir() { + return context.getBaseDir(); + } + + /** + * Gets the coreLoader of the Project + * + * @return the coreLoader value + */ + public ClassLoader getCoreLoader() { + return getClass().getClassLoader(); + } + + /** + * Add a reference to an object. NOte that in Ant2 objects and + * properties occupy the same namespace. + * + * @param name the reference name + * @param value the object to be associated with the given name. + */ + public void addReference(String name, Object value) { + try { + dataService.setDataValue(name, value); + } catch (ExecutionException e) { + throw new BuildException(e); + } + } + + + /** + * Convienence method to copy a file from a source to a destination. No + * filtering is performed. + * + * @param sourceFile the source file to be copied + * @param destFile the destination to which the file is copied + * @exception IOException if the file cannot be copied + * @deprecated + */ + public void copyFile(String sourceFile, String destFile) + throws IOException { + fileUtils.copyFile(sourceFile, destFile); + } + + /** + * Convienence method to copy a file from a source to a destination + * specifying if token filtering must be used. + * + * @param sourceFile the source file to be copied + * @param destFile the destination to which the file is copied + * @param filtering true if the copy should apply filters + * @exception IOException if the file cannot be copied + * @deprecated + */ + public void copyFile(String sourceFile, String destFile, boolean filtering) + throws IOException { + fileUtils.copyFile(sourceFile, destFile, + filtering ? globalFilters : null); + } + + /** + * Convienence method to copy a file from a source to a destination + * specifying if token filtering must be used and if source files may + * overwrite newer destination files. + * + * @param sourceFile the source file to be copied + * @param destFile the destination to which the file is copied + * @param filtering true if the copy should apply filters + * @param overwrite true if the destination can be overwritten + * @exception IOException if the file cannot be copied + * @deprecated + */ + public void copyFile(String sourceFile, String destFile, boolean filtering, + boolean overwrite) throws IOException { + fileUtils.copyFile(sourceFile, destFile, + filtering ? globalFilters : null, overwrite); + } + + /** + * Convienence method to copy a file from a source to a destination + * specifying if token filtering must be used, if source files may + * overwrite newer destination files and the last modified time of + * destFile file should be made equal to the last modified + * time of sourceFile. + * + * @param sourceFile the source file to be copied + * @param destFile the destination to which the file is copied + * @param filtering true if the copy should apply filters + * @param overwrite true if the destination can be overwritten + * @param preserveLastModified true if the last modified time of the + * source file is preserved + * @exception IOException if the file cannot be copied + * @deprecated + */ + public void copyFile(String sourceFile, String destFile, boolean filtering, + boolean overwrite, boolean preserveLastModified) + throws IOException { + fileUtils.copyFile(sourceFile, destFile, + filtering ? globalFilters : null, + overwrite, preserveLastModified); + } + + /** + * Convienence method to copy a file from a source to a destination. No + * filtering is performed. + * + * @param sourceFile the source file to be copied + * @param destFile the destination to which the file is copied + * @exception IOException if the file cannot be copied + * @deprecated + */ + public void copyFile(File sourceFile, File destFile) throws IOException { + fileUtils.copyFile(sourceFile, destFile); + } + + /** + * Convienence method to copy a file from a source to a destination + * specifying if token filtering must be used. + * + * @param sourceFile the source file to be copied + * @param destFile the destination to which the file is copied + * @param filtering true if the copy should apply filters + * @exception IOException if the file cannot be copied + * @deprecated + */ + public void copyFile(File sourceFile, File destFile, boolean filtering) + throws IOException { + fileUtils.copyFile(sourceFile, destFile, + filtering ? globalFilters : null); + } + + /** + * Convienence method to copy a file from a source to a destination + * specifying if token filtering must be used and if source files may + * overwrite newer destination files. + * + * @param sourceFile the source file to be copied + * @param destFile the destination to which the file is copied + * @param filtering true if the copy should apply filters + * @param overwrite true if the destination can be overwritten + * @exception IOException if the file cannot be copied + * @deprecated + */ + public void copyFile(File sourceFile, File destFile, boolean filtering, + boolean overwrite) throws IOException { + fileUtils.copyFile(sourceFile, destFile, + filtering ? globalFilters : null, overwrite); + } + + /** + * Convienence method to copy a file from a source to a destination + * specifying if token filtering must be used, if source files may + * overwrite newer destination files and the last modified time of + * destFile file should be made equal to the last modified + * time of sourceFile. + * + * @param sourceFile the source file to be copied + * @param destFile the destination to which the file is copied + * @param filtering true if the copy should apply filters + * @param overwrite true if the destination can be overwritten + * @param preserveLastModified true if the last modified time of the + * source file is preserved + * @exception IOException if the file cannot be copied + * @deprecated + */ + public void copyFile(File sourceFile, File destFile, boolean filtering, + boolean overwrite, boolean preserveLastModified) + throws IOException { + fileUtils.copyFile(sourceFile, destFile, + filtering ? globalFilters : null, overwrite, preserveLastModified); + } + + /** + * Initialise this porject + * + * @param context the context the project uses to access core services + * @exception ExecutionException if the project cannot be initialised. + */ + public void init(AntContext context) throws ExecutionException { + this.context = context; + fileService = (FileService)context.getCoreService(FileService.class); + dataService = (DataService)context.getCoreService(DataService.class); + } + + /** + * Output a message to the log with the default log level of MSG_INFO + * + * @param msg text to log + */ + + public void log(String msg) { + log(msg, MSG_INFO); + } + + /** + * Output a message to the log with the given log level and an event + * scope of project + * + * @param msg text to log + * @param msgLevel level to log at + */ + public void log(String msg, int msgLevel) { + context.log(msg, msgLevel); + } + + /** + * Output a message to the log with the given log level and an event + * scope of a task + * + * @param task task to use in the log + * @param msg text to log + * @param msgLevel level to log at + */ + public void log(Task task, String msg, int msgLevel) { + context.log(msg, msgLevel); + } + + /** + * Resolve a file relative to the project's basedir + * + * @param fileName the file name + * @return the file as a File resolved relative to the project's basedir + */ + public File resolveFile(String fileName) { + try { + return fileService.resolveFile(fileName); + } catch (ExecutionException e) { + throw new BuildException(e); + } + } + + /** + * Replace property references (${} values) in the given string + * + * @param value the string in which property references are replaced + * @return the string with the properties replaced. + */ + public String replaceProperties(String value) { + try { + return dataService.replacePropertyRefs(value); + } catch (ExecutionException e) { + throw new BuildException(e); + } + } + + /** + * add a build listener to this project + * + * @param listener the listener to be added to the project + */ + public void addBuildListener(BuildListener listener) { + // XXX do nothing for now + } + + /** + * Create a Task. This faced hard codes a few well known tasks at this + * time + * + * @param taskName the name of the task to be created. + * @return the created task instance + */ + public Task createTask(String taskName) { + // we piggy back the task onto the current context + Task task = null; + if (taskName.equals("java")) { + task = new Java(); + } else if (taskName.equals("exec")) { + task = new ExecTask(); + } else { + return null; + } + try { + task.setProject(this); + task.init(context); + return task; + } catch (ExecutionException e) { + throw new BuildException(e); + } + } +} + diff --git a/proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/Echo.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectComponent.java old mode 100755 new mode 100644 similarity index 54% rename from proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/Echo.java rename to proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectComponent.java index c3ee9f37a..cbfbefaa3 --- a/proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/Echo.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectComponent.java @@ -51,112 +51,106 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.taskdef.io; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; +package org.apache.tools.ant; -import org.apache.ant.common.task.AbstractTask; -import org.apache.ant.common.task.TaskException; -import org.apache.ant.common.util.MessageLevel; +import org.apache.ant.common.antlib.AntContext; +import org.apache.ant.common.util.ExecutionException; /** - * Basic Echo Tast for testing + * ProjectComponent facade * * @author Conor MacNeill - * @created 16 January 2002 + * @created 31 January 2002 */ -public class Echo extends AbstractTask { - /** The message to be echoed */ - private String message = ""; - /** the file to which output is sent if any */ - private File file = null; - /** indicates if the fileoutput is to be appended to an existing file */ - private boolean append = false; - - // by default, messages are always displayed - /** the log level to be used when echoing - defaults to Warning level */ - private int logLevel = MessageLevel.MSG_WARN; +public abstract class ProjectComponent { + /** The project in which the project component operates */ + protected Project project; + /** The location within the build file of this project component */ + protected Location location; + /** The core context for this component */ + private AntContext context; /** - * Sets the message variable. + * Sets the project of the ProjectComponent * - * @param msg Sets the value for the message variable. + * @param project the project object with which this component is + * associated */ - public void setMessage(String msg) { - this.message = msg; + public void setProject(Project project) { + this.project = project; } /** - * Set the file to which output is to be sent + * Sets the file location where this task was defined. * - * @param file the new file value + * @param location the new location value */ - public void setFile(File file) { - this.file = file; + public void setLocation(Location location) { + this.location = location; } /** - * Indicate if output is to be appended to the file + * Gets the project of the ProjectComponent * - * @param append true if output should be appended + * @return the project */ - public void setAppend(boolean append) { - this.append = append; + public Project getProject() { + return project; } /** - * Does the work. + * Gets the location of the ProjectComponent's associated model element + * in the build file * - * @throws TaskException if cannot output message + * @return the location of the associated model element */ - public void execute() throws TaskException { - if (file == null) { - log(message, logLevel); - } else { - FileWriter out = null; - try { - out = new FileWriter(file.getAbsolutePath(), append); - out.write(message, 0, message.length()); - } catch (IOException ioe) { - throw new TaskException(ioe); - } finally { - if (out != null) { - try { - out.close(); - } catch (IOException ioex) { - } - } - } - } + public Location getLocation() { + return location; } /** - * Set a multiline message. + * Initialise this component * - * @param msg the message + * @param context the core context for this component + * @exception ExecutionException if the component cannot be initialized */ - public void addText(String msg) { - message += msg; + public void init(AntContext context) throws ExecutionException { + this.context = context; + org.apache.ant.common.util.Location contextLocation + = context.getLocation(); + + if (contextLocation + == org.apache.ant.common.util.Location.UNKNOWN_LOCATION) { + location = Location.UNKNOWN_LOCATION; + } else { + location = new Location(contextLocation.getSource(), + contextLocation.getLineNumber(), + contextLocation.getColumnNumber()); + } + } + + /** Destroy this component */ + public void destroy() { + // nothing to do } /** - * testing only + * Log a message as a build event * - * @param frame testing + * @param message the message to be logged + * @param level the priority level of the message */ - public void addFrame(java.awt.Frame frame) { - log("Adding frame " + frame, MessageLevel.MSG_WARN); + public void log(String message, int level) { + context.log(message, level); } /** - * testing + * Log a message as a build event * - * @param runnable testing + * @param message the message to be logged */ - public void addRun(Runnable runnable) { - log("Adding runnable of type " - + runnable.getClass().getName(), MessageLevel.MSG_WARN); + public void log(String message) { + context.log(message, Project.MSG_INFO); } } diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectHelper.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectHelper.java new file mode 100644 index 000000000..5ecd1a5d9 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectHelper.java @@ -0,0 +1,135 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant; +import java.util.Hashtable; +import java.util.Vector; +import org.apache.ant.common.antlib.AntContext; +import org.apache.ant.common.service.DataService; +import org.apache.ant.common.util.AntException; +import org.apache.ant.common.util.ExecutionException; +import org.apache.ant.common.util.PropertyUtils; + +/** + * Ant1 ProjectHelper facade + * + * @author Conor MacNeill + * @created 31 January 2002 + */ +public class ProjectHelper { + /** + * This method will parse a string containing ${value} style property + * values into two lists. The first list is a collection of text + * fragments, while the other is a set of string property names null + * entries in the first list indicate a property reference from the + * second list. + * + * @param value the string to be parsed + * @param fragments the fragments parsed out of the string + * @param propertyRefs the property refs to be replaced + */ + public static void parsePropertyString(String value, Vector fragments, + Vector propertyRefs) { + try { + PropertyUtils.parsePropertyString(value, fragments, propertyRefs); + } catch (AntException e) { + throw new BuildException(e); + } + } + + /** + * 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. + * @param project the project object which contains the property values + * @return the string with the property references replaced with their + * project values + * @exception BuildException if there is a problem replacing the + * property values. + */ + public static String replaceProperties(Project project, String value) + throws BuildException { + try { + AntContext context = project.getContext(); + DataService dataService + = (DataService)context.getCoreService(DataService.class); + return dataService.replacePropertyRefs(value); + } catch (ExecutionException e) { + throw new BuildException(e); + } + } + + /** + * 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. + * @param project the project object + * @param keys the collection of property values to use + * @return the string with the property references replaced with their + * project values + */ + public static String replaceProperties(Project project, String value, + Hashtable keys) { + try { + AntContext context = project.getContext(); + DataService dataService + = (DataService)context.getCoreService(DataService.class); + return dataService.replacePropertyRefs(value, keys); + } catch (ExecutionException e) { + throw new BuildException(e); + } + } +} + diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Target.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Target.java new file mode 100644 index 000000000..26fa2f595 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Target.java @@ -0,0 +1,64 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant; + +/** + * Ant1 Target facade. + * + * @author Conor MacNeill + * @created 31 January 2002 + */ +public class Target { +} + diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/task/TaskException.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java old mode 100755 new mode 100644 similarity index 56% rename from proposal/mutant/src/java/common/org/apache/ant/common/task/TaskException.java rename to proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java index 20b0d0c83..284949b68 --- a/proposal/mutant/src/java/common/org/apache/ant/common/task/TaskException.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java @@ -51,84 +51,107 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.common.task; - -import org.apache.ant.common.util.AntException; -import org.apache.ant.common.util.Location; +package org.apache.tools.ant; /** - * An TaskException indicates a problem while executing tasks in a build + * Ant1 Task facade * * @author Conor MacNeill - * @created 16 January 2002 + * @created 31 January 2002 */ -public class TaskException extends AntException { +public abstract class Task extends ProjectComponent + implements org.apache.ant.common.antlib.Task { + /** the name of this task */ + protected String taskName; + /** The target with which this target is associated */ + protected Target target = null; + /** The type of this target */ + protected String taskType = null; + /** The description of this task */ + protected String description = null; + /** - * Constructs an exception with the given descriptive message. + * Set the name to use in logging messages. * - * @param msg Description of or information about the exception. + * @param name the name to use in logging messages. */ - public TaskException(String msg) { - super(msg); + public void setTaskName(String name) { + this.taskName = name; } /** - * Constructs an exception with the given descriptive message and a - * location in a file. + * Sets the target object of this task. * - * @param msg Description of or information about the exception. - * @param location Location in the project file where the error occured. + * @param target Target in whose scope this task belongs. */ - public TaskException(String msg, Location location) { - super(msg, location); + public void setOwningTarget(Target target) { + this.target = target; } + /** + * Sets a description of the current action. It will be usefull in + * commenting what we are doing. + * + * @param desc the new description value + */ + public void setDescription(String desc) { + description = desc; + } /** - * Constructs an exception with the given message and exception as a - * root cause. + * Get the name to use in logging messages. * - * @param msg Description of or information about the exception. - * @param cause Throwable that might have cause this one. + * @return the name to use in logging messages. */ - public TaskException(String msg, Throwable cause) { - super(msg, cause); + public String getTaskName() { + return taskName; } /** - * Constructs an exception with the given message and exception as a - * root cause and a location in a file. + * Get the Target to which this task belongs * - * @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. + * @return the task's target. */ - public TaskException(String msg, Throwable cause, Location location) { - super(msg, cause, location); + public Target getOwningTarget() { + return target; } + /** + * Gets the description of the Task + * + * @return the task's description + */ + public String getDescription() { + return description; + } /** - * Constructs an exception with the given exception as a root cause. + * Handle output captured for this task * - * @param cause Exception that might have caused this one. + * @param line the captured output */ - public TaskException(Throwable cause) { - super(cause); + protected void handleOutput(String line) { + log(line, Project.MSG_INFO); } + /** + * Handle error output captured for this task + * + * @param line the captured error output + */ + protected void handleErrorOutput(String line) { + log(line, Project.MSG_ERR); + } /** - * Constructs an exception with the given exception as a root cause and - * a location in a file. + * Set the name with which the task has been invoked. * - * @param cause Exception that might have cause this one. - * @param location Location in the project file where the error occured. + * @param type the name the task has been invoked as. */ - public TaskException(Throwable cause, Location location) { - super(cause, location); + void setTaskType(String type) { + this.taskType = type; } } diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/TaskContainer.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/TaskContainer.java new file mode 100644 index 000000000..39adddd3c --- /dev/null +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/TaskContainer.java @@ -0,0 +1,64 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant; + +/** + * TaskContainer facade + * + * @author Conor MacNeill + * @created 31 January 2002 + */ +public interface TaskContainer { +} + diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/types/DataType.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/types/DataType.java new file mode 100644 index 000000000..9815b0356 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/types/DataType.java @@ -0,0 +1,234 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant.types; +import java.util.Stack; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; + +import org.apache.tools.ant.ProjectComponent; + +/** + * Ant1 DataType facade + * + * @author Conor MacNeill + * @created 31 January 2002 + */ +public abstract class DataType extends ProjectComponent + implements org.apache.ant.common.antlib.DataType { + + /** The description the user has set. */ + protected String description = null; + /** Value to the refid attribute. */ + protected Reference ref = null; + /** + * Are we sure we don't hold circular references?

+ * + * Subclasses are responsible for setting this value to false if we'd + * need to investigate this condition (usually because a child element + * has been added that is a subclass of DataType).

+ */ + protected boolean checked = true; + + /** + * Sets a description of the current data type. It will be useful in + * commenting what we are doing. + * + * @param desc the new description value + */ + public void setDescription(String desc) { + description = desc; + } + + /** + * Set the value of the refid attribute.

+ * + * Subclasses may need to check whether any other attributes have been + * set as well or child elements have been created and thus override + * this method. if they do the must call super.setRefid. + *

+ * + * @param ref the new refid value + */ + public void setRefid(Reference ref) { + this.ref = ref; + checked = false; + } + + /** + * Sets the id of the DataType + * + * @param id the name under which the data type is to be referenced + */ + public void setId(String id) { + project.addReference(id, this); + } + + /** + * Return the description for the current data type. + * + * @return the data type's description + */ + public String getDescription() { + return description; + } + + /** + * Has the refid attribute of this element been set? + * + * @return true if this data type is a refeence to another instance + */ + public boolean isReference() { + return ref != null; + } + + /** + * Performs the check for circular references and returns the referenced + * object. + * + * @param requiredClass the class which the object being referenced must + * support + * @param dataTypeName the name of the data type + * @return the refenced object + */ + protected Object getCheckedRef(Class requiredClass, String dataTypeName) { + if (!checked) { + Stack stk = new Stack(); + stk.push(this); + dieOnCircularReference(stk, getProject()); + } + + Object o = ref.getReferencedObject(getProject()); + if (!(requiredClass.isAssignableFrom(o.getClass()))) { + String msg = ref.getRefId() + " doesn\'t denote a " + dataTypeName; + throw new BuildException(msg); + } else { + return o; + } + } + + /** + * Check to see whether any DataType we hold references to is included + * in the Stack (which holds all DataType instances that directly or + * indirectly reference this instance, including this instance itself). + *

+ * + * If one is included, throw a BuildException created by {@link + * #circularReference circularReference}.

+ * + * This implementation is appropriate only for a DataType that cannot + * hold other DataTypes as children.

+ * + * The general contract of this method is that it shouldn't do anything + * if {@link #checked checked} is true and set it to true + * on exit.

+ * + * @param stk stack used to check for a circular reference + * @param p the project + * @exception BuildException if this data type is a reference to an + * instance which depends on this data type + */ + protected void dieOnCircularReference(Stack stk, Project p) + throws BuildException { + + if (checked || !isReference()) { + return; + } + Object o = ref.getReferencedObject(p); + + if (o instanceof DataType) { + if (stk.contains(o)) { + throw circularReference(); + } else { + stk.push(o); + ((DataType)o).dieOnCircularReference(stk, p); + stk.pop(); + } + } + checked = true; + } + + /** + * Creates an exception that indicates that refid has to be the only + * attribute if it is set. + * + * @return an appropriate excpetion instance + */ + protected BuildException tooManyAttributes() { + return new BuildException("You must not specify more than " + + "one attribute when using refid"); + } + + /** + * Creates an exception that indicates that this XML element must not + * have child elements if the refid attribute is set. + * + * @return an appropriate excpetion instance + */ + protected BuildException noChildrenAllowed() { + return new BuildException("You must not specify nested " + + "elements when using refid"); + } + + /** + * Creates an exception that indicates the user has generated a loop of + * data types referencing each other. + * + * @return an appropriate excpetion instance + */ + protected BuildException circularReference() { + return new BuildException("This data type contains a " + + "circular reference."); + } +} + diff --git a/proposal/mutant/src/java/antlibs/file/antlib.xml b/proposal/mutant/src/java/antlibs/file/antlib.xml deleted file mode 100755 index b545e73a1..000000000 --- a/proposal/mutant/src/java/antlibs/file/antlib.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/proposal/mutant/src/java/antlibs/io/antlib.xml b/proposal/mutant/src/java/antlibs/io/antlib.xml deleted file mode 100755 index 67b5b729b..000000000 --- a/proposal/mutant/src/java/antlibs/io/antlib.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/proposal/mutant/src/java/antlibs/system/antlib.xml b/proposal/mutant/src/java/antlibs/system/antlib.xml new file mode 100644 index 000000000..8cac5324f --- /dev/null +++ b/proposal/mutant/src/java/antlibs/system/antlib.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/FileConverter.java b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/FileConverter.java old mode 100755 new mode 100644 similarity index 85% rename from proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/FileConverter.java rename to proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/FileConverter.java index e535c1223..107662f92 --- a/proposal/mutant/src/java/antlibs/io/code/org/apache/ant/taskdef/io/FileConverter.java +++ b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/FileConverter.java @@ -51,12 +51,13 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.taskdef.io; +package org.apache.ant.antlib.system; import java.io.File; -import org.apache.ant.common.converter.AbstractConverter; -import org.apache.ant.common.converter.ConversionException; +import org.apache.ant.common.antlib.AbstractConverter; +import org.apache.ant.common.util.ExecutionException; import org.apache.ant.common.util.AntException; +import org.apache.ant.common.service.FileService; /** * A converter to convert to File objects, resolving against the @@ -84,14 +85,16 @@ public class FileConverter extends AbstractConverter { * @param value The value to be converted * @param type the desired type of the converted object * @return the value of the converted object - * @exception ConversionException if the conversion cannot be made + * @exception ExecutionException if the conversion cannot be made */ - public Object convert(String value, Class type) throws ConversionException { + public Object convert(String value, Class type) throws ExecutionException { try { - return getContext().resolveFile(value); + FileService fileService + = (FileService)getContext().getCoreService(FileService.class); + return fileService.resolveFile(value); } catch (AntException e) { - throw new ConversionException("Unable to resolve file: " + throw new ExecutionException("Unable to resolve file: " + value, e); } } diff --git a/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Import.java b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Import.java new file mode 100644 index 000000000..1313b4431 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Import.java @@ -0,0 +1,74 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antlib.system; + +import org.apache.ant.common.antlib.AbstractTask; + +/** + * Task to import a component or components from a library + * + * @author Conor MacNeill + * @created 27 January 2002 + */ +public class Import extends AbstractTask { + /** The Ant LIbrary Id from which the component must be imported */ + private String antlibId = null; + /** The name of the component to be imported */ + private String componentName = null; + + /** Do thw work and import the components */ + public void execute() { + } +} + diff --git a/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/LibPath.java b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/LibPath.java new file mode 100644 index 000000000..115b7f67e --- /dev/null +++ b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/LibPath.java @@ -0,0 +1,72 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antlib.system; + +import org.apache.ant.common.antlib.AbstractTask; + +/** + * Task to add an additional classpath search path to the given library + * + * @author Conor MacNeill + * @created 27 January 2002 + */ +public class LibPath extends AbstractTask { + /** The id of the library for which this additional path is being set */ + private String libraryId; + + /** Add the libpath to the set of paths associated with the library */ + public void execute() { + } +} + diff --git a/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/LoadLib.java b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/LoadLib.java new file mode 100644 index 000000000..431956636 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/LoadLib.java @@ -0,0 +1,162 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antlib.system; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import org.apache.ant.common.antlib.AbstractTask; +import org.apache.ant.common.antlib.AntContext; +import org.apache.ant.common.service.ComponentService; +import org.apache.ant.common.util.ExecutionException; +import org.apache.ant.init.InitUtils; + +/** + * Load an AntLibrary and optionally import all its components + * + * @author Conor MacNeill + * @created 29 January 2002 + */ +public class LoadLib extends AbstractTask { + /** Flag which indicates if all components should be imported */ + private boolean importAll; + + /** + * This is the location, either file or URL of the library or libraries + * to be loaded + */ + private URL url; + + /** + * Sets the URL of the library to be loaded + * + * @param url the URL from which the library is to be loaded + * @exception ExecutionException if the URL cannot be set + */ + public void setURL(URL url) throws ExecutionException { + checkNullURL(); + this.url = url; + } + + /** + * Set the file from which the library should be loaded. + * + * @param file the file from which the library should be loaded + * @exception ExecutionException if the file attribute cannot be set + */ + public void setFile(File file) throws ExecutionException { + checkNullURL(); + try { + this.url = InitUtils.getFileURL(file); + } catch (MalformedURLException e) { + throw new ExecutionException(e); + } + } + + /** + * Set the dir in which to search for AntLibraries. + * + * @param dir the dir from which all Ant Libraries found will be loaded. + * @exception ExecutionException if the dir attribute cannot be set + */ + public void setDir(File dir) throws ExecutionException { + checkNullURL(); + try { + this.url = InitUtils.getFileURL(dir); + } catch (MalformedURLException e) { + throw new ExecutionException(e); + } + } + + /** + * Indicate whether all components from the library should be imported + * + * @param importAll true if all components in the library should be + * imported. + */ + public void setImportAll(boolean importAll) { + this.importAll = importAll; + } + + + /** + * Load the library or libraries and optiinally import their components + * + * @exception ExecutionException if the library or libraries cannot be + * loaded. + */ + public void execute() throws ExecutionException { + if (url == null) { + throw new ExecutionException("A location from which to load " + + "libraries must be provided"); + } + AntContext context = getContext(); + ComponentService componentService = (ComponentService) + context.getCoreService(ComponentService.class); + componentService.loadLib(url.toString(), importAll); + } + + /** + * Check if any of the location specifying attributes have already been + * set. + * + * @exception ExecutionException if the search URL has already been set + */ + private void checkNullURL() throws ExecutionException { + if (url != null) { + throw new ExecutionException("Location of library has already been " + + "set. Please use only one of file, dir or url attributes"); + } + } +} + diff --git a/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/PrimitiveConverter.java b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/PrimitiveConverter.java new file mode 100644 index 000000000..4009e43c5 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/PrimitiveConverter.java @@ -0,0 +1,113 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antlib.system; + +import org.apache.ant.common.antlib.AbstractConverter; +import org.apache.ant.common.util.ExecutionException; +import org.apache.ant.common.util.PropertyUtils; + +/** + * A converter to convert to Java's primitie types + * + * @author Conor MacNeill + */ +public class PrimitiveConverter extends AbstractConverter { + + /** + * Get the list of classes this converter is able to convert to. + * + * @return an array of Class objects representing the classes this + * converter handles. + */ + public Class[] getTypes() { + return new Class[] { + Character.class, Character.TYPE, Byte.TYPE, Short.TYPE, + Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, + Boolean.class, Boolean.TYPE}; + } + + /** + * Convert a string from the value given to an instance of the given + * type. + * + * @param value The value to be converted + * @param type the desired type of the converted object + * @return the value of the converted object + * @exception ExecutionException if the conversion cannot be made + */ + public Object convert(String value, Class type) throws ExecutionException { + if (type.equals(Character.class) + || type.equals(Character.TYPE)) { + return new Character(value.charAt(0)); + } else if (type.equals(Byte.TYPE)) { + return new Byte(value); + } else if (type.equals(Short.TYPE)) { + return new Short(value); + } else if (type.equals(Integer.TYPE)) { + return new Integer(value); + } else if (type.equals(Long.TYPE)) { + return new Long(value); + } else if (type.equals(Float.TYPE)) { + return new Float(value); + } else if (type.equals(Double.TYPE)) { + return new Double(value); + } else if (type.equals(Boolean.class) + || type.equals(Boolean.TYPE)) { + return new Boolean(PropertyUtils.toBoolean(value)); + } + throw new ExecutionException("This converter does not handle " + + type.getName()); + } +} + diff --git a/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Taskdef.java b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Taskdef.java new file mode 100644 index 000000000..a736dd107 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Taskdef.java @@ -0,0 +1,69 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antlib.system; + +import org.apache.ant.common.antlib.AbstractTask; + +/** + * Define a new task for use in the build file + * + * @author Conor MacNeill + * @created 27 January 2002 + */ +public class Taskdef extends AbstractTask { + /** Define the new task */ + public void execute() { + } +} + diff --git a/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Typedef.java b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Typedef.java new file mode 100644 index 000000000..4577e6f08 --- /dev/null +++ b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/Typedef.java @@ -0,0 +1,69 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.antlib.system; + +import org.apache.ant.common.antlib.AbstractTask; + +/** + * Define a new type to be used in the build + * + * @author Conor MacNeill + * @created 27 January 2002 + */ +public class Typedef extends AbstractTask { + /** define the type */ + public void execute() { + } +} + diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TypeContext.java b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/URLConverter.java old mode 100755 new mode 100644 similarity index 70% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TypeContext.java rename to proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/URLConverter.java index b7ceadcb2..e48f67d02 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TypeContext.java +++ b/proposal/mutant/src/java/antlibs/system/code/org/apache/ant/antlib/system/URLConverter.java @@ -51,41 +51,46 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.execution; -import org.apache.ant.common.task.DataType; -import org.apache.ant.antcore.model.ModelElement; +package org.apache.ant.antlib.system; + +import java.net.URL; +import java.net.MalformedURLException; +import org.apache.ant.common.antlib.AbstractConverter; +import org.apache.ant.common.util.ExecutionException; /** - * This is the core's implementation of the AntContext for Types + * A converter to convert to URLs relative to the project base dir * * @author Conor MacNeill - * @created 20 January 2002 */ -public class TypeContext extends ExecutionContext { - /** The task being managed by this context */ - private DataType typeInstance; +public class URLConverter extends AbstractConverter { /** - * get the DataType instance associated with this context. + * Get the list of classes this converter is able to convert to. * - * @return the DataType instance + * @return an array of Class objects representing the classes this + * converter handles. */ - public DataType getInstance() { - return typeInstance; + public Class[] getTypes() { + return new Class[]{URL.class}; } /** - * Initilaise the context and associate it with the given DataType - * instance + * Convert a string from the value given to an instance of the given + * type. * - * @param typeInstance the DataType instance - * @param modelElement the model element associated with this context + * @param value The value to be converted + * @param type the desired type of the converted object + * @return the value of the converted object + * @exception ExecutionException if the conversion cannot be made */ - public void init(DataType typeInstance, ModelElement modelElement) { - this.typeInstance = typeInstance; - setModelElement(modelElement); - typeInstance.init(this); + public Object convert(String value, Class type) throws ExecutionException { + try { + return new URL(value); + } + catch (MalformedURLException e) { + throw new ExecutionException(e); + } } - } diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/BuildLogger.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/BuildLogger.java index e02360255..eeb2dcdf0 100755 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/BuildLogger.java +++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/BuildLogger.java @@ -54,7 +54,7 @@ package org.apache.ant.cli; import java.io.PrintStream; -import org.apache.ant.antcore.event.BuildListener; +import org.apache.ant.common.event.BuildListener; /** * Interface used by Ant to log the build output. A build logger is a build diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java index d17afdb0b..6f762e350 100755 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java +++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java @@ -53,6 +53,7 @@ */ package org.apache.ant.cli; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; @@ -61,20 +62,23 @@ import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.apache.ant.cli.xml.XMLProjectParser; -import org.apache.ant.common.util.AntException; -import org.apache.ant.common.util.Location; -import org.apache.ant.common.util.MessageLevel; -import org.apache.ant.antcore.event.BuildListener; +import org.apache.ant.antcore.config.AntConfig; +import org.apache.ant.antcore.config.AntConfigHandler; import org.apache.ant.antcore.execution.ExecutionManager; import org.apache.ant.antcore.model.Project; +import org.apache.ant.antcore.model.xmlparser.XMLProjectParser; import org.apache.ant.antcore.util.ConfigException; +import org.apache.ant.antcore.xml.ParseContext; import org.apache.ant.antcore.xml.XMLParseException; -import org.apache.ant.init.InitUtils; +import org.apache.ant.common.event.BuildListener; +import org.apache.ant.common.util.AntException; +import org.apache.ant.common.util.Location; +import org.apache.ant.common.util.MessageLevel; import org.apache.ant.init.InitConfig; +import org.apache.ant.init.InitUtils; /** - * This is the command line front end to end. It drives the core + * This is the command line front end. It drives the core. * * @author Conor MacNeill * @created 9 January 2002 @@ -112,7 +116,7 @@ public class Commandline { private String loggerClassname = null; /** Our current message output status. Follows MessageLevel values */ - private int messageOutputLevel = MessageLevel.MSG_VERBOSE; + private int messageOutputLevel = MessageLevel.MSG_INFO; /** * Start the command line front end for mutant. @@ -163,41 +167,98 @@ public class Commandline { } } + /** + * Get the AntConfig from the given config area if it is available + * + * @param configArea the config area from which the config may be read + * @return the AntConfig instance representing the config info read in + * from the config area. May be null if the AntConfig is not + * present + * @exception ConfigException if the URL for the config file cannotbe + * formed. + */ + private AntConfig getAntConfig(File configArea) throws ConfigException { + try { + File configFile = new File(configArea, "antconfig.xml"); + URL configFileURL = InitUtils.getFileURL(configFile); + + ParseContext context = new ParseContext(); + AntConfigHandler configHandler = new AntConfigHandler(); + + context.parse(configFileURL, "antconfig", configHandler); + + return configHandler.getAntConfig(); + } catch (MalformedURLException e) { + throw new ConfigException("Unable to form URL to read config from " + + configArea, e); + } catch (XMLParseException e) { + if (!(e.getCause() instanceof FileNotFoundException)) { + throw new ConfigException("Unable to parse config file from " + + configArea, e); + } + // ignore missing config files + return null; + } + } + /** * Start the command line front end for mutant. * * @param args the commandline arguments - * @param config the initialisation configuration + * @param initConfig Ant's initialization configuration */ - private void process(String[] args, InitConfig config) { - this.config = config; + private void process(String[] args, InitConfig initConfig) { + this.config = initConfig; + System.out.println("Ant Home is " + initConfig.getAntHome()); try { parseArguments(args); + + AntConfig userConfig = getAntConfig(initConfig.getUserConfigArea()); + AntConfig systemConfig + = getAntConfig(initConfig.getSystemConfigArea()); + + AntConfig config = systemConfig; + if (config == null) { + config = userConfig; + } else if (userConfig != null) { + config.merge(userConfig); + } + + if (!buildFileURL.getProtocol().equals("file") + && !config.isRemoteProjectAllowed()) { + throw new ConfigException("Remote Projects are not allowed: " + + buildFileURL); + } + Project project = parseProject(); // create the execution manager to execute the build - ExecutionManager executionManager = new ExecutionManager(config); + ExecutionManager executionManager + = new ExecutionManager(initConfig, config); addBuildListeners(executionManager); executionManager.runBuild(project, targets); - } catch (AntException e) { - Location location = e.getLocation(); - Throwable cause = e.getCause(); - System.out.println(e.getMessage()); - - if (cause != null) { - System.out.print("Root cause: " + cause.getClass().getName()); - if (!cause.getMessage().equals(e.getMessage())) { - System.out.print(": " + cause.getMessage()); + } catch (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) { + System.out.print(location); } - System.out.println(); - } + System.out.println(e.getMessage()); - e.printStackTrace(); + if (messageOutputLevel >= MessageLevel.MSG_VERBOSE) { + t.printStackTrace(); + } + + if (cause != null) { + System.out.println("Root cause: " + cause.toString()); + } + } else { + t.printStackTrace(System.err); + } - System.exit(1); - } catch (Throwable t) { - t.printStackTrace(); System.exit(1); } } @@ -224,20 +285,21 @@ public class Commandline { */ private void parseArguments(String[] args) throws ConfigException { - for (int i = 0; i < args.length; i++) { - String arg = args[i]; + + int i = 0; + while (i < args.length) { + String arg = args[i++]; if (arg.equals("-buildfile") || arg.equals("-file") || arg.equals("-f")) { try { - String url = args[i + 1]; + String url = args[i++]; if (url.indexOf(":") == -1) { // We convert any hash characters to their URL escape. buildFileURL = InitUtils.getFileURL(new File(url)); } else { buildFileURL = new URL(url); } - i++; } catch (MalformedURLException e) { System.err.println("Buildfile is not valid: " + e.getMessage()); @@ -249,8 +311,7 @@ public class Commandline { } } else if (arg.equals("-logfile") || arg.equals("-l")) { try { - File logFile = new File(args[i + 1]); - i++; + File logFile = new File(args[i++]); out = new PrintStream(new FileOutputStream(logFile)); err = out; } catch (IOException ioe) { @@ -270,8 +331,7 @@ public class Commandline { messageOutputLevel = MessageLevel.MSG_VERBOSE; } else if (arg.equals("-listener")) { try { - listeners.add(args[i + 1]); - i++; + listeners.add(args[i++]); } catch (ArrayIndexOutOfBoundsException aioobe) { System.err.println("You must specify a classname when " + "using the -listener argument"); @@ -284,7 +344,7 @@ public class Commandline { return; } try { - loggerClassname = args[++i]; + loggerClassname = args[i++]; } catch (ArrayIndexOutOfBoundsException aioobe) { System.err.println("You must specify a classname when " + "using the -logger argument"); diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java index 2bdc977eb..c3bc61f8f 100755 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java +++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java @@ -57,7 +57,7 @@ import java.io.PrintStream; import org.apache.ant.common.util.AntException; import org.apache.ant.common.util.Location; import org.apache.ant.common.util.MessageLevel; -import org.apache.ant.antcore.event.BuildEvent; +import org.apache.ant.common.event.BuildEvent; import org.apache.ant.antcore.model.BuildElement; import org.apache.ant.antcore.model.Target; @@ -170,7 +170,7 @@ public class DefaultLogger implements BuildLogger { out.println(e.getMessage()); if (messageOutputLevel >= MessageLevel.MSG_VERBOSE) { - t.printStackTrace(); + t.printStackTrace(out); } if (cause != null) { @@ -207,7 +207,7 @@ public class DefaultLogger implements BuildLogger { break; case BuildEvent.TARGET_STARTED: if (MessageLevel.MSG_INFO <= messageOutputLevel) { - Target target = (Target)event.getModelElement(); + Target target = (Target)event.getSource(); out.println(lSep + target.getName() + ":"); } break; @@ -223,10 +223,10 @@ public class DefaultLogger implements BuildLogger { // Filter out messages based on priority if (event.getPriority() <= messageOutputLevel - && event.getModelElement() instanceof BuildElement) { + && event.getSource() instanceof BuildElement) { // Print out the name of the task if we're in one BuildElement buildElement - = (BuildElement)event.getModelElement(); + = (BuildElement)event.getSource(); String name = buildElement.getType(); if (!emacsMode) { diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/converter/AbstractConverter.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractConverter.java old mode 100755 new mode 100644 similarity index 85% rename from proposal/mutant/src/java/common/org/apache/ant/common/converter/AbstractConverter.java rename to proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractConverter.java index e1e07db78..b7a461b58 --- a/proposal/mutant/src/java/common/org/apache/ant/common/converter/AbstractConverter.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractConverter.java @@ -51,9 +51,8 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.common.converter; +package org.apache.ant.common.antlib; -import org.apache.ant.common.context.AntContext; /** * Abstract implementation of the Converter interface @@ -82,5 +81,19 @@ public abstract class AbstractConverter implements Converter { protected AntContext getContext() { return context; } + + /** + * This method allows a converter to indicate whether it can create + * the given type which is a sub-type of one of the converter's main + * types indicated in getTypes. Most converters can return false here. + * + * @param subType the sub-type + * @return true if this converter can convert a string representation to + * the given subclass of one of its main class + */ + public boolean canConvertSubType(Class subType) { + return false; + } + } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/task/AbstractTask.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java old mode 100755 new mode 100644 similarity index 97% rename from proposal/mutant/src/java/common/org/apache/ant/common/task/AbstractTask.java rename to proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java index c0e488e38..6c8e705a3 --- a/proposal/mutant/src/java/common/org/apache/ant/common/task/AbstractTask.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java @@ -51,8 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.common.task; -import org.apache.ant.common.context.AntContext; +package org.apache.ant.common.antlib; /** * Abstract implementation of the Task interface diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java new file mode 100644 index 000000000..67d475c81 --- /dev/null +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java @@ -0,0 +1,104 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.common.antlib; +import java.io.File; + +import org.apache.ant.common.util.ExecutionException; +import org.apache.ant.common.util.Location; + +/** + * The AntContext is the interface through which the Ant container and the + * Ant components communicate. Common operations are provided directly in + * this interface. Other core services are available through the generic + * service objects supported by the core. + * + * @author Conor MacNeill + * @created 14 January 2002 + */ +public interface AntContext { + /** + * Log a message + * + * @param message the message to be logged + * @param level the priority level of the message + */ + void log(String message, int level); + + /** + * Get a instance of the specified service interface with which to + * interact with the core. + * + * @param serviceInterfaceClass the class object for the required + * interface + * @return an instance of the requested interface + * @exception ExecutionException if the core service is not supported + */ + Object getCoreService(Class serviceInterfaceClass) + throws ExecutionException; + + /** + * Get the build file location with which this context is associated. + * + * @return the associated build file location + */ + Location getLocation(); + + /** + * Get the basedir for the current execution + * + * @return the base directory for this execution of Ant + */ + File getBaseDir(); +} + diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntLibFactory.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntLibFactory.java new file mode 100644 index 000000000..040a36ed4 --- /dev/null +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntLibFactory.java @@ -0,0 +1,116 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.common.antlib; +import org.apache.ant.common.util.ExecutionException; + +/** + * An Ant Library Factory is a class is used to create instances of the + * classes in the AntLibrary. An separate instance of the factory will be + * created by each ExecutiuonFrame which uses this library. The factory will + * be created before any instances are required. + * + * @author Conor MacNeill + * @created 31 January 2002 + */ +public interface AntLibFactory { + /** + * Create an instance of the given type class + * + * @param typeClass the class for which an instance is required + * @return an instance of the required class + * @exception InstantiationException if the class cannot be instantiated + * @exception IllegalAccessException if the instance cannot be accessed + * @exception ExecutionException if there is a problem creating the type + */ + Object createTypeInstance(Class typeClass) + throws InstantiationException, IllegalAccessException, + ExecutionException; + + /** + * Initialise the factory + * + * @param context the factory's context + * @exception ExecutionException if the factory cannot be initialized + */ + void init(AntContext context) throws ExecutionException; + + /** + * Create an instance of the given task class + * + * @param taskClass the class for which an instance is required + * @return an instance of the required class + * @exception InstantiationException if the class cannot be instantiated + * @exception IllegalAccessException if the instance cannot be accessed + * @exception ExecutionException if there is a problem creating the task + */ + Object createTaskInstance(Class taskClass) + throws InstantiationException, IllegalAccessException, + ExecutionException; + + /** + * Create an instance of the given converter class + * + * @param converterClass the converter class for which an instance is + * required + * @return a converter instance + * @exception InstantiationException if the class cannot be instantiated + * @exception IllegalAccessException if the instance cannot be accessed + * @exception ExecutionException if there is a problem creating the + * converter + */ + Converter createConverter(Class converterClass) + throws InstantiationException, IllegalAccessException, + ExecutionException; +} + diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/converter/Converter.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Converter.java old mode 100755 new mode 100644 similarity index 83% rename from proposal/mutant/src/java/common/org/apache/ant/common/converter/Converter.java rename to proposal/mutant/src/java/common/org/apache/ant/common/antlib/Converter.java index 07c4f4548..b697df883 --- a/proposal/mutant/src/java/common/org/apache/ant/common/converter/Converter.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Converter.java @@ -51,9 +51,9 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.common.converter; +package org.apache.ant.common.antlib; -import org.apache.ant.common.context.AntContext; +import org.apache.ant.common.util.ExecutionException; /** * Convert between a string and a data type @@ -69,9 +69,9 @@ public interface Converter { * @param value The value to be converted * @param type the desired type of the converted object * @return the value of the converted object - * @exception ConversionException if the conversion cannot be made + * @exception ExecutionException if the conversion cannot be made */ - Object convert(String value, Class type) throws ConversionException; + Object convert(String value, Class type) throws ExecutionException; /** * Initialise the converter. The converter may use the AntContext to @@ -88,5 +88,17 @@ public interface Converter { * converter handles. */ Class[] getTypes(); + + + /** + * This method allows a converter to indicate whether it can create + * the given type which is a sub-type of one of the converter's main + * types indicated in getTypes. Most converters can return false here. + * + * @param subType the sub-type + * @return true if this converter can convert a string representation to + * the given subclass of one of its main class + */ + boolean canConvertSubType(Class subType); } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/task/DataType.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/DataType.java old mode 100755 new mode 100644 similarity index 89% rename from proposal/mutant/src/java/common/org/apache/ant/common/task/DataType.java rename to proposal/mutant/src/java/common/org/apache/ant/common/antlib/DataType.java index 256e154a6..5da1bb939 --- a/proposal/mutant/src/java/common/org/apache/ant/common/task/DataType.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/DataType.java @@ -51,8 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.common.task; -import org.apache.ant.common.context.AntContext; +package org.apache.ant.common.antlib; /** * This is the interface used to descibe Ant types. A class used as a @@ -62,13 +61,6 @@ import org.apache.ant.common.context.AntContext; * @author Conor MacNeill * @created 20 January 2002 */ -public interface DataType { - /** - * Initialise the type instance. The type instance may use the - * AntContext to request services from the Ant core. - * - * @param context the type's context - */ - void init(AntContext context); +public interface DataType extends ExecutionComponent { } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/task/Task.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/ExecutionComponent.java old mode 100755 new mode 100644 similarity index 85% rename from proposal/mutant/src/java/common/org/apache/ant/common/task/Task.java rename to proposal/mutant/src/java/common/org/apache/ant/common/antlib/ExecutionComponent.java index 1bb2c41f4..e80392f52 --- a/proposal/mutant/src/java/common/org/apache/ant/common/task/Task.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/ExecutionComponent.java @@ -51,32 +51,24 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.common.task; -import org.apache.ant.common.context.AntContext; +package org.apache.ant.common.antlib; +import org.apache.ant.common.util.ExecutionException; /** - * The Task interface defines the methods that a Task must implement. + * An execution component is a component from an AntLibrary which is used in the + * execution of an Ant build. A component can have a context. * * @author Conor MacNeill - * @created 16 January 2002 + * @created 1 February 2002 */ -public interface Task { +public interface ExecutionComponent { /** * Initialise the task. The task may use the AntContext to request * services from the Ant core. * * @param context the Task's context + * @exception ExecutionException if the component cannot be initialised */ - void init(AntContext context); - - /** - * Execute the task. - * - * @exception TaskException if the task has a problem executing. - */ - void execute() throws TaskException; - - /** Task is about to be cleaned up */ - void destroy(); + void init(AntContext context) throws ExecutionException; } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/converter/ConversionException.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/StandardLibFactory.java old mode 100755 new mode 100644 similarity index 54% rename from proposal/mutant/src/java/common/org/apache/ant/common/converter/ConversionException.java rename to proposal/mutant/src/java/common/org/apache/ant/common/antlib/StandardLibFactory.java index b92185b36..8a5ba729e --- a/proposal/mutant/src/java/common/org/apache/ant/common/converter/ConversionException.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/StandardLibFactory.java @@ -51,85 +51,72 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.common.converter; - -import org.apache.ant.common.util.AntException; -import org.apache.ant.common.util.Location; +package org.apache.ant.common.antlib; +import org.apache.ant.common.util.ExecutionException; /** - * Exception class for problems when converting values + * Standard Ant Library Factory * * @author Conor MacNeill - * @created 20 January 2002 + * @created 1 February 2002 + * @see AntLibFactory */ -public class ConversionException extends AntException { +public class StandardLibFactory implements AntLibFactory { /** - * Constructs an exception with the given descriptive message. + * Create an instance of the given task class * - * @param msg Description of or information about the exception. + * @param taskClass the class for which an instance is required + * @return an instance of the required class + * @exception InstantiationException if the class cannot be instantiated + * @exception IllegalAccessException if the instance cannot be accessed + * @exception ExecutionException if there is a problem creating the task */ - public ConversionException(String msg) { - super(msg); + public Object createTaskInstance(Class taskClass) + throws InstantiationException, IllegalAccessException, + ExecutionException { + return taskClass.newInstance(); } - /** - * Constructs an exception with the given descriptive message and a - * location in a file. + * Create an instance of the given type class * - * @param msg Description of or information about the exception. - * @param location Location in the project file where the error occured. + * @param typeClass the class for which an instance is required + * @return an instance of the required class + * @exception InstantiationException if the class cannot be instantiated + * @exception IllegalAccessException if the instance cannot be accessed + * @exception ExecutionException if there is a problem creating the type */ - public ConversionException(String msg, Location location) { - super(msg, location); + public Object createTypeInstance(Class typeClass) + throws InstantiationException, IllegalAccessException, + ExecutionException { + return typeClass.newInstance(); } - /** - * Constructs an exception with the given message and exception as a - * root cause. + * Initilaise the factory * - * @param msg Description of or information about the exception. - * @param cause Throwable that might have cause this one. + * @param context the factory's context + * @exception ExecutionException if the factory cannot be initialized */ - public ConversionException(String msg, Throwable cause) { - super(msg, cause); + public void init(AntContext context) throws ExecutionException { + // do nothing } - /** - * Constructs an exception with the given message and exception as a - * root cause and a location in a file. + * Create an instance of the given converter class * - * @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. + * @param converterClass the converter class for which an instance is + * required + * @return a converter instance + * @exception InstantiationException if the class cannot be instantiated + * @exception IllegalAccessException if the instance cannot be accessed + * @exception ExecutionException if there is a problem creating the + * converter */ - public ConversionException(String msg, Throwable cause, Location location) { - super(msg, cause, location); + public Converter createConverter(Class converterClass) + throws InstantiationException, IllegalAccessException, + ExecutionException { + return (Converter)converterClass.newInstance(); } - - - /** - * Constructs an exception with the given exception as a root cause. - * - * @param cause Exception that might have caused this one. - */ - public ConversionException(Throwable cause) { - super(cause); - } - - - /** - * Constructs an exception with the given exception as a root cause and - * a location in a file. - * - * @param cause Exception that might have cause this one. - * @param location Location in the project file where the error occured. - */ - public ConversionException(Throwable cause, Location location) { - super(cause, location); - } - } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java new file mode 100644 index 000000000..a3f8a3af5 --- /dev/null +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java @@ -0,0 +1,74 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.common.antlib; +import org.apache.ant.common.util.ExecutionException; + +/** + * The Task interface defines the methods that a Task must implement. + * + * @author Conor MacNeill + * @created 16 January 2002 + */ +public interface Task extends ExecutionComponent { + /** + * Execute the task. + * + * @exception ExecutionException if the task has a problem executing. + */ + void execute() throws ExecutionException; + + /** Task is about to be cleaned up */ + void destroy(); +} + diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/task/TaskContainer.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/TaskContainer.java old mode 100755 new mode 100644 similarity index 92% rename from proposal/mutant/src/java/common/org/apache/ant/common/task/TaskContainer.java rename to proposal/mutant/src/java/common/org/apache/ant/common/antlib/TaskContainer.java index 2397dce02..e7bdeb52a --- a/proposal/mutant/src/java/common/org/apache/ant/common/task/TaskContainer.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/TaskContainer.java @@ -51,7 +51,8 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.common.task; +package org.apache.ant.common.antlib; +import org.apache.ant.common.util.ExecutionException; /** * A TaskContainer is an object which can contain and manage ExecutionTasks. @@ -64,8 +65,8 @@ public interface TaskContainer { * Add a task to the container. * * @param task the task tobe added - * @exception TaskException if the container cannot add the task + * @exception ExecutionException if the container cannot add the task */ - void addTask(Task task) throws TaskException; + void addTask(Task task) throws ExecutionException; } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEvent.java b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildEvent.java old mode 100755 new mode 100644 similarity index 86% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEvent.java rename to proposal/mutant/src/java/common/org/apache/ant/common/event/BuildEvent.java index aec2fd0e1..281deead3 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildEvent.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildEvent.java @@ -51,10 +51,9 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.event; +package org.apache.ant.common.event; import java.util.EventObject; -import org.apache.ant.antcore.model.ModelElement; /** * A BuildEvent indicates the occurence of a significant event in the build. @@ -95,10 +94,10 @@ public class BuildEvent extends EventObject { * Create a build event. * * @param eventType the type of the buildEvent. - * @param modelElement the element with which this event is associated + * @param source the element with which this event is associated */ - public BuildEvent(ModelElement modelElement, int eventType) { - super(modelElement); + public BuildEvent(Object source, int eventType) { + super(source); this.eventType = eventType; } @@ -107,25 +106,25 @@ public class BuildEvent extends EventObject { * * @param eventType the type of the buildEvent. * @param cause An exception if associated with the event - * @param modelElement the element with which this event is associated + * @param source the object with which this event is associated */ - public BuildEvent(ModelElement modelElement, int eventType, + public BuildEvent(Object source, int eventType, Throwable cause) { - this(modelElement, eventType); + this(source, eventType); this.cause = cause; } /** * Create a build event for a message * - * @param modelElement the build element with which the event is + * @param source the object with which the event is * associated. * @param message the message associated with this event * @param priority the message priority */ - public BuildEvent(ModelElement modelElement, String message, + public BuildEvent(Object source, String message, int priority) { - this(modelElement, MESSAGE); + this(source, MESSAGE); this.message = message; this.messagePriority = priority; } @@ -139,15 +138,6 @@ public class BuildEvent extends EventObject { return eventType; } - /** - * Get the build element involved in this event. - * - * @return the build element to which this event is associated. - */ - public ModelElement getModelElement() { - return (ModelElement)getSource(); - } - /** * Returns the logging message. This field will only be set for * "messageLogged" events. diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildListener.java b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildListener.java old mode 100755 new mode 100644 similarity index 98% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildListener.java rename to proposal/mutant/src/java/common/org/apache/ant/common/event/BuildListener.java index 6e23c2b54..86d830f85 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/event/BuildListener.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildListener.java @@ -51,7 +51,7 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.antcore.event; +package org.apache.ant.common.event; import java.util.EventListener; diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java b/proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java new file mode 100644 index 000000000..8599b12c8 --- /dev/null +++ b/proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java @@ -0,0 +1,84 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.common.service; +import org.apache.ant.common.util.ExecutionException; + +/** + * The Component Service is used to manage the definitions that Ant uses at + * runtime. It supports the following operations + *
    + *
  • Definition of library search paths + *
  • Importing tasks from a library + *
  • taskdefs + *
  • typedefs + *
+ * + * + * @author Conor MacNeill + * @created 27 January 2002 + */ +public interface ComponentService { + /** + * Load a single or multiple Ant libraries + * + * @param libLocation the location of the library or the libraries + * @param importAll true if all components of the loaded libraries + * should be imported + * @exception ExecutionException if the library or libraries cannot be + * imported. + */ + void loadLib(String libLocation, boolean importAll) + throws ExecutionException; +} + diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/service/DataService.java b/proposal/mutant/src/java/common/org/apache/ant/common/service/DataService.java new file mode 100644 index 000000000..9f02cdb6e --- /dev/null +++ b/proposal/mutant/src/java/common/org/apache/ant/common/service/DataService.java @@ -0,0 +1,132 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.common.service; +import java.util.Map; + +import org.apache.ant.common.util.ExecutionException; + +/** + * Service interface for Data value manipulation operations provided by the + * core. + * + * @author Conor MacNeill + * @created 31 January 2002 + */ +public interface DataService { + /** + * Get a data value + * + * @param valueName the name of the data value + * @return the current object associated with the name or null if no + * value is currently associated with the name + * @exception ExecutionException if the value cannot be retrieved. + */ + Object getDataValue(String valueName) throws ExecutionException; + + /** + * Indicate if a data value has been set + * + * @param name the name of the data value - may contain reference + * delimiters + * @return true if the value exists + * @exception ExecutionException if the containing frame for the value + * does not exist + */ + boolean isDataValueSet(String name) throws ExecutionException; + + /** + * Set a data value. If an existing data value exists, associated with + * the given name, the value will not be changed + * + * @param valueName the name of the data value + * @param value the value to be associated with the name + * @exception ExecutionException if the value cannot be set + */ + void setDataValue(String valueName, Object value) throws ExecutionException; + + /** + * Set a data value which can be overwritten + * + * @param valueName the name of the data value + * @param value the value to be associated with the name + * @exception ExecutionException if the value cannot be set + */ + void setMutableDataValue(String valueName, Object value) + throws ExecutionException; + + /** + * Replace ${} style constructions in the given value with the string + * value of the corresponding data values in the frame + * + * @param value the string to be scanned for property references. + * @return the string with all property references replaced + * @exception ExecutionException if any of the properties do not exist + */ + String replacePropertyRefs(String value) throws ExecutionException; + + /** + * Replace ${} style constructions in the given value with the string + * value of the objects in the given map. Any values which are not found + * are left unchanged. + * + * @param value the string to be scanned for property references. + * @param replacementValues the collection of replacement values + * @return the string with all property references replaced + * @exception ExecutionException if any of the properties do not exist + */ + String replacePropertyRefs(String value, Map replacementValues) + throws ExecutionException; + +} + diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/context/AntContext.java b/proposal/mutant/src/java/common/org/apache/ant/common/service/FileService.java old mode 100755 new mode 100644 similarity index 82% rename from proposal/mutant/src/java/common/org/apache/ant/common/context/AntContext.java rename to proposal/mutant/src/java/common/org/apache/ant/common/service/FileService.java index cd62184c0..43f89f6b2 --- a/proposal/mutant/src/java/common/org/apache/ant/common/context/AntContext.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/service/FileService.java @@ -51,35 +51,27 @@ * information on the Apache Software Foundation, please see * . */ -package org.apache.ant.common.context; +package org.apache.ant.common.service; import java.io.File; -import org.apache.ant.common.util.AntException; +import org.apache.ant.common.util.ExecutionException; /** - * The TaskContext is the interface through which the Ant Task container and - * the Task instances communicate + * Service interface for File manipulation operations provided by the Ant + * Core * * @author Conor MacNeill - * @created 14 January 2002 + * @created 27 January 2002 */ -public abstract class AntContext { - /** - * Log a message - * - * @param message the message to be logged - * @param level the priority level of the message - */ - public abstract void log(String message, int level); - +public interface FileService { /** * Resolve a file according to the base directory of the project * associated with this context * * @param fileName the file name to be resolved. * @return the file resolved to the project's base dir - * @exception AntException if the file cannot be resolved + * @exception ExecutionException if the file cannot be resolved */ - public abstract File resolveFile(String fileName) throws AntException; + File resolveFile(String fileName) throws ExecutionException; } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/GeneralAntException.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/ExecutionException.java old mode 100755 new mode 100644 similarity index 88% rename from proposal/mutant/src/java/common/org/apache/ant/common/util/GeneralAntException.java rename to proposal/mutant/src/java/common/org/apache/ant/common/util/ExecutionException.java index c930d8299..9a8aec1ff --- a/proposal/mutant/src/java/common/org/apache/ant/common/util/GeneralAntException.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/ExecutionException.java @@ -54,19 +54,19 @@ package org.apache.ant.common.util; /** - * An GeneralAntException is used to for any exception case for which there - * is no specific AntException subclass which is appropriate + * An ExecutionException indicates a problem while executing tasks in a + * build * * @author Conor MacNeill - * @created 21 January 2002 + * @created 20 January 2002 */ -public class GeneralAntException extends AntException { +public class ExecutionException extends AntException { /** * Constructs an exception with the given descriptive message. * * @param msg Description of or information about the exception. */ - public GeneralAntException(String msg) { + public ExecutionException(String msg) { super(msg); } @@ -78,7 +78,7 @@ public class GeneralAntException extends AntException { * @param msg Description of or information about the exception. * @param location Location in the project file where the error occured. */ - public GeneralAntException(String msg, Location location) { + public ExecutionException(String msg, Location location) { super(msg, location); } @@ -90,7 +90,7 @@ public class GeneralAntException extends AntException { * @param msg Description of or information about the exception. * @param cause Throwable that might have cause this one. */ - public GeneralAntException(String msg, Throwable cause) { + public ExecutionException(String msg, Throwable cause) { super(msg, cause); } @@ -103,7 +103,7 @@ public class GeneralAntException extends AntException { * @param cause Exception that might have cause this one. * @param location Location in the project file where the error occured. */ - public GeneralAntException(String msg, Throwable cause, Location location) { + public ExecutionException(String msg, Throwable cause, Location location) { super(msg, cause, location); } @@ -113,7 +113,7 @@ public class GeneralAntException extends AntException { * * @param cause Exception that might have caused this one. */ - public GeneralAntException(Throwable cause) { + public ExecutionException(Throwable cause) { super(cause); } @@ -125,7 +125,7 @@ public class GeneralAntException extends AntException { * @param cause Exception that might have cause this one. * @param location Location in the project file where the error occured. */ - public GeneralAntException(Throwable cause, Location location) { + public ExecutionException(Throwable cause, Location location) { super(cause, location); } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/FileUtils.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/FileUtils.java index bfe62ae18..d7b6afdc8 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/util/FileUtils.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/FileUtils.java @@ -78,32 +78,32 @@ public class FileUtils { * null, this call is equivalent to * new java.io.File(filename) * . - * @param filename a file name + * @param filename the filename to be resolved * @return an absolute file that doesn't contain "./" or * "../" sequences and uses the correct separator for the * current platform. - * @exception GeneralAntException if the file cannot be resolved + * @exception ExecutionException if the file cannot be resolved */ public File resolveFile(File file, String filename) - throws GeneralAntException { - filename = filename.replace('/', File.separatorChar) + throws ExecutionException { + String platformFilename = filename.replace('/', File.separatorChar) .replace('\\', File.separatorChar); // deal with absolute files - if (filename.startsWith(File.separator) || - (filename.length() >= 2 && - Character.isLetter(filename.charAt(0)) && - filename.charAt(1) == ':') - ) { - return normalize(filename); + if (platformFilename.startsWith(File.separator) || + (platformFilename.length() >= 2 && + Character.isLetter(platformFilename.charAt(0)) && + platformFilename.charAt(1) == ':')) { + return normalize(platformFilename); } if (file == null) { - return new File(filename); + return new File(platformFilename); } File helpFile = new File(file.getAbsolutePath()); - StringTokenizer tok = new StringTokenizer(filename, File.separator); + StringTokenizer tok + = new StringTokenizer(platformFilename, File.separator); while (tok.hasMoreTokens()) { String part = tok.nextToken(); if (part.equals("..")) { @@ -112,7 +112,7 @@ public class FileUtils { String msg = "The file or path you specified (" + filename + ") is invalid relative to " + file.getPath(); - throw new GeneralAntException(msg); + throw new ExecutionException(msg); } } else if (part.equals(".")) { // Do nothing here @@ -138,37 +138,35 @@ public class FileUtils { * * * @param path the path to be normalized - * @return the normalized path - * @exception GeneralAntException if there is a problem with the path + * @return the normalized path + * @exception ExecutionException if there is a problem with the path * @throws NullPointerException if the file path is equal to null. */ - public File normalize(String path) - throws NullPointerException, GeneralAntException { - String orig = path; + public File normalize(String path) + throws NullPointerException, ExecutionException { - path = path.replace('/', File.separatorChar) + String platformPath = path.replace('/', File.separatorChar) .replace('\\', File.separatorChar); // make sure we are dealing with an absolute path - if (!path.startsWith(File.separator) && - !(path.length() >= 2 && - Character.isLetter(path.charAt(0)) && - path.charAt(1) == ':') - ) { + if (!platformPath.startsWith(File.separator) && + !(platformPath.length() >= 2 && + Character.isLetter(platformPath.charAt(0)) && + platformPath.charAt(1) == ':')) { String msg = path + " is not an absolute path"; - throw new GeneralAntException(msg); + throw new ExecutionException(msg); } boolean dosWithDrive = false; String root = null; // Eliminate consecutive slashes after the drive spec - if (path.length() >= 2 && - Character.isLetter(path.charAt(0)) && - path.charAt(1) == ':') { + if (platformPath.length() >= 2 && + Character.isLetter(platformPath.charAt(0)) && + platformPath.charAt(1) == ':') { dosWithDrive = true; - char[] ca = path.replace('/', '\\').toCharArray(); + char[] ca = platformPath.replace('/', '\\').toCharArray(); StringBuffer sb = new StringBuffer(); sb.append(Character.toUpperCase(ca[0])).append(':'); @@ -180,40 +178,40 @@ public class FileUtils { } } - path = sb.toString().replace('\\', File.separatorChar); - if (path.length() == 2) { - root = path; - path = ""; + platformPath = sb.toString().replace('\\', File.separatorChar); + if (platformPath.length() == 2) { + root = platformPath; + platformPath = ""; } else { - root = path.substring(0, 3); - path = path.substring(3); + root = platformPath.substring(0, 3); + platformPath = platformPath.substring(3); } } else { - if (path.length() == 1) { + if (platformPath.length() == 1) { root = File.separator; - path = ""; - } else if (path.charAt(1) == File.separatorChar) { + platformPath = ""; + } else if (platformPath.charAt(1) == File.separatorChar) { // UNC drive root = File.separator + File.separator; - path = path.substring(2); + platformPath = platformPath.substring(2); } else { root = File.separator; - path = path.substring(1); + platformPath = platformPath.substring(1); } } Stack s = new Stack(); s.push(root); - StringTokenizer tok = new StringTokenizer(path, File.separator); + StringTokenizer tok = new StringTokenizer(platformPath, File.separator); while (tok.hasMoreTokens()) { String thisToken = tok.nextToken(); if (".".equals(thisToken)) { continue; } else if ("..".equals(thisToken)) { if (s.size() < 2) { - throw new GeneralAntException("Cannot resolve path " - + orig); + throw new ExecutionException("Cannot resolve path " + + path); } else { s.pop(); } @@ -232,11 +230,11 @@ public class FileUtils { sb.append(s.elementAt(i)); } - path = sb.toString(); + platformPath = sb.toString(); if (dosWithDrive) { - path = path.replace('/', '\\'); + platformPath = platformPath.replace('/', '\\'); } - return new File(path); + return new File(platformPath); } } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/Location.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/Location.java index bdda5a012..dadebc835 100755 --- a/proposal/mutant/src/java/common/org/apache/ant/common/util/Location.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/Location.java @@ -97,16 +97,16 @@ public class Location { } /** Creates an "unknown" location. */ - private Location() { + public Location() { this(null, 0, 0); } /** - * Get the source URL for this location + * Get the source for this location * - * @return a URL string + * @return the location's source */ - public String getSourceURL() { + public String getSource() { return source; } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/PropertyUtils.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/PropertyUtils.java new file mode 100644 index 000000000..6759c6905 --- /dev/null +++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/PropertyUtils.java @@ -0,0 +1,126 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.ant.common.util; + +import java.util.List; + +/** + * A set of utilities for handling Ant properties and values + * + * @author Conor MacNeill + * @created 31 January 2002 + */ +public class PropertyUtils { + /** + * This method will parse a string containing ${value} style property + * values into two lists. The first list is a collection of text + * fragments, while the other is a set of string property names. Null + * entries in the first list indicate a property reference from the + * second list. + * + * @param value the string to be parsed + * @param fragments the fragments parsed out of the string + * @param propertyRefs the property refs to be replaced + * @exception ExecutionException if there is a problem parsing out the + * values + */ + public static void parsePropertyString(String value, List fragments, + List propertyRefs) + throws ExecutionException { + int prev = 0; + int pos; + while ((pos = value.indexOf("$", prev)) >= 0) { + if (pos > 0) { + fragments.add(value.substring(prev, pos)); + } + + if (pos == (value.length() - 1)) { + fragments.add("$"); + prev = pos + 1; + } else if (value.charAt(pos + 1) != '{') { + fragments.add(value.substring(pos + 1, pos + 2)); + prev = pos + 2; + } else { + int endName = value.indexOf('}', pos); + if (endName < 0) { + throw new ExecutionException("Syntax error in property: " + + value); + } + String propertyName = value.substring(pos + 2, endName); + fragments.add(null); + propertyRefs.add(propertyName); + prev = endName + 1; + } + } + + if (prev < value.length()) { + fragments.add(value.substring(prev)); + } + } + + /** + * returns the boolean equivalent of a string, which is considered true + * if either "on", "true", or "yes" is found, ignoring case. + * + * @param s the string value to be interpreted at a boolean + * @return the value of s as a boolean + */ + public static boolean toBoolean(String s) { + return (s != null && (s.equalsIgnoreCase("on") + || s.equalsIgnoreCase("true") + || s.equalsIgnoreCase("yes"))); + } + +} + diff --git a/proposal/mutant/src/java/init/org/apache/ant/init/InitConfig.java b/proposal/mutant/src/java/init/org/apache/ant/init/InitConfig.java index 7d259f7ac..51d3f97a8 100755 --- a/proposal/mutant/src/java/init/org/apache/ant/init/InitConfig.java +++ b/proposal/mutant/src/java/init/org/apache/ant/init/InitConfig.java @@ -54,6 +54,7 @@ package org.apache.ant.init; import java.net.URL; +import java.io.File; /** * InitConfig is the initialization configuration created to start Ant. This @@ -98,20 +99,20 @@ public class InitConfig { private URL libraryURL; /** The location of the system configuration file */ - private URL systemConfigArea; + private File systemConfigArea; /** The location of ANT_HOME */ private URL antHome; /** The location of the user config file */ - private URL userConfigArea; + private File userConfigArea; /** * Sets the location of the user configuration files * * @param userConfigArea the new user config area */ - public void setUserConfigArea(URL userConfigArea) { + public void setUserConfigArea(File userConfigArea) { this.userConfigArea = userConfigArea; } @@ -129,7 +130,7 @@ public class InitConfig { * * @param systemConfigArea the new system config area */ - public void setSystemConfigArea(URL systemConfigArea) { + public void setSystemConfigArea(File systemConfigArea) { this.systemConfigArea = systemConfigArea; } @@ -192,7 +193,7 @@ public class InitConfig { * * @return the location of the user's Ant config files */ - public URL getUserConfigArea() { + public File getUserConfigArea() { return userConfigArea; } @@ -210,7 +211,7 @@ public class InitConfig { * * @return the location of the system Ant config files */ - public URL getSystemConfigArea() { + public File getSystemConfigArea() { return systemConfigArea; } diff --git a/proposal/mutant/src/java/init/org/apache/ant/init/LoaderUtils.java b/proposal/mutant/src/java/init/org/apache/ant/init/LoaderUtils.java index db88b3ec8..12b04d4b9 100755 --- a/proposal/mutant/src/java/init/org/apache/ant/init/LoaderUtils.java +++ b/proposal/mutant/src/java/init/org/apache/ant/init/LoaderUtils.java @@ -81,38 +81,38 @@ public class LoaderUtils { /** - * Get the URLs to create class loader from the jars in a given location + * Get the URLs of a set of libraries in the given location * - * @param baseURL the baeURL is the location of the libs directory + * @param location the location to be searched * @param defaultFile default file if none can be found * @return an array of URLs for the relevant jars * @exception MalformedURLException the URLs cannot be created */ - public static URL[] getLoaderURLs(URL baseURL, String defaultFile) + public static URL[] getLocationURLs(URL location, String defaultFile) throws MalformedURLException { - return getLoaderURLs(baseURL, defaultFile, new String[]{".jar"}); + return getLocationURLs(location, defaultFile, new String[]{".jar"}); } /** - * Get the URLs for a class loader + * Get the URLs of a set of libraries in the given location * - * @param baseURL the baeURL is the location of the libs directory + * @param location the location to be searched * @param extensions array of allowable file extensions * @param defaultFile default file if none can be found * @return an array of URLs for the relevant jars * @exception MalformedURLException if the URL to the jars could not be * formed */ - public static URL[] getLoaderURLs(URL baseURL, String defaultFile, - String[] extensions) + public static URL[] getLocationURLs(URL location, String defaultFile, + String[] extensions) throws MalformedURLException { URL[] urls = null; - if (baseURL.getProtocol().equals("file")) { + if (location.getProtocol().equals("file")) { // URL is local filesystem. - urls = getDirectoryURLs(new File(baseURL.getFile()), extensions); + urls = getLocalURLs(new File(location.getFile()), extensions); } else { // URL is remote - try to read a file with the list of jars - URL jarListURL = new URL(baseURL, LIST_FILE); + URL jarListURL = new URL(location, LIST_FILE); BufferedReader reader = null; List jarList = new ArrayList(); try { @@ -123,7 +123,7 @@ public class LoaderUtils { while ((line = reader.readLine().trim()) != null) { for (int i = 0; i < extensions.length; ++i) { if (line.endsWith(extensions[i])) { - jarList.add(new URL(baseURL, line)); + jarList.add(new URL(location, line)); break; } } @@ -132,7 +132,7 @@ public class LoaderUtils { } catch (IOException e) { // use the default location if (defaultFile != null) { - urls = new URL[]{new URL(baseURL, defaultFile)}; + urls = new URL[]{new URL(location, defaultFile)}; } } finally { if (reader != null) { @@ -180,25 +180,40 @@ public class LoaderUtils { /** - * Get an array of URLs for each jar file in the directory + * Get an array of URLs for each file in the filesystem. If the given + * location is a directory, it is searched for files of the given + * extension. If it is a file, it is returned as a URL if it matches the + * given extension list. * - * @param directory the local directory + * @param location the location within the local filesystem to be + * searched * @param extensions an array of file extensions to be considered in the * search * @return an array of URLs for the file found in the directory. * @exception MalformedURLException if the URLs to the jars cannot be * formed */ - private static URL[] getDirectoryURLs(File directory, - final String[] extensions) + private static URL[] getLocalURLs(File location, + final String[] extensions) throws MalformedURLException { URL[] urls = new URL[0]; - if (!directory.exists()) { + if (!location.exists()) { return urls; } - File[] jars = directory.listFiles( + if (!location.isDirectory()) { + String path = location.getPath(); + for (int i = 0; i < extensions.length; ++i) { + if (path.endsWith(extensions[i])) { + urls[0] = InitUtils.getFileURL(location); + break; + } + } + return urls; + } + + File[] jars = location.listFiles( new FilenameFilter() { public boolean accept(File dir, String name) { for (int i = 0; i < extensions.length; ++i) { @@ -212,7 +227,6 @@ public class LoaderUtils { urls = new URL[jars.length]; for (int i = 0; i < jars.length; ++i) { urls[i] = InitUtils.getFileURL(jars[i]); - // ps.println("Adding URL " + urls[i]); } return urls; } diff --git a/proposal/mutant/src/java/remote/org/apache/ant/remote/RemoteMain.java b/proposal/mutant/src/java/remote/org/apache/ant/remote/RemoteMain.java new file mode 100644 index 000000000..71de737dd --- /dev/null +++ b/proposal/mutant/src/java/remote/org/apache/ant/remote/RemoteMain.java @@ -0,0 +1,48 @@ +package org.apache.ant.remote; + +import java.net.URL; +import java.net.URLClassLoader; +import java.lang.reflect.Method; + +/** + * Command line to run Ant core from a remote server + * + * @author Conor MacNeill + * @created 27 January 2002 + */ +public class RemoteMain { + /** + * The main program for the RemoteLauncher class + * + * @param args The command line arguments + * @exception Exception if the launcher encounters a problem + */ + public static void main(String[] args) throws Exception { + + if (args.length == 0) { + throw new Exception("You must specify the location of the " + + "remote server"); + } + + String antHome = args[0]; + + URL[] remoteStart = new URL[1]; + remoteStart[0] = new URL(antHome + "/lib/start.jar"); + URLClassLoader remoteLoader = new URLClassLoader(remoteStart); + + String[] realArgs = new String[args.length - 1]; + System.arraycopy(args, 1, realArgs, 0, realArgs.length); + + System.out.print("Loading remote Ant ... "); + Class launcher + = Class.forName("org.apache.ant.start.Main", true, remoteLoader); + + final Class[] param = {Class.forName("[Ljava.lang.String;")}; + final Method startMethod = launcher.getMethod("main", param); + final Object[] arguments = {realArgs}; + System.out.println("Done"); + System.out.println("Starting Ant from remote server"); + startMethod.invoke(null, arguments); + } +} + diff --git a/proposal/mutant/src/java/start/org/apache/ant/start/Main.java b/proposal/mutant/src/java/start/org/apache/ant/start/Main.java index bcb2ad352..69e23fee6 100755 --- a/proposal/mutant/src/java/start/org/apache/ant/start/Main.java +++ b/proposal/mutant/src/java/start/org/apache/ant/start/Main.java @@ -138,7 +138,8 @@ public class Main { private URL getToolsJarURL() throws InitException { try { - Class compilerClass = Class.forName("sun.tools.javac.Main"); + // just check whether this throws an exception + Class.forName("sun.tools.javac.Main"); // tools jar is on system classpath - no need for URL return null; } catch (ClassNotFoundException cnfe) { @@ -195,14 +196,18 @@ public class Main { InitConfig config = new InitConfig(); URL libraryURL = getLibraryURL(); + System.out.println("Library URL is " + libraryURL); config.setLibraryURL(libraryURL); URL antHome = getAntHome(); config.setAntHome(antHome); - config.setSystemConfigArea(new URL(antHome, "conf/")); + if (antHome.getProtocol().equals("file")) { + File systemConfigArea = new File(antHome.getFile(), "conf"); + config.setSystemConfigArea(systemConfigArea); + } File userConfigArea = new File(System.getProperty("user.home"), ".ant/conf"); - config.setUserConfigArea(InitUtils.getFileURL(userConfigArea)); + config.setUserConfigArea(userConfigArea); // set up the class loaders that will be used when running Ant ClassLoader systemLoader = getClass().getClassLoader(); @@ -210,20 +215,20 @@ public class Main { URL toolsJarURL = getToolsJarURL(); config.setToolsJarURL(toolsJarURL); - URL commonJarLib = new URL(libraryURL, "common"); + URL commonJarLib = new URL(libraryURL, "common/"); ClassLoader commonLoader - = new URLClassLoader(LoaderUtils.getLoaderURLs(commonJarLib, + = new URLClassLoader(LoaderUtils.getLocationURLs(commonJarLib, "common.jar"), systemLoader); config.setCommonLoader(commonLoader); // core needs XML parser for parsing various XML components. URL[] parserURLs - = LoaderUtils.getLoaderURLs(new URL(libraryURL, "parser"), + = LoaderUtils.getLocationURLs(new URL(libraryURL, "parser/"), "crimson.jar"); config.setParserURLs(parserURLs); URL[] coreURLs - = LoaderUtils.getLoaderURLs(new URL(libraryURL, "antcore"), + = LoaderUtils.getLocationURLs(new URL(libraryURL, "antcore/"), "antcore.jar"); URL[] combinedURLs = new URL[parserURLs.length + coreURLs.length]; System.arraycopy(coreURLs, 0, combinedURLs, 0, coreURLs.length); @@ -233,9 +238,9 @@ public class Main { commonLoader); config.setCoreLoader(coreLoader); - URL cliJarLib = new URL(libraryURL, "cli"); + URL cliJarLib = new URL(libraryURL, "cli/"); ClassLoader frontEndLoader - = new URLClassLoader(LoaderUtils.getLoaderURLs(cliJarLib, + = new URLClassLoader(LoaderUtils.getLocationURLs(cliJarLib, "cli.jar"), coreLoader); // System.out.println("Front End Loader config");