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: + *
    + *
  1. Value of + * + * @param clazz + * @return + * @ant:task name="..."
  2. + *
  3. Lowercased classname with "Task" suffix removed
  4. + *
+ * + */ + 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 @@ += +