diff --git a/build.xml b/build.xml
index 66c1d0fb4..c31efa79e 100644
--- a/build.xml
+++ b/build.xml
@@ -1602,7 +1602,8 @@
value="${tests-classpath.value}"/>
-
+
@@ -1775,6 +1776,8 @@
value="${tests-classpath.value}"/>
+
diff --git a/src/etc/testcases/taskdefs/antlib.xml b/src/etc/testcases/taskdefs/antlib.xml
index c9ac9863e..4e1d32b05 100644
--- a/src/etc/testcases/taskdefs/antlib.xml
+++ b/src/etc/testcases/taskdefs/antlib.xml
@@ -36,4 +36,21 @@
Hello from x:p
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/org/apache/tools/ant/ComponentHelper.java b/src/main/org/apache/tools/ant/ComponentHelper.java
index 8e2a7732a..7425d4420 100644
--- a/src/main/org/apache/tools/ant/ComponentHelper.java
+++ b/src/main/org/apache/tools/ant/ComponentHelper.java
@@ -36,6 +36,7 @@ import java.lang.reflect.Modifier;
import java.lang.reflect.InvocationTargetException;
import org.apache.tools.ant.taskdefs.Typedef;
+import org.apache.tools.ant.taskdefs.Definer;
import org.apache.tools.ant.launch.Launcher;
/**
@@ -91,7 +92,6 @@ public class ComponentHelper {
private static final String ERROR_NO_TASK_LIST_LOAD = "Can't load default task list";
private static final String ERROR_NO_TYPE_LIST_LOAD = "Can't load default type list";
public static final String COMPONENT_HELPER_REFERENCE = "ant.ComponentHelper";
- private static final String ANTLIB_PREFIX = "antlib:";
/**
* string used to control build.syspath policy {@value}
@@ -782,13 +782,15 @@ public class ComponentHelper {
checkedNamespaces.add(uri);
Typedef definer = new Typedef();
definer.setProject(project);
+ definer.init();
definer.setURI(uri);
- definer.setResource(
- uri.substring(ANTLIB_PREFIX.length()).replace('.', '/')
- + "/antlib.xml");
+ //there to stop error messages being "null"
+ definer.setTaskName(uri);
+ //if this is left out, bad things happen. like all build files break
+ //on the first element encountered.
+ definer.setResource(Definer.makeResourceFromURI(uri));
// a fishing expedition :- ignore errors if antlib not present
definer.setOnError(new Typedef.OnError(Typedef.OnError.POLICY_IGNORE));
- definer.init();
definer.execute();
}
@@ -813,7 +815,7 @@ public class ComponentHelper {
AntTypeDefinition def = getDefinition(componentName);
if (def == null) {
//not a known type
- boolean isAntlib = componentName.indexOf(ANTLIB_PREFIX) == 0;
+ boolean isAntlib = componentName.indexOf(MagicNames.ANTLIB_PREFIX) == 0;
out.println("Cause: The name is undefined.");
out.println("Action: Check the spelling.");
out.println("Action: Check that any custom tasks/types have been declared.");
diff --git a/src/main/org/apache/tools/ant/MagicNames.java b/src/main/org/apache/tools/ant/MagicNames.java
index f7b2bfb49..d5694c0c3 100644
--- a/src/main/org/apache/tools/ant/MagicNames.java
+++ b/src/main/org/apache/tools/ant/MagicNames.java
@@ -28,6 +28,12 @@ public final class MagicNames {
private MagicNames() {
}
+ /**
+ * prefix for antlib URIs:
+ * {@value}
+ */
+ public static final String ANTLIB_PREFIX = "antlib:";
+
/**
* Ant version property. {@value}
*/
diff --git a/src/main/org/apache/tools/ant/taskdefs/Definer.java b/src/main/org/apache/tools/ant/taskdefs/Definer.java
index 02ca5b014..e6f6c8e62 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Definer.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Definer.java
@@ -33,6 +33,8 @@ import org.apache.tools.ant.ComponentHelper;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.MagicNames;
+import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.types.EnumeratedAttribute;
/**
@@ -44,6 +46,13 @@ import org.apache.tools.ant.types.EnumeratedAttribute;
* @noinspection ParameterHidesMemberVariable
*/
public abstract class Definer extends DefBase {
+
+ /**
+ * the extension of an antlib file for autoloading.
+ * {@value[
+ */
+ private static final String ANTLIB_XML = "/antlib.xml";
+
private static class ResourceStack extends ThreadLocal {
public Object initialValue() {
return new HashMap();
@@ -188,10 +197,20 @@ public abstract class Definer extends DefBase {
ClassLoader al = createLoader();
if (!definerSet) {
- throw new BuildException(
- "name, file or resource attribute of "
- + getTaskName() + " is undefined", getLocation());
- }
+ //we arent fully defined yet. this is an error unless
+ //we are in an antlib, in which case the resource name is determined
+ //automatically.
+ //NB: URIs in the ant core package will be "" at this point.
+ if (getURI()!=null && getURI().startsWith(MagicNames.ANTLIB_PREFIX)) {
+ //convert the URI to a resource
+ String uri1 = getURI();
+ setResource(makeResourceFromURI(uri1));
+ } else {
+ throw new BuildException(
+ "name, file or resource attribute of "
+ + getTaskName() + " is undefined", getLocation());
+ }
+ }
if (name != null) {
if (classname == null) {
@@ -262,6 +281,38 @@ public abstract class Definer extends DefBase {
}
}
+ /**
+ * This is where the logic to map from a URI to an antlib resource
+ * is kept.
+ * @return the name of a resource. It may not exist
+ */
+
+ public static String makeResourceFromURI(String uri) {
+ String path = uri.substring(MagicNames.ANTLIB_PREFIX.length());
+ String resource;
+ if (path.startsWith("//")) {
+ //handle new style full paths to an antlib, in which
+ //all but the forward slashes are allowed.
+ resource = path.substring("//".length());
+ if (!resource.endsWith(".xml")) {
+ //if we haven't already named an XML file, it gets antlib.xml
+ resource = resource + ANTLIB_XML;
+ }
+ } else {
+ //convert from a package to a path
+ resource = path.replace('.', '/') + ANTLIB_XML;
+ }
+ return resource;
+ }
+
+ /**
+ * Convert a file to a file: URL.
+ *
+ * @return the URL, or null if it isn't valid and the active error policy
+ * is not to raise a fault
+ * @throws BuildException if the file is missing/not a file and the
+ * policy requires failure at this point.
+ */
private URL fileToURL() {
String message = null;
if (!(file.exists())) {
@@ -330,7 +381,7 @@ public abstract class Definer extends DefBase {
}
/**
- * Load type definitions as properties from a url.
+ * Load type definitions as properties from a URL.
*
* @param al the classloader to use
* @param url the url to get the definitions from
@@ -355,18 +406,12 @@ public abstract class Definer extends DefBase {
} catch (IOException ex) {
throw new BuildException(ex, getLocation());
} finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- // ignore
- }
- }
+ FileUtils.close(is);
}
}
/**
- * Load an antlib from a url.
+ * Load an antlib from a URL.
*
* @param classLoader the classloader to use.
* @param url the url to load the definitions from.
@@ -551,9 +596,13 @@ public abstract class Definer extends DefBase {
}
}
+ /**
+ * handle too many definitions by raising an exception.
+ * @throws BuildException always.
+ */
private void tooManyDefinitions() {
throw new BuildException(
- "Only one of the attributes name,file,resource"
+ "Only one of the attributes name, file and resource"
+ " can be set", getLocation());
}
}
diff --git a/src/testcases/org/apache/tools/ant/taskdefs/AntlibTest.java b/src/testcases/org/apache/tools/ant/taskdefs/AntlibTest.java
index 68a930942..0fbb328c1 100644
--- a/src/testcases/org/apache/tools/ant/taskdefs/AntlibTest.java
+++ b/src/testcases/org/apache/tools/ant/taskdefs/AntlibTest.java
@@ -18,8 +18,8 @@
package org.apache.tools.ant.taskdefs;
import org.apache.tools.ant.BuildFileTest;
-import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
+import org.apache.tools.ant.Project;
/**
*/
@@ -32,6 +32,15 @@ public class AntlibTest extends BuildFileTest {
configureProject("src/etc/testcases/taskdefs/antlib.xml");
}
+ /**
+ * only do the antlib tests if we are in the same JVM as ant.
+ * @return
+ */
+ private boolean isSharedJVM() {
+ String property = System.getProperty("tests.and.ant.share.classloader");
+ return property!=null && Project.toBoolean(property);
+ }
+
public void testAntlibFile() {
expectLog("antlib.file", "MyTask called");
}
@@ -49,6 +58,25 @@ public class AntlibTest extends BuildFileTest {
expectLog("ns.current", "Echo2 inside a macroHello from x:p");
}
+
+ public void testAntlib_uri() {
+ if (isSharedJVM()) {
+ executeTarget("antlib_uri");
+ }
+ }
+
+ public void testAntlib_uri_auto() {
+ if (isSharedJVM()) {
+ executeTarget("antlib_uri_auto");
+ }
+ }
+
+ public void testAntlib_uri_auto2() {
+ if (isSharedJVM()) {
+ executeTarget("antlib_uri_auto2");
+ }
+ }
+
public static class MyTask extends Task {
public void execute() {
log("MyTask called");