/* * Copyright 2003-2004 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.apache.tools.ant.taskdefs; import java.io.File; import java.io.IOException; import java.util.Vector; import java.util.Enumeration; import org.apache.tools.ant.Task; import org.apache.tools.ant.Project; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.DirSet; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.FileList; import org.apache.tools.ant.types.PropertySet; import org.apache.tools.ant.types.Reference; /** * Calls a given target for all defined sub-builds. This is an extension * of ant for bulk project execution. *
*
* subant can be used with directory sets to execute a build from different directories. * 2 different options are offered *
*failOnError is true. Otherwise,
* a warning log message is simply output.
*/
private void execute(File file, File directory)
throws BuildException {
if (!file.exists() || file.isDirectory() || !file.canRead()) {
String msg = "Invalid file: " + file;
if (failOnError) {
throw new BuildException(msg);
}
log(msg, Project.MSG_WARN);
return;
}
Ant ant = createAntTask(directory);
String antfilename = null;
try {
antfilename = file.getCanonicalPath();
} catch (IOException e) {
throw new BuildException(e);
}
ant.setAntfile(antfilename);
try {
ant.execute();
} catch (BuildException e) {
if (failOnError) {
throw e;
}
log("Failure for target '" + target
+ "' of: " + antfilename + "\n"
+ e.getMessage(), Project.MSG_WARN);
} catch (Throwable e) {
if (failOnError) {
throw new BuildException(e);
}
log("Failure for target '" + target
+ "' of: " + antfilename + "\n"
+ e.toString(),
Project.MSG_WARN);
}
}
/**
* This method builds the file name to use in conjunction with directories.
*
* Defaults to "build.xml".
* If genericantfile is set, this attribute is ignored.
Use genericantfile, in order to run the same build file
* with different basedirs.
antfile is ignored.
*
* @param afile (path of the generic ant file, absolute or relative to
* project base directory)
* */
public void setGenericAntfile(File afile) {
this.genericantfile = afile;
}
/**
* Sets whether to fail with a build exception on error, or go on.
*
* @param failOnError the new value for this boolean flag.
*/
public void setFailonerror(boolean failOnError) {
this.failOnError = failOnError;
}
/**
* The target to call on the different sub-builds. Set to "" to execute
* the default target.
* @param target the target
*
*/
// REVISIT: Defaults to the target name that contains this task if not specified.
public void setTarget(String target) {
this.target = target;
}
/**
* Corresponds to <ant>'s
* output attribute.
*
* @param s the filename to write the output to.
*/
public void setOutput(String s) {
this.output = s;
}
/**
* Corresponds to <ant>'s
* inheritall attribute.
*
* @param b the new value for this boolean flag.
*/
public void setInheritall(boolean b) {
this.inheritAll = b;
}
/**
* Corresponds to <ant>'s
* inheritrefs attribute.
*
* @param b the new value for this boolean flag.
*/
public void setInheritrefs(boolean b) {
this.inheritRefs = b;
}
/**
* Corresponds to <ant>'s
* nested <property> element.
*
* @param p the property to pass on explicitly to the sub-build.
*/
public void addProperty(Property p) {
properties.addElement(p);
}
/**
* Corresponds to <ant>'s
* nested <reference> element.
*
* @param r the reference to pass on explicitly to the sub-build.
*/
public void addReference(Ant.Reference r) {
references.addElement(r);
}
/**
* Corresponds to <ant>'s
* nested <propertyset> element.
* @param ps the propertset
*/
public void addPropertyset(PropertySet ps) {
propertySets.addElement(ps);
}
/**
* Adds a directory set to the implicit build path.
*
* Note that the directories will be added to the build path * in no particular order, so if order is significant, one should * use a file list instead! * * @param set the directory set to add. */ public void addDirset(DirSet set) { getBuildpath().addDirset(set); } /** * Adds a file set to the implicit build path. *
* Note that the directories will be added to the build path * in no particular order, so if order is significant, one should * use a file list instead! * * @param set the file set to add. */ public void addFileset(FileSet set) { getBuildpath().addFileset(set); } /** * Adds an ordered file list to the implicit build path. *
* Note that contrary to file and directory sets, file lists
* can reference non-existent files or directories!
*
* @param list the file list to add.
*/
public void addFilelist(FileList list) {
getBuildpath().addFilelist(list);
}
/**
* Set the buildpath to be used to find sub-projects.
*
* @param s an Ant Path object containing the buildpath.
*/
public void setBuildpath(Path s) {
getBuildpath().append(s);
}
/**
* Creates a nested build path, and add it to the implicit build path.
*
* @return the newly created nested build path.
*/
public Path createBuildpath() {
return getBuildpath().createPath();
}
/**
* Creates a nested <buildpathelement>,
* and add it to the implicit build path.
*
* @return the newly created nested build path element.
*/
public Path.PathElement createBuildpathElement() {
return getBuildpath().createPathElement();
}
/**
* Gets the implicit build path, creating it if null.
*
* @return the implicit build path.
*/
private Path getBuildpath() {
if (buildpath == null) {
buildpath = new Path(getProject());
}
return buildpath;
}
/**
* Buildpath to use, by reference.
*
* @param r a reference to an Ant Path object containing the buildpath.
*/
public void setBuildpathRef(Reference r) {
createBuildpath().setRefid(r);
}
/**
* Creates the <ant> task configured to run a specific target.
*
* @param directory : if not null the directory where the build should run
*
* @return the ant task, configured with the explicit properties and
* references necessary to run the sub-build.
*/
private Ant createAntTask(File directory) {
Ant ant = (Ant) getProject().createTask("ant");
ant.setOwningTarget(getOwningTarget());
ant.setTaskName(getTaskName());
ant.init();
if (target != null && target.length() > 0) {
ant.setTarget(target);
}
if (output != null) {
ant.setOutput(output);
}
if (directory != null) {
ant.setDir(directory);
}
ant.setInheritAll(inheritAll);
for (Enumeration i = properties.elements(); i.hasMoreElements();) {
copyProperty(ant.createProperty(), (Property) i.nextElement());
}
for (Enumeration i = propertySets.elements(); i.hasMoreElements();) {
ant.addPropertyset((PropertySet) i.nextElement());
}
ant.setInheritRefs(inheritRefs);
for (Enumeration i = references.elements(); i.hasMoreElements();) {
ant.addReference((Ant.Reference) i.nextElement());
}
return ant;
}
/**
* Assigns an Ant property to another.
*
* @param to the destination property whose content is modified.
* @param from the source property whose content is copied.
*/
private static void copyProperty(Property to, Property from) {
to.setName(from.getName());
if (from.getValue() != null) {
to.setValue(from.getValue());
}
if (from.getFile() != null) {
to.setFile(from.getFile());
}
if (from.getResource() != null) {
to.setResource(from.getResource());
}
if (from.getPrefix() != null) {
to.setPrefix(from.getPrefix());
}
if (from.getRefid() != null) {
to.setRefid(from.getRefid());
}
if (from.getEnvironment() != null) {
to.setEnvironment(from.getEnvironment());
}
if (from.getClasspath() != null) {
to.setClasspath(from.getClasspath());
}
}
} // END class SubAnt