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 |