/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed 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.harmony.xml;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.ext.LexicalHandler;

import android.compat.annotation.UnsupportedAppUsage;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import libcore.io.IoUtils;

import dalvik.annotation.optimization.ReachabilitySensitive;

/**
 * Adapts SAX API to the Expat native XML parser. Not intended for reuse
 * across documents.
 *
 * @see org.apache.harmony.xml.ExpatReader
 */
class ExpatParser {

    private static final int BUFFER_SIZE = 8096; // in bytes

    /** Pointer to XML_Parser instance. */
    // A few native methods taking the pointer value are static; @ReachabilitySensitive is
    // necessary to ensure the Java object is kept reachable sufficiently long in these cases.
    @ReachabilitySensitive
    private long pointer;

    private boolean inStartElement = false;
    private int attributeCount = -1;
    private long attributePointer = 0;

    private final Locator locator = new ExpatLocator();

    @UnsupportedAppUsage
    private final ExpatReader xmlReader;

    private final String publicId;
    private final String systemId;

    private final String encoding;

    @UnsupportedAppUsage
    private final ExpatAttributes attributes = new CurrentAttributes();

    private static final String OUTSIDE_START_ELEMENT
            = "Attributes can only be used within the scope of startElement().";

    /** We default to UTF-8 when the user doesn't specify an encoding. */
    private static final String DEFAULT_ENCODING = "UTF-8";

    /** Encoding used for Java chars, used to parse Readers and Strings */
    /*package*/ static final String CHARACTER_ENCODING = "UTF-16";

    /** Timeout for HTTP connections (in ms) */
    private static final int TIMEOUT = 20 * 1000;

    /**
     * Constructs a new parser with the specified encoding.
     */
    @UnsupportedAppUsage
    /*package*/ ExpatParser(String encoding, ExpatReader xmlReader,
            boolean processNamespaces, String publicId, String systemId) {
        this.publicId = publicId;
        this.systemId = systemId;

        this.xmlReader = xmlReader;

        /*
         * TODO: Let Expat try to guess the encoding instead of defaulting.
         * Unfortunately, I don't know how to tell which encoding Expat picked,
         * so I won't know how to encode "<externalEntity>" below. The solution
         * I think is to fix Expat to not require the "<externalEntity>"
         * workaround.
         */
        this.encoding = encoding == null ? DEFAULT_ENCODING : encoding;
        this.pointer = initialize(
            this.encoding,
            processNamespaces
        );
    }

    /**
     * Used by {@link EntityParser}.
     */
    private ExpatParser(String encoding, ExpatReader xmlReader, long pointer,
            String publicId, String systemId) {
        this.encoding = encoding;
        this.xmlReader = xmlReader;
        this.pointer = pointer;
        this.systemId = systemId;
        this.publicId = publicId;
    }

    /**
     * Initializes native resources.
     *
     * @return the pointer to the native parser
     */
    private native long initialize(String encoding, boolean namespacesEnabled);

    /**
     * Called at the start of an element.
     *
     * @param uri namespace URI of element or "" if namespace processing is
     *  disabled
     * @param localName local name of element or "" if namespace processing is
     *  disabled
     * @param qName qualified name or "" if namespace processing is enabled
     * @param attributePointer pointer to native attribute char*--we keep
     *  a separate pointer so we can detach it from the parser instance
     * @param attributeCount number of attributes
     */
    /*package*/ void startElement(String uri, String localName, String qName,
            long attributePointer, int attributeCount) throws SAXException {
        ContentHandler contentHandler = xmlReader.contentHandler;
        if (contentHandler == null) {
            return;
        }

        try {
            inStartElement = true;
            this.attributePointer = attributePointer;
            this.attributeCount = attributeCount;

            contentHandler.startElement(
                    uri, localName, qName, this.attributes);
        } finally {
            inStartElement = false;
            this.attributeCount = -1;
            this.attributePointer = 0;
        }
    }

    /*package*/ void endElement(String uri, String localName, String qName)
            throws SAXException {
        ContentHandler contentHandler = xmlReader.contentHandler;
        if (contentHandler != null) {
            contentHandler.endElement(uri, localName, qName);
        }
    }

    /*package*/ void text(char[] text, int length) throws SAXException {
        ContentHandler contentHandler = xmlReader.contentHandler;
        if (contentHandler != null) {
            contentHandler.characters(text, 0, length);
        }
    }

    /*package*/ void comment(char[] text, int length) throws SAXException {
        LexicalHandler lexicalHandler = xmlReader.lexicalHandler;
        if (lexicalHandler != null) {
            lexicalHandler.comment(text, 0, length);
        }
    }

    /*package*/ void startCdata() throws SAXException {
        LexicalHandler lexicalHandler = xmlReader.lexicalHandler;
        if (lexicalHandler != null) {
            lexicalHandler.startCDATA();
        }
    }

    /*package*/ void endCdata() throws SAXException {
        LexicalHandler lexicalHandler = xmlReader.lexicalHandler;
        if (lexicalHandler != null) {
            lexicalHandler.endCDATA();
        }
    }

    /*package*/ void startNamespace(String prefix, String uri)
            throws SAXException {
        ContentHandler contentHandler = xmlReader.contentHandler;
        if (contentHandler != null) {
            contentHandler.startPrefixMapping(prefix, uri);
        }
    }

    /*package*/ void endNamespace(String prefix) throws SAXException {
        ContentHandler contentHandler = xmlReader.contentHandler;
        if (contentHandler != null) {
            contentHandler.endPrefixMapping(prefix);
        }
    }

    /*package*/ void startDtd(String name, String publicId, String systemId)
            throws SAXException {
        LexicalHandler lexicalHandler = xmlReader.lexicalHandler;
        if (lexicalHandler != null) {
            lexicalHandler.startDTD(name, publicId, systemId);
        }
    }

    /*package*/ void endDtd() throws SAXException {
        LexicalHandler lexicalHandler = xmlReader.lexicalHandler;
        if (lexicalHandler != null) {
            lexicalHandler.endDTD();
        }
    }

    /*package*/ void processingInstruction(String target, String data)
            throws SAXException {
        ContentHandler contentHandler = xmlReader.contentHandler;
        if (contentHandler != null) {
            contentHandler.processingInstruction(target, data);
        }
    }

    /*package*/ void notationDecl(String name, String publicId, String systemId) throws SAXException {
        DTDHandler dtdHandler = xmlReader.dtdHandler;
        if (dtdHandler != null) {
            dtdHandler.notationDecl(name, publicId, systemId);
        }
    }

    /*package*/ void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) throws SAXException {
        DTDHandler dtdHandler = xmlReader.dtdHandler;
        if (dtdHandler != null) {
            dtdHandler.unparsedEntityDecl(name, publicId, systemId, notationName);
        }
    }

    /**
     * Handles an external entity.
     *
     * @param context to be passed back to Expat when we parse the entity
     * @param publicId the publicId of the entity
     * @param systemId the systemId of the entity
     */
    /*package*/ void handleExternalEntity(String context, String publicId,
            String systemId) throws SAXException, IOException {
        EntityResolver entityResolver = xmlReader.entityResolver;
        if (entityResolver == null) {
            return;
        }

        /*
         * The spec. is terribly under-specified here. It says that if the
         * systemId is a URL, we should try to resolve it, but it doesn't
         * specify how to tell whether or not the systemId is a URL let alone
         * how to resolve it.
         *
         * Other implementations do various insane things. We try to keep it
         * simple: if the systemId parses as a URI and it's relative, we try to
         * resolve it against the parent document's systemId. If anything goes
         * wrong, we go with the original systemId. If crazybob had designed
         * the API, he would have left all resolving to the EntityResolver.
         */
        if (this.systemId != null) {
            try {
                URI systemUri = new URI(systemId);
                if (!systemUri.isAbsolute() && !systemUri.isOpaque()) {
                    // It could be relative (or it may not be a URI at all!)
                    URI baseUri = new URI(this.systemId);
                    systemUri = baseUri.resolve(systemUri);

                    // Replace systemId w/ resolved URI
                    systemId = systemUri.toString();
                }
            } catch (Exception e) {
                System.logI("Could not resolve '" + systemId + "' relative to"
                        + " '" + this.systemId + "' at " + locator, e);
            }
        }

        InputSource inputSource = entityResolver.resolveEntity(
                publicId, systemId);
        if (inputSource == null) {
            /*
             * The spec. actually says that we should try to treat systemId
             * as a URL and download and parse its contents here, but an
             * entity resolver can easily accomplish the same by returning
             * new InputSource(systemId).
             *
             * Downloading external entities by default would result in several
             * unwanted DTD downloads, not to mention pose a security risk
             * when parsing untrusted XML -- see for example
             * http://archive.cert.uni-stuttgart.de/bugtraq/2002/10/msg00421.html --
             * so we just do nothing instead. This also enables the user to
             * opt out of entity parsing when using
             * {@link org.xml.sax.helpers.DefaultHandler}, something that
             * wouldn't be possible otherwise.
             */
            return;
        }

        String encoding = pickEncoding(inputSource);
        long pointer = createEntityParser(this.pointer, context);
        try {
            EntityParser entityParser = new EntityParser(encoding, xmlReader,
                    pointer, inputSource.getPublicId(),
                    inputSource.getSystemId());

            parseExternalEntity(entityParser, inputSource);
        } finally {
            releaseParser(pointer);
        }
    }

    /**
     * Picks an encoding for an external entity. Defaults to UTF-8.
     */
    private String pickEncoding(InputSource inputSource) {
        Reader reader = inputSource.getCharacterStream();
        if (reader != null) {
            return CHARACTER_ENCODING;
        }

        String encoding = inputSource.getEncoding();
        return encoding == null ? DEFAULT_ENCODING : encoding;
    }

    /**
     * Parses the the external entity provided by the input source.
     */
    private void parseExternalEntity(ExpatParser entityParser,
            InputSource inputSource) throws IOException, SAXException {
        /*
         * Expat complains if the external entity isn't wrapped with a root
         * element so we add one and ignore it later on during parsing.
         */

        // Try the character stream.
        Reader reader = inputSource.getCharacterStream();
        if (reader != null) {
            try {
                entityParser.append("<externalEntity>");
                entityParser.parseFragment(reader);
                entityParser.append("</externalEntity>");
            } finally {
                IoUtils.closeQuietly(reader);
            }
            return;
        }

        // Try the byte stream.
        InputStream in = inputSource.getByteStream();
        if (in != null) {
            try {
                entityParser.append("<externalEntity>"
                        .getBytes(entityParser.encoding));
                entityParser.parseFragment(in);
                entityParser.append("</externalEntity>"
                        .getBytes(entityParser.encoding));
            } finally {
                IoUtils.closeQuietly(in);
            }
            return;
        }

        // Make sure we use the user-provided systemId.
        String systemId = inputSource.getSystemId();
        if (systemId == null) {
            // TODO: We could just try our systemId here.
            throw new ParseException("No input specified.", locator);
        }

        // Try the system id.
        in = openUrl(systemId);
        try {
            entityParser.append("<externalEntity>"
                    .getBytes(entityParser.encoding));
            entityParser.parseFragment(in);
            entityParser.append("</externalEntity>"
                    .getBytes(entityParser.encoding));
        } finally {
            IoUtils.closeQuietly(in);
        }
    }

    /**
     * Creates a native entity parser.
     *
     * @param parentPointer pointer to parent Expat parser
     * @param context passed to {@link #handleExternalEntity}
     * @return pointer to native parser
     */
    private static native long createEntityParser(long parentPointer, String context);

    /**
     * Appends part of an XML document. This parser will parse the given XML to
     * the extent possible and dispatch to the appropriate methods.
     *
     * @param xml a whole or partial snippet of XML
     * @throws SAXException if an error occurs during parsing
     */
    /*package*/ void append(String xml) throws SAXException {
        try {
            appendString(this.pointer, xml, false);
        } catch (ExpatException e) {
            throw new ParseException(e.getMessage(), this.locator);
        }
    }

    private native void appendString(long pointer, String xml, boolean isFinal)
            throws SAXException, ExpatException;

    /**
     * Appends part of an XML document. This parser will parse the given XML to
     * the extent possible and dispatch to the appropriate methods.
     *
     * @param xml a whole or partial snippet of XML
     * @param offset into the char[]
     * @param length of characters to use
     * @throws SAXException if an error occurs during parsing
     */
    @UnsupportedAppUsage
    /*package*/ void append(char[] xml, int offset, int length)
            throws SAXException {
        try {
            appendChars(this.pointer, xml, offset, length);
        } catch (ExpatException e) {
            throw new ParseException(e.getMessage(), this.locator);
        }
    }

    private native void appendChars(long pointer, char[] xml, int offset,
            int length) throws SAXException, ExpatException;

    /**
     * Appends part of an XML document. This parser will parse the given XML to
     * the extent possible and dispatch to the appropriate methods.
     *
     * @param xml a whole or partial snippet of XML
     * @throws SAXException if an error occurs during parsing
     */
    /*package*/ void append(byte[] xml) throws SAXException {
        append(xml, 0, xml.length);
    }

    /**
     * Appends part of an XML document. This parser will parse the given XML to
     * the extent possible and dispatch to the appropriate methods.
     *
     * @param xml a whole or partial snippet of XML
     * @param offset into the byte[]
     * @param length of bytes to use
     * @throws SAXException if an error occurs during parsing
     */
    @UnsupportedAppUsage
    /*package*/ void append(byte[] xml, int offset, int length)
            throws SAXException {
        try {
            appendBytes(this.pointer, xml, offset, length);
        } catch (ExpatException e) {
            throw new ParseException(e.getMessage(), this.locator);
        }
    }

    private native void appendBytes(long pointer, byte[] xml, int offset,
            int length) throws SAXException, ExpatException;

    /**
     * Parses an XML document from the given input stream.
     */
    /*package*/ void parseDocument(InputStream in) throws IOException,
            SAXException {
        startDocument();
        parseFragment(in);
        finish();
        endDocument();
    }

    /**
     * Parses an XML Document from the given reader.
     */
    /*package*/ void parseDocument(Reader in) throws IOException, SAXException {
        startDocument();
        parseFragment(in);
        finish();
        endDocument();
    }

    /**
     * Parses XML from the given Reader.
     */
    private void parseFragment(Reader in) throws IOException, SAXException {
        char[] buffer = new char[BUFFER_SIZE / 2];
        int length;
        while ((length = in.read(buffer)) != -1) {
            try {
                appendChars(this.pointer, buffer, 0, length);
            } catch (ExpatException e) {
                throw new ParseException(e.getMessage(), locator);
            }
        }
    }

    /**
     * Parses XML from the given input stream.
     */
    private void parseFragment(InputStream in)
            throws IOException, SAXException {
        byte[] buffer = new byte[BUFFER_SIZE];
        int length;
        while ((length = in.read(buffer)) != -1) {
            try {
                appendBytes(this.pointer, buffer, 0, length);
            } catch (ExpatException e) {
                throw new ParseException(e.getMessage(), this.locator);
            }
        }
    }

    private void startDocument() throws SAXException {
        ContentHandler contentHandler = xmlReader.contentHandler;
        if (contentHandler != null) {
            contentHandler.setDocumentLocator(this.locator);
            contentHandler.startDocument();
        }
    }

    private void endDocument() throws SAXException {
        ContentHandler contentHandler;
        contentHandler = xmlReader.contentHandler;
        if (contentHandler != null) {
            contentHandler.endDocument();
        }
    }

    /**
     * Indicate that we're finished parsing.
     *
     * @throws SAXException if the xml is incomplete
     */
    @UnsupportedAppUsage
    /*package*/ void finish() throws SAXException {
        try {
            appendString(this.pointer, "", true);
        } catch (ExpatException e) {
            throw new ParseException(e.getMessage(), this.locator);
        }
    }

    @Override protected synchronized void finalize() throws Throwable {
        try {
            if (this.pointer != 0) {
                release(this.pointer);
                this.pointer = 0;
            }
        } finally {
            super.finalize();
        }
    }

    /**
     * Releases all native objects.
     */
    private native void release(long pointer);

    /**
     * Releases native parser only.
     */
    private static native void releaseParser(long pointer);

    /**
     * Initialize static resources.
     */
    private static native void staticInitialize(String emptyString);

    static {
        staticInitialize("");
    }

    /**
     * Gets the current line number within the XML file.
     */
    private int line() {
        return line(this.pointer);
    }

    private static native int line(long pointer);

    /**
     * Gets the current column number within the XML file.
     */
    private int column() {
        return column(this.pointer);
    }

    private static native int column(long pointer);

    /**
     * Clones the current attributes so they can be used outside of
     * startElement().
     */
    @UnsupportedAppUsage
    /*package*/ Attributes cloneAttributes() {
        if (!inStartElement) {
            throw new IllegalStateException(OUTSIDE_START_ELEMENT);
        }

        if (attributeCount == 0) {
            return ClonedAttributes.EMPTY;
        }

        long clonePointer
                = cloneAttributes(this.attributePointer, this.attributeCount);
        return new ClonedAttributes(pointer, clonePointer, attributeCount);
    }

    private static native long cloneAttributes(long pointer, int attributeCount);

    /**
     * Used for cloned attributes.
     */
    private static class ClonedAttributes extends ExpatAttributes {
    // TODO: Can we please remove this? It appears unused, and the finalizer
    // asynchronously invalidates the result returned by getPointer() at a
    // largely unpredictable time. b/70989581

        private static final Attributes EMPTY = new ClonedAttributes(0, 0, 0);

        private final long parserPointer;
        private long pointer;
        private final int length;

        /**
         * Constructs a Java wrapper for native attributes.
         *
         * @param parserPointer pointer to the parse, can be 0 if length is 0.
         * @param pointer pointer to the attributes array, can be 0 if the
         *  length is 0.
         * @param length number of attributes
         */
        private ClonedAttributes(long parserPointer, long pointer, int length) {
            this.parserPointer = parserPointer;
            this.pointer = pointer;
            this.length = length;
        }

        @Override
        public long getParserPointer() {
            return this.parserPointer;
        }

        @Override
        public long getPointer() {
            return pointer;
        }

        @Override
        public int getLength() {
            return length;
        }

        @Override protected synchronized void finalize() throws Throwable {
            try {
                if (pointer != 0) {
                    freeAttributes(pointer);
                    pointer = 0;
                }
            } finally {
                super.finalize();
            }
        }
    }

    private class ExpatLocator implements Locator {

        public String getPublicId() {
            return publicId;
        }

        public String getSystemId() {
            return systemId;
        }

        public int getLineNumber() {
            return line();
        }

        public int getColumnNumber() {
            return column();
        }

        @Override
        public String toString() {
            return "Locator[publicId: " + publicId + ", systemId: " + systemId
                + ", line: " + getLineNumber()
                + ", column: " + getColumnNumber() + "]";
        }
    }

    /**
     * Attributes that are only valid during startElement().
     */
    private class CurrentAttributes extends ExpatAttributes {

        @Override
        public long getParserPointer() {
            return pointer;
        }

        @Override
        public long getPointer() {
            if (!inStartElement) {
                throw new IllegalStateException(OUTSIDE_START_ELEMENT);
            }
            return attributePointer;
        }

        @Override
        public int getLength() {
            if (!inStartElement) {
                throw new IllegalStateException(OUTSIDE_START_ELEMENT);
            }
            return attributeCount;
        }
    }

    /**
     * Includes line and column in the message.
     */
    private static class ParseException extends SAXParseException {

        private ParseException(String message, Locator locator) {
            super(makeMessage(message, locator), locator);
        }

        private static String makeMessage(String message, Locator locator) {
            return makeMessage(message, locator.getLineNumber(),
                    locator.getColumnNumber());
        }

        private static String makeMessage(
                String message, int line, int column) {
            return "At line " + line + ", column "
                    + column + ": " + message;
        }
    }

    /**
     * Opens an InputStream for the given URL.
     */
    /*package*/ static InputStream openUrl(String url) throws IOException {
        try {
            URLConnection urlConnection = new URL(url).openConnection();
            urlConnection.setConnectTimeout(TIMEOUT);
            urlConnection.setReadTimeout(TIMEOUT);
            urlConnection.setDoInput(true);
            urlConnection.setDoOutput(false);
            return urlConnection.getInputStream();
        } catch (Exception e) {
            IOException ioe = new IOException("Couldn't open " + url);
            ioe.initCause(e);
            throw ioe;
        }
    }

    /**
     * Parses an external entity.
     */
    private static class EntityParser extends ExpatParser {

        @UnsupportedAppUsage
        private int depth = 0;

        private EntityParser(String encoding, ExpatReader xmlReader,
                long pointer, String publicId, String systemId) {
            super(encoding, xmlReader, pointer, publicId, systemId);
        }

        @Override
        void startElement(String uri, String localName, String qName,
                long attributePointer, int attributeCount) throws SAXException {
            /*
             * Skip topmost element generated by our workaround in
             * {@link #handleExternalEntity}.
             */
            if (depth++ > 0) {
                super.startElement(uri, localName, qName, attributePointer,
                        attributeCount);
            }
        }

        @Override
        void endElement(String uri, String localName, String qName)
                throws SAXException {
            if (--depth > 0) {
                super.endElement(uri, localName, qName);
            }
        }

        @Override
        @SuppressWarnings("FinalizeDoesntCallSuperFinalize")
        protected synchronized void finalize() throws Throwable {
            /*
             * Don't release our native resources. We do so explicitly in
             * {@link #handleExternalEntity} and we don't want to release the
             * parsing context--our parent is using it.
             */
        }
    }
}
