Java/Ant/Custom Task
Содержание
Ant Write Our Own Task
<source lang="java">
/*
* Uses org.apache.tools.ant.Main, * which is Copyright 2000-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */
package org.mwrm.ant.tasks; import org.apache.tools.ant.Task; import org.apache.tools.ant.Main; /**
*The ProjectHelpTask
class displays usage information
* for the current project. This is the same information as is displayed
* by -projecthelp
.
* */
public class ProjectHelpTask extends Task {
/** The location of the build file to use * when obtaining usage information. */ private String buildfile; /***
Runs the task.
* It calls {@link org.apache.tools.ant.Main#main(String[] args)
* org.apache.tools.ant.Main.main()} with the -projecthelp
* parameter. It will also send the current build file"s file name
* via the -f
parameter.
**
The buildfile
attribute is optional.
* The default is the task"s build file.
* @see org.apache.tools.ant.Main org.apache.tools.ant.Main
*/
public final void execute() {
// If the buildfile attribute is null, we"ll use the task"s build file
if (buildfile == null) {
buildfile = getLocation().getFileName();
}
// The arguments that we will pass to the Main class.
// The buildfile attribute must follow the -f parameter.
String[] args = {"-projecthelp", "-f", buildfile};
// Call the Main Ant class with the arguments.
Main.main(args);
}
/**
* Setter method for the buildfile
attribute.
* @param file The file name of the build file to use.
*
*/
public final void setBuildfile(final String file) {
this.buildfile = file;
}
}
</source>
Create your own Ant task
<source lang="java">
/* Code revised from
Cooking with Java XP by Eric M. Burke and Brian M. Coyner ISBN: 0-596-00387-0 Pages: 288
- /
<?xml version="1.0"?> <project name="Ant Task" default="compile" basedir=".">
<property name="dir.build" value="build"/> <property name="dir.dist" value="dist"/> <property name="dir.src" value="src"/> <path id="classpath.project"> <pathelement path="${dir.build}"/> </path> <target name="compile" description="Compile all source code."> <javac srcdir="${dir.src}" destdir="${dir.build}"> <classpath refid="classpath.project"/> </javac> </target> <target name="demoDialogBox" depends="compile"> <taskdef name="dialogbox" classname="DialogBoxTask" classpath="${dir.build}"/> <dialogbox message="Are you ready?" title="Important Question" property="response" optiontype="yes_no"/> <dialogbox message="You entered ${response}!"/> <dialogbox title="First response: ${response}">This is a dialog with a multi-line message.</dialogbox> </target>
</project>
import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.ProjectHelper; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.EnumeratedAttribute; import javax.swing.*; public class DialogBoxTask extends Task {
private String message; private String title = "Question"; private int optionType = -1; private String propertyName; public void setTitle(String title) { this.title = title; } public void setProperty(String propertyName) { this.propertyName = propertyName; } public void setOptiontype(OptionType ot) { log("Calling setOptionType: " + ot.getValue(), Project.MSG_DEBUG); String value = ot.getValue(); if ("ok".equals(value)) { optionType = -1; } else if ("ok_cancel".equals(value)) { optionType = JOptionPane.OK_CANCEL_OPTION; } else if ("yes_no".equals(value)) { optionType = JOptionPane.YES_NO_OPTION; } else { // only remaining possibility optionType = JOptionPane.YES_NO_CANCEL_OPTION; } } public void setMessage(String msg) { // ant always replaces properties for attributes message = msg; } public void addText(String msg) { if (message == null) { message = ""; } // we must manually replace properties for nested text message += ProjectHelper.replaceProperties( getProject(), msg, getProject().getProperties()); } public void execute() throws BuildException { validateAttributes(); log("optionType = " + optionType, Project.MSG_DEBUG); if (optionType == -1) { JOptionPane.showMessageDialog( null, // parent message, title, JOptionPane.INFORMATION_MESSAGE); } else { int response = JOptionPane.showConfirmDialog( null, // parent message, title, optionType, JOptionPane.QUESTION_MESSAGE); if (propertyName != null) { String responseText = formatResponseCode(response); log("Setting " + propertyName + " to " + responseText, Project.MSG_VERBOSE); getProject().setProperty(propertyName, responseText); } } } protected void validateAttributes() { if (message == null) { throw new BuildException("Message must be specified using the " + "message attribute or nested text."); } if (optionType == -1 && propertyName != null) { throw new BuildException( "Cannot specify property unless optionType is " + ""ok_cancel", "yes_no", or "yes_no_cancel""); } } public static class OptionType extends EnumeratedAttribute { public String[] getValues() { return new String[]{ "ok", "ok_cancel", "yes_no", "yes_no_cancel", }; } } private String formatResponseCode(int optionPaneResponse) { switch (optionPaneResponse) { // note: JOptionPane.OK_OPTION is the same as YES_OPTION case JOptionPane.YES_OPTION: return "yes"; case JOptionPane.NO_OPTION: return "no"; case JOptionPane.CANCEL_OPTION: case JOptionPane.CLOSED_OPTION: return "cancel"; default: throw new BuildException("Internal error: Unknown option " + "pane response: " + optionPaneResponse); } }
}
</source>
Extend Javadoc Task
<source lang="java">
/*
* Extends org.apache.tools.ant.taskdefs.Javadoc * and uses org.apache.tools.ant.taskdefs.UpToDate, * which are Copyright 2000-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */
package org.mwrm.ant.tasks; import java.io.File; import java.util.Enumeration; import java.util.StringTokenizer; import java.util.Vector; import org.apache.tools.ant.Project; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.taskdefs.Javadoc; import org.apache.tools.ant.taskdefs.UpToDate; import org.apache.tools.ant.types.FileSet; /**
*The ExtendJavadocTask
class
* extends the {@link org.apache.tools.ant.taskdefs.Javadoc Javadoc} task.
* It checks whether a set of source files are newer than a set of target files
* and if so, it generates Javadocs.
* */
public class ExtendJavadocTask extends Javadoc {
/** The attribute of the task element. */ private File target; /** A set of file sets, * each of which is provided by a nested file set. */ private Vector targetFileSets = new Vector(); /** The internal uptodate task. */ private UpToDate utd; /***
Creates a new instance of an internal
* <uptodate>
task
* and adds it to the current project.
* @see UpToDate org.apache.tools.ant.taskdefs.UpToDate */ public final void init() { // We need an instance of the <uptodate> task utd = new UpToDate(); // We need to add the task to this project utd.setProject(this.getProject()); } /***
Checks if Javadocs should be created
* and then calls super.execute()
if so.
This method does usage checks on the task"s attributes
* and its nested elements.
* It will throw a BuildException
if there is a violation.
*/ public final void execute() { // This is the usage information // We can"t have a target attribute // and nested targetfiles elements if (target != null && targetFileSets.size() > 0) { String msg = "You can"t specify a targetfile attribute " + "and <targetfiles> elements."; throw new BuildException(msg); } // We have to specify either a target attribute // or at least one nested targetfiles elements if (target == null && targetFileSets.size() == 0) { String msg = "You must specify either a targetfile attribute " + "or at least one <targetfiles> element."; throw new BuildException(msg); } // If this is false, the files aren"t up to date // and we have to run the javadocs boolean eval = false; // If we"ve got to this point, we know the usage must be correct. // Let"s check whether a single target attribute has been used. if (target != null) { // Get the results of the check eval = getResult(target); } else { // If a target attribute wasn"t specified, // at least one nested targetfiles element was. // We first get all the file sets represented by the nested elements Enumeration e = targetFileSets.elements(); // And then iterate over them while (e.hasMoreElements()) { // The next element is a file set, so we get its files // in a semi-colon-separated list String files = e.nextElement().toString(); // Next, we split the list into its file names StringTokenizer st = new StringTokenizer(files, ";"); // And iterate over them to test each one while (st.hasMoreTokens()) { // We create a file //from the current file name in the iteration File tempTarget = new File(st.nextToken()); // Get the results of the check eval = getResult(tempTarget); // One false result is enough to fail the whole file set if (!eval) { break; } } // One false result is enough to fail the whole file set if (!eval) { break; } } } // If the test failed, we want to generate Javadocs if (!eval) { super.execute(); } else { log("Skipping Javadoc creation. The files are up to date.", Project.MSG_INFO); } }/**
Checks whether the files are up to date.
* @param file The file to evaluate * @return boolean The result */ private boolean getResult(final File file) { // Set the target property in the <uptodate> task utd.setTargetFile(file); // Evaluate the files return utd.eval(); } /***
The setter method for the target
attribute.
* @param targetFile A file to check against */ public final void setTarget(final File targetFile) { this.target = targetFile; } /***
The setter method for the file set
* contained in the nested <srcfiles>
element.
* @param fileset A file set of source files */ public final void addSrcfiles(final FileSet fileset) { utd.addSrcfiles(fileset); } /***
The setter method for the file sets
* contained in nested <targetfiles>
elements.
* @param fileset A file set of target files */ public final void addTargetfiles(final FileSet fileset) { targetFileSets.add(fileset); }
}
</source>
How to use a Class argument in a custom class attribute
<source lang="java">
/*
* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */
package org.mwrm.ant.tasks; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; import org.apache.tools.ant.BuildException; /**
*The ClassSetTask
class
* demonstrates how to use a Class
argument
* in a custom class attribute.
* */
public class ClassSetTask extends Task {
/** The qualified class name. */ private Class qualifiedName; /***
Runs the task and displays the qualified name of the class
* that is set as the setQualifiedName
attribute.
* */ public final void execute() { log("qualifiedName: " + qualifiedName, Project.MSG_INFO); } /***
Sets the fully qualified name of the class.
** @param qName The fully qualified name of a class */ public final void setQualifiedName(final Class qName) { if (qName.getName().equals("java.lang.Integer") || qName.getName().equals("java.lang.String")) { log(qName.getName() + " found.", Project.MSG_INFO); } else { String msg = "You can only specify java.lang.Integer " + "or java.lang.String in qualifiedName."; throw new BuildException(msg); } this.qualifiedName = qName; }
}
</source>
Life Cycle Task
<source lang="java">
/*
* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */
package org.mwrm.ant.tasks; import java.util.Hashtable; import java.util.Enumeration; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; import org.apache.tools.ant.BuildException; /**
*At each stage in a task"s life cycle, this class displays information
* to show the internal state of the task and its position with in the project.
* It takes a name
attribute.
*/
public class LifeCycleTask extends Task {
/** The name
attribute of this task. */
private String name;
/** The body text of this task. */
private String text;
/**
* The constructor displays the state of the task * as it is instantiated.
*/ public LifeCycleTask() { System.out.println("---------------"); System.out.println("Constructor called"); System.out.println("Value of name attribute: " + name); System.out.println("Value of the body text: " + text); System.out.println("Project: " + getProject()); System.out.println("Location: " + getLocation()); System.out.println("Target: " + getOwningTarget()); System.out.println("---------------"); } /***
Displays the state of the task at initialization.
* @see #logAll(String method) */ public final void init() { logAll("init()"); } /***
Displays the state of the task when Ant runs it. * This method also runs some usage checks * to ensure the task is being used properly.
*/ public final void execute() { if (name == null) { throw new BuildException("You must specify a name attribute in " + getTaskName() + "."); } logAll("execute()"); // Write the name to output log(name, Project.MSG_INFO); } /***
Sets the name to display * and shows the state of the task afterwards.
* @param aName The name to display */ public final void setName(final String aName) { // The value of the name attribute this.name = aName; logAll("setName()"); } /***
Sets the body text of the task * and shows the state of the task afterwards.
* @param bodyText The body text */ public final void addText(final String bodyText) { // If the body text is just whitespace, it might as well be null if (bodyText.trim().equals("")) { this.text = null; } else { this.text = bodyText.trim(); } logAll("addText()"); }/**
Checks for task references.
* @return String * A string that tells us details of the reference check */ private String referenceCheck() { // The default setting String setString = "Reference not found."; // We need the references that have been set in this project Hashtable refs = getProject().getReferences(); Enumeration e = refs.elements(); // Let"s iterate over them while (e.hasMoreElements()) { // We want to work with each object, so we"ll instantiate an object Object obj = e.nextElement(); // Check to see whether this object is a task // If it is, we"ll build a string that contains its name and type if (obj.getClass().getName(). equals("org.apache.tools.ant.UnknownElement") || obj.getClass().getName(). equals(this.getClass().getName())) { Task aTask = (Task) obj; setString = "Reference to " + aTask.getTaskName() + " found, of type " + aTask.getClass().getName() + ". "; setString = setString + "Its id is " + aTask.getRuntimeConfigurableWrapper(). getAttributeMap().get("id") + "."; } } return setString; } /***
A central logging method that all the life-cycle methods call
* to display the state of the task.
* It displays the value of the name
attribute
* and other information about the task,
* including the name of its project and its location in the build file.
* @param method The name of the method that issued the logging call */ public final void logAll(final String method) { log("---------------", Project.MSG_VERBOSE); log(method + " called", Project.MSG_VERBOSE); log("Value of name attribute: " + name, Project.MSG_VERBOSE); log("Value of the body text: " + text, Project.MSG_VERBOSE); log("Project: " + getProject().getName(), Project.MSG_VERBOSE); // Here we build some information on the location // within the build file String locationString = getLocation().getFileName(); locationString = locationString + " at line " + getLocation().getLineNumber(); // Location.getColumnNumber() is for Ant 1.7+ // Comment it out if you are using Ant 1.6.x //locationString = locationString + " and column " // + getLocation().getColumnNumber(); log("Location: " + locationString, Project.MSG_VERBOSE); // We could use the Location.toString() method //log("Location: " + getLocation(), Project.MSG_VERBOSE); log("Target: " + getOwningTarget(), Project.MSG_VERBOSE); // referenceCheck() returns a string with information // on any references to custom tasks log(referenceCheck(), Project.MSG_VERBOSE); // If the configuration wrapper is null, we use its // run-time equivalent if (getWrapper() == null) { log("Reference id: " + getRuntimeConfigurableWrapper().getAttributeMap().get("id"), Project.MSG_VERBOSE); } else { // This time we use the protected getWrapper() method log("Reference id: " + getWrapper().getAttributeMap().get("id"), Project.MSG_VERBOSE); } log("---------------", Project.MSG_VERBOSE); }
}
</source>