Package com.sun.faban.harness.util

Source Code of com.sun.faban.harness.util.XMLReader

/* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.sun.com/cddl/cddl.html or
* install_dir/legal/LICENSE
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at install_dir/legal/LICENSE.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id$
*
* Copyright 2005-2009 Sun Microsystems Inc. All Rights Reserved
*/
package com.sun.faban.harness.util;

import com.sun.faban.common.NameValuePair;
import com.sun.faban.common.ParamReader;
import com.sun.faban.common.Utilities;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Provides all XML accesses to the parameter repository and other XML files.
*/
public class XMLReader {

    private static Logger logger = Logger.getLogger(XMLReader.class.getName());
    private Document doc;
    private XPath xPath;
    private String file;
    private boolean updated = false;
    private HashMap<Node, ArrayList<NameValuePair<Integer>>> hostPortsTable;

    /**
     * Constructs the XML reader.
     * @param file The XML file
     */
    public XMLReader(String file) {
        initLocal(file);
    }

    /**
     * Constructs the XML reader.
     * @param file The XML file
     * @param useFabanNS Whether to apply Faban namespaces in this file
     * @param warnDeprecated Whether to warn for deprecated Faban elements
     */
    public XMLReader(String file, boolean useFabanNS, boolean warnDeprecated) {
        if (useFabanNS)
            try {
                this.file = file;
                ParamReader reader = new ParamReader(file, warnDeprecated);
                doc = reader.getDocument();
                xPath = reader.getXPath();
            } catch (Exception e) {
                throw new XMLException(e.getMessage(), e);
            }
        else
            initLocal(file);
    }

    private String completeXPath(String xpath) {
        // If no absolute xpath is not given use //xpath to find the parameter
        if (xpath.charAt(0) != '/') {
            xpath = "//" + xpath;
        } else {
            //the JXPathContext expects 'params' (which is the variable name returned by XMLFile
            xpath = "params" + xpath;
        }
        return xpath;
    }

    private void initLocal(String file) {
        this.file = file;
        try {
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().
                    newDocumentBuilder();
            doc = builder.parse(new File(file));
            xPath = XPathFactory.newInstance().newXPath();
        } catch (Exception e) {
            throw new XMLException(e.getMessage(), e);
        }
    }

    /**
     * Returns nodelist for the given tag.
     * @param tagName
     * @return nodelist
     */
    public NodeList getNodeListForTagName(String tagName){
        return doc.getElementsByTagName(tagName);
    }

    /**
     * Returns nodelist for top level elements(Children of root element).
     * @return nodelist.
     */
    public NodeList getTopLevelElements() {
        NodeList topLevelElements = doc.getDocumentElement().getChildNodes();
        return topLevelElements;
    }

    /**
     * Returns the root element.
     * @return element.
     */
    public Element getRootNode() {
        return doc.getDocumentElement();
    }

    /**
     * Returns node for the given xpath.
     * @param xpath
     * @return node
     */
    public Node getNode(String xpath) {
        xpath = completeXPath(xpath);
        return getNode(xpath, doc);
    }

    /**
     * Returns node for the given xpath based on the base node.
     * @param xpath
     * @param base
     * @return node.
     */
    public Node getNode(String xpath, Node base) {
        Node node = null;
        try {
            node = (Node) xPath.evaluate(xpath,
                                                base, XPathConstants.NODE);
        } catch (XPathExpressionException e) {
            logger.log(Level.WARNING, "Error processing XPath expression: " +
                                                                xpath, e);
        }
        return node;
    }

    /**
     * Returns the nodelist for a given xpath.
     * @param xpath
     * @return nodelist.
     */
    public NodeList getNodes(String xpath) {
        xpath = completeXPath(xpath);
        return getNodes(xpath, doc);
    }

    /**
     * Returns the nodelist for a given xpath based on a base node.
     * @param xpath
     * @param base
     * @return nodelist.
     */
    public NodeList getNodes(String xpath, Node base) {
        NodeList nodes = null;
        try {
            nodes = (NodeList) xPath.evaluate(xpath,
                                                base, XPathConstants.NODESET);
        } catch (XPathExpressionException e) {
            logger.log(Level.WARNING, "Error processing XPath expression: " +
                                                                xpath, e);
        }
        return nodes;
    }

    /**
     * Returns the value for the given xpath.
     * @param xpath
     * @return string.
     */
    public String getValue(String xpath) {
        xpath = completeXPath(xpath);
        return getValue(xpath, doc);
    }

    /**
     * Returns the value for the given xpath based on the base node.
     * @param xpath
     * @param base
     * @return string.
     */
    public String getValue(String xpath, Node base) {
        try {
            return xPath.evaluate(xpath, base);
        } catch (XPathExpressionException e) {
            throw new XMLException("Error evaluating " + xpath + ", " +
                                   e.getMessage(), e);
        }
    }

    /**
     * Returns the list of values for a given xpath.
     * @param xpath
     * @return List<String>.
     */
    public List<String> getValues(String xpath) {
        xpath = completeXPath(xpath);
        return getValues(xpath, doc);
    }

    /**
     * Returns the list of values for a given xpath based on base node.
     * @param xpath
     * @param base
     * @return List<String>.
     */
    public List<String> getValues(String xpath, Node base) {
        try {
            NodeList nodeList = (NodeList) xPath.evaluate(
                                xpath, base, XPathConstants.NODESET);
            int length = nodeList.getLength();
            ArrayList<String> vList = new ArrayList<String>();
            for (int i = 0; i < length; i++) {
                Node node = nodeList.item(i);
                String value = null;
                nodeTraceLoop:
                while (node != null)
                    switch (node.getNodeType()) {
                        case Node.ATTRIBUTE_NODE :
                        case Node.CDATA_SECTION_NODE :
                        case Node.COMMENT_NODE :
                        case Node.PROCESSING_INSTRUCTION_NODE :
                        case Node.TEXT_NODE : value = node.getNodeValue();
                                              break nodeTraceLoop;
                        default : node = node.getFirstChild();
                    }

                if (value == null)
                    value = "";
                vList.add(value);
            }
            return vList;
        } catch (XPathExpressionException e) {
            throw new XMLException("Error evaluating " + xpath + ", " +
                                   e.getMessage(), e);
        }
    }

    /**
     * Returns the list of attribute values for a given xpath and attribute.
     * @param xpath
     * @param attribute
     * @return List<String>.
     */
    public List<String> getAttributeValues(String xpath, String attribute) {
        xpath = completeXPath(xpath);
        return getAttributeValues(xpath, attribute, doc);
    }

    /**
     * Returns the list of attribute values for a given xpath and attribute
     * based on base node.
     * @param xpath
     * @param attribute
     * @param base
     * @return List<String>.
     */
    public List<String> getAttributeValues(String xpath, String attribute, Node base) {
        try {
            NodeList nodeList = (NodeList) xPath.evaluate(xpath + "[@" + attribute + "]",
                                base, XPathConstants.NODESET);
            int length = nodeList.getLength();
            ArrayList<String> vList = new ArrayList<String>();
            for (int i = 0; i < length; i++) {
                Node node = nodeList.item(i);
                String value = null;
                nodeTraceLoop:
                while (node != null)
                    switch (node.getNodeType()) {
                        case Node.ELEMENT_NODE:
                            Element e = (Element) node;
                            value = e.getAttribute(attribute);
                            break nodeTraceLoop;
                        case Node.ATTRIBUTE_NODE :
                            value = node.getNodeValue();
                            break nodeTraceLoop;
                        default : node = node.getFirstChild();
                    }

                if (value == null)
                    value = "";
                vList.add(value);
            }
            return vList;
        } catch (XPathExpressionException e) {
            throw new XMLException("Error evaluating " + xpath + ", " +
                                   e.getMessage(), e);
        }
    }

    /**
     * Sets the new value for a given xpath.
     * @param xpath The XPath to the element to set the value
     * @param newValue The new value
     */
    public void setValue(String xpath, String newValue) {
        // If no absolute xpath is not given use //xpath to find the parameter
        xpath = completeXPath(xpath);
       
        try {
            NodeList nodeList = (NodeList) xPath.evaluate(
                                xpath, doc, XPathConstants.NODESET);
            int length = nodeList.getLength();
            boolean updated = false;
            for (int i = 0; i < length; i++) {
                Node node = nodeList.item(i);
                nodeTraceLoop:
                while (node != null) {
                    short nodeType = node.getNodeType();
                    logger.finer("XPath: " + xpath);
                    logger.finer("NodeType[" + i + "]: " + nodeType);

                    switch (nodeType) {
                        case Node.ATTRIBUTE_NODE :
                        case Node.CDATA_SECTION_NODE :
                        case Node.COMMENT_NODE :
                        case Node.PROCESSING_INSTRUCTION_NODE :
                        case Node.TEXT_NODE : node.setNodeValue(newValue);
                                              updated = true;
                                              break nodeTraceLoop;
                        default :   if (node.hasChildNodes()) {
                                        node = node.getFirstChild();
                                    } else {
                                        node.setTextContent(newValue);
                                        updated = true;
                                        break nodeTraceLoop;
                                    }
                    }
                }
            }
            if (updated)
                this.updated = true;
            else
                throw new XMLException("Update of XPath " + xpath +
                        " unsuccessful!");
        } catch (XPathExpressionException e) {
            throw new XMLException("Error evaluating " + xpath + ", " +
                                   e.getMessage(), e);
        }
    }

    /**
     * Sets the new value for the element.
     * @param element The DOM element
     * @param value The new value
     */
    public void setValue(Element element, String value) {
        NodeList children = element.getChildNodes();
        boolean valueSet = false;
        int childCount = children.getLength();
        for (int i = 0; i < childCount; i++) {
            Node child = children.item(i);
            short nodeType = child.getNodeType();
            if (nodeType == Node.TEXT_NODE) {
                child.setNodeValue(value);
                valueSet = true;
                break;
            }
        }
        if (!valueSet)
            element.appendChild(doc.createTextNode(value));
    }
   
    /**
     * Replaces the new value for the element text.
     * @param element
     * @param value
     */
    public void replaceValue(Element element, String value) {
        NodeList children = element.getChildNodes();
        int childCount = children.getLength();
        for (int i = 0; i < childCount; i++) {
            Node child = children.item(i);
            short nodeType = child.getNodeType();
            if (nodeType == Node.TEXT_NODE) {
                child.setTextContent(value);
                this.updated = true;
                break;
            }
        }
    }

    /**
     * Deletes a node.
     * @param deleteNode
     * @param parent
     * @return Element
     */
    public void deleteNode(Node deleteNode, Node parent) {
        parent.removeChild(deleteNode);
        this.updated = true;
    }

    /**
     * Adds a node.
     * @param parent
     * @param namespaceURI
     * @param prefix
     * @param nodeName
     * @return Element
     */
    public Element addNode(Element parent, String namespaceURI,
                           String prefix, String nodeName) {
        Element newNode;
        if (namespaceURI == null) {
            newNode = doc.createElement(nodeName);
        } else {
            newNode = doc.createElementNS(namespaceURI, nodeName);
            if (prefix != null)
                newNode.setPrefix(prefix);
        }
        parent.appendChild(newNode);
        this.updated = true;
        return newNode;
    }

    /**
     * Adds a node.
     * @param baseXPath
     * @param namespaceURI
     * @param prefix
     * @param nodeName
     * @return Element
     */
    public Element addNode(String baseXPath, String namespaceURI,
                           String prefix, String nodeName) {
        // If no absolute baseXPath is not given use //baseXPath to find the parameter
        if(baseXPath.charAt(0) != '/')
            baseXPath = "//" + baseXPath;
        else    //the JXPathContext expects 'params' (which is the variable name returned by XMLFile
            baseXPath = "params" + baseXPath;
        try {
            NodeList nodeList = (NodeList) xPath.evaluate(
                                baseXPath, doc, XPathConstants.NODESET);
            int length = nodeList.getLength();
            if (length == 0) {
                logger.warning("No match for XPath " + baseXPath);
                return null;
            } else if (length > 1) {
                logger.warning("XPath " + baseXPath +
                        " references more than one node. Please make the " +
                        "XPath more specific.");
                return null;
            }

            Node node = nodeList.item(0);
            if (node.getNodeType() != Node.ELEMENT_NODE) {
                logger.warning("XPath " + baseXPath +
                        " does not reference an element.");
                return null;
            }

            return addNode((Element) node, namespaceURI, prefix, nodeName);
           
        } catch (XPathExpressionException e) {
            throw new XMLException("Error evaluating " + baseXPath + ", " +
                                   e.getMessage(), e);
        }

    }

    /**
     * This method saves the XML file if it was modified
     * and if a back up file name is specified the original
     * file is backed up.
     * @param backupFileName  - the name of the backup file
     * @return Whether the save succeeded
     * @throws Exception Error saving the file
     */
    public boolean save(String backupFileName) throws Exception {

        // Check if a save is needed
        if(!updated)
            return false;

        //backup the file
        if(backupFileName != null) {
            BufferedReader in = new BufferedReader(new FileReader(file));
            BufferedWriter out = new BufferedWriter(new FileWriter(backupFileName));
            int ch;
            while((ch = in.read()) != -1)
                out.write(ch);
            in.close();
            out.close();
        }

        TransformerFactory tFactory = TransformerFactory.newInstance();
        Transformer transformer = tFactory.newTransformer();
        // transformer.getOutputProperties().list(System.out);

        if (doc.getDoctype() != null){
            transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, doc.getDoctype().getPublicId());
            transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
        }

        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(new File(file));
        transformer.transform(source, result);

        return true;
    }

    /**
     * Scans the XML for specific entries matching
     * "//fa:hostConfig/fa:hostPorts" and processes them for later retrieval.
     */
    public void processHostPorts() {
        String xPathExpr = "//fa:hostConfig/fa:hostPorts";
        hostPortsTable = new HashMap<Node, ArrayList<NameValuePair<Integer>>>();
        try {
            NodeList nodeList = (NodeList) xPath.evaluate(xPathExpr, doc,
                                                        XPathConstants.NODESET);
            int entries = nodeList.getLength();
            for (int i = 0; i < entries; i++) {
                processHostPorts(nodeList.item(i));
            }

        } catch (XPathExpressionException e) {
            logger.log(Level.WARNING, "Error processing XPath expression: " +
                                                                xPathExpr, e);
        }
    }

    private boolean isHostNode(Node hostsNode) {
        if (hostsNode.getNodeType() != Node.ELEMENT_NODE)
            return false;
        String nodeName = hostsNode.getNodeName();
        if (nodeName == null)
            return false;
        if (!nodeName.endsWith(":host"))
            return false;
        if (!ParamReader.FABANURI.equals(hostsNode.getNamespaceURI()))
            return false;
        return true;
    }

    private void processHostPorts(Node hostPortNode) {

        Node hostConfig = hostPortNode.getParentNode();
        Node firstChild = hostConfig.getFirstChild();
        Node hostsNode = firstChild;
        if (!isHostNode(hostsNode)) {
            hostsNode = null;
            NodeList hostConfigNodes = hostConfig.getChildNodes();
            int length = hostConfigNodes.getLength();
            for (int i = 1; i < length; i++) {
                Node pHost = hostConfigNodes.item(i);
                if (isHostNode(pHost)) {
                    hostsNode = pHost;
                    break;
                }
            }
        }

        LinkedHashSet<String> hostsSet = new LinkedHashSet<String>();

        if (hostsNode != null) {
            Node textNode = hostsNode.getFirstChild();
            if (textNode != null && textNode.getNodeType() == Node.TEXT_NODE) {
                String[] hostList = textNode.getNodeValue().split("\\s");
                for (String hostName : hostList) {
                    hostsSet.add(hostName);
                }
            }
        }

        Node clientsNode = hostPortNode.getFirstChild();
        String clients;
        if (clientsNode == null) {
            clients = "";
        } else {
            clients = clientsNode.getNodeValue();
            if (clients == null)
                clients = "";
        }

        ArrayList<NameValuePair<Integer>> hostsPorts =
                                    new ArrayList<NameValuePair<Integer>>();

        String hosts = Utilities.parseHostPorts(clients, hostsPorts, hostsSet);

        if (hostsNode == null) {
            hostsNode = doc.createElementNS(ParamReader.FABANURI, "host");
            hostsNode.setPrefix("fa");
            hostsNode.appendChild(doc.createTextNode(hosts.toString().trim()));
            hostConfig.insertBefore(hostsNode, firstChild);
        } else {
            Node textNode = hostsNode.getFirstChild();
            if (textNode != null)
                textNode.setNodeValue(hosts.toString().trim());
            else
                hostsNode.appendChild(doc.createTextNode(
                        hosts.toString().trim()));                       
        }
        hostPortsTable.put(hostPortNode, hostsPorts);
    }

    /**
     * Obtains the host:port name value pair list from the element
     * matching this XPath.
     * @param xPathExpr
     * @return The list of host:port elements, or null if the XPath does
     * not exist or does not point to a host:port node.
     */
    public List<NameValuePair<Integer>> getHostPorts(String xPathExpr) {
        ArrayList<NameValuePair<Integer>> hostsPorts = null;
        if(xPathExpr.charAt(0) != '/')
            xPathExpr = "//" + xPathExpr;
        else    //the JXPathContext expects 'params' which is the variable name returned by XMLFile
            xPathExpr = "params" + xPathExpr;

        try {
            Node hostPortNode = (Node) xPath.evaluate(xPathExpr,
                                                doc, XPathConstants.NODE);
            if (hostPortNode != null)
                hostsPorts = hostPortsTable.get(hostPortNode);

        } catch (XPathExpressionException e) {
            logger.log(Level.WARNING, "Error processing XPath expression: " +
                                                                xPathExpr, e);
        }
        return hostsPorts;
    }

    /**
     * Obtains the host:port pairs based on a role.
     * @param roleNode The node representing the role
     * @return The host:port pairs
     */
    public List<NameValuePair<Integer>> getHostPorts(Element roleNode) {
        ArrayList<NameValuePair<Integer>> hostsPorts = null;
        try {
            Node hostPortNode = (Node) xPath.evaluate(
                    "fa:hostConfig/fa:hostPorts", roleNode, XPathConstants.NODE);
            if (hostPortNode != null)
                hostsPorts = hostPortsTable.get(hostPortNode);
        } catch (XPathExpressionException e) {
            logger.log(Level.WARNING, "Error processing XPath expression: " +
                    "fa:hostConfig/fa:hostPorts", e);
        }
        return hostsPorts;
    }

    /**
     * Returns NodeList for a given xpath string.
     * @param xPathExpr
     * @return NodeList
     */
    public NodeList getNodeList(String xPathExpr) {
        NodeList nodes = null;
        if(xPathExpr.charAt(0) != '/')
            xPathExpr = "//" + xPathExpr;
        else    //the JXPathContext expects 'params' which is the variable name returned by XMLFile
            xPathExpr = "params" + xPathExpr;

        try {
            nodes = (NodeList) xPath.evaluate(xPathExpr,
                                                doc, XPathConstants.NODESET);
        } catch (XPathExpressionException e) {
            logger.log(Level.WARNING, "Error processing XPath expression: " +
                                                                xPathExpr, e);
        }
        return nodes;
    }

    /**
     * Runs some testing of the XML reader.
     * @param args The command line arguments
     * @throws Exception If there are errors with the test
     */
    public static void main(String[] args) throws Exception {
        if(args.length < 3)
            System.out.println("Usage : java XMLReader <XML File> <XPath exp>");

        XMLReader util = new XMLReader(args[0], true, false);
        util.processHostPorts();

        System.out.println("File : " + args[0]);
        System.out.println("XPath : " + args[1]);

        System.out.print("\ngetValues : " + args[1] + " = ");
        String[] values = (String[])util.getValues(args[1]).toArray(new String[1]);
        for(int j = 0; j < values.length; j++)
            System.out.print(values[j] + "\t");

        System.out.print("\ngetValue : " + args[1] + " = ");
        System.out.println(util.getValue(args[1]));

        System.out.print("\ngetBooleanValue : " + args[1] + " = ");
        System.out.println(Boolean.toString(Boolean.valueOf(util.getValue(args[1])).booleanValue()));

    }
}
TOP

Related Classes of com.sun.faban.harness.util.XMLReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.