1/* 2 * Copyright (C) 2007 Esmertec AG. 3 * Copyright (C) 2007 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.im.imps; 19 20import java.io.IOException; 21import java.io.InputStream; 22 23import org.xml.sax.Attributes; 24import org.xml.sax.ContentHandler; 25import org.xml.sax.InputSource; 26import org.xml.sax.SAXException; 27 28/* 29 * NOT thread-safe. Always use this in one thread. 30 */ 31final class WbxmlParser { 32 private static final int BUFFER_SIZE = 1024; 33 34 private ContentHandler mContentHandler; 35 private int mNativeParser; 36 private AttributesImpl atts; 37 38 public WbxmlParser() { 39 atts = new AttributesImpl(); 40 mNativeParser = nativeCreate("UTF-8"); 41 if (mNativeParser == 0) { 42 throw new OutOfMemoryError(); 43 } 44 } 45 46 @Override 47 protected void finalize() { 48 if (mNativeParser != 0) { 49 nativeRelease(mNativeParser); 50 } 51 } 52 53 public void setContentHandler(ContentHandler contentHandler) { 54 mContentHandler = contentHandler; 55 } 56 57 public void reset() { 58 if (mNativeParser != 0) { 59 nativeReset(mNativeParser); 60 } 61 atts.names = null; 62 atts.values = null; 63 mContentHandler = null; 64 } 65 66 public void parse(InputSource in) throws ParserException, SAXException, IOException { 67 InputStream byteStream = in.getByteStream(); 68 byte[] buffer = new byte[BUFFER_SIZE]; 69 int length; 70 // FIXME: nativeParse should throw ParserException but the dalvik 71 // seems to have problem throwing non-system exceptions from JNI 72 // code. Use IAE for now and file a bug report for this. 73 try { 74 while ((length = byteStream.read(buffer)) != -1) { 75 nativeParse(mNativeParser, buffer, length, false); 76 } 77 nativeParse(mNativeParser, new byte[1], 0, true); 78 } catch (IllegalArgumentException e) { 79 throw new ParserException(e); 80 } 81 } 82 83 void startElement(String name, String[] attrNames, String[] attrValues) 84 throws SAXException { 85 atts.names = attrNames; 86 atts.values = attrValues; 87 if(mContentHandler != null) { 88 mContentHandler.startElement("", name, name, atts); 89 } 90 } 91 92 void endElement(String name) throws SAXException { 93 if(mContentHandler != null) { 94 mContentHandler.endElement("", name, name); 95 } 96 } 97 98 void characters(char[] ch, int length) throws SAXException { 99 if(mContentHandler != null) { 100 mContentHandler.characters(ch, 0, length); 101 } 102 } 103 104 static native void nativeStaticInitialize(); 105 106 native int nativeCreate(String encoding); 107 108 native void nativeRelease(int nativeParser); 109 110 native void nativeReset(int nativeParser); 111 112 // XXX: nativeParse should throw ParserException but the dalvik seems to 113 // have problem throwing non-system exceptions from JNI code. Use IAE 114 // for now and file a bug report for this. 115 native void nativeParse(int nativeParser, byte[] ch, int length, 116 boolean isEnd) throws IllegalArgumentException, SAXException, IOException; 117 118 static { 119 try { 120 System.loadLibrary("wbxml_jni"); 121 nativeStaticInitialize(); 122 } catch (UnsatisfiedLinkError ule) { 123 System.err.println("WARNING: Could not load library libwbxml_jni.so"); 124 } 125 } 126 127 static class AttributesImpl implements Attributes { 128 String[] names = null; 129 String[] values = null; 130 131 public int getIndex(String qName) { 132 if(names == null) { 133 return -1; 134 } 135 for (int i = 0; i < names.length; i++) { 136 if (names[i].equals(qName)) { 137 return i; 138 } 139 } 140 return -1; 141 } 142 143 public int getIndex(String uri, String localName) { 144 if(!"".equals(uri)) { 145 return -1; 146 } 147 return getIndex(localName); 148 } 149 150 public int getLength() { 151 return names == null ? 0 : names.length; 152 } 153 154 public String getLocalName(int index) { 155 if(index < 0 || index >= getLength()) { 156 return null; 157 } 158 return names[index]; 159 } 160 161 public String getQName(int index) { 162 if(index < 0 || index >= getLength()) { 163 return null; 164 } 165 return names[index]; 166 } 167 168 public String getType(int index) { 169 if(index < 0 || index >= getLength()) { 170 return null; 171 } 172 return "CDATA"; 173 } 174 175 public String getType(String qName) { 176 return getIndex(qName) == -1 ? null : "CDATA"; 177 } 178 179 public String getType(String uri, String localName) { 180 return getIndex(uri, localName) == -1 ? null : "CDATA"; 181 } 182 183 public String getURI(int index) { 184 if(index < 0 || index >= getLength()) { 185 return null; 186 } 187 return ""; 188 } 189 190 public String getValue(int index) { 191 if(index < 0 || index >= getLength()) { 192 return null; 193 } 194 return values[index]; 195 } 196 197 public String getValue(String qName) { 198 int index = getIndex(qName); 199 return index == -1 ? null : values[index]; 200 } 201 202 public String getValue(String uri, String localName) { 203 int index = getIndex(uri, localName); 204 return index == -1 ? null : values[index]; 205 } 206 } 207} 208