Helper class that collects the methods a task or nested element
holds to set attributes, create nested elements or hold PCDATA
elements.
It contains hashtables containing classes that use introspection
to handle all the invocation of the project-component specific methods.
This class is somewhat complex, as it implements the O/X mapping between
Ant XML and Java class instances. This is not the best place for someone new
to Ant to start contributing to the codebase, as a change here can break the
entire system in interesting ways. Always run a full test of Ant before checking
in/submitting changes to this file.
The class is final and has a private constructor.
To get an instance for a specific (class,project) combination, use
.
This may return an existing version, or a new one
...do not make any assumptions about its uniqueness, or its validity after the Project
instance has finished its build.
| Method from org.apache.tools.ant.IntrospectionHelper Detail: |
public void addText(Project project,
Object element,
String text) throws BuildException {
if (addText == null) {
text = text.trim();
// Element doesn't handle text content
if (text.length() == 0) {
// Only whitespace - ignore
return;
}
// Not whitespace - fail
throw new BuildException(project.getElementName(element)
+ " doesn't support nested text data (\"" + condenseText(text) + "\").");
}
try {
addText.invoke(element, new Object[] {text});
} catch (IllegalAccessException ie) {
// impossible as getMethods should only return public methods
throw new BuildException(ie);
} catch (InvocationTargetException ite) {
throw extractBuildException(ite);
}
}
Adds PCDATA to an element, using the element's
void addText(String) method, if it has one. If no
such method is present, a BuildException is thrown if the
given text contains non-whitespace. |
public static void clearCache() {
HELPERS.clear();
}
Clears the static cache of on build finished. |
public Object createElement(Project project,
Object parent,
String elementName) throws BuildException {
NestedCreator nc = getNestedCreator(project, "", parent, elementName, null);
try {
Object nestedElement = nc.create(project, parent, null);
if (project != null) {
project.setProjectReference(nestedElement);
}
return nestedElement;
} catch (IllegalAccessException ie) {
// impossible as getMethods should only return public methods
throw new BuildException(ie);
} catch (InstantiationException ine) {
// impossible as getMethods should only return public methods
throw new BuildException(ine);
} catch (InvocationTargetException ite) {
throw extractBuildException(ite);
}
} Deprecated! since - 1.6.x.
This is not a namespace aware method.
Creates a named nested element. Depending on the results of the
initial introspection, either a method in the given parent instance
or a simple no-arg constructor is used to create an instance of the
specified element type. |
public Method getAddTextMethod() throws BuildException {
if (!supportsCharacters()) {
throw new BuildException("Class " + bean.getName()
+ " doesn't support nested text data.");
}
return addText;
}
Returns the addText method when the introspected
class supports nested text. |
public Map getAttributeMap() {
return attributeTypes.isEmpty()
? Collections.EMPTY_MAP : Collections.unmodifiableMap(attributeTypes);
}
Returns a read-only map of attributes supported by the introspected class. |
public Method getAttributeMethod(String attributeName) throws BuildException {
Object setter = attributeSetters.get(attributeName);
if (setter == null) {
throw new UnsupportedAttributeException("Class "
+ bean.getName() + " doesn't support the \""
+ attributeName + "\" attribute.", attributeName);
}
return ((AttributeSetter) setter).method;
}
Returns the setter method of a named attribute. |
public Class getAttributeType(String attributeName) throws BuildException {
Class at = (Class) attributeTypes.get(attributeName);
if (at == null) {
throw new UnsupportedAttributeException("Class "
+ bean.getName() + " doesn't support the \""
+ attributeName + "\" attribute.", attributeName);
}
return at;
}
Returns the type of a named attribute. |
public Enumeration getAttributes() {
return attributeSetters.keys();
}
Returns an enumeration of the names of the attributes supported by the introspected class. |
public IntrospectionHelper.Creator getElementCreator(Project project,
String parentUri,
Object parent,
String elementName,
UnknownElement ue) {
NestedCreator nc = getNestedCreator(project, parentUri, parent, elementName, ue);
return new Creator(project, parent, nc);
}
returns an object that creates and stores an object
for an element of a parent. |
public Method getElementMethod(String elementName) throws BuildException {
Object creator = nestedCreators.get(elementName);
if (creator == null) {
throw new UnsupportedElementException("Class "
+ bean.getName() + " doesn't support the nested \""
+ elementName + "\" element.", elementName);
}
return ((NestedCreator) creator).method;
}
Returns the adder or creator method of a named nested element. |
public Class getElementType(String elementName) throws BuildException {
Class nt = (Class) nestedTypes.get(elementName);
if (nt == null) {
throw new UnsupportedElementException("Class "
+ bean.getName() + " doesn't support the nested \""
+ elementName + "\" element.", elementName);
}
return nt;
}
Returns the type of a named nested element. |
public List getExtensionPoints() {
return addTypeMethods.isEmpty()
? Collections.EMPTY_LIST : Collections.unmodifiableList(addTypeMethods);
}
Returns a read-only list of extension points supported
by the introspected class.
A task/type or nested element with void methods named add()
or addConfigured(), taking a single class or interface
argument, supports extensions point. This method returns the list of
all these void add[Configured](type) methods. |
public static synchronized IntrospectionHelper getHelper(Class c) {
return getHelper(null, c);
}
Returns a helper for the given class, either from the cache
or by creating a new instance. |
public static IntrospectionHelper getHelper(Project p,
Class c) {
IntrospectionHelper ih = (IntrospectionHelper) HELPERS.get(c.getName());
// If a helper cannot be found, or if the helper is for another
// classloader, create a new IH
if (ih == null || ih.bean != c) {
ih = new IntrospectionHelper(c);
if (p != null) {
// #30162: do *not* cache this if there is no project, as we
// cannot guarantee that the cache will be cleared.
HELPERS.put(c.getName(), ih);
}
}
return ih;
}
Returns a helper for the given class, either from the cache
or by creating a new instance.
The method will make sure the helper will be cleaned up at the end of
the project, and only one instance will be created for each class. |
public Map getNestedElementMap() {
return nestedTypes.isEmpty()
? Collections.EMPTY_MAP : Collections.unmodifiableMap(nestedTypes);
}
Returns a read-only map of nested elements supported
by the introspected class. |
public Enumeration getNestedElements() {
return nestedTypes.keys();
}
Returns an enumeration of the names of the nested elements supported
by the introspected class. |
public boolean isContainer() {
return TaskContainer.class.isAssignableFrom(bean);
}
Indicates whether the introspected class is a task container,
supporting arbitrary nested tasks/types. |
public boolean isDynamic() {
return DynamicElement.class.isAssignableFrom(bean)
|| DynamicElementNS.class.isAssignableFrom(bean);
}
Indicates whether the introspected class is a dynamic one,
supporting arbitrary nested elements and/or attributes. |
public void setAttribute(Project p,
Object element,
String attributeName,
String value) throws BuildException {
AttributeSetter as = (AttributeSetter) attributeSetters.get(
attributeName.toLowerCase(Locale.US));
if (as == null) {
if (element instanceof DynamicAttributeNS) {
DynamicAttributeNS dc = (DynamicAttributeNS) element;
String uriPlusPrefix = ProjectHelper.extractUriFromComponentName(attributeName);
String uri = ProjectHelper.extractUriFromComponentName(uriPlusPrefix);
String localName = ProjectHelper.extractNameFromComponentName(attributeName);
String qName = "".equals(uri) ? localName : uri + ":" + localName;
dc.setDynamicAttribute(uri, localName, qName, value);
return;
}
if (element instanceof DynamicAttribute) {
DynamicAttribute dc = (DynamicAttribute) element;
dc.setDynamicAttribute(attributeName.toLowerCase(Locale.US), value);
return;
}
if (attributeName.indexOf(':") != -1) {
return; // Ignore attribute from unknown uri's
}
String msg = getElementName(p, element)
+ " doesn't support the \"" + attributeName + "\" attribute.";
throw new UnsupportedAttributeException(msg, attributeName);
}
try {
as.set(p, element, value);
} catch (IllegalAccessException ie) {
// impossible as getMethods should only return public methods
throw new BuildException(ie);
} catch (InvocationTargetException ite) {
throw extractBuildException(ite);
}
}
Sets the named attribute in the given element, which is part of the
given project. |
public void storeElement(Project project,
Object parent,
Object child,
String elementName) throws BuildException {
if (elementName == null) {
return;
}
NestedCreator ns = (NestedCreator) nestedCreators.get(elementName.toLowerCase(Locale.US));
if (ns == null) {
return;
}
try {
ns.store(parent, child);
} catch (IllegalAccessException ie) {
// impossible as getMethods should only return public methods
throw new BuildException(ie);
} catch (InstantiationException ine) {
// impossible as getMethods should only return public methods
throw new BuildException(ine);
} catch (InvocationTargetException ite) {
throw extractBuildException(ite);
}
}
Stores a named nested element using a storage method determined
by the initial introspection. If no appropriate storage method
is available, this method returns immediately. |
public boolean supportsCharacters() {
return addText != null;
}
Returns whether or not the introspected class supports PCDATA. |
public boolean supportsNestedElement(String elementName) {
return supportsNestedElement("", elementName);
}
Indicates if this element supports a nested element of the
given name. |
public boolean supportsNestedElement(String parentUri,
String elementName) {
if (isDynamic() || addTypeMethods.size() > 0) {
return true;
}
String name = ProjectHelper.extractNameFromComponentName(elementName);
if (!nestedCreators.containsKey(name.toLowerCase(Locale.US))) {
return false;
}
String uri = ProjectHelper.extractUriFromComponentName(elementName);
if (uri.equals(ProjectHelper.ANT_CORE_URI)) {
uri = "";
}
if ("".equals(uri)) {
return true;
}
if (parentUri.equals(ProjectHelper.ANT_CORE_URI)) {
parentUri = "";
}
return uri.equals(parentUri);
}
Indicate if this element supports a nested element of the
given name. |
public void throwNotSupported(Project project,
Object parent,
String elementName) {
String msg = project.getElementName(parent)
+ " doesn't support the nested \"" + elementName + "\" element.";
throw new UnsupportedElementException(msg, elementName);
}
Utility method to throw a NotSupported exception |