Submitted by: Matt Foemmel git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267656 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -17,7 +17,7 @@ if "" == "%JAVAC%" set JAVAC=%JAVA_HOME%\bin\javac | |||
| echo. | |||
| echo ... Bootstrapping Ant Distribution | |||
| set CLASSPATH=src\main;classes;lib\xml.jar | |||
| set CLASSPATH=src\main;classes;%CLASSPATH% | |||
| if exist %JAVA_HOME%\lib\tools.jar set CLASSPATH=%CLASSPATH%;%JAVA_HOME%\lib\tools.jar | |||
| echo JAVA_HOME=%JAVA_HOME% | |||
| @@ -40,7 +40,6 @@ echo. | |||
| echo ... Copying Required Files | |||
| copy %TOOLS%\ant\taskdefs\*.properties classes\org\apache\tools\ant\taskdefs | |||
| copy %TOOLS%\ant\*.properties classes\org\apache\tools\ant | |||
| echo. | |||
| echo ... Building Ant Distribution | |||
| @@ -5,7 +5,7 @@ fi | |||
| SRCDIR=src/main/org/apache/tools | |||
| CLASSDIR=classes | |||
| CLASSPATH=${CLASSPATH}:${JAVA_HOME}/lib/classes.zip:${JAVA_HOME}/lib/tools.jar | |||
| CLASSPATH=${CLASSPATH}:lib/xml.jar:src/main:${CLASSDIR} | |||
| CLASSPATH=${CLASSPATH}:src/main:${CLASSDIR} | |||
| mkdir -p ${CLASSDIR} | |||
| @@ -17,7 +17,6 @@ javac -d ${CLASSDIR} ${SRCDIR}/ant/*.java | |||
| javac -d ${CLASSDIR} ${SRCDIR}/ant/taskdefs/*.java | |||
| cp src/main/org/apache/tools/ant/taskdefs/defaults.properties ${CLASSDIR}/org/apache/tools/ant/taskdefs | |||
| cp src/main/org/apache/tools/ant/parser.properties ${CLASSDIR}/org/apache/tools/ant | |||
| java org.apache.tools.ant.Main main | |||
| java org.apache.tools.ant.Main clean | |||
| @@ -1,3 +1,3 @@ | |||
| @echo off | |||
| REM convience bat file to build with | |||
| java -classpath "%CLASSPATH%;lib\ant.jar;lib\xml.jar" org.apache.tools.ant.Main %1 %2 %3 %4 %5 | |||
| java -classpath "%CLASSPATH%;lib\ant.jar" org.apache.tools.ant.Main %1 %2 %3 %4 %5 | |||
| @@ -1,6 +1,6 @@ | |||
| #!/bin/sh | |||
| ADDL_CLASSPATH=./lib/ant.jar:./lib/xml.jar | |||
| ADDL_CLASSPATH=./lib/ant.jar | |||
| if [ "$CLASSPATH" != "" ] ; then | |||
| CLASSPATH=$CLASSPATH:$ADDL_CLASSPATH | |||
| @@ -21,7 +21,7 @@ | |||
| <property name="build.javadocs" value="build/javadocs"/> | |||
| <property name="ant.dist.dir" value="dist"/> | |||
| <property name="classpath" value="lib/xml.jar"/> | |||
| <property name="classpath" value=""/> | |||
| <property name="packages" value="org.apache.tools.*"/> | |||
| <property name="manifest" value="src/etc/manifest"/> | |||
| @@ -1,98 +0,0 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 1999 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "The Jakarta Project", "Tomcat", 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 | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.net.URL; | |||
| import java.lang.reflect.Method; | |||
| import org.w3c.dom.Document; | |||
| import org.xml.sax.InputSource; | |||
| import org.xml.sax.SAXException; | |||
| /** | |||
| * Implementation of Parser using Apache Xerces-J. | |||
| * | |||
| * @author pier@apache.org | |||
| */ | |||
| public class ApacheParser extends Parser { | |||
| Class DOMParser = null; | |||
| Method parse; | |||
| Method getDocument; | |||
| /** | |||
| * Parse the specified file and return a DOM Document. | |||
| */ | |||
| public Document parse(File buildFile) | |||
| throws SAXException, IOException { | |||
| try { | |||
| if (DOMParser == null) { | |||
| DOMParser = Class.forName("org.apache.xerces.parsers.DOMParser"); | |||
| parse = DOMParser.getMethod("parse", new Class[]{String.class}); | |||
| getDocument = DOMParser.getMethod("getDocument", new Class[]{}); | |||
| } | |||
| Object p=DOMParser.newInstance(); | |||
| URL url=new URL("file","",buildFile.getAbsolutePath()); | |||
| parse.invoke(p, new Object[]{url.toExternalForm()}); | |||
| return(org.w3c.dom.Document)getDocument.invoke(p, new Object[]{}); | |||
| } catch (Exception e) { | |||
| if (e instanceof IOException) throw (IOException)e; | |||
| if (e instanceof SAXException) throw (SAXException)e; | |||
| throw new IOException(e.toString()); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,7 +1,7 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 1999 The Apache Software Foundation. All rights | |||
| * Copyright (c) 1999 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| @@ -9,7 +9,7 @@ | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * 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 | |||
| @@ -17,15 +17,15 @@ | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * 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", "Tomcat", and "Apache Software | |||
| * Foundation" must not be used to endorse or promote products derived | |||
| * from this software without prior written permission. For written | |||
| * 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" | |||
| @@ -50,7 +50,7 @@ | |||
| * individuals on behalf of the Apache Software Foundation. For more | |||
| * information on the Apache Software Foundation, please see | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| */ | |||
| package org.apache.tools.ant; | |||
| @@ -65,10 +65,13 @@ public class BuildException extends RuntimeException { | |||
| /** Exception that might have caused this one. */ | |||
| private Exception cause; | |||
| /** Location in the build file where the exception occured */ | |||
| private Location location = Location.UNKNOWN_LOCATION; | |||
| /** | |||
| * Constructs a build exception with no descriptive information. | |||
| */ | |||
| public BuildException() { | |||
| super(); | |||
| } | |||
| @@ -77,7 +80,7 @@ public class BuildException extends RuntimeException { | |||
| * Constructs an exception with the given descriptive message. | |||
| * @param msg Description of or information about the exception. | |||
| */ | |||
| public BuildException(String msg) { | |||
| super(msg); | |||
| } | |||
| @@ -93,14 +96,60 @@ public class BuildException extends RuntimeException { | |||
| super(msg); | |||
| this.cause = cause; | |||
| } | |||
| /** | |||
| * Constructs an exception with the given message and exception as | |||
| * a root cause and a location in a file. | |||
| * @param msg Description of or information about the exception. | |||
| * @param cause Exception that might have cause this one. | |||
| * @param location Location in the project file where the error occured. | |||
| */ | |||
| public BuildException(String msg, Exception cause, Location location) { | |||
| this(msg, cause); | |||
| this.location = location; | |||
| } | |||
| /** | |||
| * Constructs an exception with the given exception as a root cause. | |||
| * @param cause Exception that might have caused this one. | |||
| */ | |||
| public BuildException(Exception cause) { | |||
| super(cause.toString()); | |||
| this.cause = cause; | |||
| } | |||
| /** | |||
| * Constructs an exception with the given descriptive message and a location | |||
| * in a file. | |||
| * @param msg Description of or information about the exception. | |||
| * @param location Location in the project file where the error occured. | |||
| */ | |||
| public BuildException(String msg, Location location) { | |||
| super(msg); | |||
| this.location = location; | |||
| } | |||
| /** | |||
| * Returns the nested exception. | |||
| */ | |||
| public Exception getException() { | |||
| return cause; | |||
| } | |||
| /** | |||
| * Returns the location of the error and the error message. | |||
| */ | |||
| public String toString() { | |||
| return location.toString() + getMessage(); | |||
| } | |||
| /** | |||
| * Sets the file location where the error occured. | |||
| */ | |||
| public void setLocation(Location location) { | |||
| this.location = location; | |||
| } | |||
| } | |||
| @@ -141,7 +141,7 @@ public class Main { | |||
| /* Interestingly enough, we get to here when a user | |||
| * uses -Dname=value. However, in some cases, the JDK | |||
| * goes ahead * and parses this out to args | |||
| * goes ahead * and parses this out to args | |||
| * {"-Dname", "value"} | |||
| * so instead of parsing on "=", we just make the "-D" | |||
| * characters go away and skip one argument forward. | |||
| @@ -189,7 +189,7 @@ public class Main { | |||
| // ok, so if we've made it here, let's run the damn build allready | |||
| runBuild(); | |||
| return; | |||
| } | |||
| @@ -216,15 +216,23 @@ public class Main { | |||
| project.setUserProperty(arg, value); | |||
| } | |||
| project.setUserProperty( "ant.file" , buildFile.getAbsolutePath() ); | |||
| // first use the ProjectHelper to create the project object | |||
| // from the given build file. | |||
| try { | |||
| try { | |||
| Class.forName("javax.xml.parsers.SAXParserFactory"); | |||
| } catch (ClassNotFoundException cnfe) { | |||
| throw new BuildException(cnfe); | |||
| } | |||
| ProjectHelper.configureProject(project, buildFile); | |||
| } catch (BuildException be) { | |||
| String msg = "BUILD CONFIG ERROR: "; | |||
| System.out.println(msg + be.getMessage()); | |||
| be.printStackTrace(); | |||
| System.out.println("\nBUILD CONFIG ERROR\n"); | |||
| if (be.getException() == null) { | |||
| System.out.println(be.toString()); | |||
| } else { | |||
| be.getException().printStackTrace(); | |||
| } | |||
| System.exit(1); | |||
| } | |||
| @@ -240,8 +248,8 @@ public class Main { | |||
| project.executeTarget((String) en.nextElement()); | |||
| } | |||
| } catch (BuildException be) { | |||
| String msg = "BUILD FATAL ERROR: "; | |||
| System.out.println(msg + be.getMessage()); | |||
| String msg = "\nBUILD FATAL ERROR\n\n"; | |||
| System.out.println(msg + be.toString()); | |||
| if (msgOutputLevel > Project.MSG_INFO) { | |||
| be.printStackTrace(); | |||
| } | |||
| @@ -1,111 +0,0 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 1999 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "The Jakarta Project", "Tomcat", 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 | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant; | |||
| import java.io.File; | |||
| import java.io.InputStream; | |||
| import java.io.IOException; | |||
| import java.util.Properties; | |||
| import org.w3c.dom.Document; | |||
| import org.xml.sax.SAXException; | |||
| /** | |||
| * Dummy parser abstraction class for ANT to be used until the Java API for | |||
| * XML Parsing are released. | |||
| * | |||
| * @author pier@apache.org | |||
| */ | |||
| public abstract class Parser { | |||
| // The properties file to be loaded | |||
| private static String properties="org/apache/tools/ant/parser.properties"; | |||
| /** | |||
| * Create a working instance of a parser | |||
| */ | |||
| public static Parser getParser(Project project) | |||
| throws BuildException { | |||
| InputStream in=project.getClass().getResourceAsStream("parser.properties"); | |||
| if (in==null) throw new BuildException("Cannot find properties file"); | |||
| String name; | |||
| try { | |||
| Properties prop=new Properties(); | |||
| prop.load(in); | |||
| name=prop.getProperty("parser"); | |||
| if (name==null) throw new BuildException("Parser name not found"); | |||
| } catch(IOException e) { | |||
| throw new BuildException("Cannot load properties file"); | |||
| } | |||
| try { | |||
| return((Parser)Class.forName(name).newInstance()); | |||
| } catch (ClassNotFoundException e) { | |||
| throw new BuildException("Class "+name+" cannot be found"); | |||
| } catch (InstantiationException e) { | |||
| throw new BuildException("Class "+name+" cannot be instantiated"); | |||
| } catch (IllegalAccessException e) { | |||
| throw new BuildException("Class "+name+" cannot be accessed"); | |||
| } catch (ClassCastException e) { | |||
| throw new BuildException("Class "+name+" doesn't extend Parser"); | |||
| } | |||
| } | |||
| /** | |||
| * Parse the specified file and return a DOM Document. | |||
| */ | |||
| public abstract Document parse(File f) | |||
| throws SAXException, IOException; | |||
| } | |||
| @@ -55,13 +55,13 @@ | |||
| package org.apache.tools.ant; | |||
| import java.beans.*; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.*; | |||
| import java.lang.reflect.*; | |||
| import java.util.*; | |||
| import org.xml.sax.SAXException; | |||
| import org.xml.sax.*; | |||
| import org.w3c.dom.*; | |||
| import org.apache.tools.ant.taskdefs.*; | |||
| import javax.xml.parsers.*; | |||
| /** | |||
| * Configures a Project (complete with Targets and Tasks) based on | |||
| @@ -72,228 +72,332 @@ import org.apache.tools.ant.taskdefs.*; | |||
| public class ProjectHelper { | |||
| public static void configureProject(Project project, File buildFile) | |||
| throws BuildException | |||
| { | |||
| private static SAXParserFactory parserFactory = null; | |||
| // XXX | |||
| // need to get rid of the DOM layer and use SAX | |||
| private org.xml.sax.Parser parser; | |||
| private Project project; | |||
| private File buildFile; | |||
| private Locator locator; | |||
| Document doc; | |||
| /** | |||
| * Configures the Project with the contents of the specified XML file. | |||
| */ | |||
| public static void configureProject(Project project, File buildFile) throws BuildException { | |||
| new ProjectHelper(project, buildFile).parse(); | |||
| } | |||
| /** | |||
| * Constructs a new Ant parser for the specified XML file. | |||
| */ | |||
| private ProjectHelper(Project project, File buildFile) { | |||
| this.project = project; | |||
| this.buildFile = buildFile; | |||
| } | |||
| /** | |||
| * Parses the project file. | |||
| */ | |||
| private void parse() throws BuildException { | |||
| try { | |||
| doc=Parser.getParser(project).parse(buildFile); | |||
| } catch (IOException ioe) { | |||
| String msg = "Can't open config file: " + buildFile + | |||
| " due to: " + ioe; | |||
| throw new BuildException(msg); | |||
| } catch (SAXException se) { | |||
| String msg = "Can't open config file: " + buildFile + | |||
| " due to: " + se; | |||
| throw new BuildException(msg); | |||
| parser = getParserFactory().newSAXParser().getParser(); | |||
| parser.setDocumentHandler(new RootHandler()); | |||
| parser.parse(new InputSource(new FileReader(buildFile))); | |||
| } | |||
| catch(ParserConfigurationException exc) { | |||
| throw new BuildException("Parser has not been configured correctly", exc); | |||
| } | |||
| catch(SAXParseException exc) { | |||
| Location location = | |||
| new Location(buildFile.toString(), exc.getLineNumber(), exc.getColumnNumber()); | |||
| throw new BuildException(exc.getMessage(), exc.getException(), location); | |||
| } | |||
| catch(SAXException exc) { | |||
| throw new BuildException(exc.getMessage(), exc.getException()); | |||
| } | |||
| catch(FileNotFoundException exc) { | |||
| throw new BuildException("File \"" + buildFile.toString() + "\" not found"); | |||
| } | |||
| catch(IOException exc) { | |||
| throw new BuildException("Error reading project file", exc); | |||
| } | |||
| } | |||
| Element root = doc.getDocumentElement(); | |||
| /** | |||
| * The common superclass for all sax event handlers in Ant. Basically | |||
| * throws an exception in each method, so subclasses should override | |||
| * what they can handle. | |||
| * | |||
| * Each type of xml element (task, target, etc) in ant will | |||
| * have its own subclass of AbstractHandler. | |||
| * | |||
| * In the constructor, this class takes over the handling of sax | |||
| * events from the parent handler, and returns | |||
| * control back to the parent in the endElement method. | |||
| */ | |||
| private class AbstractHandler extends HandlerBase { | |||
| protected DocumentHandler parentHandler; | |||
| // sanity check, make sure that we have the right element | |||
| // as we aren't validating the input | |||
| public AbstractHandler(DocumentHandler parentHandler) { | |||
| this.parentHandler = parentHandler; | |||
| if (!root.getTagName().equals("project")) { | |||
| String msg = "Config file is not of expected XML type"; | |||
| throw new BuildException(msg); | |||
| // Start handling SAX events | |||
| parser.setDocumentHandler(this); | |||
| } | |||
| public void startElement(String tag, AttributeList attrs) throws SAXParseException { | |||
| throw new SAXParseException("Unexpected element \"" + tag + "\"", locator); | |||
| } | |||
| project.setDefaultTarget(root.getAttribute("default")); | |||
| public void characters(char[] buf, int start, int end) throws SAXParseException { | |||
| String s = new String(buf, start, end).trim(); | |||
| String name = root.getAttribute("name"); | |||
| project.setName(name); | |||
| if (name != null) project.addReference(name, project); | |||
| if (s.length() > 0) { | |||
| throw new SAXParseException("Unexpected text \"" + s + "\"", locator); | |||
| } | |||
| } | |||
| String id = root.getAttribute("id"); | |||
| if (id != null) project.addReference(id, project); | |||
| public void endElement(String name) throws SAXException { | |||
| String baseDir = project.getProperty("basedir"); | |||
| if (baseDir == null) { | |||
| baseDir = root.getAttribute("basedir"); | |||
| if (baseDir.equals("")) { | |||
| // Using clunky JDK1.1 methods here | |||
| baseDir = new File(buildFile.getAbsolutePath()).getParent(); | |||
| // Let parent resume handling SAX events | |||
| parser.setDocumentHandler(parentHandler); | |||
| } | |||
| } | |||
| /** | |||
| * Handler for the root element. It's only child must be the "project" element. | |||
| */ | |||
| private class RootHandler extends HandlerBase { | |||
| public void startElement(String tag, AttributeList attrs) throws SAXParseException { | |||
| if (tag.equals("project")) { | |||
| new ProjectHandler(this).init(tag, attrs); | |||
| } else { | |||
| throw new SAXParseException("Config file is not of expected XML type", locator); | |||
| } | |||
| } | |||
| project.setBasedir(baseDir); | |||
| // set up any properties that may be in the config file | |||
| public void setDocumentLocator(Locator locator) { | |||
| ProjectHelper.this.locator = locator; | |||
| } | |||
| } | |||
| /** | |||
| * Handler for the top level "project" element. | |||
| */ | |||
| private class ProjectHandler extends AbstractHandler { | |||
| public ProjectHandler(DocumentHandler parentHandler) { | |||
| super(parentHandler); | |||
| } | |||
| public void init(String tag, AttributeList attrs) throws SAXParseException { | |||
| String def = null; | |||
| String name = null; | |||
| String id = null; | |||
| String baseDir = new File(buildFile.getAbsolutePath()).getParent(); | |||
| for (int i = 0; i < attrs.getLength(); i++) { | |||
| String key = attrs.getName(i); | |||
| String value = attrs.getValue(i); | |||
| if (key.equals("default")) { | |||
| def = value; | |||
| } else if (key.equals("name")) { | |||
| name = value; | |||
| } else if (key.equals("id")) { | |||
| id = value; | |||
| } else if (key.equals("basedir")) { | |||
| baseDir = value; | |||
| } else { | |||
| throw new SAXParseException("Unexpected attribute \"" + attrs.getName(i) + "\"", locator); | |||
| } | |||
| } | |||
| project.setDefaultTarget(def); | |||
| // configureProperties(project, root); | |||
| project.setName(name); | |||
| if (name != null) project.addReference(name, project); | |||
| // set up any task defs that may be in the config file | |||
| if (id != null) project.addReference(id, project); | |||
| // configureTaskDefs(project, root); | |||
| if (project.getProperty("basedir") != null) { | |||
| project.setBasedir(project.getProperty("basedir")); | |||
| } else { | |||
| project.setBasedir(baseDir); | |||
| } | |||
| // set up the taskdefs, properties, and targets into the project | |||
| configureProject(project, root); | |||
| } | |||
| public void startElement(String name, AttributeList attrs) throws SAXParseException { | |||
| if (name.equals("taskdef")) { | |||
| handleTaskdef(name, attrs); | |||
| } else if (name.equals("property")) { | |||
| handleProperty(name, attrs); | |||
| } else if (name.equals("target")) { | |||
| handleTarget(name, attrs); | |||
| } else { | |||
| throw new SAXParseException("Unexpected element \"" + name + "\"", locator); | |||
| } | |||
| } | |||
| private void handleTaskdef(String name, AttributeList attrs) throws SAXParseException { | |||
| new TaskHandler(this, null).init(name, attrs); | |||
| } | |||
| private void handleProperty(String name, AttributeList attrs) throws SAXParseException { | |||
| new TaskHandler(this, null).init(name, attrs); | |||
| } | |||
| private void handleTarget(String tag, AttributeList attrs) throws SAXParseException { | |||
| new TargetHandler(this).init(tag, attrs); | |||
| } | |||
| } | |||
| private static void configureProject(Project project, Element root) | |||
| throws BuildException | |||
| { | |||
| // configure taskdefs | |||
| NodeList list = root.getElementsByTagName("taskdef"); | |||
| for (int i = 0; i < list.getLength(); i++) { | |||
| Task taskdef = new Taskdef(); | |||
| configure(project, taskdef, (Element)list.item(i)); | |||
| taskdef.setProject(project); | |||
| taskdef.init(); | |||
| } | |||
| // configure properties | |||
| list = root.getElementsByTagName("property"); | |||
| for (int i = 0; i < list.getLength(); i++) { | |||
| Task property = new Property(); | |||
| configure(project, property, (Element)list.item(i)); | |||
| property.setProject(project); | |||
| property.init(); | |||
| } | |||
| // configure targets | |||
| list = root.getElementsByTagName("target"); | |||
| for (int i = 0; i < list.getLength(); i++) { | |||
| Element element = (Element)list.item(i); | |||
| String targetName = element.getAttribute("name"); | |||
| String targetDep = element.getAttribute("depends"); | |||
| String targetCond = element.getAttribute("if"); | |||
| String targetId = element.getAttribute("id"); | |||
| // all targets must have a name | |||
| if (targetName.equals("")) { | |||
| String msg = "target element appears without a name attribute"; | |||
| throw new BuildException(msg); | |||
| /** | |||
| * Handler for "target" elements. | |||
| */ | |||
| private class TargetHandler extends AbstractHandler { | |||
| private Target target; | |||
| public TargetHandler(DocumentHandler parentHandler) { | |||
| super(parentHandler); | |||
| } | |||
| public void init(String tag, AttributeList attrs) throws SAXParseException { | |||
| String name = null; | |||
| String depends = ""; | |||
| String cond = null; | |||
| String id = null; | |||
| for (int i = 0; i < attrs.getLength(); i++) { | |||
| String key = attrs.getName(i); | |||
| String value = attrs.getValue(i); | |||
| if (key.equals("name")) { | |||
| name = value; | |||
| } else if (key.equals("depends")) { | |||
| depends = value; | |||
| } else if (key.equals("if")) { | |||
| cond = value; | |||
| } else if (key.equals("id")) { | |||
| id = value; | |||
| } else { | |||
| throw new SAXParseException("Unexpected attribute \"" + key + "\"", locator); | |||
| } | |||
| } | |||
| Target target = new Target(); | |||
| target.setName(targetName); | |||
| target.setCondition(targetCond); | |||
| project.addTarget(targetName, target); | |||
| if (name == null) { | |||
| throw new SAXParseException("target element appears without a name attribute", locator); | |||
| } | |||
| if (targetId != null && !targetId.equals("")) | |||
| project.addReference(targetId,target); | |||
| target = new Target(); | |||
| target.setName(name); | |||
| target.setCondition(cond); | |||
| project.addTarget(name, target); | |||
| if (id != null && !id.equals("")) | |||
| project.addReference(id, target); | |||
| // take care of dependencies | |||
| if (targetDep.length() > 0) { | |||
| StringTokenizer tok = | |||
| new StringTokenizer(targetDep, ",", false); | |||
| if (depends.length() > 0) { | |||
| StringTokenizer tok = | |||
| new StringTokenizer(depends, ",", false); | |||
| while (tok.hasMoreTokens()) { | |||
| target.addDependency(tok.nextToken().trim()); | |||
| } | |||
| } | |||
| } | |||
| // populate target with tasks | |||
| configureTasks(project, target, element); | |||
| public void startElement(String name, AttributeList attrs) throws SAXParseException { | |||
| new TaskHandler(this, target).init(name, attrs); | |||
| } | |||
| } | |||
| private static void configureTasks(Project project, | |||
| Target target, | |||
| Element targetElement) | |||
| throws BuildException | |||
| { | |||
| NodeList list = targetElement.getChildNodes(); | |||
| for (int i = 0; i < list.getLength(); i++) { | |||
| Node node = list.item(i); | |||
| // right now, all we are interested in is element nodes | |||
| // not quite sure what to do with others except drop 'em | |||
| if (node.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element element = (Element)node; | |||
| String taskType = element.getTagName(); | |||
| /** | |||
| * Handler for all task elements. | |||
| */ | |||
| private class TaskHandler extends AbstractHandler { | |||
| private Target target; | |||
| private Task task; | |||
| // XXX | |||
| // put in some sanity checking | |||
| public TaskHandler(DocumentHandler parentHandler, Target target) { | |||
| super(parentHandler); | |||
| Task task = project.createTask(taskType); | |||
| this.target = target; | |||
| } | |||
| // get the attributes of this element and reflect them | |||
| // into the task | |||
| public void init(String tag, AttributeList attrs) throws SAXParseException { | |||
| task = project.createTask(tag); | |||
| configure(task, attrs); | |||
| task.setLocation(new Location(buildFile.toString(), locator.getLineNumber(), locator.getColumnNumber())); | |||
| task.init(); | |||
| configure(project, task, element); | |||
| task.init(); | |||
| // Top level tasks don't have associated targets | |||
| if (target != null) { | |||
| task.setTarget(target); | |||
| target.addTask(task); | |||
| } | |||
| } | |||
| processNestedProperties(project, task, element); | |||
| public void characters(char[] buf, int start, int end) throws SAXParseException { | |||
| String text = new String(buf, start, end).trim(); | |||
| if (text.length() == 0) return; | |||
| try { | |||
| Method addProp = task.getClass().getMethod("addText", new Class[]{String.class}); | |||
| Object child = addProp.invoke(task, new Object[] {text}); | |||
| } catch(NoSuchMethodException exc) { | |||
| throw new SAXParseException(task.getClass() + " does not support nested text elements", locator); | |||
| } catch(InvocationTargetException exc) { | |||
| throw new SAXParseException("Error invoking \"addText\" method", locator, exc); | |||
| } catch(IllegalAccessException exc) { | |||
| throw new SAXParseException("Unable to access \"addText\" method", locator, exc); | |||
| } | |||
| } | |||
| public void startElement(String name, AttributeList attrs) throws SAXParseException { | |||
| new NestedPropertyHandler(this, task).init(name, attrs); | |||
| } | |||
| } | |||
| private static void processNestedProperties(Project project, | |||
| Object target, | |||
| Element targetElement) | |||
| throws BuildException | |||
| { | |||
| Class targetClass = target.getClass(); | |||
| NodeList list = targetElement.getChildNodes(); | |||
| for (int i = 0; i < list.getLength(); i++) { | |||
| Node node = list.item(i); | |||
| // right now, all we are interested in is element nodes | |||
| // not quite sure what to do with others except drop 'em | |||
| if (node.getNodeType() == Node.TEXT_NODE) { | |||
| String text = ((Text)node).getData(); | |||
| try { | |||
| Method addProp = targetClass.getMethod( | |||
| "addText", new Class[]{"".getClass()}); | |||
| Object child = addProp.invoke(target, new Object[] {text}); | |||
| } catch (NoSuchMethodException nsme) { | |||
| if (text.trim().length() > 0) | |||
| throw new BuildException(targetClass + | |||
| " does not support nested text elements"); | |||
| } catch (InvocationTargetException ite) { | |||
| throw new BuildException(ite.getMessage()); | |||
| } catch (IllegalAccessException iae) { | |||
| throw new BuildException(iae.getMessage()); | |||
| } | |||
| } | |||
| /** | |||
| * Handler for all nested properties. | |||
| */ | |||
| private class NestedPropertyHandler extends AbstractHandler { | |||
| private DocumentHandler parentHandler; | |||
| if (node.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element element = (Element)node; | |||
| String propType = element.getTagName(); | |||
| String methodName = "create" + | |||
| Character.toUpperCase(propType.charAt(0)) + | |||
| propType.substring(1); | |||
| try { | |||
| Method addProp = | |||
| targetClass.getMethod(methodName, new Class[]{}); | |||
| Object child = addProp.invoke(target, new Object[] {}); | |||
| configure(project, child, element); | |||
| processNestedProperties(project, child, element); | |||
| } catch (NoSuchMethodException nsme) { | |||
| throw new BuildException(targetClass + | |||
| " does not support nested " + propType + " properties"); | |||
| } catch (InvocationTargetException ite) { | |||
| throw new BuildException(ite.getMessage()); | |||
| } catch (IllegalAccessException iae) { | |||
| throw new BuildException(iae.getMessage()); | |||
| } | |||
| private Object target; | |||
| private Object child; | |||
| public NestedPropertyHandler(DocumentHandler parentHandler, Object target) { | |||
| super(parentHandler); | |||
| this.target = target; | |||
| } | |||
| public void init(String propType, AttributeList attrs) throws SAXParseException { | |||
| Class targetClass = target.getClass(); | |||
| String methodName = "create" + Character.toUpperCase(propType.charAt(0)) + propType.substring(1); | |||
| try { | |||
| Method addProp = targetClass.getMethod(methodName, new Class[]{}); | |||
| child = addProp.invoke(target, new Object[] {}); | |||
| configure(child, attrs); | |||
| } catch(NoSuchMethodException exc) { | |||
| throw new SAXParseException(targetClass + " does not support nested " + propType + " properties", locator); | |||
| } catch(InvocationTargetException exc) { | |||
| throw new SAXParseException(exc.getMessage(), locator); | |||
| } catch(IllegalAccessException exc) { | |||
| throw new SAXParseException(exc.getMessage(), locator); | |||
| } | |||
| } | |||
| } | |||
| private static void configure(Project project, | |||
| Object target, | |||
| Element element) | |||
| throws BuildException | |||
| { | |||
| NamedNodeMap nodeMap = element.getAttributes(); | |||
| public void startElement(String name, AttributeList attrs) throws SAXParseException { | |||
| new NestedPropertyHandler(this, child).init(name, attrs); | |||
| } | |||
| } | |||
| private void configure(Object target, AttributeList attrs) throws BuildException { | |||
| if( target instanceof TaskAdapter ) | |||
| target=((TaskAdapter)target).getProxy(); | |||
| @@ -332,48 +436,40 @@ public class ProjectHelper { | |||
| } | |||
| } | |||
| for (int i = 0; i < nodeMap.getLength(); i++) { | |||
| Node node = nodeMap.item(i); | |||
| // these should only be attribs, we won't see anything | |||
| // else here. | |||
| if (node.getNodeType() == Node.ATTRIBUTE_NODE) { | |||
| Attr attr = (Attr)node; | |||
| // reflect these into the target | |||
| for (int i = 0; i < attrs.getLength(); i++) { | |||
| // reflect these into the target | |||
| Method setMethod = (Method)propertySetters.get(attr.getName()); | |||
| if (setMethod == null) { | |||
| if (attr.getName().equals("id")) { | |||
| project.addReference(attr.getValue(), target); | |||
| continue; | |||
| } | |||
| String msg = "Configuration property \"" + attr.getName() + | |||
| "\" does not have a setMethod in " + target.getClass(); | |||
| throw new BuildException(msg); | |||
| Method setMethod = (Method)propertySetters.get(attrs.getName(i)); | |||
| if (setMethod == null) { | |||
| if (attrs.getName(i).equals("id")) { | |||
| project.addReference(attrs.getValue(i), target); | |||
| continue; | |||
| } | |||
| String value=replaceProperties( attr.getValue(), project.getProperties() ); | |||
| try { | |||
| setMethod.invoke(target, new String[] {value}); | |||
| } catch (IllegalAccessException iae) { | |||
| String msg = "Error setting value for attrib: " + | |||
| attr.getName(); | |||
| iae.printStackTrace(); | |||
| throw new BuildException(msg); | |||
| } catch (InvocationTargetException ie) { | |||
| String msg = "Error setting value for attrib: " + | |||
| attr.getName() + " in " + target.getClass().getName(); | |||
| ie.printStackTrace(); | |||
| ie.getTargetException().printStackTrace(); | |||
| throw new BuildException(msg); | |||
| } | |||
| String msg = "Class " + target.getClass() + | |||
| " doesn't support the \"" + attrs.getName(i) + "\" property"; | |||
| throw new BuildException(msg); | |||
| } | |||
| String value=replaceProperties(attrs.getValue(i), project.getProperties() ); | |||
| try { | |||
| setMethod.invoke(target, new String[] {value}); | |||
| } catch (IllegalAccessException iae) { | |||
| String msg = "Error setting value for attrib: " + | |||
| attrs.getName(i); | |||
| iae.printStackTrace(); | |||
| throw new BuildException(msg); | |||
| } catch (InvocationTargetException ie) { | |||
| String msg = "Error setting value for attrib: " + | |||
| attrs.getName(i) + " in " + target.getClass().getName(); | |||
| ie.printStackTrace(); | |||
| ie.getTargetException().printStackTrace(); | |||
| throw new BuildException(msg); | |||
| } | |||
| } | |||
| } | |||
| /** Replace ${NAME} with the property value | |||
| */ | |||
| public static String replaceProperties( String value, Hashtable keys ) | |||
| @@ -411,13 +507,12 @@ public class ProjectHelper { | |||
| // System.out.println("Before replace: " + value); | |||
| return sb.toString(); | |||
| } | |||
| } | |||
| private static SAXParserFactory getParserFactory() { | |||
| if (parserFactory == null) { | |||
| parserFactory = SAXParserFactory.newInstance(); | |||
| } | |||
| return parserFactory; | |||
| } | |||
| } | |||
| @@ -1,81 +0,0 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 1999 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "The Jakarta Project", "Tomcat", 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 | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import com.sun.xml.parser.Resolver; | |||
| import com.sun.xml.tree.XmlDocument; | |||
| import org.w3c.dom.Document; | |||
| import org.xml.sax.InputSource; | |||
| import org.xml.sax.SAXException; | |||
| /** | |||
| * Implementation of Parser using Sun ProjectX. | |||
| * | |||
| * @author pier@apache.org | |||
| */ | |||
| public class SunParser extends Parser { | |||
| /** | |||
| * Parse the specified file and return a DOM Document. | |||
| */ | |||
| public Document parse(File buildFile) | |||
| throws SAXException, IOException { | |||
| InputSource input = Resolver.createInputSource(buildFile); | |||
| return XmlDocument.createXmlDocument(input, false); | |||
| } | |||
| } | |||
| @@ -117,7 +117,13 @@ public class Target { | |||
| Enumeration enum = tasks.elements(); | |||
| while (enum.hasMoreElements()) { | |||
| Task task = (Task) enum.nextElement(); | |||
| task.execute(); | |||
| try { | |||
| task.execute(); | |||
| } catch(BuildException exc) { | |||
| exc.setLocation(task.getLocation()); | |||
| throw exc; | |||
| } | |||
| } | |||
| } else { | |||
| project.log("Skipped because property '" + this.condition + "' not set.", this.name, Project.MSG_VERBOSE); | |||
| @@ -57,13 +57,14 @@ package org.apache.tools.ant; | |||
| /** | |||
| * Base class for all tasks. | |||
| */ | |||
| public abstract class Task { | |||
| protected Project project = null; | |||
| protected Target target = null; | |||
| protected String description=null; | |||
| protected Location location = Location.UNKNOWN_LOCATION; | |||
| /** | |||
| * Sets the project object of this task. This method is used by | |||
| * project when a task is added to it so that the task has | |||
| @@ -87,7 +88,7 @@ public abstract class Task { | |||
| /** Sets a description of the current action. It will be usefull in commenting | |||
| * what we are doing. | |||
| */ | |||
| */ | |||
| public void setDescription( String desc ) { | |||
| description=desc; | |||
| } | |||
| @@ -95,7 +96,7 @@ public abstract class Task { | |||
| public String getDescription() { | |||
| return description; | |||
| } | |||
| /** | |||
| * Called by the project to let the task initialize properly. Normally it does nothing. | |||
| * | |||
| @@ -110,5 +111,18 @@ public abstract class Task { | |||
| */ | |||
| public void execute() throws BuildException {}; | |||
| /** | |||
| * Returns the file location where this task was defined. | |||
| */ | |||
| public Location getLocation() { | |||
| return location; | |||
| } | |||
| /** | |||
| * Sets the file location where this task was defined. | |||
| */ | |||
| public void setLocation(Location location) { | |||
| this.location = location; | |||
| } | |||
| } | |||
| @@ -1 +0,0 @@ | |||
| parser=org.apache.tools.ant.SunParser | |||