ehatcher 02/03/03 04:37:13
Modified: proposal/sandbox/antlib/src/main/org/apache/tools/ant/types
DataTypeAdapterTask.java
proposal/sandbox/antlib/src/main/org/apache/tools/ant
IntrospectionHelper.java Project.java
ProjectHelper.java RoleAdapter.java
SymbolTable.java TaskAdapter.java
Log:
once again for Jose Alberto - think I got it right this time
Revision Changes Path
1.4 +21 -3
jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/types/DataTypeAdapterTask.java
Index: DataTypeAdapterTask.java
===================================================================
RCS file:
/home/cvs/jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/types/DataTypeAdapterTask.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- DataTypeAdapterTask.java 2 Mar 2002 22:23:10 -0000 1.3
+++ DataTypeAdapterTask.java 3 Mar 2002 12:37:13 -0000 1.4
@@ -66,6 +66,7 @@
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 @@
* 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 @@
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 @@
return this.proxy ;
}
+ public void setId(String id) {
+ log("Setting adapter id to: " + id, Project.MSG_DEBUG);
+ this.id = id;
+ }
}
1.2 +706 -706
jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/IntrospectionHelper.java
Index: IntrospectionHelper.java
===================================================================
RCS file:
/home/cvs/jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/IntrospectionHelper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- IntrospectionHelper.java 18 Feb 2002 08:55:16 -0000 1.1
+++ IntrospectionHelper.java 3 Mar 2002 12:37:13 -0000 1.2
@@ -1,706 +1,706 @@
-/*
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowlegement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowlegement may appear in the software itself,
- * if and wherever such third-party acknowlegements normally appear.
- *
- * 4. The names "The Jakarta Project", "Ant", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact [EMAIL PROTECTED]
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Group.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-package org.apache.tools.ant;
-
-import org.apache.tools.ant.types.Path;
-import org.apache.tools.ant.types.EnumeratedAttribute;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Constructor;
-import java.io.File;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Locale;
-
-/**
- * Helper class that collects the methods a task or nested element
- * holds to set attributes, create nested elements or hold PCDATA
- * elements.
- *
- * @author <a href="mailto:[EMAIL PROTECTED]">Stefan Bodewig</a>
- */
-public class IntrospectionHelper implements BuildListener {
-
- /**
- * holds the types of the attributes that could be set.
- */
- private Hashtable attributeTypes;
-
- /**
- * holds the attribute setter methods.
- */
- private Hashtable attributeSetters;
-
- /**
- * Holds the types of nested elements that could be created.
- */
- private Hashtable nestedTypes;
-
- /**
- * Holds methods to create nested elements.
- */
- private Hashtable nestedCreators;
-
- /**
- * Holds methods to store configured nested elements.
- */
- private Hashtable nestedStorers;
-
- /**
- * The method to add PCDATA stuff.
- */
- private Method addText = null;
-
- /**
- * The Class that's been introspected.
- */
- private Class bean;
-
- /**
- * instances we've already created
- */
- private static Hashtable helpers = new Hashtable();
-
- private IntrospectionHelper(final Class bean) {
- attributeTypes = new Hashtable();
- attributeSetters = new Hashtable();
- nestedTypes = new Hashtable();
- nestedCreators = new Hashtable();
- nestedStorers = new Hashtable();
-
- this.bean = bean;
-
- Method[] methods = bean.getMethods();
- for (int i=0; i<methods.length; i++) {
- final Method m = methods[i];
- final String name = m.getName();
- Class returnType = m.getReturnType();
- Class[] args = m.getParameterTypes();
-
- // not really user settable properties on tasks
- if (org.apache.tools.ant.Task.class.isAssignableFrom(bean)
- && args.length == 1 &&
- (
- (
- "setLocation".equals(name) &&
org.apache.tools.ant.Location.class.equals(args[0])
- ) || (
- "setTaskType".equals(name) &&
java.lang.String.class.equals(args[0])
- )
- )) {
- continue;
- }
-
- // hide addTask for TaskContainers
-// if
(org.apache.tools.ant.TaskContainer.class.isAssignableFrom(bean)
-// && args.length == 1 && "addTask".equals(name)
-// && org.apache.tools.ant.Task.class.equals(args[0])) {
-// continue;
-// }
-
-
- if ("addText".equals(name)
- && java.lang.Void.TYPE.equals(returnType)
- && args.length == 1
- && java.lang.String.class.equals(args[0])) {
-
- addText = methods[i];
-
- } else if (name.startsWith("set")
- && java.lang.Void.TYPE.equals(returnType)
- && args.length == 1
- && !args[0].isArray()) {
-
- String propName = getPropertyName(name, "set");
- if (attributeSetters.get(propName) != null) {
- if (java.lang.String.class.equals(args[0])) {
- /*
- Ignore method m, as there is an overloaded
- form of this method that takes in a
- non-string argument, which gains higher
- priority.
- */
- continue;
- }
- /*
- If the argument is not a String, and if there
- is an overloaded form of this method already defined,
- we just override that with the new one.
- This mechanism does not guarantee any specific order
- in which the methods will be selected: so any code
- that depends on the order in which "set" methods have
- been defined, is not guaranteed to be selected in any
- particular order.
- */
- }
- AttributeSetter as = createAttributeSetter(m, args[0]);
- if (as != null) {
- attributeTypes.put(propName, args[0]);
- attributeSetters.put(propName, as);
- }
-
- } else if (name.startsWith("create")
- && !returnType.isArray()
- && !returnType.isPrimitive()
- && args.length == 0) {
-
- String propName = getPropertyName(name, "create");
- nestedTypes.put(propName, returnType);
- nestedCreators.put(propName, new NestedCreator() {
-
- public Object create(Object parent)
- throws InvocationTargetException,
- IllegalAccessException {
-
- return m.invoke(parent, new Object[] {});
- }
-
- });
- nestedStorers.remove(propName);
-
- } else if (name.startsWith("addConfigured")
- && java.lang.Void.TYPE.equals(returnType)
- && args.length == 1
- && !java.lang.String.class.equals(args[0])
- && !args[0].isArray()
- && !args[0].isPrimitive()) {
-
- try {
- final Constructor c =
- args[0].getConstructor(new Class[] {});
- String propName = getPropertyName(name, "addConfigured");
- nestedTypes.put(propName, args[0]);
- nestedCreators.put(propName, new NestedCreator() {
-
- public Object create(Object parent)
- throws InvocationTargetException,
- IllegalAccessException,
- InstantiationException {
-
- Object o = c.newInstance(new Object[] {});
- return o;
- }
-
- });
- nestedStorers.put(propName, new NestedStorer() {
-
- public void store(Object parent, Object child)
- throws InvocationTargetException,
- IllegalAccessException,
- InstantiationException {
-
- m.invoke(parent, new Object[] {child});
- }
-
- });
- } catch (NoSuchMethodException nse) {
- }
- } else if (name.startsWith("add")
- && java.lang.Void.TYPE.equals(returnType)
- && args.length == 1
- && !java.lang.String.class.equals(args[0])
- && !args[0].isArray()
- && !args[0].isPrimitive()) {
-
- try {
- final Constructor c =
- args[0].getConstructor(new Class[] {});
- String propName = getPropertyName(name, "add");
- nestedTypes.put(propName, args[0]);
- nestedCreators.put(propName, new NestedCreator() {
-
- public Object create(Object parent)
- throws InvocationTargetException,
- IllegalAccessException,
- InstantiationException {
-
- Object o = c.newInstance(new Object[] {});
- m.invoke(parent, new Object[] {o});
- return o;
- }
-
- });
- nestedStorers.remove(name);
- } catch (NoSuchMethodException nse) {
- }
- }
- }
- }
-
- /**
- * Factory method for helper objects.
- */
- public static synchronized IntrospectionHelper getHelper(Class c) {
- IntrospectionHelper ih = (IntrospectionHelper) helpers.get(c);
- if (ih == null) {
- ih = new IntrospectionHelper(c);
- helpers.put(c, ih);
- }
- return ih;
- }
-
- /**
- * Sets the named attribute.
- */
- public void setAttribute(Project p, Object element, String attributeName,
- String value)
- throws BuildException {
- AttributeSetter as = (AttributeSetter)
attributeSetters.get(attributeName);
- if (as == null) {
- String msg = getElementName(p, element) +
- //String msg = "Class " + element.getClass().getName() +
- " doesn't support the \"" + attributeName + "\" attribute.";
- throw new BuildException(msg);
- }
- try {
- as.set(p, element, value);
- } catch (IllegalAccessException ie) {
- // impossible as getMethods should only return public methods
- throw new BuildException(ie);
- } catch (InvocationTargetException ite) {
- Throwable t = ite.getTargetException();
- if (t instanceof BuildException) {
- throw (BuildException) t;
- }
- throw new BuildException(t);
- }
- }
-
- /**
- * Adds PCDATA areas.
- */
- public void addText(Project project, Object element, String text) {
- if (addText == null) {
- // Element doesn't handle text content
- if ( text.trim().length() == 0 ) {
- // Only whitespace - ignore
- return;
- }
- else {
- // Not whitespace - fail
- String msg = getElementName(project, element) +
- " doesn't support nested text data.";
- throw new BuildException(msg);
- }
- }
- try {
- addText.invoke(element, new String[] {text});
- } catch (IllegalAccessException ie) {
- // impossible as getMethods should only return public methods
- throw new BuildException(ie);
- } catch (InvocationTargetException ite) {
- Throwable t = ite.getTargetException();
- if (t instanceof BuildException) {
- throw (BuildException) t;
- }
- throw new BuildException(t);
- }
- }
-
- /**
- * Creates a named nested element.
- */
- public Object createElement(Project project, Object element, String
elementName)
- throws BuildException {
-
- try {
- // First check if there are any roles supported by this class
- Object nestedElement = project.createInRole(element, elementName);
- if (nestedElement == null) {
- NestedCreator nc =
- (NestedCreator) nestedCreators.get(elementName);
- if (nc == null) {
- String msg = getElementName(project, element) +
- " doesn't support the nested \"" + elementName +
- "\" element.";
- throw new BuildException(msg);
- }
- nestedElement = nc.create(element);
- }
- if (nestedElement instanceof ProjectComponent) {
- ((ProjectComponent) nestedElement).setProject(project);
- }
- return nestedElement;
- } catch (IllegalAccessException ie) {
- // impossible as getMethods should only return public methods
- throw new BuildException(ie);
- } catch (InstantiationException ine) {
- // impossible as getMethods should only return public methods
- throw new BuildException(ine);
- } catch (InvocationTargetException ite) {
- Throwable t = ite.getTargetException();
- if (t instanceof BuildException) {
- throw (BuildException) t;
- }
- throw new BuildException(t);
- }
- }
-
- /**
- * Creates a named nested element.
- */
- public void storeElement(Project project, Object element, Object child,
String elementName)
- throws BuildException {
- if (elementName == null) {
- return;
- }
- NestedStorer ns = (NestedStorer)nestedStorers.get(elementName);
- if (ns == null) {
- return;
- }
- try {
- ns.store(element, child);
- } catch (IllegalAccessException ie) {
- // impossible as getMethods should only return public methods
- throw new BuildException(ie);
- } catch (InstantiationException ine) {
- // impossible as getMethods should only return public methods
- throw new BuildException(ine);
- } catch (InvocationTargetException ite) {
- Throwable t = ite.getTargetException();
- if (t instanceof BuildException) {
- throw (BuildException) t;
- }
- throw new BuildException(t);
- }
- }
-
- /**
- * returns the type of a named nested element.
- */
- public Class getElementType(String elementName)
- throws BuildException {
- Class nt = (Class) nestedTypes.get(elementName);
- if (nt == null) {
- String msg = "Class " + bean.getName() +
- " doesn't support the nested \"" + elementName + "\"
element.";
- throw new BuildException(msg);
- }
- return nt;
- }
-
- /**
- * returns the type of a named attribute.
- */
- public Class getAttributeType(String attributeName)
- throws BuildException {
- Class at = (Class) attributeTypes.get(attributeName);
- if (at == null) {
- String msg = "Class " + bean.getName() +
- " doesn't support the \"" + attributeName + "\" attribute.";
- throw new BuildException(msg);
- }
- return at;
- }
-
- /**
- * Does the introspected class support PCDATA?
- */
- public boolean supportsCharacters() {
- return addText != null;
- }
-
- /**
- * Return all attribues supported by the introspected class.
- */
- public Enumeration getAttributes() {
- return attributeSetters.keys();
- }
-
- /**
- * Return all nested elements supported by the introspected class.
- */
- public Enumeration getNestedElements() {
- return nestedTypes.keys();
- }
-
- /**
- * Create a proper implementation of AttributeSetter for the given
- * attribute type.
- */
- private AttributeSetter createAttributeSetter(final Method m,
- final Class arg) {
-
- // simplest case - setAttribute expects String
- if (java.lang.String.class.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException {
- m.invoke(parent, new String[] {value});
- }
- };
-
- // now for the primitive types, use their wrappers
- } else if (java.lang.Character.class.equals(arg)
- || java.lang.Character.TYPE.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException {
- m.invoke(parent, new Character[] {new
Character(value.charAt(0))});
- }
-
- };
- } else if (java.lang.Byte.TYPE.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException {
- m.invoke(parent, new Byte[] {new Byte(value)});
- }
-
- };
- } else if (java.lang.Short.TYPE.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException {
- m.invoke(parent, new Short[] {new Short(value)});
- }
-
- };
- } else if (java.lang.Integer.TYPE.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException {
- m.invoke(parent, new Integer[] {new Integer(value)});
- }
-
- };
- } else if (java.lang.Long.TYPE.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException {
- m.invoke(parent, new Long[] {new Long(value)});
- }
-
- };
- } else if (java.lang.Float.TYPE.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException {
- m.invoke(parent, new Float[] {new Float(value)});
- }
-
- };
- } else if (java.lang.Double.TYPE.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException {
- m.invoke(parent, new Double[] {new Double(value)});
- }
-
- };
-
- // boolean gets an extra treatment, because we have a nice method
- // in Project
- } else if (java.lang.Boolean.class.equals(arg)
- || java.lang.Boolean.TYPE.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException {
- m.invoke(parent,
- new Boolean[] {new
Boolean(Project.toBoolean(value))});
- }
-
- };
-
- // Class doesn't have a String constructor but a decent factory
method
- } else if (java.lang.Class.class.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException, BuildException {
- try {
- m.invoke(parent, new Class[]
{Class.forName(value)});
- } catch (ClassNotFoundException ce) {
- throw new BuildException(ce);
- }
- }
- };
-
- // resolve relative paths through Project
- } else if (java.io.File.class.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException {
- m.invoke(parent, new File[] {p.resolveFile(value)});
- }
-
- };
-
- // resolve relative paths through Project
- } else if (org.apache.tools.ant.types.Path.class.equals(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException {
- m.invoke(parent, new Path[] {new Path(p, value)});
- }
-
- };
-
- // EnumeratedAttributes have their own helper class
- } else if
(org.apache.tools.ant.types.EnumeratedAttribute.class.isAssignableFrom(arg)) {
- return new AttributeSetter() {
- public void set(Project p, Object parent, String value)
- throws InvocationTargetException,
IllegalAccessException, BuildException {
- try {
- org.apache.tools.ant.types.EnumeratedAttribute
ea = (org.apache.tools.ant.types.EnumeratedAttribute)arg.newInstance();
- ea.setValue(value);
- m.invoke(parent, new EnumeratedAttribute[] {ea});
- } catch (InstantiationException ie) {
- throw new BuildException(ie);
- }
- }
- };
-
- // worst case. look for a public String constructor and use it
- } else {
-
- try {
- final Constructor c =
- arg.getConstructor(new Class[] {java.lang.String.class});
-
- return new AttributeSetter() {
- public void set(Project p, Object parent,
- String value)
- throws InvocationTargetException,
IllegalAccessException, BuildException {
- try {
- Object attribute = c.newInstance(new
String[] {value});
- if (attribute instanceof ProjectComponent) {
- ((ProjectComponent)
attribute).setProject(p);
- }
- m.invoke(parent, new Object[] {attribute});
- } catch (InstantiationException ie) {
- throw new BuildException(ie);
- }
- }
- };
-
- } catch (NoSuchMethodException nme) {
- }
- }
-
- return null;
- }
-
- protected String getElementName(Project project, Object element)
- {
- Hashtable elements = project.getTaskDefinitions();
- String typeName = "task";
- if (!elements.contains( element.getClass() ))
- {
- elements = project.getDataTypeDefinitions();
- typeName = "data type";
- if (!elements.contains( element.getClass() ))
- {
- elements = null;
- }
- }
-
- if (elements != null)
- {
- Enumeration e = elements.keys();
- while (e.hasMoreElements())
- {
- String elementName = (String) e.nextElement();
- Class elementClass = (Class) elements.get( elementName );
- if ( element.getClass().equals( elementClass ) )
- {
- return "The <" + elementName + "> " + typeName;
- }
- }
- }
-
- return "Class " + element.getClass().getName();
- }
-
- /**
- * extract the name of a property from a method name - subtracting
- * a given prefix.
- */
- private String getPropertyName(String methodName, String prefix) {
- int start = prefix.length();
- return methodName.substring(start).toLowerCase(Locale.US);
- }
-
- private interface NestedCreator {
- Object create(Object parent)
- throws InvocationTargetException, IllegalAccessException,
InstantiationException;
- }
-
- private interface NestedStorer {
- void store(Object parent, Object child)
- throws InvocationTargetException, IllegalAccessException,
InstantiationException;
- }
-
- private interface AttributeSetter {
- void set(Project p, Object parent, String value)
- throws InvocationTargetException, IllegalAccessException,
- BuildException;
- }
-
- public void buildStarted(BuildEvent event) {}
- public void buildFinished(BuildEvent event) {
- attributeTypes.clear();
- attributeSetters.clear();
- nestedTypes.clear();
- nestedCreators.clear();
- addText = null;
- helpers.clear();
- }
-
- public void targetStarted(BuildEvent event) {}
- public void targetFinished(BuildEvent event) {}
- public void taskStarted(BuildEvent event) {}
- public void taskFinished(BuildEvent event) {}
- public void messageLogged(BuildEvent event) {}
-}
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact [EMAIL PROTECTED]
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.tools.ant;
+
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.EnumeratedAttribute;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
+import java.io.File;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+
+/**
+ * Helper class that collects the methods a task or nested element
+ * holds to set attributes, create nested elements or hold PCDATA
+ * elements.
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Stefan Bodewig</a>
+ */
+public class IntrospectionHelper implements BuildListener {
+
+ /**
+ * holds the types of the attributes that could be set.
+ */
+ private Hashtable attributeTypes;
+
+ /**
+ * holds the attribute setter methods.
+ */
+ private Hashtable attributeSetters;
+
+ /**
+ * Holds the types of nested elements that could be created.
+ */
+ private Hashtable nestedTypes;
+
+ /**
+ * Holds methods to create nested elements.
+ */
+ private Hashtable nestedCreators;
+
+ /**
+ * Holds methods to store configured nested elements.
+ */
+ private Hashtable nestedStorers;
+
+ /**
+ * The method to add PCDATA stuff.
+ */
+ private Method addText = null;
+
+ /**
+ * The Class that's been introspected.
+ */
+ private Class bean;
+
+ /**
+ * instances we've already created
+ */
+ private static Hashtable helpers = new Hashtable();
+
+ private IntrospectionHelper(final Class bean) {
+ attributeTypes = new Hashtable();
+ attributeSetters = new Hashtable();
+ nestedTypes = new Hashtable();
+ nestedCreators = new Hashtable();
+ nestedStorers = new Hashtable();
+
+ this.bean = bean;
+
+ Method[] methods = bean.getMethods();
+ for (int i=0; i<methods.length; i++) {
+ final Method m = methods[i];
+ final String name = m.getName();
+ Class returnType = m.getReturnType();
+ Class[] args = m.getParameterTypes();
+
+ // not really user settable properties on tasks
+ if (org.apache.tools.ant.Task.class.isAssignableFrom(bean)
+ && args.length == 1 &&
+ (
+ (
+ "setLocation".equals(name) &&
org.apache.tools.ant.Location.class.equals(args[0])
+ ) || (
+ "setTaskType".equals(name) &&
java.lang.String.class.equals(args[0])
+ )
+ )) {
+ continue;
+ }
+
+ // hide addTask for TaskContainers
+// if
(org.apache.tools.ant.TaskContainer.class.isAssignableFrom(bean)
+// && args.length == 1 && "addTask".equals(name)
+// && org.apache.tools.ant.Task.class.equals(args[0])) {
+// continue;
+// }
+
+
+ if ("addText".equals(name)
+ && java.lang.Void.TYPE.equals(returnType)
+ && args.length == 1
+ && java.lang.String.class.equals(args[0])) {
+
+ addText = methods[i];
+
+ } else if (name.startsWith("set")
+ && java.lang.Void.TYPE.equals(returnType)
+ && args.length == 1
+ && !args[0].isArray()) {
+
+ String propName = getPropertyName(name, "set");
+ if (attributeSetters.get(propName) != null) {
+ if (java.lang.String.class.equals(args[0])) {
+ /*
+ Ignore method m, as there is an overloaded
+ form of this method that takes in a
+ non-string argument, which gains higher
+ priority.
+ */
+ continue;
+ }
+ /*
+ If the argument is not a String, and if there
+ is an overloaded form of this method already defined,
+ we just override that with the new one.
+ This mechanism does not guarantee any specific order
+ in which the methods will be selected: so any code
+ that depends on the order in which "set" methods have
+ been defined, is not guaranteed to be selected in any
+ particular order.
+ */
+ }
+ AttributeSetter as = createAttributeSetter(m, args[0]);
+ if (as != null) {
+ attributeTypes.put(propName, args[0]);
+ attributeSetters.put(propName, as);
+ }
+
+ } else if (name.startsWith("create")
+ && !returnType.isArray()
+ && !returnType.isPrimitive()
+ && args.length == 0) {
+
+ String propName = getPropertyName(name, "create");
+ nestedTypes.put(propName, returnType);
+ nestedCreators.put(propName, new NestedCreator() {
+
+ public Object create(Object parent)
+ throws InvocationTargetException,
+ IllegalAccessException {
+
+ return m.invoke(parent, new Object[] {});
+ }
+
+ });
+ nestedStorers.remove(propName);
+
+ } else if (name.startsWith("addConfigured")
+ && java.lang.Void.TYPE.equals(returnType)
+ && args.length == 1
+ && !java.lang.String.class.equals(args[0])
+ && !args[0].isArray()
+ && !args[0].isPrimitive()) {
+
+ try {
+ final Constructor c =
+ args[0].getConstructor(new Class[] {});
+ String propName = getPropertyName(name, "addConfigured");
+ nestedTypes.put(propName, args[0]);
+ nestedCreators.put(propName, new NestedCreator() {
+
+ public Object create(Object parent)
+ throws InvocationTargetException,
+ IllegalAccessException,
+ InstantiationException {
+
+ Object o = c.newInstance(new Object[] {});
+ return o;
+ }
+
+ });
+ nestedStorers.put(propName, new NestedStorer() {
+
+ public void store(Object parent, Object child)
+ throws InvocationTargetException,
+ IllegalAccessException,
+ InstantiationException {
+
+ m.invoke(parent, new Object[] {child});
+ }
+
+ });
+ } catch (NoSuchMethodException nse) {
+ }
+ } else if (name.startsWith("add")
+ && java.lang.Void.TYPE.equals(returnType)
+ && args.length == 1
+ && !java.lang.String.class.equals(args[0])
+ && !args[0].isArray()
+ && !args[0].isPrimitive()) {
+
+ try {
+ final Constructor c =
+ args[0].getConstructor(new Class[] {});
+ String propName = getPropertyName(name, "add");
+ nestedTypes.put(propName, args[0]);
+ nestedCreators.put(propName, new NestedCreator() {
+
+ public Object create(Object parent)
+ throws InvocationTargetException,
+ IllegalAccessException,
+ InstantiationException {
+
+ Object o = c.newInstance(new Object[] {});
+ m.invoke(parent, new Object[] {o});
+ return o;
+ }
+
+ });
+ nestedStorers.remove(name);
+ } catch (NoSuchMethodException nse) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Factory method for helper objects.
+ */
+ public static synchronized IntrospectionHelper getHelper(Class c) {
+ IntrospectionHelper ih = (IntrospectionHelper) helpers.get(c);
+ if (ih == null) {
+ ih = new IntrospectionHelper(c);
+ helpers.put(c, ih);
+ }
+ return ih;
+ }
+
+ /**
+ * Sets the named attribute.
+ */
+ public void setAttribute(Project p, Object element, String attributeName,
+ String value)
+ throws BuildException {
+ AttributeSetter as = (AttributeSetter)
attributeSetters.get(attributeName);
+ if (as == null) {
+ String msg = getElementName(p, element) +
+ //String msg = "Class " + element.getClass().getName() +
+ " doesn't support the \"" + attributeName + "\" attribute.";
+ throw new BuildException(msg);
+ }
+ try {
+ as.set(p, element, value);
+ } catch (IllegalAccessException ie) {
+ // impossible as getMethods should only return public methods
+ throw new BuildException(ie);
+ } catch (InvocationTargetException ite) {
+ Throwable t = ite.getTargetException();
+ if (t instanceof BuildException) {
+ throw (BuildException) t;
+ }
+ throw new BuildException(t);
+ }
+ }
+
+ /**
+ * Adds PCDATA areas.
+ */
+ public void addText(Project project, Object element, String text) {
+ if (addText == null) {
+ // Element doesn't handle text content
+ if ( text.trim().length() == 0 ) {
+ // Only whitespace - ignore
+ return;
+ }
+ else {
+ // Not whitespace - fail
+ String msg = getElementName(project, element) +
+ " doesn't support nested text data.";
+ throw new BuildException(msg);
+ }
+ }
+ try {
+ addText.invoke(element, new String[] {text});
+ } catch (IllegalAccessException ie) {
+ // impossible as getMethods should only return public methods
+ throw new BuildException(ie);
+ } catch (InvocationTargetException ite) {
+ Throwable t = ite.getTargetException();
+ if (t instanceof BuildException) {
+ throw (BuildException) t;
+ }
+ throw new BuildException(t);
+ }
+ }
+
+ /**
+ * Creates a named nested element.
+ */
+ public Object createElement(Project project, Object element, String
elementName)
+ throws BuildException {
+
+ try {
+ // First check if there are any roles supported by this class
+ Object nestedElement = project.createInRole(element, elementName);
+ if (nestedElement == null) {
+ NestedCreator nc =
+ (NestedCreator) nestedCreators.get(elementName);
+ if (nc == null) {
+ String msg = getElementName(project, element) +
+ " doesn't support the nested \"" + elementName +
+ "\" element.";
+ throw new BuildException(msg);
+ }
+ nestedElement = nc.create(element);
+ }
+ if (nestedElement instanceof ProjectComponent) {
+ ((ProjectComponent) nestedElement).setProject(project);
+ }
+ return nestedElement;
+ } catch (IllegalAccessException ie) {
+ // impossible as getMethods should only return public methods
+ throw new BuildException(ie);
+ } catch (InstantiationException ine) {
+ // impossible as getMethods should only return public methods
+ throw new BuildException(ine);
+ } catch (InvocationTargetException ite) {
+ Throwable t = ite.getTargetException();
+ if (t instanceof BuildException) {
+ throw (BuildException) t;
+ }
+ throw new BuildException(t);
+ }
+ }
+
+ /**
+ * Creates a named nested element.
+ */
+ public void storeElement(Project project, Object element, Object child,
String elementName)
+ throws BuildException {
+ if (elementName == null) {
+ return;
+ }
+ NestedStorer ns = (NestedStorer)nestedStorers.get(elementName);
+ if (ns == null) {
+ return;
+ }
+ try {
+ ns.store(element, child);
+ } catch (IllegalAccessException ie) {
+ // impossible as getMethods should only return public methods
+ throw new BuildException(ie);
+ } catch (InstantiationException ine) {
+ // impossible as getMethods should only return public methods
+ throw new BuildException(ine);
+ } catch (InvocationTargetException ite) {
+ Throwable t = ite.getTargetException();
+ if (t instanceof BuildException) {
+ throw (BuildException) t;
+ }
+ throw new BuildException(t);
+ }
+ }
+
+ /**
+ * returns the type of a named nested element.
+ */
+ public Class getElementType(String elementName)
+ throws BuildException {
+ Class nt = (Class) nestedTypes.get(elementName);
+ if (nt == null) {
+ String msg = "Class " + bean.getName() +
+ " doesn't support the nested \"" + elementName + "\"
element.";
+ throw new BuildException(msg);
+ }
+ return nt;
+ }
+
+ /**
+ * returns the type of a named attribute.
+ */
+ public Class getAttributeType(String attributeName)
+ throws BuildException {
+ Class at = (Class) attributeTypes.get(attributeName);
+ if (at == null) {
+ String msg = "Class " + bean.getName() +
+ " doesn't support the \"" + attributeName + "\" attribute.";
+ throw new BuildException(msg);
+ }
+ return at;
+ }
+
+ /**
+ * Does the introspected class support PCDATA?
+ */
+ public boolean supportsCharacters() {
+ return addText != null;
+ }
+
+ /**
+ * Return all attribues supported by the introspected class.
+ */
+ public Enumeration getAttributes() {
+ return attributeSetters.keys();
+ }
+
+ /**
+ * Return all nested elements supported by the introspected class.
+ */
+ public Enumeration getNestedElements() {
+ return nestedTypes.keys();
+ }
+
+ /**
+ * Create a proper implementation of AttributeSetter for the given
+ * attribute type.
+ */
+ private AttributeSetter createAttributeSetter(final Method m,
+ final Class arg) {
+
+ // simplest case - setAttribute expects String
+ if (java.lang.String.class.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException {
+ m.invoke(parent, new String[] {value});
+ }
+ };
+
+ // now for the primitive types, use their wrappers
+ } else if (java.lang.Character.class.equals(arg)
+ || java.lang.Character.TYPE.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException {
+ m.invoke(parent, new Character[] {new
Character(value.charAt(0))});
+ }
+
+ };
+ } else if (java.lang.Byte.TYPE.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException {
+ m.invoke(parent, new Byte[] {new Byte(value)});
+ }
+
+ };
+ } else if (java.lang.Short.TYPE.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException {
+ m.invoke(parent, new Short[] {new Short(value)});
+ }
+
+ };
+ } else if (java.lang.Integer.TYPE.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException {
+ m.invoke(parent, new Integer[] {new Integer(value)});
+ }
+
+ };
+ } else if (java.lang.Long.TYPE.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException {
+ m.invoke(parent, new Long[] {new Long(value)});
+ }
+
+ };
+ } else if (java.lang.Float.TYPE.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException {
+ m.invoke(parent, new Float[] {new Float(value)});
+ }
+
+ };
+ } else if (java.lang.Double.TYPE.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException {
+ m.invoke(parent, new Double[] {new Double(value)});
+ }
+
+ };
+
+ // boolean gets an extra treatment, because we have a nice method
+ // in Project
+ } else if (java.lang.Boolean.class.equals(arg)
+ || java.lang.Boolean.TYPE.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException {
+ m.invoke(parent,
+ new Boolean[] {new
Boolean(Project.toBoolean(value))});
+ }
+
+ };
+
+ // Class doesn't have a String constructor but a decent factory
method
+ } else if (java.lang.Class.class.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException, BuildException {
+ try {
+ m.invoke(parent, new Class[]
{Class.forName(value)});
+ } catch (ClassNotFoundException ce) {
+ throw new BuildException(ce);
+ }
+ }
+ };
+
+ // resolve relative paths through Project
+ } else if (java.io.File.class.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException {
+ m.invoke(parent, new File[] {p.resolveFile(value)});
+ }
+
+ };
+
+ // resolve relative paths through Project
+ } else if (org.apache.tools.ant.types.Path.class.equals(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException {
+ m.invoke(parent, new Path[] {new Path(p, value)});
+ }
+
+ };
+
+ // EnumeratedAttributes have their own helper class
+ } else if
(org.apache.tools.ant.types.EnumeratedAttribute.class.isAssignableFrom(arg)) {
+ return new AttributeSetter() {
+ public void set(Project p, Object parent, String value)
+ throws InvocationTargetException,
IllegalAccessException, BuildException {
+ try {
+ org.apache.tools.ant.types.EnumeratedAttribute
ea = (org.apache.tools.ant.types.EnumeratedAttribute)arg.newInstance();
+ ea.setValue(value);
+ m.invoke(parent, new EnumeratedAttribute[] {ea});
+ } catch (InstantiationException ie) {
+ throw new BuildException(ie);
+ }
+ }
+ };
+
+ // worst case. look for a public String constructor and use it
+ } else {
+
+ try {
+ final Constructor c =
+ arg.getConstructor(new Class[] {java.lang.String.class});
+
+ return new AttributeSetter() {
+ public void set(Project p, Object parent,
+ String value)
+ throws InvocationTargetException,
IllegalAccessException, BuildException {
+ try {
+ Object attribute = c.newInstance(new
String[] {value});
+ if (attribute instanceof ProjectComponent) {
+ ((ProjectComponent)
attribute).setProject(p);
+ }
+ m.invoke(parent, new Object[] {attribute});
+ } catch (InstantiationException ie) {
+ throw new BuildException(ie);
+ }
+ }
+ };
+
+ } catch (NoSuchMethodException nme) {
+ }
+ }
+
+ return null;
+ }
+
+ protected String getElementName(Project project, Object element)
+ {
+ Hashtable elements = project.getTaskDefinitions();
+ String typeName = "task";
+ if (!elements.contains( element.getClass() ))
+ {
+ elements = project.getDataTypeDefinitions();
+ typeName = "data type";
+ if (!elements.contains( element.getClass() ))
+ {
+ elements = null;
+ }
+ }
+
+ if (elements != null)
+ {
+ Enumeration e = elements.keys();
+ while (e.hasMoreElements())
+ {
+ String elementName = (String) e.nextElement();
+ Class elementClass = (Class) elements.get( elementName );
+ if ( element.getClass().equals( elementClass ) )
+ {
+ return "The <" + elementName + "> " + typeName;
+ }
+ }
+ }
+
+ return "Class " + element.getClass().getName();
+ }
+
+ /**
+ * extract the name of a property from a method name - subtracting
+ * a given prefix.
+ */
+ private String getPropertyName(String methodName, String prefix) {
+ int start = prefix.length();
+ return methodName.substring(start).toLowerCase(Locale.US);
+ }
+
+ private interface NestedCreator {
+ Object create(Object parent)
+ throws InvocationTargetException, IllegalAccessException,
InstantiationException;
+ }
+
+ private interface NestedStorer {
+ void store(Object parent, Object child)
+ throws InvocationTargetException, IllegalAccessException,
InstantiationException;
+ }
+
+ private interface AttributeSetter {
+ void set(Project p, Object parent, String value)
+ throws InvocationTargetException, IllegalAccessException,
+ BuildException;
+ }
+
+ public void buildStarted(BuildEvent event) {}
+ public void buildFinished(BuildEvent event) {
+ attributeTypes.clear();
+ attributeSetters.clear();
+ nestedTypes.clear();
+ nestedCreators.clear();
+ addText = null;
+ helpers.clear();
+ }
+
+ public void targetStarted(BuildEvent event) {}
+ public void targetFinished(BuildEvent event) {}
+ public void taskStarted(BuildEvent event) {}
+ public void taskFinished(BuildEvent event) {}
+ public void messageLogged(BuildEvent event) {}
+}
1.4 +997 -550
jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/Project.java
Index: Project.java
===================================================================
RCS file:
/home/cvs/jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/Project.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Project.java 2 Mar 2002 22:20:43 -0000 1.3
+++ Project.java 3 Mar 2002 12:37:13 -0000 1.4
@@ -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 [EMAIL PROTECTED]
+ * 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 [EMAIL PROTECTED]
*
- * 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
- * <http://www.apache.org/>.
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
*/
-
package org.apache.tools.ant;
import java.io.File;
@@ -63,35 +62,67 @@
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.
- * <p>
- * 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. <p>
*
- * @author [EMAIL PROTECTED]
+ * 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.
+ *
+ [EMAIL PROTECTED] [EMAIL PROTECTED]
+ [EMAIL PROTECTED] [EMAIL PROTECTED]
+ [EMAIL PROTECTED] 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 @@
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 @@
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 @@
private FileUtils fileUtils;
+
/**
- * create a new ant project
+ * <p>
+ *
+ * Description: The only reason for this class is to make the
+ * LoadDefinition method visible in this package.</p>
+ *
+ [EMAIL PROTECTED] jfernandez
+ [EMAIL PROTECTED] 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
*/
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
+ *
+ [EMAIL PROTECTED] 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();
+ // 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();
- 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 (!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();
+ private void autoLoad(File base, String dir) {
+ FileSet fs = new FileSet();
+ fs.setProject(this);
+ fs.setDir(new File(base, dir));
+ fs.setIncludes("*.jar");
- 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");
+ 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.
+ *
+ [EMAIL PROTECTED] 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.
+ *
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] The coreLoader value
+ */
public ClassLoader getCoreLoader() {
+ if (coreLoader == null) {
+ setDefaultCoreLoader();
+ }
return coreLoader;
}
-
+
+
+ /**
+ * Adds a feature to the BuildListener attribute of the Project object
+ *
+ [EMAIL PROTECTED] listener The feature to be added to the
BuildListener attribute
+ */
public void addBuildListener(BuildListener listener) {
listeners.addElement(listener);
}
+
+ /**
+ * Description of the Method
+ *
+ [EMAIL PROTECTED] listener Description of the Parameter
+ */
public void removeBuildListener(BuildListener listener) {
listeners.removeElement(listener);
}
+
+ /**
+ * Gets the buildListeners attribute of the Project object
+ *
+ [EMAIL PROTECTED] The buildListeners value
+ */
public Vector getBuildListeners() {
return listeners;
}
+
/**
- * Get the symbols associated with this project.
+ * Get the symbols associated with this project.
+ *
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] msg text to log
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] task task to use in the log
+ [EMAIL PROTECTED] msg text to log
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] target target to use in the log
+ [EMAIL PROTECTED] msg text to log
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] 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.
+ *
+ [EMAIL PROTECTED] name name of property
+ [EMAIL PROTECTED] value new value of the property
*/
public void setProperty(String name, String value) {
// command line properties take precedence
@@ -343,21 +513,23 @@
}
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.
+ *
+ [EMAIL PROTECTED] name name of property
+ [EMAIL PROTECTED] value new value of the property
+ [EMAIL PROTECTED] 1.5
*/
public void setNewProperty(String name, String value) {
if (null != properties.get(name)) {
@@ -365,26 +537,34 @@
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
+ *
+ [EMAIL PROTECTED] name The new userProperty value
+ [EMAIL PROTECTED] value The new userProperty value
+ [EMAIL PROTECTED] #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.
+ *
+ [EMAIL PROTECTED] name The new propertyInternal value
+ [EMAIL PROTECTED] value The new propertyInternal value
*/
private void setPropertyInternal(String name, String value) {
if (null != userProperties.get(name)) {
@@ -393,182 +573,226 @@
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.
+ *
+ [EMAIL PROTECTED] name the name of the property
+ [EMAIL PROTECTED] 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.
+ [EMAIL PROTECTED] value the string to be scanned for
property
+ * references.
+ [EMAIL PROTECTED] Description of the Return Value
+ [EMAIL PROTECTED] 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.
+ *
+ [EMAIL PROTECTED] name the name of the property
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] defaultTarget The new defaultTarget value
+ [EMAIL PROTECTED], use setDefault
+ [EMAIL PROTECTED] #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
+ *
+ [EMAIL PROTECTED] 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.
+ *
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] name string
*/
public String getName() {
return name;
}
- /** set the project description
- * @param description text
+
+ /**
+ * set the project description
+ *
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] description or null if no description has been set
*/
public String getDescription() {
return description;
}
- /** @deprecated */
+
+ /**
+ [EMAIL PROTECTED] token The feature to be added to the Filter
attribute
+ [EMAIL PROTECTED] value The feature to be added to the Filter
attribute
+ [EMAIL PROTECTED]
+ */
public void addFilter(String token, String value) {
if (token == null) {
return;
}
-
+
globalFilterSet.addFilter(new FilterSet.Filter(token, value));
}
- /** @deprecated */
+
+ /**
+ [EMAIL PROTECTED] The filters value
+ [EMAIL PROTECTED]
+ */
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
+ *
+ [EMAIL PROTECTED] baseD project base directory.
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] baseDir project base directory.
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] the base directory. If this is null, then the base
dir is not
+ * valid
*/
public File getBaseDir() {
if (baseDir == null) {
@@ -581,18 +805,22 @@
return baseDir;
}
+
/**
- * static query of the java version
- * @return something like "1.1" or "1.3"
+ * static query of the java version
+ *
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] BuildException if this Java version is not supported
*/
public void setJavaVersionProperty() throws BuildException {
setPropertyInternal("ant.java.version", javaVersion);
@@ -607,163 +835,202 @@
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
+ *
+ [EMAIL PROTECTED] loader The feature to be added to the ToLoader
attribute
+ [EMAIL PROTECTED] path The feature to be added to the ToLoader
attribute
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] role The feature to be added to the
RoleDefinition attribute
+ [EMAIL PROTECTED] roleClass The feature to be added to the
RoleDefinition attribute
+ [EMAIL PROTECTED] adapter The feature to be added to the
RoleDefinition attribute
+ [EMAIL PROTECTED] 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
+ [EMAIL PROTECTED] name the name to test
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] role The feature to be added to the
DefinitionOnRole attribute
+ [EMAIL PROTECTED] type The feature to be added to the
DefinitionOnRole attribute
+ [EMAIL PROTECTED] 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
+ [EMAIL PROTECTED] name the name to test
+ [EMAIL PROTECTED] role Description of the Parameter
+ [EMAIL PROTECTED] true if it is a task or a datatype
*/
public boolean isDefinedOnRole(String role, String name) {
- return (symbols.get(role, name) != null);
+ return (symbols.get(role, name) != null);
}
-
+
+
/**
- * turn all the system properties into ant properties.
- * user properties still override these values
+ * add a new task definition, complain if there is an overwrite attempt
+ *
+ [EMAIL PROTECTED] taskName name of the task
+ [EMAIL PROTECTED] taskClass full task classname
+ [EMAIL PROTECTED] BuildException and logs as Project.MSG_ERR for
conditions, that
+ * will cause the task execution to fail.
*/
- 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);
- }
+ public void addTaskDefinition(String taskName, Class taskClass)
+ throws BuildException {
+ addDefinitionOnRole(TASK_ROLE, taskName, taskClass);
}
- /**
- * 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);
- }
/**
- * 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.
+ *
+ [EMAIL PROTECTED] taskClass Description of the Parameter
+ [EMAIL PROTECTED] BuildException and logs as Project.MSG_ERR for
conditions, that
+ * will cause the task execution to fail.
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] typeName name of the datatype
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] The dataTypeDefinitions value
*/
public Hashtable getDataTypeDefinitions() {
- return symbols.getDataTypeDefinitions();
+ return symbols.getDefinitions(DATATYPE_ROLE);
}
+
/**
- * This call expects to add a <em>new</em> 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 <em>new</em> Target.
+ *
+ [EMAIL PROTECTED] target is the Target to be added to the
current
+ * Project.
+ [EMAIL PROTECTED] 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 <em>new</em> 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 <em>new</em> Target.
+ *
+ [EMAIL PROTECTED] target is the Target to be added to the
current
+ * Project.
+ [EMAIL PROTECTED] targetName is the name to use for the Target
+ [EMAIL PROTECTED] BuildException if the Target already exists in the
project.
+ [EMAIL PROTECTED] 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.
+ [EMAIL PROTECTED] 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
+ [EMAIL PROTECTED] target is the Target to be added/replaced in
the current
+ * Project.
+ [EMAIL PROTECTED] targetName is the name to use for the Target
*/
public void addOrReplaceTarget(String targetName, Target target) {
String msg = " +Target: " + targetName;
@@ -772,59 +1039,123 @@
targets.put(targetName, target);
}
+
/**
- * get the target hashtable
- * @return hashtable, the contents of which can be cast to Target
+ * get the target hashtable
+ *
+ [EMAIL PROTECTED] 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
- */
- public Task createTask(String taskType) throws BuildException {
- Class c = symbols.get("task", taskType);
- if (c == null) {
+ /**
+ * Create a new element instance on a Role
+ *
+ [EMAIL PROTECTED] role name of the role to use
+ [EMAIL PROTECTED] type name of the element to create
+ [EMAIL PROTECTED] null if element unknown on this role
+ */
+ 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);
}
}
+
+ /**
+ [EMAIL PROTECTED] container Description of the Parameter
+ [EMAIL PROTECTED] type Description of the Parameter
+ [EMAIL PROTECTED] 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;
+ }
+
+
+ /**
+ * create a new task instance
+ *
+ [EMAIL PROTECTED] taskType name of the task
+ [EMAIL PROTECTED] null if the task name is unknown
+ [EMAIL PROTECTED] 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.
+ * Keep a record of all tasks that have been created so that they can be
+ * invalidated if a taskdef overrides the definition.
+ *
+ [EMAIL PROTECTED] type The feature to be added to the CreatedTask
attribute
+ [EMAIL PROTECTED] task The feature to be added to the CreatedTask
attribute
*/
private void addCreatedTask(String type, Task task) {
synchronized (createdTasks) {
@@ -837,9 +1168,12 @@
}
}
+
/**
- * 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.
+ *
+ [EMAIL PROTECTED] type Description of the Parameter
*/
private void invalidateCreatedTasks(String type) {
synchronized (createdTasks) {
@@ -856,88 +1190,63 @@
}
}
+
/**
- * 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
+ *
+ [EMAIL PROTECTED] typeName name of the datatype
+ [EMAIL PROTECTED] null if the datatype name is unknown
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] targetNames Description of the Parameter
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] line Description of the Parameter
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] targetName the target to execute
+ [EMAIL PROTECTED] BuildException if the build failed
*/
public void executeTarget(String targetName) throws BuildException {
@@ -965,37 +1274,47 @@
} 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. <p>
*
- * <p>If fileName is a relative file name, resolve it relative to
- * rootDir.</p>
+ * If fileName is a relative file name, resolve it relative to
rootDir.</p>
*
- * @deprecated
+ [EMAIL PROTECTED] fileName Description of the Parameter
+ [EMAIL PROTECTED] rootDir Description of the Parameter
+ [EMAIL PROTECTED] Description of the Return Value
+ [EMAIL PROTECTED]
*/
public File resolveFile(String fileName, File rootDir) {
return fileUtils.resolveFile(rootDir, fileName);
}
+
+ /**
+ * Description of the Method
+ *
+ [EMAIL PROTECTED] fileName Description of the Parameter
+ [EMAIL PROTECTED] Description of the Return Value
+ */
public File resolveFile(String fileName) {
return fileUtils.resolveFile(baseDir, fileName);
}
+
/**
- * Translate a path into its native (platform specific) format.
- * <p>
- * This method uses the PathTokenizer class to separate the input path
- * into its components. This handles DOS style paths in a relatively
- * sensible way. The file separators are then converted to their platform
- * specific versions.
- *
- * @param to_process the path to be converted
+ * Translate a path into its native (platform specific) format. <p>
*
- * @return the native version of to_process or
- * an empty string if to_process is null or empty
+ * 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.
+ *
+ [EMAIL PROTECTED] to_process the path to be converted
+ [EMAIL PROTECTED] 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 @@
}
path.append(pathComponent);
}
-
+
return path.toString();
}
+
/**
- * 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
+ [EMAIL PROTECTED] sourceFile Description of the Parameter
+ [EMAIL PROTECTED] destFile Description of the Parameter
+ [EMAIL PROTECTED] IOException
+ [EMAIL PROTECTED]
*/
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.
- *
- * @throws IOException
+ * Convienence method to copy a file from a source to a destination
+ * specifying if token filtering must be used.
*
- * @deprecated
+ [EMAIL PROTECTED] sourceFile Description of the Parameter
+ [EMAIL PROTECTED] destFile Description of the Parameter
+ [EMAIL PROTECTED] filtering Description of the Parameter
+ [EMAIL PROTECTED] IOException
+ [EMAIL PROTECTED]
*/
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
- *
- * @deprecated
+ * 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.
+ *
+ [EMAIL PROTECTED] sourceFile Description of the Parameter
+ [EMAIL PROTECTED] destFile Description of the Parameter
+ [EMAIL PROTECTED] filtering Description of the Parameter
+ [EMAIL PROTECTED] overwrite Description of the Parameter
+ [EMAIL PROTECTED] IOException
+ [EMAIL PROTECTED]
*/
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 <code>destFile</code> file should be made equal
- * to the last modified time of <code>sourceFile</code>.
- *
- * @throws IOException
- *
- * @deprecated
+
+ /**
+ * 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
<code>destFile</code>
+ * file should be made equal to the last modified time of
<code>sourceFile</code>
+ * .
+ *
+ [EMAIL PROTECTED] sourceFile Description of the Parameter
+ [EMAIL PROTECTED] destFile Description of the Parameter
+ [EMAIL PROTECTED] filtering Description of the Parameter
+ [EMAIL PROTECTED] overwrite Description of the Parameter
+ [EMAIL PROTECTED] preserveLastModified Description of the Parameter
+ [EMAIL PROTECTED] IOException
+ [EMAIL PROTECTED]
*/
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.
+ * Convienence method to copy a file from a source to a destination. No
+ * filtering is performed.
*
- * @throws IOException
- *
- * @deprecated
+ [EMAIL PROTECTED] sourceFile Description of the Parameter
+ [EMAIL PROTECTED] destFile Description of the Parameter
+ [EMAIL PROTECTED] IOException
+ [EMAIL PROTECTED]
*/
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.
- *
- * @throws IOException
+ * Convienence method to copy a file from a source to a destination
+ * specifying if token filtering must be used.
*
- * @deprecated
+ [EMAIL PROTECTED] sourceFile Description of the Parameter
+ [EMAIL PROTECTED] destFile Description of the Parameter
+ [EMAIL PROTECTED] filtering Description of the Parameter
+ [EMAIL PROTECTED] IOException
+ [EMAIL PROTECTED]
*/
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
- *
- * @deprecated
+ * 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.
+ *
+ [EMAIL PROTECTED] sourceFile Description of the Parameter
+ [EMAIL PROTECTED] destFile Description of the Parameter
+ [EMAIL PROTECTED] filtering Description of the Parameter
+ [EMAIL PROTECTED] overwrite Description of the Parameter
+ [EMAIL PROTECTED] IOException
+ [EMAIL PROTECTED]
*/
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 <code>destFile</code> file should be made equal
- * to the last modified time of <code>sourceFile</code>.
- *
- * @throws IOException
- *
- * @deprecated
+ * 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
<code>destFile</code>
+ * file should be made equal to the last modified time of
<code>sourceFile</code>
+ * .
+ *
+ [EMAIL PROTECTED] sourceFile Description of the Parameter
+ [EMAIL PROTECTED] destFile Description of the Parameter
+ [EMAIL PROTECTED] filtering Description of the Parameter
+ [EMAIL PROTECTED] overwrite Description of the Parameter
+ [EMAIL PROTECTED] preserveLastModified Description of the Parameter
+ [EMAIL PROTECTED] IOException
+ [EMAIL PROTECTED]
*/
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
+ [EMAIL PROTECTED] file The new fileLastModified value
+ [EMAIL PROTECTED] time The new fileLastModified value
+ [EMAIL PROTECTED] BuildException Description of the Exception
+ [EMAIL PROTECTED]
*/
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.
+ *
+ [EMAIL PROTECTED] s Description of the Parameter
+ [EMAIL PROTECTED] Description of the Return Value
*/
public static boolean toBoolean(String s) {
return (s.equalsIgnoreCase("on") ||
@@ -1153,19 +1508,22 @@
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.
+ *
+ [EMAIL PROTECTED] 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.
+ [EMAIL PROTECTED] targets is a Hashtable representing a
"name to Target"
+ * mapping
+ [EMAIL PROTECTED] a Vector of Strings with the
names of the
+ * targets in sorted order.
+ [EMAIL PROTECTED] 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 @@
// 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 @@
// "ret" now contains the sorted sequence of Targets upto the current
// Target.
+ /**
+ * Description of the Method
+ *
+ [EMAIL PROTECTED] root Description of the Parameter
+ [EMAIL PROTECTED] targets Description of the Parameter
+ [EMAIL PROTECTED] state Description of the Parameter
+ [EMAIL PROTECTED] visiting Description of the Parameter
+ [EMAIL PROTECTED] ret Description of the Parameter
+ [EMAIL PROTECTED] 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 @@
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 @@
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 @@
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
+ *
+ [EMAIL PROTECTED] end Description of the Parameter
+ [EMAIL PROTECTED] stk Description of the Parameter
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] name The feature to be added to the Reference
attribute
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] The references value
+ */
public Hashtable getReferences() {
return references;
}
+
/**
- * @return The object with the "id" key.
+ [EMAIL PROTECTED] key Description of the Parameter
+ [EMAIL PROTECTED] 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 @@
}
}
+
/**
- * send build finished event to the listeners
- * @param exception exception which indicates failure if not null
+ * send build finished event to the listeners
+ *
+ [EMAIL PROTECTED] exception exception which indicates failure if not
null
*/
protected void fireBuildFinished(Throwable exception) {
BuildEvent event = new BuildEvent(this);
@@ -1313,9 +1709,11 @@
}
}
-
+
/**
- * send target started event to the listeners
+ * send target started event to the listeners
+ *
+ [EMAIL PROTECTED] target Description of the Parameter
*/
protected void fireTargetStarted(Target target) {
BuildEvent event = new BuildEvent(target);
@@ -1325,9 +1723,12 @@
}
}
+
/**
- * send build finished event to the listeners
- * @param exception exception which indicates failure if not null
+ * send build finished event to the listeners
+ *
+ [EMAIL PROTECTED] exception exception which indicates failure if not
null
+ [EMAIL PROTECTED] target Description of the Parameter
*/
protected void fireTargetFinished(Target target, Throwable exception) {
BuildEvent event = new BuildEvent(target);
@@ -1338,6 +1739,12 @@
}
}
+
+ /**
+ * Description of the Method
+ *
+ [EMAIL PROTECTED] 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 @@
}
}
+
+ /**
+ * Description of the Method
+ *
+ [EMAIL PROTECTED] task Description of the Parameter
+ [EMAIL PROTECTED] exception Description of the Parameter
+ */
protected void fireTaskFinished(Task task, Throwable exception) {
threadTasks.remove(Thread.currentThread());
System.out.flush();
@@ -1360,6 +1774,14 @@
}
}
+
+ /**
+ * Description of the Method
+ *
+ [EMAIL PROTECTED] event Description of the Parameter
+ [EMAIL PROTECTED] message Description of the Parameter
+ [EMAIL PROTECTED] 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 @@
}
}
+
+ /**
+ * Description of the Method
+ *
+ [EMAIL PROTECTED] project Description of the Parameter
+ [EMAIL PROTECTED] message Description of the Parameter
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] target Description of the Parameter
+ [EMAIL PROTECTED] message Description of the Parameter
+ [EMAIL PROTECTED] 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
+ *
+ [EMAIL PROTECTED] task Description of the Parameter
+ [EMAIL PROTECTED] message Description of the Parameter
+ [EMAIL PROTECTED] priority Description of the Parameter
+ */
protected void fireMessageLogged(Task task, String message, int
priority) {
BuildEvent event = new BuildEvent(task);
fireMessageLoggedEvent(event, message, priority);
}
+
}
1.2 +833 -797
jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/ProjectHelper.java
Index: ProjectHelper.java
===================================================================
RCS file:
/home/cvs/jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/ProjectHelper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ProjectHelper.java 18 Feb 2002 08:55:16 -0000 1.1
+++ ProjectHelper.java 3 Mar 2002 12:37:13 -0000 1.2
@@ -1,797 +1,833 @@
-/*
- * The Apache Software License, Version 1.1
- *
- * 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:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- * any, must include the following acknowlegement:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowlegement may appear in the software itself,
- * if and wherever such third-party acknowlegements normally appear.
- *
- * 4. The names "The Jakarta Project", "Ant", and "Apache Software
- * Foundation" must not be used to endorse or promote products derived
- * from this software without prior written permission. For written
- * permission, please contact [EMAIL PROTECTED]
- *
- * 5. Products derived from this software may not be called "Apache"
- * nor may "Apache" appear in their names without prior written
- * permission of the Apache Group.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-package org.apache.tools.ant;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.Vector;
-import java.util.Enumeration;
-import java.util.Locale;
-import org.xml.sax.Locator;
-import org.xml.sax.InputSource;
-import org.xml.sax.HandlerBase;
-import org.xml.sax.SAXParseException;
-import org.xml.sax.SAXException;
-import org.xml.sax.DocumentHandler;
-import org.xml.sax.AttributeList;
-
-
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.ParserConfigurationException;
-
-/**
- * Configures a Project (complete with Targets and Tasks) based on
- * a XML build file.
- *
- * @author [EMAIL PROTECTED]
- */
-
-public class ProjectHelper {
-
- private static SAXParserFactory parserFactory = null;
-
- private org.xml.sax.Parser parser;
- private Project project;
- private File buildFile;
- private File buildFileParent;
- private Locator locator;
-
- /**
- * Configures the Project with the contents of the specified XML file.
- */
- public static void configureProject(Project project, File buildFile)
throws BuildException {
- new ProjectHelper(project, buildFile).parse();
- }
-
- /**
- * Constructs a new Ant parser for the specified XML file.
- */
- private ProjectHelper(Project project, File buildFile) {
- this.project = project;
- this.buildFile = new File(buildFile.getAbsolutePath());
- buildFileParent = new File(this.buildFile.getParent());
- }
-
- /**
- * Parses the project file.
- */
- private void parse() throws BuildException {
- FileInputStream inputStream = null;
- InputSource inputSource = null;
-
- try {
- SAXParser saxParser = getParserFactory().newSAXParser();
- parser = saxParser.getParser();
-
- String uri = "file:" + buildFile.getAbsolutePath().replace('\\',
'/');
- 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);
- project.log("parsing buildfile " + buildFile + " with URI = " +
uri, Project.MSG_VERBOSE);
- saxParser.parse(inputSource, new RootHandler());
- }
- catch(ParserConfigurationException exc) {
- throw new BuildException("Parser has not been configured
correctly", exc);
- }
- catch(SAXParseException exc) {
- Location location =
- new Location(buildFile.toString(), exc.getLineNumber(),
exc.getColumnNumber());
-
- Throwable t = exc.getException();
- if (t instanceof BuildException) {
- BuildException be = (BuildException) t;
- if (be.getLocation() == Location.UNKNOWN_LOCATION) {
- be.setLocation(location);
- }
- throw be;
- }
-
- throw new BuildException(exc.getMessage(), t, location);
- }
- catch(SAXException exc) {
- Throwable t = exc.getException();
- if (t instanceof BuildException) {
- throw (BuildException) t;
- }
- throw new BuildException(exc.getMessage(), t);
- }
- catch(FileNotFoundException exc) {
- throw new BuildException(exc);
- }
- catch(IOException exc) {
- throw new BuildException("Error reading project file", exc);
- }
- finally {
- if (inputStream != null) {
- try {
- inputStream.close();
- }
- catch (IOException ioe) {
- // ignore this
- }
- }
- }
- }
-
- /**
- * The common superclass for all sax event handlers in Ant. Basically
- * throws an exception in each method, so subclasses should override
- * what they can handle.
- *
- * Each type of xml element (task, target, etc) in ant will
- * have its own subclass of AbstractHandler.
- *
- * In the constructor, this class takes over the handling of sax
- * events from the parent handler, and returns
- * control back to the parent in the endElement method.
- */
- private class AbstractHandler extends HandlerBase {
- protected DocumentHandler parentHandler;
-
- public AbstractHandler(DocumentHandler parentHandler) {
- this.parentHandler = parentHandler;
-
- // Start handling SAX events
- parser.setDocumentHandler(this);
- }
-
- public void startElement(String tag, AttributeList attrs) throws
SAXParseException {
- throw new SAXParseException("Unexpected element \"" + tag +
"\"", locator);
- }
-
- public void characters(char[] buf, int start, int end) throws
SAXParseException {
- String s = new String(buf, start, end).trim();
-
- if (s.length() > 0) {
- throw new SAXParseException("Unexpected text \"" + s + "\"",
locator);
- }
- }
-
- /**
- * Called when this element and all elements nested into it have been
- * handled.
- */
- protected void finished() {}
-
- public void endElement(String name) throws SAXException {
-
- finished();
- // Let parent resume handling SAX events
- parser.setDocumentHandler(parentHandler);
- }
- }
-
- /**
- * Handler for the root element. It's only child must be the "project"
element.
- */
- private class RootHandler extends HandlerBase {
-
- /**
- * resolve file: URIs as relative to the build file.
- */
- 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 #
- while (index != -1) {
- path = path.substring(0, index) + "#" +
path.substring(index + 3);
- index = path.indexOf("%23");
- }
-
- File file = new File(path);
- 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.MSG_WARN);
- }
- }
- // use default if not file or file not found
- return null;
- }
-
- public void startElement(String tag, AttributeList attrs) throws
SAXParseException {
- if (tag.equals("project")) {
- new ProjectHandler(this).init(tag, attrs);
- } else {
- throw new SAXParseException("Config file is not of expected
XML type", locator);
- }
- }
-
- public void setDocumentLocator(Locator locator) {
- ProjectHelper.this.locator = locator;
- }
- }
-
- /**
- * Handler for the top level "project" element.
- */
- private class ProjectHandler extends AbstractHandler {
- public ProjectHandler(DocumentHandler parentHandler) {
- super(parentHandler);
- }
-
- public void init(String tag, AttributeList attrs) throws
SAXParseException {
- String def = null;
- String name = null;
- String id = null;
- String baseDir = null;
-
- for (int i = 0; i < attrs.getLength(); i++) {
- String key = attrs.getName(i);
- String value = attrs.getValue(i);
-
- if (key.equals("default")) {
- def = value;
- } else if (key.equals("name")) {
- name = value;
- } else if (key.equals("id")) {
- id = value;
- } else if (key.equals("basedir")) {
- baseDir = value;
- } else {
- throw new SAXParseException("Unexpected attribute \"" +
attrs.getName(i) + "\"", locator);
- }
- }
-
- if (def == null) {
- throw new SAXParseException("The default attribute of
project is required",
- locator);
- }
-
-
- project.setDefaultTarget(def);
-
- if (name != null) {
- project.setName(name);
- project.addReference(name, project);
- }
-
- if (id != null) {
- project.addReference(id, project);
- }
-
- if (project.getProperty("basedir") != null) {
- project.setBasedir(project.getProperty("basedir"));
- } else {
- if (baseDir == null) {
- project.setBasedir(buildFileParent.getAbsolutePath());
- } else {
- // check whether the user has specified an absolute path
- if ((new File(baseDir)).isAbsolute()) {
- project.setBasedir(baseDir);
- } else {
- project.setBaseDir(project.resolveFile(baseDir,
buildFileParent));
- }
- }
- }
-
- }
-
- public void startElement(String name, AttributeList attrs) throws
SAXParseException {
- if (name.equals("taskdef")) {
- handleTopTask(name, attrs);
- } else if (name.equals("typedef")) {
- handleTopTask(name, attrs);
- } else if (name.equals("antlib")) {
- handleTopTask(name, attrs);
- } else if (name.equals("property")) {
- handleTopTask(name, attrs);
- } else if (name.equals("target")) {
- handleTarget(name, attrs);
- } else if (project.isDefinedOnRole(Project.DATATYPE_ROLE, name))
{
- handleTopTask(name, attrs);
- } else {
- throw new SAXParseException("Unexpected element \"" + name +
"\"", locator);
- }
- }
-
- private void handleTopTask(String name, AttributeList attrs)
- throws SAXParseException {
- InmediateTarget target = new InmediateTarget(name);
- (new TaskHandler(this, target, null, target)).init(name, attrs);
- }
-
- private void handleTarget(String tag, AttributeList attrs) throws
SAXParseException {
- new TargetHandler(this).init(tag, attrs);
- }
-
- }
-
- /**
- * Handler for "target" elements.
- */
- private class TargetHandler extends AbstractHandler {
- private Target target;
-
- public TargetHandler(DocumentHandler parentHandler) {
- super(parentHandler);
- }
-
- public void init(String tag, AttributeList attrs) throws
SAXParseException {
- String name = null;
- String depends = "";
- String ifCond = null;
- String unlessCond = null;
- String id = null;
- String description = null;
-
- for (int i = 0; i < attrs.getLength(); i++) {
- String key = attrs.getName(i);
- String value = attrs.getValue(i);
-
- if (key.equals("name")) {
- name = value;
- } else if (key.equals("depends")) {
- depends = value;
- } else if (key.equals("if")) {
- ifCond = value;
- } else if (key.equals("unless")) {
- unlessCond = value;
- } else if (key.equals("id")) {
- id = value;
- } else if (key.equals("description")) {
- description = value;
- } else {
- throw new SAXParseException("Unexpected attribute \"" +
key + "\"", locator);
- }
- }
-
- if (name == null) {
- throw new SAXParseException("target element appears without
a name attribute", locator);
- }
-
- target = new Target();
- target.setName(name);
- target.setIf(ifCond);
- target.setUnless(unlessCond);
- target.setDescription(description);
- project.addTarget(name, target);
-
- if (id != null && !id.equals("")) {
- project.addReference(id, target);
- }
-
- // take care of dependencies
-
- if (depends.length() > 0) {
- target.setDepends(depends);
- }
- }
-
- public void startElement(String name, AttributeList attrs) throws
SAXParseException {
- new TaskHandler(this, target, null, target).init(name, attrs);
- }
- }
-
- /**
- * Handler for all task elements.
- */
- private class TaskHandler extends AbstractHandler {
- private Target target;
- private TaskContainer container;
- private Task task;
- private RuntimeConfigurable parentWrapper;
- private RuntimeConfigurable wrapper = null;
-
- public TaskHandler(DocumentHandler parentHandler, TaskContainer
container, RuntimeConfigurable parentWrapper, Target target) {
- super(parentHandler);
- this.container = container;
- this.parentWrapper = parentWrapper;
- this.target = target;
- }
-
- public void init(String tag, AttributeList attrs) throws
SAXParseException {
- try {
- task = (Task)project.createInRole(container, tag);
- } catch (BuildException e) {
- // swallow here, will be thrown again in
- // UnknownElement.maybeConfigure if the problem persists.
- }
-
- if (task == null) {
- task = new UnknownElement(tag);
- task.setProject(project);
- task.setTaskType(tag);
- task.setTaskName(tag);
- container.addTask(task);
- }
-
- 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);
- }
- }
-
- protected void finished() {
- if (container instanceof InmediateTarget) {
- ((InmediateTarget)container).execute();
- }
- }
-
- public void characters(char[] buf, int start, int end) throws
SAXParseException {
- if (wrapper == null) {
- try {
- addText(project, task, buf, start, end);
- } catch (BuildException exc) {
- throw new SAXParseException(exc.getMessage(), locator,
exc);
- }
- } else {
- wrapper.addText(buf, start, end);
- }
- }
-
- public void startElement(String name, AttributeList attrs) throws
SAXParseException {
- if (task instanceof TaskContainer) {
- // task can contain other tasks - no other nested elements
possible
- new TaskHandler(this, (TaskContainer)task, wrapper,
target).init(name, attrs);
- }
- else {
- new NestedElementHandler(this, task, wrapper,
target).init(name, attrs);
- }
- }
- }
-
- /**
- * Handler for all nested properties.
- */
- private class NestedElementHandler extends AbstractHandler {
- private Object parent;
- private Object child;
- private RuntimeConfigurable parentWrapper;
- private RuntimeConfigurable childWrapper = null;
- private Target target;
-
- public NestedElementHandler(DocumentHandler parentHandler,
- Object parent,
- RuntimeConfigurable parentWrapper,
- Target target) {
- super(parentHandler);
-
- if (parent instanceof RoleAdapter) {
- this.parent = ((RoleAdapter) parent).getProxy();
- } else {
- this.parent = parent;
- }
- this.parentWrapper = parentWrapper;
- this.target = target;
- }
-
- public void init(String propType, AttributeList attrs) throws
SAXParseException {
- Class parentClass = parent.getClass();
- IntrospectionHelper ih =
- IntrospectionHelper.getHelper(parentClass);
-
- try {
- String elementName = propType.toLowerCase(Locale.US);
- if (parent instanceof UnknownElement) {
- 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);
- child = uc;
- } else {
- child = ih.createElement(project, parent, elementName);
- }
-
- configureId(child, attrs);
-
- if (parentWrapper != null) {
- childWrapper = new RuntimeConfigurable(child, propType);
- childWrapper.setAttributes(attrs);
- parentWrapper.addChild(childWrapper);
- } else {
- configure(child, attrs, project);
- ih.storeElement(project, parent, child, elementName);
- }
- } catch (BuildException exc) {
- throw new SAXParseException(exc.getMessage(), locator, exc);
- }
- }
-
- public void characters(char[] buf, int start, int end) throws
SAXParseException {
- if (parentWrapper == null) {
- try {
- addText(project, child, buf, start, end);
- } catch (BuildException exc) {
- throw new SAXParseException(exc.getMessage(), locator,
exc);
- }
- } else {
- childWrapper.addText(buf, start, end);
- }
- }
-
- public void startElement(String name, AttributeList attrs) throws
SAXParseException {
- if (child instanceof TaskContainer) {
- // taskcontainer nested element can contain other tasks - no
other
- // nested elements possible
- new TaskHandler(this, (TaskContainer)child, childWrapper,
target).init(name, attrs);
- }
- else {
- new NestedElementHandler(this, child, childWrapper,
target).init(name, attrs);
- }
- }
- }
-
- /**
- * 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);
- }
- }
-
- public static void configure(Object target, AttributeList attrs,
- Project project) throws BuildException {
- if( target instanceof RoleAdapter ) {
- target=((RoleAdapter)target).getProxy();
- }
-
- 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),
- project.getProperties() );
- try {
- ih.setAttribute(project, target,
- attrs.getName(i).toLowerCase(Locale.US),
value);
-
- } catch (BuildException be) {
- // id attribute must be set externally
- if (!attrs.getName(i).equals("id")) {
- throw be;
- }
- }
- }
- }
-
- /**
- * Adds the content of #PCDATA sections to an element.
- */
- public static void addText(Project project, Object target, char[] buf,
int start, int end)
- throws BuildException {
- addText(project, target, new String(buf, start, end));
- }
-
- /**
- * Adds the content of #PCDATA sections to an element.
- */
- public static void addText(Project project, Object target, String text)
- throws BuildException {
-
- if (text == null ) {
- return;
- }
-
- if(target instanceof RoleAdapter) {
- target = ((RoleAdapter) target).getProxy();
- }
-
- IntrospectionHelper.getHelper(target.getClass()).addText(project,
target, text);
- }
-
- /**
- * 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());
- ih.storeElement(project, parent, child, tag);
- }
-
- /**
- * 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.
- * @since 1.5
- */
- public static String replaceProperties(Project project, String value)
- throws BuildException {
- return project.replaceProperties(value);
- }
-
- /**
- * 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.
- */
- public static String replaceProperties(Project project, String value,
Hashtable keys)
- throws BuildException {
- if (value == null) {
- return null;
- }
-
- Vector fragments = new Vector();
- Vector propertyRefs = new Vector();
- parsePropertyString(value, fragments, propertyRefs);
-
- StringBuffer sb = new StringBuffer();
- Enumeration i = fragments.elements();
- Enumeration j = propertyRefs.elements();
- while (i.hasMoreElements()) {
- String fragment = (String)i.nextElement();
- if (fragment == null) {
- String propertyName = (String)j.nextElement();
- if (!keys.containsKey(propertyName)) {
- project.log("Property ${" + propertyName + "} has not
been set", Project.MSG_VERBOSE);
- }
- fragment = (keys.containsKey(propertyName)) ? (String)
keys.get(propertyName)
- : "${" +
propertyName + "}";
- }
- sb.append(fragment);
- }
-
- return sb.toString();
- }
-
- /**
- * 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)
- throws BuildException {
- int prev = 0;
- int pos;
- while ((pos = value.indexOf("$", prev)) >= 0) {
- if (pos > 0) {
- fragments.addElement(value.substring(prev, pos));
- }
-
- if( pos == (value.length() - 1)) {
- fragments.addElement("$");
- prev = pos + 1;
- }
- else if (value.charAt(pos + 1) != '{' ) {
- fragments.addElement(value.substring(pos + 1, pos + 2));
- prev = pos + 2;
- } else {
- int endName = value.indexOf('}', pos);
- if (endName < 0) {
- throw new BuildException("Syntax error in property: "
- + value );
- }
- String propertyName = value.substring(pos + 2, endName);
- fragments.addElement(null);
- propertyRefs.addElement(propertyName);
- prev = endName + 1;
- }
- }
-
- if (prev < value.length()) {
- fragments.addElement(value.substring(prev));
- }
- }
-
- private static SAXParserFactory getParserFactory() {
- if (parserFactory == null) {
- parserFactory = SAXParserFactory.newInstance();
- }
-
- return parserFactory;
- }
-
- /**
- * Scan AttributeList for the id attribute and maybe add a
- * reference to project.
- *
- * <p>Moved out of [EMAIL PROTECTED] #configure configure} to make it
happen
- * at parser time.</p>
- */
- private void configureId(Object target, AttributeList attr) {
- String id = attr.getValue("id");
- if (id != null) {
- if( target instanceof RoleAdapter ) {
- ((RoleAdapter)target).setId(id);
- }
- project.addReference(id, target);
- }
- }
-
-}
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * 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:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact [EMAIL PROTECTED]
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.tools.ant;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Locale;
+import org.xml.sax.Locator;
+import org.xml.sax.InputSource;
+import org.xml.sax.HandlerBase;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.SAXException;
+import org.xml.sax.DocumentHandler;
+import org.xml.sax.AttributeList;
+
+
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.ParserConfigurationException;
+
+/**
+ * Configures a Project (complete with Targets and Tasks) based on
+ * a XML build file.
+ *
+ * @author [EMAIL PROTECTED]
+ */
+
+public class ProjectHelper {
+
+ private static SAXParserFactory parserFactory = null;
+
+ private org.xml.sax.Parser parser;
+ private Project project;
+ private File buildFile;
+ private File buildFileParent;
+ private Locator locator;
+
+ /**
+ * Configures the Project with the contents of the specified XML file.
+ */
+ public static void configureProject(Project project, File buildFile)
throws BuildException {
+ new ProjectHelper(project, buildFile).parse();
+ }
+
+ /**
+ * Constructs a new Ant parser for the specified XML file.
+ */
+ private ProjectHelper(Project project, File buildFile) {
+ this.project = project;
+ this.buildFile = new File(buildFile.getAbsolutePath());
+ buildFileParent = new File(this.buildFile.getParent());
+ }
+
+ /**
+ * Parses the project file.
+ */
+ private void parse() throws BuildException {
+ FileInputStream inputStream = null;
+ InputSource inputSource = null;
+
+ try {
+ SAXParser saxParser = getParserFactory().newSAXParser();
+ parser = saxParser.getParser();
+
+ String uri = "file:" + buildFile.getAbsolutePath().replace('\\',
'/');
+ 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);
+ project.log("parsing buildfile " + buildFile + " with URI = " +
uri, Project.MSG_VERBOSE);
+ saxParser.parse(inputSource, new RootHandler());
+ }
+ catch(ParserConfigurationException exc) {
+ throw new BuildException("Parser has not been configured
correctly", exc);
+ }
+ catch(SAXParseException exc) {
+ Location location =
+ new Location(buildFile.toString(), exc.getLineNumber(),
exc.getColumnNumber());
+
+ Throwable t = exc.getException();
+ if (t instanceof BuildException) {
+ BuildException be = (BuildException) t;
+ if (be.getLocation() == Location.UNKNOWN_LOCATION) {
+ be.setLocation(location);
+ }
+ throw be;
+ }
+
+ throw new BuildException(exc.getMessage(), t, location);
+ }
+ catch(SAXException exc) {
+ Throwable t = exc.getException();
+ if (t instanceof BuildException) {
+ throw (BuildException) t;
+ }
+ throw new BuildException(exc.getMessage(), t);
+ }
+ catch(FileNotFoundException exc) {
+ throw new BuildException(exc);
+ }
+ catch(IOException exc) {
+ throw new BuildException("Error reading project file", exc);
+ }
+ finally {
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ }
+ catch (IOException ioe) {
+ // ignore this
+ }
+ }
+ }
+ }
+
+ /**
+ * The common superclass for all sax event handlers in Ant. Basically
+ * throws an exception in each method, so subclasses should override
+ * what they can handle.
+ *
+ * Each type of xml element (task, target, etc) in ant will
+ * have its own subclass of AbstractHandler.
+ *
+ * In the constructor, this class takes over the handling of sax
+ * events from the parent handler, and returns
+ * control back to the parent in the endElement method.
+ */
+ private class AbstractHandler extends HandlerBase {
+ protected DocumentHandler parentHandler;
+
+ public AbstractHandler(DocumentHandler parentHandler) {
+ this.parentHandler = parentHandler;
+
+ // Start handling SAX events
+ parser.setDocumentHandler(this);
+ }
+
+ public void startElement(String tag, AttributeList attrs) throws
SAXParseException {
+ throw new SAXParseException("Unexpected element \"" + tag +
"\"", locator);
+ }
+
+ public void characters(char[] buf, int start, int end) throws
SAXParseException {
+ String s = new String(buf, start, end).trim();
+
+ if (s.length() > 0) {
+ throw new SAXParseException("Unexpected text \"" + s + "\"",
locator);
+ }
+ }
+
+ /**
+ * Called when this element and all elements nested into it have been
+ * handled.
+ */
+ protected void finished() {}
+
+ public void endElement(String name) throws SAXException {
+
+ finished();
+ // Let parent resume handling SAX events
+ parser.setDocumentHandler(parentHandler);
+ }
+ }
+
+ /**
+ * Handler for the root element. It's only child must be the "project"
element.
+ */
+ private class RootHandler extends HandlerBase {
+
+ /**
+ * resolve file: URIs as relative to the build file.
+ */
+ 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 #
+ while (index != -1) {
+ path = path.substring(0, index) + "#" +
path.substring(index + 3);
+ index = path.indexOf("%23");
+ }
+
+ File file = new File(path);
+ 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.MSG_WARN);
+ }
+ }
+ // use default if not file or file not found
+ return null;
+ }
+
+ public void startElement(String tag, AttributeList attrs) throws
SAXParseException {
+ if (tag.equals("project")) {
+ new ProjectHandler(this).init(tag, attrs);
+ } else {
+ throw new SAXParseException("Config file is not of expected
XML type", locator);
+ }
+ }
+
+ public void setDocumentLocator(Locator locator) {
+ ProjectHelper.this.locator = locator;
+ }
+ }
+
+ /**
+ * Handler for the top level "project" element.
+ */
+ private class ProjectHandler extends AbstractHandler {
+ public ProjectHandler(DocumentHandler parentHandler) {
+ super(parentHandler);
+ }
+
+ public void init(String tag, AttributeList attrs) throws
SAXParseException {
+ String def = null;
+ String name = null;
+ String id = null;
+ String baseDir = null;
+
+ for (int i = 0; i < attrs.getLength(); i++) {
+ String key = attrs.getName(i);
+ String value = attrs.getValue(i);
+
+ if (key.equals("default")) {
+ def = value;
+ } else if (key.equals("name")) {
+ name = value;
+ } else if (key.equals("id")) {
+ id = value;
+ } else if (key.equals("basedir")) {
+ baseDir = value;
+ } else {
+ throw new SAXParseException("Unexpected attribute \"" +
attrs.getName(i) + "\"", locator);
+ }
+ }
+
+ if (def == null) {
+ throw new SAXParseException("The default attribute of
project is required",
+ locator);
+ }
+
+
+ project.setDefaultTarget(def);
+
+ if (name != null) {
+ project.setName(name);
+ project.addReference(name, project);
+ }
+
+ if (id != null) {
+ project.addReference(id, project);
+ }
+
+ if (project.getProperty("basedir") != null) {
+ project.setBasedir(project.getProperty("basedir"));
+ } else {
+ if (baseDir == null) {
+ project.setBasedir(buildFileParent.getAbsolutePath());
+ } else {
+ // check whether the user has specified an absolute path
+ if ((new File(baseDir)).isAbsolute()) {
+ project.setBasedir(baseDir);
+ } else {
+ project.setBaseDir(project.resolveFile(baseDir,
buildFileParent));
+ }
+ }
+ }
+
+ }
+
+ public void startElement(String name, AttributeList attrs) throws
SAXParseException {
+ if (name.equals("taskdef")) {
+ handleTopTask(name, attrs);
+ } else if (name.equals("typedef")) {
+ handleTopTask(name, attrs);
+ } else if (name.equals("antlib")) {
+ handleTopTask(name, attrs);
+ } else if (name.equals("property")) {
+ 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 {
+ throw new SAXParseException("Unexpected element \"" + name +
"\"", locator);
+ }
+ }
+
+ private void handleTopTask(String name, AttributeList attrs)
+ throws SAXParseException {
+ InmediateTarget target = new InmediateTarget(name);
+ (new TaskHandler(this, target, null, target)).init(name, attrs);
+ }
+
+ private void handleTarget(String tag, AttributeList attrs) throws
SAXParseException {
+ new TargetHandler(this).init(tag, attrs);
+ }
+
+ private void handleDescription(String tag, AttributeList attrs)
throws SAXParseException {
+ new DescriptionHandler(this).init(tag, attrs);
+ }
+
+ }
+
+ /**
+ * Handler for "target" elements.
+ */
+ private class TargetHandler extends AbstractHandler {
+ private Target target;
+
+ public TargetHandler(DocumentHandler parentHandler) {
+ super(parentHandler);
+ }
+
+ public void init(String tag, AttributeList attrs) throws
SAXParseException {
+ String name = null;
+ String depends = "";
+ String ifCond = null;
+ String unlessCond = null;
+ String id = null;
+ String description = null;
+
+ for (int i = 0; i < attrs.getLength(); i++) {
+ String key = attrs.getName(i);
+ String value = attrs.getValue(i);
+
+ if (key.equals("name")) {
+ name = value;
+ } else if (key.equals("depends")) {
+ depends = value;
+ } else if (key.equals("if")) {
+ ifCond = value;
+ } else if (key.equals("unless")) {
+ unlessCond = value;
+ } else if (key.equals("id")) {
+ id = value;
+ } else if (key.equals("description")) {
+ description = value;
+ } else {
+ throw new SAXParseException("Unexpected attribute \"" +
key + "\"", locator);
+ }
+ }
+
+ if (name == null) {
+ throw new SAXParseException("target element appears without
a name attribute", locator);
+ }
+
+ target = new Target();
+ target.setName(name);
+ target.setIf(ifCond);
+ target.setUnless(unlessCond);
+ target.setDescription(description);
+ project.addTarget(name, target);
+
+ if (id != null && !id.equals("")) {
+ project.addReference(id, target);
+ }
+
+ // take care of dependencies
+
+ if (depends.length() > 0) {
+ target.setDepends(depends);
+ }
+ }
+
+ public void startElement(String name, AttributeList attrs) throws
SAXParseException {
+ if (name.equals("description")) {
+ new DescriptionHandler(this).init(name, attrs);
+ }
+ else {
+ new TaskHandler(this, target, null, target).init(name,
attrs);
+ }
+ }
+ }
+
+ /**
+ * Handler for all task elements.
+ */
+ private class TaskHandler extends AbstractHandler {
+ private Target target;
+ private TaskContainer container;
+ private Task task;
+ private RuntimeConfigurable parentWrapper;
+ private RuntimeConfigurable wrapper = null;
+
+ public TaskHandler(DocumentHandler parentHandler, TaskContainer
container, RuntimeConfigurable parentWrapper, Target target) {
+ super(parentHandler);
+ this.container = container;
+ this.parentWrapper = parentWrapper;
+ this.target = target;
+ }
+
+ public void init(String tag, AttributeList attrs) throws
SAXParseException {
+ try {
+ task = (Task)project.createInRole(container, tag);
+ } catch (BuildException e) {
+ // swallow here, will be thrown again in
+ // UnknownElement.maybeConfigure if the problem persists.
+ }
+
+ if (task == null) {
+ task = new UnknownElement(tag);
+ task.setProject(project);
+ task.setTaskType(tag);
+ task.setTaskName(tag);
+ container.addTask(task);
+ }
+
+ 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);
+ }
+ }
+
+ protected void finished() {
+ if (container instanceof InmediateTarget) {
+ ((InmediateTarget)container).execute();
+ }
+ }
+
+ public void characters(char[] buf, int start, int end) throws
SAXParseException {
+ if (wrapper == null) {
+ try {
+ addText(project, task, buf, start, end);
+ } catch (BuildException exc) {
+ throw new SAXParseException(exc.getMessage(), locator,
exc);
+ }
+ } else {
+ wrapper.addText(buf, start, end);
+ }
+ }
+
+ public void startElement(String name, AttributeList attrs) throws
SAXParseException {
+ if (task instanceof TaskContainer) {
+ // task can contain other tasks - no other nested elements
possible
+ new TaskHandler(this, (TaskContainer)task, wrapper,
target).init(name, attrs);
+ }
+ else {
+ new NestedElementHandler(this, task, wrapper,
target).init(name, attrs);
+ }
+ }
+ }
+
+ /**
+ * Handler for all nested properties.
+ */
+ private class NestedElementHandler extends AbstractHandler {
+ private Object parent;
+ private Object child;
+ private RuntimeConfigurable parentWrapper;
+ private RuntimeConfigurable childWrapper = null;
+ private Target target;
+
+ public NestedElementHandler(DocumentHandler parentHandler,
+ Object parent,
+ RuntimeConfigurable parentWrapper,
+ Target target) {
+ super(parentHandler);
+
+ if (parent instanceof RoleAdapter) {
+ this.parent = ((RoleAdapter) parent).getProxy();
+ } else {
+ this.parent = parent;
+ }
+ this.parentWrapper = parentWrapper;
+ this.target = target;
+ }
+
+ public void init(String propType, AttributeList attrs) throws
SAXParseException {
+ Class parentClass = parent.getClass();
+ IntrospectionHelper ih =
+ IntrospectionHelper.getHelper(parentClass);
+
+ try {
+ String elementName = propType.toLowerCase(Locale.US);
+ if (parent instanceof UnknownElement) {
+ 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);
+ child = uc;
+ } else {
+ child = ih.createElement(project, parent, elementName);
+ }
+
+ configureId(child, attrs);
+
+ if (parentWrapper != null) {
+ childWrapper = new RuntimeConfigurable(child, propType);
+ childWrapper.setAttributes(attrs);
+ parentWrapper.addChild(childWrapper);
+ } else {
+ configure(child, attrs, project);
+ ih.storeElement(project, parent, child, elementName);
+ }
+ } catch (BuildException exc) {
+ throw new SAXParseException(exc.getMessage(), locator, exc);
+ }
+ }
+
+ public void characters(char[] buf, int start, int end) throws
SAXParseException {
+ if (parentWrapper == null) {
+ try {
+ addText(project, child, buf, start, end);
+ } catch (BuildException exc) {
+ throw new SAXParseException(exc.getMessage(), locator,
exc);
+ }
+ } else {
+ childWrapper.addText(buf, start, end);
+ }
+ }
+
+ public void startElement(String name, AttributeList attrs) throws
SAXParseException {
+ if (child instanceof TaskContainer) {
+ // taskcontainer nested element can contain other tasks - no
other
+ // nested elements possible
+ new TaskHandler(this, (TaskContainer)child, childWrapper,
target).init(name, attrs);
+ }
+ else {
+ new NestedElementHandler(this, child, childWrapper,
target).init(name, attrs);
+ }
+ }
+ }
+
+ /**
+ * Handler to perform appropriate semantics for the special
+ * <description> 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);
+ }
+ }
+
+ public static void configure(Object target, AttributeList attrs,
+ Project project) throws BuildException {
+ if( target instanceof RoleAdapter ) {
+ target=((RoleAdapter)target).getProxy();
+ }
+
+ 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),
+ project.getProperties() );
+ try {
+ ih.setAttribute(project, target,
+ attrs.getName(i).toLowerCase(Locale.US),
value);
+
+ } catch (BuildException be) {
+ // id attribute must be set externally
+ if (!attrs.getName(i).equals("id")) {
+ throw be;
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds the content of #PCDATA sections to an element.
+ */
+ public static void addText(Project project, Object target, char[] buf,
int start, int end)
+ throws BuildException {
+ addText(project, target, new String(buf, start, end));
+ }
+
+ /**
+ * Adds the content of #PCDATA sections to an element.
+ */
+ public static void addText(Project project, Object target, String text)
+ throws BuildException {
+
+ if (text == null ) {
+ return;
+ }
+
+ if(target instanceof RoleAdapter) {
+ target = ((RoleAdapter) target).getProxy();
+ }
+
+ IntrospectionHelper.getHelper(target.getClass()).addText(project,
target, text);
+ }
+
+ /**
+ * 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());
+ ih.storeElement(project, parent, child, tag);
+ }
+
+ /**
+ * 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.
+ * @since 1.5
+ */
+ public static String replaceProperties(Project project, String value)
+ throws BuildException {
+ return project.replaceProperties(value);
+ }
+
+ /**
+ * 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.
+ */
+ public static String replaceProperties(Project project, String value,
Hashtable keys)
+ throws BuildException {
+ if (value == null) {
+ return null;
+ }
+
+ Vector fragments = new Vector();
+ Vector propertyRefs = new Vector();
+ parsePropertyString(value, fragments, propertyRefs);
+
+ StringBuffer sb = new StringBuffer();
+ Enumeration i = fragments.elements();
+ Enumeration j = propertyRefs.elements();
+ while (i.hasMoreElements()) {
+ String fragment = (String)i.nextElement();
+ if (fragment == null) {
+ String propertyName = (String)j.nextElement();
+ if (!keys.containsKey(propertyName)) {
+ project.log("Property ${" + propertyName + "} has not
been set", Project.MSG_VERBOSE);
+ }
+ fragment = (keys.containsKey(propertyName)) ? (String)
keys.get(propertyName)
+ : "${" +
propertyName + "}";
+ }
+ sb.append(fragment);
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * 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)
+ throws BuildException {
+ int prev = 0;
+ int pos;
+ while ((pos = value.indexOf("$", prev)) >= 0) {
+ if (pos > 0) {
+ fragments.addElement(value.substring(prev, pos));
+ }
+
+ if( pos == (value.length() - 1)) {
+ fragments.addElement("$");
+ prev = pos + 1;
+ }
+ else if (value.charAt(pos + 1) != '{' ) {
+ fragments.addElement(value.substring(pos + 1, pos + 2));
+ prev = pos + 2;
+ } else {
+ int endName = value.indexOf('}', pos);
+ if (endName < 0) {
+ throw new BuildException("Syntax error in property: "
+ + value );
+ }
+ String propertyName = value.substring(pos + 2, endName);
+ fragments.addElement(null);
+ propertyRefs.addElement(propertyName);
+ prev = endName + 1;
+ }
+ }
+
+ if (prev < value.length()) {
+ fragments.addElement(value.substring(prev));
+ }
+ }
+
+ private static SAXParserFactory getParserFactory() {
+ if (parserFactory == null) {
+ parserFactory = SAXParserFactory.newInstance();
+ }
+
+ return parserFactory;
+ }
+
+ /**
+ * Scan AttributeList for the id attribute and maybe add a
+ * reference to project.
+ *
+ * <p>Moved out of [EMAIL PROTECTED] #configure configure} to make it
happen
+ * at parser time.</p>
+ */
+ private void configureId(Object target, AttributeList attr) {
+ String id = attr.getValue("id");
+ if (id != null) {
+ if( target instanceof RoleAdapter ) {
+ ((RoleAdapter)target).setId(id);
+ }
+ project.addReference(id, target);
+ }
+ }
+
+}
1.4 +5 -0
jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/RoleAdapter.java
Index: RoleAdapter.java
===================================================================
RCS file:
/home/cvs/jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/RoleAdapter.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- RoleAdapter.java 2 Mar 2002 22:20:43 -0000 1.3
+++ RoleAdapter.java 3 Mar 2002 12:37:13 -0000 1.4
@@ -56,6 +56,11 @@
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
*/
1.4 +357 -287
jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/SymbolTable.java
Index: SymbolTable.java
===================================================================
RCS file:
/home/cvs/jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/SymbolTable.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- SymbolTable.java 2 Mar 2002 22:20:43 -0000 1.3
+++ SymbolTable.java 3 Mar 2002 12:37:13 -0000 1.4
@@ -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 @@
/** Parent symbol table */
private SymbolTable parentTable;
-
+
/** Project associated with this symbol table */
private Project project;
@@ -82,8 +83,8 @@
/**
* 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 @@
* 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 @@
* @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 @@
* @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 @@
* @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();
+ 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);
+ 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,127 +206,20 @@
* @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.
* @param name the name of the element for this Class
@@ -285,46 +227,53 @@
* @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 @@
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 @@
* @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 @@
* 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);
+ }
+ }
+
}
}
1.4 +22 -14
jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/TaskAdapter.java
Index: TaskAdapter.java
===================================================================
RCS file:
/home/cvs/jakarta-ant/proposal/sandbox/antlib/src/main/org/apache/tools/ant/TaskAdapter.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- TaskAdapter.java 2 Mar 2002 22:20:43 -0000 1.3
+++ TaskAdapter.java 3 Mar 2002 12:37:13 -0000 1.4
@@ -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 [EMAIL PROTECTED]
*
* 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 @@
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 @@
* 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 @@
throw new BuildException(message);
}
}
-
+
/**
* Do the execution.
*/
@@ -122,7 +123,7 @@
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 @@
// 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 @@
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 @@
return this.proxy ;
}
+ public void setId(String id) {}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>