git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@713016 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -519,6 +519,9 @@ Other changes: | |||||
| * <import> has a new attribute "as" that can be used to control the | * <import> has a new attribute "as" that can be used to control the | ||||
| prefix prepended to the imported target's names. | prefix prepended to the imported target's names. | ||||
| * a new task <include> provides an alternative to <import> that | |||||
| should be preferred when you don't want to override any targets. | |||||
| Changes from Ant 1.7.0 TO Ant 1.7.1 | Changes from Ant 1.7.0 TO Ant 1.7.1 | ||||
| ============================================= | ============================================= | ||||
| @@ -27,6 +27,14 @@ | |||||
| <p> | <p> | ||||
| Imports another build file into the current project. | Imports another build file into the current project. | ||||
| </p> | </p> | ||||
| <p> | |||||
| <b>Note</b> this task heavily relies on the ProjectHelper | |||||
| implementation and doesn't really perform any work of its own. If | |||||
| you have configured Ant to use a ProjectHelper other than Ant's | |||||
| default, this task may or may not work. | |||||
| </p> | |||||
| <p> | <p> | ||||
| On execution it will read another Ant file into | On execution it will read another Ant file into | ||||
| the same Project. This means that it basically works like the | the same Project. This means that it basically works like the | ||||
| @@ -83,7 +91,7 @@ property of the main buildfile.</p> | |||||
| <p>Note that "builddocs" is not the filename, but the name attribute | <p>Note that "builddocs" is not the filename, but the name attribute | ||||
| present in the imported project tag.</p> | present in the imported project tag.</p> | ||||
| <p> | <p> | ||||
| If import file does not have a name attribute, the ant.file.projectname | |||||
| If the imported file does not have a name attribute, the ant.file.projectname | |||||
| property will not be set. | property will not be set. | ||||
| </p> | </p> | ||||
| @@ -182,6 +190,89 @@ directory.</p> | |||||
| <p>Imports the project defined by the property deploy-platform</p> | <p>Imports the project defined by the property deploy-platform</p> | ||||
| <h3>How is <import> different | |||||
| from <a href="include.html"><include></a>?</h3> | |||||
| <p>When using import the imported targets are available by up to two | |||||
| names. Their "normal" name without any prefix and potentially with | |||||
| a prefixed name (the value of the as attribute or the imported | |||||
| project's name attribute, if any).</p> | |||||
| <p>When using include the included targets are only available in the | |||||
| prefixed form.</p> | |||||
| <p>When using import, the imported target's depends attribute | |||||
| remains unchanged, i.e. it uses "normal" names and allows you to | |||||
| override targets in the dependency list.</p> | |||||
| <p>When using include, the included target's depends attribute is | |||||
| rewritten so that prefixed names are used. This allows writers of | |||||
| the included file to control which target is invoked as part of the | |||||
| dependencies.</p> | |||||
| <p>It is possible to include the same file more than once by using | |||||
| different prefixes, it is not possible to import the same file more | |||||
| than once.</p> | |||||
| <p>Use import if you intend to override a target, otherwise use include.</p> | |||||
| <p><i>nested.xml</i> shall be:</p> | |||||
| <pre> | |||||
| <project> | |||||
| <target name="setUp"> | |||||
| <property name="prop" value="in nested"/> | |||||
| </target> | |||||
| <target name="echo" depends="setUp"> | |||||
| <echo>prop has the value ${prop}</echo> | |||||
| </target> | |||||
| </project> | |||||
| </pre> | |||||
| <p>When using import like in</p> | |||||
| <pre> | |||||
| <project> | |||||
| <target name="setUp"> | |||||
| <property name="prop" value="in importing"/> | |||||
| </target> | |||||
| <import file="nested.xml" as="nested"/> | |||||
| </project> | |||||
| </pre> | |||||
| <p>Running the target <i>nested.echo</i> will emit: | |||||
| <pre> | |||||
| setUp: | |||||
| nested.echo: | |||||
| [echo] prop has the value in importing | |||||
| </pre> | |||||
| <p>When using include like in</p> | |||||
| <pre> | |||||
| <project> | |||||
| <target name="setUp"> | |||||
| <property name="prop" value="in importing"/> | |||||
| </target> | |||||
| <include file="nested.xml" as="nested"/> | |||||
| </project> | |||||
| </pre> | |||||
| <p>Running the target <i>nested.echo</i> will emit: | |||||
| <pre> | |||||
| nested.setUp: | |||||
| nested.echo: | |||||
| [echo] prop has the value in nested | |||||
| </pre> | |||||
| <p>and there won't be any target named "echo" on the including build file.</p> | |||||
| </body> | </body> | ||||
| </html> | </html> | ||||
| @@ -0,0 +1,274 @@ | |||||
| <!-- | |||||
| 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. | |||||
| --> | |||||
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | |||||
| <html> | |||||
| <head> | |||||
| <meta http-equiv="Content-Language" content="en-us"> | |||||
| <link rel="stylesheet" type="text/css" href="../stylesheets/style.css"> | |||||
| <title>Include Task</title> | |||||
| </head> | |||||
| <body> | |||||
| <h2><a name="include">Include</a></h2> | |||||
| <h3>Description</h3> | |||||
| <p> | |||||
| Include another build file into the current project. | |||||
| </p> | |||||
| <p> | |||||
| <b>Note</b> this task heavily relies on the ProjectHelper | |||||
| implementation and doesn't really perform any work of its own. If | |||||
| you have configured Ant to use a ProjectHelper other than Ant's | |||||
| default, this task may or may not work. | |||||
| </p> | |||||
| <p> | |||||
| On execution it will read another Ant file into the same Project | |||||
| rewriting the included target names and depends lists. This is | |||||
| different | |||||
| from <a href="http://ant.apache.org/faq.html#xml-entity-include">Entity | |||||
| Includes as explained in the Ant FAQ</a> in so far as the target | |||||
| names get prefixed by the included project's name or the as | |||||
| attribute and do not appear as if the file was contained in the | |||||
| including file. | |||||
| </p> | |||||
| <p> | |||||
| The include task may only be used as a top-level task. This means that | |||||
| it may not be used in a target. | |||||
| </p> | |||||
| <p> | |||||
| There are two further functional aspects that pertain to this task and | |||||
| that are not possible with entity includes: | |||||
| <ul> | |||||
| <li>target rewriting</li> | |||||
| <li>special properties</li> | |||||
| </ul> | |||||
| </p> | |||||
| <h4>Target rewriting</h4> | |||||
| <p>Any target in the included file will be renamed | |||||
| to <i>prefix.name</i> where <i>name</i> is the original target's | |||||
| name and <i>prefix</i> is either the value of the <i>as</i> | |||||
| attribute or the <i>name</i> attribute of the <i>project</i> tag of | |||||
| the included file.</p> | |||||
| <p>The depends attribute of all included targets is rewritten so that | |||||
| all target names are prefixed as well. This makes the included file | |||||
| self-contained.</p> | |||||
| <h4>Special Properties</h4> | |||||
| <p>Included files are treated as they are present in the main | |||||
| buildfile. This makes it easy to understand, but it makes it impossible | |||||
| for them to reference files and resources relative to their path. | |||||
| Because of this, for every included file, Ant adds a property that | |||||
| contains the path to the included buildfile. With this path, the | |||||
| included buildfile can keep resources and be able to reference them | |||||
| relative to its position.</p> | |||||
| <p>So if I include for example a <i>docsbuild.xml</i> file named <b>builddocs</b>, | |||||
| I can get its path as <b>ant.file.builddocs</b>, similarly to the <b>ant.file</b> | |||||
| property of the main buildfile.</p> | |||||
| <p>Note that "builddocs" is not the filename, but the name attribute | |||||
| present in the included project tag.</p> | |||||
| <p> | |||||
| If the included file does not have a name attribute, the ant.file.projectname | |||||
| property will not be set. | |||||
| </p> | |||||
| <h4>Resolving files against the included file</h4> | |||||
| <p>Suppose your main build file called <code>including.xml</code> | |||||
| includes a build file <code>included.xml</code>, located anywhere on | |||||
| the file system, and <code>included.xml</code> reads a set of | |||||
| properties from <code>included.properties</code>:</p> | |||||
| <pre><!-- including.xml --> | |||||
| <project name="including" basedir="." default="..."> | |||||
| <include file="${path_to_included}/included.xml"/> | |||||
| </project> | |||||
| <!-- included.xml --> | |||||
| <project name="included" basedir="." default="..."> | |||||
| <property file="included.properties"/> | |||||
| </project> | |||||
| </pre> | |||||
| <p>This snippet however will resolve <code>included.properties</code> | |||||
| against the basedir of <code>including.xml</code>, because the basedir | |||||
| of <code>included.xml</code> is ignored by Ant. The right way to use | |||||
| <code>included.properties</code> is:</p> | |||||
| <pre> | |||||
| <!-- included.xml --> | |||||
| <project name="included" basedir="." default="..."> | |||||
| <dirname property="included.basedir" file="${ant.file.included}"/> | |||||
| <property file="${included.basedir}/included.properties"/> | |||||
| </project> | |||||
| </pre> | |||||
| <p>As explained above <code>${ant.file.included}</code> stores the | |||||
| path of the build script, that defines the project called | |||||
| <code>included</code>, (in short it stores the path to | |||||
| <code>included.xml</code>) and <a | |||||
| href="dirname.html"><code><dirname></code></a> takes its | |||||
| directory. This technique also allows <code>included.xml</code> to be | |||||
| used as a standalone file (without being included in other | |||||
| project).</p> | |||||
| <h3>Parameters</h3> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tbody> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top"> | |||||
| file | |||||
| </td> | |||||
| <td valign="top"> | |||||
| The file to include. If this is a relative file name, the file name will be resolved | |||||
| relative to the <i>including</i> file. <b>Note</b>, this is unlike most other | |||||
| ant file attributes, where relative files are resolved relative to ${basedir}. | |||||
| </td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top"> | |||||
| optional | |||||
| </td> | |||||
| <td valign="top"> | |||||
| If true, do not stop the build if the file does not exist, | |||||
| default is false. | |||||
| </td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top"> | |||||
| as | |||||
| </td> | |||||
| <td valign="top"> | |||||
| Specifies the prefix prepended to the target names. If | |||||
| ommitted, the name attribute of the project tag of the | |||||
| imported file will be used. | |||||
| </td> | |||||
| <td valign="top" align="center">Yes, if the included file's | |||||
| project tag doesn't specify a name attribute.</td> | |||||
| </tr> | |||||
| </tbody> | |||||
| </table> | |||||
| <h3>Examples</h3> | |||||
| <pre> <include file="../common-targets.xml"/> | |||||
| </pre> | |||||
| <p>Includes targets from the common-targets.xml file that is in a parent | |||||
| directory.</p> | |||||
| <pre> <include file="${deploy-platform}.xml"/> | |||||
| </pre> | |||||
| <p>Includes the project defined by the property deploy-platform</p> | |||||
| <h3>How is <a href="import.html"><import></a> different | |||||
| from <include>?</h3> | |||||
| <p>When using import the imported targets are available by up to two | |||||
| names. Their "normal" name without any prefix and potentially with | |||||
| a prefixed name (the value of the as attribute or the imported | |||||
| project's name attribute, if any).</p> | |||||
| <p>When using include the included targets are only available in the | |||||
| prefixed form.</p> | |||||
| <p>When using import, the imported target's depends attribute | |||||
| remains unchanged, i.e. it uses "normal" names and allows you to | |||||
| override targets in the dependency list.</p> | |||||
| <p>When using include, the included target's depends attribute is | |||||
| rewritten so that prefixed names are used. This allows writers of | |||||
| the included file to control which target is invoked as part of the | |||||
| dependencies.</p> | |||||
| <p>It is possible to include the same file more than once by using | |||||
| different prefixes, it is not possible to import the same file more | |||||
| than once.</p> | |||||
| <p>Use import if you intend to override a target, otherwise use include.</p> | |||||
| <p><i>nested.xml</i> shall be:</p> | |||||
| <pre> | |||||
| <project> | |||||
| <target name="setUp"> | |||||
| <property name="prop" value="in nested"/> | |||||
| </target> | |||||
| <target name="echo" depends="setUp"> | |||||
| <echo>prop has the value ${prop}</echo> | |||||
| </target> | |||||
| </project> | |||||
| </pre> | |||||
| <p>When using import like in</p> | |||||
| <pre> | |||||
| <project> | |||||
| <target name="setUp"> | |||||
| <property name="prop" value="in importing"/> | |||||
| </target> | |||||
| <import file="nested.xml" as="nested"/> | |||||
| </project> | |||||
| </pre> | |||||
| <p>Running the target <i>nested.echo</i> will emit: | |||||
| <pre> | |||||
| setUp: | |||||
| nested.echo: | |||||
| [echo] prop has the value in importing | |||||
| </pre> | |||||
| <p>When using include like in</p> | |||||
| <pre> | |||||
| <project> | |||||
| <target name="setUp"> | |||||
| <property name="prop" value="in importing"/> | |||||
| </target> | |||||
| <include file="nested.xml" as="nested"/> | |||||
| </project> | |||||
| </pre> | |||||
| <p>Running the target <i>nested.echo</i> will emit: | |||||
| <pre> | |||||
| nested.setUp: | |||||
| nested.echo: | |||||
| [echo] prop has the value in nested | |||||
| </pre> | |||||
| <p>and there won't be any target named "echo" on the including build file.</p> | |||||
| </body> | |||||
| </html> | |||||
| @@ -77,6 +77,7 @@ | |||||
| <a href="CoreTasks/unpack.html">GUnzip</a><br/> | <a href="CoreTasks/unpack.html">GUnzip</a><br/> | ||||
| <a href="CoreTasks/pack.html">GZip</a><br/> | <a href="CoreTasks/pack.html">GZip</a><br/> | ||||
| <a href="CoreTasks/import.html">Import</a><br/> | <a href="CoreTasks/import.html">Import</a><br/> | ||||
| <a href="CoreTasks/include.html">Include</a><br/> | |||||
| <a href="CoreTasks/input.html">Input</a><br/> | <a href="CoreTasks/input.html">Input</a><br/> | ||||
| <a href="CoreTasks/jar.html">Jar</a><br/> | <a href="CoreTasks/jar.html">Jar</a><br/> | ||||
| <a href="CoreTasks/java.html">Java</a><br/> | <a href="CoreTasks/java.html">Java</a><br/> | ||||
| @@ -843,6 +843,11 @@ documentation.</p> | |||||
| in it with targets of your own.</p></td> | in it with targets of your own.</p></td> | ||||
| </tr> | </tr> | ||||
| <tr valign="top"> | |||||
| <td nowrap><a href="CoreTasks/include.html">Include</a></td> | |||||
| <td><p>Include another build file.</p></td> | |||||
| </tr> | |||||
| <tr valign="top"> | <tr valign="top"> | ||||
| <td nowrap><a href="OptionalTasks/javacc.html">JavaCC</a></td> | <td nowrap><a href="OptionalTasks/javacc.html">JavaCC</a></td> | ||||
| <td><p>Invokes the | <td><p>Invokes the | ||||
| @@ -128,7 +128,7 @@ public class ProjectHelper { | |||||
| * | * | ||||
| * @return the configured prefix or null | * @return the configured prefix or null | ||||
| * | * | ||||
| * @since ant 1.8.0 | |||||
| * @since Ant 1.8.0 | |||||
| */ | */ | ||||
| public static String getCurrentTargetPrefix() { | public static String getCurrentTargetPrefix() { | ||||
| return (String) targetPrefix.get(); | return (String) targetPrefix.get(); | ||||
| @@ -137,12 +137,47 @@ public class ProjectHelper { | |||||
| /** | /** | ||||
| * Sets the prefix to prepend to imported target names. | * Sets the prefix to prepend to imported target names. | ||||
| * | * | ||||
| * @since ant 1.8.0 | |||||
| * @since Ant 1.8.0 | |||||
| */ | */ | ||||
| public static void setCurrentTargetPrefix(String prefix) { | public static void setCurrentTargetPrefix(String prefix) { | ||||
| targetPrefix.set(prefix); | targetPrefix.set(prefix); | ||||
| } | } | ||||
| private final static ThreadLocal inIncludeMode = new ThreadLocal() { | |||||
| protected Object initialValue() { | |||||
| return Boolean.FALSE; | |||||
| } | |||||
| }; | |||||
| /** | |||||
| * Whether the current file should be read in include as opposed | |||||
| * to import mode. | |||||
| * | |||||
| * <p>In include mode included targets are only known by their | |||||
| * prefixed names and their depends lists get rewritten so that | |||||
| * all dependencies get the prefix as well.</p> | |||||
| * | |||||
| * <p>In import mode imported targets are known by an adorned as | |||||
| * well as a prefixed name and the unadorned target may be | |||||
| * overwritten in the importing build file. The depends list of | |||||
| * the imported targets is not modified at all.</p> | |||||
| * | |||||
| * @since Ant 1.8.0 | |||||
| */ | |||||
| public static boolean isInIncludeMode() { | |||||
| return inIncludeMode.get() == Boolean.TRUE; | |||||
| } | |||||
| /** | |||||
| * Sets whether the current file should be read in include as | |||||
| * opposed to import mode. | |||||
| * | |||||
| * @since Ant 1.8.0 | |||||
| */ | |||||
| public static void setInIncludeMode(boolean includeMode) { | |||||
| inIncludeMode.set(includeMode ? Boolean.TRUE : Boolean.FALSE); | |||||
| } | |||||
| // -------------------- Parse method -------------------- | // -------------------- Parse method -------------------- | ||||
| /** | /** | ||||
| * Parses the project file, configuring the project as it goes. | * Parses the project file, configuring the project as it goes. | ||||
| @@ -125,19 +125,31 @@ public class Target implements TaskContainer { | |||||
| * depends on. Must not be <code>null</code>. | * depends on. Must not be <code>null</code>. | ||||
| */ | */ | ||||
| public void setDepends(String depS) { | public void setDepends(String depS) { | ||||
| if (depS.length() > 0) { | |||||
| for (Iterator iter = parseDepends(depS, getName()).iterator(); | |||||
| iter.hasNext(); ) { | |||||
| addDependency((String) iter.next()); | |||||
| } | |||||
| } | |||||
| public static List/*<String>*/ parseDepends(String depends, | |||||
| String targetName) { | |||||
| ArrayList list = new ArrayList(); | |||||
| if (depends.length() > 0) { | |||||
| StringTokenizer tok = | StringTokenizer tok = | ||||
| new StringTokenizer(depS, ",", true); | |||||
| new StringTokenizer(depends, ",", true); | |||||
| while (tok.hasMoreTokens()) { | while (tok.hasMoreTokens()) { | ||||
| String token = tok.nextToken().trim(); | String token = tok.nextToken().trim(); | ||||
| // Make sure the dependency is not empty string | // Make sure the dependency is not empty string | ||||
| if ("".equals(token) || ",".equals(token)) { | if ("".equals(token) || ",".equals(token)) { | ||||
| throw new BuildException("Syntax Error: depends " + "attribute of target \"" | |||||
| + getName() + "\" has an empty string as dependency."); | |||||
| throw new BuildException("Syntax Error: depends " | |||||
| + "attribute of target \"" | |||||
| + targetName | |||||
| + "\" has an empty string as " | |||||
| + "dependency."); | |||||
| } | } | ||||
| addDependency(token); | |||||
| list.add(token); | |||||
| // Make sure that depends attribute does not | // Make sure that depends attribute does not | ||||
| // end in a , | // end in a , | ||||
| @@ -145,12 +157,15 @@ public class Target implements TaskContainer { | |||||
| token = tok.nextToken(); | token = tok.nextToken(); | ||||
| if (!tok.hasMoreTokens() || !",".equals(token)) { | if (!tok.hasMoreTokens() || !",".equals(token)) { | ||||
| throw new BuildException("Syntax Error: Depend " | throw new BuildException("Syntax Error: Depend " | ||||
| + "attribute for target \"" + getName() | |||||
| + "\" ends with a , character"); | |||||
| + "attribute for target \"" | |||||
| + targetName | |||||
| + "\" ends with a \",\" " | |||||
| + "character"); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return list; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -45,6 +45,7 @@ import java.io.UnsupportedEncodingException; | |||||
| import java.net.URL; | import java.net.URL; | ||||
| import java.util.HashMap; | import java.util.HashMap; | ||||
| import java.util.Hashtable; | import java.util.Hashtable; | ||||
| import java.util.Iterator; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| import java.util.Stack; | import java.util.Stack; | ||||
| @@ -845,9 +846,25 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
| context.getLocator()); | context.getLocator()); | ||||
| } | } | ||||
| String prefix = null; | |||||
| boolean isInIncludeMode = | |||||
| context.isIgnoringProjectTag() && isInIncludeMode(); | |||||
| if (isInIncludeMode) { | |||||
| prefix = getTargetPrefix(context); | |||||
| if (prefix == null) { | |||||
| throw new BuildException("can't include build file " | |||||
| + context.getBuildFile() | |||||
| + ", no as attribute has been given" | |||||
| + " and the project tag doesn't" | |||||
| + " specify a name attribute"); | |||||
| } | |||||
| name = prefix + "." + name; | |||||
| } | |||||
| // Check if this target is in the current build file | // Check if this target is in the current build file | ||||
| if (context.getCurrentTargets().get(name) != null) { | if (context.getCurrentTargets().get(name) != null) { | ||||
| throw new BuildException("Duplicate target '" + name + "'", target.getLocation()); | |||||
| throw new BuildException("Duplicate target '" + name + "'", | |||||
| target.getLocation()); | |||||
| } | } | ||||
| Hashtable projectTargets = project.getTargets(); | Hashtable projectTargets = project.getTargets(); | ||||
| boolean usedTarget = false; | boolean usedTarget = false; | ||||
| @@ -862,12 +879,19 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
| usedTarget = true; | usedTarget = true; | ||||
| } | } | ||||
| if (depends.length() > 0) { | if (depends.length() > 0) { | ||||
| target.setDepends(depends); | |||||
| if (!isInIncludeMode) { | |||||
| target.setDepends(depends); | |||||
| } else { | |||||
| for (Iterator iter = | |||||
| Target.parseDepends(depends, name).iterator(); | |||||
| iter.hasNext(); ) { | |||||
| target.addDependency(prefix + "." + iter.next()); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| String prefix = null; | |||||
| if (context.isIgnoringProjectTag() | |||||
| if (!isInIncludeMode && context.isIgnoringProjectTag() | |||||
| && (prefix = getTargetPrefix(context)) != null) { | && (prefix = getTargetPrefix(context)) != null) { | ||||
| // In an impored file (and not completely | |||||
| // In an imported file (and not completely | |||||
| // ignoring the project tag or having a preconfigured prefix) | // ignoring the project tag or having a preconfigured prefix) | ||||
| String newName = prefix + "." + name; | String newName = prefix + "." + name; | ||||
| Target newTarget = usedTarget ? new Target(target) : target; | Target newTarget = usedTarget ? new Target(target) : target; | ||||
| @@ -145,7 +145,7 @@ public class ImportTask extends Task { | |||||
| } | } | ||||
| } | } | ||||
| if (importStack.contains(importedFile)) { | |||||
| if (!isInIncludeMode() && importStack.contains(importedFile)) { | |||||
| getProject().log( | getProject().log( | ||||
| "Skipped already imported file:\n " | "Skipped already imported file:\n " | ||||
| + importedFile + "\n", Project.MSG_VERBOSE); | + importedFile + "\n", Project.MSG_VERBOSE); | ||||
| @@ -155,14 +155,36 @@ public class ImportTask extends Task { | |||||
| // nested invokations are possible like an imported file | // nested invokations are possible like an imported file | ||||
| // importing another one | // importing another one | ||||
| String oldPrefix = ProjectHelper.getCurrentTargetPrefix(); | String oldPrefix = ProjectHelper.getCurrentTargetPrefix(); | ||||
| boolean oldIncludeMode = ProjectHelper.isInIncludeMode(); | |||||
| try { | try { | ||||
| ProjectHelper.setCurrentTargetPrefix(targetPrefix); | ProjectHelper.setCurrentTargetPrefix(targetPrefix); | ||||
| ProjectHelper.setInIncludeMode(isInIncludeMode()); | |||||
| helper.parse(getProject(), importedFile); | helper.parse(getProject(), importedFile); | ||||
| } catch (BuildException ex) { | } catch (BuildException ex) { | ||||
| throw ProjectHelper.addLocationToBuildException( | throw ProjectHelper.addLocationToBuildException( | ||||
| ex, getLocation()); | ex, getLocation()); | ||||
| } finally { | } finally { | ||||
| ProjectHelper.setCurrentTargetPrefix(oldPrefix); | ProjectHelper.setCurrentTargetPrefix(oldPrefix); | ||||
| ProjectHelper.setInIncludeMode(oldIncludeMode); | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Whether the task is in include (as opposed to import) mode. | |||||
| * | |||||
| * <p>In include mode included targets are only known by their | |||||
| * prefixed names and their depends lists get rewritten so that | |||||
| * all dependencies get the prefix as well.</p> | |||||
| * | |||||
| * <p>In import mode imported targets are known by an adorned as | |||||
| * well as a prefixed name and the unadorned target may be | |||||
| * overwritten in the importing build file. The depends list of | |||||
| * the imported targets is not modified at all.</p> | |||||
| * | |||||
| * @since Ant 1.8.0 | |||||
| */ | |||||
| protected final boolean isInIncludeMode() { | |||||
| return "include".equals(getTaskType()); | |||||
| } | |||||
| } | } | ||||
| @@ -56,6 +56,7 @@ get=org.apache.tools.ant.taskdefs.Get | |||||
| gunzip=org.apache.tools.ant.taskdefs.GUnzip | gunzip=org.apache.tools.ant.taskdefs.GUnzip | ||||
| gzip=org.apache.tools.ant.taskdefs.GZip | gzip=org.apache.tools.ant.taskdefs.GZip | ||||
| import=org.apache.tools.ant.taskdefs.ImportTask | import=org.apache.tools.ant.taskdefs.ImportTask | ||||
| include=org.apache.tools.ant.taskdefs.ImportTask | |||||
| input=org.apache.tools.ant.taskdefs.Input | input=org.apache.tools.ant.taskdefs.Input | ||||
| jar=org.apache.tools.ant.taskdefs.Jar | jar=org.apache.tools.ant.taskdefs.Jar | ||||
| java=org.apache.tools.ant.taskdefs.Java | java=org.apache.tools.ant.taskdefs.Java | ||||
| @@ -28,4 +28,22 @@ | |||||
| <target name="testExplicitPrefix" depends="c.b"> | <target name="testExplicitPrefix" depends="c.b"> | ||||
| <au:assertEquals expected="baz" actual="${foo}"/> | <au:assertEquals expected="baz" actual="${foo}"/> | ||||
| </target> | </target> | ||||
| <target name="testNoExplicitPrefixUsedWithoutPrefix" depends="a"> | |||||
| <au:assertEquals expected="bar" actual="${foo}"/> | |||||
| </target> | |||||
| <target name="testExplicitPrefixUsedWithoutPrefix" depends="b"> | |||||
| <au:assertEquals expected="baz" actual="${foo}"/> | |||||
| </target> | |||||
| <import file="importtests/override.xml"/> | |||||
| <target name="setProperty"> | |||||
| <property name="prop" value="in including/importing"/> | |||||
| </target> | |||||
| <target name="testOverride" depends="override.dummy"> | |||||
| <au:assertEquals expected="in including/importing" actual="${prop}"/> | |||||
| </target> | |||||
| </project> | </project> | ||||
| @@ -0,0 +1,25 @@ | |||||
| <?xml version="1.0"?> | |||||
| <!-- | |||||
| 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. | |||||
| --> | |||||
| <project name="override"> | |||||
| <target name="setProperty"> | |||||
| <property name="prop" value="in included/imported"/> | |||||
| </target> | |||||
| <target name="dummy" depends="setProperty"/> | |||||
| </project> | |||||
| @@ -0,0 +1,41 @@ | |||||
| <?xml version="1.0"?> | |||||
| <!-- | |||||
| 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. | |||||
| --> | |||||
| <project default="antunit" xmlns:au="antlib:org.apache.ant.antunit"> | |||||
| <import file="../antunit-base.xml" /> | |||||
| <include file="importtests/a.xml"/> | |||||
| <include file="importtests/b.xml" as="c"/> | |||||
| <target name="testNoExplicitPrefix" depends="a.a"> | |||||
| <au:assertEquals expected="bar" actual="${foo}"/> | |||||
| </target> | |||||
| <target name="testExplicitPrefix" depends="c.b"> | |||||
| <au:assertEquals expected="baz" actual="${foo}"/> | |||||
| </target> | |||||
| <include file="importtests/override.xml"/> | |||||
| <target name="setProperty"> | |||||
| <property name="prop" value="in including/importing"/> | |||||
| </target> | |||||
| <target name="testNoOverride" depends="override.dummy"> | |||||
| <au:assertEquals expected="in included/imported" actual="${prop}"/> | |||||
| </target> | |||||
| </project> | |||||