diff --git a/src/main/org/apache/tools/ant/IntrospectionHelper.java b/src/main/org/apache/tools/ant/IntrospectionHelper.java index 52bf574f5..cc55e6d92 100644 --- a/src/main/org/apache/tools/ant/IntrospectionHelper.java +++ b/src/main/org/apache/tools/ant/IntrospectionHelper.java @@ -29,6 +29,9 @@ import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.resources.FileProvider; +import org.apache.tools.ant.types.resources.FileResource; import org.apache.tools.ant.taskdefs.PreSetDef; import org.apache.tools.ant.util.StringUtils; @@ -137,9 +140,14 @@ public final class IntrospectionHelper { * adding PCDATA to a bean. *
  • void setFoo(Bar) is recognised as a method for * setting the value of attribute foo, so long as - * Bar is non-void and is not an array type. Non-String - * parameter types always overload String parameter types, but that is - * the only guarantee made in terms of priority. + * Bar is non-void and is not an array type. + * As of Ant 1.8, a Resource or FileProvider parameter overrides a java.io.File parameter; + * in practice the only effect of this is to allow objects rendered from + * the 1.8 PropertyHelper implementation to be used as Resource parameters, + * since Resources set from Strings are resolved as project-relative files + * to preserve backward compatibility. Beyond this, non-String + * parameter types always overload String parameter types; these are + * the only guarantees made in terms of priority. *
  • Foo createBar() is recognised as a method for * creating a nested element called bar of type * Foo, so long as Foo is not a primitive or @@ -198,7 +206,8 @@ public final class IntrospectionHelper { } else if (name.startsWith("set") && java.lang.Void.TYPE.equals(returnType) && args.length == 1 && !args[0].isArray()) { String propName = getPropertyName(name, "set"); - if (attributeSetters.get(propName) != null) { + AttributeSetter as = (AttributeSetter) attributeSetters.get(propName); + if (as != null) { if (java.lang.String.class.equals(args[0])) { /* Ignore method m, as there is an overloaded @@ -208,9 +217,14 @@ public final class IntrospectionHelper { */ continue; } + if (java.io.File.class.equals(args[0])) { + // Ant Resources/FileProviders override java.io.File + if (Resource.class.equals(as.type) || FileProvider.class.equals(as.type)) { + continue; + } + } /* - If the argument is not a String and if there - is an overloaded form of this method already defined, + In cases other than those just explicitly covered, we just override that with the new one. This mechanism does not guarantee any specific order in which the methods will be selected: so any code @@ -219,7 +233,7 @@ public final class IntrospectionHelper { particular order. */ } - AttributeSetter as = createAttributeSetter(m, args[0], propName); + as = createAttributeSetter(m, args[0], propName); if (as != null) { attributeTypes.put(propName, args[0]); attributeSetters.put(propName, as); @@ -930,6 +944,8 @@ public final class IntrospectionHelper { *
  • Class (Class.forName is used) *
  • File (resolved relative to the appropriate project) *
  • Path (resolve relative to the appropriate project) + *
  • Resource (resolved as a FileResource relative to the appropriate project) + *
  • FileProvider (resolved as a FileResource relative to the appropriate project) *
  • EnumeratedAttribute (uses its own * {@link EnumeratedAttribute#setValue(String) setValue} method) *
  • Other primitive types (wrapper classes are used with constructors @@ -1022,6 +1038,15 @@ public final class IntrospectionHelper { } }; } + // resolve Resources/FileProviders as FileResources relative to Project: + if (Resource.class.equals(reflectedArg) || FileProvider.class.equals(reflectedArg)) { + return new AttributeSetter(m, arg) { + void set(Project p, Object parent, String value) throws InvocationTargetException, + IllegalAccessException, BuildException { + m.invoke(parent, new Object[] { new FileResource(p, p.resolveFile(value)) }); + }; + }; + } // EnumeratedAttributes have their own helper class if (EnumeratedAttribute.class.isAssignableFrom(reflectedArg)) { return new AttributeSetter(m, arg) {