diff --git a/bootstrap.bat b/bootstrap.bat
index 53be8e055..d2a70b7b0 100755
--- a/bootstrap.bat
+++ b/bootstrap.bat
@@ -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
diff --git a/bootstrap.sh b/bootstrap.sh
index 0ea973ee7..1e70ebcc6 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -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
diff --git a/build.bat b/build.bat
index ebc5543db..614280239 100755
--- a/build.bat
+++ b/build.bat
@@ -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
diff --git a/build.sh b/build.sh
index 8b92bd3e8..8a6212b42 100755
--- a/build.sh
+++ b/build.sh
@@ -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
diff --git a/build.xml b/build.xml
index e5c29bd88..f77d06f33 100644
--- a/build.xml
+++ b/build.xml
@@ -21,7 +21,7 @@
-
+
diff --git a/src/main/org/apache/tools/ant/ApacheParser.java b/src/main/org/apache/tools/ant/ApacheParser.java
deleted file mode 100644
index 39d0dc67c..000000000
--- a/src/main/org/apache/tools/ant/ApacheParser.java
+++ /dev/null
@@ -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
- * .
- */
-
-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());
- }
- }
-}
diff --git a/src/main/org/apache/tools/ant/BuildException.java b/src/main/org/apache/tools/ant/BuildException.java
index feebdf9f9..aa04cc609 100644
--- a/src/main/org/apache/tools/ant/BuildException.java
+++ b/src/main/org/apache/tools/ant/BuildException.java
@@ -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
* .
- */
+ */
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;
+ }
}
diff --git a/src/main/org/apache/tools/ant/Main.java b/src/main/org/apache/tools/ant/Main.java
index 55e39b0b3..42706bfda 100644
--- a/src/main/org/apache/tools/ant/Main.java
+++ b/src/main/org/apache/tools/ant/Main.java
@@ -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();
}
diff --git a/src/main/org/apache/tools/ant/Parser.java b/src/main/org/apache/tools/ant/Parser.java
deleted file mode 100644
index b25fbcd48..000000000
--- a/src/main/org/apache/tools/ant/Parser.java
+++ /dev/null
@@ -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
- * .
- */
-
-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;
-}
-
-
diff --git a/src/main/org/apache/tools/ant/ProjectHelper.java b/src/main/org/apache/tools/ant/ProjectHelper.java
index 37dc264e3..6192ee897 100644
--- a/src/main/org/apache/tools/ant/ProjectHelper.java
+++ b/src/main/org/apache/tools/ant/ProjectHelper.java
@@ -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;
+ }
+}
diff --git a/src/main/org/apache/tools/ant/SunParser.java b/src/main/org/apache/tools/ant/SunParser.java
deleted file mode 100644
index 2c68d1ade..000000000
--- a/src/main/org/apache/tools/ant/SunParser.java
+++ /dev/null
@@ -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
- * .
- */
-
-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);
- }
-}
-
-
\ No newline at end of file
diff --git a/src/main/org/apache/tools/ant/Target.java b/src/main/org/apache/tools/ant/Target.java
index f38259b25..ddc11bb37 100644
--- a/src/main/org/apache/tools/ant/Target.java
+++ b/src/main/org/apache/tools/ant/Target.java
@@ -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);
diff --git a/src/main/org/apache/tools/ant/Task.java b/src/main/org/apache/tools/ant/Task.java
index 568f257c6..daf7fc1d2 100644
--- a/src/main/org/apache/tools/ant/Task.java
+++ b/src/main/org/apache/tools/ant/Task.java
@@ -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;
+ }
}
diff --git a/src/main/org/apache/tools/ant/parser.properties b/src/main/org/apache/tools/ant/parser.properties
deleted file mode 100644
index 10716a480..000000000
--- a/src/main/org/apache/tools/ant/parser.properties
+++ /dev/null
@@ -1 +0,0 @@
-parser=org.apache.tools.ant.SunParser
\ No newline at end of file