Browse Source

Antlib changes. One I like, one I am still not sure I have right

1. you can go <typedef uri="antlib:something" /> and the resource is worked out automatically from the URI.
2. if you use antlib://org/ex/resource.xml we load in the resource by its full path, so you dont need multiple packages to have multiple antlib files.
I'm not sure about #2; I think it is convenient once you have antlib-only distros (i.e. inline declaration and script; nothing else), but am not sure about the syntax. Maybe
antlib://org.ex/antlib.xml would be better, and more in keeping with WWW URLs; if /antlib.xml is omitted, we would add it by default.


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278535 13f79535-47bb-0310-9956-ffa450edef68
master
Steve Loughran 20 years ago
parent
commit
7527ef1962
6 changed files with 127 additions and 22 deletions
  1. +4
    -1
      build.xml
  2. +17
    -0
      src/etc/testcases/taskdefs/antlib.xml
  3. +8
    -6
      src/main/org/apache/tools/ant/ComponentHelper.java
  4. +6
    -0
      src/main/org/apache/tools/ant/MagicNames.java
  5. +63
    -14
      src/main/org/apache/tools/ant/taskdefs/Definer.java
  6. +29
    -1
      src/testcases/org/apache/tools/ant/taskdefs/AntlibTest.java

+ 4
- 1
build.xml View File

@@ -1602,7 +1602,8 @@
value="${tests-classpath.value}"/>
<sysproperty key="root" file="${basedir}"/>
<sysproperty key="build.compiler" value="${build.compiler}"/>

<sysproperty key="tests.and.ant.share.classloader"
value="${tests.and.ant.share.classloader}"/>
<formatter type="brief" usefile="false"/>

<batchtest>
@@ -1775,6 +1776,8 @@
value="${tests-classpath.value}"/>
<sysproperty key="root" file="${basedir}"/>
<sysproperty key="build.compiler" value="${build.compiler}"/>
<sysproperty key="tests.and.ant.share.classloader"
value="${tests.and.ant.share.classloader}"/>
<classpath refid="tests-classpath"/>
<formatter type="plain" usefile="false"/>
<test name="${testcase}"/>


+ 17
- 0
src/etc/testcases/taskdefs/antlib.xml View File

@@ -36,4 +36,21 @@
<x:preset.echo xmlns:x="abc" name="p"/>
<x:p xmlns:x="abc">Hello from x:p</x:p>
</target>

<target name="antlib_uri" >
<typedef uri="antlib:org.example.tasks" onerror="failall"/>
</target>

<target name="antlib_uri_auto" xmlns:ex="antlib:org.example.tasks">
<ex:simple>
<echo message="inside simple" />
</ex:simple>
</target>

<target name="antlib_uri_auto2" xmlns:ex="antlib://org/example/tasks/antlib2.xml">
<ex:simple>
<echo message="inside simple"/>
</ex:simple>
</target>
</project>

+ 8
- 6
src/main/org/apache/tools/ant/ComponentHelper.java View File

@@ -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.");


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

@@ -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}
*/


+ 63
- 14
src/main/org/apache/tools/ant/taskdefs/Definer.java View File

@@ -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());
}
}

+ 29
- 1
src/testcases/org/apache/tools/ant/taskdefs/AntlibTest.java View File

@@ -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");


Loading…
Cancel
Save