⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlproperty.java

📁 Use the links below to download a source distribution of Ant from one of our mirrors. It is good pra
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* *  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> *   &lt;root-tag myattr="true"&gt; *     &lt;inner-tag someattr="val"&gt;Text&lt;/inner-tag&gt; *     &lt;a2&gt;&lt;a3&gt;&lt;a4&gt;false&lt;/a4&gt;&lt;/a3&gt;&lt;/a2&gt; *     &lt;x&gt;x1&lt;/x&gt; *     &lt;x&gt;x2&lt;/x&gt; *   &lt;/root-tag&gt; *</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> * &lt;root-tag&gt; *   &lt;build&gt; *   &lt;build folder="build"&gt; *     &lt;classes id="build.classes" location="${build.folder}/classes"/&gt; *     &lt;reference refid="build.classes"/&gt; *   &lt;/build&gt; *   &lt;compile&gt; *     &lt;classpath pathid="compile.classpath"&gt; *       &lt;pathelement location="${build.classes}"/&gt; *     &lt;/classpath&gt; *   &lt;/compile&gt; *   &lt;run-time&gt; *     &lt;jars&gt;*.jar&lt;/jars&gt; *     &lt;classpath pathid="run-time.classpath"&gt; *       &lt;path refid="compile.classpath"/&gt; *       &lt;pathelement path="${run-time.jars}"/&gt; *     &lt;/classpath&gt; *   &lt;/run-time&gt; * &lt;/root-tag&gt; * </pre> * * <p>is equivalent to the following entries in a build file:</p> * * <pre> * &lt;property name="build" location="build"/&gt; * &lt;property name="build.classes" location="${build.location}/classes"/&gt; * &lt;property name="build.reference" refid="build.classes"/&gt; * * &lt;property name="run-time.jars" value="*.jar/&gt; * * &lt;classpath id="compile.classpath"&gt; *   &lt;pathelement location="${build.classes}"/&gt; * &lt;/classpath&gt; * * &lt;classpath id="run-time.classpath"&gt; *   &lt;path refid="compile.classpath"/&gt; *   &lt;pathelement path="${run-time.jars}"/&gt; * &lt;/classpath&gt; * </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) {            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);        }    }    /** 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;                    } 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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -