git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@836334 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1022,6 +1022,15 @@ Other changes: | |||||
contained provide URLs) and can get multiple resources in a single | contained provide URLs) and can get multiple resources in a single | ||||
task. | task. | ||||
* <import> can now import non-File resources if they provide an URL | |||||
- as the <url> and <javaresource> resources do. | |||||
Bugzilla Report 29251 | |||||
* <import> can now import multiple resources specified as resource | |||||
collections. | |||||
Bugzilla Report 22269. | |||||
Changes from Ant 1.7.0 TO Ant 1.7.1 | Changes from Ant 1.7.0 TO Ant 1.7.1 | ||||
============================================= | ============================================= | ||||
@@ -95,6 +95,14 @@ present in the imported project tag.</p> | |||||
property will not be set. | property will not be set. | ||||
</p> | </p> | ||||
<p>Since Ant 1.8.0 the task can also import resources from URLs or | |||||
classpath resources (which are URLs, really). If you need to know | |||||
whether the current build file's source has been a file or an URL | |||||
you can consult the | |||||
property <b>ant.file.type.<em>projectname</em></b> (using the same | |||||
example as above <b>ant.file.type.builddocs</b>) which either have | |||||
the value "file" or "url".</p> | |||||
<h4>Resolving files against the imported file</h4> | <h4>Resolving files against the imported file</h4> | ||||
<p>Suppose your main build file called <code>importing.xml</code> | <p>Suppose your main build file called <code>importing.xml</code> | ||||
@@ -135,6 +143,19 @@ directory. This technique also allows <code>imported.xml</code> to be | |||||
used as a standalone file (without being imported in other | used as a standalone file (without being imported in other | ||||
project).</p> | project).</p> | ||||
<p>The above description only works for imported files that actually | |||||
are imported from files and not from URLs. For files imported from | |||||
URLs using resources relative to the imported file requires you to | |||||
use tasks that can work on non-file resources in the first place. | |||||
To create a relative resource you'd use something like:</p> | |||||
<pre> | |||||
<url id="imported.basedir" url="${ant.file.imported}/."/> | |||||
<loadproperties> | |||||
<url url="${toString:imported.basedir}/imported.properties"/> | |||||
</loadproperties> | |||||
</pre> | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tbody> | <tbody> | ||||
@@ -152,7 +173,7 @@ project).</p> | |||||
relative to the <i>importing</i> file. <b>Note</b>, this is unlike most other | relative to the <i>importing</i> file. <b>Note</b>, this is unlike most other | ||||
ant file attributes, where relative files are resolved relative to ${basedir}. | ant file attributes, where relative files are resolved relative to ${basedir}. | ||||
</td> | </td> | ||||
<td valign="top" align="center">Yes</td> | |||||
<td valign="top" align="center">Yes or a nested resource collection</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top"> | <td valign="top"> | ||||
@@ -188,6 +209,14 @@ project).</p> | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
<h3>Parameters specified as nested elements</h3> | |||||
<h4>any <a href="../CoreTypes/resources.html">resource</a> or resource | |||||
collection</h4> | |||||
<p>The specified resources will be imported. <em>Since Ant | |||||
1.8.0</em></p> | |||||
<h3>Examples</h3> | <h3>Examples</h3> | ||||
<pre> <import file="../common-targets.xml"/> | <pre> <import file="../common-targets.xml"/> | ||||
</pre> | </pre> | ||||
@@ -200,6 +229,17 @@ directory.</p> | |||||
<p>Imports the project defined by the property deploy-platform</p> | <p>Imports the project defined by the property deploy-platform</p> | ||||
<pre> | |||||
<import> | |||||
<javaresource name="common/targets.xml"> | |||||
<classpath location="common.jar"/> | |||||
</javaresource> | |||||
</import> | |||||
</pre> | |||||
<p>Imports targets from the targets.xml file that is inside the | |||||
directory common inside the jar file common.jar.</p> | |||||
<h3>How is <import> different | <h3>How is <import> different | ||||
from <a href="include.html"><include></a>?</h3> | from <a href="include.html"><include></a>?</h3> | ||||
@@ -28,6 +28,8 @@ | |||||
Include another build file into the current project. | Include another build file into the current project. | ||||
</p> | </p> | ||||
<p><em>since Ant 1.8.0</em></p> | |||||
<p> | <p> | ||||
<b>Note</b> this task heavily relies on the ProjectHelper | <b>Note</b> this task heavily relies on the ProjectHelper | ||||
implementation and doesn't really perform any work of its own. If | implementation and doesn't really perform any work of its own. If | ||||
@@ -98,6 +100,12 @@ present in the included project tag.</p> | |||||
property will not be set. | property will not be set. | ||||
</p> | </p> | ||||
<p>If you need to know whether the current build file's source has | |||||
been a file or an URL you can consult the | |||||
property <b>ant.file.type.<em>projectname</em></b> (using the same | |||||
example as above <b>ant.file.type.builddocs</b>) which either have | |||||
the value "file" or "url".</p> | |||||
<h4>Resolving files against the included file</h4> | <h4>Resolving files against the included file</h4> | ||||
<p>Suppose your main build file called <code>including.xml</code> | <p>Suppose your main build file called <code>including.xml</code> | ||||
@@ -138,6 +146,19 @@ directory. This technique also allows <code>included.xml</code> to be | |||||
used as a standalone file (without being included in other | used as a standalone file (without being included in other | ||||
project).</p> | project).</p> | ||||
<p>The above description only works for included files that actually | |||||
are included from files and not from URLs. For files included from | |||||
URLs using resources relative to the included file requires you to | |||||
use tasks that can work on non-file resources in the first place. | |||||
To create a relative resource you'd use something like:</p> | |||||
<pre> | |||||
<url id="included.basedir" url="${ant.file.included}/."/> | |||||
<loadproperties> | |||||
<url url="${toString:included.basedir}/included.properties"/> | |||||
</loadproperties> | |||||
</pre> | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tbody> | <tbody> | ||||
@@ -155,7 +176,7 @@ project).</p> | |||||
relative to the <i>including</i> file. <b>Note</b>, this is unlike most other | 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}. | ant file attributes, where relative files are resolved relative to ${basedir}. | ||||
</td> | </td> | ||||
<td valign="top" align="center">Yes</td> | |||||
<td valign="top" align="center">Yes or a nested resource collection</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top"> | <td valign="top"> | ||||
@@ -174,7 +195,7 @@ project).</p> | |||||
<td valign="top"> | <td valign="top"> | ||||
Specifies the prefix prepended to the target names. If | Specifies the prefix prepended to the target names. If | ||||
ommitted, the name attribute of the project tag of the | ommitted, the name attribute of the project tag of the | ||||
imported file will be used. | |||||
included file will be used. | |||||
</td> | </td> | ||||
<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> | ||||
@@ -192,6 +213,13 @@ project).</p> | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
<h3>Parameters specified as nested elements</h3> | |||||
<h4>any <a href="../CoreTypes/resources.html">resource</a> or resource | |||||
collection</h4> | |||||
<p>The specified resources will be included.</p> | |||||
<h3>Examples</h3> | <h3>Examples</h3> | ||||
<pre> <include file="../common-targets.xml"/> | <pre> <include file="../common-targets.xml"/> | ||||
</pre> | </pre> | ||||
@@ -204,6 +232,17 @@ directory.</p> | |||||
<p>Includes the project defined by the property deploy-platform</p> | <p>Includes the project defined by the property deploy-platform</p> | ||||
<pre> | |||||
<include> | |||||
<javaresource name="common/targets.xml"> | |||||
<classpath location="common.jar"/> | |||||
</javaresource> | |||||
</include> | |||||
</pre> | |||||
<p>Includes targets from the targets.xml file that is inside the | |||||
directory common inside the jar file common.jar.</p> | |||||
<h3>How is <a href="import.html"><import></a> different | <h3>How is <a href="import.html"><import></a> different | ||||
from <include>?</h3> | from <include>?</h3> | ||||
@@ -113,6 +113,27 @@ public final class MagicNames { | |||||
*/ | */ | ||||
public static final String ANT_FILE = "ant.file"; | public static final String ANT_FILE = "ant.file"; | ||||
/** | |||||
* property for type of ant build file (either file or url) | |||||
* Value: {@value} | |||||
* @since Ant 1.8.0 | |||||
*/ | |||||
public static final String ANT_FILE_TYPE = "ant.file.type"; | |||||
/** | |||||
* ant build file of type file | |||||
* Value: {@value} | |||||
* @since Ant 1.8.0 | |||||
*/ | |||||
public static final String ANT_FILE_TYPE_FILE = "file"; | |||||
/** | |||||
* ant build file of type url | |||||
* Value: {@value} | |||||
* @since Ant 1.8.0 | |||||
*/ | |||||
public static final String ANT_FILE_TYPE_URL = "url"; | |||||
/** | /** | ||||
* Property used to store the java version ant is running in. | * Property used to store the java version ant is running in. | ||||
* Value: {@value} | * Value: {@value} | ||||
@@ -773,6 +773,8 @@ public class Main implements AntMain { | |||||
project.setUserProperty(MagicNames.ANT_FILE, | project.setUserProperty(MagicNames.ANT_FILE, | ||||
buildFile.getAbsolutePath()); | buildFile.getAbsolutePath()); | ||||
project.setUserProperty(MagicNames.ANT_FILE_TYPE, | |||||
MagicNames.ANT_FILE_TYPE_FILE); | |||||
project.setKeepGoingMode(keepGoingMode); | project.setKeepGoingMode(keepGoingMode); | ||||
if (proxy) { | if (proxy) { | ||||
@@ -18,6 +18,8 @@ | |||||
package org.apache.tools.ant.helper; | package org.apache.tools.ant.helper; | ||||
import java.io.File; | import java.io.File; | ||||
import java.net.MalformedURLException; | |||||
import java.net.URL; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import java.util.List; | import java.util.List; | ||||
@@ -27,12 +29,12 @@ import java.util.Vector; | |||||
import org.xml.sax.Locator; | import org.xml.sax.Locator; | ||||
import org.xml.sax.Attributes; | import org.xml.sax.Attributes; | ||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.Target; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.Location; | import org.apache.tools.ant.Location; | ||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.RuntimeConfigurable; | import org.apache.tools.ant.RuntimeConfigurable; | ||||
import org.apache.tools.ant.Target; | |||||
import org.apache.tools.ant.util.FileUtils; | |||||
/** | /** | ||||
* Context information for the ant processing. | * Context information for the ant processing. | ||||
@@ -45,6 +47,9 @@ public class AntXMLContext { | |||||
/** The configuration file to parse. */ | /** The configuration file to parse. */ | ||||
private File buildFile; | private File buildFile; | ||||
/** The configuration file to parse. */ | |||||
private URL buildFileURL; | |||||
/** Vector with all the targets, in the order they are | /** Vector with all the targets, in the order they are | ||||
* defined. Project maintains a Hashtable, which is not ordered. | * defined. Project maintains a Hashtable, which is not ordered. | ||||
* This will allow description to know the original order. | * This will allow description to know the original order. | ||||
@@ -57,6 +62,12 @@ public class AntXMLContext { | |||||
*/ | */ | ||||
private File buildFileParent; | private File buildFileParent; | ||||
/** | |||||
* Parent directory of the build file. Used for resolving entities | |||||
* and setting the project's base directory. | |||||
*/ | |||||
private URL buildFileParentURL; | |||||
/** Name of the current project */ | /** Name of the current project */ | ||||
private String currentProjectName; | private String currentProjectName; | ||||
@@ -115,6 +126,24 @@ public class AntXMLContext { | |||||
this.buildFile = buildFile; | this.buildFile = buildFile; | ||||
this.buildFileParent = new File(buildFile.getParent()); | this.buildFileParent = new File(buildFile.getParent()); | ||||
implicitTarget.setLocation(new Location(buildFile.getAbsolutePath())); | implicitTarget.setLocation(new Location(buildFile.getAbsolutePath())); | ||||
try { | |||||
setBuildFile(FileUtils.getFileUtils().getFileURL(buildFile)); | |||||
} catch (MalformedURLException ex) { | |||||
throw new BuildException(ex); | |||||
} | |||||
} | |||||
/** | |||||
* sets the build file to which the XML context belongs | |||||
* @param buildFile ant build file | |||||
* @since Ant 1.8.0 | |||||
*/ | |||||
public void setBuildFile(URL buildFile) throws MalformedURLException { | |||||
this.buildFileURL = buildFile; | |||||
this.buildFileParentURL = new URL(buildFile, "."); | |||||
if (implicitTarget.getLocation() == null) { | |||||
implicitTarget.setLocation(new Location(buildFile.toString())); | |||||
} | |||||
} | } | ||||
/** | /** | ||||
@@ -133,6 +162,24 @@ public class AntXMLContext { | |||||
return buildFileParent; | return buildFileParent; | ||||
} | } | ||||
/** | |||||
* find out the build file | |||||
* @return the build file to which the xml context belongs | |||||
* @since Ant 1.8.0 | |||||
*/ | |||||
public URL getBuildFileURL() { | |||||
return buildFileURL; | |||||
} | |||||
/** | |||||
* find out the parent build file of this build file | |||||
* @return the parent build file of this build file | |||||
* @since Ant 1.8.0 | |||||
*/ | |||||
public URL getBuildFileParentURL() { | |||||
return buildFileParentURL; | |||||
} | |||||
/** | /** | ||||
* find out the project to which this antxml context belongs | * find out the project to which this antxml context belongs | ||||
* @return project | * @return project | ||||
@@ -218,6 +218,11 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
context.setBuildFile(buildFile); | context.setBuildFile(buildFile); | ||||
buildFileName = buildFile.toString(); | buildFileName = buildFile.toString(); | ||||
} else if (url != null) { | } else if (url != null) { | ||||
try { | |||||
context.setBuildFile(url); | |||||
} catch (java.net.MalformedURLException ex) { | |||||
throw new BuildException(ex); | |||||
} | |||||
buildFileName = url.toString(); | buildFileName = url.toString(); | ||||
} else { | } else { | ||||
throw new BuildException("Source " + source.getClass().getName() | throw new BuildException("Source " + source.getClass().getName() | ||||
@@ -738,7 +743,8 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
} | } | ||||
// XXX Move to Project ( so it is shared by all helpers ) | // XXX Move to Project ( so it is shared by all helpers ) | ||||
String antFileProp = "ant.file." + context.getCurrentProjectName(); | |||||
String antFileProp = | |||||
MagicNames.ANT_FILE + "." + context.getCurrentProjectName(); | |||||
String dup = project.getProperty(antFileProp); | String dup = project.getProperty(antFileProp); | ||||
if (dup != null && nameAttributeSet) { | if (dup != null && nameAttributeSet) { | ||||
File dupFile = new File(dup); | File dupFile = new File(dup); | ||||
@@ -748,10 +754,20 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
+ " and again in " + context.getBuildFile(), Project.MSG_WARN); | + " and again in " + context.getBuildFile(), Project.MSG_WARN); | ||||
} | } | ||||
} | } | ||||
if (context.getBuildFile() != null && nameAttributeSet) { | |||||
project.setUserProperty( | |||||
MagicNames.ANT_FILE + "." + context.getCurrentProjectName(), context | |||||
.getBuildFile().toString()); | |||||
if (nameAttributeSet) { | |||||
String typeProp = MagicNames.ANT_FILE_TYPE + "." | |||||
+ context.getCurrentProjectName(); | |||||
if (context.getBuildFile() != null) { | |||||
project.setUserProperty(antFileProp, | |||||
context.getBuildFile().toString()); | |||||
project.setUserProperty(typeProp, | |||||
MagicNames.ANT_FILE_TYPE_FILE); | |||||
} else if (context.getBuildFileURL() != null) { | |||||
project.setUserProperty(antFileProp, | |||||
context.getBuildFileURL().toString()); | |||||
project.setUserProperty(typeProp, | |||||
MagicNames.ANT_FILE_TYPE_URL); | |||||
} | |||||
} | } | ||||
if (context.isIgnoringProjectTag()) { | if (context.isIgnoringProjectTag()) { | ||||
// no further processing | // no further processing | ||||
@@ -26,10 +26,13 @@ import org.apache.tools.ant.types.Resource; | |||||
import org.apache.tools.ant.types.ResourceCollection; | import org.apache.tools.ant.types.ResourceCollection; | ||||
import org.apache.tools.ant.types.resources.FileProvider; | import org.apache.tools.ant.types.resources.FileProvider; | ||||
import org.apache.tools.ant.types.resources.FileResource; | import org.apache.tools.ant.types.resources.FileResource; | ||||
import org.apache.tools.ant.types.resources.URLResource; | |||||
import org.apache.tools.ant.types.resources.Union; | import org.apache.tools.ant.types.resources.Union; | ||||
import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
import java.io.File; | import java.io.File; | ||||
import java.net.MalformedURLException; | |||||
import java.net.URL; | |||||
import java.util.Iterator; | import java.util.Iterator; | ||||
import java.util.Vector; | import java.util.Vector; | ||||
@@ -151,17 +154,9 @@ public class ImportTask extends Task { | |||||
} | } | ||||
Union resourcesToImport = new Union(getProject(), resources); | Union resourcesToImport = new Union(getProject(), resources); | ||||
if (file != null) { | |||||
File buildFile = | |||||
new File(getLocation().getFileName()).getAbsoluteFile(); | |||||
// Paths are relative to the build file they're imported from, | |||||
// *not* the current directory (same as entity includes). | |||||
File buildFileParent = new File(buildFile.getParent()); | |||||
File importedFile = FILE_UTILS.resolveFile(buildFileParent, file); | |||||
resources.add(new FileResource(importedFile)); | |||||
Resource fromFileAttribute = getFileAttributeResource(); | |||||
if (fromFileAttribute != null) { | |||||
resources.add(fromFileAttribute); | |||||
} | } | ||||
for (Iterator i = resourcesToImport.iterator(); i.hasNext(); ) { | for (Iterator i = resourcesToImport.iterator(); i.hasNext(); ) { | ||||
importResource(helper, (Resource) i.next()); | importResource(helper, (Resource) i.next()); | ||||
@@ -227,6 +222,34 @@ public class ImportTask extends Task { | |||||
} | } | ||||
} | } | ||||
private Resource getFileAttributeResource() { | |||||
// Paths are relative to the build file they're imported from, | |||||
// *not* the current directory (same as entity includes). | |||||
if (file != null) { | |||||
File buildFile = | |||||
new File(getLocation().getFileName()).getAbsoluteFile(); | |||||
if (buildFile.exists()) { | |||||
File buildFileParent = new File(buildFile.getParent()); | |||||
File importedFile = | |||||
FILE_UTILS.resolveFile(buildFileParent, file); | |||||
return new FileResource(importedFile); | |||||
} | |||||
// maybe this import tasks is inside an imported URL? | |||||
try { | |||||
URL buildFileURL = new URL(getLocation().getFileName()); | |||||
URL importedFile = new URL(buildFileURL, file); | |||||
return new URLResource(importedFile); | |||||
} catch (MalformedURLException ex) { | |||||
log(ex.toString(), Project.MSG_VERBOSE); | |||||
} | |||||
throw new BuildException("failed to resolve " + file | |||||
+ " relative to " | |||||
+ getLocation().getFileName()); | |||||
} | |||||
return null; | |||||
} | |||||
/** | /** | ||||
* Whether the task is in include (as opposed to import) mode. | * Whether the task is in include (as opposed to import) mode. | ||||
* | * | ||||
@@ -0,0 +1,49 @@ | |||||
<?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" /> | |||||
<mkdir dir="${input}/a/b"/> | |||||
<mkdir dir="${input}/a/c"/> | |||||
<echo file="${input}/a/b/outer.xml"><![CDATA[ | |||||
<project> | |||||
<import file="../c/inner.xml"/> | |||||
</project> | |||||
]]></echo> | |||||
<echo file="${input}/a/c/inner.xml"><![CDATA[ | |||||
<project> | |||||
<target name="foo"> | |||||
<echo>In inner</echo> | |||||
</target> | |||||
</project>]]></echo> | |||||
<mkdir dir="${output}"/> | |||||
<jar destfile="${output}/test.jar"> | |||||
<fileset dir="${input}"/> | |||||
</jar> | |||||
<delete dir="${input}"/> | |||||
<import> | |||||
<javaresource name="a/b/outer.xml"> | |||||
<classpath location="${output}/test.jar"/> | |||||
</javaresource> | |||||
</import> | |||||
<target name="testImportOfNestedFile" depends="foo"> | |||||
<au:assertLogContains text="In inner"/> | |||||
</target> | |||||
</project> |