diff --git a/src/main/org/apache/tools/ant/AntTypeDefinition.java b/src/main/org/apache/tools/ant/AntTypeDefinition.java index 5a24182da..0e3dd3a34 100644 --- a/src/main/org/apache/tools/ant/AntTypeDefinition.java +++ b/src/main/org/apache/tools/ant/AntTypeDefinition.java @@ -329,7 +329,7 @@ public class AntTypeDefinition { } /** - * Equality method for this definition + * Equality method for this definition (assumes the names are the same) * * @param other another definition * @param project the project the definition @@ -345,6 +345,69 @@ public class AntTypeDefinition { if (!(other.getTypeClass(project).equals(getTypeClass(project)))) { return false; } - return other.getExposedClass(project).equals(getExposedClass(project)); + if (!other.getExposedClass(project).equals(getExposedClass(project))) { + return false; + } + if (other.adapterClass != adapterClass) { + return false; + } + if (other.adaptToClass != adaptToClass) { + return false; + } + return true; + } + + /** + * Similar definition + * used to compare two definitions defined twice with the same + * name and the same types. + * the classloader may be different but have the same + * path so #sameDefinition cannot + * be used. + * @param other the definition to compare to + * @param project the current project + * @return true if the definitions are the same + */ + public boolean similarDefinition(AntTypeDefinition other, Project project) { + if (other == null) { + return false; + } + if (getClass() != other.getClass()) { + return false; + } + if (!getClassName().equals(other.getClassName())) { + return false; + } + if (!extractClassname(adapterClass).equals( + extractClassname(other.adapterClass))) { + return false; + } + if (!extractClassname(adaptToClass).equals( + extractClassname(other.adaptToClass))) { + return false; + } + // all the names are the same: check if the class path of the loader + // is the same + ClassLoader oldLoader = other.getClassLoader(); + ClassLoader newLoader = this.getClassLoader(); + if (oldLoader != null + && newLoader != null + && oldLoader instanceof AntClassLoader + && newLoader instanceof AntClassLoader + && ((AntClassLoader) oldLoader).getClasspath() + .equals(((AntClassLoader) newLoader).getClasspath()) + ) { + return true; + } else { + return false; + } + } + + private String extractClassname(Class c) { + if (c == null) { + return ""; + } else { + return c.getClass().getName(); + } } } diff --git a/src/main/org/apache/tools/ant/ComponentHelper.java b/src/main/org/apache/tools/ant/ComponentHelper.java index 3d1837168..5af83be28 100644 --- a/src/main/org/apache/tools/ant/ComponentHelper.java +++ b/src/main/org/apache/tools/ant/ComponentHelper.java @@ -670,21 +670,19 @@ public class ComponentHelper { if (sameDefinition(def, old)) { return; } + int logLevel = Project.MSG_WARN; + if (def.similarDefinition(old, project)) { + logLevel = Project.MSG_VERBOSE; + } Class oldClass = antTypeTable.getExposedClass(name); - if (oldClass != null && Task.class.isAssignableFrom(oldClass)) { - int logLevel = Project.MSG_WARN; - if (def.getClassName().equals(old.getClassName()) - && def.getClassLoader() == old.getClassLoader()) { - logLevel = Project.MSG_VERBOSE; - } - project.log( - "Trying to override old definition of task " - + name, logLevel); + boolean isTask = + (oldClass != null && Task.class.isAssignableFrom(oldClass)); + project.log( + "Trying to override old definition of " + + (isTask ? "task" : "datatype") + + " " + name, logLevel); + if (isTask) { invalidateCreatedTasks(name); - } else { - project.log( - "Trying to override old definition of datatype " - + name, Project.MSG_WARN); } } project.log(" +Datatype " + name + " " + def.getClassName(), diff --git a/src/main/org/apache/tools/ant/UnknownElement.java b/src/main/org/apache/tools/ant/UnknownElement.java index b0f69c206..d2854e98f 100644 --- a/src/main/org/apache/tools/ant/UnknownElement.java +++ b/src/main/org/apache/tools/ant/UnknownElement.java @@ -530,4 +530,52 @@ public class UnknownElement extends Task { } return false; } + + /** + * like contents equals, but ignores project + * @param obj the object to check against + * @return true if this unknownelement has the same contents the other + */ + public boolean similar(Object obj) { + if (obj == null) { + return false; + } + if (!getClass().getName().equals(obj.getClass().getName())) { + return false; + } + UnknownElement other = (UnknownElement) obj; + if (!equalsString(elementName, other.elementName)) { + return false; + } + if (!namespace.equals(other.namespace)) { + return false; + } + if (!qname.equals(other.qname)) { + return false; + } + if (!getWrapper().getAttributeMap().equals( + other.getWrapper().getAttributeMap())) { + return false; + } + if (children == null) { + return other.children == null; + } + if (children.size() != other.children.size()) { + return false; + } + for (int i = 0; i < children.size(); ++i) { + UnknownElement child = (UnknownElement) children.get(i); + if (!child.similar(other.children.get(i))) { + return false; + } + } + return true; + } + + private boolean equalsString(String a, String b) { + if (a == null) { + return b == null; + } + return a.equals(b); + } } diff --git a/src/main/org/apache/tools/ant/taskdefs/DefBase.java b/src/main/org/apache/tools/ant/taskdefs/DefBase.java index 818317bb0..73c45a600 100644 --- a/src/main/org/apache/tools/ant/taskdefs/DefBase.java +++ b/src/main/org/apache/tools/ant/taskdefs/DefBase.java @@ -93,7 +93,7 @@ public abstract class DefBase extends Task implements AntlibInterface { if (uri.equals(ProjectHelper.ANT_CORE_URI)) { uri = ""; } - if (uri.startsWith("ant:") && !uri.startsWith("antlib:")) { + if (uri.startsWith("ant:")) { throw new BuildException("Attempt to use a reserved URI " + uri); } this.uri = uri; diff --git a/src/main/org/apache/tools/ant/taskdefs/MacroDef.java b/src/main/org/apache/tools/ant/taskdefs/MacroDef.java index dd5a05d62..0197beb8d 100644 --- a/src/main/org/apache/tools/ant/taskdefs/MacroDef.java +++ b/src/main/org/apache/tools/ant/taskdefs/MacroDef.java @@ -102,7 +102,7 @@ public class MacroDef extends Task implements AntlibInterface, TaskContainer { if (uri.equals(ProjectHelper.ANT_CORE_URI)) { uri = ""; } - if (uri.startsWith("ant:") && !uri.startsWith("antlib:")) { + if (uri.startsWith("ant:")) { throw new BuildException("Attempt to use a reserved URI " + uri); } this.uri = uri; @@ -283,6 +283,7 @@ public class MacroDef extends Task implements AntlibInterface, TaskContainer { public static class Attribute { private String name; private String defaultValue; + /** * The name of the attribute. * @@ -319,6 +320,35 @@ public class MacroDef extends Task implements AntlibInterface, TaskContainer { public String getDefault() { return defaultValue; } + + /** + * equality method + * + * @param obj an Object value + * @return a boolean value + */ + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj.getClass() != getClass()) { + return false; + } + Attribute other = (Attribute) obj; + if (name == null) { + return other.name == null; + } + if (!name.equals(other.name)) { + return false; + } + if (defaultValue == null) { + return other.defaultValue == null; + } + if (!name.equals(other.defaultValue)) { + return false; + } + return true; + } } /** @@ -364,6 +394,74 @@ public class MacroDef extends Task implements AntlibInterface, TaskContainer { public boolean isOptional() { return optional; } + + /** + * equality method + * + * @param obj an Object value + * @return a boolean value + */ + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj.getClass() != getClass()) { + return false; + } + TemplateElement other = (TemplateElement) obj; + if (name == null) { + return other.name == null; + } + if (!name.equals(other.name)) { + return false; + } + return optional == other.optional; + } + } + + /** + * equality method for macrodef, ignores project and + * runtime info. + * + * @param obj an Object value + * @return a boolean value + */ + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (!obj.getClass().equals(getClass())) { + return false; + } + MacroDef other = (MacroDef) obj; + if (name == null) { + return other.name == null; + } + if (!name.equals(other.name)) { + return false; + } + if (uri == null || uri.equals("") + || uri.equals(ProjectHelper.ANT_CORE_URI)) { + return other.uri == null || other.uri.equals("") + || other.uri.equals(ProjectHelper.ANT_CORE_URI); + } + if (!uri.equals(other.uri)) { + return false; + } + + if (attributeStyle != other.attributeStyle) { + return false; + } + if (!nestedTask.similar(other.nestedTask)) { + return false; + } + if (!attributes.equals(other.attributes)) { + return false; + } + if (!elements.equals(other.elements)) { + return false; + } + return true; } /** @@ -372,15 +470,15 @@ public class MacroDef extends Task implements AntlibInterface, TaskContainer { * is given. */ private static class MyAntTypeDefinition extends AntTypeDefinition { - private MacroDef template; + private MacroDef macroDef; /** * Creates a new MyAntTypeDefinition instance. * - * @param template a MacroDef value + * @param macroDef a MacroDef value */ - public MyAntTypeDefinition(MacroDef template) { - this.template = template; + public MyAntTypeDefinition(MacroDef macroDef) { + this.macroDef = macroDef; } /** @@ -394,20 +492,39 @@ public class MacroDef extends Task implements AntlibInterface, TaskContainer { if (o == null) { return null; } - ((MacroInstance) o).setTemplate(template); + ((MacroInstance) o).setMacroDef(macroDef); return o; } /** * Equality method for this definition - * This only checks for pointer equality. * * @param other another definition * @param project the current project * @return true if the definitions are the same */ public boolean sameDefinition(AntTypeDefinition other, Project project) { - return this == other; + if (!super.sameDefinition(other, project)) { + return false; + } + MyAntTypeDefinition otherDef = (MyAntTypeDefinition) other; + return macroDef.equals(otherDef.macroDef); + } + + /** + * Similiar method for this definition + * + * @param other another definition + * @param project the current project + * @return true if the definitions are the same + */ + public boolean similarDefinition( + AntTypeDefinition other, Project project) { + if (!super.similarDefinition(other, project)) { + return false; + } + MyAntTypeDefinition otherDef = (MyAntTypeDefinition) other; + return macroDef.equals(otherDef.macroDef); } } } diff --git a/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java b/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java index 027561e02..856f4c053 100644 --- a/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java +++ b/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java @@ -80,7 +80,7 @@ import org.apache.tools.ant.RuntimeConfigurable; * @since Ant 1.6 */ public class MacroInstance extends Task implements DynamicConfigurator { - private MacroDef template; + private MacroDef macroDef; private Map map = new HashMap(); private Map elements = new HashMap(); private Hashtable localProperties = new Hashtable(); @@ -88,10 +88,10 @@ public class MacroInstance extends Task implements DynamicConfigurator { /** * Called from MacroDef.MyAntTypeDefinition#create() * - * @param template a MacroDef value + * @param macroDef a MacroDef value */ - protected void setTemplate(MacroDef template) { - this.template = template; + protected void setMacroDef(MacroDef macroDef) { + this.macroDef = macroDef; } /** @@ -112,7 +112,7 @@ public class MacroInstance extends Task implements DynamicConfigurator { * has already been seen */ public Object createDynamicElement(String name) throws BuildException { - if (template.getElements().get(name) == null) { + if (macroDef.getElements().get(name) == null) { throw new BuildException("unsupported element " + name); } if (elements.get(name) != null) { @@ -130,7 +130,7 @@ public class MacroInstance extends Task implements DynamicConfigurator { private List unknownElements = new ArrayList(); /** - * Add an unknown element (to be snipped into the template instance) + * Add an unknown element (to be snipped into the macroDef instance) * * @param nestedTask an unknown element */ @@ -225,7 +225,7 @@ public class MacroInstance extends Task implements DynamicConfigurator { } private String macroSubs(String s, Map macroMapping) { - if (template.getAttributeStyle() == MacroDef.AttributeStyle.ANT) { + if (macroDef.getAttributeStyle() == MacroDef.AttributeStyle.ANT) { return macroSubsAnt(s, macroMapping); } else { return macroSubsXPath(s, macroMapping); @@ -259,7 +259,7 @@ public class MacroInstance extends Task implements DynamicConfigurator { UnknownElement unknownElement = (UnknownElement) r.getProxy(); String tag = unknownElement.getTag(); MacroDef.TemplateElement templateElement = - (MacroDef.TemplateElement) template.getElements().get(tag); + (MacroDef.TemplateElement) macroDef.getElements().get(tag); if (templateElement == null) { UnknownElement child = copy(unknownElement); rc.addChild(child.getWrapper()); @@ -294,9 +294,9 @@ public class MacroInstance extends Task implements DynamicConfigurator { public void execute() { localProperties = new Hashtable(); Set copyKeys = new HashSet(map.keySet()); - for (int i = 0; i < template.getAttributes().size(); ++i) { + for (int i = 0; i < macroDef.getAttributes().size(); ++i) { MacroDef.Attribute attribute = - (MacroDef.Attribute) template.getAttributes().get(i); + (MacroDef.Attribute) macroDef.getAttributes().get(i); String value = (String) map.get(attribute.getName()); if (value == null) { value = attribute.getDefault(); @@ -315,7 +315,7 @@ public class MacroInstance extends Task implements DynamicConfigurator { } // need to set the project on unknown element - UnknownElement c = copy(template.getNestedTask()); + UnknownElement c = copy(macroDef.getNestedTask()); c.init(); c.perform(); } diff --git a/src/main/org/apache/tools/ant/taskdefs/PreSetDef.java b/src/main/org/apache/tools/ant/taskdefs/PreSetDef.java index af57d885c..99c2b40f0 100644 --- a/src/main/org/apache/tools/ant/taskdefs/PreSetDef.java +++ b/src/main/org/apache/tools/ant/taskdefs/PreSetDef.java @@ -99,7 +99,7 @@ public class PreSetDef extends Task implements AntlibInterface, TaskContainer { if (uri.equals(ProjectHelper.ANT_CORE_URI)) { uri = ""; } - if (uri.startsWith("ant:") && !uri.startsWith("antlib:")) { + if (uri.startsWith("ant:")) { throw new BuildException("Attempt to use a reserved URI " + uri); } this.uri = uri; @@ -266,14 +266,51 @@ public class PreSetDef extends Task implements AntlibInterface, TaskContainer { /** * Equality method for this definition - * This only checks for pointer equality. * * @param other another definition * @param project the current project * @return true if the definitions are the same */ public boolean sameDefinition(AntTypeDefinition other, Project project) { - return this == other; + if (other == null) { + return false; + } + if (other.getClass() != getClass()) { + return false; + } + MyAntTypeDefinition otherDef = (MyAntTypeDefinition) other; + if (!parent.sameDefinition(otherDef.parent, project)) { + return false; + } + if (!element.similar(otherDef.element)) { + return false; + } + return true; + } + + /** + * Similiar method for this definition + * + * @param other another definition + * @param project the current project + * @return true if the definitions are the same + */ + public boolean similarDefinition( + AntTypeDefinition other, Project project) { + if (other == null) { + return false; + } + if (!other.getClass().getName().equals(getClass().getName())) { + return false; + } + MyAntTypeDefinition otherDef = (MyAntTypeDefinition) other; + if (!parent.similarDefinition(otherDef.parent, project)) { + return false; + } + if (!element.similar(otherDef.element)) { + return false; + } + return true; } } }