| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package org.apache.tools.ant.taskdefs; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Hashtable; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.ParserConfigurationException; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.types.Path; |
| import org.apache.tools.ant.types.Resource; |
| import org.apache.tools.ant.types.ResourceCollection; |
| import org.apache.tools.ant.types.XMLCatalog; |
| import org.apache.tools.ant.types.resources.FileResource; |
| import org.apache.tools.ant.util.FileUtils; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.EntityResolver; |
| |
| /** |
| * Loads property values from a valid XML file, generating the |
| * property names from the file's element and attribute names. |
| * |
| * <p>Example:</p> |
| * <pre> |
| * <root-tag myattr="true"> |
| * <inner-tag someattr="val">Text</inner-tag> |
| * <a2><a3><a4>false</a4></a3></a2> |
| * <x>x1</x> |
| * <x>x2</x> |
| * </root-tag> |
| *</pre> |
| * |
| * <p>this generates the following properties:</p> |
| * |
| * <pre> |
| * root-tag(myattr)=true |
| * root-tag.inner-tag=Text |
| * root-tag.inner-tag(someattr)=val |
| * root-tag.a2.a3.a4=false |
| * root-tag.x=x1,x2 |
| * </pre> |
| * |
| * <p>The <i>collapseAttributes</i> property of this task can be set |
| * to true (the default is false) which will instead result in the |
| * following properties (note the difference in names of properties |
| * corresponding to XML attributes):</p> |
| * |
| * <pre> |
| * root-tag.myattr=true |
| * root-tag.inner-tag=Text |
| * root-tag.inner-tag.someattr=val |
| * root-tag.a2.a3.a4=false |
| * root-tag.x=x1,x2 |
| * </pre> |
| * |
| * <p>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):</p> |
| * |
| * <ul> |
| * <li><b>value</b>: Identifies a text value for a property.</li> |
| * <li><b>location</b>: Identifies a file location for a property.</li> |
| * <li><b>id</b>: Sets an id for a property</li> |
| * <li><b>refid</b>: Sets a property to the value of another property |
| * based upon the provided id</li> |
| * <li><b>pathid</b>: Defines a path rather than a property with |
| * the given id.</li> |
| * </ul> |
| * |
| * <p>For example, with keepRoot = false, the following properties file:</p> |
| * |
| * <pre> |
| * <root-tag> |
| * <build> |
| * <build folder="build"> |
| * <classes id="build.classes" location="${build.folder}/classes"/> |
| * <reference refid="build.classes"/> |
| * </build> |
| * <compile> |
| * <classpath pathid="compile.classpath"> |
| * <pathelement location="${build.classes}"/> |
| * </classpath> |
| * </compile> |
| * <run-time> |
| * <jars>*.jar</jars> |
| * <classpath pathid="run-time.classpath"> |
| * <path refid="compile.classpath"/> |
| * <pathelement path="${run-time.jars}"/> |
| * </classpath> |
| * </run-time> |
| * </root-tag> |
| * </pre> |
| * |
| * <p>is equivalent to the following entries in a build file:</p> |
| * |
| * <pre> |
| * <property name="build" location="build"/> |
| * <property name="build.classes" location="${build.location}/classes"/> |
| * <property name="build.reference" refid="build.classes"/> |
| * |
| * <property name="run-time.jars" value="*.jar/> |
| * |
| * <classpath id="compile.classpath"> |
| * <pathelement location="${build.classes}"/> |
| * </classpath> |
| * |
| * <classpath id="run-time.classpath"> |
| * <path refid="compile.classpath"/> |
| * <pathelement path="${run-time.jars}"/> |
| * </classpath> |
| * </pre> |
| * |
| * <p> This task <i>requires</i> the following attributes:</p> |
| * |
| * <ul> |
| * <li><b>file</b>: The name of the file to load.</li> |
| * </ul> |
| * |
| * <p>This task supports the following attributes:</p> |
| * |
| * <ul> |
| * <li><b>prefix</b>: Optionally specify a prefix applied to |
| * all properties loaded. Defaults to an empty string.</li> |
| * <li><b>keepRoot</b>: Indicate whether the root xml element |
| * is kept as part of property name. Defaults to true.</li> |
| * <li><b>validate</b>: Indicate whether the xml file is validated. |
| * Defaults to false.</li> |
| * <li><b>collapseAttributes</b>: Indicate whether attributes are |
| * stored in property names with parens or with period |
| * delimiters. Defaults to false, meaning properties |
| * are stored with parens (i.e., foo(attr)).</li> |
| * <li><b>semanticAttributes</b>: Indicate whether attributes |
| * named "location", "value", "refid" and "path" |
| * are interpreted as ant properties. Defaults |
| * to false.</li> |
| * <li><b>rootDirectory</b>: Indicate the directory to use |
| * as the root directory for resolving location |
| * properties. Defaults to the directory |
| * of the project using the task.</li> |
| * <li><b>includeSemanticAttribute</b>: Indicate whether to include |
| * the semantic attribute ("location" or "value") as |
| * part of the property name. Defaults to false.</li> |
| * </ul> |
| * |
| * @ant.task name="xmlproperty" category="xml" |
| */ |
| public class XmlProperty extends org.apache.tools.ant.Task { |
| |
| private Resource src; |
| private String prefix = ""; |
| private boolean keepRoot = true; |
| private boolean validate = false; |
| private boolean collapseAttributes = false; |
| private boolean semanticAttributes = false; |
| private boolean includeSemanticAttribute = false; |
| private File rootDirectory = null; |
| private Hashtable addedAttributes = new Hashtable(); |
| private XMLCatalog xmlCatalog = new XMLCatalog(); |
| private String delimiter = ","; |
| |
| private static final String ID = "id"; |
| private static final String REF_ID = "refid"; |
| private static final String LOCATION = "location"; |
| private static final String VALUE = "value"; |
| private static final String PATH = "path"; |
| private static final String PATHID = "pathid"; |
| private static final String[] ATTRIBUTES = new String[] { |
| ID, REF_ID, LOCATION, VALUE, PATH, PATHID |
| }; |
| |
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); |
| |
| /** |
| * Constructor. |
| */ |
| public XmlProperty() { |
| super(); |
| } |
| |
| /** |
| * Initializes the task. |
| */ |
| |
| public void init() { |
| super.init(); |
| xmlCatalog.setProject(getProject()); |
| } |
| |
| /** |
| * @return the xmlCatalog as the entityresolver. |
| */ |
| protected EntityResolver getEntityResolver() { |
| return xmlCatalog; |
| } |
| |
| /** |
| * Run the task. |
| * @throws BuildException The exception raised during task execution. |
| * @todo validate the source file is valid before opening, print a better error message |
| * @todo add a verbose level log message listing the name of the file being loaded |
| */ |
| public void execute() throws BuildException { |
| Resource r = getResource(); |
| |
| if (r == null) { |
| throw new BuildException("XmlProperty task requires a source resource"); |
| } |
| 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); |
| } |
| } |
| |
| /** Iterate through all nodes in the tree. */ |
| private void addNodeRecursively(Node node, String prefix, Object container) { |
| // Set the prefix for this node to include its tag name. |
| String nodePrefix = prefix; |
| if (node.getNodeType() != Node.TEXT_NODE) { |
| if (prefix.trim().length() > 0) { |
| nodePrefix += "."; |
| } |
| nodePrefix += node.getNodeName(); |
| } |
| // Pass the container to the processing of this node, |
| Object nodeObject = processNode(node, nodePrefix, container); |
| |
| // now, iterate through children. |
| if (node.hasChildNodes()) { |
| NodeList nodeChildren = node.getChildNodes(); |
| int numChildren = nodeChildren.getLength(); |
| |
| for (int i = 0; i < numChildren; i++) { |
| // For each child, pass the object added by |
| // processNode to its children -- in other word, each |
| // object can pass information along to its children. |
| addNodeRecursively(nodeChildren.item(i), nodePrefix, nodeObject); |
| } |
| } |
| } |
| |
| void addNodeRecursively(org.w3c.dom.Node node, String prefix) { |
| addNodeRecursively(node, prefix, null); |
| } |
| |
| /** |
| * Process the given node, adding any required attributes from |
| * this child node alone -- but <em>not</em> processing any |
| * children. |
| * |
| * @param node the XML Node to parse |
| * @param prefix A string to prepend to any properties that get |
| * added by this node. |
| * @param container Optionally, an object that a parent node |
| * generated that this node might belong to. For example, this |
| * node could be within a node that generated a Path. |
| * @return the Object created by this node. Generally, this is |
| * either a String if this node resulted in setting an attribute, |
| * or a Path. |
| */ |
| 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; |
| } |
| 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); |
| } |
| |
| /** |
| * Actually add the given property/value to the project |
| * after writing a log message. |
| */ |
| private void addProperty (String name, String value, String id) { |
| String msg = name + ":" + value; |
| if (id != null) { |
| msg += ("(id=" + id + ")"); |
| } |
| log(msg, Project.MSG_DEBUG); |
| |
| if (addedAttributes.containsKey(name)) { |
| // If this attribute was added by this task, then |
| // we append this value to the existing value. |
| // We use the setProperty method which will |
| // forcibly override the property if it already exists. |
| // We need to put these properties into the project |
| // when we read them, though (instead of keeping them |
| // outside of the project and batch adding them at the end) |
| // to allow other properties to reference them. |
| value = (String) addedAttributes.get(name) + getDelimiter() + value; |
| getProject().setProperty(name, value); |
| addedAttributes.put(name, value); |
| } else if (getProject().getProperty(name) == null) { |
| getProject().setNewProperty(name, value); |
| addedAttributes.put(name, value); |
| } else { |
| log("Override ignored for property " + name, Project.MSG_VERBOSE); |
| } |
| if (id != null) { |
| getProject().addReference(id, value); |
| } |
| } |
| |
| /** |
| * Return a reasonable attribute name for the given node. |
| * If we are using semantic attributes or collapsing |
| * attributes, the returned name is ".nodename". |
| * Otherwise, we return "(nodename)". This is long-standing |
| * (and default) <xmlproperty> behavior. |
| */ |
| private String getAttributeName (Node attributeNode) { |
| String attributeName = attributeNode.getNodeName(); |
| |
| if (semanticAttributes) { |
| // Never include the "refid" attribute as part of the |
| // attribute name. |
| if (attributeName.equals(REF_ID)) { |
| return ""; |
| } |
| // Otherwise, return it appended unless property to hide it is set. |
| if (!isSemanticAttribute(attributeName) || includeSemanticAttribute) { |
| return "." + attributeName; |
| } |
| return ""; |
| } |
| return collapseAttributes ? "." + attributeName : "(" + attributeName + ")"; |
| } |
| |
| /** |
| * Return whether the provided attribute name is recognized or not. |
| */ |
| private static boolean isSemanticAttribute (String attributeName) { |
| for (int i = 0; i < ATTRIBUTES.length; i++) { |
| if (attributeName.equals(ATTRIBUTES[i])) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Return the value for the given attribute. |
| * If we are not using semantic attributes, its just the |
| * literal string value of the attribute. |
| * |
| * <p>If we <em>are</em> using semantic attributes, then first |
| * dependent properties are resolved (i.e., ${foo} is resolved |
| * based on the foo property value), and then an appropriate data |
| * type is used. In particular, location-based properties are |
| * resolved to absolute file names. Also for refid values, look |
| * up the referenced object from the project.</p> |
| */ |
| private String getAttributeValue (Node attributeNode) { |
| String nodeValue = attributeNode.getNodeValue().trim(); |
| if (semanticAttributes) { |
| String attributeName = attributeNode.getNodeName(); |
| nodeValue = getProject().replaceProperties(nodeValue); |
| if (attributeName.equals(LOCATION)) { |
| File f = resolveFile(nodeValue); |
| return f.getPath(); |
| } |
| if (attributeName.equals(REF_ID)) { |
| Object ref = getProject().getReference(nodeValue); |
| if (ref != null) { |
| return ref.toString(); |
| } |
| } |
| } |
| return nodeValue; |
| } |
| |
| /** |
| * The XML file to parse; required. |
| * @param src the file to parse |
| */ |
| public void setFile(File src) { |
| setSrcResource(new FileResource(src)); |
| } |
| |
| /** |
| * The resource to pack; required. |
| * @param src resource to expand |
| */ |
| 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; |
| } |
| |
| /** |
| * Set the source resource. |
| * @param a the resource to pack as a single element Resource collection. |
| */ |
| 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()); |
| } |
| |
| /** |
| * the prefix to prepend to each property |
| * @param prefix the prefix to prepend to each property |
| */ |
| public void setPrefix(String prefix) { |
| this.prefix = prefix.trim(); |
| } |
| |
| /** |
| * flag to include the xml root tag as a |
| * first value in the property name; optional, |
| * default is true |
| * @param keepRoot if true (default), include the xml root tag |
| */ |
| public void setKeeproot(boolean keepRoot) { |
| this.keepRoot = keepRoot; |
| } |
| |
| /** |
| * flag to validate the XML file; optional, default false |
| * @param validate if true validate the XML file, default false |
| */ |
| public void setValidate(boolean validate) { |
| this.validate = validate; |
| } |
| |
| /** |
| * flag to treat attributes as nested elements; |
| * optional, default false |
| * @param collapseAttributes if true treat attributes as nested elements |
| */ |
| public void setCollapseAttributes(boolean collapseAttributes) { |
| this.collapseAttributes = collapseAttributes; |
| } |
| |
| /** |
| * Attribute to enable special handling of attributes - see ant manual. |
| * @param semanticAttributes if true enable the special handling. |
| */ |
| public void setSemanticAttributes(boolean semanticAttributes) { |
| this.semanticAttributes = semanticAttributes; |
| } |
| |
| /** |
| * The directory to use for resolving file references. |
| * Ignored if semanticAttributes is not set to true. |
| * @param rootDirectory the directory. |
| */ |
| public void setRootDirectory(File rootDirectory) { |
| this.rootDirectory = rootDirectory; |
| } |
| |
| /** |
| * Include the semantic attribute name as part of the property name. |
| * Ignored if semanticAttributes is not set to true. |
| * @param includeSemanticAttribute if true include the sematic attribute |
| * name. |
| */ |
| public void setIncludeSemanticAttribute(boolean includeSemanticAttribute) { |
| this.includeSemanticAttribute = includeSemanticAttribute; |
| } |
| |
| /** |
| * add an XMLCatalog as a nested element; optional. |
| * @param catalog the XMLCatalog to use |
| */ |
| public void addConfiguredXMLCatalog(XMLCatalog catalog) { |
| xmlCatalog.addConfiguredXMLCatalog(catalog); |
| } |
| |
| /* Expose members for extensibility */ |
| |
| /** |
| * @return the file attribute. |
| */ |
| protected File getFile () { |
| return src instanceof FileResource ? ((FileResource) src).getFile() : null; |
| } |
| |
| /** |
| * @return the resource. |
| */ |
| protected Resource getResource() { |
| // delegate this way around to support subclasses that |
| // overwrite getFile |
| File f = getFile(); |
| return f == null ? src : src instanceof FileResource |
| && ((FileResource) src).getFile().equals(f) ? src : new FileResource(f); |
| } |
| |
| /** |
| * @return the prefix attribute. |
| */ |
| protected String getPrefix () { |
| return this.prefix; |
| } |
| |
| /** |
| * @return the keeproot attribute. |
| */ |
| protected boolean getKeeproot () { |
| return this.keepRoot; |
| } |
| |
| /** |
| * @return the validate attribute. |
| */ |
| protected boolean getValidate () { |
| return this.validate; |
| } |
| |
| /** |
| * @return the collapse attributes attribute. |
| */ |
| protected boolean getCollapseAttributes () { |
| return this.collapseAttributes; |
| } |
| |
| /** |
| * @return the semantic attributes attribute. |
| */ |
| protected boolean getSemanticAttributes () { |
| return this.semanticAttributes; |
| } |
| |
| /** |
| * @return the root directory attribute. |
| */ |
| protected File getRootDirectory () { |
| return this.rootDirectory; |
| } |
| |
| /** |
| * @return the include semantic attribute. |
| */ |
| protected boolean getIncludeSementicAttribute () { |
| return this.includeSemanticAttribute; |
| } |
| |
| /** |
| * Let project resolve the file - or do it ourselves if |
| * rootDirectory has been set. |
| */ |
| private File resolveFile(String fileName) { |
| return FILE_UTILS.resolveFile(rootDirectory == null ? getProject().getBaseDir() |
| : rootDirectory, fileName); |
| } |
| |
| /** |
| * Whether this task can deal with non-file resources. |
| * |
| * <p>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.</p> |
| * @return true for this task. |
| * @since Ant 1.7 |
| */ |
| protected boolean supportsNonFileResources() { |
| return getClass().equals(XmlProperty.class); |
| } |
| |
| /** |
| * Get the current delimiter. |
| * @return delimiter |
| */ |
| public String getDelimiter() { |
| return delimiter; |
| } |
| |
| /** |
| * Sets a new delimiter. |
| * @param delimiter new value |
| * @since Ant 1.7.1 |
| */ |
| public void setDelimiter(String delimiter) { |
| this.delimiter = delimiter; |
| } |
| } |