FileDocCategorySizeDatePackage
WbxmlParser.javaAPI DocAndroid 1.5 API6184Wed May 06 22:42:46 BST 2009com.android.im.imps

WbxmlParser.java

/*
 * Copyright (C) 2007 Esmertec AG.
 * 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 com.android.im.imps;

import java.io.IOException;
import java.io.InputStream;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/*
 * NOT thread-safe. Always use this in one thread.
 */
final class WbxmlParser {
    private static final int BUFFER_SIZE = 1024;

    private ContentHandler mContentHandler;
    private int mNativeParser;
    private AttributesImpl atts;

    public WbxmlParser() {
        atts = new AttributesImpl();
        mNativeParser = nativeCreate("UTF-8");
        if (mNativeParser == 0) {
            throw new OutOfMemoryError();
        }
    }

    @Override
    protected void finalize() {
        if (mNativeParser != 0) {
            nativeRelease(mNativeParser);
        }
    }

    public void setContentHandler(ContentHandler contentHandler) {
        mContentHandler = contentHandler;
    }

    public void reset() {
        if (mNativeParser != 0) {
            nativeReset(mNativeParser);
        }
        atts.names = null;
        atts.values = null;
        mContentHandler = null;
    }

    public void parse(InputSource in) throws ParserException, SAXException, IOException {
        InputStream byteStream = in.getByteStream();
        byte[] buffer = new byte[BUFFER_SIZE];
        int length;
        // FIXME: nativeParse should throw ParserException but the dalvik
        // seems to have problem throwing non-system exceptions from JNI
        // code. Use IAE for now and file a bug report for this.
        try {
            while ((length = byteStream.read(buffer)) != -1) {
                nativeParse(mNativeParser, buffer, length, false);
            }
            nativeParse(mNativeParser, new byte[1], 0, true);
        } catch (IllegalArgumentException e) {
            throw new ParserException(e);
        }
    }

    void startElement(String name, String[] attrNames, String[] attrValues)
            throws SAXException {
        atts.names = attrNames;
        atts.values = attrValues;
        if(mContentHandler != null) {
            mContentHandler.startElement("", name, name, atts);
        }
    }

    void endElement(String name) throws SAXException {
        if(mContentHandler != null) {
            mContentHandler.endElement("", name, name);
        }
    }

    void characters(char[] ch, int length) throws SAXException {
        if(mContentHandler != null) {
            mContentHandler.characters(ch, 0, length);
        }
    }

    static native void nativeStaticInitialize();

    native int nativeCreate(String encoding);

    native void nativeRelease(int nativeParser);

    native void nativeReset(int nativeParser);

    // XXX: nativeParse should throw ParserException but the dalvik seems to
    // have problem throwing non-system exceptions from JNI code. Use IAE
    // for now and file a bug report for this.
    native void nativeParse(int nativeParser, byte[] ch, int length,
            boolean isEnd) throws IllegalArgumentException, SAXException, IOException;

    static {
        try {
            System.loadLibrary("wbxml_jni");
            nativeStaticInitialize();
        } catch (UnsatisfiedLinkError ule) {
            System.err.println("WARNING: Could not load library libwbxml_jni.so");
        }
    }

    static class AttributesImpl implements Attributes {
        String[] names = null;
        String[] values = null;

        public int getIndex(String qName) {
            if(names == null) {
                return -1;
            }
            for (int i = 0; i < names.length; i++) {
                if (names[i].equals(qName)) {
                    return i;
                }
            }
            return -1;
        }

        public int getIndex(String uri, String localName) {
            if(!"".equals(uri)) {
                return -1;
            }
            return getIndex(localName);
        }

        public int getLength() {
            return names == null ? 0 : names.length;
        }

        public String getLocalName(int index) {
            if(index < 0 || index >= getLength()) {
                return null;
            }
            return names[index];
        }

        public String getQName(int index) {
            if(index < 0 || index >= getLength()) {
                return null;
            }
            return names[index];
        }

        public String getType(int index) {
            if(index < 0 || index >= getLength()) {
                return null;
            }
            return "CDATA";
        }

        public String getType(String qName) {
            return getIndex(qName) == -1 ? null : "CDATA";
        }

        public String getType(String uri, String localName) {
            return getIndex(uri, localName) == -1 ? null : "CDATA";
        }

        public String getURI(int index) {
            if(index < 0 || index >= getLength()) {
                return null;
            }
            return "";
        }

        public String getValue(int index) {
            if(index < 0 || index >= getLength()) {
                return null;
            }
            return values[index];
        }

        public String getValue(String qName) {
            int index = getIndex(qName);
            return index == -1 ? null : values[index];
        }

        public String getValue(String uri, String localName) {
            int index = getIndex(uri, localName);
            return index == -1 ? null : values[index];
        }
    }
}