diff --git a/WHATSNEW b/WHATSNEW index e711a660d..bed08bd10 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -1022,6 +1022,15 @@ Other changes: contained provide URLs) and can get multiple resources in a single task. + * can now import non-File resources if they provide an URL + - as the and resources do. + Bugzilla Report 29251 + + * can now import multiple resources specified as resource + collections. + Bugzilla Report 22269. + + Changes from Ant 1.7.0 TO Ant 1.7.1 ============================================= diff --git a/docs/manual/CoreTasks/import.html b/docs/manual/CoreTasks/import.html index 2337495ec..d2c18b1ab 100644 --- a/docs/manual/CoreTasks/import.html +++ b/docs/manual/CoreTasks/import.html @@ -95,6 +95,14 @@ present in the imported project tag.

property will not be set.

+

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 ant.file.type.projectname (using the same + example as above ant.file.type.builddocs) which either have + the value "file" or "url".

+

Resolving files against the imported file

Suppose your main build file called importing.xml @@ -135,6 +143,19 @@ directory. This technique also allows imported.xml to be used as a standalone file (without being imported in other project).

+

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:

+ +
+  <url id="imported.basedir" url="${ant.file.imported}/."/>
+  <loadproperties>
+    <url url="${toString:imported.basedir}/imported.properties"/>
+  </loadproperties>
+
+

Parameters

@@ -152,7 +173,7 @@ project).

relative to the importing file. Note, this is unlike most other ant file attributes, where relative files are resolved relative to ${basedir}. - +
YesYes or a nested resource collection
@@ -188,6 +209,14 @@ project).

+

Parameters specified as nested elements

+ +

any resource or resource +collection

+ +

The specified resources will be imported. Since Ant + 1.8.0

+

Examples

  <import file="../common-targets.xml"/>
 
@@ -200,6 +229,17 @@ directory.

Imports the project defined by the property deploy-platform

+
+  <import>
+    <javaresource name="common/targets.xml">
+      <classpath location="common.jar"/>
+    </javaresource>
+  </import>
+
+ +

Imports targets from the targets.xml file that is inside the + directory common inside the jar file common.jar.

+

How is <import> different from <include>?

diff --git a/docs/manual/CoreTasks/include.html b/docs/manual/CoreTasks/include.html index 729741e73..b89967977 100644 --- a/docs/manual/CoreTasks/include.html +++ b/docs/manual/CoreTasks/include.html @@ -28,6 +28,8 @@ Include another build file into the current project.

+

since Ant 1.8.0

+

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

property will not be set.

+

If you need to know whether the current build file's source has + been a file or an URL you can consult the + property ant.file.type.projectname (using the same + example as above ant.file.type.builddocs) which either have + the value "file" or "url".

+

Resolving files against the included file

Suppose your main build file called including.xml @@ -138,6 +146,19 @@ directory. This technique also allows included.xml to be used as a standalone file (without being included in other project).

+

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:

+ +
+  <url id="included.basedir" url="${ant.file.included}/."/>
+  <loadproperties>
+    <url url="${toString:included.basedir}/included.properties"/>
+  </loadproperties>
+
+

Parameters

@@ -155,7 +176,7 @@ project).

relative to the including file. Note, this is unlike most other ant file attributes, where relative files are resolved relative to ${basedir}. - + @@ -192,6 +213,13 @@ project).

YesYes or a nested resource collection
@@ -174,7 +195,7 @@ project).

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. Yes, if the included file's project tag doesn't specify a name attribute.
+

Parameters specified as nested elements

+ +

any resource or resource +collection

+ +

The specified resources will be included.

+

Examples

  <include file="../common-targets.xml"/>
 
@@ -204,6 +232,17 @@ directory.

Includes the project defined by the property deploy-platform

+
+  <include>
+    <javaresource name="common/targets.xml">
+      <classpath location="common.jar"/>
+    </javaresource>
+  </include>
+
+ +

Includes targets from the targets.xml file that is inside the + directory common inside the jar file common.jar.

+

How is <import> different from <include>?

diff --git a/src/main/org/apache/tools/ant/MagicNames.java b/src/main/org/apache/tools/ant/MagicNames.java index de6746861..87371bd74 100644 --- a/src/main/org/apache/tools/ant/MagicNames.java +++ b/src/main/org/apache/tools/ant/MagicNames.java @@ -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} diff --git a/src/main/org/apache/tools/ant/Main.java b/src/main/org/apache/tools/ant/Main.java index 820ebb95a..886e3c414 100644 --- a/src/main/org/apache/tools/ant/Main.java +++ b/src/main/org/apache/tools/ant/Main.java @@ -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) { diff --git a/src/main/org/apache/tools/ant/helper/AntXMLContext.java b/src/main/org/apache/tools/ant/helper/AntXMLContext.java index dc2d40497..36f7b0844 100644 --- a/src/main/org/apache/tools/ant/helper/AntXMLContext.java +++ b/src/main/org/apache/tools/ant/helper/AntXMLContext.java @@ -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 diff --git a/src/main/org/apache/tools/ant/helper/ProjectHelper2.java b/src/main/org/apache/tools/ant/helper/ProjectHelper2.java index 5feb9170c..d5d1adef6 100644 --- a/src/main/org/apache/tools/ant/helper/ProjectHelper2.java +++ b/src/main/org/apache/tools/ant/helper/ProjectHelper2.java @@ -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 diff --git a/src/main/org/apache/tools/ant/taskdefs/ImportTask.java b/src/main/org/apache/tools/ant/taskdefs/ImportTask.java index 30f0da718..a3abc2a36 100644 --- a/src/main/org/apache/tools/ant/taskdefs/ImportTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/ImportTask.java @@ -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. * diff --git a/src/tests/antunit/taskdefs/import-url-test.xml b/src/tests/antunit/taskdefs/import-url-test.xml new file mode 100644 index 000000000..71e7a304e --- /dev/null +++ b/src/tests/antunit/taskdefs/import-url-test.xml @@ -0,0 +1,49 @@ + + + + + + + + + + +]]> + + + In inner + +]]> + + + + + + + + + + + + + + + +