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> | |||||