/*
 * Copyright (C) 2008 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.
 */

#define LOG_TAG "ExpatParser"

#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
#include "LocalArray.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
#include "ScopedStringChars.h"
#include "ScopedUtfChars.h"
#include "UniquePtr.h"
#include "jni.h"
#include "cutils/log.h"
#include "unicode/unistr.h"

#include <string.h>
#include <libexpat/expat.h>

#define BUCKET_COUNT 128

/**
 * Wrapper around an interned string.
 */
struct InternedString {
    InternedString() : interned(NULL), bytes(NULL) {
    }

    ~InternedString() {
        delete[] bytes;
    }

    /** The interned string itself. */
    jstring interned;

    /** UTF-8 equivalent of the interned string. */
    const char* bytes;

    /** Hash code of the interned string. */
    int hash;
};

/**
 * Keeps track of strings between start and end events.
 */
class StringStack {
public:
    StringStack() : array(new jstring[DEFAULT_CAPACITY]), capacity(DEFAULT_CAPACITY), size(0) {
    }

    ~StringStack() {
        delete[] array;
    }

    void push(JNIEnv* env, jstring s) {
        if (size == capacity) {
            int newCapacity = capacity * 2;
            jstring* newArray = new jstring[newCapacity];
            if (newArray == NULL) {
                jniThrowOutOfMemoryError(env, NULL);
                return;
            }
            memcpy(newArray, array, capacity * sizeof(jstring));

            delete[] array;
            array = newArray;
            capacity = newCapacity;
        }

        array[size++] = s;
    }

    jstring pop() {
        return (size == 0) ? NULL : array[--size];
    }

private:
    enum { DEFAULT_CAPACITY = 10 };

    jstring* array;
    int capacity;
    int size;
};

/**
 * Data passed to parser handler method by the parser.
 */
struct ParsingContext {
    ParsingContext(jobject object) : env(NULL), object(object), buffer(NULL), bufferSize(-1) {
        for (int i = 0; i < BUCKET_COUNT; i++) {
            internedStrings[i] = NULL;
        }
    }

    // Warning: 'env' must be valid on entry.
    ~ParsingContext() {
        freeBuffer();

        // Free interned string cache.
        for (int i = 0; i < BUCKET_COUNT; i++) {
            if (internedStrings[i]) {
                InternedString** bucket = internedStrings[i];
                InternedString* current;
                while ((current = *(bucket++)) != NULL) {
                    // Free the interned string reference.
                    env->DeleteGlobalRef(current->interned);

                    // Free the bucket.
                    delete current;
                }

                // Free the buckets.
                delete[] internedStrings[i];
            }
        }
    }

    jcharArray ensureCapacity(int length) {
        if (bufferSize < length) {
            // Free the existing char[].
            freeBuffer();

            // Allocate a new char[].
            jcharArray javaBuffer = env->NewCharArray(length);
            if (javaBuffer == NULL) return NULL;

            // Create a global reference.
            javaBuffer = reinterpret_cast<jcharArray>(env->NewGlobalRef(javaBuffer));
            if (javaBuffer == NULL) return NULL;

            buffer = javaBuffer;
            bufferSize = length;
        }
        return buffer;
    }

private:
    void freeBuffer() {
        if (buffer != NULL) {
            env->DeleteGlobalRef(buffer);
            buffer = NULL;
            bufferSize = -1;
        }
    }

public:
    /**
     * The JNI environment for the current thread. This should only be used
     * to keep a reference to the env for use in Expat callbacks.
     */
    JNIEnv* env;

    /** The Java parser object. */
    jobject object;

    /** Buffer for text events. */
    jcharArray buffer;

private:
    /** The size of our buffer in jchars. */
    int bufferSize;

public:
    /** Current attributes. */
    const char** attributes;

    /** Number of attributes. */
    int attributeCount;

    /** True if namespace support is enabled. */
    bool processNamespaces;

    /** Keep track of names. */
    StringStack stringStack;

    /** Cache of interned strings. */
    InternedString** internedStrings[BUCKET_COUNT];
};

static ParsingContext* toParsingContext(void* data) {
    return reinterpret_cast<ParsingContext*>(data);
}

static ParsingContext* toParsingContext(XML_Parser parser) {
    return reinterpret_cast<ParsingContext*>(XML_GetUserData(parser));
}

static XML_Parser toXMLParser(jlong address) {
  return reinterpret_cast<XML_Parser>(address);
}

static jlong fromXMLParser(XML_Parser parser) {
  return reinterpret_cast<uintptr_t>(parser);
}

static jmethodID commentMethod;
static jmethodID endCdataMethod;
static jmethodID endDtdMethod;
static jmethodID endElementMethod;
static jmethodID endNamespaceMethod;
static jmethodID handleExternalEntityMethod;
static jmethodID internMethod;
static jmethodID notationDeclMethod;
static jmethodID processingInstructionMethod;
static jmethodID startCdataMethod;
static jmethodID startDtdMethod;
static jmethodID startElementMethod;
static jmethodID startNamespaceMethod;
static jmethodID textMethod;
static jmethodID unparsedEntityDeclMethod;
static jstring emptyString;

/**
 * Calculates a hash code for a null-terminated string. This is *not* equivalent
 * to Java's String.hashCode(). This hashes the bytes while String.hashCode()
 * hashes UTF-16 chars.
 *
 * @param s null-terminated string to hash
 * @returns hash code
 */
static int hashString(const char* s) {
    int hash = 0;
    if (s) {
        while (*s) {
            hash = hash * 31 + *s++;
        }
    }
    return hash;
}

/**
 * Creates a new interned string wrapper. Looks up the interned string
 * representing the given UTF-8 bytes.
 *
 * @param bytes null-terminated string to intern
 * @param hash of bytes
 * @returns wrapper of interned Java string
 */
static InternedString* newInternedString(JNIEnv* env, const char* bytes, int hash) {
    // Allocate a new wrapper.
    UniquePtr<InternedString> wrapper(new InternedString);
    if (wrapper.get() == NULL) {
        jniThrowOutOfMemoryError(env, NULL);
        return NULL;
    }

    // Create a copy of the UTF-8 bytes.
    // TODO: sometimes we already know the length. Reuse it if so.
    char* copy = new char[strlen(bytes) + 1];
    if (copy == NULL) {
        jniThrowOutOfMemoryError(env, NULL);
        return NULL;
    }
    strcpy(copy, bytes);
    wrapper->bytes = copy;

    // Save the hash.
    wrapper->hash = hash;

    // To intern a string, we must first create a new string and then call
    // intern() on it. We then keep a global reference to the interned string.
    ScopedLocalRef<jstring> newString(env, env->NewStringUTF(bytes));
    if (env->ExceptionCheck()) {
        return NULL;
    }

    // Call intern().
    ScopedLocalRef<jstring> interned(env,
            reinterpret_cast<jstring>(env->CallObjectMethod(newString.get(), internMethod)));
    if (env->ExceptionCheck()) {
        return NULL;
    }

    // Create a global reference to the interned string.
    wrapper->interned = reinterpret_cast<jstring>(env->NewGlobalRef(interned.get()));
    if (env->ExceptionCheck()) {
        return NULL;
    }

    return wrapper.release();
}

/**
 * Allocates a new bucket with one entry.
 *
 * @param entry to store in the bucket
 * @returns a reference to the bucket
 */
static InternedString** newInternedStringBucket(InternedString* entry) {
    InternedString** bucket = new InternedString*[2];
    if (bucket != NULL) {
        bucket[0] = entry;
        bucket[1] = NULL;
    }
    return bucket;
}

/**
 * Expands an interned string bucket and adds the given entry. Frees the
 * provided bucket and returns a new one.
 *
 * @param existingBucket the bucket to replace
 * @param entry to add to the bucket
 * @returns a reference to the newly-allocated bucket containing the given entry
 */
static InternedString** expandInternedStringBucket(
        InternedString** existingBucket, InternedString* entry) {
    // Determine the size of the existing bucket.
    int size = 0;
    while (existingBucket[size]) size++;

    // Allocate the new bucket with enough space for one more entry and
    // a null terminator.
    InternedString** newBucket = new InternedString*[size + 2];
    if (newBucket == NULL) return NULL;

    memcpy(newBucket, existingBucket, size * sizeof(InternedString*));
    newBucket[size] = entry;
    newBucket[size + 1] = NULL;
    delete[] existingBucket;

    return newBucket;
}

/**
 * Returns an interned string for the given UTF-8 string.
 *
 * @param bucket to search for s
 * @param s null-terminated string to find
 * @param hash of s
 * @returns interned Java string equivalent of s or null if not found
 */
static jstring findInternedString(InternedString** bucket, const char* s, int hash) {
    InternedString* current;
    while ((current = *(bucket++)) != NULL) {
        if (current->hash != hash) continue;
        if (!strcmp(s, current->bytes)) return current->interned;
    }
    return NULL;
}

/**
 * Returns an interned string for the given UTF-8 string.
 *
 * @param s null-terminated string to intern
 * @returns interned Java string equivelent of s or NULL if s is null
 */
static jstring internString(JNIEnv* env, ParsingContext* parsingContext, const char* s) {
    if (s == NULL) return NULL;

    int hash = hashString(s);
    int bucketIndex = hash & (BUCKET_COUNT - 1);

    InternedString*** buckets = parsingContext->internedStrings;
    InternedString** bucket = buckets[bucketIndex];
    InternedString* internedString;

    if (bucket) {
        // We have a bucket already. Look for the given string.
        jstring found = findInternedString(bucket, s, hash);
        if (found) {
            // We found it!
            return found;
        }

        // We didn't find it. :(
        // Create a new entry.
        internedString = newInternedString(env, s, hash);
        if (internedString == NULL) return NULL;

        // Expand the bucket.
        bucket = expandInternedStringBucket(bucket, internedString);
        if (bucket == NULL) {
            delete internedString;
            jniThrowOutOfMemoryError(env, NULL);
            return NULL;
        }

        buckets[bucketIndex] = bucket;

        return internedString->interned;
    } else {
        // We don't even have a bucket yet. Create an entry.
        internedString = newInternedString(env, s, hash);
        if (internedString == NULL) return NULL;

        // Create a new bucket with one entry.
        bucket = newInternedStringBucket(internedString);
        if (bucket == NULL) {
            delete internedString;
            jniThrowOutOfMemoryError(env, NULL);
            return NULL;
        }

        buckets[bucketIndex] = bucket;

        return internedString->interned;
    }
}

static void jniThrowExpatException(JNIEnv* env, XML_Error error) {
    const char* message = XML_ErrorString(error);
    jniThrowException(env, "org/apache/harmony/xml/ExpatException", message);
}

/**
 * Copies UTF-8 characters into the buffer. Returns the number of Java chars
 * which were buffered.
 *
 * @returns number of UTF-16 characters which were copied
 */
static size_t fillBuffer(ParsingContext* parsingContext, const char* utf8, int byteCount) {
    JNIEnv* env = parsingContext->env;

    // Grow buffer if necessary (the length in bytes is always >= the length in chars).
    jcharArray javaChars = parsingContext->ensureCapacity(byteCount);
    if (javaChars == NULL) {
        return -1;
    }

    // Decode UTF-8 characters into our char[].
    ScopedCharArrayRW chars(env, javaChars);
    if (chars.get() == NULL) {
        return -1;
    }
    UErrorCode status = U_ZERO_ERROR;
    UnicodeString utf16(UnicodeString::fromUTF8(StringPiece(utf8, byteCount)));
    return utf16.extract(chars.get(), byteCount, status);
}

/**
 * Buffers the given text and passes it to the given method.
 *
 * @param method to pass the characters and length to with signature
 *  (char[], int)
 * @param data parsing context
 * @param text to copy into the buffer
 * @param length of text to copy (in bytes)
 */
static void bufferAndInvoke(jmethodID method, void* data, const char* text, size_t length) {
    ParsingContext* parsingContext = toParsingContext(data);
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    // Buffer the element name.
    size_t utf16length = fillBuffer(parsingContext, text, length);

    // Invoke given method.
    jobject javaParser = parsingContext->object;
    jcharArray buffer = parsingContext->buffer;
    env->CallVoidMethod(javaParser, method, buffer, utf16length);
}

static const char** toAttributes(jlong attributePointer) {
    return reinterpret_cast<const char**>(static_cast<uintptr_t>(attributePointer));
}

/**
 * The component parts of an attribute or element name.
 */
class ExpatElementName {
public:
    ExpatElementName(JNIEnv* env, ParsingContext* parsingContext, jlong attributePointer, jint index) {
        const char** attributes = toAttributes(attributePointer);
        const char* name = attributes[index * 2];
        init(env, parsingContext, name);
    }

    ExpatElementName(JNIEnv* env, ParsingContext* parsingContext, const char* s) {
        init(env, parsingContext, s);
    }

    ~ExpatElementName() {
        free(mCopy);
    }

    /**
     * Returns the namespace URI, like "http://www.w3.org/1999/xhtml".
     * Possibly empty.
     */
    jstring uri() {
        return internString(mEnv, mParsingContext, mUri);
    }

    /**
     * Returns the element or attribute local name, like "h1". Never empty. When
     * namespace processing is disabled, this may contain a prefix, yielding a
     * local name like "html:h1". In such cases, the qName will always be empty.
     */
    jstring localName() {
        return internString(mEnv, mParsingContext, mLocalName);
    }

    /**
     * Returns the namespace prefix, like "html". Possibly empty.
     */
    jstring qName() {
        if (*mPrefix == 0) {
            return localName();
        }

        // return prefix + ":" + localName
        ::LocalArray<1024> qName(strlen(mPrefix) + 1 + strlen(mLocalName) + 1);
        snprintf(&qName[0], qName.size(), "%s:%s", mPrefix, mLocalName);
        return internString(mEnv, mParsingContext, &qName[0]);
    }

    /**
     * Returns true if this expat name has the same URI and local name.
     */
    bool matches(const char* uri, const char* localName) {
        return strcmp(uri, mUri) == 0 && strcmp(localName, mLocalName) == 0;
    }

    /**
     * Returns true if this expat name has the same qualified name.
     */
    bool matchesQName(const char* qName) {
        const char* lastColon = strrchr(qName, ':');

        // Compare local names only if either:
        //  - the input qualified name doesn't have a colon (like "h1")
        //  - this element doesn't have a prefix. Such is the case when it
        //    doesn't belong to a namespace, or when this parser's namespace
        //    processing is disabled. In the latter case, this element's local
        //    name may still contain a colon (like "html:h1").
        if (lastColon == NULL || *mPrefix == 0) {
            return strcmp(qName, mLocalName) == 0;
        }

        // Otherwise compare both prefix and local name
        size_t prefixLength = lastColon - qName;
        return strlen(mPrefix) == prefixLength
            && strncmp(qName, mPrefix, prefixLength) == 0
            && strcmp(lastColon + 1, mLocalName) == 0;
    }

private:
    JNIEnv* mEnv;
    ParsingContext* mParsingContext;
    char* mCopy;
    const char* mUri;
    const char* mLocalName;
    const char* mPrefix;

    /**
     * Decodes an Expat-encoded name of one of these three forms:
     *     "uri|localName|prefix" (example: "http://www.w3.org/1999/xhtml|h1|html")
     *     "uri|localName" (example: "http://www.w3.org/1999/xhtml|h1")
     *     "localName" (example: "h1")
     */
    void init(JNIEnv* env, ParsingContext* parsingContext, const char* s) {
        mEnv = env;
        mParsingContext = parsingContext;
        mCopy = strdup(s);

        // split the input into up to 3 parts: a|b|c
        char* context = NULL;
        char* a = strtok_r(mCopy, "|", &context);
        char* b = strtok_r(NULL, "|", &context);
        char* c = strtok_r(NULL, "|", &context);

        if (c != NULL) { // input of the form "uri|localName|prefix"
            mUri = a;
            mLocalName = b;
            mPrefix = c;
        } else if (b != NULL) { // input of the form "uri|localName"
            mUri = a;
            mLocalName = b;
            mPrefix = "";
        } else { // input of the form "localName"
            mLocalName = a;
            mUri = "";
            mPrefix = "";
        }
    }

    // Disallow copy and assignment.
    ExpatElementName(const ExpatElementName&);
    void operator=(const ExpatElementName&);
};

/**
 * Called by Expat at the start of an element. Delegates to the same method
 * on the Java parser.
 *
 * @param data parsing context
 * @param elementName "uri|localName" or "localName" for the current element
 * @param attributes alternating attribute names and values. Like element
 * names, attribute names follow the format "uri|localName" or "localName".
 */
static void startElement(void* data, const char* elementName, const char** attributes) {
    ParsingContext* parsingContext = toParsingContext(data);
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    // Count the number of attributes.
    int count = 0;
    while (attributes[count * 2]) count++;

    // Make the attributes available for the duration of this call.
    parsingContext->attributes = attributes;
    parsingContext->attributeCount = count;

    jobject javaParser = parsingContext->object;

    ExpatElementName e(env, parsingContext, elementName);
    jstring uri = parsingContext->processNamespaces ? e.uri() : emptyString;
    jstring localName = parsingContext->processNamespaces ? e.localName() : emptyString;
    jstring qName = e.qName();

    parsingContext->stringStack.push(env, qName);
    parsingContext->stringStack.push(env, uri);
    parsingContext->stringStack.push(env, localName);

    jlong attributesAddress = reinterpret_cast<jlong>(attributes);
    env->CallVoidMethod(javaParser, startElementMethod, uri, localName, qName, attributesAddress, count);

    parsingContext->attributes = NULL;
    parsingContext->attributeCount = -1;
}

/**
 * Called by Expat at the end of an element. Delegates to the same method
 * on the Java parser.
 *
 * @param data parsing context
 * @param elementName "uri|localName" or "localName" for the current element;
 *         we assume that this matches the last data on our stack.
 */
static void endElement(void* data, const char* /*elementName*/) {
    ParsingContext* parsingContext = toParsingContext(data);
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    jobject javaParser = parsingContext->object;

    jstring localName = parsingContext->stringStack.pop();
    jstring uri = parsingContext->stringStack.pop();
    jstring qName = parsingContext->stringStack.pop();

    env->CallVoidMethod(javaParser, endElementMethod, uri, localName, qName);
}

/**
 * Called by Expat when it encounters text. Delegates to the same method
 * on the Java parser. This may be called mutiple times with incremental pieces
 * of the same contiguous block of text.
 *
 * @param data parsing context
 * @param characters buffer containing encountered text
 * @param length number of characters in the buffer
 */
static void text(void* data, const char* characters, int length) {
    bufferAndInvoke(textMethod, data, characters, length);
}

/**
 * Called by Expat when it encounters a comment. Delegates to the same method
 * on the Java parser.

 * @param data parsing context
 * @param comment 0-terminated
 */
static void comment(void* data, const char* comment) {
    bufferAndInvoke(commentMethod, data, comment, strlen(comment));
}

/**
 * Called by Expat at the beginning of a namespace mapping.
 *
 * @param data parsing context
 * @param prefix null-terminated namespace prefix used in the XML
 * @param uri of the namespace
 */
static void startNamespace(void* data, const char* prefix, const char* uri) {
    ParsingContext* parsingContext = toParsingContext(data);
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    jstring internedPrefix = emptyString;
    if (prefix != NULL) {
        internedPrefix = internString(env, parsingContext, prefix);
        if (env->ExceptionCheck()) return;
    }

    jstring internedUri = emptyString;
    if (uri != NULL) {
        internedUri = internString(env, parsingContext, uri);
        if (env->ExceptionCheck()) return;
    }

    parsingContext->stringStack.push(env, internedPrefix);

    jobject javaParser = parsingContext->object;
    env->CallVoidMethod(javaParser, startNamespaceMethod, internedPrefix, internedUri);
}

/**
 * Called by Expat at the end of a namespace mapping.
 *
 * @param data parsing context
 * @param prefix null-terminated namespace prefix used in the XML;
 *         we assume this is the same as the last prefix on the stack.
 */
static void endNamespace(void* data, const char* /*prefix*/) {
    ParsingContext* parsingContext = toParsingContext(data);
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    jstring internedPrefix = parsingContext->stringStack.pop();

    jobject javaParser = parsingContext->object;
    env->CallVoidMethod(javaParser, endNamespaceMethod, internedPrefix);
}

/**
 * Called by Expat at the beginning of a CDATA section.
 *
 * @param data parsing context
 */
static void startCdata(void* data) {
    ParsingContext* parsingContext = toParsingContext(data);
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    jobject javaParser = parsingContext->object;
    env->CallVoidMethod(javaParser, startCdataMethod);
}

/**
 * Called by Expat at the end of a CDATA section.
 *
 * @param data parsing context
 */
static void endCdata(void* data) {
    ParsingContext* parsingContext = toParsingContext(data);
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    jobject javaParser = parsingContext->object;
    env->CallVoidMethod(javaParser, endCdataMethod);
}

/**
 * Called by Expat at the beginning of a DOCTYPE section.
 * Expat gives us 'hasInternalSubset', but the Java API doesn't expect it, so we don't need it.
 */
static void startDtd(void* data, const char* name,
        const char* systemId, const char* publicId, int /*hasInternalSubset*/) {
    ParsingContext* parsingContext = toParsingContext(data);
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    jstring javaName = internString(env, parsingContext, name);
    if (env->ExceptionCheck()) return;

    jstring javaPublicId = internString(env, parsingContext, publicId);
    if (env->ExceptionCheck()) return;

    jstring javaSystemId = internString(env, parsingContext, systemId);
    if (env->ExceptionCheck()) return;

    jobject javaParser = parsingContext->object;
    env->CallVoidMethod(javaParser, startDtdMethod, javaName, javaPublicId,
        javaSystemId);
}

/**
 * Called by Expat at the end of a DOCTYPE section.
 *
 * @param data parsing context
 */
static void endDtd(void* data) {
    ParsingContext* parsingContext = toParsingContext(data);
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    jobject javaParser = parsingContext->object;
    env->CallVoidMethod(javaParser, endDtdMethod);
}

/**
 * Called by Expat when it encounters processing instructions.
 *
 * @param data parsing context
 * @param target of the instruction
 * @param instructionData
 */
static void processingInstruction(void* data, const char* target, const char* instructionData) {
    ParsingContext* parsingContext = toParsingContext(data);
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    jstring javaTarget = internString(env, parsingContext, target);
    if (env->ExceptionCheck()) return;

    ScopedLocalRef<jstring> javaInstructionData(env, env->NewStringUTF(instructionData));
    if (env->ExceptionCheck()) return;

    jobject javaParser = parsingContext->object;
    env->CallVoidMethod(javaParser, processingInstructionMethod, javaTarget, javaInstructionData.get());
}

/**
 * Creates a new entity parser.
 *
 * @param object the Java ExpatParser instance
 * @param parentParser pointer
 * @param javaEncoding the character encoding name
 * @param javaContext that was provided to handleExternalEntity
 * @returns the pointer to the C Expat entity parser
 */
static jlong ExpatParser_createEntityParser(JNIEnv* env, jobject, jlong parentParser, jstring javaContext) {
    ScopedUtfChars context(env, javaContext);
    if (context.c_str() == NULL) {
        return 0;
    }

    XML_Parser parent = toXMLParser(parentParser);
    XML_Parser entityParser = XML_ExternalEntityParserCreate(parent, context.c_str(), NULL);
    if (entityParser == NULL) {
        jniThrowOutOfMemoryError(env, NULL);
    }

    return fromXMLParser(entityParser);
}

/**
 * Handles external entities. We ignore the "base" URI and keep track of it
 * ourselves.
 */
static int handleExternalEntity(XML_Parser parser, const char* context,
        const char*, const char* systemId, const char* publicId) {
    ParsingContext* parsingContext = toParsingContext(parser);
    jobject javaParser = parsingContext->object;
    JNIEnv* env = parsingContext->env;
    jobject object = parsingContext->object;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) {
        return XML_STATUS_ERROR;
    }

    ScopedLocalRef<jstring> javaSystemId(env, env->NewStringUTF(systemId));
    if (env->ExceptionCheck()) {
        return XML_STATUS_ERROR;
    }
    ScopedLocalRef<jstring> javaPublicId(env, env->NewStringUTF(publicId));
    if (env->ExceptionCheck()) {
        return XML_STATUS_ERROR;
    }
    ScopedLocalRef<jstring> javaContext(env, env->NewStringUTF(context));
    if (env->ExceptionCheck()) {
        return XML_STATUS_ERROR;
    }

    // Pass the wrapped parser and both strings to java.
    env->CallVoidMethod(javaParser, handleExternalEntityMethod, javaContext.get(),
            javaPublicId.get(), javaSystemId.get());

    /*
     * Parsing the external entity leaves parsingContext->env and object set to
     * NULL, so we need to restore both.
     *
     * TODO: consider restoring the original env and object instead of setting
     * them to NULL in the append() functions.
     */
    parsingContext->env = env;
    parsingContext->object = object;

    return env->ExceptionCheck() ? XML_STATUS_ERROR : XML_STATUS_OK;
}

/**
 * Expat gives us 'base', but the Java API doesn't expect it, so we don't need it.
 */
static void unparsedEntityDecl(void* data, const char* name, const char* /*base*/, const char* systemId, const char* publicId, const char* notationName) {
    ParsingContext* parsingContext = toParsingContext(data);
    jobject javaParser = parsingContext->object;
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    ScopedLocalRef<jstring> javaName(env, env->NewStringUTF(name));
    if (env->ExceptionCheck()) return;
    ScopedLocalRef<jstring> javaPublicId(env, env->NewStringUTF(publicId));
    if (env->ExceptionCheck()) return;
    ScopedLocalRef<jstring> javaSystemId(env, env->NewStringUTF(systemId));
    if (env->ExceptionCheck()) return;
    ScopedLocalRef<jstring> javaNotationName(env, env->NewStringUTF(notationName));
    if (env->ExceptionCheck()) return;

    env->CallVoidMethod(javaParser, unparsedEntityDeclMethod, javaName.get(), javaPublicId.get(), javaSystemId.get(), javaNotationName.get());
}

/**
 * Expat gives us 'base', but the Java API doesn't expect it, so we don't need it.
 */
static void notationDecl(void* data, const char* name, const char* /*base*/, const char* systemId, const char* publicId) {
    ParsingContext* parsingContext = toParsingContext(data);
    jobject javaParser = parsingContext->object;
    JNIEnv* env = parsingContext->env;

    // Bail out if a previously called handler threw an exception.
    if (env->ExceptionCheck()) return;

    ScopedLocalRef<jstring> javaName(env, env->NewStringUTF(name));
    if (env->ExceptionCheck()) return;
    ScopedLocalRef<jstring> javaPublicId(env, env->NewStringUTF(publicId));
    if (env->ExceptionCheck()) return;
    ScopedLocalRef<jstring> javaSystemId(env, env->NewStringUTF(systemId));
    if (env->ExceptionCheck()) return;

    env->CallVoidMethod(javaParser, notationDeclMethod, javaName.get(), javaPublicId.get(), javaSystemId.get());
}

/**
 * Creates a new Expat parser. Called from the Java ExpatParser constructor.
 *
 * @param object the Java ExpatParser instance
 * @param javaEncoding the character encoding name
 * @param processNamespaces true if the parser should handle namespaces
 * @returns the pointer to the C Expat parser
 */
static jlong ExpatParser_initialize(JNIEnv* env, jobject object, jstring javaEncoding,
        jboolean processNamespaces) {
    // Allocate parsing context.
    UniquePtr<ParsingContext> context(new ParsingContext(object));
    if (context.get() == NULL) {
        jniThrowOutOfMemoryError(env, NULL);
        return 0;
    }

    context->processNamespaces = processNamespaces;

    // Create a parser.
    XML_Parser parser;
    ScopedUtfChars encoding(env, javaEncoding);
    if (encoding.c_str() == NULL) {
        return 0;
    }
    if (processNamespaces) {
        // Use '|' to separate URIs from local names.
        parser = XML_ParserCreateNS(encoding.c_str(), '|');
    } else {
        parser = XML_ParserCreate(encoding.c_str());
    }

    if (parser != NULL) {
        if (processNamespaces) {
            XML_SetNamespaceDeclHandler(parser, startNamespace, endNamespace);
            XML_SetReturnNSTriplet(parser, 1);
        }

        XML_SetCdataSectionHandler(parser, startCdata, endCdata);
        XML_SetCharacterDataHandler(parser, text);
        XML_SetCommentHandler(parser, comment);
        XML_SetDoctypeDeclHandler(parser, startDtd, endDtd);
        XML_SetElementHandler(parser, startElement, endElement);
        XML_SetExternalEntityRefHandler(parser, handleExternalEntity);
        XML_SetNotationDeclHandler(parser, notationDecl);
        XML_SetProcessingInstructionHandler(parser, processingInstruction);
        XML_SetUnparsedEntityDeclHandler(parser, unparsedEntityDecl);
        XML_SetUserData(parser, context.release());
    } else {
        jniThrowOutOfMemoryError(env, NULL);
        return 0;
    }

    return fromXMLParser(parser);
}

/**
 * Decodes the bytes as characters and parse the characters as XML. This
 * performs character decoding using the charset specified at XML_Parser
 * creation. For Java chars, that charset must be UTF-16 so that a Java char[]
 * can be reinterpreted as a UTF-16 encoded byte[]. appendBytes, appendChars
 * and appendString all call through this method.
 */
static void append(JNIEnv* env, jobject object, jlong pointer,
        const char* bytes, size_t byteOffset, size_t byteCount, jboolean isFinal) {
    XML_Parser parser = toXMLParser(pointer);
    ParsingContext* context = toParsingContext(parser);
    context->env = env;
    context->object = object;
    if (!XML_Parse(parser, bytes + byteOffset, byteCount, isFinal) && !env->ExceptionCheck()) {
        jniThrowExpatException(env, XML_GetErrorCode(parser));
    }
    context->object = NULL;
    context->env = NULL;
}

static void ExpatParser_appendBytes(JNIEnv* env, jobject object, jlong pointer,
        jbyteArray xml, jint byteOffset, jint byteCount) {
    ScopedByteArrayRO byteArray(env, xml);
    if (byteArray.get() == NULL) {
        return;
    }

    const char* bytes = reinterpret_cast<const char*>(byteArray.get());
    append(env, object, pointer, bytes, byteOffset, byteCount, XML_FALSE);
}

static void ExpatParser_appendChars(JNIEnv* env, jobject object, jlong pointer,
        jcharArray xml, jint charOffset, jint charCount) {
    ScopedCharArrayRO charArray(env, xml);
    if (charArray.get() == NULL) {
        return;
    }

    const char* bytes = reinterpret_cast<const char*>(charArray.get());
    size_t byteOffset = 2 * charOffset;
    size_t byteCount = 2 * charCount;
    append(env, object, pointer, bytes, byteOffset, byteCount, XML_FALSE);
}

static void ExpatParser_appendString(JNIEnv* env, jobject object, jlong pointer, jstring javaXml, jboolean isFinal) {
    ScopedStringChars xml(env, javaXml);
    if (xml.get() == NULL) {
        return;
    }
    const char* bytes = reinterpret_cast<const char*>(xml.get());
    size_t byteCount = 2 * xml.size();
    append(env, object, pointer, bytes, 0, byteCount, isFinal);
}

/**
 * Releases parser only.
 */
static void ExpatParser_releaseParser(JNIEnv*, jobject, jlong address) {
  XML_ParserFree(toXMLParser(address));
}

/**
 * Cleans up after the parser. Called at garbage collection time.
 */
static void ExpatParser_release(JNIEnv* env, jobject, jlong address) {
  XML_Parser parser = toXMLParser(address);

  ParsingContext* context = toParsingContext(parser);
  context->env = env;
  delete context;

  XML_ParserFree(parser);
}

static int ExpatParser_line(JNIEnv*, jobject, jlong address) {
  return XML_GetCurrentLineNumber(toXMLParser(address));
}

static int ExpatParser_column(JNIEnv*, jobject, jlong address) {
  return XML_GetCurrentColumnNumber(toXMLParser(address));
}

/**
 * Gets the URI of the attribute at the given index.
 *
 * @param attributePointer to the attribute array
 * @param index of the attribute
 * @returns interned Java string containing attribute's URI
 */
static jstring ExpatAttributes_getURI(JNIEnv* env, jobject, jlong address,
        jlong attributePointer, jint index) {
  ParsingContext* context = toParsingContext(toXMLParser(address));
  return ExpatElementName(env, context, attributePointer, index).uri();
}

/**
 * Gets the local name of the attribute at the given index.
 *
 * @param attributePointer to the attribute array
 * @param index of the attribute
 * @returns interned Java string containing attribute's local name
 */
static jstring ExpatAttributes_getLocalName(JNIEnv* env, jobject, jlong address,
        jlong attributePointer, jint index) {
  ParsingContext* context = toParsingContext(toXMLParser(address));
  return ExpatElementName(env, context, attributePointer, index).localName();
}

/**
 * Gets the qualified name of the attribute at the given index.
 *
 * @param attributePointer to the attribute array
 * @param index of the attribute
 * @returns interned Java string containing attribute's local name
 */
static jstring ExpatAttributes_getQName(JNIEnv* env, jobject, jlong address,
        jlong attributePointer, jint index) {
  ParsingContext* context = toParsingContext(toXMLParser(address));
  return ExpatElementName(env, context, attributePointer, index).qName();
}

/**
 * Gets the value of the attribute at the given index.
 *
 * @param object Java ExpatParser instance
 * @param attributePointer to the attribute array
 * @param index of the attribute
 * @returns Java string containing attribute's value
 */
static jstring ExpatAttributes_getValueByIndex(JNIEnv* env, jobject,
        jlong attributePointer, jint index) {
    const char** attributes = toAttributes(attributePointer);
    const char* value = attributes[(index * 2) + 1];
    return env->NewStringUTF(value);
}

/**
 * Gets the index of the attribute with the given qualified name.
 *
 * @param attributePointer to the attribute array
 * @param qName to look for
 * @returns index of attribute with the given uri and local name or -1 if not
 *  found
 */
static jint ExpatAttributes_getIndexForQName(JNIEnv* env, jobject,
        jlong attributePointer, jstring qName) {
    ScopedUtfChars qNameBytes(env, qName);
    if (qNameBytes.c_str() == NULL) {
        return -1;
    }

    const char** attributes = toAttributes(attributePointer);
    int found = -1;
    for (int index = 0; attributes[index * 2]; ++index) {
        if (ExpatElementName(NULL, NULL, attributePointer, index).matchesQName(qNameBytes.c_str())) {
            found = index;
            break;
        }
    }

    return found;
}

/**
 * Gets the index of the attribute with the given URI and name.
 *
 * @param attributePointer to the attribute array
 * @param uri to look for
 * @param localName to look for
 * @returns index of attribute with the given uri and local name or -1 if not
 *  found
 */
static jint ExpatAttributes_getIndex(JNIEnv* env, jobject, jlong attributePointer,
        jstring uri, jstring localName) {
    ScopedUtfChars uriBytes(env, uri);
    if (uriBytes.c_str() == NULL) {
        return -1;
    }

    ScopedUtfChars localNameBytes(env, localName);
    if (localNameBytes.c_str() == NULL) {
        return -1;
    }

    const char** attributes = toAttributes(attributePointer);
    for (int index = 0; attributes[index * 2]; ++index) {
        if (ExpatElementName(NULL, NULL, attributePointer, index).matches(uriBytes.c_str(),
                localNameBytes.c_str())) {
            return index;
        }
    }
    return -1;
}

/**
 * Gets the value of the attribute with the given qualified name.
 *
 * @param attributePointer to the attribute array
 * @param uri to look for
 * @param localName to look for
 * @returns value of attribute with the given uri and local name or NULL if not
 *  found
 */
static jstring ExpatAttributes_getValueForQName(JNIEnv* env, jobject clazz,
        jlong attributePointer, jstring qName) {
    jint index = ExpatAttributes_getIndexForQName(env, clazz, attributePointer, qName);
    return index == -1 ? NULL
            : ExpatAttributes_getValueByIndex(env, clazz, attributePointer, index);
}

/**
 * Gets the value of the attribute with the given URI and name.
 *
 * @param attributePointer to the attribute array
 * @param uri to look for
 * @param localName to look for
 * @returns value of attribute with the given uri and local name or NULL if not
 *  found
 */
static jstring ExpatAttributes_getValue(JNIEnv* env, jobject clazz,
        jlong attributePointer, jstring uri, jstring localName) {
    jint index = ExpatAttributes_getIndex(env, clazz, attributePointer, uri, localName);
    return index == -1 ? NULL
            : ExpatAttributes_getValueByIndex(env, clazz, attributePointer, index);
}

/**
 * Clones an array of strings. Uses one contiguous block of memory so as to
 * maximize performance.
 *
 * @param address char** to clone
 * @param count number of attributes
 */
static jlong ExpatParser_cloneAttributes(JNIEnv* env, jobject, jlong address, jint count) {
    const char** source = reinterpret_cast<const char**>(static_cast<uintptr_t>(address));
    count *= 2;

    // Figure out how big the buffer needs to be.
    int arraySize = (count + 1) * sizeof(char*);
    int totalSize = arraySize;
    int stringLengths[count];
    for (int i = 0; i < count; i++) {
        int length = strlen(source[i]);
        stringLengths[i] = length;
        totalSize += length + 1;
    }

    char* buffer = new char[totalSize];
    if (buffer == NULL) {
        jniThrowOutOfMemoryError(env, NULL);
        return 0;
    }

    // Array is at the beginning of the buffer.
    char** clonedArray = reinterpret_cast<char**>(buffer);
    clonedArray[count] = NULL; // null terminate

    // String data follows immediately after.
    char* destinationString = buffer + arraySize;
    for (int i = 0; i < count; i++) {
        const char* sourceString = source[i];
        int stringLength = stringLengths[i];
        memcpy(destinationString, sourceString, stringLength + 1);
        clonedArray[i] = destinationString;
        destinationString += stringLength + 1;
    }

    return reinterpret_cast<uintptr_t>(buffer);
}

/**
 * Frees cloned attributes.
 */
static void ExpatAttributes_freeAttributes(JNIEnv*, jobject, jlong pointer) {
    delete[] reinterpret_cast<char*>(static_cast<uintptr_t>(pointer));
}

/**
 * Called when we initialize our Java parser class.
 *
 * @param clazz Java ExpatParser class
 */
static void ExpatParser_staticInitialize(JNIEnv* env, jobject classObject, jstring empty) {
    jclass clazz = reinterpret_cast<jclass>(classObject);
    startElementMethod = env->GetMethodID(clazz, "startElement",
        "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JI)V");
    if (startElementMethod == NULL) return;

    endElementMethod = env->GetMethodID(clazz, "endElement",
        "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
    if (endElementMethod == NULL) return;

    textMethod = env->GetMethodID(clazz, "text", "([CI)V");
    if (textMethod == NULL) return;

    commentMethod = env->GetMethodID(clazz, "comment", "([CI)V");
    if (commentMethod == NULL) return;

    startCdataMethod = env->GetMethodID(clazz, "startCdata", "()V");
    if (startCdataMethod == NULL) return;

    endCdataMethod = env->GetMethodID(clazz, "endCdata", "()V");
    if (endCdataMethod == NULL) return;

    startDtdMethod = env->GetMethodID(clazz, "startDtd",
        "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
    if (startDtdMethod == NULL) return;

    endDtdMethod = env->GetMethodID(clazz, "endDtd", "()V");
    if (endDtdMethod == NULL) return;

    startNamespaceMethod = env->GetMethodID(clazz, "startNamespace",
        "(Ljava/lang/String;Ljava/lang/String;)V");
    if (startNamespaceMethod == NULL) return;

    endNamespaceMethod = env->GetMethodID(clazz, "endNamespace",
        "(Ljava/lang/String;)V");
    if (endNamespaceMethod == NULL) return;

    processingInstructionMethod = env->GetMethodID(clazz,
        "processingInstruction", "(Ljava/lang/String;Ljava/lang/String;)V");
    if (processingInstructionMethod == NULL) return;

    handleExternalEntityMethod = env->GetMethodID(clazz,
        "handleExternalEntity",
        "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
    if (handleExternalEntityMethod == NULL) return;

    notationDeclMethod = env->GetMethodID(clazz, "notationDecl",
            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
    if (notationDeclMethod == NULL) return;

    unparsedEntityDeclMethod = env->GetMethodID(clazz, "unparsedEntityDecl",
            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
    if (unparsedEntityDeclMethod == NULL) return;

    internMethod = env->GetMethodID(JniConstants::stringClass, "intern", "()Ljava/lang/String;");
    if (internMethod == NULL) return;

    // Reference to "".
    emptyString = reinterpret_cast<jstring>(env->NewGlobalRef(empty));
}

static JNINativeMethod parserMethods[] = {
    NATIVE_METHOD(ExpatParser, appendString, "(JLjava/lang/String;Z)V"),
    NATIVE_METHOD(ExpatParser, appendBytes, "(J[BII)V"),
    NATIVE_METHOD(ExpatParser, appendChars, "(J[CII)V"),
    NATIVE_METHOD(ExpatParser, cloneAttributes, "(JI)J"),
    NATIVE_METHOD(ExpatParser, column, "(J)I"),
    NATIVE_METHOD(ExpatParser, createEntityParser, "(JLjava/lang/String;)J"),
    NATIVE_METHOD(ExpatParser, initialize, "(Ljava/lang/String;Z)J"),
    NATIVE_METHOD(ExpatParser, line, "(J)I"),
    NATIVE_METHOD(ExpatParser, release, "(J)V"),
    NATIVE_METHOD(ExpatParser, releaseParser, "(J)V"),
    NATIVE_METHOD(ExpatParser, staticInitialize, "(Ljava/lang/String;)V"),
};

static JNINativeMethod attributeMethods[] = {
    NATIVE_METHOD(ExpatAttributes, freeAttributes, "(J)V"),
    NATIVE_METHOD(ExpatAttributes, getIndexForQName, "(JLjava/lang/String;)I"),
    NATIVE_METHOD(ExpatAttributes, getIndex, "(JLjava/lang/String;Ljava/lang/String;)I"),
    NATIVE_METHOD(ExpatAttributes, getLocalName, "(JJI)Ljava/lang/String;"),
    NATIVE_METHOD(ExpatAttributes, getQName, "(JJI)Ljava/lang/String;"),
    NATIVE_METHOD(ExpatAttributes, getURI, "(JJI)Ljava/lang/String;"),
    NATIVE_METHOD(ExpatAttributes, getValueByIndex, "(JI)Ljava/lang/String;"),
    NATIVE_METHOD(ExpatAttributes, getValueForQName, "(JLjava/lang/String;)Ljava/lang/String;"),
    NATIVE_METHOD(ExpatAttributes, getValue, "(JLjava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
};
void register_org_apache_harmony_xml_ExpatParser(JNIEnv* env) {
    jniRegisterNativeMethods(env, "org/apache/harmony/xml/ExpatParser", parserMethods, NELEM(parserMethods));
    jniRegisterNativeMethods(env, "org/apache/harmony/xml/ExpatAttributes", attributeMethods, NELEM(attributeMethods));
}
