git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@713373 13f79535-47bb-0310-9956-ffa450edef68master
@@ -516,8 +516,9 @@ Other changes: | |||||
STARTTLS. | STARTTLS. | ||||
Bugzilla Report 46063. | Bugzilla Report 46063. | ||||
* <import> has a new attribute "as" that can be used to control the | |||||
prefix prepended to the imported target's names. | |||||
* <import> has new attributes "as" and "prefixSeparator" that can be | |||||
used to control the prefix prepended to the imported target's | |||||
names. | |||||
* a new task <include> provides an alternative to <import> that | * a new task <include> provides an alternative to <import> that | ||||
should be preferred when you don't want to override any targets. | should be preferred when you don't want to override any targets. | ||||
@@ -175,6 +175,16 @@ project).</p> | |||||
</td> | </td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top"> | |||||
prefixSeparator | |||||
</td> | |||||
<td valign="top"> | |||||
Specifies the separator to be used between the prefix and the | |||||
target name. Defaults to ".". | |||||
</td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
@@ -69,6 +69,11 @@ that are not possible with entity includes: | |||||
all target names are prefixed as well. This makes the included file | all target names are prefixed as well. This makes the included file | ||||
self-contained.</p> | self-contained.</p> | ||||
<p>Note that prefixes nest, so if a build file includes a file with | |||||
prefix "a" and the included file includes another file with prefix | |||||
"b", then the targets of that last build file will be prefixed by | |||||
"a.b.".</p> | |||||
<h4>Special Properties</h4> | <h4>Special Properties</h4> | ||||
<p>Included files are treated as they are present in the main | <p>Included files are treated as they are present in the main | ||||
@@ -171,6 +176,16 @@ project).</p> | |||||
<td valign="top" align="center">Yes, if the included file's | <td valign="top" align="center">Yes, if the included file's | ||||
project tag doesn't specify a name attribute.</td> | project tag doesn't specify a name attribute.</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top"> | |||||
prefixSeparator | |||||
</td> | |||||
<td valign="top"> | |||||
Specifies the separator to be used between the prefix and the | |||||
target name. Defaults to ".". | |||||
</td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
@@ -143,6 +143,32 @@ public class ProjectHelper { | |||||
targetPrefix.set(prefix); | targetPrefix.set(prefix); | ||||
} | } | ||||
private final static ThreadLocal prefixSeparator = new ThreadLocal() { | |||||
protected Object initialValue() { | |||||
return "."; | |||||
} | |||||
}; | |||||
/** | |||||
* The separator between the prefix and the target name. | |||||
* | |||||
* <p>May be set by <import>'s prefixSeperator attribute.</p> | |||||
* | |||||
* @since Ant 1.8.0 | |||||
*/ | |||||
public static String getCurrentPrefixSeparator() { | |||||
return (String) prefixSeparator.get(); | |||||
} | |||||
/** | |||||
* Sets the separator between the prefix and the target name. | |||||
* | |||||
* @since Ant 1.8.0 | |||||
*/ | |||||
public static void setCurrentPrefixSeparator(String sep) { | |||||
prefixSeparator.set(sep); | |||||
} | |||||
private final static ThreadLocal inIncludeMode = new ThreadLocal() { | private final static ThreadLocal inIncludeMode = new ThreadLocal() { | ||||
protected Object initialValue() { | protected Object initialValue() { | ||||
return Boolean.FALSE; | return Boolean.FALSE; | ||||
@@ -849,6 +849,8 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
String prefix = null; | String prefix = null; | ||||
boolean isInIncludeMode = | boolean isInIncludeMode = | ||||
context.isIgnoringProjectTag() && isInIncludeMode(); | context.isIgnoringProjectTag() && isInIncludeMode(); | ||||
String sep = getCurrentPrefixSeparator(); | |||||
if (isInIncludeMode) { | if (isInIncludeMode) { | ||||
prefix = getTargetPrefix(context); | prefix = getTargetPrefix(context); | ||||
if (prefix == null) { | if (prefix == null) { | ||||
@@ -858,7 +860,7 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
+ " and the project tag doesn't" | + " and the project tag doesn't" | ||||
+ " specify a name attribute"); | + " specify a name attribute"); | ||||
} | } | ||||
name = prefix + "." + name; | |||||
name = prefix + sep + name; | |||||
} | } | ||||
// Check if this target is in the current build file | // Check if this target is in the current build file | ||||
@@ -878,6 +880,7 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
project.addOrReplaceTarget(name, target); | project.addOrReplaceTarget(name, target); | ||||
usedTarget = true; | usedTarget = true; | ||||
} | } | ||||
if (depends.length() > 0) { | if (depends.length() > 0) { | ||||
if (!isInIncludeMode) { | if (!isInIncludeMode) { | ||||
target.setDepends(depends); | target.setDepends(depends); | ||||
@@ -885,7 +888,7 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
for (Iterator iter = | for (Iterator iter = | ||||
Target.parseDepends(depends, name).iterator(); | Target.parseDepends(depends, name).iterator(); | ||||
iter.hasNext(); ) { | iter.hasNext(); ) { | ||||
target.addDependency(prefix + "." + iter.next()); | |||||
target.addDependency(prefix + sep + iter.next()); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -893,7 +896,7 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
&& (prefix = getTargetPrefix(context)) != null) { | && (prefix = getTargetPrefix(context)) != null) { | ||||
// In an imported 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 + sep + name; | |||||
Target newTarget = usedTarget ? new Target(target) : target; | Target newTarget = usedTarget ? new Target(target) : target; | ||||
newTarget.setName(newName); | newTarget.setName(newName); | ||||
context.getCurrentTargets().put(newName, newTarget); | context.getCurrentTargets().put(newName, newTarget); | ||||
@@ -909,10 +912,17 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
if (configuredValue != null) { | if (configuredValue != null) { | ||||
return configuredValue; | return configuredValue; | ||||
} | } | ||||
String projectName = context.getCurrentProjectName(); | String projectName = context.getCurrentProjectName(); | ||||
if (projectName != null && projectName.length() == 0) { | |||||
if ("".equals(projectName)) { | |||||
projectName = null; | projectName = null; | ||||
} | } | ||||
// help nested include tasks | |||||
if (projectName != null) { | |||||
setCurrentTargetPrefix(projectName); | |||||
} | |||||
return projectName; | return projectName; | ||||
} | } | ||||
@@ -56,6 +56,7 @@ public class ImportTask extends Task { | |||||
private String file; | private String file; | ||||
private boolean optional; | private boolean optional; | ||||
private String targetPrefix; | private String targetPrefix; | ||||
private String prefixSeparator = "."; | |||||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | ||||
/** | /** | ||||
@@ -89,9 +90,15 @@ public class ImportTask extends Task { | |||||
} | } | ||||
/** | /** | ||||
* This relies on the task order model. | |||||
* The separator to use between prefix and target name, default is | |||||
* ".". | |||||
* | * | ||||
* @since Ant 1.8.0 | |||||
*/ | */ | ||||
public void setPrefixSeparator(String s) { | |||||
prefixSeparator = s; | |||||
} | |||||
public void execute() { | public void execute() { | ||||
if (file == null) { | if (file == null) { | ||||
throw new BuildException("import requires file attribute"); | throw new BuildException("import requires file attribute"); | ||||
@@ -156,16 +163,22 @@ public class ImportTask extends Task { | |||||
// importing another one | // importing another one | ||||
String oldPrefix = ProjectHelper.getCurrentTargetPrefix(); | String oldPrefix = ProjectHelper.getCurrentTargetPrefix(); | ||||
boolean oldIncludeMode = ProjectHelper.isInIncludeMode(); | boolean oldIncludeMode = ProjectHelper.isInIncludeMode(); | ||||
String oldSep = ProjectHelper.getCurrentPrefixSeparator(); | |||||
try { | try { | ||||
ProjectHelper.setCurrentTargetPrefix(targetPrefix); | |||||
ProjectHelper.setInIncludeMode(isInIncludeMode()); | |||||
String prefix = targetPrefix; | |||||
if (isInIncludeMode() && oldPrefix != null | |||||
&& targetPrefix != null) { | |||||
prefix = oldPrefix + oldSep + targetPrefix; | |||||
} | |||||
setProjectHelperProps(prefix, prefixSeparator, | |||||
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.setInIncludeMode(oldIncludeMode); | |||||
setProjectHelperProps(oldPrefix, oldSep, oldIncludeMode); | |||||
} | } | ||||
} | } | ||||
@@ -187,4 +200,16 @@ public class ImportTask extends Task { | |||||
return "include".equals(getTaskType()); | return "include".equals(getTaskType()); | ||||
} | } | ||||
/** | |||||
* Sets a bunch of Thread-local ProjectHelper properties. | |||||
* | |||||
* @since Ant 1.8.0 | |||||
*/ | |||||
private static void setProjectHelperProps(String prefix, | |||||
String prefixSep, | |||||
boolean inIncludeMode) { | |||||
ProjectHelper.setCurrentTargetPrefix(prefix); | |||||
ProjectHelper.setCurrentPrefixSeparator(prefixSep); | |||||
ProjectHelper.setInIncludeMode(inIncludeMode); | |||||
} | |||||
} | } |
@@ -0,0 +1,21 @@ | |||||
<?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> | |||||
<include file="b.xml" as="b" prefixSeparator="::"/> | |||||
<include file="a.xml" as="a" prefixSeparator=""/> | |||||
</project> |
@@ -38,4 +38,10 @@ | |||||
<target name="testNoOverride" depends="override.dummy"> | <target name="testNoOverride" depends="override.dummy"> | ||||
<au:assertEquals expected="in included/imported" actual="${prop}"/> | <au:assertEquals expected="in included/imported" actual="${prop}"/> | ||||
</target> | </target> | ||||
<include file="importtests/nested.xml" as="nested"/> | |||||
<!-- really only tests that the targets have the expected names by | |||||
forcing an exception if the dependencies don't exist --> | |||||
<target name="testNesting" depends="nested.b::b, nested.aa"/> | |||||
</project> | </project> |