From f5c95e9ca4ca7a2f05523c8205b378a43e1329c4 Mon Sep 17 00:00:00 2001 From: Peter Reilly Date: Tue, 17 Oct 2006 21:33:42 +0000 Subject: [PATCH] add fall-back for undefined references that are parsed git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@465065 13f79535-47bb-0310-9956-ffa450edef68 --- WHATSNEW | 3 + src/main/org/apache/tools/ant/Project.java | 56 ++++++++++++++++++- .../org/apache/tools/ant/UnknownElement.java | 43 ++++++++++++++ .../tools/ant/helper/AntXMLContext.java | 2 +- .../tools/ant/helper/ProjectHelper2.java | 2 + .../org/apache/tools/ant/taskdefs/Ant.java | 1 + .../antunit/types/defer-reference-test.xml | 8 +-- 7 files changed, 109 insertions(+), 6 deletions(-) diff --git a/WHATSNEW b/WHATSNEW index a8971e7cd..ce82b7223 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -16,6 +16,9 @@ Other changes: of Watchdog, ExecuteWatchdog and ExecuteJava, which could reduce the occurence of race conditions here, especially on Java1.5+. +* Allow broken reference build files. The defer reference processing would + break too many files - so allow them with a warning. + Changes from Ant 1.7.0Beta2 to Ant 1.7.0Beta3 ============================================= diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java index c52983a04..ace9e2956 100644 --- a/src/main/org/apache/tools/ant/Project.java +++ b/src/main/org/apache/tools/ant/Project.java @@ -33,6 +33,7 @@ import java.util.Stack; import java.util.Vector; import java.util.Set; import java.util.HashSet; +import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; import org.apache.tools.ant.input.DefaultInputHandler; @@ -61,6 +62,8 @@ import org.apache.tools.ant.util.StringUtils; * */ public class Project implements ResourceFactory { + private static final String LINE_SEP = System.getProperty("line.separator"); + /** Message priority of "error". */ public static final int MSG_ERR = 0; /** Message priority of "warning". */ @@ -136,6 +139,12 @@ public class Project implements ResourceFactory { /** Map of references within the project (paths etc) (String to Object). */ private Hashtable references = new AntRefTable(); + /** Map of id references - used for indicating broken build files */ + private HashMap idReferences = new HashMap(); + + /** the parent project for old id resolution (if inheritreferences is set) */ + private Project parentIdProject = null; + /** Name of the project's default target. */ private String defaultTarget; @@ -1814,6 +1823,46 @@ public class Project implements ResourceFactory { return new BuildException(new String(sb)); } + /** + * Inherit the id references. + * @param parent the parent project of this project. + */ + public void inheritIDReferences(Project parent) { + parentIdProject = parent; + } + + /** + * Attempt to resolve an Unknown Reference using the + * parsed id's - for BC. + */ + private Object resolveIdReference(String key, Project callerProject) { + UnknownElement origUE = (UnknownElement) idReferences.get(key); + if (origUE == null) { + return parentIdProject == null + ? null + : parentIdProject.resolveIdReference(key, callerProject); + } + callerProject.log( + "Warning: Reference " + key + " has not been set at runtime," + + " but was found during" + LINE_SEP + + "build file parsing, attempting to resolve." + + " Future versions of Ant may support" + LINE_SEP + + " referencing ids defined in non-executed targets.", MSG_WARN); + UnknownElement copyUE = origUE.copy(callerProject); + copyUE.maybeConfigure(); + return copyUE.getRealThing(); + } + + /** + * Add an id reference. + * Used for broken build files. + * @param id the id to set. + * @param value the value to set it to (Unknown element in this case. + */ + public void addIdReference(String id, Object value) { + idReferences.put(id, value); + } + /** * Add a reference to the project. * @@ -1856,7 +1905,12 @@ public class Project implements ResourceFactory { * there is no such reference in the project. */ public Object getReference(String key) { - return references.get(key); + Object ret = references.get(key); + if (ret != null) { + return ret; + } + // Check for old id behaviour + return resolveIdReference(key, this); } /** diff --git a/src/main/org/apache/tools/ant/UnknownElement.java b/src/main/org/apache/tools/ant/UnknownElement.java index 9f87109cd..3eabf17ac 100644 --- a/src/main/org/apache/tools/ant/UnknownElement.java +++ b/src/main/org/apache/tools/ant/UnknownElement.java @@ -19,8 +19,10 @@ package org.apache.tools.ant; import java.util.ArrayList; +import java.util.Enumeration; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.io.IOException; import org.apache.tools.ant.taskdefs.PreSetDef; @@ -621,4 +623,45 @@ public class UnknownElement extends Task { private static boolean equalsString(String a, String b) { return (a == null) ? (b == null) : a.equals(b); } + + /** + * Make a copy of the unknown element and set it in the new project. + * @param newProject the project to create the UE in. + * @return the copied UE. + */ + public UnknownElement copy(Project newProject) { + UnknownElement ret = new UnknownElement(getTag()); + ret.setNamespace(getNamespace()); + ret.setProject(newProject); + ret.setQName(getQName()); + ret.setTaskType(getTaskType()); + ret.setTaskName(getTaskName()); + ret.setLocation(getLocation()); + if (getOwningTarget() == null) { + Target t = new Target(); + t.setProject(getProject()); + ret.setOwningTarget(t); + } else { + ret.setOwningTarget(getOwningTarget()); + } + RuntimeConfigurable copyRC = new RuntimeConfigurable( + ret, getTaskName()); + copyRC.setPolyType(getWrapper().getPolyType()); + Map m = getWrapper().getAttributeMap(); + for (Iterator i = m.entrySet().iterator(); i.hasNext();) { + Map.Entry entry = (Map.Entry) i.next(); + copyRC.setAttribute( + (String) entry.getKey(), (String) entry.getValue()); + } + copyRC.addText(getWrapper().getText().toString()); + + for (Enumeration e = getWrapper().getChildren(); e.hasMoreElements();) { + RuntimeConfigurable r = (RuntimeConfigurable) e.nextElement(); + UnknownElement ueChild = (UnknownElement) r.getProxy(); + UnknownElement copyChild = ueChild.copy(newProject); + copyRC.addChild(copyChild.getWrapper()); + ret.addChild(copyChild); + } + return ret; + } } diff --git a/src/main/org/apache/tools/ant/helper/AntXMLContext.java b/src/main/org/apache/tools/ant/helper/AntXMLContext.java index f8faaabe4..dc2d40497 100644 --- a/src/main/org/apache/tools/ant/helper/AntXMLContext.java +++ b/src/main/org/apache/tools/ant/helper/AntXMLContext.java @@ -268,7 +268,7 @@ public class AntXMLContext { public void configureId(Object element, Attributes attr) { String id = attr.getValue("id"); if (id != null) { - project.addReference(id, element); + project.addIdReference(id, element); } } diff --git a/src/main/org/apache/tools/ant/helper/ProjectHelper2.java b/src/main/org/apache/tools/ant/helper/ProjectHelper2.java index 2f1efd428..74101a614 100644 --- a/src/main/org/apache/tools/ant/helper/ProjectHelper2.java +++ b/src/main/org/apache/tools/ant/helper/ProjectHelper2.java @@ -1015,6 +1015,8 @@ public class ProjectHelper2 extends ProjectHelper { context.getCurrentTarget().addTask(task); } + context.configureId(task, attrs); + // container.addTask(task); // This is a nop in UE: task.init(); diff --git a/src/main/org/apache/tools/ant/taskdefs/Ant.java b/src/main/org/apache/tools/ant/taskdefs/Ant.java index b0ecc7d07..2eaa9db7e 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Ant.java +++ b/src/main/org/apache/tools/ant/taskdefs/Ant.java @@ -491,6 +491,7 @@ public class Ant extends Task { continue; } copyReference(key, key); + newProject.inheritIDReferences(getProject()); } } } diff --git a/src/tests/antunit/types/defer-reference-test.xml b/src/tests/antunit/types/defer-reference-test.xml index 5a87e3e6e..2c546df74 100644 --- a/src/tests/antunit/types/defer-reference-test.xml +++ b/src/tests/antunit/types/defer-reference-test.xml @@ -5,10 +5,10 @@ - - - + + ${_output2} +