Author: bodewig
Date: Wed Jun 23 12:15:13 2010
New Revision: 957170
URL: http://svn.apache.org/viewvc?rev=957170&view=rev
Log:
allow targets to deal with missing extension points. PR 49473. Submitted by
Danny Yates.
Modified:
ant/core/trunk/CONTRIBUTORS
ant/core/trunk/WHATSNEW
ant/core/trunk/contributors.xml
ant/core/trunk/docs/manual/targets.html
ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelper.java
ant/core/trunk/src/main/org/apache/tools/ant/helper/ProjectHelper2.java
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/AntStructure.java
ant/core/trunk/src/tests/antunit/core/extension-point-test.xml
Modified: ant/core/trunk/CONTRIBUTORS
URL:
http://svn.apache.org/viewvc/ant/core/trunk/CONTRIBUTORS?rev=957170&r1=957169&r2=957170&view=diff
==============================================================================
--- ant/core/trunk/CONTRIBUTORS (original)
+++ ant/core/trunk/CONTRIBUTORS Wed Jun 23 12:15:13 2010
@@ -70,6 +70,7 @@ Daniel Henrique
Daniel Ribagnac
Daniel Spilker
Danno Ferrin
+Danny Yates
Dante Briones
Davanum Srinivas
Dave Brondsema
Modified: ant/core/trunk/WHATSNEW
URL:
http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=957170&r1=957169&r2=957170&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Wed Jun 23 12:15:13 2010
@@ -27,6 +27,11 @@ Changes that could break older environme
formatter where ampersands will now always get encoded.
Bugzilla Report 49404.
+ * The list elements returned by ProjectHelper#getExtensionStack are
+ now String arrays of length 3 rather than 2 in order to support the
+ onMissingExtensionPoint attribute.
+ Bugzilla Report 49473.
+
Fixed bugs:
-----------
@@ -100,6 +105,13 @@ Other changes:
when used in any other way than a CLASSPATH for a forked Java VM.
Bugzilla Report 46842.
+ * A new attribute allows targets to deal with non-existant extensions
+ points, i.e. they can extend and extension-point if it has been
+ defined or silently work as plain targets if it hasn't. This is
+ useful for targets that get included/imported in different
+ scenarios where a given extension-point may or may not exist.
+ Bugzilla Report 49473.
+
Changes from Ant 1.8.0 TO Ant 1.8.1
===================================
Modified: ant/core/trunk/contributors.xml
URL:
http://svn.apache.org/viewvc/ant/core/trunk/contributors.xml?rev=957170&r1=957169&r2=957170&view=diff
==============================================================================
--- ant/core/trunk/contributors.xml (original)
+++ ant/core/trunk/contributors.xml Wed Jun 23 12:15:13 2010
@@ -304,6 +304,10 @@
<last>Ferrin</last>
</name>
<name>
+ <first>Danny</first>
+ <last>Yates</last>
+ </name>
+ <name>
<first>Dante</first>
<last>Briones</last>
</name>
Modified: ant/core/trunk/docs/manual/targets.html
URL:
http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/targets.html?rev=957170&r1=957169&r2=957170&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/targets.html (original)
+++ ant/core/trunk/docs/manual/targets.html Wed Jun 23 12:15:13 2010
@@ -205,6 +205,17 @@
<em>since Ant 1.8.0.</em></td>
<td align="center" valign="top">No</td>
</tr>
+ <tr>
+ <td valign="top">onMissingExtensionPoint</td>
+ <td valign="top">What to do if this target tries to extend a
+ missing
+ <a href="#extension-points">extension-point</a>. ("fail",
+ "warn", "ignore").
+ <em>since Ant 1.8.2.</em></td>
+ <td align="center" valign="top">No. Not allowed unless
+ <code>extensionOf</code> is present. Defaults to <code>fail</code>.
+ </td>
+ </tr>
</table>
<p>A target name can be any alphanumeric string valid in the
Modified: ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelper.java
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelper.java?rev=957170&r1=957169&r2=957170&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelper.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/ProjectHelper.java Wed Jun 23
12:15:13 2010
@@ -82,6 +82,23 @@ public class ProjectHelper {
helper.parse(project, buildFile);
}
+ /**
+ * Possible value for target's onMissingExtensionPoint attribute:
+ * fail if the extension-point is not defined.
+ */
+ public static final String MISSING_EP_FAIL = "fail";
+ /**
+ * Possible value for target's onMissingExtensionPoint attribute:
+ * warn if the extension-point is not defined.
+ */
+ public static final String MISSING_EP_WARN = "warn";
+ /**
+ * Possible value for target's onMissingExtensionPoint attribute:
+ * ignore the extensionOf attribute if the extension-point is not
+ * defined.
+ */
+ public static final String MISSING_EP_IGNORE = "ignore";
+
/** Default constructor */
public ProjectHelper() {
}
@@ -108,9 +125,11 @@ public class ProjectHelper {
* Extension stack.
* Used to keep track of targets that extend extension points.
*
- * @return a list of two element string arrays where the first
- * element is the name of the extensionpoint and the second the
- * name of the target
+ * @return a list of three element string arrays where the first
+ * element is the name of the extensionpoint, the second the name
+ * of the target and the third one of the MISSINS_EP constants
+ * defined inside this class - it determines how to deal with
+ * targets that want to extend missing extension-points.
*/
public List getExtensionStack() {
return extensionStack;
Modified:
ant/core/trunk/src/main/org/apache/tools/ant/helper/ProjectHelper2.java
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/helper/ProjectHelper2.java?rev=957170&r1=957169&r2=957170&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/helper/ProjectHelper2.java
(original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/helper/ProjectHelper2.java Wed
Jun 23 12:15:13 2010
@@ -59,6 +59,7 @@ import java.util.Stack;
*
*/
public class ProjectHelper2 extends ProjectHelper {
+
/** Reference holding the (ordered) target Vector */
public static final String REFID_TARGETS = "ant.targets";
@@ -183,21 +184,29 @@ public class ProjectHelper2 extends Proj
String[] extensionInfo = (String[]) i.next();
String tgName = extensionInfo[0];
String name = extensionInfo[1];
+ String missingBehaviour = extensionInfo[2];
Hashtable projectTargets = project.getTargets();
if (!projectTargets.containsKey(tgName)) {
- throw new BuildException("can't add target "
- + name + " to extension-point "
- + tgName
- + " because the extension-point"
- + " is unknown.");
- }
- Target t = (Target) projectTargets.get(tgName);
- if (!(t instanceof ExtensionPoint)) {
- throw new BuildException("referenced target "
- + tgName
- + " is not an extension-point");
+ String message = "can't add target " + name
+ + " to extension-point " + tgName
+ + " because the extension-point is unknown.";
+ if (missingBehaviour.equals(MISSING_EP_FAIL)) {
+ throw new BuildException(message);
+ } else if (missingBehaviour.equals(MISSING_EP_WARN)) {
+ Target target = (Target) projectTargets.get(name);
+ context.getProject().log(target,
+ "Warning: " + message,
+ Project.MSG_WARN);
+ }
+ } else {
+ Target t = (Target) projectTargets.get(tgName);
+ if (!(t instanceof ExtensionPoint)) {
+ throw new BuildException("referenced target "
+ + tgName
+ + " is not an
extension-point");
+ }
+ t.addDependency(name);
}
- t.addDependency(name);
}
}
}
@@ -250,7 +259,7 @@ public class ProjectHelper2 extends Proj
buildFileName = url.toString();
} else {
throw new BuildException("Source " + source.getClass().getName()
- + " not supported by this plugin");
+ + " not supported by this plugin");
}
InputStream inputStream = null;
InputSource inputSource = null;
@@ -297,7 +306,7 @@ public class ProjectHelper2 extends Proj
parser.parse(inputSource);
} catch (SAXParseException exc) {
Location location = new Location(exc.getSystemId(),
exc.getLineNumber(), exc
- .getColumnNumber());
+ .getColumnNumber());
Throwable t = exc.getException();
if (t instanceof BuildException) {
@@ -317,11 +326,11 @@ public class ProjectHelper2 extends Proj
} catch (FileNotFoundException exc) {
throw new BuildException(exc);
} catch (UnsupportedEncodingException exc) {
- throw new BuildException("Encoding of project file " +
buildFileName + " is invalid.",
- exc);
+ throw new BuildException("Encoding of project file " +
buildFileName + " is invalid.",
+ exc);
} catch (IOException exc) {
throw new BuildException("Error reading project file " +
buildFileName + ": "
- + exc.getMessage(), exc);
+ + exc.getMessage(), exc);
} finally {
FileUtils.close(inputStream);
ZipFile.closeQuietly(zf);
@@ -440,7 +449,7 @@ public class ProjectHelper2 extends Proj
public AntHandler onStartChild(String uri, String tag, String qname,
Attributes attrs,
AntXMLContext context) throws
SAXParseException {
throw new SAXParseException("Unexpected element \"" + qname + "
\"", context
- .getLocator());
+ .getLocator());
}
/**
@@ -453,7 +462,7 @@ public class ProjectHelper2 extends Proj
* @exception SAXParseException if an error occurs
*/
public void onEndChild(String uri, String tag, String qname,
AntXMLContext context)
- throws SAXParseException {
+ throws SAXParseException {
}
/**
@@ -480,7 +489,7 @@ public class ProjectHelper2 extends Proj
* case of error in an overridden version
*/
public void characters(char[] buf, int start, int count, AntXMLContext
context)
- throws SAXParseException {
+ throws SAXParseException {
String s = new String(buf, start, count).trim();
if (s.length() > 0) {
@@ -548,9 +557,9 @@ public class ProjectHelper2 extends Proj
if (!file.isAbsolute()) {
file =
FILE_UTILS.resolveFile(context.getBuildFileParent(), path);
context.getProject().log(
- "Warning: '" + systemId + "' in " +
context.getBuildFile()
- + " should be expressed simply as '" +
path.replace('\\', '/')
- + "' for compliance with other XML tools",
Project.MSG_WARN);
+ "Warning: '" + systemId + "' in "
+ context.getBuildFile()
+ + " should be expressed simply as
'" + path.replace('\\', '/')
+ + "' for compliance with other
XML tools", Project.MSG_WARN);
}
context.getProject().log("file=" + file, Project.MSG_DEBUG);
try {
@@ -559,7 +568,7 @@ public class ProjectHelper2 extends Proj
return inputSource;
} catch (FileNotFoundException fne) {
context.getProject().log(file.getAbsolutePath() + " could
not be found",
- Project.MSG_WARN);
+ Project.MSG_WARN);
}
}
@@ -583,7 +592,7 @@ public class ProjectHelper2 extends Proj
* <code>"project"</code>
*/
public void startElement(String uri, String tag, String qname,
Attributes attrs)
- throws SAXParseException {
+ throws SAXParseException {
AntHandler next = currentHandler.onStartChild(uri, tag, qname,
attrs, context);
antHandlers.push(currentHandler);
currentHandler = next;
@@ -678,10 +687,10 @@ public class ProjectHelper2 extends Proj
}
if (name.equals(qname)) {
throw new SAXParseException("Unexpected element \"{" + uri
- + "}" + name + "\" {" + ANT_CORE_URI + "}" + name,
context.getLocator());
+ + "}" + name + "\" {" +
ANT_CORE_URI + "}" + name, context.getLocator());
}
throw new SAXParseException("Unexpected element \"" + qname
- + "\" " + name, context.getLocator());
+ + "\" " + name, context.getLocator());
}
}
@@ -774,7 +783,7 @@ public class ProjectHelper2 extends Proj
} else {
// XXX ignore attributes in a different NS ( maybe store
them ? )
throw new SAXParseException("Unexpected attribute \"" +
attrs.getQName(i)
- + "\"", context.getLocator());
+ + "\"", context.getLocator());
}
}
@@ -805,8 +814,8 @@ public class ProjectHelper2 extends Proj
if (context.isIgnoringProjectTag() &&
!dupFile.equals(contextFile)) {
project.log("Duplicated project name in import. Project "
- + context.getCurrentProjectName() + " defined
first in " + dup
- + " and again in " + contextFile,
Project.MSG_WARN);
+ + context.getCurrentProjectName() + " defined
first in " + dup
+ + " and again in " + contextFile,
Project.MSG_WARN);
}
}
if (nameAttributeSet) {
@@ -839,7 +848,7 @@ public class ProjectHelper2 extends Proj
project.setBasedir(baseDir);
} else {
project.setBaseDir(FILE_UTILS.resolveFile(context.getBuildFileParent(),
- baseDir));
+ baseDir));
}
}
}
@@ -905,6 +914,7 @@ public class ProjectHelper2 extends Proj
String name = null;
String depends = "";
String extensionPoint = null;
+ String extensionPointMissing = null;
Project project = context.getProject();
Target target = "target".equals(tag)
@@ -940,15 +950,17 @@ public class ProjectHelper2 extends Proj
target.setDescription(value);
} else if (key.equals("extensionOf")) {
extensionPoint = value;
+ } else if (key.equals("onMissingExtensionPoint")) {
+ extensionPointMissing = value;
} else {
throw new SAXParseException("Unexpected attribute \"" +
key + "\"", context
- .getLocator());
+ .getLocator());
}
}
if (name == null) {
throw new SAXParseException("target element appears without a
name attribute",
- context.getLocator());
+ context.getLocator());
}
String prefix = null;
@@ -978,7 +990,7 @@ public class ProjectHelper2 extends Proj
// If the name has not already been defined define it
if (projectTargets.containsKey(name)) {
project.log("Already defined in main or a previous import,
ignore " + name,
- Project.MSG_VERBOSE);
+ Project.MSG_VERBOSE);
} else {
target.setName(name);
context.getCurrentTargets().put(name, target);
@@ -1008,10 +1020,16 @@ public class ProjectHelper2 extends Proj
context.getCurrentTargets().put(newName, newTarget);
project.addOrReplaceTarget(newName, newTarget);
}
+ if (extensionPointMissing != null && extensionPoint == null) {
+ throw new BuildException("onMissingExtensionPoint attribute
cannot " +
+ "be specified unless extensionOf is
specified",
+ target.getLocation());
+
+ }
if (extensionPoint != null) {
ProjectHelper helper =
(ProjectHelper) context.getProject().
- getReference(ProjectHelper.PROJECTHELPER_REFERENCE);
+ getReference(ProjectHelper.PROJECTHELPER_REFERENCE);
for (Iterator iter =
Target.parseDepends(extensionPoint, name,
"extensionOf")
.iterator();
@@ -1020,12 +1038,26 @@ public class ProjectHelper2 extends Proj
if (isInIncludeMode()) {
tgName = prefix + sep + tgName;
}
-
- // defer extensionpoint resolution until the full
- // import stack has been processed
- helper.getExtensionStack().add(new String[] {
- tgName, name
- });
+ if (extensionPointMissing == null) {
+ extensionPointMissing = MISSING_EP_FAIL;
+ }
+ if (extensionPointMissing.equals(MISSING_EP_FAIL) ||
+ extensionPointMissing.equals(MISSING_EP_IGNORE) ||
+ extensionPointMissing.equals(MISSING_EP_WARN)) {
+ // defer extensionpoint resolution until the full
+ // import stack has been processed
+ helper.getExtensionStack().add(new String[] {
+ tgName, name, extensionPointMissing
+ });
+ } else {
+ throw new BuildException("onMissingExtensionPoint"
+ + " attribute can only be '"
+ + MISSING_EP_FAIL
+ + "', '" + MISSING_EP_WARN
+ + "' or '" + MISSING_EP_IGNORE
+ + "'",
+ target.getLocation());
+ }
}
}
}
@@ -1128,7 +1160,7 @@ public class ProjectHelper2 extends Proj
task.setTaskName(qname);
Location location = new
Location(context.getLocator().getSystemId(), context
- .getLocator().getLineNumber(),
context.getLocator().getColumnNumber());
+ .getLocator().getLineNumber(),
context.getLocator().getColumnNumber());
task.setLocation(location);
task.setOwningTarget(context.getCurrentTarget());
@@ -1159,8 +1191,8 @@ public class ProjectHelper2 extends Proj
// be namespaced, need to extract the name
// and convert from qualified name to uri/name
if (ANT_TYPE.equals(name)
- || (ANT_CORE_URI.equals(attrUri)
- && ANT_TYPE.equals(attrs.getLocalName(i)))) {
+ || (ANT_CORE_URI.equals(attrUri)
+ && ANT_TYPE.equals(attrs.getLocalName(i)))) {
name = ANT_TYPE;
int index = value.indexOf(":");
if (index >= 0) {
@@ -1168,10 +1200,10 @@ public class ProjectHelper2 extends Proj
String mappedUri = context.getPrefixMapping(prefix);
if (mappedUri == null) {
throw new BuildException("Unable to find XML NS
prefix \"" + prefix
- + "\"");
+ + "\"");
}
value = ProjectHelper.genComponentName(mappedUri, value
- .substring(index + 1));
+
.substring(index + 1));
}
}
wrapper.setAttribute(name, value);
Modified:
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/AntStructure.java
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/AntStructure.java?rev=957170&r1=957169&r2=957170&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/AntStructure.java
(original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/AntStructure.java Wed
Jun 23 12:15:13 2010
@@ -106,8 +106,8 @@ public class AntStructure extends Task {
while (dataTypes.hasNext()) {
String typeName = (String) dataTypes.next();
printer.printElementDecl(
- out, getProject(), typeName,
- (Class)
getProject().getDataTypeDefinitions().get(typeName));
+ out, getProject(), typeName,
+ (Class)
getProject().getDataTypeDefinitions().get(typeName));
}
Iterator tasks = getProject().getCopyOfTaskDefinitions().keySet()
@@ -266,13 +266,14 @@ public class AntStructure extends Task {
private void printTargetAttrs(PrintWriter out, String tag) {
out.print("<!ATTLIST ");
out.println(tag);
- out.println(" id ID #IMPLIED");
- out.println(" name CDATA #REQUIRED");
- out.println(" if CDATA #IMPLIED");
- out.println(" unless CDATA #IMPLIED");
- out.println(" depends CDATA #IMPLIED");
- out.println(" extensionOf CDATA #IMPLIED");
- out.println(" description CDATA #IMPLIED>");
+ out.println(" id ID #IMPLIED");
+ out.println(" name CDATA #REQUIRED");
+ out.println(" if CDATA #IMPLIED");
+ out.println(" unless CDATA #IMPLIED");
+ out.println(" depends CDATA #IMPLIED");
+ out.println(" extensionOf CDATA #IMPLIED");
+ out.println(" onMissingExtensionPoint CDATA #IMPLIED");
+ out.println(" description CDATA #IMPLIED>");
out.println("");
}
Modified: ant/core/trunk/src/tests/antunit/core/extension-point-test.xml
URL:
http://svn.apache.org/viewvc/ant/core/trunk/src/tests/antunit/core/extension-point-test.xml?rev=957170&r1=957169&r2=957170&view=diff
==============================================================================
--- ant/core/trunk/src/tests/antunit/core/extension-point-test.xml (original)
+++ ant/core/trunk/src/tests/antunit/core/extension-point-test.xml Wed Jun 23
12:15:13 2010
@@ -88,4 +88,49 @@
<au:assertLogContains text="in target prepare"/>
</target>
+ <target name="testMissingExtensionPointCausesError">
+ <mkdir dir="${output}"/>
+ <echo file="${output}/build.xml"><![CDATA[
+<project default="bar">
+ <target name="bar" extensionOf="foo"/>
+</project>]]></echo>
+ <au:expectfailure
+ expectedMessage="can't add target bar to extension-point foo because
the extension-point is unknown">
+ <ant dir="${output}" target="bar"/>
+ </au:expectfailure>
+ </target>
+
+ <target name="testMissingExtensionPointCausesWarningWhenConfigured">
+ <mkdir dir="${output}"/>
+ <echo file="${output}/build.xml"><![CDATA[
+<project default="bar">
+ <target name="bar" extensionOf="foo" onMissingExtensionPoint="warn"/>
+</project>]]></echo>
+ <ant dir="${output}" target="bar"/>
+ <au:assertLogContains level="warning"
+ text="can't add target bar to extension-point foo because the
extension-point is unknown" />
+ </target>
+
+ <target name="testMissingExtensionPointIgnoredWhenConfigured">
+ <mkdir dir="${output}"/>
+ <echo file="${output}/build.xml"><![CDATA[
+<project default="bar">
+ <target name="bar" extensionOf="foo" onMissingExtensionPoint="ignore"/>
+</project>]]></echo>
+ <ant dir="${output}" target="bar"/>
+ <au:assertLogDoesntContain level="warning"
+ text="can't add target bar to extension-point foo because the
extension-point is unknown" />
+ </target>
+
+ <target
name="testOnlyAllowsExtensionPointMissingAttributeWhenExtensionOfPresent">
+ <mkdir dir="${output}"/>
+ <echo file="${output}/build.xml"><![CDATA[
+<project default="bar">
+ <target name="bar" onMissingExtensionPoint="ignore"/>
+</project>]]></echo>
+ <au:expectfailure
+ expectedMessage="onMissingExtensionPoint attribute cannot be specified
unless extensionOf is specified">
+ <ant dir="${output}" target="bar"/>
+ </au:expectfailure>
+ </target>
</project>