in src/main/org/apache/tools/ant/IntrospectionHelper.java [187:306]
private IntrospectionHelper(final Class<?> bean) {
this.bean = bean;
Method addTextMethod = null;
for (final Method m : bean.getMethods()) {
final String name = m.getName();
final Class<?> returnType = m.getReturnType();
final Class<?>[] args = m.getParameterTypes();
// check of add[Configured](Class) pattern
if (args.length == 1 && Void.TYPE.equals(returnType)
&& ("add".equals(name) || "addConfigured".equals(name))) {
insertAddTypeMethod(m);
continue;
}
// not really user settable properties on tasks/project components
if (ProjectComponent.class.isAssignableFrom(bean)
&& args.length == 1 && isHiddenSetMethod(name, args[0])) {
continue;
}
// hide addTask for TaskContainers
if (isContainer() && args.length == 1 && "addTask".equals(name)
&& Task.class.equals(args[0])) {
continue;
}
if ("addText".equals(name) && Void.TYPE.equals(returnType)
&& args.length == 1 && String.class.equals(args[0])) {
addTextMethod = m;
} else if (name.startsWith("set") && Void.TYPE.equals(returnType)
&& args.length == 1 && !args[0].isArray()) {
final String propName = getPropertyName(name, "set");
AttributeSetter as = attributeSetters.get(propName);
if (as != null) {
if (String.class.equals(args[0])) {
/*
Ignore method m, as there is an overloaded
form of this method that takes in a
non-string argument, which gains higher
priority.
*/
continue;
}
if (File.class.equals(args[0])) {
// Ant Resources/FileProviders override java.io.File
if (Resource.class.equals(as.type) || FileProvider.class.equals(as.type)) {
continue;
}
}
/*
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
that depends on the order in which "set" methods have
been defined, is not guaranteed to be selected in any
particular order.
*/
}
as = createAttributeSetter(m, args[0], propName);
if (as != null) {
attributeTypes.put(propName, args[0]);
attributeSetters.put(propName, as);
}
} else if (name.startsWith("create") && !returnType.isArray()
&& !returnType.isPrimitive() && args.length == 0) {
final String propName = getPropertyName(name, "create");
// Check if a create of this property is already present
// add takes preference over create for CB purposes
if (nestedCreators.get(propName) == null) {
nestedTypes.put(propName, returnType);
nestedCreators.put(propName, new CreateNestedCreator(m));
}
} else if (name.startsWith("addConfigured")
&& Void.TYPE.equals(returnType) && args.length == 1
&& !String.class.equals(args[0])
&& !args[0].isArray() && !args[0].isPrimitive()) {
try {
Constructor<?> constructor = null;
try {
constructor = args[0].getConstructor();
} catch (final NoSuchMethodException ex) {
constructor = args[0].getConstructor(Project.class);
}
final String propName = getPropertyName(name, "addConfigured");
nestedTypes.put(propName, args[0]);
nestedCreators.put(propName, new AddNestedCreator(m,
constructor, AddNestedCreator.ADD_CONFIGURED));
} catch (final NoSuchMethodException nse) {
// ignore
}
} else if (name.startsWith("add")
&& Void.TYPE.equals(returnType) && args.length == 1
&& !String.class.equals(args[0])
&& !args[0].isArray() && !args[0].isPrimitive()) {
try {
Constructor<?> constructor = null;
try {
constructor = args[0].getConstructor();
} catch (final NoSuchMethodException ex) {
constructor = args[0].getConstructor(Project.class);
}
final String propName = getPropertyName(name, "add");
if (nestedTypes.get(propName) != null) {
/*
* Ignore this method as there is an addConfigured
* form of this method that has a higher
* priority
*/
continue;
}
nestedTypes.put(propName, args[0]);
nestedCreators.put(propName, new AddNestedCreator(m,
constructor, AddNestedCreator.ADD));
} catch (final NoSuchMethodException nse) {
// ignore
}
}
}
addText = addTextMethod;
}