From 6252354506953777f5b921b8746a54e7d317475a Mon Sep 17 00:00:00 2001
From: Erik Hatcher
Date: Sun, 3 Mar 2002 12:37:41 +0000
Subject: [PATCH] once again for Jose Alberto - think I got it right this time
git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271710 13f79535-47bb-0310-9956-ffa450edef68
---
proposal/sandbox/antlib/build.xml | 46 +-
.../main/org/apache/tools/ant/Project.java | 1539 +++++++++++------
.../org/apache/tools/ant/ProjectHelper.java | 156 +-
.../org/apache/tools/ant/RoleAdapter.java | 5 +
.../org/apache/tools/ant/SymbolTable.java | 646 ++++---
.../org/apache/tools/ant/TaskAdapter.java | 36 +-
.../org/apache/tools/ant/taskdefs/Ant.java | 24 +-
.../org/apache/tools/ant/taskdefs/Antjar.java | 14 +-
.../org/apache/tools/ant/taskdefs/Antlib.java | 682 +++++---
.../tools/ant/types/DataTypeAdapterTask.java | 24 +-
10 files changed, 1971 insertions(+), 1201 deletions(-)
diff --git a/proposal/sandbox/antlib/build.xml b/proposal/sandbox/antlib/build.xml
index 10783034c..4961c04fa 100644
--- a/proposal/sandbox/antlib/build.xml
+++ b/proposal/sandbox/antlib/build.xml
@@ -6,21 +6,24 @@
+
-
-
+
+
-
-
-
+
+
+
+
+
@@ -39,6 +42,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -48,6 +77,11 @@
optimize="${optimize}">
+
+
+
+
+
@@ -56,7 +90,7 @@
-
diff --git a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/Project.java b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/Project.java
index 20f856f4b..118a2d59c 100644
--- a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/Project.java
+++ b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/Project.java
@@ -1,57 +1,56 @@
/*
- * The Apache Software License, Version 1.1
+ * The Apache Software License, Version 1.1
*
- * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
- * reserved.
+ * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
+ * reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * 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.
+ * 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.
+ * 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.
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
*
- * 4. The names "The Jakarta Project", "Ant", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact apache@apache.org.
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
*
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Group.
+ * 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 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
- * .
+ * 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;
@@ -63,35 +62,67 @@ import java.util.Properties;
import java.util.Enumeration;
import java.util.Stack;
import java.lang.reflect.Modifier;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
-
-import org.apache.tools.ant.types.DataTypeAdapterTask;
-import org.apache.tools.ant.types.FilterSet;
-import org.apache.tools.ant.types.FilterSetCollection;
-import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.types.DataTypeAdapterTask;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.FilterSet;
+import org.apache.tools.ant.types.FilterSetCollection;
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.taskdefs.Antlib;
/**
- * Central representation of an Ant project. This class defines a
- * Ant project with all of it's targets and tasks. It also provides
- * the mechanism to kick off a build using a particular target name.
- *
- * This class also encapsulates methods which allow Files to be refered
- * to using abstract path names which are translated to native system
- * file paths at runtime as well as defining various project properties.
+ * Central representation of an Ant project. This class defines a Ant project
+ * with all of it's targets and tasks. It also provides the mechanism to kick
+ * off a build using a particular target name.
*
- * @author duncan@x180.com
+ * This class also encapsulates methods which allow Files to be refered to
+ * using abstract path names which are translated to native system file paths
+ * at runtime as well as defining various project properties.
+ *
+ *@author duncan@x180.com
+ *@author j_a_fernandez@yahoo.com
+ *@created February 27, 2002
*/
public class Project {
+ /**
+ * Description of the Field
+ */
public final static int MSG_ERR = 0;
+ /**
+ * Description of the Field
+ */
public final static int MSG_WARN = 1;
+ /**
+ * Description of the Field
+ */
public final static int MSG_INFO = 2;
+ /**
+ * Description of the Field
+ */
public final static int MSG_VERBOSE = 3;
+ /**
+ * Description of the Field
+ */
public final static int MSG_DEBUG = 4;
+ /**
+ * LoaderId for the CoreLoader.
+ */
+ public final static String CORELOADER_ID = null;
+
+ /**
+ * Description of the Field
+ */
public final static String TASK_ROLE = "task";
- public final static String DATATYPE_ROLE = "datatype";
+ /**
+ * Description of the Field
+ */
+ public final static String DATATYPE_ROLE = "data-type";
// private set of constants to represent the state
// of a DFS of the Target dependencies
@@ -100,15 +131,38 @@ public class Project {
private static String javaVersion;
+ /**
+ * Description of the Field
+ */
public final static String JAVA_1_0 = "1.0";
+ /**
+ * Description of the Field
+ */
public final static String JAVA_1_1 = "1.1";
+ /**
+ * Description of the Field
+ */
public final static String JAVA_1_2 = "1.2";
+ /**
+ * Description of the Field
+ */
public final static String JAVA_1_3 = "1.3";
+ /**
+ * Description of the Field
+ */
public final static String JAVA_1_4 = "1.4";
+ /**
+ * Description of the Field
+ */
public final static String TOKEN_START = FilterSet.DEFAULT_TOKEN_START;
+ /**
+ * Description of the Field
+ */
public final static String TOKEN_END = FilterSet.DEFAULT_TOKEN_END;
+ private final static String CORE_DEFINITIONS = "org/apache/tools/ant/antlib.xml";
+
private String name;
private String description;
@@ -126,13 +180,19 @@ public class Project {
private Vector listeners = new Vector();
- /** The Ant core classloader - may be null if using system loader */
+ /**
+ * The Ant core classloader - may be null if using system loader
+ */
private ClassLoader coreLoader = null;
- /** Records the latest task on a thread */
+ /**
+ * Records the latest task on a thread
+ */
private Hashtable threadTasks = new Hashtable();
- /** Store symbol tables */
+ /**
+ * Store symbol tables
+ */
private SymbolTable symbols;
static {
@@ -161,179 +221,289 @@ public class Project {
private FileUtils fileUtils;
+
+ /**
+ *
+ *
+ * Description: The only reason for this class is to make the
+ * LoadDefinition method visible in this package.
+ *
+ *@author jfernandez
+ *@created February 27, 2002
+ */
+ private class Corelib extends Antlib {
+ /**
+ * Constructor for the Corelib object
+ */
+ Corelib() {
+ super(Project.this);
+ setLoaderid(CORELOADER_ID);
+ getOnerror().setValue("ignore");
+ }
+
+
+ /**
+ * Description of the Method
+ */
+ public void loadCoreDefinitions() {
+ getOnerror().setValue("report");
+ super.loadDefinitions(CORE_DEFINITIONS);
+ }
+ }
+
+
/**
- * create a new ant project
+ * create a new ant project
*/
public Project() {
fileUtils = FileUtils.newFileUtils();
- symbols = new SymbolTable();
- symbols.setProject(this);
+ symbols = new SymbolTable();
+ symbols.setProject(this);
}
-
+
+
/**
- * create a new ant project that inherits from caler project
- * @param p the calling project
+ * create a new ant project that inherits from caller project
+ *
+ *@param p the calling project
*/
- public Project(Project p) {
+ private Project(Project p) {
fileUtils = FileUtils.newFileUtils();
- symbols = new SymbolTable(p);
- symbols.setProject(this);
+ symbols = new SymbolTable(p.getSymbols());
+ symbols.setProject(this);
+ setCoreLoader(p.getCoreLoader());
}
-
+
+
/**
- * Initialise the project.
- *
- * This involves setting the default task definitions and loading the
- * system properties.
+ * Loads the core definitions into the Root project.
*/
- public void init() throws BuildException {
- setJavaVersionProperty();
-
- // Initialize simbol table just in case
- symbols.addRole("task", TaskContainer.class, TaskAdapter.class);
- symbols.addRole("datatype", TaskContainer.class,
- DataTypeAdapterTask.class);
+ private void loadDefinitions() {
+ // Initialize symbol table just in case
+ symbols.addRole(TASK_ROLE, TaskContainer.class, TaskAdapter.class);
+ symbols.addRole(DATATYPE_ROLE, TaskContainer.class,
+ DataTypeAdapterTask.class);
- String defs = "/org/apache/tools/ant/taskdefs/defaults.properties";
+ Corelib load = new Corelib();
+ load.loadDefinitions();
- try {
- Properties props = new Properties();
- InputStream in = this.getClass().getResourceAsStream(defs);
- if (in == null) {
- throw new BuildException("Can't load default task list");
- }
- props.load(in);
- in.close();
-
- Enumeration enum = props.propertyNames();
- while (enum.hasMoreElements()) {
- String key = (String) enum.nextElement();
- String value = props.getProperty(key);
- try {
- Class taskClass = Class.forName(value);
- addTaskDefinition(key, taskClass);
- } catch (NoClassDefFoundError ncdfe) {
- log("Could not load a dependent class (" +
- ncdfe.getMessage() + ") for task " + key, MSG_DEBUG);
- } catch (ClassNotFoundException cnfe) {
- log("Could not load class ("
- + value + ") for task " + key, MSG_DEBUG);
- }
+ // If the most basic of tasks, "property", is not defined
+ // then there was no antlib jars from where to load the descriptors
+ // we should be doing bootstrapping, or ant.jar is not an antlib.
+ if (!isDefinedOnRole(TASK_ROLE, "property")) {
+ load.loadCoreDefinitions();
+
+ if (!isDefinedOnRole(TASK_ROLE, "property")) {
+ throw new BuildException("Can't load core definitions");
}
- } catch (IOException ioe) {
- throw new BuildException("Can't load default task list");
}
+ autoLoadDefinitions();
+ }
- String dataDefs = "/org/apache/tools/ant/types/defaults.properties";
+ private void autoLoadDefinitions() {
+ DirectoryScanner ds = new DirectoryScanner();
+ ds.setBasedir(new File(getProperty("ant.home"),"autolib"));
+ ds.scan();
+ String dirs[] = ds.getIncludedDirectories();
+ for (int i = 0; i < dirs.length; i++) {
+ autoLoad(ds.getBasedir(), dirs[i]);
+ }
+ }
- try{
- Properties props = new Properties();
- InputStream in = this.getClass().getResourceAsStream(dataDefs);
- if (in == null) {
- throw new BuildException("Can't load default datatype list");
- }
- props.load(in);
- in.close();
-
- Enumeration enum = props.propertyNames();
- while (enum.hasMoreElements()) {
- String key = (String) enum.nextElement();
- String value = props.getProperty(key);
- try {
- Class dataClass = Class.forName(value);
- addDataTypeDefinition(key, dataClass);
- } catch (NoClassDefFoundError ncdfe) {
- // ignore...
- } catch (ClassNotFoundException cnfe) {
- // ignore...
- }
- }
- } catch (IOException ioe) {
- throw new BuildException("Can't load default datatype list");
+ private void autoLoad(File base, String dir) {
+ FileSet fs = new FileSet();
+ fs.setProject(this);
+ fs.setDir(new File(base, dir));
+ fs.setIncludes("*.jar");
+
+ Path cp = new Path(this);
+ cp.addFileset(fs);
+ if (cp.size() == 0) {
+ return;
}
+ Antlib.FailureAction fa = new Antlib.FailureAction();
+ fa.setValue("ignore");
+
+ Antlib lib = new Antlib(this);
+ lib.setClasspath(cp);
+ lib.setLoaderid(dir);
+ lib.setOnerror(fa);
+ lib.loadDefinitions();
+ }
+
+ /**
+ * Creates a subproject of the current project.
+ *
+ *@return Description of the Return Value
+ */
+ public Project createSubProject() {
+ return new Project(this);
+ }
+
+
+ /**
+ * Initialise the project. This involves setting the default task
+ * definitions and loading the system properties.
+ *
+ *@exception BuildException Description of the Exception
+ */
+ public void init() throws BuildException {
+ setJavaVersionProperty();
setSystemProperties();
+ if (!isRoleDefined(TASK_ROLE)) {
+ // Top project, need to load the core definitions
+ loadDefinitions();
+ }
}
+
+ /**
+ * Sets the CoreLoader to the default of the Project object
+ */
+ private void setDefaultCoreLoader() {
+ coreLoader = this.getClass().getClassLoader();
+ if (coreLoader == null) {
+ // This should only happen if ANT is being
+ // loader by the Bootstrap classloader
+ // This may be the case in JDK 1.1
+ coreLoader = ClassLoader.getSystemClassLoader();
+ }
+ }
+
+
+ /**
+ * Sets the coreLoader attribute of the Project object
+ *
+ *@param coreLoader The new coreLoader value
+ */
public void setCoreLoader(ClassLoader coreLoader) {
- this.coreLoader = coreLoader;
+ if (coreLoader == null) {
+ setDefaultCoreLoader();
+ }
+ else this.coreLoader = coreLoader;
}
-
+
+
+ /**
+ * Gets the coreLoader attribute of the Project object
+ *
+ *@return The coreLoader value
+ */
public ClassLoader getCoreLoader() {
+ if (coreLoader == null) {
+ setDefaultCoreLoader();
+ }
return coreLoader;
}
-
+
+
+ /**
+ * Adds a feature to the BuildListener attribute of the Project object
+ *
+ *@param listener The feature to be added to the BuildListener attribute
+ */
public void addBuildListener(BuildListener listener) {
listeners.addElement(listener);
}
+
+ /**
+ * Description of the Method
+ *
+ *@param listener Description of the Parameter
+ */
public void removeBuildListener(BuildListener listener) {
listeners.removeElement(listener);
}
+
+ /**
+ * Gets the buildListeners attribute of the Project object
+ *
+ *@return The buildListeners value
+ */
public Vector getBuildListeners() {
return listeners;
}
+
/**
- * Get the symbols associated with this project.
+ * Get the symbols associated with this project.
+ *
+ *@return The symbols value
*/
- public SymbolTable getSymbols() {
- return symbols;
+ private SymbolTable getSymbols() {
+ // Package protected on purpose
+ return symbols;
}
+
/**
- * Output a message to the log with the default log level
- * of MSG_INFO
- * @param msg text to log
+ * Output a message to the log with the default log level of MSG_INFO
+ *
+ *@param msg text to log
*/
-
+
public void log(String msg) {
log(msg, MSG_INFO);
}
+
/**
- * Output a message to the log with the given log level
- * and an event scope of project
- * @param msg text to log
- * @param msgLevel level to log at
+ * Output a message to the log with the given log level and an event scope
+ * of project
+ *
+ *@param msg text to log
+ *@param msgLevel level to log at
*/
public void log(String msg, int msgLevel) {
fireMessageLogged(this, msg, msgLevel);
}
+
/**
- * Output a message to the log with the given log level
- * and an event scope of a task
- * @param task task to use in the log
- * @param msg text to log
- * @param msgLevel level to log at
+ * Output a message to the log with the given log level and an event scope
+ * of a task
+ *
+ *@param task task to use in the log
+ *@param msg text to log
+ *@param msgLevel level to log at
*/
public void log(Task task, String msg, int msgLevel) {
fireMessageLogged(task, msg, msgLevel);
}
+
/**
- * Output a message to the log with the given log level
- * and an event scope of a target
- * @param target target to use in the log
- * @param msg text to log
- * @param msgLevel level to log at
+ * Output a message to the log with the given log level and an event scope
+ * of a target
+ *
+ *@param target target to use in the log
+ *@param msg text to log
+ *@param msgLevel level to log at
*/
public void log(Target target, String msg, int msgLevel) {
fireMessageLogged(target, msg, msgLevel);
}
-
+
+ /**
+ * Gets the globalFilterSet attribute of the Project object
+ *
+ *@return The globalFilterSet value
+ */
public FilterSet getGlobalFilterSet() {
return globalFilterSet;
}
-
+
+
/**
- * set a property. Any existing property of the same name
- * is overwritten, unless it is a user property.
- * @param name name of property
- * @param value new value of the property
+ * set a property. Any existing property of the same name is overwritten,
+ * unless it is a user property.
+ *
+ *@param name name of property
+ *@param value new value of the property
*/
public void setProperty(String name, String value) {
// command line properties take precedence
@@ -343,21 +513,23 @@ public class Project {
}
if (null != properties.get(name)) {
- log("Overriding previous definition of property " + name,
- MSG_VERBOSE);
+ log("Overriding previous definition of property " + name,
+ MSG_VERBOSE);
}
log("Setting project property: " + name + " -> " +
- value, MSG_DEBUG);
+ value, MSG_DEBUG);
properties.put(name, value);
}
+
/**
- * set a property. An existing property of the same name
- * will not be overwritten.
- * @param name name of property
- * @param value new value of the property
- * @since 1.5
+ * set a property. An existing property of the same name will not be
+ * overwritten.
+ *
+ *@param name name of property
+ *@param value new value of the property
+ *@since 1.5
*/
public void setNewProperty(String name, String value) {
if (null != properties.get(name)) {
@@ -365,26 +537,34 @@ public class Project {
return;
}
log("Setting project property: " + name + " -> " +
- value, MSG_DEBUG);
+ value, MSG_DEBUG);
properties.put(name, value);
}
+
/**
- * set a user property, which can not be overwritten by
- * set/unset property calls
- * @see #setProperty(String,String)
+ * set a user property, which can not be overwritten by set/unset property
+ * calls
+ *
+ *@param name The new userProperty value
+ *@param value The new userProperty value
+ *@see #setProperty(String,String)
*/
public void setUserProperty(String name, String value) {
log("Setting ro project property: " + name + " -> " +
- value, MSG_DEBUG);
+ value, MSG_DEBUG);
userProperties.put(name, value);
properties.put(name, value);
}
-
+
+
/**
- * Allows Project and subclasses to set a property unless its
- * already defined as a user property. There are a few cases
- * internally to Project that need to do this currently.
+ * Allows Project and subclasses to set a property unless its already
+ * defined as a user property. There are a few cases internally to Project
+ * that need to do this currently.
+ *
+ *@param name The new propertyInternal value
+ *@param value The new propertyInternal value
*/
private void setPropertyInternal(String name, String value) {
if (null != userProperties.get(name)) {
@@ -393,182 +573,226 @@ public class Project {
properties.put(name, value);
}
+
/**
- * query a property.
- * @param name the name of the property
- * @return the property value, or null for no match
+ * query a property.
+ *
+ *@param name the name of the property
+ *@return the property value, or null for no match
*/
public String getProperty(String name) {
if (name == null) {
- return null;
+ return null;
}
String property = (String) properties.get(name);
return property;
}
+
/**
- * Replace ${} style constructions in the given value with the
- * string value of the corresponding data types.
+ * Replace ${} style constructions in the given value with the string value
+ * of the corresponding data types.
*
- * @param value the string to be scanned for property references.
+ *@param value the string to be scanned for property
+ * references.
+ *@return Description of the Return Value
+ *@exception BuildException Description of the Exception
*/
public String replaceProperties(String value)
- throws BuildException {
+ throws BuildException {
return ProjectHelper.replaceProperties(this, value, properties);
}
+
/**
- * query a user property.
- * @param name the name of the property
- * @return the property value, or null for no match
+ * query a user property.
+ *
+ *@param name the name of the property
+ *@return the property value, or null for no match
*/
public String getUserProperty(String name) {
if (name == null) {
- return null;
+ return null;
}
String property = (String) userProperties.get(name);
return property;
}
+
/**
- * get a copy of the property hashtable
- * @return the hashtable containing all properties, user included
+ * get a copy of the property hashtable
+ *
+ *@return the hashtable containing all properties, user included
*/
public Hashtable getProperties() {
Hashtable propertiesCopy = new Hashtable();
-
+
Enumeration e = properties.keys();
while (e.hasMoreElements()) {
Object name = e.nextElement();
Object value = properties.get(name);
propertiesCopy.put(name, value);
}
-
+
return propertiesCopy;
}
+
/**
- * get a copy of the user property hashtable
- * @return the hashtable user properties only
+ * get a copy of the user property hashtable
+ *
+ *@return the hashtable user properties only
*/
public Hashtable getUserProperties() {
Hashtable propertiesCopy = new Hashtable();
-
+
Enumeration e = userProperties.keys();
while (e.hasMoreElements()) {
Object name = e.nextElement();
Object value = properties.get(name);
propertiesCopy.put(name, value);
}
-
+
return propertiesCopy;
}
+
/**
- * set the default target of the project
- * @deprecated, use setDefault
- * @see #setDefault(String)
+ * set the default target of the project
+ *
+ *@param defaultTarget The new defaultTarget value
+ *@deprecated, use setDefault
+ *@see #setDefault(String)
*/
public void setDefaultTarget(String defaultTarget) {
this.defaultTarget = defaultTarget;
}
+
/**
- * get the default target of the project
- * @return default target or null
+ * get the default target of the project
+ *
+ *@return default target or null
*/
public String getDefaultTarget() {
return defaultTarget;
}
-
+
/**
- * set the default target of the project
- * XML attribute name.
+ * set the default target of the project XML attribute name.
+ *
+ *@param defaultTarget The new default value
*/
public void setDefault(String defaultTarget) {
this.defaultTarget = defaultTarget;
}
+
/**
- * ant xml property. Set the project name as
- * an attribute of this class, and of the property
- * ant.project.name
+ * ant xml property. Set the project name as an attribute of this class,
+ * and of the property ant.project.name
+ *
+ *@param name The new name value
*/
public void setName(String name) {
- setUserProperty("ant.project.name", name);
+ setUserProperty("ant.project.name", name);
this.name = name;
}
- /** get the project name
- * @return name string
+
+ /**
+ * get the project name
+ *
+ *@return name string
*/
public String getName() {
return name;
}
- /** set the project description
- * @param description text
+
+ /**
+ * set the project description
+ *
+ *@param description text
*/
public void setDescription(String description) {
this.description = description;
}
- /** get the project description
- * @return description or null if no description has been set
+
+ /**
+ * get the project description
+ *
+ *@return description or null if no description has been set
*/
public String getDescription() {
return description;
}
- /** @deprecated */
+
+ /**
+ *@param token The feature to be added to the Filter attribute
+ *@param value The feature to be added to the Filter attribute
+ *@deprecated
+ */
public void addFilter(String token, String value) {
if (token == null) {
return;
}
-
+
globalFilterSet.addFilter(new FilterSet.Filter(token, value));
}
- /** @deprecated */
+
+ /**
+ *@return The filters value
+ *@deprecated
+ */
public Hashtable getFilters() {
// we need to build the hashtable dynamically
return globalFilterSet.getFilterHash();
}
+
/**
- * match basedir attribute in xml
- * @param baseD project base directory.
- * @throws BuildException if the directory was invalid
+ * match basedir attribute in xml
+ *
+ *@param baseD project base directory.
+ *@throws BuildException if the directory was invalid
*/
public void setBasedir(String baseD) throws BuildException {
setBaseDir(new File(baseD));
}
+
/**
- * set the base directory; XML attribute.
- * checks for the directory existing and being a directory type
- * @param baseDir project base directory.
- * @throws BuildException if the directory was invalid
+ * set the base directory; XML attribute. checks for the directory existing
+ * and being a directory type
+ *
+ *@param baseDir project base directory.
+ *@throws BuildException if the directory was invalid
*/
public void setBaseDir(File baseDir) throws BuildException {
baseDir = fileUtils.normalize(baseDir.getAbsolutePath());
- if (!baseDir.exists()) {
+ if (!baseDir.exists()) {
throw new BuildException("Basedir " + baseDir.getAbsolutePath() + " does not exist");
}
- if (!baseDir.isDirectory()) {
+ if (!baseDir.isDirectory()) {
throw new BuildException("Basedir " + baseDir.getAbsolutePath() + " is not a directory");
}
this.baseDir = baseDir;
- setPropertyInternal( "basedir", this.baseDir.getPath());
+ setPropertyInternal("basedir", this.baseDir.getPath());
String msg = "Project base dir set to: " + this.baseDir;
log(msg, MSG_VERBOSE);
}
+
/**
- * get the base directory of the project as a file object
- * @return the base directory. If this is null, then the base
- * dir is not valid
+ * get the base directory of the project as a file object
+ *
+ *@return the base directory. If this is null, then the base dir is not
+ * valid
*/
public File getBaseDir() {
if (baseDir == null) {
@@ -581,18 +805,22 @@ public class Project {
return baseDir;
}
+
/**
- * static query of the java version
- * @return something like "1.1" or "1.3"
+ * static query of the java version
+ *
+ *@return something like "1.1" or "1.3"
*/
public static String getJavaVersion() {
return javaVersion;
}
+
/**
- * set the ant.java.version property, also tests for
- * unsupported JVM versions, prints the verbose log messages
- * @throws BuildException if this Java version is not supported
+ * set the ant.java.version property, also tests for unsupported JVM
+ * versions, prints the verbose log messages
+ *
+ *@throws BuildException if this Java version is not supported
*/
public void setJavaVersionProperty() throws BuildException {
setPropertyInternal("ant.java.version", javaVersion);
@@ -607,163 +835,202 @@ public class Project {
log("Detected OS: " + System.getProperty("os.name"), MSG_VERBOSE);
}
+
+ /**
+ * turn all the system properties into ant properties. user properties
+ * still override these values
+ */
+ public void setSystemProperties() {
+ Properties systemP = System.getProperties();
+ Enumeration e = systemP.keys();
+ while (e.hasMoreElements()) {
+ Object name = e.nextElement();
+ String value = systemP.get(name).toString();
+ this.setPropertyInternal(name.toString(), value);
+ }
+ }
+
+
+ /**
+ * Adds a feature to the ToLoader attribute of the Project object
+ *
+ *@param loader The feature to be added to the ToLoader attribute
+ *@param path The feature to be added to the ToLoader attribute
+ *@return Description of the Return Value
+ */
public ClassLoader addToLoader(String loader, Path path) {
- return symbols.addToLoader(loader, path);
+ if (loader == CORELOADER_ID) {
+ // It is not possible to add more libraries to the CoreLoader
+ // Just return it as is.
+ return getCoreLoader();
+ }
+ return symbols.addToLoader(loader, path);
}
- public boolean addRoleDefinition(String role,
- Class roleClass, Class adapter)
- {
- return symbols.addRole(role, roleClass, adapter);
+
+ /**
+ * Adds a feature to the RoleDefinition attribute of the Project object
+ *
+ *@param role The feature to be added to the RoleDefinition attribute
+ *@param roleClass The feature to be added to the RoleDefinition attribute
+ *@param adapter The feature to be added to the RoleDefinition attribute
+ *@return Description of the Return Value
+ */
+ public boolean addRoleDefinition(String role,
+ Class roleClass, Class adapter) {
+ return symbols.addRole(role, roleClass, adapter);
}
+
/**
- * test for a role name being in use already
+ * test for a role name being in use already
*
- * @param name the name to test
- * @return true if it is a task or a datatype
+ *@param name the name to test
+ *@return true if it is a task or a datatype
*/
public boolean isRoleDefined(String name) {
- return (symbols.getRole(name) != null);
+ return (symbols.getRole(name) != null);
}
+
+ /**
+ * Adds a feature to the DefinitionOnRole attribute of the Project object
+ *
+ *@param role The feature to be added to the DefinitionOnRole attribute
+ *@param type The feature to be added to the DefinitionOnRole attribute
+ *@param clz The feature to be added to the DefinitionOnRole attribute
+ */
public void addDefinitionOnRole(String role,
- String type, Class clz)
- {
- Class old = symbols.add(role, type, clz);
- // Special management for Tasks
+ String type, Class clz) {
+ Class old = symbols.add(role, type, clz);
+ // Special management for Tasks
if (TASK_ROLE.equals(role) && null != old && !old.equals(clz)) {
- invalidateCreatedTasks(type);
+ invalidateCreatedTasks(type);
}
}
+
/**
- * test for a name being in use already on this role
+ * test for a name being in use already on this role
*
- * @param name the name to test
- * @return true if it is a task or a datatype
+ *@param name the name to test
+ *@param role Description of the Parameter
+ *@return true if it is a task or a datatype
*/
public boolean isDefinedOnRole(String role, String name) {
- return (symbols.get(role, name) != null);
- }
-
- /**
- * turn all the system properties into ant properties.
- * user properties still override these values
- */
- public void setSystemProperties() {
- Properties systemP = System.getProperties();
- Enumeration e = systemP.keys();
- while (e.hasMoreElements()) {
- Object name = e.nextElement();
- String value = systemP.get(name).toString();
- this.setPropertyInternal(name.toString(), value);
- }
+ return (symbols.get(role, name) != null);
}
+
/**
- * add a new task definition, complain if there is an overwrite attempt
- * @param taskName name of the task
- * @param taskClass full task classname
- * @throws BuildException and logs as Project.MSG_ERR for
- * conditions, that will cause the task execution to fail.
+ * add a new task definition, complain if there is an overwrite attempt
+ *
+ *@param taskName name of the task
+ *@param taskClass full task classname
+ *@throws BuildException and logs as Project.MSG_ERR for conditions, that
+ * will cause the task execution to fail.
*/
- public void addTaskDefinition(String taskName, Class taskClass)
- throws BuildException {
- Class old = symbols.add("task", taskName, taskClass);
- if (null != old && !old.equals(taskClass)) {
- invalidateCreatedTasks(taskName);
- }
-
- String msg =
- " +User task: " + taskName + " " + taskClass.getName();
- log(msg, MSG_DEBUG);
- checkTaskClass(taskClass);
+ public void addTaskDefinition(String taskName, Class taskClass)
+ throws BuildException {
+ addDefinitionOnRole(TASK_ROLE, taskName, taskClass);
}
+
/**
- * Checks a class, whether it is suitable for serving as ant task.
- * @throws BuildException and logs as Project.MSG_ERR for
- * conditions, that will cause the task execution to fail.
+ * Checks a class, whether it is suitable for serving as ant task.
+ *
+ *@param taskClass Description of the Parameter
+ *@throws BuildException and logs as Project.MSG_ERR for conditions, that
+ * will cause the task execution to fail.
+ *@deprecated this is done now when added to SymbolTable
*/
public void checkTaskClass(final Class taskClass) throws BuildException {
- if( !Task.class.isAssignableFrom(taskClass) ) {
+ if (!Task.class.isAssignableFrom(taskClass)) {
TaskAdapter.checkTaskClass(taskClass, this);
}
}
+
/**
- * get the current task definition hashtable
+ * get the current task definition hashtable
+ *
+ *@return The taskDefinitions value
*/
public Hashtable getTaskDefinitions() {
- return symbols.getTaskDefinitions();
+ return symbols.getDefinitions(TASK_ROLE);
}
+
/**
- * add a new datatype
- * @param typeName name of the datatype
- * @param typeClass full datatype classname
+ * add a new datatype
+ *
+ *@param typeName name of the datatype
+ *@param typeClass full datatype classname
*/
public void addDataTypeDefinition(String typeName, Class typeClass) {
- symbols.add("datatype", typeName, typeClass);
-
- String msg =
- " +User datatype: " + typeName + " " + typeClass.getName();
- log(msg, MSG_DEBUG);
+ addDefinitionOnRole(DATATYPE_ROLE, typeName, typeClass);
}
+
/**
- * get the current task definition hashtable
+ * get the current task definition hashtable
+ *
+ *@return The dataTypeDefinitions value
*/
public Hashtable getDataTypeDefinitions() {
- return symbols.getDataTypeDefinitions();
+ return symbols.getDefinitions(DATATYPE_ROLE);
}
+
/**
- * This call expects to add a new Target.
- * @param target is the Target to be added to the current
- * Project.
- * @exception BuildException if the Target already exists
- * in the project.
- * @see Project#addOrReplaceTarget to replace existing Targets.
+ * This call expects to add a new Target.
+ *
+ *@param target is the Target to be added to the current
+ * Project.
+ *@see Project#addOrReplaceTarget to replace existing
+ * Targets.
*/
public void addTarget(Target target) {
String name = target.getName();
if (targets.get(name) != null) {
- throw new BuildException("Duplicate target: `"+name+"'");
+ throw new BuildException("Duplicate target: `" + name + "'");
}
addOrReplaceTarget(name, target);
}
+
/**
- * This call expects to add a new Target.
- * @param target is the Target to be added to the current
- * Project.
- * @param targetName is the name to use for the Target
- * @exception BuildException if the Target already exists
- * in the project.
- * @see Project#addOrReplaceTarget to replace existing Targets.
- */
- public void addTarget(String targetName, Target target)
- throws BuildException {
- if (targets.get(targetName) != null) {
- throw new BuildException("Duplicate target: `"+targetName+"'");
- }
- addOrReplaceTarget(targetName, target);
- }
+ * This call expects to add a new Target.
+ *
+ *@param target is the Target to be added to the current
+ * Project.
+ *@param targetName is the name to use for the Target
+ *@exception BuildException if the Target already exists in the project.
+ *@see Project#addOrReplaceTarget to replace existing
+ * Targets.
+ */
+ public void addTarget(String targetName, Target target)
+ throws BuildException {
+ if (targets.get(targetName) != null) {
+ throw new BuildException("Duplicate target: `" + targetName + "'");
+ }
+ addOrReplaceTarget(targetName, target);
+ }
+
/**
- * @param target is the Target to be added or replaced in
- * the current Project.
+ *@param target is the Target to be added or replaced in the current
+ * Project.
*/
public void addOrReplaceTarget(Target target) {
addOrReplaceTarget(target.getName(), target);
}
+
/**
- * @param target is the Target to be added/replaced in
- * the current Project.
- * @param targetName is the name to use for the Target
+ *@param target is the Target to be added/replaced in the current
+ * Project.
+ *@param targetName is the name to use for the Target
*/
public void addOrReplaceTarget(String targetName, Target target) {
String msg = " +Target: " + targetName;
@@ -772,59 +1039,123 @@ public class Project {
targets.put(targetName, target);
}
+
/**
- * get the target hashtable
- * @return hashtable, the contents of which can be cast to Target
+ * get the target hashtable
+ *
+ *@return hashtable, the contents of which can be cast to Target
*/
public Hashtable getTargets() {
return targets;
}
+
/**
- * create a new task instance
- * @param taskType name of the task
- * @throws BuildException when task creation goes bad
- * @return null if the task name is unknown
+ * Create a new element instance on a Role
+ *
+ *@param role name of the role to use
+ *@param type name of the element to create
+ *@return null if element unknown on this role
*/
- public Task createTask(String taskType) throws BuildException {
- Class c = symbols.get("task", taskType);
-
- if (c == null) {
+ public Object createForRole(String role, String type) {
+ SymbolTable.Factory f = symbols.get(role, type);
+ if (f == null) {
return null;
}
-
+
try {
- Object o = c.newInstance();
- Task task = null;
- if( o instanceof Task ) {
- task=(Task)o;
- } else {
- // "Generic" Bean - use the setter pattern
- // and an Adapter
- TaskAdapter taskA=new TaskAdapter();
- taskA.setProxy( o );
- task=taskA;
+ Object o = f.create(this);
+ // Do special book keeping for ProjectComponents
+ if (o instanceof ProjectComponent) {
+ ((ProjectComponent) o).setProject(this);
+ if (o instanceof Task) {
+ Task task = (Task) o;
+ task.setTaskType(type);
+
+ // set default value, can be changed by the user
+ task.setTaskName(type);
+ addCreatedTask(type, task);
+ }
}
- task.setProject(this);
- task.setTaskType(taskType);
-
- // set default value, can be changed by the user
- task.setTaskName(taskType);
-
- String msg = " +Task: " + taskType;
- log (msg, MSG_DEBUG);
- addCreatedTask(taskType, task);
- return task;
+ String msg = " +" + role + ": " + type;
+ log(msg, MSG_DEBUG);
+ return o;
} catch (Throwable t) {
- String msg = "Could not create task of type: "
- + taskType + " due to " + t;
+ String msg = "Could not create " + role + " of type: "
+ + type + " due to " + t;
throw new BuildException(msg, t);
}
}
+
+ /**
+ *@param container Description of the Parameter
+ *@param type Description of the Parameter
+ *@return Description of the Return Value
+ */
+ public Object createInRole(Object container, String type) {
+ Class clz = container.getClass();
+ String roles[] = symbols.findRoles(clz);
+ Object theOne = null;
+ Method add = null;
+
+ for (int i = 0; i < roles.length; i++) {
+ Object o = createForRole(roles[i], type);
+ if (o != null) {
+ if (theOne != null) {
+ String msg = "Element " + type +
+ " is ambiguous for container " + clz.getName();
+ if (theOne instanceof RoleAdapter) {
+ theOne = ((RoleAdapter) theOne).getProxy();
+ }
+ if (o instanceof RoleAdapter) {
+ o = ((RoleAdapter) o).getProxy();
+ }
+
+ log(msg, MSG_ERR);
+ log("cannot distinguish between " +
+ theOne.getClass().getName() +
+ " and " + o.getClass().getName(), MSG_ERR);
+ throw new BuildException(msg);
+ }
+ theOne = o;
+ add = symbols.getRole(roles[i]).getInterfaceMethod();
+ }
+ }
+ if (theOne != null) {
+ try {
+ add.invoke(container, new Object[]{theOne});
+ } catch (InvocationTargetException ite) {
+ if (ite.getTargetException() instanceof BuildException) {
+ throw (BuildException) ite.getTargetException();
+ }
+ throw new BuildException(ite.getTargetException());
+ } catch (Exception e) {
+ throw new BuildException(e);
+ }
+ }
+ return theOne;
+ }
+
+
/**
- * Keep a record of all tasks that have been created so that they
- * can be invalidated if a taskdef overrides the definition.
+ * create a new task instance
+ *
+ *@param taskType name of the task
+ *@return null if the task name is unknown
+ *@throws BuildException when task creation goes bad
+ */
+ public Task createTask(String taskType) throws BuildException {
+ return (Task) createForRole(TASK_ROLE, taskType);
+ }
+
+
+ /**
+ * Keep a record of all tasks that have been created so that they can be
+ * invalidated if a taskdef overrides the definition.
+ *
+ *@param type The feature to be added to the CreatedTask attribute
+ *@param task The feature to be added to the CreatedTask attribute
*/
private void addCreatedTask(String type, Task task) {
synchronized (createdTasks) {
@@ -837,9 +1168,12 @@ public class Project {
}
}
+
/**
- * Mark tasks as invalid which no longer are of the correct type
- * for a given taskname.
+ * Mark tasks as invalid which no longer are of the correct type for a
+ * given taskname.
+ *
+ *@param type Description of the Parameter
*/
private void invalidateCreatedTasks(String type) {
synchronized (createdTasks) {
@@ -856,88 +1190,63 @@ public class Project {
}
}
+
/**
- * create a new DataType instance
- * @param typeName name of the datatype
- * @throws BuildException when datatype creation goes bad
- * @return null if the datatype name is unknown
+ * create a new DataType instance
+ *
+ *@param typeName name of the datatype
+ *@return null if the datatype name is unknown
+ *@throws BuildException when datatype creation goes bad
*/
public Object createDataType(String typeName) throws BuildException {
- Class c = symbols.get("datatype", typeName);
-
- if (c == null) {
- return null;
- }
-
- try {
- java.lang.reflect.Constructor ctor = null;
- boolean noArg = false;
- // DataType can have a "no arg" constructor or take a single
- // Project argument.
- try {
- ctor = c.getConstructor(new Class[0]);
- noArg = true;
- } catch (NoSuchMethodException nse) {
- ctor = c.getConstructor(new Class[] {Project.class});
- noArg = false;
- }
-
- Object o = null;
- if (noArg) {
- o = ctor.newInstance(new Object[0]);
- } else {
- o = ctor.newInstance(new Object[] {this});
- }
- if (o instanceof ProjectComponent) {
- ((ProjectComponent)o).setProject(this);
- }
- String msg = " +DataType: " + typeName;
- log (msg, MSG_DEBUG);
- return o;
- } catch (java.lang.reflect.InvocationTargetException ite) {
- Throwable t = ite.getTargetException();
- String msg = "Could not create datatype of type: "
- + typeName + " due to " + t;
- throw new BuildException(msg, t);
- } catch (Throwable t) {
- String msg = "Could not create datatype of type: "
- + typeName + " due to " + t;
- throw new BuildException(msg, t);
- }
+ // This is to make the function backward compatible
+ // Since we know if it returning an adapter for it
+ DataTypeAdapterTask dt =
+ (DataTypeAdapterTask) createForRole(DATATYPE_ROLE, typeName);
+ return (dt != null ? dt.getProxy() : null);
}
+
/**
- * execute the sequence of targets, and the targets they depend on
- * @param Vector a vector of target name strings
- * @throws BuildException if the build failed
+ * execute the sequence of targets, and the targets they depend on
+ *
+ *@param targetNames Description of the Parameter
+ *@throws BuildException if the build failed
*/
public void executeTargets(Vector targetNames) throws BuildException {
Throwable error = null;
for (int i = 0; i < targetNames.size(); i++) {
- executeTarget((String)targetNames.elementAt(i));
+ executeTarget((String) targetNames.elementAt(i));
}
}
+
+ /**
+ * Description of the Method
+ *
+ *@param line Description of the Parameter
+ *@param isError Description of the Parameter
+ */
public void demuxOutput(String line, boolean isError) {
- Task task = (Task)threadTasks.get(Thread.currentThread());
+ Task task = (Task) threadTasks.get(Thread.currentThread());
if (task == null) {
fireMessageLogged(this, line, isError ? MSG_ERR : MSG_INFO);
- }
- else {
+ } else {
if (isError) {
task.handleErrorOutput(line);
- }
- else {
+ } else {
task.handleOutput(line);
}
}
}
-
+
+
/**
- * execute the targets and any targets it depends on
- * @param targetName the target to execute
- * @throws BuildException if the build failed
+ * execute the targets and any targets it depends on
+ *
+ *@param targetName the target to execute
+ *@throws BuildException if the build failed
*/
public void executeTarget(String targetName) throws BuildException {
@@ -965,37 +1274,47 @@ public class Project {
} while (!curtarget.getName().equals(targetName));
}
+
/**
- * Return the canonical form of fileName as an absolute path.
+ * Return the canonical form of fileName as an absolute path.
*
- *
If fileName is a relative file name, resolve it relative to
- * rootDir.
+ * If fileName is a relative file name, resolve it relative to rootDir.
*
- * @deprecated
+ *@param fileName Description of the Parameter
+ *@param rootDir Description of the Parameter
+ *@return Description of the Return Value
+ *@deprecated
*/
public File resolveFile(String fileName, File rootDir) {
return fileUtils.resolveFile(rootDir, fileName);
}
+
+ /**
+ * Description of the Method
+ *
+ *@param fileName Description of the Parameter
+ *@return Description of the Return Value
+ */
public File resolveFile(String fileName) {
return fileUtils.resolveFile(baseDir, fileName);
}
+
/**
- * Translate a path into its native (platform specific) format.
- *
- * This method uses the PathTokenizer class to separate the input path
- * into its components. This handles DOS style paths in a relatively
- * sensible way. The file separators are then converted to their platform
- * specific versions.
+ * Translate a path into its native (platform specific) format.
*
- * @param to_process the path to be converted
+ * This method uses the PathTokenizer class to separate the input path into
+ * its components. This handles DOS style paths in a relatively sensible
+ * way. The file separators are then converted to their platform specific
+ * versions.
*
- * @return the native version of to_process or
- * an empty string if to_process is null or empty
+ *@param to_process the path to be converted
+ *@return the native version of to_process or an empty string if
+ * to_process is null or empty
*/
public static String translatePath(String to_process) {
- if ( to_process == null || to_process.length() == 0 ) {
+ if (to_process == null || to_process.length() == 0) {
return "";
}
@@ -1010,142 +1329,178 @@ public class Project {
}
path.append(pathComponent);
}
-
+
return path.toString();
}
+
/**
- * Convienence method to copy a file from a source to a destination.
- * No filtering is performed.
+ * Convienence method to copy a file from a source to a destination. No
+ * filtering is performed.
*
- * @throws IOException
- *
- * @deprecated
+ *@param sourceFile Description of the Parameter
+ *@param destFile Description of the Parameter
+ *@throws IOException
+ *@deprecated
*/
public void copyFile(String sourceFile, String destFile) throws IOException {
fileUtils.copyFile(sourceFile, destFile);
}
+
/**
- * Convienence method to copy a file from a source to a destination
- * specifying if token filtering must be used.
+ * Convienence method to copy a file from a source to a destination
+ * specifying if token filtering must be used.
*
- * @throws IOException
- *
- * @deprecated
+ *@param sourceFile Description of the Parameter
+ *@param destFile Description of the Parameter
+ *@param filtering Description of the Parameter
+ *@throws IOException
+ *@deprecated
*/
public void copyFile(String sourceFile, String destFile, boolean filtering)
- throws IOException {
+ throws IOException {
fileUtils.copyFile(sourceFile, destFile, filtering ? globalFilters : null);
}
+
/**
- * Convienence method to copy a file from a source to a
- * destination specifying if token filtering must be used and if
- * source files may overwrite newer destination files.
- *
- * @throws IOException
+ * Convienence method to copy a file from a source to a destination
+ * specifying if token filtering must be used and if source files may
+ * overwrite newer destination files.
*
- * @deprecated
+ *@param sourceFile Description of the Parameter
+ *@param destFile Description of the Parameter
+ *@param filtering Description of the Parameter
+ *@param overwrite Description of the Parameter
+ *@throws IOException
+ *@deprecated
*/
public void copyFile(String sourceFile, String destFile, boolean filtering,
- boolean overwrite) throws IOException {
+ boolean overwrite) throws IOException {
fileUtils.copyFile(sourceFile, destFile, filtering ? globalFilters : null, overwrite);
}
- /**
- * Convienence method to copy a file from a source to a
- * destination specifying if token filtering must be used, if
- * source files may overwrite newer destination files and the
- * last modified time of destFile
file should be made equal
- * to the last modified time of sourceFile
.
- *
- * @throws IOException
+
+ /**
+ * Convienence method to copy a file from a source to a destination
+ * specifying if token filtering must be used, if source files may
+ * overwrite newer destination files and the last modified time of destFile
+ * file should be made equal to the last modified time of sourceFile
+ * .
*
- * @deprecated
+ *@param sourceFile Description of the Parameter
+ *@param destFile Description of the Parameter
+ *@param filtering Description of the Parameter
+ *@param overwrite Description of the Parameter
+ *@param preserveLastModified Description of the Parameter
+ *@throws IOException
+ *@deprecated
*/
public void copyFile(String sourceFile, String destFile, boolean filtering,
- boolean overwrite, boolean preserveLastModified)
- throws IOException {
- fileUtils.copyFile(sourceFile, destFile, filtering ? globalFilters : null,
- overwrite, preserveLastModified);
+ boolean overwrite, boolean preserveLastModified)
+ throws IOException {
+ fileUtils.copyFile(sourceFile, destFile, filtering ? globalFilters : null,
+ overwrite, preserveLastModified);
}
+
/**
- * Convienence method to copy a file from a source to a destination.
- * No filtering is performed.
- *
- * @throws IOException
+ * Convienence method to copy a file from a source to a destination. No
+ * filtering is performed.
*
- * @deprecated
+ *@param sourceFile Description of the Parameter
+ *@param destFile Description of the Parameter
+ *@throws IOException
+ *@deprecated
*/
public void copyFile(File sourceFile, File destFile) throws IOException {
fileUtils.copyFile(sourceFile, destFile);
}
+
/**
- * Convienence method to copy a file from a source to a destination
- * specifying if token filtering must be used.
+ * Convienence method to copy a file from a source to a destination
+ * specifying if token filtering must be used.
*
- * @throws IOException
- *
- * @deprecated
+ *@param sourceFile Description of the Parameter
+ *@param destFile Description of the Parameter
+ *@param filtering Description of the Parameter
+ *@throws IOException
+ *@deprecated
*/
public void copyFile(File sourceFile, File destFile, boolean filtering)
- throws IOException {
+ throws IOException {
fileUtils.copyFile(sourceFile, destFile, filtering ? globalFilters : null);
}
+
/**
- * Convienence method to copy a file from a source to a
- * destination specifying if token filtering must be used and if
- * source files may overwrite newer destination files.
- *
- * @throws IOException
+ * Convienence method to copy a file from a source to a destination
+ * specifying if token filtering must be used and if source files may
+ * overwrite newer destination files.
*
- * @deprecated
+ *@param sourceFile Description of the Parameter
+ *@param destFile Description of the Parameter
+ *@param filtering Description of the Parameter
+ *@param overwrite Description of the Parameter
+ *@throws IOException
+ *@deprecated
*/
public void copyFile(File sourceFile, File destFile, boolean filtering,
- boolean overwrite) throws IOException {
+ boolean overwrite) throws IOException {
fileUtils.copyFile(sourceFile, destFile, filtering ? globalFilters : null, overwrite);
}
+
/**
- * Convienence method to copy a file from a source to a
- * destination specifying if token filtering must be used, if
- * source files may overwrite newer destination files and the
- * last modified time of destFile
file should be made equal
- * to the last modified time of sourceFile
.
- *
- * @throws IOException
+ * Convienence method to copy a file from a source to a destination
+ * specifying if token filtering must be used, if source files may
+ * overwrite newer destination files and the last modified time of destFile
+ * file should be made equal to the last modified time of sourceFile
+ * .
*
- * @deprecated
+ *@param sourceFile Description of the Parameter
+ *@param destFile Description of the Parameter
+ *@param filtering Description of the Parameter
+ *@param overwrite Description of the Parameter
+ *@param preserveLastModified Description of the Parameter
+ *@throws IOException
+ *@deprecated
*/
public void copyFile(File sourceFile, File destFile, boolean filtering,
- boolean overwrite, boolean preserveLastModified)
- throws IOException {
- fileUtils.copyFile(sourceFile, destFile, filtering ? globalFilters : null,
- overwrite, preserveLastModified);
+ boolean overwrite, boolean preserveLastModified)
+ throws IOException {
+ fileUtils.copyFile(sourceFile, destFile, filtering ? globalFilters : null,
+ overwrite, preserveLastModified);
}
+
/**
- * Calls File.setLastModified(long time) in a Java 1.1 compatible way.
+ * Calls File.setLastModified(long time) in a Java 1.1 compatible way.
*
- * @deprecated
+ *@param file The new fileLastModified value
+ *@param time The new fileLastModified value
+ *@exception BuildException Description of the Exception
+ *@deprecated
*/
public void setFileLastModified(File file, long time) throws BuildException {
if (getJavaVersion() == JAVA_1_1) {
log("Cannot change the modification time of " + file
- + " in JDK 1.1", Project.MSG_WARN);
+ + " in JDK 1.1", Project.MSG_WARN);
return;
}
fileUtils.setFileLastModified(file, time);
log("Setting modification time for " + file, MSG_VERBOSE);
}
+
/**
- * returns the boolean equivalent of a string, which is considered true
- * if either "on", "true", or "yes" is found, ignoring case.
+ * returns the boolean equivalent of a string, which is considered true if
+ * either "on", "true", or "yes" is found, ignoring case.
+ *
+ *@param s Description of the Parameter
+ *@return Description of the Return Value
*/
public static boolean toBoolean(String s) {
return (s.equalsIgnoreCase("on") ||
@@ -1153,19 +1508,22 @@ public class Project {
s.equalsIgnoreCase("yes"));
}
+
/**
- * Topologically sort a set of Targets.
- * @param root is the (String) name of the root Target. The sort is
- * created in such a way that the sequence of Targets uptil the root
- * target is the minimum possible such sequence.
- * @param targets is a Hashtable representing a "name to Target" mapping
- * @return a Vector of Strings with the names of the targets in
- * sorted order.
- * @exception BuildException if there is a cyclic dependency among the
- * Targets, or if a Target does not exist.
+ * Topologically sort a set of Targets.
+ *
+ *@param root is the (String) name of the root Target. The
+ * sort is created in such a way that the sequence of Targets uptil the
+ * root target is the minimum possible such sequence.
+ *@param targets is a Hashtable representing a "name to Target"
+ * mapping
+ *@return a Vector of Strings with the names of the
+ * targets in sorted order.
+ *@exception BuildException if there is a cyclic dependency among the
+ * Targets, or if a Target does not exist.
*/
public final Vector topoSort(String root, Hashtable targets)
- throws BuildException {
+ throws BuildException {
Vector ret = new Vector();
Hashtable state = new Hashtable();
Stack visiting = new Stack();
@@ -1179,21 +1537,21 @@ public class Project {
// build Target.
tsort(root, targets, state, visiting, ret);
- log("Build sequence for target `"+root+"' is "+ret, MSG_VERBOSE);
- for (Enumeration en=targets.keys(); en.hasMoreElements();) {
- String curTarget = (String)(en.nextElement());
+ log("Build sequence for target `" + root + "' is " + ret, MSG_VERBOSE);
+ for (Enumeration en = targets.keys(); en.hasMoreElements(); ) {
+ String curTarget = (String) (en.nextElement());
String st = (String) state.get(curTarget);
if (st == null) {
tsort(curTarget, targets, state, visiting, ret);
- }
- else if (st == VISITING) {
- throw new RuntimeException("Unexpected node in visiting state: "+curTarget);
+ } else if (st == VISITING) {
+ throw new RuntimeException("Unexpected node in visiting state: " + curTarget);
}
}
- log("Complete build sequence is "+ret, MSG_VERBOSE);
+ log("Complete build sequence is " + ret, MSG_VERBOSE);
return ret;
}
+
// one step in a recursive DFS traversal of the Target dependency tree.
// - The Hashtable "state" contains the state (VISITED or VISITING or null)
// of all the target names.
@@ -1211,14 +1569,24 @@ public class Project {
// "ret" now contains the sorted sequence of Targets upto the current
// Target.
+ /**
+ * Description of the Method
+ *
+ *@param root Description of the Parameter
+ *@param targets Description of the Parameter
+ *@param state Description of the Parameter
+ *@param visiting Description of the Parameter
+ *@param ret Description of the Parameter
+ *@exception BuildException Description of the Exception
+ */
private final void tsort(String root, Hashtable targets,
- Hashtable state, Stack visiting,
- Vector ret)
- throws BuildException {
+ Hashtable state, Stack visiting,
+ Vector ret)
+ throws BuildException {
state.put(root, VISITING);
visiting.push(root);
- Target target = (Target)(targets.get(root));
+ Target target = (Target) (targets.get(root));
// Make sure we exist
if (target == null) {
@@ -1227,7 +1595,7 @@ public class Project {
sb.append("' does not exist in this project. ");
visiting.pop();
if (!visiting.empty()) {
- String parent = (String)visiting.peek();
+ String parent = (String) visiting.peek();
sb.append("It is used from target `");
sb.append(parent);
sb.append("'.");
@@ -1236,14 +1604,13 @@ public class Project {
throw new BuildException(new String(sb));
}
- for (Enumeration en=target.getDependencies(); en.hasMoreElements();) {
+ for (Enumeration en = target.getDependencies(); en.hasMoreElements(); ) {
String cur = (String) en.nextElement();
- String m=(String)state.get(cur);
+ String m = (String) state.get(cur);
if (m == null) {
// Not been visited
tsort(cur, targets, state, visiting, ret);
- }
- else if (m == VISITING) {
+ } else if (m == VISITING) {
// Currently visiting this node, so have a cycle
throw makeCircularException(cur, visiting);
}
@@ -1251,46 +1618,73 @@ public class Project {
String p = (String) visiting.pop();
if (root != p) {
- throw new RuntimeException("Unexpected internal error: expected to pop "+root+" but got "+p);
+ throw new RuntimeException("Unexpected internal error: expected to pop " + root + " but got " + p);
}
state.put(root, VISITED);
ret.addElement(target);
}
+
+ /**
+ * Description of the Method
+ *
+ *@param end Description of the Parameter
+ *@param stk Description of the Parameter
+ *@return Description of the Return Value
+ */
private static BuildException makeCircularException(String end, Stack stk) {
StringBuffer sb = new StringBuffer("Circular dependency: ");
sb.append(end);
String c;
do {
- c = (String)stk.pop();
+ c = (String) stk.pop();
sb.append(" <- ");
sb.append(c);
- } while(!c.equals(end));
+ } while (!c.equals(end));
return new BuildException(new String(sb));
}
+
+ /**
+ * Adds a feature to the Reference attribute of the Project object
+ *
+ *@param name The feature to be added to the Reference attribute
+ *@param value The feature to be added to the Reference attribute
+ */
public void addReference(String name, Object value) {
- if (null != references.get(name)) {
- log("Overriding previous definition of reference to " + name,
- MSG_WARN);
+ Object o = references.get(name);
+ if (null != o && o != value
+ && (!(o instanceof RoleAdapter)
+ || ((RoleAdapter) o).getProxy() != value)) {
+ log("Overriding previous definition of reference to " + name,
+ MSG_WARN);
}
log("Adding reference: " + name + " -> " + value, MSG_DEBUG);
- references.put(name,value);
+ references.put(name, value);
}
+
+ /**
+ * Gets the references attribute of the Project object
+ *
+ *@return The references value
+ */
public Hashtable getReferences() {
return references;
}
+
/**
- * @return The object with the "id" key.
+ *@param key Description of the Parameter
+ *@return The object with the "id" key.
*/
public Object getReference(String key) {
return references.get(key);
}
+
/**
- * send build started event to the listeners
+ * send build started event to the listeners
*/
protected void fireBuildStarted() {
BuildEvent event = new BuildEvent(this);
@@ -1300,9 +1694,11 @@ public class Project {
}
}
+
/**
- * send build finished event to the listeners
- * @param exception exception which indicates failure if not null
+ * send build finished event to the listeners
+ *
+ *@param exception exception which indicates failure if not null
*/
protected void fireBuildFinished(Throwable exception) {
BuildEvent event = new BuildEvent(this);
@@ -1313,9 +1709,11 @@ public class Project {
}
}
-
+
/**
- * send target started event to the listeners
+ * send target started event to the listeners
+ *
+ *@param target Description of the Parameter
*/
protected void fireTargetStarted(Target target) {
BuildEvent event = new BuildEvent(target);
@@ -1325,9 +1723,12 @@ public class Project {
}
}
+
/**
- * send build finished event to the listeners
- * @param exception exception which indicates failure if not null
+ * send build finished event to the listeners
+ *
+ *@param exception exception which indicates failure if not null
+ *@param target Description of the Parameter
*/
protected void fireTargetFinished(Target target, Throwable exception) {
BuildEvent event = new BuildEvent(target);
@@ -1338,6 +1739,12 @@ public class Project {
}
}
+
+ /**
+ * Description of the Method
+ *
+ *@param task Description of the Parameter
+ */
protected void fireTaskStarted(Task task) {
// register this as the current task on the current thread.
threadTasks.put(Thread.currentThread(), task);
@@ -1348,6 +1755,13 @@ public class Project {
}
}
+
+ /**
+ * Description of the Method
+ *
+ *@param task Description of the Parameter
+ *@param exception Description of the Parameter
+ */
protected void fireTaskFinished(Task task, Throwable exception) {
threadTasks.remove(Thread.currentThread());
System.out.flush();
@@ -1360,6 +1774,14 @@ public class Project {
}
}
+
+ /**
+ * Description of the Method
+ *
+ *@param event Description of the Parameter
+ *@param message Description of the Parameter
+ *@param priority Description of the Parameter
+ */
private void fireMessageLoggedEvent(BuildEvent event, String message, int priority) {
event.setMessage(message, priority);
for (int i = 0; i < listeners.size(); i++) {
@@ -1368,18 +1790,43 @@ public class Project {
}
}
+
+ /**
+ * Description of the Method
+ *
+ *@param project Description of the Parameter
+ *@param message Description of the Parameter
+ *@param priority Description of the Parameter
+ */
protected void fireMessageLogged(Project project, String message, int priority) {
BuildEvent event = new BuildEvent(project);
fireMessageLoggedEvent(event, message, priority);
}
+
+ /**
+ * Description of the Method
+ *
+ *@param target Description of the Parameter
+ *@param message Description of the Parameter
+ *@param priority Description of the Parameter
+ */
protected void fireMessageLogged(Target target, String message, int priority) {
BuildEvent event = new BuildEvent(target);
fireMessageLoggedEvent(event, message, priority);
}
+
+ /**
+ * Description of the Method
+ *
+ *@param task Description of the Parameter
+ *@param message Description of the Parameter
+ *@param priority Description of the Parameter
+ */
protected void fireMessageLogged(Task task, String message, int priority) {
BuildEvent event = new BuildEvent(task);
fireMessageLoggedEvent(event, message, priority);
}
+
}
diff --git a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/ProjectHelper.java b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/ProjectHelper.java
index f832bce3e..fe832c3bb 100644
--- a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/ProjectHelper.java
+++ b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/ProjectHelper.java
@@ -114,7 +114,7 @@ public class ProjectHelper {
private void parse() throws BuildException {
FileInputStream inputStream = null;
InputSource inputSource = null;
-
+
try {
SAXParser saxParser = getParserFactory().newSAXParser();
parser = saxParser.getParser();
@@ -123,7 +123,7 @@ public class ProjectHelper {
for (int index = uri.indexOf('#'); index != -1; index = uri.indexOf('#')) {
uri = uri.substring(0, index) + "%23" + uri.substring(index+1);
}
-
+
inputStream = new FileInputStream(buildFile);
inputSource = new InputSource(inputStream);
inputSource.setSystemId(uri);
@@ -145,7 +145,7 @@ public class ProjectHelper {
}
throw be;
}
-
+
throw new BuildException(exc.getMessage(), t, location);
}
catch(SAXException exc) {
@@ -231,20 +231,20 @@ public class ProjectHelper {
*/
public InputSource resolveEntity(String publicId,
String systemId) {
-
+
project.log("resolving systemId: " + systemId, Project.MSG_VERBOSE);
-
+
if (systemId.startsWith("file:")) {
String path = systemId.substring(5);
int index = path.indexOf("file:");
-
+
// we only have to handle these for backward compatibility
// since they are in the FAQ.
while (index != -1) {
path = path.substring(0, index) + path.substring(index + 5);
index = path.indexOf("file:");
}
-
+
String entitySystemId = path;
index = path.indexOf("%23");
// convert these to #
@@ -257,13 +257,13 @@ public class ProjectHelper {
if (!file.isAbsolute()) {
file = new File(buildFileParent, path);
}
-
+
try {
InputSource inputSource = new InputSource(new FileInputStream(file));
inputSource.setSystemId("file:" + entitySystemId);
return inputSource;
} catch (FileNotFoundException fne) {
- project.log(file.getAbsolutePath()+" could not be found",
+ project.log(file.getAbsolutePath()+" could not be found",
Project.MSG_WARN);
}
}
@@ -316,10 +316,10 @@ public class ProjectHelper {
}
if (def == null) {
- throw new SAXParseException("The default attribute of project is required",
+ throw new SAXParseException("The default attribute of project is required",
locator);
}
-
+
project.setDefaultTarget(def);
@@ -360,6 +360,8 @@ public class ProjectHelper {
handleTopTask(name, attrs);
} else if (name.equals("target")) {
handleTarget(name, attrs);
+ } else if (name.equals("description")) {
+ handleDescription(name, attrs);
} else if (project.isDefinedOnRole(Project.DATATYPE_ROLE, name)) {
handleTopTask(name, attrs);
} else {
@@ -367,9 +369,9 @@ public class ProjectHelper {
}
}
- private void handleTopTask(String name, AttributeList attrs)
- throws SAXParseException {
- InmediateTarget target = new InmediateTarget(name);
+ private void handleTopTask(String name, AttributeList attrs)
+ throws SAXParseException {
+ InmediateTarget target = new InmediateTarget(name);
(new TaskHandler(this, target, null, target)).init(name, attrs);
}
@@ -377,6 +379,10 @@ public class ProjectHelper {
new TargetHandler(this).init(tag, attrs);
}
+ private void handleDescription(String tag, AttributeList attrs) throws SAXParseException {
+ new DescriptionHandler(this).init(tag, attrs);
+ }
+
}
/**
@@ -441,8 +447,13 @@ public class ProjectHelper {
}
public void startElement(String name, AttributeList attrs) throws SAXParseException {
- new TaskHandler(this, target, null, target).init(name, attrs);
- }
+ if (name.equals("description")) {
+ new DescriptionHandler(this).init(name, attrs);
+ }
+ else {
+ new TaskHandler(this, target, null, target).init(name, attrs);
+ }
+ }
}
/**
@@ -466,7 +477,7 @@ public class ProjectHelper {
try {
task = (Task)project.createInRole(container, tag);
} catch (BuildException e) {
- // swallow here, will be thrown again in
+ // swallow here, will be thrown again in
// UnknownElement.maybeConfigure if the problem persists.
}
@@ -475,21 +486,21 @@ public class ProjectHelper {
task.setProject(project);
task.setTaskType(tag);
task.setTaskName(tag);
- container.addTask(task);
+ container.addTask(task);
}
- task.setLocation(new Location(buildFile.toString(),
- locator.getLineNumber(),
- locator.getColumnNumber()));
+ task.setLocation(new Location(buildFile.toString(),
+ locator.getLineNumber(),
+ locator.getColumnNumber()));
configureId(task, attrs);
- task.setOwningTarget(target);
- task.init();
- wrapper = task.getRuntimeConfigurableWrapper();
- wrapper.setAttributes(attrs);
- if (parentWrapper != null) {
- parentWrapper.addChild(wrapper);
- }
+ task.setOwningTarget(target);
+ task.init();
+ wrapper = task.getRuntimeConfigurableWrapper();
+ wrapper.setAttributes(attrs);
+ if (parentWrapper != null) {
+ parentWrapper.addChild(wrapper);
+ }
}
protected void finished() {
@@ -531,7 +542,7 @@ public class ProjectHelper {
private RuntimeConfigurable childWrapper = null;
private Target target;
- public NestedElementHandler(DocumentHandler parentHandler,
+ public NestedElementHandler(DocumentHandler parentHandler,
Object parent,
RuntimeConfigurable parentWrapper,
Target target) {
@@ -548,7 +559,7 @@ public class ProjectHelper {
public void init(String propType, AttributeList attrs) throws SAXParseException {
Class parentClass = parent.getClass();
- IntrospectionHelper ih =
+ IntrospectionHelper ih =
IntrospectionHelper.getHelper(parentClass);
try {
@@ -557,9 +568,9 @@ public class ProjectHelper {
UnknownElement uc = new UnknownElement(elementName);
uc.setProject(project);
((UnknownElement) parent).addChild(uc);
- // Set this parameters just in case is a Task
- uc.setTaskType(elementName);
- uc.setTaskName(elementName);
+ // Set this parameters just in case is a Task
+ uc.setTaskType(elementName);
+ uc.setTaskName(elementName);
child = uc;
} else {
child = ih.createElement(project, parent, elementName);
@@ -594,7 +605,7 @@ public class ProjectHelper {
public void startElement(String name, AttributeList attrs) throws SAXParseException {
if (child instanceof TaskContainer) {
- // taskcontainer nested element can contain other tasks - no other
+ // taskcontainer nested element can contain other tasks - no other
// nested elements possible
new TaskHandler(this, (TaskContainer)child, childWrapper, target).init(name, attrs);
}
@@ -604,39 +615,64 @@ public class ProjectHelper {
}
}
+ /**
+ * Handler to perform appropriate semantics for the special
+ * element on tasks.
+ */
+ private class DescriptionHandler extends AbstractHandler {
+
+ public DescriptionHandler(DocumentHandler parent) {
+ super(parent);
+ }
+
+ public void init(String tag, AttributeList attrs) throws SAXParseException {
+ if (attrs.getLength() > 0) {
+ throw new SAXParseException("No attributes allowed on " + tag, locator);
+ }
+ }
+
+ public void characters(char[] buf, int start, int end) throws SAXParseException {
+ String desc = project.getDescription();
+ if (desc == null) {
+ desc = "";
+ }
+ project.setDescription(desc + new String(buf, start, end));
+ }
+ }
+
/**
* Special target type for top level Tasks and Datatypes.
* This will allow eliminating special cases.
*/
private class InmediateTarget extends Target {
- /**
- * Create a target for a top level task or datatype.
- * @param name the name of the task to be run on this target.
- */
- InmediateTarget(String name) {
- super();
- setProject(project);
- setName("Top level " + name);
- }
+ /**
+ * Create a target for a top level task or datatype.
+ * @param name the name of the task to be run on this target.
+ */
+ InmediateTarget(String name) {
+ super();
+ setProject(project);
+ setName("Top level " + name);
+ }
}
- public static void configure(Object target, AttributeList attrs,
+ public static void configure(Object target, AttributeList attrs,
Project project) throws BuildException {
if( target instanceof RoleAdapter ) {
target=((RoleAdapter)target).getProxy();
}
- IntrospectionHelper ih =
+ IntrospectionHelper ih =
IntrospectionHelper.getHelper(target.getClass());
project.addBuildListener(ih);
for (int i = 0; i < attrs.getLength(); i++) {
// reflect these into the target
- String value=replaceProperties(project, attrs.getValue(i),
+ String value=replaceProperties(project, attrs.getValue(i),
project.getProperties() );
try {
- ih.setAttribute(project, target,
+ ih.setAttribute(project, target,
attrs.getName(i).toLowerCase(Locale.US), value);
} catch (BuildException be) {
@@ -674,7 +710,7 @@ public class ProjectHelper {
}
/**
- * Stores a configured child element into its parent object
+ * Stores a configured child element into its parent object
*/
public static void storeChild(Project project, Object parent, Object child, String tag) {
IntrospectionHelper ih = IntrospectionHelper.getHelper(parent.getClass());
@@ -719,23 +755,23 @@ public class ProjectHelper {
if (!keys.containsKey(propertyName)) {
project.log("Property ${" + propertyName + "} has not been set", Project.MSG_VERBOSE);
}
- fragment = (keys.containsKey(propertyName)) ? (String) keys.get(propertyName)
- : "${" + propertyName + "}";
+ fragment = (keys.containsKey(propertyName)) ? (String) keys.get(propertyName)
+ : "${" + propertyName + "}";
}
sb.append(fragment);
- }
-
+ }
+
return sb.toString();
}
/**
- * This method will parse a string containing ${value} style
+ * This method will parse a string containing ${value} style
* property values into two lists. The first list is a collection
* of text fragments, while the other is a set of string property names
* null entries in the first list indicate a property reference from the
* second list.
*/
- public static void parsePropertyString(String value, Vector fragments, Vector propertyRefs)
+ public static void parsePropertyString(String value, Vector fragments, Vector propertyRefs)
throws BuildException {
int prev = 0;
int pos;
@@ -754,7 +790,7 @@ public class ProjectHelper {
} else {
int endName = value.indexOf('}', pos);
if (endName < 0) {
- throw new BuildException("Syntax error in property: "
+ throw new BuildException("Syntax error in property: "
+ value );
}
String propertyName = value.substring(pos + 2, endName);
@@ -779,17 +815,17 @@ public class ProjectHelper {
/**
* Scan AttributeList for the id attribute and maybe add a
- * reference to project.
+ * reference to project.
*
* Moved out of {@link #configure configure} to make it happen
- * at parser time.
+ * at parser time.
*/
private void configureId(Object target, AttributeList attr) {
String id = attr.getValue("id");
if (id != null) {
- if( target instanceof RoleAdapter ) {
- ((RoleAdapter)target).setId(id);
- }
+ if( target instanceof RoleAdapter ) {
+ ((RoleAdapter)target).setId(id);
+ }
project.addReference(id, target);
}
}
diff --git a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/RoleAdapter.java b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/RoleAdapter.java
index e028ebe92..57c1f62d9 100644
--- a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/RoleAdapter.java
+++ b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/RoleAdapter.java
@@ -55,6 +55,11 @@ package org.apache.tools.ant;
public interface RoleAdapter {
+ /**
+ * Obtain the id in case it is needed.
+ */
+ public void setId(String id);
+
/**
* Set the object being adapted.
* @param o the object being adapted
diff --git a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/SymbolTable.java b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/SymbolTable.java
index e6b8c843b..ecbb0984d 100644
--- a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/SymbolTable.java
+++ b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/SymbolTable.java
@@ -54,6 +54,7 @@
package org.apache.tools.ant;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
@@ -64,7 +65,7 @@ public class SymbolTable {
/** Parent symbol table */
private SymbolTable parentTable;
-
+
/** Project associated with this symbol table */
private Project project;
@@ -82,8 +83,8 @@ public class SymbolTable {
/**
* Parameters for checking adapters.
*/
- private static final Class[] CHECK_ADAPTER_PARAMS =
- new Class[]{Class.class, Project.class};
+ private static final Class[] CHECK_ADAPTER_PARAMS =
+ new Class[]{Class.class, Project.class};
/**
* Create a top level Symbol table.
@@ -96,8 +97,8 @@ public class SymbolTable {
* from that defined in the calling Project.
* @param p the calling project
*/
- public SymbolTable(Project p) {
- parentTable = p.getSymbols();
+ public SymbolTable(SymbolTable st) {
+ parentTable = st;
}
/**
@@ -105,7 +106,55 @@ public class SymbolTable {
* @param p the project for this symbol table
*/
public void setProject(Project p) {
- this.project = p;
+ this.project = p;
+ }
+
+ /**
+ * Get the specified loader for the project.
+ * @param name the name of the loader
+ * @return the corresponding ANT classloader
+ */
+ private AntClassLoader getLoader(String name) {
+ AntClassLoader cl = (AntClassLoader) loaders.get(name);
+ if (cl == null && parentTable != null) {
+ return parentTable.getLoader(name);
+ }
+ return cl;
+ }
+
+ /**
+ * Add the specified class-path to a loader.
+ * If the loader is defined in an ancestor project then a new
+ * classloader inheritin from the one already existing
+ * will be created, otherwise the path willbe added to the existing
+ * ClassLoader.
+ * @param name the name of the loader to use.
+ * @param clspath the path to be added to the classloader
+ */
+ public ClassLoader addToLoader(String name, Path clspath) {
+ // Find if the loader is already defined in the current project
+ AntClassLoader cl = (AntClassLoader) loaders.get(name);
+ if (cl == null) {
+ // Is it inherited from the calling project
+ if (parentTable != null) {
+ cl = parentTable.getLoader(name);
+ }
+ cl = new AntClassLoader(cl, project, clspath, true);
+ loaders.put(name, cl);
+ }
+ else {
+ // Add additional path to the existing definition
+ String[] pathElements = clspath.list();
+ for (int i = 0; i < pathElements.length; ++i) {
+ try {
+ cl.addPathElement(pathElements[i]);
+ }
+ catch (BuildException e) {
+ // ignore path elements invalid relative to the project
+ }
+ }
+ }
+ return cl;
}
/**
@@ -115,9 +164,9 @@ public class SymbolTable {
* @return an array of roles supported by the class
*/
public String[] findRoles(final Class clz) {
- Vector list = new Vector();
- findRoles(clz, list);
- return (String[])list.toArray(new String[list.size()]);
+ Vector list = new Vector();
+ findRoles(clz, list);
+ return (String[])list.toArray(new String[list.size()]);
}
/**
@@ -126,27 +175,27 @@ public class SymbolTable {
* @param list the roles collected up to this point
*/
private void findRoles(final Class clz, Vector list) {
- for (Enumeration e = roles.keys(); e.hasMoreElements();) {
- String role = (String) e.nextElement();
-
- if (((Role) roles.get(role)).isImplementedBy(clz)) {
- list.addElement(role);
- }
- }
- if (parentTable != null) findRoles(clz, list);
+ for (Enumeration e = roles.keys(); e.hasMoreElements();) {
+ String role = (String) e.nextElement();
+
+ if (((Role) roles.get(role)).isImplementedBy(clz)) {
+ list.addElement(role);
+ }
+ }
+ if (parentTable != null) parentTable.findRoles(clz, list);
}
-
+
/**
* Get the Role definition
* @param role the name of the role
- * @return the method used to support objects on this role
+ * @return the Role description
*/
public Role getRole(String role) {
- Role r = (Role) roles.get(role);
- if (r == null && parentTable != null) {
- return parentTable.getRole(role);
- }
- return r;
+ Role r = (Role) roles.get(role);
+ if (r == null && parentTable != null) {
+ return parentTable.getRole(role);
+ }
+ return r;
}
/**
@@ -157,126 +206,19 @@ public class SymbolTable {
* @return whether the role replaced a different definition
*/
public boolean addRole(String role, Class rclz, Class aclz) {
- // Check if role already declared
- Role old = getRole(role);
- if (old != null && old.isSameAsFor(rclz, aclz)
- ) {
- project.log("Ignoring override for role " + role
- + ", it is already defined by the same definition.",
- project.MSG_VERBOSE);
- return false;
- }
- // Role interfaces should only contain one method
- roles.put(role, new Role(rclz, aclz));
- return (old != null);
- }
-
- /**
- * Verify if the interface is valid.
- * @param clz the interface to validate
- * @return the method defined by the interface
- */
- private Method validInterface(Class clz) {
- Method m[] = clz.getDeclaredMethods();
- if (m.length == 1
- && java.lang.Void.TYPE.equals(m[0].getReturnType())) {
- Class args[] = m[0].getParameterTypes();
- if (args.length == 1
- && !java.lang.String.class.equals(args[0])
- && !args[0].isArray()
- && !args[0].isPrimitive()) {
- return m[0];
- }
- else {
- throw new BuildException("Invalid role interface method in: "
- + clz.getName());
- }
- }
- else {
- throw new BuildException("More than one method on role interface");
- }
- }
-
- /**
- * Verify if the adapter is valid with respect to the interface.
- * @param clz the class adapter to validate
- * @param mtd the method whose only argument must match
- * @return the static method to use for validating adaptees
- */
- private Method validAdapter(Class clz, Method mtd) {
- if (clz == null) return null;
-
- checkClass(clz);
- if (!mtd.getParameterTypes()[0].isAssignableFrom(clz)) {
- String msg = "Adapter " + clz.getName() +
- " is incompatible with role interface " +
- mtd.getDeclaringClass().getName();
- throw new BuildException(msg);
- }
- String msg = "Class " + clz.getName() + " is not an adapter: ";
- if (!RoleAdapter.class.isAssignableFrom(clz)) {
- throw new BuildException(msg + "does not implement RoleAdapter");
- }
- try {
- Method chk = clz.getMethod("checkClass", CHECK_ADAPTER_PARAMS);
- if (!Modifier.isStatic(chk.getModifiers())) {
- throw new BuildException(msg + "checkClass() is not static");
- }
- return chk;
- }
- catch(NoSuchMethodException nme){
- throw new BuildException(msg + "checkClass() not found", nme);
- }
- }
-
- /**
- * Get the specified loader for the project.
- * @param name the name of the loader
- * @return the corresponding ANT classloader
- */
- private AntClassLoader getLoader(String name) {
- AntClassLoader cl = (AntClassLoader) loaders.get(name);
- if (cl == null && parentTable != null) {
- return parentTable.getLoader(name);
- }
- return cl;
+ // Check if role already declared
+ Role old = getRole(role);
+ if (old != null && old.isSameAsFor(rclz, aclz)) {
+ project.log("Ignoring override for role " + role
+ + ", it is already defined by the same definition.",
+ project.MSG_VERBOSE);
+ return false;
+ }
+ // Role interfaces should only contain one method
+ roles.put(role, new Role(rclz, aclz));
+ return (old != null);
}
- /**
- * Add the specified class-path to a loader.
- * If the loader is defined in an ancestor project then a new
- * classloader inheritin from the one already existing
- * will be created, otherwise the path willbe added to the existing
- * ClassLoader.
- * @param name the name of the loader to use.
- * @param clspath the path to be added to the classloader
- */
- public ClassLoader addToLoader(String name, Path clspath) {
- // Find if the loader is already defined in the current project
- AntClassLoader cl = (AntClassLoader) loaders.get(name);
- if (cl == null) {
- // Is it inherited from the calling project
- if (parentTable != null) {
- cl = parentTable.getLoader(name);
- }
- cl = new AntClassLoader(cl, project, clspath, true);
- loaders.put(name, cl);
- }
- else {
- // Add additional path to the existing definition
- String[] pathElements = clspath.list();
- for (int i = 0; i < pathElements.length; ++i) {
- try {
- cl.addPathElement(pathElements[i]);
- }
- catch (BuildException e) {
- // ignore path elements invalid relative to the project
- }
- }
- }
- return cl;
- }
-
/**
* Add a new type of element to a role.
* @param role the role for this Class.
@@ -285,46 +227,53 @@ public class SymbolTable {
* @return the old definition
*/
public Class add(String role, String name, Class clz) {
- // Find the role definition
- Role r = getRole(role);
- if (r == null) {
- throw new BuildException("Unknown role: " + role);
- }
- // Check if it is already defined
- Class old = get(role, name);
- if (old != null) {
- if (old.equals(clz)) {
- project.log("Ignoring override for "+ role + " " + name
- + ", it is already defined by the same class.",
- project.MSG_VERBOSE);
- return old;
- }
- else {
+ // Find the role definition
+ Role r = getRole(role);
+ if (r == null) {
+ throw new BuildException("Unknown role: " + role);
+ }
+ // Check if it is already defined
+ Factory old = get(role, name);
+ if (old != null) {
+ if (old.getOriginalClass().equals(clz)) {
+ project.log("Ignoring override for "+ role + " " + name
+ + ", it is already defined by the same class.",
+ project.MSG_VERBOSE);
+ return old.getOriginalClass();
+ }
+ else {
project.log("Trying to override old definition of " +
- role + " " + name,
- project.MSG_WARN);
- }
- }
- checkClass(clz);
- // Check that the Class is compatible with the role definition
- r.verifyAdaptability(role, clz);
- // Record the new type
- Hashtable defTable = (Hashtable)defs.get(role);
- if (defTable == null) {
- defTable = new Hashtable();
- defs.put(role, defTable);
- }
- defTable.put(name, clz);
- return old;
+ role + " " + name,
+ project.MSG_WARN);
+ }
+ }
+ Factory f = checkClass(clz);
+ // Check that the Class is compatible with the role definition
+ f = r.verifyAdaptability(role, f);
+ // Record the new type
+ Hashtable defTable = (Hashtable)defs.get(role);
+ if (defTable == null) {
+ defTable = new Hashtable();
+ defs.put(role, defTable);
+ }
+ defTable.put(name, f);
+
+ String msg =
+ " +User " + role + ": " + name + " " + clz.getName();
+ project.log(msg, project.MSG_DEBUG);
+ return (old != null ? old.getOriginalClass() : null);
}
/**
* Checks a class, whether it is suitable for serving in ANT.
+ * @return the factory to use when instantiating the class
* @throws BuildException and logs as Project.MSG_ERR for
* conditions, that will cause execution to fail.
*/
- void checkClass(final Class clz)
- throws BuildException {
+ Factory checkClass(final Class clz) // Package on purpose
+ throws BuildException {
+ if (clz == null) return null;
+
if(!Modifier.isPublic(clz.getModifiers())) {
final String message = clz + " is not public";
project.log(message, Project.MSG_ERR);
@@ -336,21 +285,53 @@ public class SymbolTable {
throw new BuildException(message);
}
try {
- // Class can have a "no arg" constructor or take a single
+ // Class can have a "no arg" constructor or take a single
// Project argument.
// don't have to check for public, since
// getConstructor finds public constructors only.
try {
clz.getConstructor(new Class[0]);
+ return new Factory(){
+ public Object create(Project p) {
+ try {
+ return clz.newInstance();
+ }
+ catch(Exception e) {
+ throw new BuildException(e);
+ }
+ }
+
+ public Class getOriginalClass() {
+ return clz;
+ }
+ };
} catch (NoSuchMethodException nse) {
- clz.getConstructor(new Class[] {Project.class});
+ final Constructor c =
+ clz.getConstructor(new Class[] {Project.class});
+ return new Factory(){
+ public Object create(Project p) {
+ try {
+ return c.newInstance(new Object[]{p});
+ }
+ catch(Exception e) {
+ throw new BuildException(e);
+ }
+ }
+
+ public Class getOriginalClass() {
+ return clz;
+ }
+ };
}
} catch(NoSuchMethodException e) {
- final String message =
- "No valid public constructor in " + clz;
+ final String message = "No valid public constructor in " + clz;
project.log(message, Project.MSG_ERR);
throw new BuildException(message);
}
+ catch (NoClassDefFoundError ncdfe) {
+ final String msg = "Class cannot be loaded: " + ncdfe.getMessage();
+ throw new BuildException(msg, ncdfe);
+ }
}
/**
@@ -359,32 +340,25 @@ public class SymbolTable {
* @param name the name of the element to sea
* @return the Class implementation
*/
- public Class get(String role, String name) {
- Hashtable defTable = (Hashtable)defs.get(role);
- if (defTable != null) {
- Class clz = (Class)defTable.get(name);
- if (clz != null) return clz;
- }
- if (parentTable != null) {
- return parentTable.get(role, name);
- }
- return null;
- }
-
- /**
- * Get a Hashtable that is usable for manipulating Tasks,
- * @return a Hashtable that delegates to the Symbol table.
- */
- public Hashtable getTaskDefinitions() {
- return new SymbolHashtable("task");
+ public Factory get(String role, String name) {
+ Hashtable defTable = (Hashtable)defs.get(role);
+ if (defTable != null) {
+ Factory f = (Factory)defTable.get(name);
+ if (f != null) return f;
+ }
+ if (parentTable != null) {
+ return parentTable.get(role, name);
+ }
+ return null;
}
/**
- * Get a Hashtable that is usable for manipulating Datatypes,
+ * Get a Hashtable that is usable for manipulating elements on Role.
+ * @param role the role of the elements in the table
* @return a Hashtable that delegates to the Symbol table.
*/
- public Hashtable getDataTypeDefinitions() {
- return new SymbolHashtable("datatype");
+ Hashtable getDefinitions(String role) { // package scope on purpose
+ return new SymbolHashtable(role);
}
/**
@@ -392,100 +366,196 @@ public class SymbolTable {
* the search operations to the Symbol table
*/
private class SymbolHashtable extends Hashtable {
- final String role;
- SymbolHashtable(String role) {
- this.role = role;
- }
-
- public synchronized Object put(Object key, Object value) {
- return SymbolTable.this.add(role, (String) key, (Class) value);
- }
-
- public synchronized Object get(Object key) {
- return SymbolTable.this.get(role, (String)key);
- }
+ final String role;
+ SymbolHashtable(String role) {
+ this.role = role;
+ }
+
+ public synchronized Object put(Object key, Object value) {
+ return SymbolTable.this.add(role, (String) key, (Class) value);
+ }
+
+ public synchronized Object get(Object key) {
+ Factory f = SymbolTable.this.get(role, (String)key);
+ return (f == null? null : f.getOriginalClass());
+ }
+ }
+
+ /**
+ * Factory for creating ANT objects.
+ * Class objects are not instanciated directly but through a Factory
+ * which is able to resolve issues such as proxys and such.
+ */
+ public static interface Factory {
+ /**
+ * Creates an object for the Role
+ * @param the project in which it is created
+ * @return the instantiated object with a proxy if necessary
+ */
+ public Object create(Project p);
+
+ /**
+ * Creates an object for the Role, adapted if necessary
+ * for a particular interface.
+ */
+// public Object adaptFor(Class clz, Project p, Object o);
+
+ /**
+ * The original class of the object without proxy.
+ */
+ public Class getOriginalClass();
}
/**
* The definition of a role
*/
public class Role {
- private Method interfaceMethod;
- private Method adapterVerifier;
-
- /**
- * Creates a new Role object
- * @param roleClz the class that defines the role
- * @param adapterClz the class for the adapter, or null if none
- */
- Role(Class roleClz, Class adapterClz) {
- interfaceMethod = validInterface(roleClz);
- adapterVerifier = validAdapter(adapterClz, interfaceMethod);
- }
-
- /**
- * Get the method used to set on interface
- */
- public Method getInterfaceMethod() {
- return interfaceMethod;
- }
-
- /**
- * Instantiate a new adapter for this role.
- */
- public RoleAdapter createAdapter() {
- if (adapterVerifier == null) return null;
-
- try {
- return (RoleAdapter)
- adapterVerifier.getDeclaringClass().newInstance();
- }
- catch(BuildException be) {
- throw be;
- }
- catch(Exception e) {
- throw new BuildException(e);
- }
- }
-
- /**
- * Verify if the class can be adapted to use by the role
- * @param role the name of the role to verify
- * @param clz the class to verify
- */
- public void verifyAdaptability(String role, Class clz) {
- if (interfaceMethod.getParameterTypes()[0].isAssignableFrom(clz)) {
- return;
- }
- if (adapterVerifier == null) {
- String msg = "Class " + clz.getName() +
- " incompatible with role: " + role;
- throw new BuildException(msg);
- }
- try {
- try {
- adapterVerifier.invoke(null,
- new Object[]{clz, project});
- }
- catch (InvocationTargetException ite) {
- throw ite.getTargetException();
- }
- }
- catch(BuildException be) { throw be; }
- catch(Error err) {throw err; }
- catch(Throwable t) {
- throw new BuildException(t);
- }
- }
-
- public boolean isSameAsFor(Class clz, Class pclz) {
- return interfaceMethod.getDeclaringClass().equals(clz) &&
- ((adapterVerifier == null && pclz == null) ||
- adapterVerifier.getDeclaringClass().equals(pclz));
- }
-
- public boolean isImplementedBy(Class clz) {
- return interfaceMethod.getDeclaringClass().isAssignableFrom(clz);
- }
+ private Method interfaceMethod;
+ private Method adapterVerifier;
+ private Factory adapterFactory;
+
+ /**
+ * Creates a new Role object
+ * @param roleClz the class that defines the role
+ * @param adapterClz the class for the adapter, or null if none
+ */
+ Role(Class roleClz, Class adapterClz) {
+ interfaceMethod = validInterface(roleClz);
+ adapterFactory = checkClass(adapterClz);
+ adapterVerifier = validAdapter(adapterClz, interfaceMethod);
+ }
+
+ /**
+ * Get the method used to set on interface
+ */
+ public Method getInterfaceMethod() {
+ return interfaceMethod;
+ }
+
+ /**
+ * Instantiate a new adapter for this role.
+ */
+ public RoleAdapter createAdapter(Project p) {
+ if (adapterFactory == null) return null;
+
+ try {
+ return (RoleAdapter) adapterFactory.create(p);
+ }
+ catch(BuildException be) {
+ throw be;
+ }
+ catch(Exception e) {
+ throw new BuildException(e);
+ }
+ }
+
+ /**
+ * Verify if the class can be adapted to use by the role
+ * @param role the name of the role to verify
+ * @param f the factory for the class to verify
+ */
+ public Factory verifyAdaptability(String role, final Factory f) {
+ final Class clz = f.getOriginalClass();
+ if (interfaceMethod.getParameterTypes()[0].isAssignableFrom(clz)) {
+ return f;
+ }
+ if (adapterVerifier == null) {
+ String msg = "Class " + clz.getName() +
+ " incompatible with role: " + role;
+ throw new BuildException(msg);
+ }
+ try {
+ try {
+ adapterVerifier.invoke(null, new Object[]{clz, project});
+ return new Factory(){
+ public Object create(Project p) {
+ RoleAdapter ra = createAdapter(p);
+ ra.setProxy(f.create(p));
+ return ra;
+ }
+
+ public Class getOriginalClass() {
+ return clz;
+ }
+ };
+ }
+ catch (InvocationTargetException ite) {
+ throw ite.getTargetException();
+ }
+ }
+ catch(BuildException be) { throw be; }
+ catch(Error err) {throw err; }
+ catch(Throwable t) {
+ throw new BuildException(t);
+ }
+ }
+
+ public boolean isSameAsFor(Class clz, Class pclz) {
+ return interfaceMethod.getDeclaringClass().equals(clz) &&
+ ((adapterVerifier == null && pclz == null) ||
+ adapterVerifier.getDeclaringClass().equals(pclz));
+ }
+
+ public boolean isImplementedBy(Class clz) {
+ return interfaceMethod.getDeclaringClass().isAssignableFrom(clz);
+ }
+
+ /**
+ * Verify if the interface is valid.
+ * @param clz the interface to validate
+ * @return the method defined by the interface
+ */
+ private Method validInterface(Class clz) {
+ Method m[] = clz.getDeclaredMethods();
+ if (m.length == 1
+ && java.lang.Void.TYPE.equals(m[0].getReturnType())) {
+ Class args[] = m[0].getParameterTypes();
+ if (args.length == 1
+ && !java.lang.String.class.equals(args[0])
+ && !args[0].isArray()
+ && !args[0].isPrimitive()) {
+ return m[0];
+ }
+ else {
+ throw new BuildException("Invalid role interface method in: "
+ + clz.getName());
+ }
+ }
+ else {
+ throw new BuildException("More than one method on role interface");
+ }
+ }
+
+ /**
+ * Verify if the adapter is valid with respect to the interface.
+ * @param clz the class adapter to validate
+ * @param mtd the method whose only argument must match
+ * @return the static method to use for validating adaptees
+ */
+ private Method validAdapter(Class clz, Method mtd) {
+ if (clz == null) return null;
+
+ if (!mtd.getParameterTypes()[0].isAssignableFrom(clz)) {
+ String msg = "Adapter " + clz.getName() +
+ " is incompatible with role interface " +
+ mtd.getDeclaringClass().getName();
+ throw new BuildException(msg);
+ }
+ String msg = "Class " + clz.getName() + " is not an adapter: ";
+ if (!RoleAdapter.class.isAssignableFrom(clz)) {
+ throw new BuildException(msg + "does not implement RoleAdapter");
+ }
+ try {
+ Method chk = clz.getMethod("checkClass", CHECK_ADAPTER_PARAMS);
+ if (!Modifier.isStatic(chk.getModifiers())) {
+ throw new BuildException(msg + "checkClass() is not static");
+ }
+ return chk;
+ }
+ catch(NoSuchMethodException nme){
+ throw new BuildException(msg + "checkClass() not found", nme);
+ }
+ }
+
}
}
diff --git a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/TaskAdapter.java b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/TaskAdapter.java
index 213f4f014..077131c1b 100644
--- a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/TaskAdapter.java
+++ b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/TaskAdapter.java
@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
+ * Copyright (c) 2000-2001 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", "Ant", 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"
@@ -55,6 +55,7 @@
package org.apache.tools.ant;
import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
@@ -68,7 +69,7 @@ import java.lang.reflect.Method;
public class TaskAdapter extends Task implements RoleAdapter {
Object proxy;
-
+
/**
* Checks a class, whether it is suitable to be adapted by TaskAdapter.
*
@@ -81,15 +82,15 @@ public class TaskAdapter extends Task implements RoleAdapter {
* Logs other suspicious conditions with Project.MSG_WARN.
*/
public static void checkTaskClass(final Class taskClass, final Project project) {
- // This code is for backward compatibility
- checkClass(taskClass, project);
+ // This code is for backward compatibility
+ checkClass(taskClass, project);
}
/**
* Checks a class, whether it is suitable to be adapted.
*
* Checks conditions only, which are additionally required for a tasks
- * adapted by TaskAdapter.
+ * adapted by TaskAdapter.
*
* Throws a BuildException and logs as Project.MSG_ERR for
* conditions, that will cause the task execution to fail.
@@ -114,7 +115,7 @@ public class TaskAdapter extends Task implements RoleAdapter {
throw new BuildException(message);
}
}
-
+
/**
* Do the execution.
*/
@@ -122,7 +123,7 @@ public class TaskAdapter extends Task implements RoleAdapter {
Method setProjectM = null;
try {
Class c = proxy.getClass();
- setProjectM =
+ setProjectM =
c.getMethod( "setProject", new Class[] {Project.class});
if(setProjectM != null) {
setProjectM.invoke(proxy, new Object[] {project});
@@ -131,7 +132,7 @@ public class TaskAdapter extends Task implements RoleAdapter {
// ignore this if the class being used as a task does not have
// a set project method.
} catch( Exception ex ) {
- log("Error setting project in " + proxy.getClass(),
+ log("Error setting project in " + proxy.getClass(),
Project.MSG_ERR);
throw new BuildException( ex );
}
@@ -146,14 +147,20 @@ public class TaskAdapter extends Task implements RoleAdapter {
throw new BuildException("No public execute() in " + proxy.getClass());
}
executeM.invoke(proxy, null);
- return;
+ return;
+ } catch( InvocationTargetException ite ) {
+ Throwable t = ite.getTargetException();
+ if (t instanceof BuildException) {
+ throw (BuildException) t;
+ }
+ throw new BuildException(t);
} catch( Exception ex ) {
log("Error in " + proxy.getClass(), Project.MSG_ERR);
throw new BuildException( ex );
}
}
-
+
/**
* Set the target object class
*/
@@ -165,4 +172,5 @@ public class TaskAdapter extends Task implements RoleAdapter {
return this.proxy ;
}
+ public void setId(String id) {}
}
diff --git a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Ant.java b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Ant.java
index 13d42380d..5d6d8d699 100644
--- a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Ant.java
+++ b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Ant.java
@@ -138,10 +138,8 @@ public class Ant extends Task {
}
public void init() {
- newProject = new Project(project);
+ newProject = project.createSubProject();
newProject.setJavaVersionProperty();
-// newProject.addTaskDefinition("property",
-// (Class)project.getTaskDefinitions().get("property"));
}
private void reinit() {
@@ -185,26 +183,6 @@ public class Ant extends Task {
}
}
-// Hashtable taskdefs = project.getTaskDefinitions();
-// Enumeration et = taskdefs.keys();
-// while (et.hasMoreElements()) {
-// String taskName = (String) et.nextElement();
-// if (taskName.equals("property")) {
-// // we have already added this taskdef in #init
-// continue;
-// }
-// Class taskClass = (Class) taskdefs.get(taskName);
-// newProject.addTaskDefinition(taskName, taskClass);
-// }
-
-// Hashtable typedefs = project.getDataTypeDefinitions();
-// Enumeration e = typedefs.keys();
-// while (e.hasMoreElements()) {
-// String typeName = (String) e.nextElement();
-// Class typeClass = (Class) typedefs.get(typeName);
-// newProject.addDataTypeDefinition(typeName, typeClass);
-// }
-
// set user-defined or all properties from calling project
Hashtable prop1;
if (inheritAll) {
diff --git a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antjar.java b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antjar.java
index 16ef3ca7b..784e28926 100644
--- a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antjar.java
+++ b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antjar.java
@@ -104,7 +104,8 @@ public class Antjar extends Jar {
public void setAntxml(File descriptor) {
libraryDescriptor = descriptor;
if (!libraryDescriptor.exists()) {
- throw new BuildException("Deployment descriptor: " + libraryDescriptor + " does not exist.");
+ throw new BuildException("Deployment descriptor: " +
+ libraryDescriptor + " does not exist.");
}
// Create a ZipFileSet for this file, and pass it up.
@@ -127,7 +128,8 @@ public class Antjar extends Jar {
throws IOException, BuildException {
// If no antxml file is specified, it's an error.
if (libraryDescriptor == null) {
- throw new BuildException("antxml attribute is required", location);
+ throw new BuildException("antxml attribute is required",
+ location);
}
super.initZipOutputStream(zOut);
@@ -149,10 +151,12 @@ public class Antjar extends Jar {
// meaning the same file is specified by the "antxml" attribute and in
// a element.
if (vPath.equalsIgnoreCase(Antlib.ANT_DESCRIPTOR)) {
- if (libraryDescriptor == null || !libraryDescriptor.equals(file) || descriptorAdded) {
+ if (libraryDescriptor == null ||
+ !libraryDescriptor.equals(file) || descriptorAdded) {
log("Warning: selected " + archiveType + " files include a " +
- Antlib.ANT_DESCRIPTOR + " which will be ignored " +
- "(please use antxml attribute to " + archiveType + " task)", Project.MSG_WARN);
+ Antlib.ANT_DESCRIPTOR + " which will be ignored " +
+ "(please use antxml attribute to " + archiveType +
+ " task)", Project.MSG_WARN);
}
else {
super.zipFile(file, zOut, vPath);
diff --git a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antlib.java b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antlib.java
index c084791c4..93a5c1982 100644
--- a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antlib.java
+++ b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/taskdefs/Antlib.java
@@ -55,12 +55,14 @@ package org.apache.tools.ant.taskdefs;
import org.apache.tools.ant.*;
import org.apache.tools.ant.types.*;
+import org.apache.tools.ant.taskdefs.*;
import org.xml.sax.*;
import javax.xml.parsers.*;
import java.util.*;
import java.util.zip.*;
import java.io.*;
+import java.net.*;
/**
* Make available the tasks and types from an Ant library.
@@ -76,16 +78,18 @@ import java.io.*;
* @since ant1.5
*/
public class Antlib extends Task {
+
+ /**
+ * Location of descriptor in library
+ */
+ public static final String ANT_DESCRIPTOR = "META-INF/antlib.xml";
+
/**
* The named classloader to use.
* Defaults to the default classLoader.
*/
private String loaderId = "";
- /**
- * library attribute
- */
- private String library = null;
/**
* file attribute
*/
@@ -95,62 +99,200 @@ public class Antlib extends Task {
*/
private boolean override = false;
/**
- * attribute to control classloader use
+ * attribute to control failure when loading
*/
- private boolean useCurrentClassloader = false;
+ private FailureAction onerror = new FailureAction();
+
/**
* classpath to build up
*/
private Path classpath = null;
+ /**
+ * the manufacture set of classes to load
+ */
+ private Path loaderPath = null;
+
/**
* our little xml parse
*/
private SAXParserFactory saxFactory;
-
+
/**
* table of aliases
*/
private Vector aliases = new Vector();
/**
- * Location of descriptor in library
+ * Some internal constants.
*/
- public static String ANT_DESCRIPTOR = "META-INF/antlib.xml";
+ private static final int FAIL = 0, REPORT = 1, IGNORE = 2;
/**
- * Prefix name for DTD of descriptor
- */
- public static String ANTLIB_DTD_URL =
- "http://jakarta.apache.org/ant/";
- /**
- * prefix of the antlib
- */
- public static String ANTLIB_DTD_PREFIX = "Antlib-V";
-
- /**
- * version counter
+ * Posible actions when classes are not found
*/
- public static String ANTLIB_DTD_VERSION = "1_0";
-
- /**
- * dtd file extension
- */
- public static String ANTLIB_DTD_EXT = ".dtd";
+ public static class FailureAction extends EnumeratedAttribute {
+ public String[] getValues() {
+ return new String[]{"fail", "report", "ignore"};
+ }
+ }
+ private static class DescriptorEnumeration implements Enumeration {
+
+ /**
+ * The name of the resource being searched for.
+ */
+ private String resourceName;
+
+ /**
+ * The index of the next file to search.
+ */
+ private int index;
+
+ /**
+ * The list of files to search
+ */
+ private File files[];
+
+ /**
+ * The URL of the next resource to return in the enumeration. If this
+ * field is null
then the enumeration has been completed,
+ * i.e., there are no more elements to return.
+ */
+ private URL nextDescriptor;
+
+ /**
+ * Construct a new enumeration of resources of the given name found
+ * within this class loader's classpath.
+ *
+ * @param name the name of the resource to search for.
+ */
+ DescriptorEnumeration(String fileNames[], String name) {
+ this.resourceName = name;
+ this.index = 0;
+ this.files = new File[fileNames.length];
+ for (int i = 0; i < files.length; i++) {
+ files[i] = new File(fileNames[i]);
+ }
+ findNextDescriptor();
+ }
+
+ /**
+ * Indicates whether there are more elements in the enumeration to
+ * return.
+ *
+ * @return true
if there are more elements in the
+ * enumeration; false
otherwise.
+ */
+ public boolean hasMoreElements() {
+ return (this.nextDescriptor != null);
+ }
+
+ /**
+ * Returns the next resource in the enumeration.
+ *
+ * @return the next resource in the enumeration.
+ */
+ public Object nextElement() {
+ URL ret = this.nextDescriptor;
+ findNextDescriptor();
+ return ret;
+ }
+
+ /**
+ * Locates the next descriptor of the correct name in the files and
+ * sets nextDescriptor
to the URL of that resource. If no
+ * more resources can be found, nextDescriptor
is set to
+ * null
.
+ */
+ private void findNextDescriptor() {
+ URL url = null;
+ while (index < files.length && url == null) {
+ try {
+ url = getDescriptorURL(files[index], this.resourceName);
+ index++;
+ }
+ catch (BuildException e) {
+ // ignore path elements which are not valid relative to the
+ // project
+ }
+ }
+ this.nextDescriptor = url;
+ }
+
+ /**
+ * Get an URL to a given resource in the given file which may
+ * either be a directory or a zip file.
+ *
+ * @param file the file (directory or jar) in which to search for
+ * the resource. Must not be null
.
+ * @param resourceName the name of the resource for which a URL
+ * is required. Must not be null
.
+ *
+ * @return a URL to the required resource or null
if the
+ * resource cannot be found in the given file object
+ * @todo This code is extracted from AntClassLoader.getResourceURL
+ * I hate when that happens but the code there is too tied to
+ * the ClassLoader internals. Maybe we can find a nice place
+ * to put it where both can use it.
+ */
+ private URL getDescriptorURL(File file, String resourceName) {
+ try {
+ if (!file.exists()) {
+ return null;
+ }
+
+ if (file.isDirectory()) {
+ File resource = new File(file, resourceName);
+
+ if (resource.exists()) {
+ try {
+ return new URL("file:"+resource.toString());
+ } catch (MalformedURLException ex) {
+ return null;
+ }
+ }
+ }
+ else {
+ ZipFile zipFile = new ZipFile(file);
+ try {
+ ZipEntry entry = zipFile.getEntry(resourceName);
+ if (entry != null) {
+ try {
+ return new URL("jar:file:"+file.toString()+"!/"+entry);
+ } catch (MalformedURLException ex) {
+ return null;
+ }
+ }
+ }
+ finally {
+ zipFile.close();
+ }
+ }
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ }
/**
* constructor creates a validating sax parser
*/
public Antlib() {
super();
+ // Default error action
+ onerror.setValue("report");
saxFactory = SAXParserFactory.newInstance();
- saxFactory.setValidating(true);
+ saxFactory.setValidating(false);
}
/**
- * constructor binds to a project as well as setting up internal state
+ * constructor binds to a project and sets ignore mode on errors
*
* @param p Description of Parameter
*/
@@ -161,12 +303,12 @@ public class Antlib extends Task {
/**
- * Set name of library to load. The library is located in $ANT_HOME/lib.
+ * Set name of library to load. The library is located in $ANT_HOME/antlib.
*
- * @param lib the name of library relative to $ANT_HOME/lib.
+ * @param lib the name of library relative to $ANT_HOME/antlib.
*/
public void setLibrary(String lib) {
- this.library = lib;
+ setFile(libraryFile("antlib", lib));
}
@@ -180,13 +322,13 @@ public class Antlib extends Task {
}
/**
- * Set the ClassLoader to use for this library.
+ * Set the ID of the ClassLoader to use for this library.
*
- * @param id the id for the ClassLoader to use,
- * if other than the default.
+ * @param id the id for the ClassLoader to use,
+ * null
means use ANT's core classloader.
*/
public void setLoaderid(String id) {
- this.loaderId = id;
+ this.loaderId = id;
}
/**
@@ -200,15 +342,26 @@ public class Antlib extends Task {
/**
- * Set whether to use a new classloader or not.
- * Default is false
.
+ * Get what to do if a definition cannot be loaded
+ * This method is mostly used by the core when loading core tasks.
+ *
+ * @return what to do if a definition cannot be loaded
+ */
+ final protected FailureAction getOnerror() {
+ return this.onerror;
+ }
+
+
+ /**
+ * Set whether to fail if a definition cannot be loaded
+ * Default is true
.
* This property is mostly used by the core when loading core tasks.
*
- * @param useCurrentClassloader if true the current classloader will
- * be used to load the definitions.
+ * @param failedonerror if true loading will stop if classes
+ * cannot be instantiated
*/
- public void setUseCurrentClassloader(boolean useCurrentClassloader) {
- this.useCurrentClassloader = useCurrentClassloader;
+ public void setOnerror(FailureAction onerror) {
+ this.onerror = onerror;
}
@@ -262,78 +415,97 @@ public class Antlib extends Task {
}
+ /**
+ * Obtain library file from ANT_HOME directory.
+ *
+ * @param lib the library name.
+ * @return the File instance of the library
+ */
+ private File libraryFile(String homeSubDir, String lib) {
+ // For the time being libraries live in $ANT_HOME/antlib.
+ // The idea being that not to load all the jars there anymore
+ String home = project.getProperty("ant.home");
+
+ if (home == null) {
+ throw new BuildException("ANT_HOME not set as required.");
+ }
+
+ return new File(new File(home, homeSubDir), lib);
+ }
+
/**
* actually do the work of loading the library
*
* @exception BuildException Description of Exception
- * @todo maybe have failonerror support for missing file?
*/
public void execute()
throws BuildException {
- File realFile = file;
- if (library != null) {
- if (file != null) {
- String msg = "You cannot specify both file and library.";
- throw new BuildException(msg, location);
- }
- // For the time being libraries live in $ANT_HOME/antlib.
- // The idea being that we would not load all the jars there anymore
- String home = project.getProperty("ant.home");
-
- if (home == null) {
- throw new BuildException("ANT_HOME not set as required.");
- }
-
- realFile = new File(new File(home, "antlib"), library);
- }
- else if (file == null) {
- String msg = "Must specify either library or file attribute.";
+ if (file == null && classpath == null) {
+ String msg =
+ "Must specify either library or file attribute or classpath.";
throw new BuildException(msg, location);
}
- if (!realFile.exists()) {
- String msg = "Cannot find library: " + realFile;
+ if (file != null && !file.exists()) {
+ String msg = "Cannot find library: " + file;
throw new BuildException(msg, location);
}
- //open the descriptor
- InputStream is = getDescriptor(realFile);
-
- if (is == null) {
- String msg = "Missing descriptor on library: " + realFile;
- throw new BuildException(msg, location);
- }
+ loadDefinitions();
+ }
-
- ClassLoader classloader=null;
- if (useCurrentClassloader && classpath != null) {
- log("ignoring the useCurrentClassloader option as a classpath is defined",
- Project.MSG_WARN);
- useCurrentClassloader=false;
- }
- if (!useCurrentClassloader) {
- classloader = makeClassLoader(realFile);
- }
- //parse it and evaluate it.
- evaluateDescriptor(classloader, processAliases(), is);
+ /**
+ * Load definitions in library and classpath
+ *
+ * @exception BuildException failure to access the resource
+ */
+ public boolean loadDefinitions() throws BuildException {
+ return loadDefinitions(ANT_DESCRIPTOR);
}
-
/**
- * Load definitions directly from an external XML file.
+ * Load definitions from resource name in library and classpath
*
- * @param xmlfile XML file in the Antlib format.
- * @exception BuildException failure to open the file
+ * @param res the name of the resources to load
+ * @exception BuildException failure to access the resource
*/
- public void loadDefinitions(File xmlfile)
+ final protected boolean loadDefinitions(String res)
throws BuildException {
+ Path path = makeLoaderClasspath();
+ ClassLoader cl = makeClassLoader(path);
+ boolean found = false;
try {
- InputStream is = new FileInputStream(xmlfile);
- loadDefinitions(is);
+ for (Enumeration e = getDescriptors(path, res); e.hasMoreElements(); ) {
+ URL resURL = (URL)e.nextElement();
+ InputStream is = resURL.openStream();
+ loadDefinitions(cl, is);
+ found = true;
+ }
+ if (!found && onerror.getIndex() != IGNORE) {
+ String sPath = path.toString();
+ if ("".equals(sPath.trim())) {
+ sPath = System.getProperty("java.classpath");
+ }
+ String msg = "Cannot find any " + res +
+ " antlib descriptors in: " + sPath;
+ switch (onerror.getIndex()) {
+ case FAIL:
+ throw new BuildException(msg);
+ case REPORT:
+ log(msg, project.MSG_WARN);
+ }
+ }
}
catch (IOException io) {
- throw new BuildException("Cannot read file: " + file, io);
+ String msg = "Cannot load definitions from: " + res;
+ switch (onerror.getIndex()) {
+ case FAIL:
+ throw new BuildException(msg, io);
+ case REPORT:
+ log(io.getMessage(), project.MSG_WARN);
+ }
}
+ return found;
}
@@ -343,46 +515,29 @@ public class Antlib extends Task {
* @param is InputStream for the Antlib descriptor.
* @exception BuildException trouble
*/
- public void loadDefinitions(InputStream is)
+ private void loadDefinitions(ClassLoader cl, InputStream is)
throws BuildException {
- evaluateDescriptor(null, processAliases(), is);
+ evaluateDescriptor(cl, processAliases(), is);
}
/**
- * get a descriptor from the library file
+ * get an Enumeration of URLs for all resouces corresponding to the
+ * descriptor name.
*
- * @param file jarfile to open
- * @return input stream to the Descriptor
+ * @param res the name of the resource to collect
+ * @return input stream to the Descriptor or null if none existent
* @exception BuildException io trouble, or it isnt a zipfile
*/
- private InputStream getDescriptor(File file)
- throws BuildException {
- try {
- final ZipFile zipfile = new ZipFile(file);
- ZipEntry entry = zipfile.getEntry(ANT_DESCRIPTOR);
-
- if (entry == null) {
- return null;
- }
-
- // Guarantee that when Entry is closed so does the zipfile instance.
- return
- new FilterInputStream(zipfile.getInputStream(entry)) {
- public void close()
- throws IOException {
- super.close();
- zipfile.close();
- }
- };
- }
- catch (ZipException ze) {
- throw new BuildException("Not a library file.", ze, location);
- }
- catch (IOException ioe) {
- throw new BuildException("Cannot read library content.",
- ioe, location);
+ private Enumeration getDescriptors(Path path, final String res)
+ throws BuildException, IOException {
+ if (loaderId == null) {
+ // Path cannot be added to the CoreLoader so simply
+ // ask for all instances of the resource descriptors
+ return project.getCoreLoader().getResources(res);
}
+
+ return new DescriptorEnumeration(path.list(), res);
}
@@ -410,18 +565,34 @@ public class Antlib extends Task {
* @return classloader using te
* @exception BuildException trouble creating the classloader
*/
- protected ClassLoader makeClassLoader(File file)
+ protected ClassLoader makeClassLoader(Path clspath)
throws BuildException {
+ if (loaderId == null) {
+ log("Loading definitions from CORE, ignored",
+ project.MSG_VERBOSE);
+ return project.getCoreLoader();
+ }
+
+ log("Using ClassLoader '" + loaderId + "' to load path: " + clspath,
+ project.MSG_VERBOSE);
+ return project.addToLoader(loaderId, clspath);
+ }
+
+
+ /**
+ * Constructs the Path to add to the ClassLoader
+ */
+ private Path makeLoaderClasspath()
+ {
Path clspath = new Path(project);
- clspath.setLocation(file);
+ if (file != null) clspath.setLocation(file);
//append any build supplied classpath
if (classpath != null) {
clspath.append(classpath);
}
- return project.getSymbols().addToLoader(loaderId, clspath);
+ return clspath;
}
-
/**
* parse the antlib descriptor
*
@@ -431,8 +602,8 @@ public class Antlib extends Task {
* @exception BuildException trouble
*/
protected void evaluateDescriptor(ClassLoader cl,
- Properties als, InputStream is)
- throws BuildException {
+ Properties als, InputStream is)
+ throws BuildException {
try {
SAXParser saxParser = saxFactory.newSAXParser();
Parser parser = saxParser.getParser();
@@ -440,7 +611,7 @@ public class Antlib extends Task {
InputSource inputSource = new InputSource(is);
//inputSource.setSystemId(uri); //URI is nasty for jar entries
project.log("parsing descriptor for library: " + file,
- Project.MSG_VERBOSE);
+ Project.MSG_VERBOSE);
saxParser.parse(inputSource, new AntLibraryHandler(cl, als));
}
catch (ParserConfigurationException exc) {
@@ -485,8 +656,8 @@ public class Antlib extends Task {
/**
- * Parses the document describing the content of the
- * library. An inner class for access to Project.log
+ * Parses the document describing the content of the
+ * library. An inner class for access to Project.log
*/
private class AntLibraryHandler extends HandlerBase {
@@ -503,13 +674,11 @@ public class Antlib extends Task {
*/
private Locator locator = null;
- private int level = 0;
-
- private SymbolTable symbols = null;
+ private int level = 0;
- private String name = null;
- private String className = null;
- private String adapter = null;
+ private String name = null;
+ private String className = null;
+ private String adapter = null;
/**
* Constructor for the AntLibraryHandler object
@@ -520,7 +689,6 @@ public class Antlib extends Task {
AntLibraryHandler(ClassLoader classloader, Properties als) {
this.classloader = classloader;
this.aliasMap = als;
- this.symbols = project.getSymbols();
}
/**
@@ -533,35 +701,35 @@ public class Antlib extends Task {
this.locator = locator;
}
- private void parseAttributes(String tag, AttributeList attrs)
- throws SAXParseException {
- name = null;
- className = null;
- adapter = null;
-
- for (int i = 0, last = attrs.getLength(); i < last; i++) {
- String key = attrs.getName(i);
- String value = attrs.getValue(i);
-
- if (key.equals("name")) {
- name = value;
- }
- else if (key.equals("class")) {
- className = value;
- }
- else if ("role".equals(tag) && key.equals("adapter")) {
- adapter = value;
- }
- else {
- throw new SAXParseException("Unexpected attribute \""
- + key + "\"", locator);
- }
- }
- if (name == null || className == null) {
- String msg = "Underspecified " + tag + " declaration.";
- throw new SAXParseException(msg, locator);
- }
- }
+ private void parseAttributes(String tag, AttributeList attrs)
+ throws SAXParseException {
+ name = null;
+ className = null;
+ adapter = null;
+
+ for (int i = 0, last = attrs.getLength(); i < last; i++) {
+ String key = attrs.getName(i);
+ String value = attrs.getValue(i);
+
+ if (key.equals("name")) {
+ name = value;
+ }
+ else if (key.equals("class")) {
+ className = value;
+ }
+ else if ("role".equals(tag) && key.equals("adapter")) {
+ adapter = value;
+ }
+ else {
+ throw new SAXParseException("Unexpected attribute \""
+ + key + "\"", locator);
+ }
+ }
+ if (name == null || className == null) {
+ String msg = "Underspecified " + tag + " declaration.";
+ throw new SAXParseException(msg, locator);
+ }
+ }
/**
* SAX callback handler
@@ -572,103 +740,105 @@ public class Antlib extends Task {
*/
public void startElement(String tag, AttributeList attrs)
throws SAXParseException {
- level ++;
+ level ++;
if ("antlib".equals(tag)) {
- if (level > 1) {
- throw new SAXParseException("Unexpected element: " + tag,
- locator);
- }
+ if (level > 1) {
+ throw new SAXParseException("Unexpected element: " + tag,
+ locator);
+ }
// No attributes to worry about
return;
}
- if (level == 1) {
- throw new SAXParseException("Missing antlib root element",
- locator);
- }
-
- // Must have the two attributes declared
- parseAttributes(tag, attrs);
-
- try {
- if ("role".equals(tag)) {
- if (isRoleInUse(name)) {
- String msg = "Cannot override role: " + name;
- log(msg, Project.MSG_WARN);
- return;
- }
- // Defining a new role
- symbols.addRole(name, loadClass(className),
- (adapter == null?
- null : loadClass(adapter)));
- return;
- }
-
- // Defining a new element kind
- //check for name alias
- String alias = aliasMap.getProperty(name);
- if (alias != null) {
- name = alias;
- }
- //catch an attempted override of an existing name
- if (!override && isInUse(tag, name)) {
- String msg = "Cannot override " + tag + ": " + name;
- log(msg, Project.MSG_WARN);
- return;
- }
- symbols.add(tag, name, loadClass(className));
- }
- catch(BuildException be) {
- throw new SAXParseException(be.getMessage(), locator, be);
- }
- }
-
- public void endElement(String tag) {
- level--;
- }
-
- private Class loadClass(String className)
- throws SAXParseException {
- try {
- //load the named class
- Class cls;
- if(classloader==null) {
- cls=Class.forName(className);
- }
- else {
- cls=classloader.loadClass(className);
- }
- return cls;
- }
- catch (ClassNotFoundException cnfe) {
- String msg = "Class " + className +
- " cannot be found";
- throw new SAXParseException(msg, locator, cnfe);
- }
- catch (NoClassDefFoundError ncdfe) {
- String msg = "Class " + className +
- " cannot be found";
- throw new SAXParseException(msg, locator);
- }
- }
+ if (level == 1) {
+ throw new SAXParseException("Missing antlib root element",
+ locator);
+ }
- /**
- * test for a name being in use already on this role
- *
- * @param name the name to test
- * @return true if it is a task or a datatype
- */
- private boolean isInUse(String role, String name) {
- return (symbols.get(role, name) != null);
+ // Must have the two attributes declared
+ parseAttributes(tag, attrs);
+
+ try {
+ if ("role".equals(tag)) {
+ if (project.isRoleDefined(name)) {
+ String msg = "Cannot override role: " + name;
+ log(msg, Project.MSG_WARN);
+ return;
+ }
+ // Defining a new role
+ Class clz = loadClass(className);
+ if (clz != null) {
+ project.addRoleDefinition(name, clz,
+ (adapter == null? null :
+ loadClass(adapter)));
+ }
+ return;
+ }
+
+ // Defining a new element kind
+ //check for name alias
+ String alias = aliasMap.getProperty(name);
+ if (alias != null) {
+ name = alias;
+ }
+ //catch an attempted override of an existing name
+ if (!override && project.isDefinedOnRole(tag, name)) {
+ String msg = "Cannot override " + tag + ": " + name;
+ log(msg, Project.MSG_WARN);
+ return;
+ }
+ Class clz = loadClass(className);
+ if (clz != null)
+ project.addDefinitionOnRole(tag, name, clz);
+ }
+ catch(BuildException be) {
+ switch (onerror.getIndex()) {
+ case FAIL:
+ throw new SAXParseException(be.getMessage(), locator, be);
+ case REPORT:
+ project.log(be.getMessage(), project.MSG_WARN);
+ break;
+ default:
+ project.log(be.getMessage(), project.MSG_DEBUG);
+ }
+ }
}
- /**
- * test for a role name being in use already
- *
- * @param name the name to test
- * @return true if it is a task or a datatype
- */
- private boolean isRoleInUse(String name) {
- return (symbols.getRole(name) != null);
+ public void endElement(String tag) {
+ level--;
+ }
+
+ private Class loadClass(String className)
+ throws SAXParseException {
+ String msg = null;
+ try {
+ //load the named class
+ Class cls;
+ if(classloader==null) {
+ cls=Class.forName(className);
+ }
+ else {
+ cls=classloader.loadClass(className);
+ }
+ return cls;
+ }
+ catch (ClassNotFoundException cnfe) {
+ msg = "Class " + className + " cannot be found";
+ if (onerror.getIndex() == FAIL)
+ throw new SAXParseException(msg, locator, cnfe);
+ }
+ catch (NoClassDefFoundError ncdfe) {
+ msg = "Class " + className + " cannot be loaded";
+ if (onerror.getIndex() == FAIL)
+ throw new SAXParseException(msg, locator);
+ }
+
+ if (onerror.getIndex() == REPORT) {
+ project.log(msg, project.MSG_WARN);
+ }
+ else {
+ project.log(msg, project.MSG_DEBUG);
+ }
+ return null;
}
//end inner class AntLibraryHandler
@@ -712,7 +882,7 @@ public class Antlib extends Task {
}
//end inner class alias
}
-
+
//end class Antlib
}
diff --git a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/types/DataTypeAdapterTask.java b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/types/DataTypeAdapterTask.java
index 18dc7c542..4669a0789 100644
--- a/proposal/sandbox/antlib/src/main/org/apache/tools/ant/types/DataTypeAdapterTask.java
+++ b/proposal/sandbox/antlib/src/main/org/apache/tools/ant/types/DataTypeAdapterTask.java
@@ -66,6 +66,7 @@ import org.apache.tools.ant.*;
public class DataTypeAdapterTask extends Task implements RoleAdapter {
Object proxy;
+ String id = null;
/**
* Checks a class, whether it is suitable to be adapted.
@@ -83,14 +84,27 @@ public class DataTypeAdapterTask extends Task implements RoleAdapter {
* Do the execution.
*/
public void execute() throws BuildException {
+ if (id != null) {
+ // Need to re-register this reference
+ // The container has register the Adapter instead
+ project.addReference(id, proxy);
+ }
+ }
+
+ /**
+ * Propagate configuration of Project
+ */
+ public void setProject(Project p) {
+ super.setProject(p);
+
// Check to see if the DataType has a setProject method to set
if (proxy instanceof ProjectComponent) {
- ((ProjectComponent)proxy).setProject(project);
+ ((ProjectComponent)proxy).setProject(p);
return;
}
// This may not be needed
- // We are trying to set project even it is was not declared
+ // We are trying to set project even if is was not declared
// just like TaskAdapter does for beans, this is not done
// by the original code
Method setProjectM = null;
@@ -99,7 +113,7 @@ public class DataTypeAdapterTask extends Task implements RoleAdapter {
setProjectM =
c.getMethod( "setProject", new Class[] {Project.class});
if(setProjectM != null) {
- setProjectM.invoke(proxy, new Object[] {project});
+ setProjectM.invoke(proxy, new Object[] {p});
}
} catch (NoSuchMethodException e) {
// ignore this if the class being used as a task does not have
@@ -122,4 +136,8 @@ public class DataTypeAdapterTask extends Task implements RoleAdapter {
return this.proxy ;
}
+ public void setId(String id) {
+ log("Setting adapter id to: " + id, Project.MSG_DEBUG);
+ this.id = id;
+ }
}