/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.io.PrintStream; import java.lang.reflect.Method; import java.util.HashMap; import java.nio.file.Files; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.Vector; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildListener; import org.apache.tools.ant.DefaultLogger; import org.apache.tools.ant.MagicNames; import org.apache.tools.ant.Main; import org.apache.tools.ant.Project; import org.apache.tools.ant.ProjectComponent; import org.apache.tools.ant.ProjectHelper; import org.apache.tools.ant.Target; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.PropertySet; import org.apache.tools.ant.util.FileUtils; import org.apache.tools.ant.util.VectorSet; /** * Build a sub-project. * *
* <target name="foo" depends="init">
* <ant antfile="build.xml" target="bar" >
* <property name="property1" value="aaaaa" />
* <property name="foo" value="baz" />
* </ant>
* </target>
*
* <target name="bar" depends="init">
* <echo message="prop is ${property1} ${foo}" />
* </target>
*
*
*
* @since Ant 1.1
*
* @ant.task category="control"
*/
public class Ant extends Task {
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
/** the basedir where is executed the build file */
private File dir = null;
/**
* the build.xml file (can be absolute) in this case dir will be
* ignored
*/
private String antFile = null;
/** the output */
private String output = null;
/** should we inherit properties from the parent ? */
private boolean inheritAll = true;
/** should we inherit references from the parent ? */
private boolean inheritRefs = false;
/** the properties to pass to the new project */
private ListThis can happen if the same instance of this task is run * twice as newProject is set to null at the end of execute (to * save memory and help the GC).
*calls init() again
* */ private void reinit() { init(); } /** * Attaches the build listeners of the current project to the new * project, configures a possible logfile, transfers task and * data-type definitions, transfers properties (either all or just * the ones specified as user properties to the current project, * depending on inheritall), transfers the input handler. */ private void initializeProject() { newProject.setInputHandler(getProject().getInputHandler()); Iterator
* This function may be overridden by providers of custom ProjectHelper so they can easily
* implement their sublauncher.
*
* @return the name of the default file
* @since Ant 1.8.0
*/
protected String getDefaultBuildFile() {
return Main.DEFAULT_BUILD_FILENAME;
}
/**
* Override the properties in the new project with the one
* explicitly defined as nested elements here.
* @throws BuildException under unknown circumstances.
*/
private void overrideProperties() throws BuildException {
// remove duplicate properties - last property wins
// Needed for backward compatibility
Set If we cannot clone it, copy the referenced object itself and
* keep our fingers crossed.Hashtable to copy to the
* new project.
* @param type the type of property to set (a plain Ant property, a
* user property or an inherited property).
* @since Ant 1.8.0
*/
private void addAlmostAll(Map, ?> props, PropertyType type) {
props.forEach((k, v) -> {
String key = k.toString();
if (MagicNames.PROJECT_BASEDIR.equals(key)
|| MagicNames.ANT_FILE.equals(key)) {
// basedir and ant.file get special treatment in execute()
return;
}
String value = v.toString();
switch (type) {
case PLAIN:
// don't re-set user properties, avoid the warning message
if (newProject.getProperty(key) == null) {
// no user property
newProject.setNewProperty(key, value);
}
break;
case USER:
newProject.setUserProperty(key, value);
break;
case INHERITED:
newProject.setInheritedProperty(key, value);
break;
}
});
}
/**
* The directory to use as a base directory for the new Ant project.
* Defaults to the current project's basedir, unless inheritall
* has been set to false, in which case it doesn't have a default
* value. This will override the basedir setting of the called project.
* @param dir new directory as File.
*/
public void setDir(File dir) {
this.dir = dir;
}
/**
* The build file to use. Defaults to "build.xml". This file is expected
* to be a filename relative to the dir attribute given.
* @param antFile the String build file name.
*/
public void setAntfile(String antFile) {
// @note: it is a string and not a file to handle relative/absolute
// otherwise a relative file will be resolved based on the current
// basedir.
this.antFile = antFile;
}
/**
* The target of the new Ant project to execute.
* Defaults to the new project's default target.
* @param targetToAdd the name of the target to invoke.
*/
public void setTarget(String targetToAdd) {
if (targetToAdd.isEmpty()) {
throw new BuildException("target attribute must not be empty");
}
targets.add(targetToAdd);
targetAttributeSet = true;
}
/**
* Set the filename to write the output to. This is relative to the value
* of the dir attribute if it has been set or to the base directory of the
* current project otherwise.
* @param outputFile the name of the file to which the output should go.
*/
public void setOutput(String outputFile) {
this.output = outputFile;
}
/**
* Property to pass to the new project.
* The property is passed as a 'user property'.
* @return the created Property object.
*/
public Property createProperty() {
Property p = new Property(true, getProject());
p.setProject(getNewProject());
p.setTaskName("property");
properties.add(p);
return p;
}
/**
* Add a Reference element identifying a data type to carry
* over to the new project.
* @param ref Reference to add.
*/
public void addReference(Reference ref) {
references.add(ref);
}
/**
* Add a target to this Ant invocation.
* @param t the TargetElement to add.
* @since Ant 1.6.3
*/
public void addConfiguredTarget(TargetElement t) {
if (targetAttributeSet) {
throw new BuildException(
"nested target is incompatible with the target attribute");
}
String name = t.getName();
if (name.isEmpty()) {
throw new BuildException("target name must not be empty");
}
targets.add(name);
}
/**
* Add a set of properties to pass to the new project.
*
* @param ps PropertySet to add.
* @since Ant 1.6
*/
public void addPropertyset(PropertySet ps) {
propertySets.add(ps);
}
/**
* Get the (sub)-Project instance currently in use.
* @return Project
* @since Ant 1.7
*/
protected Project getNewProject() {
if (newProject == null) {
reinit();
}
return newProject;
}
/**
* @since Ant 1.6.2
*/
private IteratorString target name.
*/
public void setName(String name) {
this.name = name;
}
/**
* Get the name of this TargetElement.
* @return String.
*/
public String getName() {
return name;
}
}
private enum PropertyType {
PLAIN, INHERITED, USER
}
}