diff --git a/proposal/xdocs/build.xml b/proposal/xdocs/build.xml
index 712a84f3e..42369ee28 100644
--- a/proposal/xdocs/build.xml
+++ b/proposal/xdocs/build.xml
@@ -384,10 +384,14 @@
-
+
+ classname="org.apache.ant.xdoclet.AntDocletTask">
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/proposal/xdocs/lib/xdoclet-apache-module-1.2b3-dev.jar b/proposal/xdocs/lib/xdoclet-apache-module-1.2b3-dev.jar
deleted file mode 100644
index 533af9573..000000000
Binary files a/proposal/xdocs/lib/xdoclet-apache-module-1.2b3-dev.jar and /dev/null differ
diff --git a/proposal/xdocs/metadata/xdoclet.xml b/proposal/xdocs/metadata/xdoclet.xml
new file mode 100644
index 000000000..ccf9389b3
--- /dev/null
+++ b/proposal/xdocs/metadata/xdoclet.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/proposal/xdocs/src/org/apache/tools/ant/xdoclet/AntXDocletTask.java b/proposal/xdocs/src/org/apache/ant/xdoclet/AntDocletTask.java
similarity index 67%
rename from proposal/xdocs/src/org/apache/tools/ant/xdoclet/AntXDocletTask.java
rename to proposal/xdocs/src/org/apache/ant/xdoclet/AntDocletTask.java
index 0186f88b5..c90d8a471 100644
--- a/proposal/xdocs/src/org/apache/tools/ant/xdoclet/AntXDocletTask.java
+++ b/proposal/xdocs/src/org/apache/ant/xdoclet/AntDocletTask.java
@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -51,48 +51,30 @@
* information on the Apache Software Foundation, please see
* .
*/
-package org.apache.tools.ant.xdoclet;
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.types.FileSet;
-import xdoclet.DocletTask;
-import xdoclet.doc.info.InfoSubTask;
-import xdoclet.doc.DocumentDocletTask;
-
-import java.io.File;
-import java.util.Vector;
-
-public class AntXDocletTask extends DocumentDocletTask {
- private Vector _subTasks = new Vector();
-
- public void addTasks(TaskSubTask subtask) {
- _subTasks.add(subtask);
- }
+package org.apache.ant.xdoclet;
- public void addDatatypes(DatatypeSubTask subtask) {
- _subTasks.add(subtask);
- }
+import org.apache.tools.ant.BuildException;
- /**
- * Borrowed a bit from Darrell DeBoer's myrmidon stuff (thanks Darrell!)
- */
- public void execute() throws BuildException {
- // Add the base directories of all the filesets to the sourcepath
- final Vector filesets = getFilesets();
- for (int i = 0; i < filesets.size(); i++) {
- final FileSet fileSet = (FileSet) filesets.elementAt(i);
- final File basedir = fileSet.getDir(project);
- createSourcepath().setLocation(basedir);
- }
+import xdoclet.DocletTask;
- super.execute();
+/**
+ * @created January 5, 2003
+ * @ant.element name="antdoclet" display-name="AntDoclet Task"
+ */
+public class AntDocletTask extends DocletTask
+{
+ public AntDocletTask()
+ {
+ // by default, binary classes do not provide their
+ // methods for performance reasons, but it is needed
+ // here to climb up and find true tasks.
+ System.setProperty("xjavadoc.compiledmethods", "true");
}
- protected Vector getSubTasks() {
- Vector subtasks = super.getSubTasks();
-
- subtasks.addAll(_subTasks);
-
- return subtasks;
+ protected void validateOptions() throws BuildException
+ {
+ super.validateOptions();
+ checkClass("org.apache.tools.ant.IntrospectionHelper");
}
-}
\ No newline at end of file
+}
diff --git a/proposal/xdocs/src/org/apache/ant/xdoclet/AntSubTask.java b/proposal/xdocs/src/org/apache/ant/xdoclet/AntSubTask.java
new file mode 100644
index 000000000..7230ac6e0
--- /dev/null
+++ b/proposal/xdocs/src/org/apache/ant/xdoclet/AntSubTask.java
@@ -0,0 +1,173 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 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 apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.ant.xdoclet;
+
+import java.util.Collection;
+import java.util.Iterator;
+import xjavadoc.XClass;
+import xjavadoc.XJavaDoc;
+import xjavadoc.XMethod;
+
+import xdoclet.TemplateSubTask;
+import xdoclet.XDocletException;
+import xdoclet.util.TypeConversionUtil;
+
+/**
+ * @created January 5, 2003
+ */
+public abstract class AntSubTask extends TemplateSubTask
+{
+
+ /**
+ * Checks many factors to determine if the class is indeed an Ant task or not.
+ *
+ * @param clazz
+ * @return
+ * @exception XDocletException
+ * @todo perhaps make deprecation switch configurable
+ */
+ public final static boolean isAntTask(XClass clazz) throws XDocletException
+ {
+ if (clazz.isAbstract()) {
+ return false;
+ }
+
+ // no inner classes (for now - but is this possible? desired?)
+ if (clazz.isInner()) {
+ return false;
+ }
+
+ String ignoreValue = clazz.getDoc().getTagAttributeValue("ant.task", "ignore");
+ boolean ignore = TypeConversionUtil.stringToBoolean(ignoreValue, false);
+
+ if (ignore) {
+ return false;
+ }
+
+ /*
+ * Tag[] tags = clazz.tags();
+ * for (int i = 0; i < tags.length; i++) {
+ * if ("@deprecated".equals(tags[i].name())) {
+ * return false;
+ * }
+ * }
+ */
+ if (hasExecuteMethod(clazz)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Check for class implementing an execute() method. Recursive calls are made to superclasses.
+ *
+ * @param clazz
+ * @return
+ */
+ private static boolean hasExecuteMethod(XClass clazz)
+ {
+ if (clazz == null) {
+ return false;
+ }
+
+ // It ain't a task if we've climbed back to Task itself.
+ // Also ignore other special Ant classes
+ if ("org.apache.tools.ant.Task".equals(clazz.getQualifiedName()) ||
+ "org.apache.tools.ant.Target".equals(clazz.getQualifiedName()) ||
+ "org.apache.tools.ant.TaskAdapter".equals(clazz.getQualifiedName()) ||
+ "org.apache.tools.ant.UnknownElement".equals(clazz.getQualifiedName())) {
+ return false;
+ }
+
+ // need to check that only runtime exceptions are thrown?
+ Collection methods = clazz.getMethods(true);
+ Iterator iter = methods.iterator();
+
+ while (iter.hasNext()) {
+ XMethod method = (XMethod) iter.next();
+
+ if ("execute".equals(method.getName())) {
+ if (method.getParameters().size() == 0) {
+ if (method.getReturnType().getType().getName().equals("void")) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected void startProcess() throws XDocletException
+ {
+ Collection classes = XJavaDoc.getInstance().getSourceClasses(false, processInnerClasses());
+
+ super.startProcess();
+ }
+
+ /**
+ * Returns true if the class is an Ant task. This causes the task to be processed by the XDoclet template task.
+ *
+ * @param clazz
+ * @return
+ * @exception XDocletException
+ */
+ protected boolean matchesGenerationRules(XClass clazz) throws XDocletException
+ {
+ boolean match = isAntTask(clazz);
+
+ return match;
+ }
+}
diff --git a/proposal/xdocs/src/org/apache/tools/ant/xdoclet/IndexGen.java b/proposal/xdocs/src/org/apache/ant/xdoclet/IndexGen.java
similarity index 99%
rename from proposal/xdocs/src/org/apache/tools/ant/xdoclet/IndexGen.java
rename to proposal/xdocs/src/org/apache/ant/xdoclet/IndexGen.java
index 2b69460fb..a7f6f5962 100644
--- a/proposal/xdocs/src/org/apache/tools/ant/xdoclet/IndexGen.java
+++ b/proposal/xdocs/src/org/apache/ant/xdoclet/IndexGen.java
@@ -52,7 +52,7 @@
* .
*/
-package org.apache.tools.ant.xdoclet;
+package org.apache.ant.xdoclet;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.BuildException;
diff --git a/proposal/xdocs/src/org/apache/tools/ant/xdoclet/DatatypeTagsHandler.java b/proposal/xdocs/src/org/apache/ant/xdoclet/TaskDefPropertiesSubTask.java
similarity index 53%
rename from proposal/xdocs/src/org/apache/tools/ant/xdoclet/DatatypeTagsHandler.java
rename to proposal/xdocs/src/org/apache/ant/xdoclet/TaskDefPropertiesSubTask.java
index d69c99dcc..283132e52 100644
--- a/proposal/xdocs/src/org/apache/tools/ant/xdoclet/DatatypeTagsHandler.java
+++ b/proposal/xdocs/src/org/apache/ant/xdoclet/TaskDefPropertiesSubTask.java
@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -51,75 +51,28 @@
* information on the Apache Software Foundation, please see
* .
*/
-package org.apache.tools.ant.xdoclet;
-import com.sun.javadoc.ClassDoc;
-import com.sun.javadoc.MethodDoc;
-import com.sun.javadoc.Parameter;
-import com.sun.javadoc.Type;
+package org.apache.ant.xdoclet;
-import xdoclet.XDocletException;
-import xdoclet.XDocletTagSupport;
-import xdoclet.tags.AbstractProgramElementTagsHandler;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
+import xdoclet.TemplateSubTask;
/**
- * Custom tag handler for XDoclet templates for Ant-specific processing.
- *
- * @author Erik Hatcher
- * @created February 17, 2002
+ * Generates Ant taskdef properties files, suitable for bulk defining tasks with Ant's <taskdef> task.
*
- * @todo clean up logic so that all setters are gathered first (even
- * superclass) and sorted along wih them
- * @todo need to create better logic for finding proper setters
- * @todo add ifIsAntTask, among other convenience tags
+ * @author Erik Hatcher (ehatcher@apache.org)
+ * @created January 5, 2003
+ * @ant.element display-name="taskdefproperties" name="taskdefproperties"
+ * parent="org.apache.ant.xdoclet.AntDocletTask"
+ * @ant.task ignore="true"
+ * @version $Revision$
*/
-public class DatatypeTagsHandler extends XDocletTagSupport {
-
- /**
- * Iterates over all Ant datatypes
- */
- public void forAllDatatypes(String template, Properties attributes) throws XDocletException {
- ClassDoc[] classes = AbstractProgramElementTagsHandler.getAllClasses();
- ClassDoc cur_class = null;
-
- for (int i = 0; i < classes.length; i++) {
- cur_class = classes[i];
- setCurrentClass(cur_class);
-
- if (DatatypeSubTask.isAntDatatype(cur_class)) {
- generate(template);
- }
- }
- }
+public class TaskDefPropertiesSubTask extends AntSubTask
+{
+ protected static String DEFAULT_TEMPLATE_FILE = "resources/taskdef_properties.xdt";
- /**
- * Provides the datatype name
- */
- public String typeName() throws XDocletException {
- return getDatatypeName(getCurrentClass());
- }
-
- public static final String getDatatypeName(ClassDoc clazz) throws XDocletException {
- // sheesh! There should be a friendlier method than this!
- String tagValue = getTagValue(clazz, "ant:datatype", "name", -1,
- null, null, null, null,
- null, false, XDocletTagSupport.FOR_CLASS, false);
-
- if (tagValue == null) {
- tagValue = clazz.name();
-
- tagValue = tagValue.toLowerCase();
- }
- return tagValue;
+ public TaskDefPropertiesSubTask()
+ {
+ setTemplateURL(getClass().getResource(DEFAULT_TEMPLATE_FILE));
+ setDestinationFile("taskdef.properties");
}
}
-
diff --git a/proposal/xdocs/src/org/apache/tools/ant/xdoclet/DatatypeSubTask.java b/proposal/xdocs/src/org/apache/ant/xdoclet/TaskDescriptorSubTask.java
similarity index 60%
rename from proposal/xdocs/src/org/apache/tools/ant/xdoclet/DatatypeSubTask.java
rename to proposal/xdocs/src/org/apache/ant/xdoclet/TaskDescriptorSubTask.java
index 1db35673c..486e332b4 100644
--- a/proposal/xdocs/src/org/apache/tools/ant/xdoclet/DatatypeSubTask.java
+++ b/proposal/xdocs/src/org/apache/ant/xdoclet/TaskDescriptorSubTask.java
@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -51,71 +51,57 @@
* information on the Apache Software Foundation, please see
* .
*/
-package org.apache.tools.ant.xdoclet;
-import com.sun.javadoc.ClassDoc;
+package org.apache.ant.xdoclet;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Iterator;
+
+import xjavadoc.XClass;
+import xjavadoc.XJavaDoc;
+import xjavadoc.XMethod;
+
import xdoclet.TemplateSubTask;
import xdoclet.XDocletException;
import xdoclet.XDocletTagSupport;
-import xdoclet.tags.TypeTagsHandler;
import xdoclet.util.TypeConversionUtil;
-import java.io.File;
-import java.text.MessageFormat;
-
/**
- * Custom XDoclet subtask to handle Ant datatypes
+ * Generates Ant task descriptors.
+ *
+ * @author Erik Hatcher (ehatcher@apache.org)
+ * @created January 1, 2003
+ * @ant.element display-name="taskdescriptor" name="taskdescriptor"
+ * parent="xdoclet.modules.apache.ant.org.apache.ant.xdoclet.AntDocletTask"
+ * @ant.task ignore="true"
+ * @version $Revision$
+ * @xdoclet.merge-file file="{0}.xml" relates-to="{0}.xml" description="Used for code examples. An example merge file
+ * may be found in Ant's proposal/xdocs/src directory."
*/
-public class DatatypeSubTask extends TemplateSubTask {
- public final static String SUBTASK_NAME = "datatypes";
-
- public String getSubTaskName() {
- return SUBTASK_NAME;
- }
-
- /**
- * Returns true if the class is an Ant task. This causes the task to be processed
- * by the XDoclet template task.
- */
- protected boolean matchesGenerationRules(ClassDoc clazz) throws XDocletException {
- return isAntDatatype(clazz);
- }
-
- /**
- * @todo a datatype doesn't have to extend Datatype, right? so perhaps should
- * another condition to flag a class with @ant.datatype name="..."
- */
- public static final boolean isAntDatatype(ClassDoc clazz) throws XDocletException {
- if (clazz.isAbstract()) {
- return false;
- }
-
- // no inner classes
- if (clazz.containingClass() != null) {
- return false;
- }
-
- String ignoreValue = XDocletTagSupport.getClassTagValue(clazz, "ant:datatype", "ignore", 0, null, "false", false, false);
- boolean ignore = TypeConversionUtil.stringToBoolean(ignoreValue, true);
+public class TaskDescriptorSubTask extends AntSubTask
+{
+ protected static String DEFAULT_TEMPLATE_FILE = "resources/task_xml.xdt";
- if (ignore) {
- return false;
- }
-
- return TypeTagsHandler.isOfType(clazz,
- "org.apache.tools.ant.types.DataType",
- TypeTagsHandler.TYPE_HIERARCHY);
+ public TaskDescriptorSubTask()
+ {
+ setTemplateURL(getClass().getResource(DEFAULT_TEMPLATE_FILE));
+ setDestinationFile("{0}.xml");
}
/**
- * Custom file naming. Use the task name for the file name rather than the
- * default class name.
+ * Custom file naming. Use the task name for the file name rather than the default class name.
*
- * @todo fix hardcoded path name
+ * @param clazz
+ * @return
+ * @exception XDocletException
*/
- protected String getGeneratedFileName(ClassDoc clazz) throws XDocletException {
- String typeName = DatatypeTagsHandler.getDatatypeName(clazz);
- return typeName + ".xml";
+ protected String getGeneratedFileName(XClass clazz) throws XDocletException
+ {
+ String dir = TaskTagsHandler.getCategoryName(clazz);
+ String taskName = TaskTagsHandler.getTaskName(clazz);
+
+ return new File(dir, taskName + ".xml").toString();
}
}
diff --git a/proposal/xdocs/src/org/apache/ant/xdoclet/TaskTagsHandler.java b/proposal/xdocs/src/org/apache/ant/xdoclet/TaskTagsHandler.java
new file mode 100644
index 000000000..1a5d29063
--- /dev/null
+++ b/proposal/xdocs/src/org/apache/ant/xdoclet/TaskTagsHandler.java
@@ -0,0 +1,886 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 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 apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+
+package org.apache.ant.xdoclet;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.tools.ant.IntrospectionHelper;
+import org.apache.tools.ant.types.EnumeratedAttribute;
+import xjavadoc.TagIterator;
+import xjavadoc.XClass;
+import xjavadoc.XCollections;
+import xjavadoc.XMethod;
+import xjavadoc.XParameter;
+import xjavadoc.XTag;
+import xdoclet.XDocletException;
+import xdoclet.XDocletTagSupport;
+import xdoclet.tagshandler.AbstractProgramElementTagsHandler;
+import xdoclet.tagshandler.MethodTagsHandler;
+
+/**
+ * Custom tag handler for XDoclet templates for Ant-specific processing.
+ *
+ * @author Erik Hatcher
+ * @author Jesse Stockall
+ * @created January 1, 2003
+ * @xdoclet.taghandler namespace="Ant"
+ * @todo clean up logic so that all setters are gathered first (even superclass) and sorted along wih
+ * them
+ * @todo need to create better logic for finding proper setters
+ * @todo add ifIsAntTask, among other convenience tags
+ */
+public class TaskTagsHandler extends XDocletTagSupport
+{
+
+ /**
+ * Default category for tasks without a category attribute.
+ */
+ public final static String DEFAULT_CATEGORY = "other";
+
+ /**
+ * Default requirement group for attributes without group.
+ */
+ public final static String DEFAULT_GROUP = "optional";
+
+ /**
+ * Requirement group description for optional attributes.
+ */
+ public final static String DESC_OPTIONAL = "optional";
+
+ /**
+ * Requirement group description for required attributes.
+ */
+ public final static String DESC_REQUIRED = "required";
+
+ private static Map attributeDisplayMap = new HashMap();
+ private static Map elementDisplayMap = new HashMap();
+
+ private static String[] fluffPrefixes = {"set a", "set the", "sets a", "sets the"};
+
+ static {
+ attributeDisplayMap.put("java.lang.String", "String");
+ attributeDisplayMap.put("boolean", "boolean");
+ attributeDisplayMap.put("org.apache.tools.ant.types.Path", "Path");
+ attributeDisplayMap.put("org.apache.tools.ant.types.Reference", "Reference");
+ attributeDisplayMap.put("java.io.File", "File");
+ attributeDisplayMap.put("java.util.Date", "Date");
+ attributeDisplayMap.put("java.net.URL", "URL");
+ attributeDisplayMap.put("java.lang.Long", "long");
+ attributeDisplayMap.put("java.lang.Integer", "int");
+ attributeDisplayMap.put("java.lang.Float", "float");
+ attributeDisplayMap.put("java.lang.Double", "double");
+
+ elementDisplayMap.put("org.apache.tools.ant.types.Path", "Path");
+ elementDisplayMap.put("org.apache.tools.ant.types.FileSet", "Fileset");
+ elementDisplayMap.put("org.apache.tools.ant.taskdefs.Property", "see <property>");
+ elementDisplayMap.put("org.apache.tools.ant.types.Mapper", "Mapper");
+ elementDisplayMap.put("org.apache.tools.ant.types.PatternSet", "Patternset");
+ elementDisplayMap.put("org.apache.tools.ant.types.FileList", "Filelist");
+ elementDisplayMap.put("org.apache.tools.ant.types.FilterChain", "FilterChain");
+ elementDisplayMap.put("org.apache.tools.ant.types.FilterSet", "Filterset");
+ elementDisplayMap.put("org.apache.tools.ant.types.ZipFileSet", "ZipFileset");
+ elementDisplayMap.put("org.apache.tools.ant.types.DirSet", "Dirset");
+ elementDisplayMap.put("org.apache.tools.ant.types.XMLCatalog", "XMLCatalog");
+ }
+
+ /**
+ * Provides the Ant task name. Order of rules:
+ *
+ * - Value of
+ *
+ * @param clazz
+ * @return
+ * @ant:task name="..."
+ * - Lowercased classname with "Task" suffix removed
+ *
+ *
+ */
+ public final static String getTaskName(XClass clazz)
+ {
+ String tagValue = clazz.getDoc().getTagAttributeValue("ant.task", "name");
+
+ if (tagValue == null) {
+ // use classname, but strip "Task" suffix if there
+ tagValue = clazz.getName();
+
+ if (tagValue.endsWith("Task")) {
+ tagValue = tagValue.substring(0, tagValue.indexOf("Task"));
+ }
+
+ tagValue = tagValue.toLowerCase();
+ }
+ return tagValue;
+ }
+
+ /**
+ * Provides the Ant category name as the Value of the category attribute.
+ *
+ * @param clazz
+ * @return
+ */
+ public final static String getCategoryName(XClass clazz)
+ {
+ String tagValue = clazz.getDoc().getTagAttributeValue("ant.task", "category");
+
+ if (tagValue != null) {
+ tagValue = tagValue.toLowerCase();
+ }
+ else {
+ tagValue = DEFAULT_CATEGORY;
+ }
+ return tagValue;
+ }
+
+ /**
+ * Iterates over all Ant tasks
+ *
+ * @param template
+ * @param attributes
+ * @exception XDocletException
+ */
+ public void forAllTasks(String template, Properties attributes) throws XDocletException
+ {
+ Collection classes = AbstractProgramElementTagsHandler.getAllClasses();
+ XClass cur_class = null;
+
+ Iterator iter = classes.iterator();
+
+ while (iter.hasNext()) {
+ cur_class = (XClass) iter.next();
+ setCurrentClass(cur_class);
+
+ if (AntSubTask.isAntTask(cur_class)) {
+ generate(template);
+ }
+ }
+ }
+
+// /**
+// * Iterates over all Ant attributes.
+// *
+// * @param template XDoclet template
+// * @param attributes Tag parameters
+// * @exception XDocletException Oops!
+// */
+// public void forAllAttributes(String template, Properties attributes) throws XDocletException
+// {
+// // throw exception if not an Ant task
+//
+// XClass cur_class = getCurrentClass();
+//
+// XMethod[] methods = getAttributeMethods(cur_class);
+//
+//// System.out.println("# attributes = " + methods.length);
+//
+// for (int i = 0; i < methods.length; i++) {
+// setCurrentMethod(methods[i]);
+// generate(template);
+// }
+// }
+
+ /**
+ * Iterates over all Ant attributes.
+ *
+ * @param template XDoclet template
+ * @param attributes Tag parameters
+ * @exception XDocletException Oops!
+ */
+ public void forAllAttributesInGroup(String template, Properties attributes) throws XDocletException
+ {
+ // throw exception if not an Ant task
+
+ XClass cur_class = getCurrentClass();
+
+ XMethod[] methods = getAttributeMethods(cur_class);
+
+ String group = attributes.getProperty("group", DEFAULT_GROUP);
+
+ for (int i = 0; i < methods.length; i++) {
+ String value = methods[i].getDoc().getTagAttributeValue("ant.attribute", "group");
+
+ if ((value != null && value.equals(group)) || (value == null && group.equals(DEFAULT_GROUP))) {
+ setCurrentMethod(methods[i]);
+ generate(template);
+ }
+ }
+ }
+
+ /**
+ * Determines if there's at least one Ant attribute.
+ *
+ * @param template XDoclet template
+ * @param attributes Tag parameters
+ * @exception XDocletException Oops!
+ */
+ public void ifHasAttributes(String template, Properties attributes) throws XDocletException
+ {
+ // throw exception if not an Ant task
+
+ XClass cur_class = getCurrentClass();
+
+ XMethod[] methods = getAttributeMethods(cur_class);
+
+ if (methods.length > 0) {
+ generate(template);
+ }
+ }
+
+ /**
+ * Iterates over all Ant nested element methods (addXXX, addConfiguredXXX, addXXX)
+ *
+ * @param template XDoclet template
+ * @param attributes Tag parameters
+ * @exception XDocletException Oops!
+ */
+ public void forAllElements(String template, Properties attributes) throws XDocletException
+ {
+ // throw exception if not an Ant task
+
+ XClass cur_class = getCurrentClass();
+
+ XMethod[] methods = getElementMethods(cur_class);
+
+ for (int i = 0; i < methods.length; i++) {
+ setCurrentMethod(methods[i]);
+ generate(template);
+ }
+ }
+
+ /**
+ * Iterates over all ant.attribute.group tags.
+ *
+ * @param template XDoclet template
+ * @param attributes Tag parameters
+ * @throws XDocletException Oops!
+ */
+ public void forAllAttributeGroups(String template, Properties attributes) throws XDocletException
+ {
+ Collection tags = getCurrentClass().getDoc().getTags("ant.attribute.group");
+
+ for (TagIterator t = XCollections.tagIterator(tags); t.hasNext(); ) {
+ setCurrentClassTag(t.next());
+
+ generate(template);
+ }
+ }
+
+ /**
+ * Provides the name of a requirement group.
+ *
+ * @return The description of the group, or 'optional' if not is defined
+ * @throws XDocletException
+ */
+ public String attributeGroupName() throws XDocletException
+ {
+ XTag tag = getCurrentClassTag();
+ String name = tag.getAttributeValue("name");
+
+ return name != null ? name : DEFAULT_GROUP;
+ }
+
+ /**
+ * Provides the description for a requirement group.
+ *
+ * @return The description of the group, or 'Optional' if not is defined
+ * @throws XDocletException
+ */
+ public String attributeGroupDesc() throws XDocletException
+ {
+ XTag tag = getCurrentClassTag();
+ String desc = tag.getAttributeValue("description");
+
+ return desc != null ? desc : DESC_OPTIONAL;
+ }
+
+ /**
+ * Provides the element name for the current method
+ *
+ * @return
+ * @exception XDocletException
+ */
+ public String elementName() throws XDocletException
+ {
+ String methodName = getCurrentMethod().getName();
+ String elementName = "";
+
+ if (methodName.startsWith("addConfigured")) {
+ elementName = methodName.substring(13, methodName.length());
+ }
+ else if (methodName.startsWith("add")) {
+ elementName = methodName.substring(3, methodName.length());
+ }
+ else if (methodName.startsWith("create")) {
+ elementName = methodName.substring(6, methodName.length());
+ }
+ return elementName.toLowerCase();
+ }
+
+ public String displayAttributeType() throws XDocletException
+ {
+ Collection parameters = getCurrentMethod().getParameters();
+ XParameter param = XCollections.parameterIterator(parameters).next();
+
+ String methodType = param.getType().getQualifiedName();
+ String display = (String) attributeDisplayMap.get(methodType);
+
+ if (display == null) {
+
+// System.out.println("type = " + methodType);
+
+ Class clazz = getAttributeClass(methodType);
+
+ if (clazz == null) {
+ return methodType;
+ }
+
+ Object instance = null;
+
+ try {
+ instance = clazz.newInstance();
+ }
+ catch (InstantiationException e) {
+ }
+ catch (IllegalAccessException e) {
+ }
+
+ if (instance != null && instance instanceof EnumeratedAttribute) {
+ EnumeratedAttribute enum = (EnumeratedAttribute) instance;
+ String[] values = enum.getValues();
+
+ display = "";
+ for (int i = 0; i < values.length; i++) {
+ display += """ + values[i] + """;
+ if (i != (values.length - 1)) {
+ display += ", ";
+ }
+ }
+ return display;
+ }
+
+ display = "";
+ }
+ return display;
+ }
+
+ public String displayElementType() throws XDocletException
+ {
+ String elementType = elementType();
+ String display = (String) elementDisplayMap.get(elementType);
+
+ if (display == null) {
+ display = "";
+ }
+ return display;
+ }
+
+ /**
+ * Provides the element type for the current method
+ *
+ * @return
+ * @exception XDocletException
+ */
+ public String elementType() throws XDocletException
+ {
+ XClass clazz = elementClassDoc();
+
+ if (clazz == null) {
+ throw new XDocletException("Method is not an Ant element!");
+ }
+ return clazz.getQualifiedName();
+ }
+
+ /**
+ * Provides the Ant task name.
+ *
+ * @return
+ * @exception XDocletException
+ * @see #getTaskName(xjavadoc.XClass)
+ */
+ public String taskName() throws XDocletException
+ {
+ return getTaskName(getCurrentClass());
+ }
+
+ public String propertyName()
+ {
+ return MethodTagsHandler.getPropertyNameFor(getCurrentMethod()).toLowerCase();
+ }
+
+ public String shortMethodDescription() throws XDocletException
+ {
+ String desc = getCurrentMethod().getDoc().getFirstSentence();
+
+ if (desc == null || desc.length() == 0) {
+ desc = "no description";
+ }
+
+ desc = desc.trim();
+
+ String descLower = desc.toLowerCase();
+
+ for (int i = 0; i < fluffPrefixes.length; i++) {
+ String prefix = fluffPrefixes[i].toLowerCase() + " ";
+
+ if (descLower.startsWith(prefix)) {
+ desc = desc.substring(prefix.length());
+ break;
+ }
+ }
+
+ desc = desc.substring(0, 1).toUpperCase() + desc.substring(1);
+
+ if (!desc.endsWith(".")) {
+ desc += ".";
+ }
+
+ return desc;
+ }
+
+ /**
+ * Provides the Ant category name.
+ *
+ * @return
+ * @exception XDocletException
+ * @see #getCategoryName(xjavadoc.XClass)
+ */
+ public String categoryName() throws XDocletException
+ {
+ return getCategoryName(getCurrentClass());
+ }
+
+ /**
+ * Provides the requirment group for the current method
+ *
+ * @return The group listed in the source, or 'optional' of none is listed
+ * @throws XDocletException oops
+ */
+ public String attributeGroup() throws XDocletException
+ {
+ String value = getCurrentMethod().getDoc().getTagAttributeValue("ant.attribute", "group");
+
+ return value != null ? value : DEFAULT_GROUP;
+ }
+
+ private Class getAttributeClass(String type) throws XDocletException
+ {
+// System.out.println("type = " + type);
+
+ Class clazz = null;
+
+ try {
+ clazz = Class.forName(type);
+ }
+ catch (ClassNotFoundException e) {
+ int lastDotPosition = type.lastIndexOf('.');
+
+ if (lastDotPosition < 0) {
+ // probably a primitive
+ return null;
+ }
+ type = type.substring(0, lastDotPosition) + "$" + type.substring(lastDotPosition + 1);
+ try {
+ clazz = Class.forName(type);
+ }
+ catch (ClassNotFoundException e1) {
+ throw new XDocletException(e1.getMessage());
+ }
+ }
+ return clazz;
+ }
+
+
+ /**
+ * @param cur_class
+ * @return
+ * @exception XDocletException
+ * @todo refactor to cache methods per class, and save some time
+ */
+ private XMethod[] getAttributeMethods(XClass cur_class) throws XDocletException
+ {
+ // Use Ant's own introspection mechanism to gather the
+ // attributes this class supports
+ IntrospectionHelper is = null;
+
+ try {
+ is = IntrospectionHelper.getHelper(Class.forName(cur_class.getQualifiedName()));
+ }
+ catch (ClassNotFoundException e) {
+ throw new XDocletException(e, e.getMessage());
+ }
+
+ // Regroup the attributes, since IntrospectionHelper
+ // doesn't give us the whole data structure directly
+ Enumeration enum = is.getAttributes();
+ Properties attributeTypeMap = new Properties();
+
+ while (enum.hasMoreElements()) {
+ String name = (String) enum.nextElement();
+ Class type = is.getAttributeType(name);
+
+ attributeTypeMap.setProperty(name, type.getName());
+// System.out.println(name + " = " + type.getName());
+ }
+
+ // We need to return XMethod[] from this method
+ // so get all methods from the current class
+ XMethod[] allMethods = getMethods(cur_class);
+
+// System.out.println("allMethods = " + allMethods.length);
+
+ // And now filter the methods based
+ // on what IntrospectionHelper says
+ List attributeMethods = new ArrayList();
+
+ for (int i = 0; i < allMethods.length; i++) {
+ XMethod method = allMethods[i];
+ String methodName = method.getName();
+
+// System.out.println("methodName = " + methodName);
+
+ if (!methodName.startsWith("set")) {
+ continue;
+ }
+
+ String attributeName = methodName.substring(3).toLowerCase();
+
+// System.out.println("attributeName = " + attributeName);
+
+ if ((method.getParameters().size() != 1) || (!method.isPublic())) {
+ continue;
+ }
+
+ String attributeType = XCollections.parameterIterator(method.getParameters()).next().getType().getQualifiedName();
+
+// System.out.println("attributeType = " + attributeType);
+
+ String mapAttribute = attributeTypeMap.getProperty(attributeName);
+
+ if (mapAttribute == null) {
+ continue;
+ }
+
+ // inner classes are noted with $ in our map, but not
+ // n the parameter type name.
+ if (!attributeType.equals(mapAttribute.replace('$', '.'))) {
+ continue;
+ }
+
+// System.out.println(methodName + " : " + attributeName + " : " + attributeType);
+
+ attributeMethods.add(method);
+ }
+
+ return (XMethod[]) attributeMethods.toArray(new XMethod[0]);
+ }
+
+ /**
+ * @param cur_class
+ * @return
+ * @exception XDocletException
+ * @todo add checks for number parameters and appropriate return value check for proper
+ * exception too? method prefixes: add, create, addConfigured (but not addText)
+ * @todo add DynamicConfigurator (this should be noted in the template, not dealt with here)
+ */
+ private XMethod[] getElementMethods(XClass cur_class) throws XDocletException
+ {
+ // Use Ant's own introspection mechanism to gather the
+ // elements this class supports
+ IntrospectionHelper is = null;
+
+ try {
+ is = IntrospectionHelper.getHelper(Class.forName(cur_class.getQualifiedName()));
+ }
+ catch (ClassNotFoundException e) {
+ throw new XDocletException(e.getMessage());
+ }
+
+ // Regroup the elements, since IntrospectionHelper
+ // doesn't give us the whole data structure directly
+ Enumeration enum = is.getNestedElements();
+ Properties elementTypeMap = new Properties();
+
+ while (enum.hasMoreElements()) {
+ String name = (String) enum.nextElement();
+ Class type = is.getElementType(name);
+
+ elementTypeMap.setProperty(name, type.getName());
+// System.out.println(name + " = " + type.getName());
+ }
+
+ // We need to return MethodDoc[] from this method
+ // so get all methods from the current class
+ XMethod[] allMethods = getMethods(cur_class);
+
+ // And now filter the MethodDoc's based
+ // on what IntrospectionHelper says
+ List elementMethods = new ArrayList();
+
+ for (int i = 0; i < allMethods.length; i++) {
+ XMethod method = allMethods[i];
+ String methodName = method.getName();
+
+ // Object create(), void add(Object), void addConfigured(Object)
+ String elementName = null;
+
+ // true if addXXX or addConfiguredXXX
+ boolean adder = false;
+
+ if (methodName.startsWith("create")) {
+ elementName = methodName.substring(6).toLowerCase();
+ }
+
+ if (methodName.startsWith("add")) {
+ int length = 3;
+
+ if (methodName.startsWith("addConfigured")) {
+ length = 13;
+ }
+
+ elementName = methodName.substring(length).toLowerCase();
+ adder = true;
+ }
+
+ if (elementName == null) {
+ continue;
+ }
+
+// System.out.println("elementName = " + elementName);
+
+ String elementType = null;
+
+ if (adder) {
+ if (method.getParameters().size() != 1) {
+ continue;
+ }
+ elementType = XCollections.parameterIterator(method.getParameters()).next().getType().getQualifiedName();
+ }
+ else {
+ elementType = method.getReturnType().getType().getQualifiedName();
+ }
+
+ if (!method.isPublic()) {
+ continue;
+ }
+
+ String mapElementType = elementTypeMap.getProperty(elementName);
+
+// System.out.println("elementType = " + elementType + " mapElementType = " + mapElementType);
+ if (mapElementType == null) {
+ continue;
+ }
+
+ // inner classes are noted with $ in our map, but not
+ // the parameter type name.
+ if (!elementType.equals(mapElementType.replace('$', '.'))) {
+ continue;
+ }
+
+ elementMethods.add(method);
+ }
+
+ return (XMethod[]) elementMethods.toArray(new XMethod[0]);
+ }
+
+ /**
+ * This is a slightly refactored (thank you IntelliJ) version of some cut-and-paste from XDoclet code. It sorts all
+ * methods together rather than in batches of superclasses like XDoclet stuff does.
+ *
+ * @param cur_class
+ * @return
+ * @exception XDocletException
+ */
+ private XMethod[] getMethods(XClass cur_class) throws XDocletException
+ {
+ Map already = new HashMap();
+
+ List methods = new ArrayList();
+
+ while (cur_class != null) {
+ // hardcoded to stop when it hits Task, nothing there
+ // or above that needs to be processed
+ if (cur_class.getQualifiedName().equals("org.apache.tools.ant.Task") ||
+ cur_class.getQualifiedName().equals("org.apache.tools.ant.taskdefs.MatchingTask")) {
+ break;
+ }
+
+ Collection curMethods = cur_class.getMethods();
+
+ Iterator iter = curMethods.iterator();
+
+ while (iter.hasNext()) {
+ XMethod method = (XMethod) iter.next();
+
+ if (isDeprecated(method)) {
+ continue;
+ }
+ if (shouldIgnore(method)) {
+ continue;
+ }
+
+ String methodName = method.getName();
+
+// System.out.println("method = " + method + ":" + methodName);
+
+ if (method.getContainingClass() == cur_class) {
+ if (already.containsKey(methodName) == false) {
+ already.put(methodName, method);
+ methods.add(method);
+ }
+ }
+ }
+
+ cur_class = cur_class.getSuperclass();
+ }
+
+ return sortMethods(methods);
+ }
+
+ private boolean isDeprecated(XMethod method)
+ {
+ Collection tags = method.getDoc().getTags();
+ Iterator iter = tags.iterator();
+
+ while (iter.hasNext()) {
+ XTag tag = (XTag) iter.next();
+
+ if (tag.getName().equals("@deprecated")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Provides the element type for the current method. If the return type is null, the first parameter is used.
+ *
+ * @return
+ */
+ private XClass elementClassDoc()
+ {
+ XClass clazz = null;
+ String methodName = getCurrentMethod().getName();
+
+ if (methodName.startsWith("addConfigured") ||
+ methodName.startsWith("add") ||
+ methodName.startsWith("create")) {
+ clazz = getCurrentMethod().getReturnType().getType();
+ if ("void".equals(clazz.getName())) {
+ Collection params = getCurrentMethod().getParameters();
+
+ if (params.size() == 1) {
+ clazz = XCollections.parameterIterator(params).next().getType();
+ }
+ }
+ }
+// System.out.println(methodName + ": clazz = " + clazz.getQualifiedName());
+ return clazz;
+ }
+
+ /**
+ * For now, lump attributes and elements together since we won't have those tags on the same method.
+ *
+ * @param method
+ * @return True if the method should be ignored.
+ */
+ private boolean shouldIgnore(XMethod method)
+ {
+ String value = method.getDoc().getTagAttributeValue("ant.attribute", "ignore");
+
+ if ("true".equals(value)) {
+ return true;
+ }
+
+ value = method.getDoc().getTagAttributeValue("ant.element", "ignore");
+ if ("true".equals(value)) {
+ return true;
+ }
+ return false;
+ }
+
+ private XMethod[] sortMethods(List methods)
+ {
+ //sort methods
+ Collections.sort(methods,
+ new Comparator()
+ {
+ public int compare(Object o1, Object o2)
+ {
+ XMethod m1 = (XMethod) o1;
+ XMethod m2 = (XMethod) o2;
+
+ return m1.getName().compareTo(m2.getName());
+ }
+
+
+ public boolean equals(Object obj)
+ {
+ //dumb
+ return obj == this;
+ }
+ });
+
+ return (XMethod[]) methods.toArray(new XMethod[0]);
+ }
+}
+
diff --git a/proposal/xdocs/src/org/apache/ant/xdoclet/resources/task_xml.xdt b/proposal/xdocs/src/org/apache/ant/xdoclet/resources/task_xml.xdt
new file mode 100644
index 000000000..ec4564a19
--- /dev/null
+++ b/proposal/xdocs/src/org/apache/ant/xdoclet/resources/task_xml.xdt
@@ -0,0 +1,92 @@
+deprecated="true"
+ matchingTask="true">
+
+
+
+
+
+ ]]>
+
+ ]]>
+
+
+
+
+
+
+
+
+ deprecated="true"
+ briefType="">
+ ]]>
+ ]]>
+
+
+
+
+
+
+
+ deprecated="true"
+ briefType="">
+ ]]>
+ ]]>
+
+
+
+
+
+
+
+ deprecated="true"
+ briefType="">
+ ]]>
+ ]]>
+
+
+
+
+
+
+
+
+
+ deprecated="true"
+ briefType=""
+
+ abstract="true">
+
+ ]]>
+
+ ]]>
+
+
+
+
+
+
+
+ deprecated="true">
+
+ ]]>
+
+
+
+
+
+
+
+
diff --git a/proposal/xdocs/src/org/apache/ant/xdoclet/resources/taskdef_properties.xdt b/proposal/xdocs/src/org/apache/ant/xdoclet/resources/taskdef_properties.xdt
new file mode 100644
index 000000000..09d21c4d1
--- /dev/null
+++ b/proposal/xdocs/src/org/apache/ant/xdoclet/resources/taskdef_properties.xdt
@@ -0,0 +1,2 @@
+=
+