Browse Source

Fix import's file attribute if file is imported from URL, test it, document it. Note to self - url resource needs a way to create relative urls. Not to self - the duplication in the manual pages for import and include must stop.

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@836334 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 15 years ago
parent
commit
42f31b452b
9 changed files with 269 additions and 23 deletions
  1. +9
    -0
      WHATSNEW
  2. +41
    -1
      docs/manual/CoreTasks/import.html
  3. +41
    -2
      docs/manual/CoreTasks/include.html
  4. +21
    -0
      src/main/org/apache/tools/ant/MagicNames.java
  5. +2
    -0
      src/main/org/apache/tools/ant/Main.java
  6. +51
    -4
      src/main/org/apache/tools/ant/helper/AntXMLContext.java
  7. +21
    -5
      src/main/org/apache/tools/ant/helper/ProjectHelper2.java
  8. +34
    -11
      src/main/org/apache/tools/ant/taskdefs/ImportTask.java
  9. +49
    -0
      src/tests/antunit/taskdefs/import-url-test.xml

+ 9
- 0
WHATSNEW View File

@@ -1022,6 +1022,15 @@ Other changes:
contained provide URLs) and can get multiple resources in a single
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
=============================================



+ 41
- 1
docs/manual/CoreTasks/import.html View File

@@ -95,6 +95,14 @@ present in the imported project tag.</p>
property will not be set.
</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>

<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
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>
&lt;url id="imported.basedir" url="${ant.file.imported}/."/&gt;
&lt;loadproperties&gt;
&lt;url url="${toString:imported.basedir}/imported.properties"/&gt;
&lt;/loadproperties&gt;
</pre>

<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tbody>
@@ -152,7 +173,7 @@ project).</p>
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}.
</td>
<td valign="top" align="center">Yes</td>
<td valign="top" align="center">Yes or a nested resource collection</td>
</tr>
<tr>
<td valign="top">
@@ -188,6 +209,14 @@ project).</p>
</tbody>
</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>
<pre>&nbsp; &lt;import file=&quot;../common-targets.xml&quot;/&gt;
</pre>
@@ -200,6 +229,17 @@ directory.</p>

<p>Imports the project defined by the property deploy-platform</p>

<pre>
&lt;import&gt;
&lt;javaresource name="common/targets.xml"&gt;
&lt;classpath location="common.jar"/&gt;
&lt;/javaresource&gt;
&lt;/import&gt;
</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 &lt;import&gt; different
from <a href="include.html">&lt;include&gt;</a>?</h3>



+ 41
- 2
docs/manual/CoreTasks/include.html View File

@@ -28,6 +28,8 @@
Include another build file into the current project.
</p>

<p><em>since Ant 1.8.0</em></p>

<p>
<b>Note</b> this task heavily relies on the ProjectHelper
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.
</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>

<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
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>
&lt;url id="included.basedir" url="${ant.file.included}/."/&gt;
&lt;loadproperties&gt;
&lt;url url="${toString:included.basedir}/included.properties"/&gt;
&lt;/loadproperties&gt;
</pre>

<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tbody>
@@ -155,7 +176,7 @@ project).</p>
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>
<td valign="top" align="center">Yes or a nested resource collection</td>
</tr>
<tr>
<td valign="top">
@@ -174,7 +195,7 @@ project).</p>
<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.
included 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>
@@ -192,6 +213,13 @@ project).</p>
</tbody>
</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>
<pre>&nbsp; &lt;include file=&quot;../common-targets.xml&quot;/&gt;
</pre>
@@ -204,6 +232,17 @@ directory.</p>

<p>Includes the project defined by the property deploy-platform</p>

<pre>
&lt;include&gt;
&lt;javaresource name="common/targets.xml"&gt;
&lt;classpath location="common.jar"/&gt;
&lt;/javaresource&gt;
&lt;/include&gt;
</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">&lt;import&gt;</a> different
from &lt;include&gt;?</h3>



+ 21
- 0
src/main/org/apache/tools/ant/MagicNames.java View File

@@ -113,6 +113,27 @@ public final class MagicNames {
*/
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.
* Value: {@value}


+ 2
- 0
src/main/org/apache/tools/ant/Main.java View File

@@ -773,6 +773,8 @@ public class Main implements AntMain {

project.setUserProperty(MagicNames.ANT_FILE,
buildFile.getAbsolutePath());
project.setUserProperty(MagicNames.ANT_FILE_TYPE,
MagicNames.ANT_FILE_TYPE_FILE);

project.setKeepGoingMode(keepGoingMode);
if (proxy) {


+ 51
- 4
src/main/org/apache/tools/ant/helper/AntXMLContext.java View File

@@ -18,6 +18,8 @@
package org.apache.tools.ant.helper;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -27,12 +29,12 @@ import java.util.Vector;
import org.xml.sax.Locator;
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.Project;
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.
@@ -45,6 +47,9 @@ public class AntXMLContext {
/** The configuration file to parse. */
private File buildFile;

/** The configuration file to parse. */
private URL buildFileURL;

/** Vector with all the targets, in the order they are
* defined. Project maintains a Hashtable, which is not ordered.
* This will allow description to know the original order.
@@ -57,6 +62,12 @@ public class AntXMLContext {
*/
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 */
private String currentProjectName;

@@ -115,6 +126,24 @@ public class AntXMLContext {
this.buildFile = buildFile;
this.buildFileParent = new File(buildFile.getParent());
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;
}

/**
* 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
* @return project


+ 21
- 5
src/main/org/apache/tools/ant/helper/ProjectHelper2.java View File

@@ -218,6 +218,11 @@ public class ProjectHelper2 extends ProjectHelper {
context.setBuildFile(buildFile);
buildFileName = buildFile.toString();
} else if (url != null) {
try {
context.setBuildFile(url);
} catch (java.net.MalformedURLException ex) {
throw new BuildException(ex);
}
buildFileName = url.toString();
} else {
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 )
String antFileProp = "ant.file." + context.getCurrentProjectName();
String antFileProp =
MagicNames.ANT_FILE + "." + context.getCurrentProjectName();
String dup = project.getProperty(antFileProp);
if (dup != null && nameAttributeSet) {
File dupFile = new File(dup);
@@ -748,10 +754,20 @@ public class ProjectHelper2 extends ProjectHelper {
+ " 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()) {
// no further processing


+ 34
- 11
src/main/org/apache/tools/ant/taskdefs/ImportTask.java View File

@@ -26,10 +26,13 @@ import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.FileProvider;
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.util.FileUtils;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.Vector;

@@ -151,17 +154,9 @@ public class ImportTask extends Task {
}

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(); ) {
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.
*


+ 49
- 0
src/tests/antunit/taskdefs/import-url-test.xml View File

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

Loading…
Cancel
Save