@@ -74,31 +74,31 @@ import org.apache.tools.ant.types.Path;
public class IntrospectionHelper implements BuildListener {
public class IntrospectionHelper implements BuildListener {
/**
/**
* Map from attribute names to attribute types
* Map from attribute names to attribute types
* (String to Class).
* (String to Class).
*/
*/
private Hashtable attributeTypes;
private Hashtable attributeTypes;
/**
/**
* Map from attribute names to attribute setter methods
* Map from attribute names to attribute setter methods
* (String to AttributeSetter).
* (String to AttributeSetter).
*/
*/
private Hashtable attributeSetters;
private Hashtable attributeSetters;
/**
/**
* Map from attribute names to nested types
* Map from attribute names to nested types
* (String to Class).
* (String to Class).
*/
*/
private Hashtable nestedTypes;
private Hashtable nestedTypes;
/**
/**
* Map from attribute names to methods to create nested types
* Map from attribute names to methods to create nested types
* (String to NestedCreator).
* (String to NestedCreator).
*/
*/
private Hashtable nestedCreators;
private Hashtable nestedCreators;
/**
/**
* Map from attribute names to methods to store configured nested types
* Map from attribute names to methods to store configured nested types
* (String to NestedStorer).
* (String to NestedStorer).
*/
*/
private Hashtable nestedStorers;
private Hashtable nestedStorers;
@@ -118,9 +118,9 @@ public class IntrospectionHelper implements BuildListener {
*/
*/
private static Hashtable helpers = new Hashtable();
private static Hashtable helpers = new Hashtable();
/**
* Map from primitive types to wrapper classes for use in
* createAttributeSetter (Class to Class). Note that char
/**
* Map from primitive types to wrapper classes for use in
* createAttributeSetter (Class to Class). Note that char
* and boolean are in here even though they get special treatment
* and boolean are in here even though they get special treatment
* - this way we only need to test for the wrapper class.
* - this way we only need to test for the wrapper class.
*/
*/
@@ -128,18 +128,18 @@ public class IntrospectionHelper implements BuildListener {
// Set up PRIMITIVE_TYPE_MAP
// Set up PRIMITIVE_TYPE_MAP
static {
static {
Class[] primitives = {Boolean.TYPE, Byte.TYPE, Character.TYPE,
Short.TYPE, Integer.TYPE, Long.TYPE,
Class[] primitives = {Boolean.TYPE, Byte.TYPE, Character.TYPE,
Short.TYPE, Integer.TYPE, Long.TYPE,
Float.TYPE, Double.TYPE};
Float.TYPE, Double.TYPE};
Class[] wrappers = {Boolean.class, Byte.class, Character.class,
Short.class, Integer.class, Long.class,
Class[] wrappers = {Boolean.class, Byte.class, Character.class,
Short.class, Integer.class, Long.class,
Float.class, Double.class};
Float.class, Double.class};
for (int i = 0; i < primitives.length; i++) {
for (int i = 0; i < primitives.length; i++) {
PRIMITIVE_TYPE_MAP.put (primitives[i], wrappers[i]);
PRIMITIVE_TYPE_MAP.put (primitives[i], wrappers[i]);
}
}
}
}
// XXX: (Jon Skeet) The documentation below doesn't draw a clear
// XXX: (Jon Skeet) The documentation below doesn't draw a clear
// distinction between addConfigured and add. It's obvious what the
// distinction between addConfigured and add. It's obvious what the
// code *here* does (addConfigured sets both a creator method which
// code *here* does (addConfigured sets both a creator method which
// calls a no-arg constructor and a storer method which calls the
// calls a no-arg constructor and a storer method which calls the
@@ -148,49 +148,49 @@ public class IntrospectionHelper implements BuildListener {
// obvious what the difference in actual *effect* will be later
// obvious what the difference in actual *effect* will be later
// on. I can't see any mention of addConfiguredXXX in "Developing
// on. I can't see any mention of addConfiguredXXX in "Developing
// with Ant" (at least in the version on the web site). Someone
// with Ant" (at least in the version on the web site). Someone
// who understands should update this documentation
// who understands should update this documentation
// (and preferably the manual too) at some stage.
// (and preferably the manual too) at some stage.
/**
/**
* Sole constructor, which is private to ensure that all
* Sole constructor, which is private to ensure that all
* IntrospectionHelpers are created via {@link #getHelper(Class) getHelper}.
* IntrospectionHelpers are created via {@link #getHelper(Class) getHelper}.
* Introspects the given class for bean-like methods.
* Introspects the given class for bean-like methods.
* Each method is examined in turn, and the following rules are applied:
* Each method is examined in turn, and the following rules are applied:
* <p>
* <p>
* <ul>
* <ul>
* <li>If the method is <code>Task.setLocation(Location)</code>,
* <li>If the method is <code>Task.setLocation(Location)</code>,
* <code>Task.setTaskType(String)</code>
* <code>Task.setTaskType(String)</code>
* or <code>TaskContainer.addTask(Task)</code>, it is ignored. These
* or <code>TaskContainer.addTask(Task)</code>, it is ignored. These
* methods are handled differently elsewhere.
* methods are handled differently elsewhere.
* <li><code>void addText(String)</code> is recognised as the method for
* <li><code>void addText(String)</code> is recognised as the method for
* adding PCDATA to a bean.
* adding PCDATA to a bean.
* <li><code>void setFoo(Bar)</code> is recognised as a method for
* setting the value of attribute <code>foo</code>, so long as
* <code>Bar</code> is non-void and is not an array type. Non-String
* <li><code>void setFoo(Bar)</code> is recognised as a method for
* setting the value of attribute <code>foo</code>, so long as
* <code>Bar</code> is non-void and is not an array type. Non-String
* parameter types always overload String parameter types, but that is
* parameter types always overload String parameter types, but that is
* the only guarantee made in terms of priority.
* the only guarantee made in terms of priority.
* <li><code>Foo createBar()</code> is recognised as a method for
* <li><code>Foo createBar()</code> is recognised as a method for
* creating a nested element called <code>bar</code> of type
* creating a nested element called <code>bar</code> of type
* <code>Foo</code>, so long as <code>Foo</code> is not a primitive or
* <code>Foo</code>, so long as <code>Foo</code> is not a primitive or
* array type.
* array type.
* <li><code>void addConfiguredFoo(Bar)</code> is recognised as a
* <li><code>void addConfiguredFoo(Bar)</code> is recognised as a
* method for storing a pre-configured element called
* method for storing a pre-configured element called
* <code>foo</code> and of type <code>Bar</code>, so long as
* <code>foo</code> and of type <code>Bar</code>, so long as
* <code>Bar</code> is not an array, primitive or String type.
* <code>Bar</code> must have an accessible constructor taking no
* <code>Bar</code> is not an array, primitive or String type.
* <code>Bar</code> must have an accessible constructor taking no
* arguments.
* arguments.
* <li><code>void addFoo(Bar)</code> is recognised as a
* <li><code>void addFoo(Bar)</code> is recognised as a
* method for storing an element called <code>foobar</code>
* method for storing an element called <code>foobar</code>
* and of type <code>Baz</code>, so long as
* and of type <code>Baz</code>, so long as
* <code>Baz</code> is not an array, primitive or String type.
* <code>Baz</code> must have an accessible constructor taking no
* <code>Baz</code> is not an array, primitive or String type.
* <code>Baz</code> must have an accessible constructor taking no
* arguments.
* arguments.
* </ul>
* </ul>
* Note that only one method is retained to create/set/addConfigured/add
* Note that only one method is retained to create/set/addConfigured/add
* any element or attribute.
* any element or attribute.
*
* @param bean The bean type to introspect.
*
* @param bean The bean type to introspect.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
*
*
* @see #getHelper(Class)
* @see #getHelper(Class)
*/
*/
private IntrospectionHelper(final Class bean) {
private IntrospectionHelper(final Class bean) {
@@ -257,7 +257,7 @@ public class IntrospectionHelper implements BuildListener {
particular order.
particular order.
*/
*/
}
}
AttributeSetter as
AttributeSetter as
= createAttributeSetter(m, args[0], propName);
= createAttributeSetter(m, args[0], propName);
if (as != null) {
if (as != null) {
attributeTypes.put(propName, args[0]);
attributeTypes.put(propName, args[0]);
@@ -346,35 +346,35 @@ public class IntrospectionHelper implements BuildListener {
}
}
}
}
/**
* Certain set methods are part of the Ant core interface to tasks and
/**
* Certain set methods are part of the Ant core interface to tasks and
* therefore not to be considered for introspection
* therefore not to be considered for introspection
*
*
* @param name the name of the set method
* @param name the name of the set method
* @param type the type of the set method's parameter
* @param type the type of the set method's parameter
* @return true if the given set method is to be hidden.
* @return true if the given set method is to be hidden.
*/
*/
private boolean isHiddenSetMethod(String name, Class type) {
private boolean isHiddenSetMethod(String name, Class type) {
if ("setLocation".equals(name)
if ("setLocation".equals(name)
&& org.apache.tools.ant.Location.class.equals(type)) {
&& org.apache.tools.ant.Location.class.equals(type)) {
return true;
return true;
}
}
if ("setTaskType".equals(name)
if ("setTaskType".equals(name)
&& java.lang.String.class.equals(type)) {
&& java.lang.String.class.equals(type)) {
return true;
return true;
}
}
return false;
return false;
}
}
/**
/**
* Returns a helper for the given class, either from the cache
* Returns a helper for the given class, either from the cache
* or by creating a new instance.
* or by creating a new instance.
*
*
* @param c The class for which a helper is required.
* @param c The class for which a helper is required.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
*
*
* @return a helper for the specified class
* @return a helper for the specified class
*/
*/
public static synchronized IntrospectionHelper getHelper(Class c) {
public static synchronized IntrospectionHelper getHelper(Class c) {
@@ -411,21 +411,21 @@ public class IntrospectionHelper implements BuildListener {
}
}
/**
/**
* Sets the named attribute in the given element, which is part of the
* Sets the named attribute in the given element, which is part of the
* given project.
* given project.
*
* @param p The project containing the element. This is used when files
*
* @param p The project containing the element. This is used when files
* need to be resolved. Must not be <code>null</code>.
* need to be resolved. Must not be <code>null</code>.
* @param element The element to set the attribute in. Must not be
* @param element The element to set the attribute in. Must not be
* <code>null</code>.
* <code>null</code>.
* @param attributeName The name of the attribute to set. Must not be
* @param attributeName The name of the attribute to set. Must not be
* <code>null</code>.
* <code>null</code>.
* @param value The value to set the attribute to. This may be interpreted
* @param value The value to set the attribute to. This may be interpreted
* or converted to the necessary type if the setter method
* or converted to the necessary type if the setter method
* doesn't just take a string. Must not be <code>null</code>.
* doesn't just take a string. Must not be <code>null</code>.
*
* @exception BuildException if the introspected class doesn't support
* the given attribute, or if the setting
*
* @exception BuildException if the introspected class doesn't support
* the given attribute, or if the setting
* method fails.
* method fails.
*/
*/
public void setAttribute(Project p, Object element, String attributeName,
public void setAttribute(Project p, Object element, String attributeName,
@@ -459,23 +459,23 @@ public class IntrospectionHelper implements BuildListener {
}
}
/**
/**
* Adds PCDATA to an element, using the element's
* Adds PCDATA to an element, using the element's
* <code>void addText(String)</code> method, if it has one. If no
* <code>void addText(String)</code> method, if it has one. If no
* such method is present, a BuildException is thrown if the
* such method is present, a BuildException is thrown if the
* given text contains non-whitespace.
* given text contains non-whitespace.
*
* @param project The project which the element is part of.
*
* @param project The project which the element is part of.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
* @param element The element to add the text to.
* @param element The element to add the text to.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
* @param text The text to add.
* @param text The text to add.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
*
*
* @exception BuildException if non-whitespace text is provided and no
* @exception BuildException if non-whitespace text is provided and no
* method is available to handle it, or if
* method is available to handle it, or if
* the handling method fails.
* the handling method fails.
*/
*/
public void addText(Project project, Object element, String text)
public void addText(Project project, Object element, String text)
throws BuildException {
throws BuildException {
if (addText == null) {
if (addText == null) {
// Element doesn't handle text content
// Element doesn't handle text content
@@ -503,19 +503,19 @@ public class IntrospectionHelper implements BuildListener {
}
}
}
}
public void throwNotSupported(Project project, Object parent,
public void throwNotSupported(Project project, Object parent,
String elementName) {
String elementName) {
String msg = project.getElementName(parent) +
String msg = project.getElementName(parent) +
" doesn't support the nested \"" + elementName + "\" element.";
" doesn't support the nested \"" + elementName + "\" element.";
throw new BuildException(msg);
throw new BuildException(msg);
}
}
/**
/**
* Creates a named nested element. Depending on the results of the
* Creates a named nested element. Depending on the results of the
* initial introspection, either a method in the given parent instance
* initial introspection, either a method in the given parent instance
* or a simple no-arg constructor is used to create an instance of the
* or a simple no-arg constructor is used to create an instance of the
* specified element type.
* specified element type.
*
*
* @param project Project to which the parent object belongs.
* @param project Project to which the parent object belongs.
* Must not be <code>null</code>. If the resulting
* Must not be <code>null</code>. If the resulting
* object is an instance of ProjectComponent, its
* object is an instance of ProjectComponent, its
@@ -524,21 +524,23 @@ public class IntrospectionHelper implements BuildListener {
* Must not be <code>null</code>.
* Must not be <code>null</code>.
* @param elementName Name of the element to create an instance of.
* @param elementName Name of the element to create an instance of.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
*
*
* @return an instance of the specified element type
* @return an instance of the specified element type
*
*
* @exception BuildException if no method is available to create the
* @exception BuildException if no method is available to create the
* element instance, or if the creating method
* element instance, or if the creating method
* fails.
* fails.
*/
*/
public Object createElement(Project project, Object parent,
public Object createElement(Project project, Object parent,
String elementName) throws BuildException {
String elementName) throws BuildException {
NestedCreator nc = (NestedCreator) nestedCreators.get(elementName);
NestedCreator nc = (NestedCreator) nestedCreators.get(elementName);
if (nc == null && parent instanceof DynamicConfigurator) {
if (nc == null && parent instanceof DynamicConfigurator) {
DynamicConfigurator dc = (DynamicConfigurator) parent;
DynamicConfigurator dc = (DynamicConfigurator) parent;
Object nestedElement = dc.createDynamicElement(elementName);
Object nestedElement = dc.createDynamicElement(elementName);
if (nestedElement != null) {
if (nestedElement != null) {
Project.setProjectOnObject(project, nestedElement);
if ( project != null ) {
project.setProjectReference( nestedElement );
}
return nestedElement;
return nestedElement;
}
}
}
}
@@ -547,7 +549,9 @@ public class IntrospectionHelper implements BuildListener {
}
}
try {
try {
Object nestedElement = nc.create(parent);
Object nestedElement = nc.create(parent);
Project.setProjectOnObject(project, nestedElement);
if ( project != null ) {
project.setProjectReference( nestedElement );
}
return nestedElement;
return nestedElement;
} catch (IllegalAccessException ie) {
} catch (IllegalAccessException ie) {
// impossible as getMethods should only return public methods
// impossible as getMethods should only return public methods
@@ -565,7 +569,7 @@ public class IntrospectionHelper implements BuildListener {
}
}
/**
/**
* Indicate if this element supports a nested element of the
* Indicate if this element supports a nested element of the
* given name.
* given name.
*
*
* @param elementName the name of the nested element being checked
* @param elementName the name of the nested element being checked
@@ -576,28 +580,28 @@ public class IntrospectionHelper implements BuildListener {
return nestedCreators.containsKey(elementName) ||
return nestedCreators.containsKey(elementName) ||
DynamicConfigurator.class.isAssignableFrom(bean);
DynamicConfigurator.class.isAssignableFrom(bean);
}
}
/**
/**
* Stores a named nested element using a storage method determined
* Stores a named nested element using a storage method determined
* by the initial introspection. If no appropriate storage method
* by the initial introspection. If no appropriate storage method
* is available, this method returns immediately.
* is available, this method returns immediately.
*
* @param project Ignored in this implementation.
*
* @param project Ignored in this implementation.
* May be <code>null</code>.
* May be <code>null</code>.
*
* @param parent Parent instance to store the child in.
*
* @param parent Parent instance to store the child in.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
*
*
* @param child Child instance to store in the parent.
* @param child Child instance to store in the parent.
* Should not be <code>null</code>.
* Should not be <code>null</code>.
*
* @param elementName Name of the child element to store.
*
* @param elementName Name of the child element to store.
* May be <code>null</code>, in which case
* May be <code>null</code>, in which case
* this method returns immediately.
* this method returns immediately.
*
*
* @exception BuildException if the storage method fails.
* @exception BuildException if the storage method fails.
*/
*/
public void storeElement(Project project, Object parent, Object child,
public void storeElement(Project project, Object parent, Object child,
String elementName) throws BuildException {
String elementName) throws BuildException {
if (elementName == null) {
if (elementName == null) {
return;
return;
@@ -625,13 +629,13 @@ public class IntrospectionHelper implements BuildListener {
/**
/**
* Returns the type of a named nested element.
* Returns the type of a named nested element.
*
*
* @param elementName The name of the element to find the type of.
* @param elementName The name of the element to find the type of.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
*
*
* @return the type of the nested element with the specified name.
* @return the type of the nested element with the specified name.
* This will never be <code>null</code>.
* This will never be <code>null</code>.
*
*
* @exception BuildException if the introspected class does not
* @exception BuildException if the introspected class does not
* support the named nested element.
* support the named nested element.
*/
*/
@@ -648,13 +652,13 @@ public class IntrospectionHelper implements BuildListener {
/**
/**
* Returns the type of a named attribute.
* Returns the type of a named attribute.
*
*
* @param attributeName The name of the attribute to find the type of.
* @param attributeName The name of the attribute to find the type of.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
*
*
* @return the type of the attribute with the specified name.
* @return the type of the attribute with the specified name.
* This will never be <code>null</code>.
* This will never be <code>null</code>.
*
*
* @exception BuildException if the introspected class does not
* @exception BuildException if the introspected class does not
* support the named attribute.
* support the named attribute.
*/
*/
@@ -671,7 +675,7 @@ public class IntrospectionHelper implements BuildListener {
/**
/**
* Returns whether or not the introspected class supports PCDATA.
* Returns whether or not the introspected class supports PCDATA.
*
*
* @return whether or not the introspected class supports PCDATA.
* @return whether or not the introspected class supports PCDATA.
*/
*/
public boolean supportsCharacters() {
public boolean supportsCharacters() {
@@ -679,9 +683,9 @@ public class IntrospectionHelper implements BuildListener {
}
}
/**
/**
* Returns an enumeration of the names of the attributes supported
* Returns an enumeration of the names of the attributes supported
* by the introspected class.
* by the introspected class.
*
*
* @return an enumeration of the names of the attributes supported
* @return an enumeration of the names of the attributes supported
* by the introspected class.
* by the introspected class.
*/
*/
@@ -690,9 +694,9 @@ public class IntrospectionHelper implements BuildListener {
}
}
/**
/**
* Returns an enumeration of the names of the nested elements supported
* Returns an enumeration of the names of the nested elements supported
* by the introspected class.
* by the introspected class.
*
*
* @return an enumeration of the names of the nested elements supported
* @return an enumeration of the names of the nested elements supported
* by the introspected class.
* by the introspected class.
*/
*/
@@ -707,36 +711,36 @@ public class IntrospectionHelper implements BuildListener {
* <ul>
* <ul>
* <li>String (left as it is)
* <li>String (left as it is)
* <li>Character/char (first character is used)
* <li>Character/char (first character is used)
* <li>Boolean/boolean
* <li>Boolean/boolean
* ({@link Project#toBoolean(String) Project.toBoolean(String)} is used)
* ({@link Project#toBoolean(String) Project.toBoolean(String)} is used)
* <li>Class (Class.forName is used)
* <li>Class (Class.forName is used)
* <li>File (resolved relative to the appropriate project)
* <li>File (resolved relative to the appropriate project)
* <li>Path (resolve relative to the appropriate project)
* <li>Path (resolve relative to the appropriate project)
* <li>EnumeratedAttribute (uses its own
* <li>EnumeratedAttribute (uses its own
* {@link EnumeratedAttribute#setValue(String) setValue} method)
* {@link EnumeratedAttribute#setValue(String) setValue} method)
* <li>Other primitive types (wrapper classes are used with constructors
* <li>Other primitive types (wrapper classes are used with constructors
* taking String)
* taking String)
* </ul>
* </ul>
*
* If none of the above covers the given parameters, a constructor for the
*
* If none of the above covers the given parameters, a constructor for the
* appropriate class taking a String parameter is used if it is available.
* appropriate class taking a String parameter is used if it is available.
*
*
* @param m The method to invoke on the bean when the setter is invoked.
* @param m The method to invoke on the bean when the setter is invoked.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
* @param arg The type of the single argument of the bean's method.
* @param arg The type of the single argument of the bean's method.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
* @param attrName the name of the attribute for which the setter is being
* @param attrName the name of the attribute for which the setter is being
* created.
* created.
*
*
* @return an appropriate AttributeSetter instance, or <code>null</code>
* @return an appropriate AttributeSetter instance, or <code>null</code>
* if no appropriate conversion is available.
* if no appropriate conversion is available.
*/
*/
private AttributeSetter createAttributeSetter(final Method m,
private AttributeSetter createAttributeSetter(final Method m,
Class arg,
Class arg,
final String attrName) {
final String attrName) {
// use wrappers for primitive classes, e.g. int and
// use wrappers for primitive classes, e.g. int and
// Integer are treated identically
// Integer are treated identically
final Class reflectedArg = PRIMITIVE_TYPE_MAP.containsKey (arg)
final Class reflectedArg = PRIMITIVE_TYPE_MAP.containsKey (arg)
? (Class) PRIMITIVE_TYPE_MAP.get(arg) : arg;
? (Class) PRIMITIVE_TYPE_MAP.get(arg) : arg;
// simplest case - setAttribute expects String
// simplest case - setAttribute expects String
@@ -754,15 +758,15 @@ public class IntrospectionHelper implements BuildListener {
public void set(Project p, Object parent, String value)
public void set(Project p, Object parent, String value)
throws InvocationTargetException, IllegalAccessException {
throws InvocationTargetException, IllegalAccessException {
if (value.length() == 0) {
if (value.length() == 0) {
throw new BuildException("The value \"\" is not a "
+ "legal value for attribute \""
throw new BuildException("The value \"\" is not a "
+ "legal value for attribute \""
+ attrName + "\"");
+ attrName + "\"");
}
}
m.invoke(parent, new Character[] {new Character(value.charAt(0))});
m.invoke(parent, new Character[] {new Character(value.charAt(0))});
}
}
};
};
// boolean and Boolean get special treatment because we
// boolean and Boolean get special treatment because we
// have a nice method in Project
// have a nice method in Project
} else if (java.lang.Boolean.class.equals(reflectedArg)) {
} else if (java.lang.Boolean.class.equals(reflectedArg)) {
return new AttributeSetter() {
return new AttributeSetter() {
@@ -813,7 +817,7 @@ public class IntrospectionHelper implements BuildListener {
public void set(Project p, Object parent, String value)
public void set(Project p, Object parent, String value)
throws InvocationTargetException, IllegalAccessException, BuildException {
throws InvocationTargetException, IllegalAccessException, BuildException {
try {
try {
org.apache.tools.ant.types.EnumeratedAttribute ea =
org.apache.tools.ant.types.EnumeratedAttribute ea =
(org.apache.tools.ant.types.EnumeratedAttribute) reflectedArg.newInstance();
(org.apache.tools.ant.types.EnumeratedAttribute) reflectedArg.newInstance();
ea.setValue(value);
ea.setValue(value);
m.invoke(parent, new EnumeratedAttribute[] {ea});
m.invoke(parent, new EnumeratedAttribute[] {ea});
@@ -824,7 +828,7 @@ public class IntrospectionHelper implements BuildListener {
};
};
// worst case. look for a public String constructor and use it
// worst case. look for a public String constructor and use it
// This is used (deliberately) for all primitives/wrappers other than
// This is used (deliberately) for all primitives/wrappers other than
// char and boolean
// char and boolean
} else {
} else {
@@ -838,7 +842,9 @@ public class IntrospectionHelper implements BuildListener {
throws InvocationTargetException, IllegalAccessException, BuildException {
throws InvocationTargetException, IllegalAccessException, BuildException {
try {
try {
Object attribute = c.newInstance(new String[] {value});
Object attribute = c.newInstance(new String[] {value});
Project.setProjectOnObject(p, attribute);
if ( p != null ) {
p.setProjectReference( attribute );
}
m.invoke(parent, new Object[] {attribute});
m.invoke(parent, new Object[] {attribute});
} catch (InstantiationException ie) {
} catch (InstantiationException ie) {
throw new BuildException(ie);
throw new BuildException(ie);
@@ -858,13 +864,13 @@ public class IntrospectionHelper implements BuildListener {
* relation to a given project. This is used for logging purposes
* relation to a given project. This is used for logging purposes
* when the element is asked to cope with some data it has no
* when the element is asked to cope with some data it has no
* way of handling.
* way of handling.
*
* @param project The project the element is defined in.
*
* @param project The project the element is defined in.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
*
*
* @param element The element to describe.
* @param element The element to describe.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
*
*
* @return a description of the element type
* @return a description of the element type
*/
*/
protected String getElementName(Project project, Object element) {
protected String getElementName(Project project, Object element) {
@@ -876,12 +882,12 @@ public class IntrospectionHelper implements BuildListener {
* a given prefix and converting into lower case. It is up to calling
* a given prefix and converting into lower case. It is up to calling
* code to make sure the method name does actually begin with the
* code to make sure the method name does actually begin with the
* specified prefix - no checking is done in this method.
* specified prefix - no checking is done in this method.
*
*
* @param methodName The name of the method in question.
* @param methodName The name of the method in question.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
* @param prefix The prefix to remove.
* @param prefix The prefix to remove.
* Must not be <code>null</code>.
* Must not be <code>null</code>.
*
*
* @return the lower-cased method name with the prefix removed.
* @return the lower-cased method name with the prefix removed.
*/
*/
private String getPropertyName(String methodName, String prefix) {
private String getPropertyName(String methodName, String prefix) {
@@ -890,7 +896,7 @@ public class IntrospectionHelper implements BuildListener {
}
}
/**
/**
* Internal interface used to create nested elements. Not documented
* Internal interface used to create nested elements. Not documented
* in detail for reasons of source code readability.
* in detail for reasons of source code readability.
*/
*/
private interface NestedCreator {
private interface NestedCreator {
@@ -899,7 +905,7 @@ public class IntrospectionHelper implements BuildListener {
}
}
/**
/**
* Internal interface used to storing nested elements. Not documented
* Internal interface used to storing nested elements. Not documented
* in detail for reasons of source code readability.
* in detail for reasons of source code readability.
*/
*/
private interface NestedStorer {
private interface NestedStorer {
@@ -908,7 +914,7 @@ public class IntrospectionHelper implements BuildListener {
}
}
/**
/**
* Internal interface used to setting element attributes. Not documented
* Internal interface used to setting element attributes. Not documented
* in detail for reasons of source code readability.
* in detail for reasons of source code readability.
*/
*/
private interface AttributeSetter {
private interface AttributeSetter {
@@ -918,9 +924,9 @@ public class IntrospectionHelper implements BuildListener {
}
}
/**
/**
* Clears all storage used by this class, including the static cache of
* Clears all storage used by this class, including the static cache of
* helpers.
* helpers.
*
*
* @param event Ignored in this implementation.
* @param event Ignored in this implementation.
*/
*/
public void buildFinished(BuildEvent event) {
public void buildFinished(BuildEvent event) {
@@ -937,35 +943,35 @@ public class IntrospectionHelper implements BuildListener {
* @param event Ignored in this implementation.
* @param event Ignored in this implementation.
*/
*/
public void buildStarted(BuildEvent event) {}
public void buildStarted(BuildEvent event) {}
/**
/**
* Empty implementation to satisfy the BuildListener interface.
* Empty implementation to satisfy the BuildListener interface.
*
*
* @param event Ignored in this implementation.
* @param event Ignored in this implementation.
*/
*/
public void targetStarted(BuildEvent event) {}
public void targetStarted(BuildEvent event) {}
/**
/**
* Empty implementation to satisfy the BuildListener interface.
* Empty implementation to satisfy the BuildListener interface.
*
*
* @param event Ignored in this implementation.
* @param event Ignored in this implementation.
*/
*/
public void targetFinished(BuildEvent event) {}
public void targetFinished(BuildEvent event) {}
/**
/**
* Empty implementation to satisfy the BuildListener interface.
* Empty implementation to satisfy the BuildListener interface.
*
*
* @param event Ignored in this implementation.
* @param event Ignored in this implementation.
*/
*/
public void taskStarted(BuildEvent event) {}
public void taskStarted(BuildEvent event) {}
/**
/**
* Empty implementation to satisfy the BuildListener interface.
* Empty implementation to satisfy the BuildListener interface.
*
*
* @param event Ignored in this implementation.
* @param event Ignored in this implementation.
*/
*/
public void taskFinished(BuildEvent event) {}
public void taskFinished(BuildEvent event) {}
/**
/**
* Empty implementation to satisfy the BuildListener interface.
* Empty implementation to satisfy the BuildListener interface.
*
*