Loads property values from a valid XML file, generating the
property names from the file's element and attribute names.
Optionally, to more closely mirror the abilities of the Property
task, a selected set of attributes can be treated specially. To
enable this behavior, the "semanticAttributes" property of this task
must be set to true (it defaults to false). If this attribute is
specified, the following attributes take on special meaning
(setting this to true implicitly sets collapseAttributes to true as
well):
| Method from org.apache.tools.ant.taskdefs.XmlProperty Detail: |
public void addConfigured(ResourceCollection a) {
if (a.size() != 1) {
throw new BuildException("only single argument resource collections"
+ " are supported as archives");
}
setSrcResource((Resource) a.iterator().next());
}
|
public void addConfiguredXMLCatalog(XMLCatalog catalog) {
xmlCatalog.addConfiguredXMLCatalog(catalog);
}
add an XMLCatalog as a nested element; optional. |
void addNodeRecursively(Node node,
String prefix) {
addNodeRecursively(node, prefix, null);
}
|
public void execute() throws BuildException {
Resource r = getResource();
if (r == null) {
String msg = "XmlProperty task requires a source resource";
throw new BuildException(msg);
}
try {
log("Loading " + src, Project.MSG_VERBOSE);
if (r.isExists()) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(validate);
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setEntityResolver(getEntityResolver());
Document document = null;
if (src instanceof FileResource) {
document = builder.parse(((FileResource) src).getFile());
} else {
document = builder.parse(src.getInputStream());
}
Element topElement = document.getDocumentElement();
// Keep a hashtable of attributes added by this task.
// This task is allow to override its own properties
// but not other properties. So we need to keep track
// of which properties we've added.
addedAttributes = new Hashtable();
if (keepRoot) {
addNodeRecursively(topElement, prefix, null);
} else {
NodeList topChildren = topElement.getChildNodes();
int numChildren = topChildren.getLength();
for (int i = 0; i < numChildren; i++) {
addNodeRecursively(topChildren.item(i), prefix, null);
}
}
} else {
log("Unable to find property resource: " + r,
Project.MSG_VERBOSE);
}
} catch (SAXException sxe) {
// Error generated during parsing
Exception x = sxe;
if (sxe.getException() != null) {
x = sxe.getException();
}
throw new BuildException("Failed to load " + src, x);
} catch (ParserConfigurationException pce) {
// Parser with specified options can't be built
throw new BuildException(pce);
} catch (IOException ioe) {
// I/O error
throw new BuildException("Failed to load " + src, ioe);
}
}
|
protected boolean getCollapseAttributes() {
return this.collapseAttributes;
}
|
public String getDelimiter() {
return delimiter;
}
|
protected EntityResolver getEntityResolver() {
return xmlCatalog;
}
|
protected File getFile() {
if (src instanceof FileResource) {
return ((FileResource) src).getFile();
} else {
return null;
}
}
|
protected boolean getIncludeSementicAttribute() {
return this.includeSemanticAttribute;
}
|
protected boolean getKeeproot() {
return this.keepRoot;
}
|
protected String getPrefix() {
return this.prefix;
}
|
protected Resource getResource() {
// delegate this way around to support subclasses that
// overwrite getFile
File f = getFile();
if (f != null) {
return new FileResource(f);
} else {
return src;
}
}
|
protected File getRootDirectory() {
return this.rootDirectory;
}
|
protected boolean getSemanticAttributes() {
return this.semanticAttributes;
}
|
protected boolean getValidate() {
return this.validate;
}
|
public void init() {
super.init();
xmlCatalog.setProject(getProject());
}
|
public Object processNode(Node node,
String prefix,
Object container) {
// Parse the attribute(s) and text of this node, adding
// properties for each.
// if the "path" attribute is specified, then return the created path
// which will be passed to the children of this node.
Object addedPath = null;
// The value of an id attribute of this node.
String id = null;
if (node.hasAttributes()) {
NamedNodeMap nodeAttributes = node.getAttributes();
// Is there an id attribute?
Node idNode = nodeAttributes.getNamedItem(ID);
id = (semanticAttributes && idNode != null
? idNode.getNodeValue() : null);
// Now, iterate through the attributes adding them.
for (int i = 0; i < nodeAttributes.getLength(); i++) {
Node attributeNode = nodeAttributes.item(i);
if (!semanticAttributes) {
String attributeName = getAttributeName(attributeNode);
String attributeValue = getAttributeValue(attributeNode);
addProperty(prefix + attributeName, attributeValue, null);
} else {
String nodeName = attributeNode.getNodeName();
String attributeValue = getAttributeValue(attributeNode);
Path containingPath = (container != null
&& container instanceof Path ? (Path) container : null);
/*
* The main conditional logic -- if the attribute
* is somehow "special" (i.e., it has known
* semantic meaning) then deal with it
* appropriately.
*/
if (nodeName.equals(ID)) {
// ID has already been found above.
continue;
} else if (containingPath != null
&& nodeName.equals(PATH)) {
// A "path" attribute for a node within a Path object.
containingPath.setPath(attributeValue);
} else if (container instanceof Path
&& nodeName.equals(REF_ID)) {
// A "refid" attribute for a node within a Path object.
containingPath.setPath(attributeValue);
} else if (container instanceof Path
&& nodeName.equals(LOCATION)) {
// A "location" attribute for a node within a
// Path object.
containingPath.setLocation(resolveFile(attributeValue));
} else if (nodeName.equals(PATHID)) {
// A node identifying a new path
if (container != null) {
throw new BuildException("XmlProperty does not "
+ "support nested paths");
}
addedPath = new Path(getProject());
getProject().addReference(attributeValue, addedPath);
} else {
// An arbitrary attribute.
String attributeName = getAttributeName(attributeNode);
addProperty(prefix + attributeName, attributeValue, id);
}
}
}
}
String nodeText = null;
boolean emptyNode = false;
boolean semanticEmptyOverride = false;
if (node.getNodeType() == Node.ELEMENT_NODE
&& semanticAttributes
&& node.hasAttributes()
&& (node.getAttributes().getNamedItem(VALUE) != null
|| node.getAttributes().getNamedItem(LOCATION) != null
|| node.getAttributes().getNamedItem(REF_ID) != null
|| node.getAttributes().getNamedItem(PATH) != null
|| node.getAttributes().getNamedItem(PATHID) != null)) {
semanticEmptyOverride = true;
}
if (node.getNodeType() == Node.TEXT_NODE) {
// For the text node, add a property.
nodeText = getAttributeValue(node);
} else if ((node.getNodeType() == Node.ELEMENT_NODE)
&& (node.getChildNodes().getLength() == 1)
&& (node.getFirstChild().getNodeType() == Node.CDATA_SECTION_NODE)) {
nodeText = node.getFirstChild().getNodeValue();
if ("".equals(nodeText) && !semanticEmptyOverride) {
emptyNode = true;
}
} else if ((node.getNodeType() == Node.ELEMENT_NODE)
&& (node.getChildNodes().getLength() == 0)
&& !semanticEmptyOverride) {
nodeText = "";
emptyNode = true;
} else if ((node.getNodeType() == Node.ELEMENT_NODE)
&& (node.getChildNodes().getLength() == 1)
&& (node.getFirstChild().getNodeType() == Node.TEXT_NODE)
&& ("".equals(node.getFirstChild().getNodeValue()))
&& !semanticEmptyOverride) {
nodeText = "";
emptyNode = true;
}
if (nodeText != null) {
// If the containing object was a String, then use it as the ID.
if (semanticAttributes && id == null
&& container instanceof String) {
id = (String) container;
}
if (nodeText.trim().length() != 0 || emptyNode) {
addProperty(prefix, nodeText, id);
}
}
// Return the Path we added or the ID of this node for
// children to reference if needed. Path objects are
// definitely used by child path elements, and ID may be used
// for a child text node.
return (addedPath != null ? addedPath : id);
}
Process the given node, adding any required attributes from
this child node alone -- but not processing any
children. |
public void setCollapseAttributes(boolean collapseAttributes) {
this.collapseAttributes = collapseAttributes;
}
flag to treat attributes as nested elements;
optional, default false |
public void setDelimiter(String delimiter) {
this.delimiter = delimiter;
}
|
public void setFile(File src) {
setSrcResource(new FileResource(src));
}
The XML file to parse; required. |
public void setIncludeSemanticAttribute(boolean includeSemanticAttribute) {
this.includeSemanticAttribute = includeSemanticAttribute;
}
Include the semantic attribute name as part of the property name.
Ignored if semanticAttributes is not set to true. |
public void setKeeproot(boolean keepRoot) {
this.keepRoot = keepRoot;
}
flag to include the xml root tag as a
first value in the property name; optional,
default is true |
public void setPrefix(String prefix) {
this.prefix = prefix.trim();
}
the prefix to prepend to each property |
public void setRootDirectory(File rootDirectory) {
this.rootDirectory = rootDirectory;
}
The directory to use for resolving file references.
Ignored if semanticAttributes is not set to true. |
public void setSemanticAttributes(boolean semanticAttributes) {
this.semanticAttributes = semanticAttributes;
}
Attribute to enable special handling of attributes - see ant manual. |
public void setSrcResource(Resource src) {
if (src.isDirectory()) {
throw new BuildException("the source can't be a directory");
}
if (src instanceof FileResource && !supportsNonFileResources()) {
throw new BuildException("Only FileSystem resources are"
+ " supported.");
}
this.src = src;
}
The resource to pack; required. |
public void setValidate(boolean validate) {
this.validate = validate;
}
flag to validate the XML file; optional, default false |
protected boolean supportsNonFileResources() {
return getClass().equals(XmlProperty.class);
}
Whether this task can deal with non-file resources.
This implementation returns true only if this task is
<xmlproperty>. Any subclass of this class that also wants to
support non-file resources needs to override this method. We
need to do so for backwards compatibility reasons since we
can't expect subclasses to support resources. |