/*
 * 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.axis2.util;

import com.ibm.wsdl.Constants;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.util.Base64;
import org.apache.axiom.om.util.StAXUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.CharacterData;
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.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Stack;


public class XMLUtils {
    public static final String charEncoding = "ISO-8859-1";
    private static final String saxParserFactoryProperty =
            "javax.xml.parsers.SAXParserFactory";

    private static DocumentBuilderFactory dbf = getDOMFactory();
    private static SAXParserFactory saxFactory;
    private static Stack saxParsers = new Stack();

    private static String empty = "";
    private static ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());

    static {
        // Initialize SAX Parser factory defaults
        initSAXFactory(null, true, false);
    }

    /**
     * Initializes the SAX parser factory.
     *
     * @param factoryClassName The (optional) class name of the desired
     *                         SAXParserFactory implementation. Will be
     *                         assigned to the system property
     *                         <b>javax.xml.parsers.SAXParserFactory</b>
     *                         unless this property is already set.
     *                         If <code>null</code>, leaves current setting
     *                         alone.
     * @param namespaceAware   true if we want a namespace-aware parser
     * @param validating       true if we want a validating parser
     */
    public static void initSAXFactory(String factoryClassName,
                                      boolean namespaceAware,
                                      boolean validating) {
        if (factoryClassName != null) {
            try {
                saxFactory = (SAXParserFactory) Loader.loadClass(factoryClassName).
                        newInstance();
                /*
                 * Set the system property only if it is not already set to
                 * avoid corrupting environments in which Axis is embedded.
                 */
                if (System.getProperty(saxParserFactoryProperty) == null) {
                    System.setProperty(saxParserFactoryProperty,
                                       factoryClassName);
                }
            } catch (Exception e) {
                saxFactory = SAXParserFactory.newInstance();
            }
        } else {
            saxFactory = SAXParserFactory.newInstance();
        }
        saxFactory.setNamespaceAware(namespaceAware);
        saxFactory.setValidating(validating);

        // Discard existing parsers
        saxParsers.clear();
    }

    private static DocumentBuilderFactory getDOMFactory() {
        DocumentBuilderFactory dbf;
        try {
            dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
        }
        catch (Exception e) {
            //log.error(Messages.getMessage("exception00"), e );
            dbf = null;
        }
        return (dbf);
    }

    private static boolean tryReset = true;

    /**
     * Returns a SAX parser for reuse.
     *
     * @param parser A SAX parser that is available for reuse
     */
    public static void releaseSAXParser(SAXParser parser) {
        if (!tryReset) {
            return;
        }

        //Free up possible ref. held by past contenthandler.
        try {
            XMLReader xmlReader = parser.getXMLReader();
            if (null != xmlReader) {
                synchronized (XMLUtils.class) {
                    saxParsers.push(parser);
                }
            } else {
                tryReset = false;
            }
        } catch (org.xml.sax.SAXException e) {
            tryReset = false;
        }
    }

    /**
     * Gets an empty new Document.
     *
     * @return Returns Document.
     * @throws ParserConfigurationException if construction problems occur
     */
    public static Document newDocument()
            throws ParserConfigurationException {
        synchronized (dbf) {
            return dbf.newDocumentBuilder().newDocument();
        }
    }

    /**
     * Gets a new Document read from the input source.
     *
     * @return Returns Document.
     * @throws ParserConfigurationException if construction problems occur
     * @throws SAXException                 if the document has xml sax problems
     * @throws IOException                  if i/o exceptions occur
     */
    public static Document newDocument(InputSource inp)
            throws ParserConfigurationException, SAXException, IOException {
        DocumentBuilder db;
        synchronized (dbf) {
            try {
                db = dbf.newDocumentBuilder();
            } catch (Exception e){
                // Under some peculiar conditions (classloader issues), just scrap the old dbf, create a new one and try again.
                dbf = getDOMFactory();
                db = dbf.newDocumentBuilder();
            }
        }
        db.setEntityResolver(new DefaultEntityResolver());
        db.setErrorHandler(new ParserErrorHandler());
        return (db.parse(inp));
    }

    /**
     * Gets a new Document read from the input stream
     *
     * @return Returns Document.
     * @throws ParserConfigurationException if construction problems occur
     * @throws SAXException                 if the document has xml sax problems
     * @throws IOException                  if i/o exceptions occur
     */
    public static Document newDocument(InputStream inp)
            throws ParserConfigurationException, SAXException, IOException {
        return XMLUtils.newDocument(new InputSource(inp));
    }

    /**
     * Gets a new Document read from the indicated uri
     *
     * @return Returns Document.
     * @throws ParserConfigurationException if construction problems occur
     * @throws SAXException                 if the document has xml sax problems
     * @throws IOException                  if i/o exceptions occur
     */
    public static Document newDocument(String uri)
            throws ParserConfigurationException, SAXException, IOException {
        // call the authenticated version as there might be 
        // username/password info embeded in the uri.
        return XMLUtils.newDocument(uri, null, null);
    }

    /**
     * Creates a new document from the given URI. Uses the username and password
     * if the URI requires authentication.
     *
     * @param uri      the resource to get
     * @param username basic auth username
     * @param password basic auth password
     * @throws ParserConfigurationException if construction problems occur
     * @throws SAXException                 if the document has xml sax problems
     * @throws IOException                  if i/o exceptions occur
     */
    public static Document newDocument(String uri, String username, String password)
            throws ParserConfigurationException, SAXException, IOException {
        InputSource ins = XMLUtils.getInputSourceFromURI(uri, username, password);
        Document doc = XMLUtils.newDocument(ins);
        // Close the Stream
        if (ins.getByteStream() != null) {
            ins.getByteStream().close();
        } else if (ins.getCharacterStream() != null) {
            ins.getCharacterStream().close();
        }
        return doc;
    }


    public static String getPrefix(String uri, Node e) {
        while (e != null && (e.getNodeType() == Element.ELEMENT_NODE)) {
            NamedNodeMap attrs = e.getAttributes();
            for (int n = 0; n < attrs.getLength(); n++) {
                Attr a = (Attr) attrs.item(n);
                String name;
                if ((name = a.getName()).startsWith("xmlns:") &&
                        a.getNodeValue().equals(uri)) {
                    return name.substring(6);
                }
            }
            e = e.getParentNode();
        }
        return null;
    }

    public static String getNamespace(String prefix, Node e) {
        while (e != null && (e.getNodeType() == Node.ELEMENT_NODE)) {
            Attr attr =
                    ((Element) e).getAttributeNodeNS(Constants.NS_URI_XMLNS, prefix);
            if (attr != null) {
                return attr.getValue();
            }
            e = e.getParentNode();
        }
        return null;
    }

    /**
     * Returns a QName when passed a string like "foo:bar" by mapping
     * the "foo" prefix to a namespace in the context of the given Node.
     *
     * @return Returns a QName generated from the given string representation.
     */
    public static QName getQNameFromString(String str, Node e) {
        if (str == null || e == null) {
            return null;
        }

        int idx = str.indexOf(':');
        if (idx > -1) {
            String prefix = str.substring(0, idx);
            String ns = getNamespace(prefix, e);
            if (ns == null) {
                return null;
            }
            return new QName(ns, str.substring(idx + 1));
        } else {
            return new QName("", str);
        }
    }

    /**
     * Returns a string for a particular QName, mapping a new prefix
     * if necessary.
     */
    public static String getStringForQName(QName qname, Element e) {
        String uri = qname.getNamespaceURI();
        String prefix = getPrefix(uri, e);
        if (prefix == null) {
            int i = 1;
            prefix = "ns" + i;
            while (getNamespace(prefix, e) != null) {
                i++;
                prefix = "ns" + i;
            }
            e.setAttributeNS(Constants.NS_URI_XMLNS,
                             "xmlns:" + prefix, uri);
        }
        return prefix + ":" + qname.getLocalPart();
    }

    /**
     * Concatinates all the text and cdata node children of this elem and returns
     * the resulting text.
     * (by Matt Duftler)
     *
     * @param parentEl the element whose cdata/text node values are to
     *                 be combined.
     * @return Returns the concatinated string.
     */
    public static String getChildCharacterData(Element parentEl) {
        if (parentEl == null) {
            return null;
        }
        Node tempNode = parentEl.getFirstChild();
        StringBuffer strBuf = new StringBuffer();
        CharacterData charData;

        while (tempNode != null) {
            switch (tempNode.getNodeType()) {
                case Node.TEXT_NODE :
                case Node.CDATA_SECTION_NODE:
                    charData = (CharacterData) tempNode;
                    strBuf.append(charData.getData());
                    break;
            }
            tempNode = tempNode.getNextSibling();
        }
        return strBuf.toString();
    }

    public static class ParserErrorHandler implements ErrorHandler {
        /**
         * Returns a string describing parse exception details
         */
        private String getParseExceptionInfo(SAXParseException spe) {
            String systemId = spe.getSystemId();
            if (systemId == null) {
                systemId = "null";
            }
            return "URI=" + systemId +
                    " Line=" + spe.getLineNumber() +
                    ": " + spe.getMessage();
        }

        // The following methods are standard SAX ErrorHandler methods.
        // See SAX documentation for more info.

        public void warning(SAXParseException spe) throws SAXException {
        }

        public void error(SAXParseException spe) throws SAXException {
            String message = "Error: " + getParseExceptionInfo(spe);
            throw new SAXException(message);
        }

        public void fatalError(SAXParseException spe) throws SAXException {
            String message = "Fatal Error: " + getParseExceptionInfo(spe);
            throw new SAXException(message);
        }
    }


    /**
     * Utility to get the bytes uri.
     * Does NOT handle authenticated URLs,
     * use getInputSourceFromURI(uri, username, password)
     *
     * @param uri the resource to get
     */
    public static InputSource getInputSourceFromURI(String uri) {
        return new InputSource(uri);
    }


    /**
     * Utility to get the bytes at a protected uri
     * <p/>
     * Retrieves the URL if a username and password are provided.
     * The java.net.URL class does not do Basic Authentication, so we have to
     * do it manually in this routine.
     * <p/>
     * If no username is provided, creates an InputSource from the uri
     * and lets the InputSource go fetch the contents.
     *
     * @param uri      the resource to get
     * @param username basic auth username
     * @param password basic auth password
     */
    private static InputSource getInputSourceFromURI(String uri,
                                                     String username,
                                                     String password)
            throws IOException, ProtocolException, UnsupportedEncodingException {
        URL wsdlurl = null;
        try {
            wsdlurl = new URL(uri);
        } catch (MalformedURLException e) {
            // we can't process it, it might be a 'simple' foo.wsdl
            // let InputSource deal with it
            return new InputSource(uri);
        }

        // if no authentication, just let InputSource deal with it
        if (username == null && wsdlurl.getUserInfo() == null) {
            return new InputSource(uri);
        }

        // if this is not an HTTP{S} url, let InputSource deal with it
        if (!wsdlurl.getProtocol().startsWith("http")) {
            return new InputSource(uri);
        }

        URLConnection connection = wsdlurl.openConnection();
        // Does this work for https???
        if (!(connection instanceof HttpURLConnection)) {
            // can't do http with this URL, let InputSource deal with it
            return new InputSource(uri);
        }
        HttpURLConnection uconn = (HttpURLConnection) connection;
        String userinfo = wsdlurl.getUserInfo();
        uconn.setRequestMethod("GET");
        uconn.setAllowUserInteraction(false);
        uconn.setDefaultUseCaches(false);
        uconn.setDoInput(true);
        uconn.setDoOutput(false);
        uconn.setInstanceFollowRedirects(true);
        uconn.setUseCaches(false);

        // username/password info in the URL overrides passed in values 
        String auth = null;
        if (userinfo != null) {
            auth = userinfo;
        } else if (username != null) {
            auth = (password == null) ? username : username + ":" + password;
        }

        if (auth != null) {
            uconn.setRequestProperty("Authorization",
                                     "Basic " +
                                             base64encode(auth.getBytes(charEncoding)));
        }

        uconn.connect();

        return new InputSource(uconn.getInputStream());
    }

    public static String base64encode(byte[] bytes) {
        return Base64.encode(bytes);
    }

    public static InputSource getEmptyInputSource() {
        return new InputSource(bais);
    }

    /**
     * Finds a Node with a given QNameb.
     *
     * @param node parent node
     * @param name QName of the child we need to find
     * @return Returns child node.
     */
    public static Node findNode(Node node, QName name) {
        if (name.getNamespaceURI().equals(node.getNamespaceURI()) &&
                name.getLocalPart().equals(node.getLocalName())) {
            return node;
        }
        NodeList children = node.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node ret = findNode(children.item(i), name);
            if (ret != null) {
                return ret;
            }
        }
        return null;
    }

    /**
     * Convert DOM Element into a fully built OMElement
     * @param element dom Element
     * @return OMElement
     * @throws Exception
     */
    public static OMElement toOM(Element element) throws Exception {
        return toOM(element, true);
    }
    
    /**
     * Convert DOM Element into a fully built OMElement
     * @param element
     * @param buildAll if true, full OM tree is immediately built. if false, caller is responsible 
     * for building the tree and closing the parser.
     * @return
     * @throws Exception
     */
    public static OMElement toOM(Element element, boolean buildAll) throws Exception {

        Source source = new DOMSource(element);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Result result = new StreamResult(baos);

        Transformer xformer = TransformerFactory.newInstance().newTransformer();
        xformer.transform(source, result);

        ByteArrayInputStream is = new ByteArrayInputStream(baos.toByteArray());
        XMLStreamReader reader = StAXUtils
                .createXMLStreamReader(is);

        StAXOMBuilder builder = new StAXOMBuilder(reader);
        builder.setCache(true);
        builder.releaseParserOnClose(true);

        OMElement omElement = builder.getDocumentElement();
        if (buildAll) {
            omElement.build();
            builder.close();
        }
        return omElement;
    }


    /**
     * Converts a given OMElement to a DOM Element.
     *
     * @param element
     * @return Returns Element.
     * @throws Exception
     */
    public static Element toDOM(OMElement element) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        element.serialize(baos);
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        return factory.newDocumentBuilder().parse(bais).getDocumentElement();
    }


    /**
     * Converts a given inputstream to an OMNode
     * The reurned OMNode is fully built.
     *
     * @param inputStream
     * @return OMNode
     * @throws javax.xml.stream.XMLStreamException
     *
     */
    public static OMNode toOM(InputStream inputStream) throws XMLStreamException {
        return toOM(inputStream, true);
    }
    
    /**
     * Converts a given inputstream to an OMNode
     * The reurned OMNode is fully built if buildAll is true.
     * If buildAll is false, the caller is responsible for closing the parser.
     *
     * @param inputStream
     * @param buildAll
     * @return OMNode
     * @throws javax.xml.stream.XMLStreamException
     *
     */
    public static OMNode toOM(InputStream inputStream, boolean buildAll) throws XMLStreamException {
        XMLStreamReader xmlReader = StAXUtils
                .createXMLStreamReader(inputStream);
        OMFactory fac = OMAbstractFactory.getOMFactory();
        StAXOMBuilder builder = new StAXOMBuilder(fac, xmlReader);
        builder.setCache(true);
        builder.releaseParserOnClose(true);
        OMNode omNode = builder.getDocumentElement();
        
        if (buildAll) {
            omNode.build();
            builder.close();
        }
        
        return omNode;
    }

    /**
     * Converts a given Reader to an OMNode.
     * The reurned OMNode is fully built.
     *
     * @param reader
     * @return
     * @throws XMLStreamException
     */
    public static OMNode toOM(Reader reader) throws XMLStreamException {
        return toOM(reader, true);
    }
    
    /**
     * Converts a given Reader to an OMNode.
     * The reurned OMNode is fully built if buildAll is true.
     * If buildAll is false, the caller is responsible for closing the parser.
     *
     * @param reader
     * @param buildAll
     * @return OMNode
     * @throws XMLStreamException
     */
    public static OMNode toOM(Reader reader, boolean buildAll) throws XMLStreamException {
        XMLStreamReader xmlReader = StAXUtils
                .createXMLStreamReader(reader);
        OMFactory fac = OMAbstractFactory.getOMFactory();
        StAXOMBuilder builder = new StAXOMBuilder(fac, xmlReader);
        builder.setCache(true);
        builder.releaseParserOnClose(true);
        OMNode omNode = builder.getDocumentElement();
        
        if (buildAll) {
            omNode.build();
            builder.close();
        }
        
        return omNode;
    }
}
