package android.content.res; import java.io.IOException; import java.util.ArrayList; import org.xmlpull.v1.XmlPullParserException; import android.content.res.ResourceTypes.ResChunk_header; import android.content.res.ResourceTypes.ResStringPool_ref; import android.content.res.ResourceTypes.ResXMLTree_attrExt; import android.content.res.ResourceTypes.ResXMLTree_attribute; import android.content.res.ResourceTypes.ResXMLTree_cdataExt; import android.content.res.ResourceTypes.ResXMLTree_endElementExt; import android.content.res.ResourceTypes.ResXMLTree_namespaceExt; import android.content.res.ResourceTypes.ResXMLTree_node; import android.content.res.ResourceTypes.Res_value; import android.util.Errors; import android.util.TypedValue; public class ResXMLParser { public ResXMLParser() { } public ResXMLParser(ResXMLTree tree) { init(tree); } public void init(ResXMLTree tree) { mTree = tree; mReader = tree.mReader; mEventCode = BAD_DOCUMENT; } public void restart() { mCurNode = null; mEventCode = mTree.mError == Errors.NO_ERROR ? START_DOCUMENT : BAD_DOCUMENT; } public ResStringPool getStrings() { return mTree.mStrings; } public int getEventType() throws XmlPullParserException { return mEventCode; } public int next() { if (mEventCode == START_DOCUMENT) { mCurNode = mTree.mRootNode; mCurExt = mTree.mRootExt; return (mEventCode = mTree.mRootCode); } else if (mEventCode >= FIRST_CHUNK_CODE) { try { return nextNode(); } catch (IOException e) { e.printStackTrace(); } } return mEventCode; } public int nextNode() throws IOException { if (mEventCode < 0) { return mEventCode; } do { mReader.setPosition(mCurNode.header.pointer.offset + mCurNode.header.size); if (mReader.getPosition() >= mTree.mDataEnd) { mCurNode = null; return (mEventCode = END_DOCUMENT); } ResXMLTree_node next = new ResXMLTree_node(new ResChunk_header( mReader.getData(), mReader.getPosition(), mReader.readInt(2), mReader.readInt(2), mReader.readInt()), mReader.readInt(), new ResStringPool_ref(mReader.readInt())); mCurNode = next; int headerSize = next.header.headerSize; int totalSize = next.header.size; mCurExt = next.header.pointer.offset + headerSize; int minExtSize = 0; int eventCode = next.header.type; switch ((mEventCode = eventCode)) { case ResourceTypes.RES_XML_START_NAMESPACE_TYPE: case ResourceTypes.RES_XML_END_NAMESPACE_TYPE: minExtSize = ResXMLTree_namespaceExt.sizeof(); break; case ResourceTypes.RES_XML_START_ELEMENT_TYPE: minExtSize = ResXMLTree_attrExt.sizeof(); break; case ResourceTypes.RES_XML_END_ELEMENT_TYPE: minExtSize = ResXMLTree_endElementExt.sizeof(); break; case ResourceTypes.RES_XML_CDATA_TYPE: minExtSize = ResXMLTree_cdataExt.sizeof(); break; default: continue; } if ((totalSize - headerSize) < minExtSize) { return (mEventCode = BAD_DOCUMENT); } return eventCode; } while (true); } public int getCommentID() { return mCurNode != null ? mCurNode.comment.index : -1; } public int getLineNumber() { return mCurNode != null ? mCurNode.lineNumber : -1; } public int getTextID() { try { if (mEventCode == TEXT) { mReader.setPosition(mCurExt); ResXMLTree_cdataExt ext = new ResXMLTree_cdataExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new Res_value( mReader.readInt(2), mReader.readByte(), mReader.readByte(), mReader.readInt())); return ext.data.index; } } catch (IOException e) { e.printStackTrace(); } return -1; } /** private final void doNext() throws IOException { if (m_event == END_DOCUMENT) { return; } int event = m_event; resetEventInfo(); while (true) { if (m_decreaseDepth) { m_decreaseDepth = false; m_namespaces.decreaseDepth(); } // Fake END_DOCUMENT event. if (event == END_TAG && m_namespaces.getDepth() == 1 && m_namespaces.getCurrentCount() == 0) { m_event = END_DOCUMENT; break; } int chunkType; if (event == START_DOCUMENT) { // Fake event, see CHUNK_XML_START_TAG handler. chunkType = ResourceTypes.RES_XML_START_ELEMENT_TYPE; } else { chunkType = m_reader.readInt(); } if (chunkType == ResourceTypes.RES_XML_RESOURCE_MAP_TYPE) { int chunkSize = m_reader.readInt(); if (chunkSize < 8 || (chunkSize % 4) != 0) { throw new IOException("Invalid resource ids size (" + chunkSize + ")."); } m_resourceIDs = m_reader.readIntArray(chunkSize / 4 - 2); continue; } if (chunkType < ResourceTypes.RES_XML_FIRST_CHUNK_TYPE || chunkType > ResourceTypes.RES_XML_LAST_CHUNK_TYPE) { throw new IOException("Invalid chunk type (" + chunkType + ")."); } // Fake START_DOCUMENT event. if (chunkType == ResourceTypes.RES_XML_START_ELEMENT_TYPE && event == -1) { m_event = START_DOCUMENT; break; } // Common header. m_reader.skipInt();//chunkSize int lineNumber = m_reader.readInt(); m_reader.skipInt();//0xFFFFFFFF if (chunkType == ResourceTypes.RES_XML_START_NAMESPACE_TYPE || chunkType == ResourceTypes.RES_XML_END_NAMESPACE_TYPE) { if (chunkType == ResourceTypes.RES_XML_START_NAMESPACE_TYPE) { int prefix = m_reader.readInt(); int uri = m_reader.readInt(); m_namespaces.push(prefix, uri); } else { m_reader.skipInt();//prefix m_reader.skipInt();//uri m_namespaces.pop(); } continue; } m_lineNumber = lineNumber; if (chunkType == ResourceTypes.RES_XML_START_ELEMENT_TYPE) { m_namespaceUri = m_reader.readInt(); m_name = m_reader.readInt(); m_reader.skipInt();//flags? int attributeCount = m_reader.readInt(); m_idAttribute = (attributeCount >>> 16) - 1; attributeCount &= 0xFFFF; m_classAttribute = m_reader.readInt(); m_styleAttribute = (m_classAttribute >>> 16) - 1; m_classAttribute = (m_classAttribute & 0xFFFF) - 1; m_attributes = m_reader.readIntArray(attributeCount * ATTRIBUTE_LENGHT); for (int i = ATTRIBUTE_IX_VALUE_TYPE; i < m_attributes.length;) { m_attributes[i] = (m_attributes[i] >>> 24); i += ATTRIBUTE_LENGHT; } m_namespaces.increaseDepth(); m_event = START_TAG; break; } if (chunkType == ResourceTypes.RES_XML_END_ELEMENT_TYPE) { m_namespaceUri = m_reader.readInt(); m_name = m_reader.readInt(); m_event = END_TAG; m_decreaseDepth = true; break; } if (chunkType == ResourceTypes.RES_XML_CDATA_TYPE) { m_name = m_reader.readInt(); m_reader.skipInt();//? m_reader.skipInt();//? m_event = TEXT; break; } } } /**/ public int getElementNamespaceID() { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt ext = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); return ext.ns.index; } if (mEventCode == END_TAG) { mReader.setPosition(mCurExt); ResXMLTree_endElementExt ext = new ResXMLTree_endElementExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt())); return ext.ns.index; } } catch (IOException e) { e.printStackTrace(); } return -1; } public String getElementNamespace() { int id = getElementNamespaceID(); return id >= 0 ? mTree.mStrings.stringAt(id) : null; } public int getElementNameID() { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt ext = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); return ext.name.index; } if (mEventCode == END_TAG) { mReader.setPosition(mCurExt); ResXMLTree_endElementExt ext = new ResXMLTree_endElementExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt())); return ext.name.index; } } catch (IOException e) { e.printStackTrace(); } return -1; } public String getElementName() { int id = getElementNameID(); return id >= 0 ? mTree.mStrings.stringAt(id) : null; } public int getAttributeCount() { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt ext = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); return ext.attributeCount; } } catch (IOException e) { e.printStackTrace(); } return 0; } public int getAttributeNamespaceID(int idx) { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt tag = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); if (idx < tag.attributeCount) { mReader.setPosition(tag.offset + tag.attributeStart + tag.attributeSize * idx); ResXMLTree_attribute attr = new ResXMLTree_attribute( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new Res_value( mReader.readInt(2), mReader.readByte(), mReader.readByte(), mReader.readInt())); return attr.ns.index; } } } catch (IOException e) { e.printStackTrace(); } return -2; // FIXME -2 means what } public String getAttributeNamespace(int idx) { int id = getAttributeNamespaceID(idx); return id >= 0 ? mTree.mStrings.stringAt(id) : null; } public int getAttributeNameID(int idx) { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt tag = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); if (idx < tag.attributeCount) { mReader.setPosition(tag.offset + tag.attributeStart + tag.attributeSize * idx); ResXMLTree_attribute attr = new ResXMLTree_attribute( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new Res_value( mReader.readInt(2), mReader.readByte(), mReader.readByte(), mReader.readInt())); return attr.name.index; } } } catch (IOException e) { e.printStackTrace(); } return -1; // FIXME -1 means what } public String getAttributeName(int idx) { int id = getAttributeNameID(idx); return id >= 0 ? mTree.mStrings.stringAt(id) : null; } public int getAttributeNameResID(int idx) { int id = getAttributeNameID(idx); if (id >= 0 && id < mTree.mNumResIds) return mTree.mResIds[id]; return 0; } public int getAttributeValueStringID(int idx) { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt tag = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); if (idx < tag.attributeCount) { mReader.setPosition(tag.offset + tag.attributeStart + tag.attributeSize * idx); ResXMLTree_attribute attr = new ResXMLTree_attribute( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new Res_value( mReader.readInt(2), mReader.readByte(), mReader.readByte(), mReader.readInt())); return attr.rawValue.index; } } } catch (IOException e) { e.printStackTrace(); } return -1; // FIXME -1 means what } public int getAttributeValue(int idx, Res_value outValue) { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt tag = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); if (idx < tag.attributeCount) { mReader.setPosition(tag.offset + tag.attributeStart + tag.attributeSize * idx); ResXMLTree_attribute attr = new ResXMLTree_attribute( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new Res_value( mReader.readInt(2), mReader.readByte(), mReader.readByte(), mReader.readInt())); outValue.copyFrom(attr.typedValue); return Res_value.sizeof(); } } } catch (IOException e) { e.printStackTrace(); } return Errors.BAD_TYPE; } public int getAttributeDataType(int idx) { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt tag = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); if (idx < tag.attributeCount) { mReader.setPosition(tag.offset + tag.attributeStart + tag.attributeSize * idx); ResXMLTree_attribute attr = new ResXMLTree_attribute( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new Res_value( mReader.readInt(2), mReader.readByte(), mReader.readByte(), mReader.readInt())); return attr.typedValue.dataType; } } } catch (IOException e) { e.printStackTrace(); } return TypedValue.TYPE_NULL; } public int getAttributeData(int idx) { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt tag = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); if (idx < tag.attributeCount) { mReader.setPosition(tag.offset + tag.attributeStart + tag.attributeSize * idx); ResXMLTree_attribute attr = new ResXMLTree_attribute( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), new Res_value( mReader.readInt(2), mReader.readByte(), mReader.readByte(), mReader.readInt())); return attr.typedValue.data; } } } catch (IOException e) { e.printStackTrace(); } return 0; } public int indexOfAttribute(String namespace, String name) { // System.out.println("finding: " + name + " mEventCode = " + mEventCode); if (mEventCode == START_TAG) { int N = getAttributeCount(); // System.out.println("getAttributeCount: " + N); for (int i = 0; i < N; ++i) { String curNs = getAttributeNamespace(i); String curAttr = getAttributeName(i); // if (curNs != null) // System.out.println("attribute[" + i + "]: " + curNs + ":" // + curAttr); // else // System.out.println("attribute[" + i + "]: " + curAttr); if (curAttr.equals(name) == true) { if (namespace == null) { if (curNs == null) return i; } else if (curNs != null) { if (curNs.equals(namespace) == true) return i; } } } } return Errors.NAME_NOT_FOUND; } public int indexOfID() { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt ext = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); int idx = ext.idIndex; if (idx > 0) return (idx - 1); } } catch (IOException e) { e.printStackTrace(); } return Errors.NAME_NOT_FOUND; } public int indexOfClass() { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt ext = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); int idx = ext.classIndex; if (idx > 0) return (idx - 1); } } catch (IOException e) { e.printStackTrace(); } return Errors.NAME_NOT_FOUND; } public int indexOfStyle() { try { if (mEventCode == START_TAG) { mReader.setPosition(mCurExt); ResXMLTree_attrExt ext = new ResXMLTree_attrExt( mReader.getPosition(), new ResStringPool_ref( mReader.readInt()), new ResStringPool_ref( mReader.readInt()), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2), mReader.readInt(2)); int idx = ext.styleIndex; if (idx > 0) return (idx - 1); } } catch (IOException e) { e.printStackTrace(); } return Errors.NAME_NOT_FOUND; } public static final int BAD_DOCUMENT = -1; public static final int START_DOCUMENT = 0; public static final int END_DOCUMENT = 1; public static final int FIRST_CHUNK_CODE = ResourceTypes.RES_XML_FIRST_CHUNK_TYPE; public static final int START_NAMESPACE = ResourceTypes.RES_XML_START_NAMESPACE_TYPE; public static final int END_NAMESPACE = ResourceTypes.RES_XML_END_NAMESPACE_TYPE; public static final int START_TAG = ResourceTypes.RES_XML_START_ELEMENT_TYPE; public static final int END_TAG = ResourceTypes.RES_XML_END_ELEMENT_TYPE; public static final int TEXT = ResourceTypes.RES_XML_CDATA_TYPE; // set to protected in the future public ResXMLTree mTree; public int mEventCode; public ResXMLTree_node mCurNode; public int mCurExt; public IntReader mReader = null; }