1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License. 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.xml; 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 197365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.io.IOException; 207365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.io.InputStream; 217365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.io.Reader; 227365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.net.URI; 237365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.net.URL; 247365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.net.URLConnection; 25a7a70410e26802f3ab480b08a1ab499338cb6f7eJesse Wilsonimport libcore.io.IoUtils; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.Attributes; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.ContentHandler; 28c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughesimport org.xml.sax.DTDHandler; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.EntityResolver; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.InputSource; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.Locator; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.SAXException; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.SAXParseException; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.xml.sax.ext.LexicalHandler; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Adapts SAX API to the Expat native XML parser. Not intended for reuse 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * across documents. 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see org.apache.harmony.xml.ExpatReader 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectclass ExpatParser { 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int BUFFER_SIZE = 8096; // in bytes 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** Pointer to XML_Parser instance. */ 470b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private long pointer; 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean inStartElement = false; 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int attributeCount = -1; 518107b206cd72c51ffaeac1f7fcfdf4ea0728e34cElliott Hughes private long attributePointer = 0; 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final Locator locator = new ExpatLocator(); 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final ExpatReader xmlReader; 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final String publicId; 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final String systemId; 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final String encoding; 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final ExpatAttributes attributes = new CurrentAttributes(); 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final String OUTSIDE_START_ELEMENT 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project = "Attributes can only be used within the scope of startElement()."; 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** We default to UTF-8 when the user doesn't specify an encoding. */ 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final String DEFAULT_ENCODING = "UTF-8"; 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** Encoding used for Java chars, used to parse Readers and Strings */ 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ static final String CHARACTER_ENCODING = "UTF-16"; 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** Timeout for HTTP connections (in ms) */ 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final int TIMEOUT = 20 * 1000; 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new parser with the specified encoding. 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ ExpatParser(String encoding, ExpatReader xmlReader, 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean processNamespaces, String publicId, String systemId) { 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.publicId = publicId; 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.systemId = systemId; 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.xmlReader = xmlReader; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * TODO: Let Expat try to guess the encoding instead of defaulting. 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unfortunately, I don't know how to tell which encoding Expat picked, 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * so I won't know how to encode "<externalEntity>" below. The solution 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * I think is to fix Expat to not require the "<externalEntity>" 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * workaround. 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.encoding = encoding == null ? DEFAULT_ENCODING : encoding; 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.pointer = initialize( 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.encoding, 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project processNamespaces 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ); 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Used by {@link EntityParser}. 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1030b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private ExpatParser(String encoding, ExpatReader xmlReader, long pointer, 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String publicId, String systemId) { 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.encoding = encoding; 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.xmlReader = xmlReader; 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.pointer = pointer; 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.systemId = systemId; 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.publicId = publicId; 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Initializes native resources. 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the pointer to the native parser 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1170b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private native long initialize(String encoding, boolean namespacesEnabled); 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Called at the start of an element. 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param uri namespace URI of element or "" if namespace processing is 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * disabled 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param localName local name of element or "" if namespace processing is 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * disabled 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param qName qualified name or "" if namespace processing is enabled 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param attributePointer pointer to native attribute char*--we keep 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a separate pointer so we can detach it from the parser instance 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param attributeCount number of attributes 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void startElement(String uri, String localName, String qName, 1328107b206cd72c51ffaeac1f7fcfdf4ea0728e34cElliott Hughes long attributePointer, int attributeCount) throws SAXException { 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ContentHandler contentHandler = xmlReader.contentHandler; 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (contentHandler == null) { 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project inStartElement = true; 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.attributePointer = attributePointer; 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.attributeCount = attributeCount; 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentHandler.startElement( 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project uri, localName, qName, this.attributes); 145e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project inStartElement = false; 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.attributeCount = -1; 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.attributePointer = 0; 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void endElement(String uri, String localName, String qName) 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws SAXException { 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ContentHandler contentHandler = xmlReader.contentHandler; 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (contentHandler != null) { 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentHandler.endElement(uri, localName, qName); 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void text(char[] text, int length) throws SAXException { 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ContentHandler contentHandler = xmlReader.contentHandler; 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (contentHandler != null) { 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentHandler.characters(text, 0, length); 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void comment(char[] text, int length) throws SAXException { 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project LexicalHandler lexicalHandler = xmlReader.lexicalHandler; 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lexicalHandler != null) { 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lexicalHandler.comment(text, 0, length); 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void startCdata() throws SAXException { 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project LexicalHandler lexicalHandler = xmlReader.lexicalHandler; 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lexicalHandler != null) { 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lexicalHandler.startCDATA(); 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void endCdata() throws SAXException { 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project LexicalHandler lexicalHandler = xmlReader.lexicalHandler; 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lexicalHandler != null) { 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lexicalHandler.endCDATA(); 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void startNamespace(String prefix, String uri) 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws SAXException { 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ContentHandler contentHandler = xmlReader.contentHandler; 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (contentHandler != null) { 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentHandler.startPrefixMapping(prefix, uri); 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void endNamespace(String prefix) throws SAXException { 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ContentHandler contentHandler = xmlReader.contentHandler; 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (contentHandler != null) { 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentHandler.endPrefixMapping(prefix); 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void startDtd(String name, String publicId, String systemId) 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws SAXException { 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project LexicalHandler lexicalHandler = xmlReader.lexicalHandler; 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lexicalHandler != null) { 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lexicalHandler.startDTD(name, publicId, systemId); 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void endDtd() throws SAXException { 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project LexicalHandler lexicalHandler = xmlReader.lexicalHandler; 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (lexicalHandler != null) { 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project lexicalHandler.endDTD(); 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void processingInstruction(String target, String data) 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws SAXException { 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ContentHandler contentHandler = xmlReader.contentHandler; 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (contentHandler != null) { 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentHandler.processingInstruction(target, data); 223f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 226c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes /*package*/ void notationDecl(String name, String publicId, String systemId) throws SAXException { 227c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes DTDHandler dtdHandler = xmlReader.dtdHandler; 228c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes if (dtdHandler != null) { 229c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes dtdHandler.notationDecl(name, publicId, systemId); 230c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes } 231c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes } 232c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes 233c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes /*package*/ void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) throws SAXException { 234c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes DTDHandler dtdHandler = xmlReader.dtdHandler; 235c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes if (dtdHandler != null) { 236c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes dtdHandler.unparsedEntityDecl(name, publicId, systemId, notationName); 237c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes } 238c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes } 239c9b92b4c79529c5308b2621ac1abe9a5ab039f8dElliott Hughes 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Handles an external entity. 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param context to be passed back to Expat when we parse the entity 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param publicId the publicId of the entity 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param systemId the systemId of the entity 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void handleExternalEntity(String context, String publicId, 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String systemId) throws SAXException, IOException { 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project EntityResolver entityResolver = xmlReader.entityResolver; 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (entityResolver == null) { 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The spec. is terribly under-specified here. It says that if the 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * systemId is a URL, we should try to resolve it, but it doesn't 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specify how to tell whether or not the systemId is a URL let alone 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * how to resolve it. 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Other implementations do various insane things. We try to keep it 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * simple: if the systemId parses as a URI and it's relative, we try to 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * resolve it against the parent document's systemId. If anything goes 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * wrong, we go with the original systemId. If crazybob had designed 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the API, he would have left all resolving to the EntityResolver. 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (this.systemId != null) { 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project URI systemUri = new URI(systemId); 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!systemUri.isAbsolute() && !systemUri.isOpaque()) { 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // It could be relative (or it may not be a URI at all!) 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project URI baseUri = new URI(this.systemId); 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project systemUri = baseUri.resolve(systemUri); 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Replace systemId w/ resolved URI 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project systemId = systemUri.toString(); 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 278a7ef55258ac71153487357b861c7639d627df82fElliott Hughes System.logI("Could not resolve '" + systemId + "' relative to" 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + " '" + this.systemId + "' at " + locator, e); 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InputSource inputSource = entityResolver.resolveEntity( 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project publicId, systemId); 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (inputSource == null) { 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The spec. actually says that we should try to treat systemId 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as a URL and download and parse its contents here, but an 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * entity resolver can easily accomplish the same by returning 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * new InputSource(systemId). 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Downloading external entities by default would result in several 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * unwanted DTD downloads, not to mention pose a security risk 294e810d3b49631329b11440aa5b7a54db181d42ed1Elliott Hughes * when parsing untrusted XML -- see for example 295e810d3b49631329b11440aa5b7a54db181d42ed1Elliott Hughes * http://archive.cert.uni-stuttgart.de/bugtraq/2002/10/msg00421.html -- 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * so we just do nothing instead. This also enables the user to 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * opt out of entity parsing when using 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link org.xml.sax.helpers.DefaultHandler}, something that 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * wouldn't be possible otherwise. 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String encoding = pickEncoding(inputSource); 3050b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice long pointer = createEntityParser(this.pointer, context); 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project EntityParser entityParser = new EntityParser(encoding, xmlReader, 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pointer, inputSource.getPublicId(), 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project inputSource.getSystemId()); 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parseExternalEntity(entityParser, inputSource); 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project releaseParser(pointer); 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Picks an encoding for an external entity. Defaults to UTF-8. 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private String pickEncoding(InputSource inputSource) { 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Reader reader = inputSource.getCharacterStream(); 322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reader != null) { 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return CHARACTER_ENCODING; 324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String encoding = inputSource.getEncoding(); 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return encoding == null ? DEFAULT_ENCODING : encoding; 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses the the external entity provided by the input source. 332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void parseExternalEntity(ExpatParser entityParser, 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InputSource inputSource) throws IOException, SAXException { 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Expat complains if the external entity isn't wrapped with a root 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * element so we add one and ignore it later on during parsing. 338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 339f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Try the character stream. 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Reader reader = inputSource.getCharacterStream(); 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (reader != null) { 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project entityParser.append("<externalEntity>"); 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project entityParser.parseFragment(reader); 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project entityParser.append("</externalEntity>"); 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 348a7a70410e26802f3ab480b08a1ab499338cb6f7eJesse Wilson IoUtils.closeQuietly(reader); 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Try the byte stream. 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InputStream in = inputSource.getByteStream(); 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (in != null) { 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project entityParser.append("<externalEntity>" 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getBytes(entityParser.encoding)); 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project entityParser.parseFragment(in); 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project entityParser.append("</externalEntity>" 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getBytes(entityParser.encoding)); 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 363a7a70410e26802f3ab480b08a1ab499338cb6f7eJesse Wilson IoUtils.closeQuietly(in); 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Make sure we use the user-provided systemId. 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String systemId = inputSource.getSystemId(); 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (systemId == null) { 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // TODO: We could just try our systemId here. 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ParseException("No input specified.", locator); 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Try the system id. 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project in = openUrl(systemId); 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project entityParser.append("<externalEntity>" 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getBytes(entityParser.encoding)); 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project entityParser.parseFragment(in); 381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project entityParser.append("</externalEntity>" 382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .getBytes(entityParser.encoding)); 383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 384a7a70410e26802f3ab480b08a1ab499338cb6f7eJesse Wilson IoUtils.closeQuietly(in); 385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates a native entity parser. 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param parentPointer pointer to parent Expat parser 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param context passed to {@link #handleExternalEntity} 393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return pointer to native parser 394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 3950b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private static native long createEntityParser(long parentPointer, String context); 396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Appends part of an XML document. This parser will parse the given XML to 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the extent possible and dispatch to the appropriate methods. 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param xml a whole or partial snippet of XML 402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws SAXException if an error occurs during parsing 403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void append(String xml) throws SAXException { 405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 406e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes appendString(this.pointer, xml, false); 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ExpatException e) { 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ParseException(e.getMessage(), this.locator); 409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 4120b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private native void appendString(long pointer, String xml, boolean isFinal) 413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws SAXException, ExpatException; 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Appends part of an XML document. This parser will parse the given XML to 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the extent possible and dispatch to the appropriate methods. 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param xml a whole or partial snippet of XML 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param offset into the char[] 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param length of characters to use 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws SAXException if an error occurs during parsing 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void append(char[] xml, int offset, int length) 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws SAXException { 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 427e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes appendChars(this.pointer, xml, offset, length); 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ExpatException e) { 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ParseException(e.getMessage(), this.locator); 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 4330b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private native void appendChars(long pointer, char[] xml, int offset, 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length) throws SAXException, ExpatException; 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Appends part of an XML document. This parser will parse the given XML to 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the extent possible and dispatch to the appropriate methods. 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param xml a whole or partial snippet of XML 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws SAXException if an error occurs during parsing 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void append(byte[] xml) throws SAXException { 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project append(xml, 0, xml.length); 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Appends part of an XML document. This parser will parse the given XML to 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the extent possible and dispatch to the appropriate methods. 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param xml a whole or partial snippet of XML 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param offset into the byte[] 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param length of bytes to use 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws SAXException if an error occurs during parsing 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void append(byte[] xml, int offset, int length) 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws SAXException { 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 459e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes appendBytes(this.pointer, xml, offset, length); 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ExpatException e) { 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ParseException(e.getMessage(), this.locator); 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 4650b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private native void appendBytes(long pointer, byte[] xml, int offset, 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length) throws SAXException, ExpatException; 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses an XML document from the given input stream. 470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void parseDocument(InputStream in) throws IOException, 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SAXException { 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project startDocument(); 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parseFragment(in); 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project finish(); 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project endDocument(); 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses an XML Document from the given reader. 481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void parseDocument(Reader in) throws IOException, SAXException { 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project startDocument(); 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project parseFragment(in); 485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project finish(); 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project endDocument(); 487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses XML from the given Reader. 491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void parseFragment(Reader in) throws IOException, SAXException { 493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char[] buffer = new char[BUFFER_SIZE / 2]; 494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length; 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while ((length = in.read(buffer)) != -1) { 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 497e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes appendChars(this.pointer, buffer, 0, length); 498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ExpatException e) { 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ParseException(e.getMessage(), locator); 500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses XML from the given input stream. 506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void parseFragment(InputStream in) 508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IOException, SAXException { 509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] buffer = new byte[BUFFER_SIZE]; 510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length; 511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while ((length = in.read(buffer)) != -1) { 512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 513e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes appendBytes(this.pointer, buffer, 0, length); 514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ExpatException e) { 515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ParseException(e.getMessage(), this.locator); 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void startDocument() throws SAXException { 521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ContentHandler contentHandler = xmlReader.contentHandler; 522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (contentHandler != null) { 523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentHandler.setDocumentLocator(this.locator); 524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentHandler.startDocument(); 525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void endDocument() throws SAXException { 529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ContentHandler contentHandler; 530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentHandler = xmlReader.contentHandler; 531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (contentHandler != null) { 532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contentHandler.endDocument(); 533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicate that we're finished parsing. 538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws SAXException if the xml is incomplete 540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ void finish() throws SAXException { 542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 543e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes appendString(this.pointer, "", true); 544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (ExpatException e) { 545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new ParseException(e.getMessage(), this.locator); 546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 549e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected synchronized void finalize() throws Throwable { 550e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 551e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom if (this.pointer != 0) { 552e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom release(this.pointer); 553e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom this.pointer = 0; 554e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 555e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 556e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Releases all native objects. 562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 5630b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private native void release(long pointer); 564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Releases native parser only. 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 5680b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private static native void releaseParser(long pointer); 569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Initialize static resources. 572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static native void staticInitialize(String emptyString); 574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project static { 576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project staticInitialize(""); 577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the current line number within the XML file. 581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int line() { 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return line(this.pointer); 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5860b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private static native int line(long pointer); 587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the current column number within the XML file. 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private int column() { 592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return column(this.pointer); 593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5950b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private static native int column(long pointer); 596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Clones the current attributes so they can be used outside of 599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * startElement(). 600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ Attributes cloneAttributes() { 602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!inStartElement) { 603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalStateException(OUTSIDE_START_ELEMENT); 604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (attributeCount == 0) { 607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ClonedAttributes.EMPTY; 608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6100b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice long clonePointer 611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project = cloneAttributes(this.attributePointer, this.attributeCount); 612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new ClonedAttributes(pointer, clonePointer, attributeCount); 613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6150b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private static native long cloneAttributes(long pointer, int attributeCount); 616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Used for cloned attributes. 619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static class ClonedAttributes extends ExpatAttributes { 621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static final Attributes EMPTY = new ClonedAttributes(0, 0, 0); 623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6240b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private final long parserPointer; 6250b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private long pointer; 626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final int length; 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a Java wrapper for native attributes. 630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param parserPointer pointer to the parse, can be 0 if length is 0. 632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param pointer pointer to the attributes array, can be 0 if the 633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * length is 0. 634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param length number of attributes 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6360b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice private ClonedAttributes(long parserPointer, long pointer, int length) { 637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.parserPointer = parserPointer; 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.pointer = pointer; 639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.length = length; 640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 6430b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice public long getParserPointer() { 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this.parserPointer; 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 6480b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice public long getPointer() { 649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return pointer; 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int getLength() { 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return length; 655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 657e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected synchronized void finalize() throws Throwable { 658e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 659e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom if (pointer != 0) { 660e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom freeAttributes(pointer); 661e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom pointer = 0; 662e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 663e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 664e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class ExpatLocator implements Locator { 670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getPublicId() { 672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return publicId; 673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String getSystemId() { 676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return systemId; 677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int getLineNumber() { 680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return line(); 681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int getColumnNumber() { 684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return column(); 685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String toString() { 689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return "Locator[publicId: " + publicId + ", systemId: " + systemId 690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + ", line: " + getLineNumber() 691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + ", column: " + getColumnNumber() + "]"; 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Attributes that are only valid during startElement(). 697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class CurrentAttributes extends ExpatAttributes { 699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 7010b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice public long getParserPointer() { 702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return pointer; 703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 7060b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice public long getPointer() { 707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!inStartElement) { 708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalStateException(OUTSIDE_START_ELEMENT); 709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return attributePointer; 711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int getLength() { 715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!inStartElement) { 716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalStateException(OUTSIDE_START_ELEMENT); 717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return attributeCount; 719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Includes line and column in the message. 724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static class ParseException extends SAXParseException { 726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private ParseException(String message, Locator locator) { 728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(makeMessage(message, locator), locator); 729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static String makeMessage(String message, Locator locator) { 732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return makeMessage(message, locator.getLineNumber(), 733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project locator.getColumnNumber()); 734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static String makeMessage( 737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String message, int line, int column) { 738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return "At line " + line + ", column " 739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + column + ": " + message; 740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 742f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Opens an InputStream for the given URL. 745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /*package*/ static InputStream openUrl(String url) throws IOException { 747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project URLConnection urlConnection = new URL(url).openConnection(); 749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project urlConnection.setConnectTimeout(TIMEOUT); 750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project urlConnection.setReadTimeout(TIMEOUT); 751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project urlConnection.setDoInput(true); 752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project urlConnection.setDoOutput(false); 753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return urlConnection.getInputStream(); 754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project IOException ioe = new IOException("Couldn't open " + url); 756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ioe.initCause(e); 757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw ioe; 758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Parses an external entity. 763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static class EntityParser extends ExpatParser { 765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 766f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private int depth = 0; 767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private EntityParser(String encoding, ExpatReader xmlReader, 7690b00d81d3c9e9a2df4635cd6a55e291cce303658Joel Dice long pointer, String publicId, String systemId) { 770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(encoding, xmlReader, pointer, publicId, systemId); 771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project void startElement(String uri, String localName, String qName, 7758107b206cd72c51ffaeac1f7fcfdf4ea0728e34cElliott Hughes long attributePointer, int attributeCount) throws SAXException { 776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Skip topmost element generated by our workaround in 778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #handleExternalEntity}. 779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (depth++ > 0) { 781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.startElement(uri, localName, qName, attributePointer, 782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project attributeCount); 783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 785f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project void endElement(String uri, String localName, String qName) 788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws SAXException { 789adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (--depth > 0) { 790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super.endElement(uri, localName, qName); 791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @SuppressWarnings("FinalizeDoesntCallSuperFinalize") 796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected synchronized void finalize() throws Throwable { 797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Don't release our native resources. We do so explicitly in 799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #handleExternalEntity} and we don't want to release the 800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * parsing context--our parent is using it. 801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 805