Java/Ant/Custom Task
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
Ant Write Our Own Task
/*
* 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;
/**
* <p>The <code>ProjectHelpTask</code> class displays usage information
* for the current project. This is the same information as is displayed
* by <code>-projecthelp</code>.</p>
*
*/
public class ProjectHelpTask extends Task {
/** The location of the build file to use
* when obtaining usage information. */
private String buildfile;
/**
* <p>Runs the task.
* It calls {@link org.apache.tools.ant.Main#main(String[] args)
* org.apache.tools.ant.Main.main()} with the <code>-projecthelp</code>
* parameter. It will also send the current build file"s file name
* via the <code>-f</code> parameter.</p>
*
* <p>The <code>buildfile</code> attribute is optional.
* The default is the task"s build file.</p>
* @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 <code>buildfile</code> attribute.
* @param file The file name of the build file to use.
*
*/
public final void setBuildfile(final String file) {
this.buildfile = file;
}
}
Create your own Ant task
/*
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);
}
}
}
Extend Javadoc Task
/*
* 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;
/**
* <p>The <code>ExtendJavadocTask</code> 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.</p>
*
*/
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;
/**
* <p>Creates a new instance of an internal
* <code><uptodate></code> task
* and adds it to the current project.</p>
* @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());
}
/**
* <p>Checks if Javadocs should be created
* and then calls <code>super.execute()</code> if so.</p>
* <p>This method does usage checks on the task"s attributes
* and its nested elements.
* It will throw a <code>BuildException</code> if there is a violation.</p>
*/
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);
}
}
/** <p>Checks whether the files are up to date.</p>
* @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();
}
/**
* <p>The setter method for the <code>target</code> attribute.</p>
* @param targetFile A file to check against
*/
public final void setTarget(final File targetFile) {
this.target = targetFile;
}
/**
* <p>The setter method for the file set
* contained in the nested <code><srcfiles></code> element.</p>
* @param fileset A file set of source files
*/
public final void addSrcfiles(final FileSet fileset) {
utd.addSrcfiles(fileset);
}
/**
* <p>The setter method for the file sets
* contained in nested <code><targetfiles></code> elements.</p>
* @param fileset A file set of target files
*/
public final void addTargetfiles(final FileSet fileset) {
targetFileSets.add(fileset);
}
}
How to use a Class argument in a custom class attribute
/*
*
* 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;
/**
* <p>The <code>ClassSetTask</code> class
* demonstrates how to use a <code>Class</code> argument
* in a custom class attribute.</p>
*
*/
public class ClassSetTask extends Task {
/** The qualified class name. */
private Class qualifiedName;
/**
* <p>Runs the task and displays the qualified name of the class
* that is set as the <code>setQualifiedName</code> attribute.</p>
*
*/
public final void execute() {
log("qualifiedName: " + qualifiedName, Project.MSG_INFO);
}
/**
* <p>Sets the fully qualified name of the class.</p>
** @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;
}
}
Life Cycle Task
/*
*
* 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;
/**
* <p>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 <code>name</code> attribute.</p>
*/
public class LifeCycleTask extends Task {
/** The <code>name</code> attribute of this task. */
private String name;
/** The body text of this task. */
private String text;
/**
* <p>The constructor displays the state of the task
* as it is instantiated.</p>
*/
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("---------------");
}
/**
* <p>Displays the state of the task at initialization.</p>
* @see #logAll(String method)
*/
public final void init() {
logAll("init()");
}
/**
* <p>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.</p>
*/
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);
}
/**
* <p>Sets the name to display
* and shows the state of the task afterwards.</p>
* @param aName The name to display
*/
public final void setName(final String aName) {
// The value of the name attribute
this.name = aName;
logAll("setName()");
}
/**
* <p>Sets the body text of the task
* and shows the state of the task afterwards.</p>
* @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()");
}
/** <p>Checks for task references.</p>
* @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;
}
/**
* <p>A central logging method that all the life-cycle methods call
* to display the state of the task.
* It displays the value of the <code>name</code> attribute
* and other information about the task,
* including the name of its project and its location in the build file.</p>
* @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);
}
}