diff --git a/axmlprinter/.gitignore b/axmlprinter/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/axmlprinter/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/axmlprinter/build.gradle.kts b/axmlprinter/build.gradle.kts deleted file mode 100644 index 2922bcf..0000000 --- a/axmlprinter/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -val androidSourceCompatibility: JavaVersion by rootProject.extra -val androidTargetCompatibility: JavaVersion by rootProject.extra - -description = "android manifest content parser" - -plugins { - id("java-library") -} - -java { - sourceCompatibility = androidSourceCompatibility - targetCompatibility = androidTargetCompatibility -} diff --git a/axmlprinter/src/main/java/wind/android/content/res/AXmlResourceParser.java b/axmlprinter/src/main/java/wind/android/content/res/AXmlResourceParser.java deleted file mode 100644 index 4bb6445..0000000 --- a/axmlprinter/src/main/java/wind/android/content/res/AXmlResourceParser.java +++ /dev/null @@ -1,932 +0,0 @@ -/* - * Copyright 2008 Android4ME - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package wind.android.content.res; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import wind.v1.XmlPullParserException; - -import wind.android.content.res.ChunkUtil; -import wind.android.content.res.IntReader; -import wind.android.content.res.StringBlock; -import wind.android.content.res.XmlResourceParser; -import wind.android.util.TypedValue; - -/** - * @author Dmitry Skiba - * - * Binary xml files parser. - * - * Parser has only two states: - * (1) Operational state, which parser obtains after first successful call - * to next() and retains until open(), close(), or failed call to next(). - * (2) Closed state, which parser obtains after open(), close(), or failed - * call to next(). In this state methods return invalid values or throw exceptions. - * - * TODO: - * * check all methods in closed state - * - */ -public class AXmlResourceParser implements XmlResourceParser { - - public AXmlResourceParser() { - resetEventInfo(); - } - - public void open(InputStream stream) { - close(); - if (stream!=null) { - m_reader=new wind.android.content.res.IntReader(stream,false); - } - } - - public void close() { - if (!m_operational) { - return; - } - m_operational=false; - m_reader.close(); - m_reader=null; - m_strings=null; - m_resourceIDs=null; - m_namespaces.reset(); - resetEventInfo(); - } - - /////////////////////////////////// iteration - - public int next() throws XmlPullParserException,IOException { - if (m_reader==null) { - throw new XmlPullParserException("Parser is not opened.",this,null); - } - try { - doNext(); - return m_event; - } - catch (IOException e) { - close(); - throw e; - } - } - - public int nextToken() throws XmlPullParserException,IOException { - return next(); - } - - public int nextTag() throws XmlPullParserException,IOException { - int eventType=next(); - if (eventType==TEXT && isWhitespace()) { - eventType=next(); - } - if (eventType!=START_TAG && eventType!=END_TAG) { - throw new XmlPullParserException("Expected start or end tag.",this,null); - } - return eventType; - } - - public String nextText() throws XmlPullParserException,IOException { - if(getEventType()!=START_TAG) { - throw new XmlPullParserException("Parser must be on START_TAG to read next text.",this,null); - } - int eventType=next(); - if (eventType==TEXT) { - String result=getText(); - eventType=next(); - if (eventType!=END_TAG) { - throw new XmlPullParserException("Event TEXT must be immediately followed by END_TAG.",this,null); - } - return result; - } else if (eventType==END_TAG) { - return ""; - } else { - throw new XmlPullParserException("Parser must be on START_TAG or TEXT to read text.",this,null); - } - } - - public void require(int type,String namespace,String name) throws XmlPullParserException,IOException { - if (type!=getEventType() || - (namespace!=null && !namespace.equals(getNamespace())) || - (name!=null && !name.equals(getName()))) - { - throw new XmlPullParserException(TYPES[type]+" is expected.",this,null); - } - } - - public int getDepth() { - return m_namespaces.getDepth()-1; - } - - public int getEventType() throws XmlPullParserException { - return m_event; - } - - public int getLineNumber() { - return m_lineNumber; - } - - public String getName() { - if (m_name==-1 || (m_event!=START_TAG && m_event!=END_TAG)) { - return null; - } - return m_strings.getString(m_name); - } - - public String getText() { - if (m_name==-1 || m_event!=TEXT) { - return null; - } - return m_strings.getString(m_name); - } - - public char[] getTextCharacters(int[] holderForStartAndLength) { - String text=getText(); - if (text==null) { - return null; - } - holderForStartAndLength[0]=0; - holderForStartAndLength[1]=text.length(); - char[] chars=new char[text.length()]; - text.getChars(0,text.length(),chars,0); - return chars; - } - - public String getNamespace() { - return m_strings.getString(m_namespaceUri); - } - - public String getPrefix() { - int prefix=m_namespaces.findPrefix(m_namespaceUri); - return m_strings.getString(prefix); - } - - public String getPositionDescription() { - return "XML line #"+getLineNumber(); - } - - public int getNamespaceCount(int depth) throws XmlPullParserException { - return m_namespaces.getAccumulatedCount(depth); - } - - public String getNamespacePrefix(int pos) throws XmlPullParserException { - int prefix=m_namespaces.getPrefix(pos); - return m_strings.getString(prefix); - } - - public String getNamespaceUri(int pos) throws XmlPullParserException { - int uri=m_namespaces.getUri(pos); - return m_strings.getString(uri); - } - - /////////////////////////////////// attributes - - public String getClassAttribute() { - if (m_classAttribute==-1) { - return null; - } - int offset=getAttributeOffset(m_classAttribute); - int value=m_attributes[offset+ATTRIBUTE_IX_VALUE_STRING]; - return m_strings.getString(value); - } - - public String getIdAttribute() { - if (m_idAttribute==-1) { - return null; - } - int offset=getAttributeOffset(m_idAttribute); - int value=m_attributes[offset+ATTRIBUTE_IX_VALUE_STRING]; - return m_strings.getString(value); - } - - public int getIdAttributeResourceValue(int defaultValue) { - if (m_idAttribute==-1) { - return defaultValue; - } - int offset=getAttributeOffset(m_idAttribute); - int valueType=m_attributes[offset+ATTRIBUTE_IX_VALUE_TYPE]; - if (valueType!=TypedValue.TYPE_REFERENCE) { - return defaultValue; - } - return m_attributes[offset+ATTRIBUTE_IX_VALUE_DATA]; - } - - public int getStyleAttribute() { - if (m_styleAttribute==-1) { - return 0; - } - int offset=getAttributeOffset(m_styleAttribute); - return m_attributes[offset+ATTRIBUTE_IX_VALUE_DATA]; - } - - public int getAttributeCount() { - if (m_event!=START_TAG) { - return -1; - } - return m_attributes.length/ATTRIBUTE_LENGHT; - } - - public String getAttributeNamespace(int index) { - int offset=getAttributeOffset(index); - int namespace=m_attributes[offset+ATTRIBUTE_IX_NAMESPACE_URI]; - if (namespace==-1) { - return ""; - } - return m_strings.getString(namespace); - } - - public String getAttributePrefix(int index) { - int offset=getAttributeOffset(index); - int uri=m_attributes[offset+ATTRIBUTE_IX_NAMESPACE_URI]; - int prefix=m_namespaces.findPrefix(uri); - if (prefix==-1) { - return ""; - } - return m_strings.getString(prefix); - } - - public String getAttributeName(int index) { - int offset=getAttributeOffset(index); - int name=m_attributes[offset+ATTRIBUTE_IX_NAME]; - if (name==-1) { - return ""; - } - return m_strings.getString(name); - } - - public int getAttributeNameResource(int index) { - int offset=getAttributeOffset(index); - int name=m_attributes[offset+ATTRIBUTE_IX_NAME]; - if (m_resourceIDs==null || - name<0 || name>=m_resourceIDs.length) - { - return 0; - } - return m_resourceIDs[name]; - } - - public int getAttributeValueType(int index) { - int offset=getAttributeOffset(index); - return m_attributes[offset+ATTRIBUTE_IX_VALUE_TYPE]; - } - - public int getAttributeValueData(int index) { - int offset=getAttributeOffset(index); - return m_attributes[offset+ATTRIBUTE_IX_VALUE_DATA]; - } - - public String getAttributeValue(int index) { - int offset=getAttributeOffset(index); - int valueType=m_attributes[offset+ATTRIBUTE_IX_VALUE_TYPE]; - if (valueType==TypedValue.TYPE_STRING) { - int valueString=m_attributes[offset+ATTRIBUTE_IX_VALUE_STRING]; - return m_strings.getString(valueString); - } - int valueData=m_attributes[offset+ATTRIBUTE_IX_VALUE_DATA]; - return "";//TypedValue.coerceToString(valueType,valueData); - } - - public boolean getAttributeBooleanValue(int index,boolean defaultValue) { - return getAttributeIntValue(index,defaultValue?1:0)!=0; - } - - public float getAttributeFloatValue(int index,float defaultValue) { - int offset=getAttributeOffset(index); - int valueType=m_attributes[offset+ATTRIBUTE_IX_VALUE_TYPE]; - if (valueType==TypedValue.TYPE_FLOAT) { - int valueData=m_attributes[offset+ATTRIBUTE_IX_VALUE_DATA]; - return Float.intBitsToFloat(valueData); - } - return defaultValue; - } - - public int getAttributeIntValue(int index,int defaultValue) { - int offset=getAttributeOffset(index); - int valueType=m_attributes[offset+ATTRIBUTE_IX_VALUE_TYPE]; - if (valueType>=TypedValue.TYPE_FIRST_INT && - valueType<=TypedValue.TYPE_LAST_INT) - { - return m_attributes[offset+ATTRIBUTE_IX_VALUE_DATA]; - } - return defaultValue; - } - - public int getAttributeUnsignedIntValue(int index,int defaultValue) { - return getAttributeIntValue(index,defaultValue); - } - - public int getAttributeResourceValue(int index,int defaultValue) { - int offset=getAttributeOffset(index); - int valueType=m_attributes[offset+ATTRIBUTE_IX_VALUE_TYPE]; - if (valueType==TypedValue.TYPE_REFERENCE) { - return m_attributes[offset+ATTRIBUTE_IX_VALUE_DATA]; - } - return defaultValue; - } - - public String getAttributeValue(String namespace,String attribute) { - int index=findAttribute(namespace,attribute); - if (index==-1) { - return null; - } - return getAttributeValue(index); - } - - public boolean getAttributeBooleanValue(String namespace,String attribute,boolean defaultValue) { - int index=findAttribute(namespace,attribute); - if (index==-1) { - return defaultValue; - } - return getAttributeBooleanValue(index,defaultValue); - } - - public float getAttributeFloatValue(String namespace,String attribute,float defaultValue) { - int index=findAttribute(namespace,attribute); - if (index==-1) { - return defaultValue; - } - return getAttributeFloatValue(index,defaultValue); - } - - public int getAttributeIntValue(String namespace,String attribute,int defaultValue) { - int index=findAttribute(namespace,attribute); - if (index==-1) { - return defaultValue; - } - return getAttributeIntValue(index,defaultValue); - } - - public int getAttributeUnsignedIntValue(String namespace,String attribute,int defaultValue) { - int index=findAttribute(namespace,attribute); - if (index==-1) { - return defaultValue; - } - return getAttributeUnsignedIntValue(index,defaultValue); - } - - public int getAttributeResourceValue(String namespace,String attribute,int defaultValue) { - int index=findAttribute(namespace,attribute); - if (index==-1) { - return defaultValue; - } - return getAttributeResourceValue(index,defaultValue); - } - - public int getAttributeListValue(int index,String[] options,int defaultValue) { - // TODO implement - return 0; - } - - public int getAttributeListValue(String namespace,String attribute,String[] options,int defaultValue) { - // TODO implement - return 0; - } - - public String getAttributeType(int index) { - return "CDATA"; - } - - public boolean isAttributeDefault(int index) { - return false; - } - - /////////////////////////////////// dummies - - public void setInput(InputStream stream,String inputEncoding) throws XmlPullParserException { - throw new XmlPullParserException(E_NOT_SUPPORTED); - } - public void setInput(Reader reader) throws XmlPullParserException { - throw new XmlPullParserException(E_NOT_SUPPORTED); - } - - public String getInputEncoding() { - return null; - } - - public int getColumnNumber() { - return -1; - } - - public boolean isEmptyElementTag() throws XmlPullParserException { - return false; - } - - public boolean isWhitespace() throws XmlPullParserException { - return false; - } - - public void defineEntityReplacementText(String entityName,String replacementText) throws XmlPullParserException { - throw new XmlPullParserException(E_NOT_SUPPORTED); - } - - public String getNamespace(String prefix) { - throw new RuntimeException(E_NOT_SUPPORTED); - } - - public Object getProperty(String name) { - return null; - } - public void setProperty(String name,Object value) throws XmlPullParserException { - throw new XmlPullParserException(E_NOT_SUPPORTED); - } - - public boolean getFeature(String feature) { - return false; - } - public void setFeature(String name,boolean value) throws XmlPullParserException { - throw new XmlPullParserException(E_NOT_SUPPORTED); - } - - ///////////////////////////////////////////// implementation - - /** - * Namespace stack, holds prefix+uri pairs, as well as - * depth information. - * All information is stored in one int[] array. - * Array consists of depth frames: - * Data=DepthFrame*; - * DepthFrame=Count+[Prefix+Uri]*+Count; - * Count='count of Prefix+Uri pairs'; - * Yes, count is stored twice, to enable bottom-up traversal. - * increaseDepth adds depth frame, decreaseDepth removes it. - * push/pop operations operate only in current depth frame. - * decreaseDepth removes any remaining (not pop'ed) namespace pairs. - * findXXX methods search all depth frames starting - * from the last namespace pair of current depth frame. - * All functions that operate with int, use -1 as 'invalid value'. - * - * !! functions expect 'prefix'+'uri' pairs, not 'uri'+'prefix' !! - * - */ - private static final class NamespaceStack { - public NamespaceStack() { - m_data=new int[32]; - } - - public final void reset() { - m_dataLength=0; - m_count=0; - m_depth=0; - } - - public final int getTotalCount() { - return m_count; - } - - public final int getCurrentCount() { - if (m_dataLength==0) { - return 0; - } - int offset=m_dataLength-1; - return m_data[offset]; - } - - public final int getAccumulatedCount(int depth) { - if (m_dataLength==0 || depth<0) { - return 0; - } - if (depth>m_depth) { - depth=m_depth; - } - int accumulatedCount=0; - int offset=0; - for (;depth!=0;--depth) { - int count=m_data[offset]; - accumulatedCount+=count; - offset+=(2+count*2); - } - return accumulatedCount; - } - - public final void push(int prefix,int uri) { - if (m_depth==0) { - increaseDepth(); - } - ensureDataCapacity(2); - int offset=m_dataLength-1; - int count=m_data[offset]; - m_data[offset-1-count*2]=count+1; - m_data[offset]=prefix; - m_data[offset+1]=uri; - m_data[offset+2]=count+1; - m_dataLength+=2; - m_count+=1; - } - - public final boolean pop(int prefix,int uri) { - if (m_dataLength==0) { - return false; - } - int offset=m_dataLength-1; - int count=m_data[offset]; - for (int i=0,o=offset-2;i!=count;++i,o-=2) { - if (m_data[o]!=prefix || m_data[o+1]!=uri) { - continue; - } - count-=1; - if (i==0) { - m_data[o]=count; - o-=(1+count*2); - m_data[o]=count; - } else { - m_data[offset]=count; - offset-=(1+2+count*2); - m_data[offset]=count; - System.arraycopy( - m_data,o+2, - m_data,o, - m_dataLength-o); - } - m_dataLength-=2; - m_count-=1; - return true; - } - return false; - } - - public final boolean pop() { - if (m_dataLength==0) { - return false; - } - int offset=m_dataLength-1; - int count=m_data[offset]; - if (count==0) { - return false; - } - count-=1; - offset-=2; - m_data[offset]=count; - offset-=(1+count*2); - m_data[offset]=count; - m_dataLength-=2; - m_count-=1; - return true; - } - - public final int getPrefix(int index) { - return get(index,true); - } - - public final int getUri(int index) { - return get(index,false); - } - - public final int findPrefix(int uri) { - return find(uri,false); - } - - public final int findUri(int prefix) { - return find(prefix,true); - } - - public final int getDepth() { - return m_depth; - } - - public final void increaseDepth() { - ensureDataCapacity(2); - int offset=m_dataLength; - m_data[offset]=0; - m_data[offset+1]=0; - m_dataLength+=2; - m_depth+=1; - } - public final void decreaseDepth() { - if (m_dataLength==0) { - return; - } - int offset=m_dataLength-1; - int count=m_data[offset]; - if ((offset-1-count*2)==0) { - return; - } - m_dataLength-=2+count*2; - m_count-=count; - m_depth-=1; - } - - private void ensureDataCapacity(int capacity) { - int available=(m_data.length-m_dataLength); - if (available>capacity) { - return; - } - int newLength=(m_data.length+available)*2; - int[] newData=new int[newLength]; - System.arraycopy(m_data,0,newData,0,m_dataLength); - m_data=newData; - } - - private final int find(int prefixOrUri,boolean prefix) { - if (m_dataLength==0) { - return -1; - } - int offset=m_dataLength-1; - for (int i=m_depth;i!=0;--i) { - int count=m_data[offset]; - offset-=2; - for (;count!=0;--count) { - if (prefix) { - if (m_data[offset]==prefixOrUri) { - return m_data[offset+1]; - } - } else { - if (m_data[offset+1]==prefixOrUri) { - return m_data[offset]; - } - } - offset-=2; - } - } - return -1; - } - - private final int get(int index,boolean prefix) { - if (m_dataLength==0 || index<0) { - return -1; - } - int offset=0; - for (int i=m_depth;i!=0;--i) { - int count=m_data[offset]; - if (index>=count) { - index-=count; - offset+=(2+count*2); - continue; - } - offset+=(1+index*2); - if (!prefix) { - offset+=1; - } - return m_data[offset]; - } - return -1; - } - - private int[] m_data; - private int m_dataLength; - private int m_count; - private int m_depth; - } - - /////////////////////////////////// package-visible - -// final void fetchAttributes(int[] styleableIDs,TypedArray result) { -// result.resetIndices(); -// if (m_attributes==null || m_resourceIDs==null) { -// return; -// } -// boolean needStrings=false; -// for (int i=0,e=styleableIDs.length;i!=e;++i) { -// int id=styleableIDs[i]; -// for (int o=0;o!=m_attributes.length;o+=ATTRIBUTE_LENGHT) { -// int name=m_attributes[o+ATTRIBUTE_IX_NAME]; -// if (name>=m_resourceIDs.length || -// m_resourceIDs[name]!=id) -// { -// continue; -// } -// int valueType=m_attributes[o+ATTRIBUTE_IX_VALUE_TYPE]; -// int valueData; -// int assetCookie; -// if (valueType==TypedValue.TYPE_STRING) { -// valueData=m_attributes[o+ATTRIBUTE_IX_VALUE_STRING]; -// assetCookie=-1; -// needStrings=true; -// } else { -// valueData=m_attributes[o+ATTRIBUTE_IX_VALUE_DATA]; -// assetCookie=0; -// } -// result.addValue(i,valueType,valueData,assetCookie,id,0); -// } -// } -// if (needStrings) { -// result.setStrings(m_strings); -// } -// } - - final wind.android.content.res.StringBlock getStrings() { - return m_strings; - } - - /////////////////////////////////// - - private final int getAttributeOffset(int index) { - if (m_event!=START_TAG) { - throw new IndexOutOfBoundsException("Current event is not START_TAG."); - } - int offset=index*5; - if (offset>=m_attributes.length) { - throw new IndexOutOfBoundsException("Invalid attribute index ("+index+")."); - } - return offset; - } - - private final int findAttribute(String namespace,String attribute) { - if (m_strings==null || attribute==null) { - return -1; - } - int name=m_strings.find(attribute); - if (name==-1) { - return -1; - } - int uri=(namespace!=null)? - m_strings.find(namespace): - -1; - for (int o=0;o!=m_attributes.length;++o) { - if (name==m_attributes[o+ATTRIBUTE_IX_NAME] && - (uri==-1 || uri==m_attributes[o+ATTRIBUTE_IX_NAMESPACE_URI])) - { - return o/ATTRIBUTE_LENGHT; - } - } - return -1; - } - - private final void resetEventInfo() { - m_event=-1; - m_lineNumber=-1; - m_name=-1; - m_namespaceUri=-1; - m_attributes=null; - m_idAttribute=-1; - m_classAttribute=-1; - m_styleAttribute=-1; - } - - private final void doNext() throws IOException { - // Delayed initialization. - if (m_strings==null) { - wind.android.content.res.ChunkUtil.readCheckType(m_reader,CHUNK_AXML_FILE); - /*chunkSize*/m_reader.skipInt(); - m_strings= wind.android.content.res.StringBlock.read(m_reader); - m_namespaces.increaseDepth(); - m_operational=true; - } - - 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=CHUNK_XML_START_TAG; - } else { - chunkType=m_reader.readInt(); - } - - if (chunkType==CHUNK_RESOURCEIDS) { - 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 (chunkTypeCHUNK_XML_LAST) { - throw new IOException("Invalid chunk type ("+chunkType+")."); - } - - // Fake START_DOCUMENT event. - if (chunkType==CHUNK_XML_START_TAG && event==-1) { - m_event=START_DOCUMENT; - break; - } - - // Common header. - /*chunkSize*/m_reader.skipInt(); - int lineNumber=m_reader.readInt(); - /*0xFFFFFFFF*/m_reader.skipInt(); - - if (chunkType==CHUNK_XML_START_NAMESPACE || - chunkType==CHUNK_XML_END_NAMESPACE) - { - if (chunkType==CHUNK_XML_START_NAMESPACE) { - int prefix=m_reader.readInt(); - int uri=m_reader.readInt(); - m_namespaces.push(prefix,uri); - } else { - /*prefix*/m_reader.skipInt(); - /*uri*/m_reader.skipInt(); - m_namespaces.pop(); - } - continue; - } - - m_lineNumber=lineNumber; - - if (chunkType==CHUNK_XML_START_TAG) { - m_namespaceUri=m_reader.readInt(); - m_name=m_reader.readInt(); - /*flags?*/m_reader.skipInt(); - 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>>24); - i+=ATTRIBUTE_LENGHT; - } - m_namespaces.increaseDepth(); - m_event=START_TAG; - break; - } - - if (chunkType==CHUNK_XML_END_TAG) { - m_namespaceUri=m_reader.readInt(); - m_name=m_reader.readInt(); - m_event=END_TAG; - m_decreaseDepth=true; - break; - } - - if (chunkType==CHUNK_XML_TEXT) { - m_name=m_reader.readInt(); - /*?*/m_reader.skipInt(); - /*?*/m_reader.skipInt(); - m_event=TEXT; - break; - } - } - } - - /////////////////////////////////// data - - /* - * All values are essentially indices, e.g. m_name is - * an index of name in m_strings. - */ - - private IntReader m_reader; - private boolean m_operational=false; - - private StringBlock m_strings; - private int[] m_resourceIDs; - private NamespaceStack m_namespaces=new NamespaceStack(); - - private boolean m_decreaseDepth; - - private int m_event; - private int m_lineNumber; - private int m_name; - private int m_namespaceUri; - private int[] m_attributes; - private int m_idAttribute; - private int m_classAttribute; - private int m_styleAttribute; - - private static final String - E_NOT_SUPPORTED ="Method is not supported."; - - private static final int - ATTRIBUTE_IX_NAMESPACE_URI =0, - ATTRIBUTE_IX_NAME =1, - ATTRIBUTE_IX_VALUE_STRING =2, - ATTRIBUTE_IX_VALUE_TYPE =3, - ATTRIBUTE_IX_VALUE_DATA =4, - ATTRIBUTE_LENGHT =5; - - private static final int - CHUNK_AXML_FILE =0x00080003, - CHUNK_RESOURCEIDS =0x00080180, - CHUNK_XML_FIRST =0x00100100, - CHUNK_XML_START_NAMESPACE =0x00100100, - CHUNK_XML_END_NAMESPACE =0x00100101, - CHUNK_XML_START_TAG =0x00100102, - CHUNK_XML_END_TAG =0x00100103, - CHUNK_XML_TEXT =0x00100104, - CHUNK_XML_LAST =0x00100104; -} diff --git a/axmlprinter/src/main/java/wind/android/content/res/ChunkUtil.java b/axmlprinter/src/main/java/wind/android/content/res/ChunkUtil.java deleted file mode 100644 index efebe71..0000000 --- a/axmlprinter/src/main/java/wind/android/content/res/ChunkUtil.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2008 Android4ME - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package wind.android.content.res; - -import wind.android.content.res.IntReader; - -import java.io.IOException; - -/** - * @author Dmitry Skiba - * - */ -class ChunkUtil { - - public static final void readCheckType(IntReader reader, int expectedType) throws IOException { - int type=reader.readInt(); - if (type!=expectedType) { - throw new IOException( - "Expected chunk of type 0x"+Integer.toHexString(expectedType)+ - ", read 0x"+Integer.toHexString(type)+"."); - } - } -} diff --git a/axmlprinter/src/main/java/wind/android/content/res/IntReader.java b/axmlprinter/src/main/java/wind/android/content/res/IntReader.java deleted file mode 100644 index fc0cd27..0000000 --- a/axmlprinter/src/main/java/wind/android/content/res/IntReader.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2008 Android4ME - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package wind.android.content.res; - -import java.io.DataInputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author Dmitry Skiba - * - * Simple helper class that allows reading of integers. - * - * TODO: - * * implement buffering - * - */ -public final class IntReader { - - public IntReader() { - } - public IntReader(InputStream stream,boolean bigEndian) { - reset(stream,bigEndian); - } - - public final void reset(InputStream stream,boolean bigEndian) { - m_stream=stream; - m_bigEndian=bigEndian; - m_position=0; - } - - public final void close() { - if (m_stream==null) { - return; - } - try { - m_stream.close(); - } - catch (IOException e) { - } - reset(null,false); - } - - public final InputStream getStream() { - return m_stream; - } - - public final boolean isBigEndian() { - return m_bigEndian; - } - public final void setBigEndian(boolean bigEndian) { - m_bigEndian=bigEndian; - } - - public final int readByte() throws IOException { - return readInt(1); - } - public final int readShort() throws IOException { - return readInt(2); - } - public final int readInt() throws IOException { - return readInt(4); - } - public final void readFully(byte[] b) throws IOException { - new DataInputStream(m_stream).readFully(b); - } - public final int readInt(int length) throws IOException { - if (length<0 || length>4) { - throw new IllegalArgumentException(); - } - int result=0; - if (m_bigEndian) { - for (int i=(length-1)*8;i>=0;i-=8) { - int b=m_stream.read(); - if (b==-1) { - throw new EOFException(); - } - m_position+=1; - result|=(b<0;length-=1) { - array[offset++]=readInt(); - } - } - - public final byte[] readByteArray(int length) throws IOException { - byte[] array=new byte[length]; - int read=m_stream.read(array); - m_position+=read; - if (read!=length) { - throw new EOFException(); - } - return array; - } - - public final void skip(int bytes) throws IOException { - if (bytes<=0) { - return; - } - long skipped=m_stream.skip(bytes); - m_position+=skipped; - if (skipped!=bytes) { - throw new EOFException(); - } - } - - public final void skipInt() throws IOException { - skip(4); - } - - public final int available() throws IOException { - return m_stream.available(); - } - - public final int getPosition() { - return m_position; - } - - /////////////////////////////////// data - - private InputStream m_stream; - private boolean m_bigEndian; - private int m_position; -} diff --git a/axmlprinter/src/main/java/wind/android/content/res/StringBlock.java b/axmlprinter/src/main/java/wind/android/content/res/StringBlock.java deleted file mode 100644 index 4138ce3..0000000 --- a/axmlprinter/src/main/java/wind/android/content/res/StringBlock.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2008 Android4ME - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package wind.android.content.res; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; - -/** - * @author Dmitry Skiba - * - * Block of strings, used in binary xml and arsc. - * - * TODO: - * - implement get() - * - */ -public class StringBlock { - - private int[] m_stringOffsets; - private byte[] m_strings; - private int[] m_styleOffsets; - private int[] m_styles; - private boolean m_isUTF8; - private static final int CHUNK_TYPE = 0x001C0001; - private static final int UTF8_FLAG = 0x00000100; - - private final CharsetDecoder UTF8_DECODER = Charset.forName("UTF-8").newDecoder(); - private final CharsetDecoder UTF16LE_DECODER = Charset.forName("UTF-16LE").newDecoder(); - - /** - * Reads whole (including chunk type) string block from stream. - * Stream must be at the chunk type. - */ - public static StringBlock read(IntReader reader) throws IOException { - ChunkUtil.readCheckType(reader, CHUNK_TYPE); - int chunkSize = reader.readInt(); - int stringCount = reader.readInt(); - int styleOffsetCount = reader.readInt(); - int flags = reader.readInt(); - int stringsOffset = reader.readInt(); - int stylesOffset = reader.readInt(); - - StringBlock block = new StringBlock(); - block.m_isUTF8 = (flags & UTF8_FLAG) != 0; - block.m_stringOffsets = reader.readIntArray(stringCount); - if (styleOffsetCount != 0) { - block.m_styleOffsets = reader.readIntArray(styleOffsetCount); - } - - int size = ((stylesOffset == 0) ? chunkSize : stylesOffset) - stringsOffset; - block.m_strings = new byte[size]; - reader.readFully(block.m_strings); - - if (stylesOffset != 0) { - size = (chunkSize - stylesOffset); - block.m_styles = reader.readIntArray(size / 4); - - int remaining = size % 4; - if (remaining >= 1) { - while (remaining-- > 0) { - reader.readByte(); - } - } - - } - - return block; - } - - /** - * Returns number of strings in block. - */ - public int getCount() { - return m_stringOffsets != null ? - m_stringOffsets.length : - 0; - } - - - public String getString(int index) { - if (index < 0 || m_stringOffsets == null || index >= m_stringOffsets.length) { - return null; - } - int offset = m_stringOffsets[index]; - int length; - if (m_isUTF8) { - int[] val = getUtf8(m_strings, offset); - offset = val[0]; - length = val[1]; - } else { - int[] val = getUtf16(m_strings, offset); - offset += val[0]; - length = val[1]; - } - return decodeString(offset, length); - } - - private String decodeString(int offset, int length) { - try { - return (m_isUTF8 ? UTF8_DECODER : UTF16LE_DECODER).decode( - ByteBuffer.wrap(m_strings, offset, length)).toString(); - } catch (CharacterCodingException e) { - return null; - } - } - - private static final int getShort(byte[] array, int offset) { - return (array[offset + 1] & 0xff) << 8 | array[offset] & 0xff; - } - - private static final int[] getUtf8(byte[] array, int offset) { - int val = array[offset]; - int length; - if ((val & 0x80) != 0) { - offset += 2; - } else { - offset += 1; - } - val = array[offset]; - if ((val & 0x80) != 0) { - offset += 2; - } else { - offset += 1; - } - length = 0; - while (array[offset + length] != 0) { - length++; - } - return new int[]{offset, length}; - } - - private static final int[] getUtf16(byte[] array, int offset) { - int val = (array[offset + 1] & 0xff) << 8 | array[offset] & 0xff; - if (val == 0x8000) { - int heigh = (array[offset + 3] & 0xFF) << 8; - int low = (array[offset + 2] & 0xFF); - return new int[]{4, (heigh + low) * 2}; - } - return new int[]{2, val * 2}; - } - - - - - /** - * Not yet implemented. - *

- * Returns string with style information (if any). - */ - public CharSequence get(int index) { - return getString(index); - } - - /** - * Returns string with style tags (html-like). - */ - public String getHTML(int index) { - String raw=getString(index); - if (raw==null) { - return raw; - } - int[] style=getStyle(index); - if (style==null) { - return raw; - } - StringBuilder html=new StringBuilder(raw.length()+32); - int offset=0; - while (true) { - int i=-1; - for (int j=0;j!=style.length;j+=3) { - if (style[j+1]==-1) { - continue; - } - if (i==-1 || style[i+1]>style[j+1]) { - i=j; - } - } - int start=((i!=-1)?style[i+1]:raw.length()); - for (int j=0;j!=style.length;j+=3) { - int end=style[j+2]; - if (end==-1 || end>=start) { - continue; - } - if (offset<=end) { - html.append(raw,offset,end+1); - offset=end+1; - } - style[j+2]=-1; - html.append('<'); - html.append('/'); - html.append(getString(style[j])); - html.append('>'); - } - if (offset'); - style[i+1]=-1; - } - return html.toString(); - } - - /** - * Finds index of the string. - * Returns -1 if the string was not found. - */ - public int find(String string) { - if (string==null) { - return -1; - } - for (int i=0;i!=m_stringOffsets.length;++i) { - int offset=m_stringOffsets[i]; - int length=getShort(m_strings,offset); - if (length!=string.length()) { - continue; - } - int j=0; - for (;j!=length;++j) { - offset+=2; - if (string.charAt(j)!=getShort(m_strings,offset)) { - break; - } - } - if (j==length) { - return i; - } - } - return -1; - } - - ///////////////////////////////////////////// implementation - - private StringBlock() { - } - - /** - * Returns style information - array of int triplets, - * where in each triplet: - * * first int is index of tag name ('b','i', etc.) - * * second int is tag start index in string - * * third int is tag end index in string - */ - private int[] getStyle(int index) { - if (m_styleOffsets==null || m_styles==null || - index>=m_styleOffsets.length) - { - return null; - } - int offset=m_styleOffsets[index]/4; - int style[]; - { - int count=0; - for (int i=offset;i>> 16); - } - } -} diff --git a/axmlprinter/src/main/java/wind/android/content/res/XmlResourceParser.java b/axmlprinter/src/main/java/wind/android/content/res/XmlResourceParser.java deleted file mode 100644 index 3935271..0000000 --- a/axmlprinter/src/main/java/wind/android/content/res/XmlResourceParser.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2008 Android4ME - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package wind.android.content.res; - -import wind.v1.XmlPullParser; -import wind.android.util.AttributeSet; - -/** - * @author Dmitry Skiba - * - */ -public interface XmlResourceParser extends XmlPullParser, AttributeSet { - void close(); -} diff --git a/axmlprinter/src/main/java/wind/android/util/AttributeSet.java b/axmlprinter/src/main/java/wind/android/util/AttributeSet.java deleted file mode 100644 index e9296e3..0000000 --- a/axmlprinter/src/main/java/wind/android/util/AttributeSet.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2008 Android4ME - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package wind.android.util; - -/** - * @author Dmitry Skiba - * - */ -public interface AttributeSet { - int getAttributeCount(); - String getAttributeName(int index); - String getAttributeValue(int index); - String getPositionDescription(); - int getAttributeNameResource(int index); - int getAttributeListValue(int index, String options[], int defaultValue); - boolean getAttributeBooleanValue(int index, boolean defaultValue); - int getAttributeResourceValue(int index, int defaultValue); - int getAttributeIntValue(int index, int defaultValue); - int getAttributeUnsignedIntValue(int index, int defaultValue); - float getAttributeFloatValue(int index, float defaultValue); - String getIdAttribute(); - String getClassAttribute(); - int getIdAttributeResourceValue(int index); - int getStyleAttribute(); - String getAttributeValue(String namespace, String attribute); - int getAttributeListValue(String namespace, String attribute, String options[], int defaultValue); - boolean getAttributeBooleanValue(String namespace, String attribute, boolean defaultValue); - int getAttributeResourceValue(String namespace, String attribute, int defaultValue); - int getAttributeIntValue(String namespace, String attribute, int defaultValue); - int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue); - float getAttributeFloatValue(String namespace, String attribute, float defaultValue); - - //TODO: remove - int getAttributeValueType(int index); - int getAttributeValueData(int index); -} diff --git a/axmlprinter/src/main/java/wind/android/util/TypedValue.java b/axmlprinter/src/main/java/wind/android/util/TypedValue.java deleted file mode 100644 index 657ffa1..0000000 --- a/axmlprinter/src/main/java/wind/android/util/TypedValue.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2008 Android4ME - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package wind.android.util; - -/** - * @author Dmitry Skiba - * - */ -public class TypedValue { - - public int type; - public CharSequence string; - public int data; - public int assetCookie; - public int resourceId; - public int changingConfigurations; - - public static final int - TYPE_NULL =0, - TYPE_REFERENCE =1, - TYPE_ATTRIBUTE =2, - TYPE_STRING =3, - TYPE_FLOAT =4, - TYPE_DIMENSION =5, - TYPE_FRACTION =6, - TYPE_FIRST_INT =16, - TYPE_INT_DEC =16, - TYPE_INT_HEX =17, - TYPE_INT_BOOLEAN =18, - TYPE_FIRST_COLOR_INT =28, - TYPE_INT_COLOR_ARGB8 =28, - TYPE_INT_COLOR_RGB8 =29, - TYPE_INT_COLOR_ARGB4 =30, - TYPE_INT_COLOR_RGB4 =31, - TYPE_LAST_COLOR_INT =31, - TYPE_LAST_INT =31; - - public static final int - COMPLEX_UNIT_PX =0, - COMPLEX_UNIT_DIP =1, - COMPLEX_UNIT_SP =2, - COMPLEX_UNIT_PT =3, - COMPLEX_UNIT_IN =4, - COMPLEX_UNIT_MM =5, - COMPLEX_UNIT_SHIFT =0, - COMPLEX_UNIT_MASK =15, - COMPLEX_UNIT_FRACTION =0, - COMPLEX_UNIT_FRACTION_PARENT=1, - COMPLEX_RADIX_23p0 =0, - COMPLEX_RADIX_16p7 =1, - COMPLEX_RADIX_8p15 =2, - COMPLEX_RADIX_0p23 =3, - COMPLEX_RADIX_SHIFT =4, - COMPLEX_RADIX_MASK =3, - COMPLEX_MANTISSA_SHIFT =8, - COMPLEX_MANTISSA_MASK =0xFFFFFF; - -} diff --git a/axmlprinter/src/main/java/wind/test/AXMLPrinter.java b/axmlprinter/src/main/java/wind/test/AXMLPrinter.java deleted file mode 100644 index cf8c701..0000000 --- a/axmlprinter/src/main/java/wind/test/AXMLPrinter.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2008 Android4ME - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package wind.test; - -import java.io.FileInputStream; -import wind.v1.XmlPullParser; -import wind.android.content.res.AXmlResourceParser; -//import android.util.TypedValue; - -/** - * @author Dmitry Skiba - * - * This is example usage of AXMLParser class. - * - * Prints xml document from Android's binary xml file. - */ -public class AXMLPrinter { - - public static void main(String[] arguments) { - if (arguments.length<1) { - log("Usage: AXMLPrinter "); - return; - } - try { - AXmlResourceParser parser=new AXmlResourceParser(); - parser.open(new FileInputStream(arguments[0])); - StringBuilder indent=new StringBuilder(10); - final String indentStep=" "; - while (true) { - int type=parser.next(); - if (type==XmlPullParser.END_DOCUMENT) { - break; - } - switch (type) { - case XmlPullParser.START_DOCUMENT: - { - log(""); - break; - } - case XmlPullParser.START_TAG: - { - log("%s<%s%s",indent, - getNamespacePrefix(parser.getPrefix()),parser.getName()); - indent.append(indentStep); - - int namespaceCountBefore=parser.getNamespaceCount(parser.getDepth()-1); - int namespaceCount=parser.getNamespaceCount(parser.getDepth()); - for (int i=namespaceCountBefore;i!=namespaceCount;++i) { - log("%sxmlns:%s=\"%s\"", - indent, - parser.getNamespacePrefix(i), - parser.getNamespaceUri(i)); - } - - for (int i=0;i!=parser.getAttributeCount();++i) { - log("%s%s%s=\"%s\"",indent, - getNamespacePrefix(parser.getAttributePrefix(i)), - parser.getAttributeName(i), - getAttributeValue(parser,i)); - } - log("%s>",indent); - break; - } - case XmlPullParser.END_TAG: - { - indent.setLength(indent.length()-indentStep.length()); - log("%s",indent, - getNamespacePrefix(parser.getPrefix()), - parser.getName()); - break; - } - case XmlPullParser.TEXT: - { - log("%s%s",indent,parser.getText()); - break; - } - } - } - } - catch (Exception e) { - e.printStackTrace(); - } - } - - private static String getNamespacePrefix(String prefix) { - if (prefix==null || prefix.length()==0) { - return ""; - } - return prefix+":"; - } - - private static String getAttributeValue(AXmlResourceParser parser,int index) { - int type=parser.getAttributeValueType(index); - int data=parser.getAttributeValueData(index); -// if (type==TypedValue.TYPE_STRING) { -// return parser.getAttributeValue(index); -// } -// if (type==TypedValue.TYPE_ATTRIBUTE) { -// return String.format("?%s%08X",getPackage(data),data); -// } -// if (type==TypedValue.TYPE_REFERENCE) { -// return String.format("@%s%08X",getPackage(data),data); -// } -// if (type==TypedValue.TYPE_FLOAT) { -// return String.valueOf(Float.intBitsToFloat(data)); -// } -// if (type==TypedValue.TYPE_INT_HEX) { -// return String.format("0x%08X",data); -// } -// if (type==TypedValue.TYPE_INT_BOOLEAN) { -// return data!=0?"true":"false"; -// } -// if (type==TypedValue.TYPE_DIMENSION) { -// return Float.toString(complexToFloat(data))+ -// DIMENSION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK]; -// } -// if (type==TypedValue.TYPE_FRACTION) { -// return Float.toString(complexToFloat(data))+ -// FRACTION_UNITS[data & TypedValue.COMPLEX_UNIT_MASK]; -// } -// if (type>=TypedValue.TYPE_FIRST_COLOR_INT && type<=TypedValue.TYPE_LAST_COLOR_INT) { -// return String.format("#%08X",data); -// } -// if (type>=TypedValue.TYPE_FIRST_INT && type<=TypedValue.TYPE_LAST_INT) { -// return String.valueOf(data); -// } - return String.format("<0x%X, type 0x%02X>",data,type); - } - - private static String getPackage(int id) { - if (id>>>24==1) { - return "android:"; - } - return ""; - } - - private static void log(String format,Object...arguments) { - System.out.printf(format,arguments); - System.out.println(); - } - - /////////////////////////////////// ILLEGAL STUFF, DONT LOOK :) - - public static float complexToFloat(int complex) { - return (float)(complex & 0xFFFFFF00)*RADIX_MULTS[(complex>>4) & 3]; - } - - private static final float RADIX_MULTS[]={ - 0.00390625F,3.051758E-005F,1.192093E-007F,4.656613E-010F - }; - private static final String DIMENSION_UNITS[]={ - "px","dip","sp","pt","in","mm","","" - }; - private static final String FRACTION_UNITS[]={ - "%","%p","","","","","","" - }; -} \ No newline at end of file diff --git a/axmlprinter/src/main/java/wind/v1/XmlPullParser.java b/axmlprinter/src/main/java/wind/v1/XmlPullParser.java deleted file mode 100644 index ba47c03..0000000 --- a/axmlprinter/src/main/java/wind/v1/XmlPullParser.java +++ /dev/null @@ -1,1119 +0,0 @@ -/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/ -// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/) - -package wind.v1; - -import wind.v1.XmlPullParserException; -import wind.v1.XmlPullParserFactory; - -import java.io.InputStream; -import java.io.IOException; -import java.io.Reader; - -/** - * XML Pull Parser is an interface that defines parsing functionlity provided - * in XMLPULL V1 API (visit this website to - * learn more about API and its implementations). - * - *

There are following different - * kinds of parser depending on which features are set:

    - *
  • non-validating parser as defined in XML 1.0 spec when - * FEATURE_PROCESS_DOCDECL is set to true - *
  • validating parser as defined in XML 1.0 spec when - * FEATURE_VALIDATION is true (and that implies that FEATURE_PROCESS_DOCDECL is true) - *
  • when FEATURE_PROCESS_DOCDECL is false (this is default and - * if different value is required necessary must be changed before parsing is started) - * then parser behaves like XML 1.0 compliant non-validating parser under condition that - * no DOCDECL is present in XML documents - * (internal entites can still be defined with defineEntityReplacementText()). - * This mode of operation is intened for operation in constrained environments such as J2ME. - *
- * - * - *

There are two key methods: next() and nextToken(). While next() provides - * access to high level parsing events, nextToken() allows access to lower - * level tokens. - * - *

The current event state of the parser - * can be determined by calling the - * getEventType() method. - * Initially, the parser is in the START_DOCUMENT - * state. - * - *

The method next() advances the parser to the - * next event. The int value returned from next determines the current parser - * state and is identical to the value returned from following calls to - * getEventType (). - * - *

Th following event types are seen by next()

- *
START_TAG
An XML start tag was read. - *
TEXT
Text content was read; - * the text content can be retreived using the getText() method. - * (when in validating mode next() will not report ignorable whitespaces, use nextToken() instead) - *
END_TAG
An end tag was read - *
END_DOCUMENT
No more events are available - *
- * - *

after first next() or nextToken() (or any other next*() method) - * is called user application can obtain - * XML version, standalone and encoding from XML declaration - * in following ways:

    - *
  • version: - * getProperty("http://xmlpull.org/v1/doc/properties.html#xmldecl-version") - * returns String ("1.0") or null if XMLDecl was not read or if property is not supported - *
  • standalone: - * getProperty("http://xmlpull.org/v1/doc/features.html#xmldecl-standalone") - * returns Boolean: null if there was no standalone declaration - * or if property is not supported - * otherwise returns Boolean(true) if standalon="yes" and Boolean(false) when standalone="no" - *
  • encoding: obtained from getInputEncoding() - * null if stream had unknown encoding (not set in setInputStream) - * and it was not declared in XMLDecl - *
- * - * A minimal example for using this API may look as follows: - *
- * import java.io.IOException;
- * import java.io.StringReader;
- *
- * import wind.v1.XmlPullParser;
- * import wind.v1.XmlPullParserException.html;
- * import wind.v1.XmlPullParserFactory;
- *
- * public class SimpleXmlPullApp
- * {
- *
- *     public static void main (String args[])
- *         throws XmlPullParserException, IOException
- *     {
- *         XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
- *         factory.setNamespaceAware(true);
- *         XmlPullParser xpp = factory.newPullParser();
- *
- *         xpp.setInput( new StringReader ( "<foo>Hello World!</foo>" ) );
- *         int eventType = xpp.getEventType();
- *         while (eventType != XmlPullParser.END_DOCUMENT) {
- *          if(eventType == XmlPullParser.START_DOCUMENT) {
- *              System.out.println("Start document");
- *          } else if(eventType == XmlPullParser.END_DOCUMENT) {
- *              System.out.println("End document");
- *          } else if(eventType == XmlPullParser.START_TAG) {
- *              System.out.println("Start tag "+xpp.getName());
- *          } else if(eventType == XmlPullParser.END_TAG) {
- *              System.out.println("End tag "+xpp.getName());
- *          } else if(eventType == XmlPullParser.TEXT) {
- *              System.out.println("Text "+xpp.getText());
- *          }
- *          eventType = xpp.next();
- *         }
- *     }
- * }
- * 
- * - *

The above example will generate the following output: - *

- * Start document
- * Start tag foo
- * Text Hello World!
- * End tag foo
- * 
- * - *

For more details on API usage, please refer to the - * quick Introduction available at http://www.xmlpull.org - * - * @see XmlPullParserFactory - * @see #defineEntityReplacementText - * @see #getName - * @see #getNamespace - * @see #getText - * @see #next - * @see #nextToken - * @see #setInput - * @see #FEATURE_PROCESS_DOCDECL - * @see #FEATURE_VALIDATION - * @see #START_DOCUMENT - * @see #START_TAG - * @see #TEXT - * @see #END_TAG - * @see #END_DOCUMENT - * - * @author Stefan Haustein - * @author Aleksander Slominski - */ - -public interface XmlPullParser { - - /** This constant represents the default namespace (empty string "") */ - String NO_NAMESPACE = ""; - - // ---------------------------------------------------------------------------- - // EVENT TYPES as reported by next() - - /** - * Signalize that parser is at the very beginning of the document - * and nothing was read yet. - * This event type can only be observed by calling getEvent() - * before the first call to next(), nextToken, or nextTag()). - * - * @see #next - * @see #nextToken - */ - int START_DOCUMENT = 0; - - /** - * Logical end of the xml document. Returned from getEventType, next() - * and nextToken() - * when the end of the input document has been reached. - *

NOTE: calling again - * next() or nextToken() - * will result in exception being thrown. - * - * @see #next - * @see #nextToken - */ - int END_DOCUMENT = 1; - - /** - * Returned from getEventType(), - * next(), nextToken() when - * a start tag was read. - * The name of start tag is available from getName(), its namespace and prefix are - * available from getNamespace() and getPrefix() - * if namespaces are enabled. - * See getAttribute* methods to retrieve element attributes. - * See getNamespace* methods to retrieve newly declared namespaces. - * - * @see #next - * @see #nextToken - * @see #getName - * @see #getPrefix - * @see #getNamespace - * @see #getAttributeCount - * @see #getDepth - * @see #getNamespaceCount - * @see #getNamespace - * @see #FEATURE_PROCESS_NAMESPACES - */ - int START_TAG = 2; - - /** - * Returned from getEventType(), next(), or - * nextToken() when an end tag was read. - * The name of start tag is available from getName(), its - * namespace and prefix are - * available from getNamespace() and getPrefix(). - * - * @see #next - * @see #nextToken - * @see #getName - * @see #getPrefix - * @see #getNamespace - * @see #FEATURE_PROCESS_NAMESPACES - */ - int END_TAG = 3; - - - /** - * Character data was read and will is available by calling getText(). - *

Please note: next() will - * accumulate multiple - * events into one TEXT event, skipping IGNORABLE_WHITESPACE, - * PROCESSING_INSTRUCTION and COMMENT events, - * In contrast, nextToken() will stop reading - * text when any other event is observed. - * Also, when the state was reached by calling next(), the text value will - * be normalized, whereas getText() will - * return unnormalized content in the case of nextToken(). This allows - * an exact roundtrip without chnanging line ends when examining low - * level events, whereas for high level applications the text is - * normalized apropriately. - * - * @see #next - * @see #nextToken - * @see #getText - */ - int TEXT = 4; - - // ---------------------------------------------------------------------------- - // additional events exposed by lower level nextToken() - - /** - * A CDATA sections was just read; - * this token is available only from calls to nextToken(). - * A call to next() will accumulate various text events into a single event - * of type TEXT. The text contained in the CDATA section is available - * by callling getText(). - * - * @see #nextToken - * @see #getText - */ - int CDSECT = 5; - - /** - * An entity reference was just read; - * this token is available from nextToken() - * only. The entity name is available by calling getName(). If available, - * the replacement text can be obtained by calling getTextt(); otherwise, - * the user is responsibile for resolving the entity reference. - * This event type is never returned from next(); next() will - * accumulate the replacement text and other text - * events to a single TEXT event. - * - * @see #nextToken - * @see #getText - */ - int ENTITY_REF = 6; - - /** - * Ignorable whitespace was just read. - * This token is available only from nextToken()). - * For non-validating - * parsers, this event is only reported by nextToken() when outside - * the root element. - * Validating parsers may be able to detect ignorable whitespace at - * other locations. - * The ignorable whitespace string is available by calling getText() - * - *

NOTE: this is different from calling the - * isWhitespace() method, since text content - * may be whitespace but not ignorable. - * - * Ignorable whitespace is skipped by next() automatically; this event - * type is never returned from next(). - * - * @see #nextToken - * @see #getText - */ - int IGNORABLE_WHITESPACE = 7; - - /** - * An XML processing instruction declaration was just read. This - * event type is available only via nextToken(). - * getText() will return text that is inside the processing instruction. - * Calls to next() will skip processing instructions automatically. - * @see #nextToken - * @see #getText - */ - int PROCESSING_INSTRUCTION = 8; - - /** - * An XML comment was just read. This event type is this token is - * available via nextToken() only; - * calls to next() will skip comments automatically. - * The content of the comment can be accessed using the getText() - * method. - * - * @see #nextToken - * @see #getText - */ - int COMMENT = 9; - - /** - * An XML document type declaration was just read. This token is - * available from nextToken() only. - * The unparsed text inside the doctype is available via - * the getText() method. - * - * @see #nextToken - * @see #getText - */ - int DOCDECL = 10; - - /** - * This array can be used to convert the event type integer constants - * such as START_TAG or TEXT to - * to a string. For example, the value of TYPES[START_TAG] is - * the string "START_TAG". - * - * This array is intended for diagnostic output only. Relying - * on the contents of the array may be dangerous since malicous - * applications may alter the array, although it is final, due - * to limitations of the Java language. - */ - String [] TYPES = { - "START_DOCUMENT", - "END_DOCUMENT", - "START_TAG", - "END_TAG", - "TEXT", - "CDSECT", - "ENTITY_REF", - "IGNORABLE_WHITESPACE", - "PROCESSING_INSTRUCTION", - "COMMENT", - "DOCDECL" - }; - - - // ---------------------------------------------------------------------------- - // namespace related features - - /** - * This feature determines whether the parser processes - * namespaces. As for all features, the default value is false. - *

NOTE: The value can not be changed during - * parsing an must be set before parsing. - * - * @see #getFeature - * @see #setFeature - */ - String FEATURE_PROCESS_NAMESPACES = - "http://xmlpull.org/v1/doc/features.html#process-namespaces"; - - /** - * This feature determines whether namespace attributes are - * exposed via the attribute access methods. Like all features, - * the default value is false. This feature cannot be changed - * during parsing. - * - * @see #getFeature - * @see #setFeature - */ - String FEATURE_REPORT_NAMESPACE_ATTRIBUTES = - "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes"; - - /** - * This feature determines whether the document declaration - * is processed. If set to false, - * the DOCDECL event type is reported by nextToken() - * and ignored by next(). - * - * If this featue is activated, then the document declaration - * must be processed by the parser. - * - *

Please note: If the document type declaration - * was ignored, entity references may cause exceptions - * later in the parsing process. - * The default value of this feature is false. It cannot be changed - * during parsing. - * - * @see #getFeature - * @see #setFeature - */ - String FEATURE_PROCESS_DOCDECL = - "http://xmlpull.org/v1/doc/features.html#process-docdecl"; - - /** - * If this feature is activated, all validation errors as - * defined in the XML 1.0 sepcification are reported. - * This implies that FEATURE_PROCESS_DOCDECL is true and both, the - * internal and external document type declaration will be processed. - *

Please Note: This feature can not be changed - * during parsing. The default value is false. - * - * @see #getFeature - * @see #setFeature - */ - String FEATURE_VALIDATION = - "http://xmlpull.org/v1/doc/features.html#validation"; - - /** - * Use this call to change the general behaviour of the parser, - * such as namespace processing or doctype declaration handling. - * This method must be called before the first call to next or - * nextToken. Otherwise, an exception is thrown. - *

Example: call setFeature(FEATURE_PROCESS_NAMESPACES, true) in order - * to switch on namespace processing. The initial settings correspond - * to the properties requested from the XML Pull Parser factory. - * If none were requested, all feautures are deactivated by default. - * - * @exception XmlPullParserException If the feature is not supported or can not be set - * @exception IllegalArgumentException If string with the feature name is null - */ - void setFeature(String name, - boolean state) throws XmlPullParserException; - - /** - * Returns the current value of the given feature. - *

Please note: unknown features are - * always returned as false. - * - * @param name The name of feature to be retrieved. - * @return The value of the feature. - * @exception IllegalArgumentException if string the feature name is null - */ - - boolean getFeature(String name); - - /** - * Set the value of a property. - * - * The property name is any fully-qualified URI. - * - * @exception XmlPullParserException If the property is not supported or can not be set - * @exception IllegalArgumentException If string with the property name is null - */ - void setProperty(String name, - Object value) throws XmlPullParserException; - - /** - * Look up the value of a property. - * - * The property name is any fully-qualified URI. - *

NOTE: unknown properties are always - * returned as null. - * - * @param name The name of property to be retrieved. - * @return The value of named property. - */ - Object getProperty(String name); - - - /** - * Set the input source for parser to the given reader and - * resets the parser. The event type is set to the initial value - * START_DOCUMENT. - * Setting the reader to null will just stop parsing and - * reset parser state, - * allowing the parser to free internal resources - * such as parsing buffers. - */ - void setInput(Reader in) throws XmlPullParserException; - - - /** - * Sets the input stream the parser is going to process. - * This call resets the parser state and sets the event type - * to the initial value START_DOCUMENT. - * - *

NOTE: If an input encoding string is passed, - * it MUST be used. Otherwise, - * if inputEncoding is null, the parser SHOULD try to determine - * input encoding following XML 1.0 specification (see below). - * If encoding detection is supported then following feature - * http://xmlpull.org/v1/doc/features.html#detect-encoding - * MUST be true amd otherwise it must be false - * - * @param inputStream contains a raw byte input stream of possibly - * unknown encoding (when inputEncoding is null). - * - * @param inputEncoding if not null it MUST be used as encoding for inputStream - */ - void setInput(InputStream inputStream, String inputEncoding) - throws XmlPullParserException; - - /** - * Returns the input encoding if known, null otherwise. - * If setInput(InputStream, inputEncoding) was called with an inputEncoding - * value other than null, this value must be returned - * from this method. Otherwise, if inputEncoding is null and - * the parser suppports the encoding detection feature - * (http://xmlpull.org/v1/doc/features.html#detect-encoding), - * it must return the detected encoding. - * If setInput(Reader) was called, null is returned. - * After first call to next if XML declaration was present this method - * will return encoding declared. - */ - String getInputEncoding(); - - /** - * Set new value for entity replacement text as defined in - * XML 1.0 Section 4.5 - * Construction of Internal Entity Replacement Text. - * If FEATURE_PROCESS_DOCDECL or FEATURE_VALIDATION are set, calling this - * function will result in an exception -- when processing of DOCDECL is - * enabled, there is no need to the entity replacement text manually. - * - *

The motivation for this function is to allow very small - * implementations of XMLPULL that will work in J2ME environments. - * Though these implementations may not be able to process the document type - * declaration, they still can work with known DTDs by using this function. - * - *

Please notes: The given value is used literally as replacement text - * and it corresponds to declaring entity in DTD that has all special characters - * escaped: left angle bracket is replaced with &lt;, ampersnad with &amp; - * and so on. - * - *

Note: The given value is the literal replacement text and must not - * contain any other entity reference (if it contains any entity reference - * there will be no further replacement). - * - *

Note: The list of pre-defined entity names will - * always contain standard XML entities such as - * amp (&amp;), lt (&lt;), gt (&gt;), quot (&quot;), and apos (&apos;). - * Those cannot be redefined by this method! - * - * @see #setInput - * @see #FEATURE_PROCESS_DOCDECL - * @see #FEATURE_VALIDATION - */ - void defineEntityReplacementText(String entityName, - String replacementText) throws XmlPullParserException; - - /** - * Returns the numbers of elements in the namespace stack for the given - * depth. - * If namespaces are not enabled, 0 is returned. - * - *

NOTE: when parser is on END_TAG then it is allowed to call - * this function with getDepth()+1 argument to retrieve position of namespace - * prefixes and URIs that were declared on corresponding START_TAG. - *

NOTE: to retrieve lsit of namespaces declared in current element:

-     *       XmlPullParser pp = ...
-     *       int nsStart = pp.getNamespaceCount(pp.getDepth()-1);
-     *       int nsEnd = pp.getNamespaceCount(pp.getDepth());
-     *       for (int i = nsStart; i < nsEnd; i++) {
-     *          String prefix = pp.getNamespacePrefix(i);
-     *          String ns = pp.getNamespaceUri(i);
-     *           // ...
-     *      }
-     * 
- * - * @see #getNamespacePrefix - * @see #getNamespaceUri - * @see #getNamespace() - * @see #getNamespace(String) - */ - int getNamespaceCount(int depth) throws XmlPullParserException; - - /** - * Returns the namespace prefixe for the given position - * in the namespace stack. - * Default namespace declaration (xmlns='...') will have null as prefix. - * If the given index is out of range, an exception is thrown. - *

Please note: when the parser is on an END_TAG, - * namespace prefixes that were declared - * in the corresponding START_TAG are still accessible - * although they are no longer in scope. - */ - String getNamespacePrefix(int pos) throws XmlPullParserException; - - /** - * Returns the namespace URI for the given position in the - * namespace stack - * If the position is out of range, an exception is thrown. - *

NOTE: when parser is on END_TAG then namespace prefixes that were declared - * in corresponding START_TAG are still accessible even though they are not in scope - */ - String getNamespaceUri(int pos) throws XmlPullParserException; - - /** - * Returns the URI corresponding to the given prefix, - * depending on current state of the parser. - * - *

If the prefix was not declared in the current scope, - * null is returned. The default namespace is included - * in the namespace table and is available via - * getNamespace (null). - * - *

This method is a convenience method for - * - *

-     *  for (int i = getNamespaceCount(getDepth ())-1; i >= 0; i--) {
-     *   if (getNamespacePrefix(i).equals( prefix )) {
-     *     return getNamespaceUri(i);
-     *   }
-     *  }
-     *  return null;
-     * 
- * - *

Please note: parser implementations - * may provide more efifcient lookup, e.g. using a Hashtable. - * The 'xml' prefix is bound to "http://www.w3.org/XML/1998/namespace", as - * defined in the - * Namespaces in XML - * specification. Analogous, the 'xmlns' prefix is resolved to - * http://www.w3.org/2000/xmlns/ - * - * @see #getNamespaceCount - * @see #getNamespacePrefix - * @see #getNamespaceUri - */ - String getNamespace(String prefix); - - - // -------------------------------------------------------------------------- - // miscellaneous reporting methods - - /** - * Returns the current depth of the element. - * Outside the root element, the depth is 0. The - * depth is incremented by 1 when a start tag is reached. - * The depth is decremented AFTER the end tag - * event was observed. - * - *

-     * <!-- outside -->     0
-     * <root>                  1
-     *   sometext                 1
-     *     <foobar>         2
-     *     </foobar>        2
-     * </root>              1
-     * <!-- outside -->     0
-     * 
- */ - int getDepth(); - - /** - * Returns a short text describing the current parser state, including - * the position, a - * description of the current event and the data source if known. - * This method is especially useful to provide meaningful - * error messages and for debugging purposes. - */ - String getPositionDescription(); - - - /** - * Returns the current line number, starting from 1. - * When the parser does not know the current line number - * or can not determine it, -1 is returned (e.g. for WBXML). - * - * @return current line number or -1 if unknown. - */ - int getLineNumber(); - - /** - * Returns the current column number, starting from 0. - * When the parser does not know the current column number - * or can not determine it, -1 is returned (e.g. for WBXML). - * - * @return current column number or -1 if unknown. - */ - int getColumnNumber(); - - - // -------------------------------------------------------------------------- - // TEXT related methods - - /** - * Checks whether the current TEXT event contains only whitespace - * characters. - * For IGNORABLE_WHITESPACE, this is always true. - * For TEXT and CDSECT, false is returned when the current event text - * contains at least one non-white space character. For any other - * event type an exception is thrown. - * - *

Please note: non-validating parsers are not - * able to distinguish whitespace and ignorable whitespace, - * except from whitespace outside the root element. Ignorable - * whitespace is reported as separate event, which is exposed - * via nextToken only. - * - */ - boolean isWhitespace() throws XmlPullParserException; - - /** - * Returns the text content of the current event as String. - * The value returned depends on current event type, - * for example for TEXT event it is element content - * (this is typical case when next() is used). - * - * See description of nextToken() for detailed description of - * possible returned values for different types of events. - * - *

NOTE: in case of ENTITY_REF, this method returns - * the entity replacement text (or null if not available). This is - * the only case where - * getText() and getTextCharacters() return different values. - * - * @see #getEventType - * @see #next - * @see #nextToken - */ - String getText(); - - - /** - * Returns the buffer that contains the text of the current event, - * as well as the start offset and length relevant for the current - * event. See getText(), next() and nextToken() for description of possible returned values. - * - *

Please note: this buffer must not - * be modified and its content MAY change after a call to - * next() or nextToken(). This method will always return the - * same value as getText(), except for ENTITY_REF. In the case - * of ENTITY ref, getText() returns the replacement text and - * this method returns the actual input buffer containing the - * entity name. - * If getText() returns null, this method returns null as well and - * the values returned in the holder array MUST be -1 (both start - * and length). - * - * @see #getText - * @see #next - * @see #nextToken - * - * @param holderForStartAndLength Must hold an 2-element int array - * into which the start offset and length values will be written. - * @return char buffer that contains the text of the current event - * (null if the current event has no text associated). - */ - char[] getTextCharacters(int[] holderForStartAndLength); - - // -------------------------------------------------------------------------- - // START_TAG / END_TAG shared methods - - /** - * Returns the namespace URI of the current element. - * The default namespace is represented - * as empty string. - * If namespaces are not enabled, an empty String ("") is always returned. - * The current event must be START_TAG or END_TAG; otherwise, - * null is returned. - */ - String getNamespace(); - - /** - * For START_TAG or END_TAG events, the (local) name of the current - * element is returned when namespaces are enabled. When namespace - * processing is disabled, the raw name is returned. - * For ENTITY_REF events, the entity name is returned. - * If the current event is not START_TAG, END_TAG, or ENTITY_REF, - * null is returned. - *

Please note: To reconstruct the raw element name - * when namespaces are enabled and the prefix is not null, - * you will need to add the prefix and a colon to localName.. - * - */ - String getName(); - - /** - * Returns the prefix of the current element. - * If the element is in the default namespace (has no prefix), - * null is returned. - * If namespaces are not enabled, or the current event - * is not START_TAG or END_TAG, null is returned. - */ - String getPrefix(); - - /** - * Returns true if the current event is START_TAG and the tag - * is degenerated - * (e.g. <foobar/>). - *

NOTE: if the parser is not on START_TAG, an exception - * will be thrown. - */ - boolean isEmptyElementTag() throws XmlPullParserException; - - // -------------------------------------------------------------------------- - // START_TAG Attributes retrieval methods - - /** - * Returns the number of attributes of the current start tag, or - * -1 if the current event type is not START_TAG - * - * @see #getAttributeNamespace - * @see #getAttributeName - * @see #getAttributePrefix - * @see #getAttributeValue - */ - int getAttributeCount(); - - /** - * Returns the namespace URI of the attribute - * with the given index (starts from 0). - * Returns an empty string ("") if namespaces are not enabled - * or the attribute has no namespace. - * Throws an IndexOutOfBoundsException if the index is out of range - * or the current event type is not START_TAG. - * - *

NOTE: if FEATURE_REPORT_NAMESPACE_ATTRIBUTES is set - * then namespace attributes (xmlns:ns='...') must be reported - * with namespace - * http://www.w3.org/2000/xmlns/ - * (visit this URL for description!). - * The default namespace attribute (xmlns="...") will be reported with empty namespace. - *

NOTE:The xml prefix is bound as defined in - * Namespaces in XML - * specification to "http://www.w3.org/XML/1998/namespace". - * - * @param zero based index of attribute - * @return attribute namespace, - * empty string ("") is returned if namesapces processing is not enabled or - * namespaces processing is enabled but attribute has no namespace (it has no prefix). - */ - String getAttributeNamespace(int index); - - /** - * Returns the local name of the specified attribute - * if namespaces are enabled or just attribute name if namespaces are disabled. - * Throws an IndexOutOfBoundsException if the index is out of range - * or current event type is not START_TAG. - * - * @param zero based index of attribute - * @return attribute name (null is never returned) - */ - String getAttributeName(int index); - - /** - * Returns the prefix of the specified attribute - * Returns null if the element has no prefix. - * If namespaces are disabled it will always return null. - * Throws an IndexOutOfBoundsException if the index is out of range - * or current event type is not START_TAG. - * - * @param zero based index of attribute - * @return attribute prefix or null if namespaces processing is not enabled. - */ - String getAttributePrefix(int index); - - /** - * Returns the type of the specified attribute - * If parser is non-validating it MUST return CDATA. - * - * @param zero based index of attribute - * @return attribute type (null is never returned) - */ - String getAttributeType(int index); - - /** - * Returns if the specified attribute was not in input was declared in XML. - * If parser is non-validating it MUST always return false. - * This information is part of XML infoset: - * - * @param zero based index of attribute - * @return false if attribute was in input - */ - boolean isAttributeDefault(int index); - - /** - * Returns the given attributes value. - * Throws an IndexOutOfBoundsException if the index is out of range - * or current event type is not START_TAG. - * - *

NOTE: attribute value must be normalized - * (including entity replacement text if PROCESS_DOCDECL is false) as described in - * XML 1.0 section - * 3.3.3 Attribute-Value Normalization - * - * @see #defineEntityReplacementText - * - * @param zero based index of attribute - * @return value of attribute (null is never returned) - */ - String getAttributeValue(int index); - - /** - * Returns the attributes value identified by namespace URI and namespace localName. - * If namespaces are disabled namespace must be null. - * If current event type is not START_TAG then IndexOutOfBoundsException will be thrown. - * - *

NOTE: attribute value must be normalized - * (including entity replacement text if PROCESS_DOCDECL is false) as described in - * XML 1.0 section - * 3.3.3 Attribute-Value Normalization - * - * @see #defineEntityReplacementText - * - * @param namespace Namespace of the attribute if namespaces are enabled otherwise must be null - * @param name If namespaces enabled local name of attribute otherwise just attribute name - * @return value of attribute or null if attribute with given name does not exist - */ - String getAttributeValue(String namespace, - String name); - - // -------------------------------------------------------------------------- - // actual parsing methods - - /** - * Returns the type of the current event (START_TAG, END_TAG, TEXT, etc.) - * - * @see #next() - * @see #nextToken() - */ - int getEventType() - throws XmlPullParserException; - - /** - * Get next parsing event - element content wil be coalesced and only one - * TEXT event must be returned for whole element content - * (comments and processing instructions will be ignored and emtity references - * must be expanded or exception mus be thrown if entity reerence can not be exapnded). - * If element content is empty (content is "") then no TEXT event will be reported. - * - *

NOTE: empty element (such as <tag/>) will be reported - * with two separate events: START_TAG, END_TAG - it must be so to preserve - * parsing equivalency of empty element to <tag></tag>. - * (see isEmptyElementTag ()) - * - * @see #isEmptyElementTag - * @see #START_TAG - * @see #TEXT - * @see #END_TAG - * @see #END_DOCUMENT - */ - - int next() - throws XmlPullParserException, IOException; - - - /** - * This method works similarly to next() but will expose - * additional event types (COMMENT, CDSECT, DOCDECL, ENTITY_REF, PROCESSING_INSTRUCTION, or - * IGNORABLE_WHITESPACE) if they are available in input. - * - *

If special feature - * FEATURE_XML_ROUNDTRIP - * (identified by URI: http://xmlpull.org/v1/doc/features.html#xml-roundtrip) - * is enabled it is possible to do XML document round trip ie. reproduce - * exectly on output the XML input using getText(): - * returned content is always unnormalized (exactly as in input). - * Otherwise returned content is end-of-line normalized as described - * XML 1.0 End-of-Line Handling - * and. Also when this feature is enabled exact content of START_TAG, END_TAG, - * DOCDECL and PROCESSING_INSTRUCTION is available. - * - *

Here is the list of tokens that can be returned from nextToken() - * and what getText() and getTextCharacters() returns:

- *
START_DOCUMENT
null - *
END_DOCUMENT
null - *
START_TAG
null unless FEATURE_XML_ROUNDTRIP - * enabled and then returns XML tag, ex: <tag attr='val'> - *
END_TAG
null unless FEATURE_XML_ROUNDTRIP - * id enabled and then returns XML tag, ex: </tag> - *
TEXT
return element content. - *
Note: that element content may be delivered in multiple consecutive TEXT events. - *
IGNORABLE_WHITESPACE
return characters that are determined to be ignorable white - * space. If the FEATURE_XML_ROUNDTRIP is enabled all whitespace content outside root - * element will always reported as IGNORABLE_WHITESPACE otherise rteporting is optional. - *
Note: that element content may be delevered in multiple consecutive IGNORABLE_WHITESPACE events. - *
CDSECT
- * return text inside CDATA - * (ex. 'fo<o' from <!CDATA[fo<o]]>) - *
PROCESSING_INSTRUCTION
- * if FEATURE_XML_ROUNDTRIP is true - * return exact PI content ex: 'pi foo' from <?pi foo?> - * otherwise it may be exact PI content or concatenation of PI target, - * space and data so for example for - * <?target data?> string "target data" may - * be returned if FEATURE_XML_ROUNDTRIP is false. - *
COMMENT
return comment content ex. 'foo bar' from <!--foo bar--> - *
ENTITY_REF
getText() MUST return entity replacement text if PROCESS_DOCDECL is false - * otherwise getText() MAY return null, - * additionally getTextCharacters() MUST return entity name - * (for example 'entity_name' for &entity_name;). - *
NOTE: this is the only place where value returned from getText() and - * getTextCharacters() are different - *
NOTE: it is user responsibility to resolve entity reference - * if PROCESS_DOCDECL is false and there is no entity replacement text set in - * defineEntityReplacementText() method (getText() will be null) - *
NOTE: character entities (ex. &#32;) and standard entities such as - * &amp; &lt; &gt; &quot; &apos; are reported as well - * and are not reported as TEXT tokens but as ENTITY_REF tokens! - * This requirement is added to allow to do roundtrip of XML documents! - *
DOCDECL
- * if FEATURE_XML_ROUNDTRIP is true or PROCESS_DOCDECL is false - * then return what is inside of DOCDECL for example it returns:
-     * " titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd"
-     * [<!ENTITY % active.links "INCLUDE">]"
- *

for input document that contained:

-     * <!DOCTYPE titlepage SYSTEM "http://www.foo.bar/dtds/typo.dtd"
-     * [<!ENTITY % active.links "INCLUDE">]>
- * otherwise if FEATURE_XML_ROUNDTRIP is false and PROCESS_DOCDECL is true - * then what is returned is undefined (it may be even null) - *
- *
- * - *

NOTE: there is no gurantee that there will only one TEXT or - * IGNORABLE_WHITESPACE event from nextToken() as parser may chose to deliver element content in - * multiple tokens (dividing element content into chunks) - * - *

NOTE: whether returned text of token is end-of-line normalized - * is depending on FEATURE_XML_ROUNDTRIP. - * - *

NOTE: XMLDecl (<?xml ...?>) is not reported but its content - * is available through optional properties (see class description above). - * - * @see #next - * @see #START_TAG - * @see #TEXT - * @see #END_TAG - * @see #END_DOCUMENT - * @see #COMMENT - * @see #DOCDECL - * @see #PROCESSING_INSTRUCTION - * @see #ENTITY_REF - * @see #IGNORABLE_WHITESPACE - */ - int nextToken() - throws XmlPullParserException, IOException; - - //----------------------------------------------------------------------------- - // utility methods to mak XML parsing easier ... - - /** - * Test if the current event is of the given type and if the - * namespace and name do match. null will match any namespace - * and any name. If the test is not passed, an exception is - * thrown. The exception text indicates the parser position, - * the expected event and the current event that is not meeting the - * requirement. - * - *

Essentially it does this - *

-     *  if (type != getEventType()
-     *  || (namespace != null &&  !namespace.equals( getNamespace () ) )
-     *  || (name != null &&  !name.equals( getName() ) ) )
-     *     throw new XmlPullParserException( "expected "+ TYPES[ type ]+getPositionDescription());
-     * 
- */ - void require(int type, String namespace, String name) - throws XmlPullParserException, IOException; - - /** - * If current event is START_TAG then if next element is TEXT then element content is returned - * or if next event is END_TAG then empty string is returned, otherwise exception is thrown. - * After calling this function successfully parser will be positioned on END_TAG. - * - *

The motivation for this function is to allow to parse consistently both - * empty elements and elements that has non empty content, for example for input:

    - *
  1. <tag>foo</tag> - *
  2. <tag></tag> (which is equivalent to <tag/> - * both input can be parsed with the same code: - *
    -     *   p.nextTag()
    -     *   p.requireEvent(p.START_TAG, "", "tag");
    -     *   String content = p.nextText();
    -     *   p.requireEvent(p.END_TAG, "", "tag");
    -     * 
    - * This function together with nextTag make it very easy to parse XML that has - * no mixed content. - * - * - *

    Essentially it does this - *

    -     *  if(getEventType() != START_TAG) {
    -     *     throw new XmlPullParserException(
    -     *       "parser must be on START_TAG to read next text", this, null);
    -     *  }
    -     *  int eventType = next();
    -     *  if(eventType == TEXT) {
    -     *     String result = getText();
    -     *     eventType = next();
    -     *     if(eventType != END_TAG) {
    -     *       throw new XmlPullParserException(
    -     *          "event TEXT it must be immediately followed by END_TAG", this, null);
    -     *      }
    -     *      return result;
    -     *  } else if(eventType == END_TAG) {
    -     *     return "";
    -     *  } else {
    -     *     throw new XmlPullParserException(
    -     *       "parser must be on START_TAG or TEXT to read text", this, null);
    -     *  }
    -     * 
    - */ - String nextText() throws XmlPullParserException, IOException; - - /** - * Call next() and return event if it is START_TAG or END_TAG - * otherwise throw an exception. - * It will skip whitespace TEXT before actual tag if any. - * - *

    essentially it does this - *

    -     *   int eventType = next();
    -     *   if(eventType == TEXT &&  isWhitespace()) {   // skip whitespace
    -     *      eventType = next();
    -     *   }
    -     *   if (eventType != START_TAG &&  eventType != END_TAG) {
    -     *      throw new XmlPullParserException("expected start or end tag", this, null);
    -     *   }
    -     *   return eventType;
    -     * 
    - */ - int nextTag() throws XmlPullParserException, IOException; - -} - diff --git a/axmlprinter/src/main/java/wind/v1/XmlPullParserException.java b/axmlprinter/src/main/java/wind/v1/XmlPullParserException.java deleted file mode 100644 index 3523778..0000000 --- a/axmlprinter/src/main/java/wind/v1/XmlPullParserException.java +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/ -// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/) - -package wind.v1; - -import wind.v1.XmlPullParser; - -/** - * This exception is thrown to signal XML Pull Parser related faults. - * - * @author Aleksander Slominski - */ -public class XmlPullParserException extends Exception { - protected Throwable detail; - protected int row = -1; - protected int column = -1; - - /* public XmlPullParserException() { - }*/ - - public XmlPullParserException(String s) { - super(s); - } - - /* - public XmlPullParserException(String s, Throwable thrwble) { - super(s); - this.detail = thrwble; - } - - public XmlPullParserException(String s, int row, int column) { - super(s); - this.row = row; - this.column = column; - } - */ - - public XmlPullParserException(String msg, XmlPullParser parser, Throwable chain) { - super ((msg == null ? "" : msg+" ") - + (parser == null ? "" : "(position:"+parser.getPositionDescription()+") ") - + (chain == null ? "" : "caused by: "+chain)); - - if (parser != null) { - this.row = parser.getLineNumber(); - this.column = parser.getColumnNumber(); - } - this.detail = chain; - } - - public Throwable getDetail() { return detail; } - // public void setDetail(Throwable cause) { this.detail = cause; } - public int getLineNumber() { return row; } - public int getColumnNumber() { return column; } - - /* - public String getMessage() { - if(detail == null) - return super.getMessage(); - else - return super.getMessage() + "; nested exception is: \n\t" - + detail.getMessage(); - } - */ - - //NOTE: code that prints this and detail is difficult in J2ME - public void printStackTrace() { - if (detail == null) { - super.printStackTrace(); - } else { - synchronized(System.err) { - System.err.println(super.getMessage() + "; nested exception is:"); - detail.printStackTrace(); - } - } - } - -} - diff --git a/axmlprinter/src/main/java/wind/v1/XmlPullParserFactory.java b/axmlprinter/src/main/java/wind/v1/XmlPullParserFactory.java deleted file mode 100644 index e1465da..0000000 --- a/axmlprinter/src/main/java/wind/v1/XmlPullParserFactory.java +++ /dev/null @@ -1,360 +0,0 @@ -/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/ -// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/) - -package wind.v1; - -import wind.v1.XmlPullParser; -import wind.v1.XmlPullParserException; -import wind.v1.XmlSerializer; - -import java.io.InputStream; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -/** - * This class is used to create implementations of XML Pull Parser defined in XMPULL V1 API. - * The name of actual factory class will be determined based on several parameters. - * It works similar to JAXP but tailored to work in J2ME environments - * (no access to system properties or file system) so name of parser class factory to use - * and its class used for loading (no class loader - on J2ME no access to context class loaders) - * must be passed explicitly. If no name of parser factory was passed (or is null) - * it will try to find name by searching in CLASSPATH for - * META-INF/services/wind.v1.XmlPullParserFactory resource that should contain - * a comma separated list of class names of factories or parsers to try (in order from - * left to the right). If none found, it will throw an exception. - * - *
    NOTE:In J2SE or J2EE environments, you may want to use - * newInstance(property, classLoaderCtx) - * where first argument is - * System.getProperty(XmlPullParserFactory.PROPERTY_NAME) - * and second is Thread.getContextClassLoader().getClass() . - * - * @see wind.v1.XmlPullParser - * - * @author Aleksander Slominski - * @author Stefan Haustein - */ - -public class XmlPullParserFactory { - /** used as default class to server as context class in newInstance() */ - final static Class referenceContextClass; - - static { - XmlPullParserFactory f = new XmlPullParserFactory(); - referenceContextClass = f.getClass(); - } - - /** Name of the system or midlet property that should be used for - a system property containing a comma separated list of factory - or parser class names (value: - wind.v1.XmlPullParserFactory). */ - - - public static final String PROPERTY_NAME = - "org.xmlpull.v1.XmlPullParserFactory"; - - private static final String RESOURCE_NAME = - "/META-INF/services/" + PROPERTY_NAME; - - - // public static final String DEFAULT_PROPERTY = - // "wind.xpp3.XmlPullParser,org.kxml2.io.KXmlParser"; - - - protected Vector parserClasses; - protected String classNamesLocation; - - protected Vector serializerClasses; - - - // features are kept there - protected Hashtable features = new Hashtable(); - - - /** - * Protected constructor to be called by factory implementations. - */ - - protected XmlPullParserFactory() { - } - - - - /** - * Set the features to be set when XML Pull Parser is created by this factory. - *

    NOTE: factory features are not used for XML Serializer. - * - * @param name string with URI identifying feature - * @param state if true feature will be set; if false will be ignored - */ - - public void setFeature(String name, - boolean state) throws XmlPullParserException { - - features.put(name, new Boolean(state)); - } - - - /** - * Return the current value of the feature with given name. - *

    NOTE: factory features are not used for XML Serializer. - * - * @param name The name of feature to be retrieved. - * @return The value of named feature. - * Unknown features are always returned as false - */ - - public boolean getFeature (String name) { - Boolean value = (Boolean) features.get(name); - return value != null ? value.booleanValue() : false; - } - - /** - * Specifies that the parser produced by this factory will provide - * support for XML namespaces. - * By default the value of this is set to false. - * - * @param awareness true if the parser produced by this code - * will provide support for XML namespaces; false otherwise. - */ - - public void setNamespaceAware(boolean awareness) { - features.put (wind.v1.XmlPullParser.FEATURE_PROCESS_NAMESPACES, new Boolean (awareness)); - } - - /** - * Indicates whether or not the factory is configured to produce - * parsers which are namespace aware - * (it simply set feature XmlPullParser.FEATURE_PROCESS_NAMESPACES to true or false). - * - * @return true if the factory is configured to produce parsers - * which are namespace aware; false otherwise. - */ - - public boolean isNamespaceAware() { - return getFeature (wind.v1.XmlPullParser.FEATURE_PROCESS_NAMESPACES); - } - - - /** - * Specifies that the parser produced by this factory will be validating - * (it simply set feature XmlPullParser.FEATURE_VALIDATION to true or false). - * - * By default the value of this is set to false. - * - * @param validating - if true the parsers created by this factory must be validating. - */ - - public void setValidating(boolean validating) { - features.put (wind.v1.XmlPullParser.FEATURE_VALIDATION, new Boolean (validating)); - } - - /** - * Indicates whether or not the factory is configured to produce parsers - * which validate the XML content during parse. - * - * @return true if the factory is configured to produce parsers - * which validate the XML content during parse; false otherwise. - */ - - public boolean isValidating() { - return getFeature (wind.v1.XmlPullParser.FEATURE_VALIDATION); - } - - /** - * Creates a new instance of a XML Pull Parser - * using the currently configured factory features. - * - * @return A new instance of a XML Pull Parser. - * @throws XmlPullParserException if a parser cannot be created which satisfies the - * requested configuration. - */ - - public wind.v1.XmlPullParser newPullParser() throws XmlPullParserException { - - if (parserClasses == null) throw new XmlPullParserException - ("Factory initialization was incomplete - has not tried "+classNamesLocation); - - if (parserClasses.size() == 0) throw new XmlPullParserException - ("No valid parser classes found in "+classNamesLocation); - - final StringBuffer issues = new StringBuffer (); - - for (int i = 0; i < parserClasses.size (); i++) { - final Class ppClass = (Class) parserClasses.elementAt (i); - try { - final wind.v1.XmlPullParser pp = (wind.v1.XmlPullParser) ppClass.newInstance(); - // if( ! features.isEmpty() ) { - //Enumeration keys = features.keys(); - // while(keys.hasMoreElements()) { - - for (Enumeration e = features.keys (); e.hasMoreElements ();) { - final String key = (String) e.nextElement(); - final Boolean value = (Boolean) features.get(key); - if(value != null && value.booleanValue()) { - pp.setFeature(key, true); - } - } - return pp; - - } catch(Exception ex) { - issues.append (ppClass.getName () + ": "+ ex.toString ()+"; "); - } - } - - throw new XmlPullParserException ("could not create parser: "+issues); - } - - - /** - * Creates a new instance of a XML Serializer. - * - *

    NOTE: factory features are not used for XML Serializer. - * - * @return A new instance of a XML Serializer. - * @throws XmlPullParserException if a parser cannot be created which satisfies the - * requested configuration. - */ - - public wind.v1.XmlSerializer newSerializer() throws XmlPullParserException { - - if (serializerClasses == null) { - throw new XmlPullParserException - ("Factory initialization incomplete - has not tried "+classNamesLocation); - } - if(serializerClasses.size() == 0) { - throw new XmlPullParserException - ("No valid serializer classes found in "+classNamesLocation); - } - - final StringBuffer issues = new StringBuffer (); - - for (int i = 0; i < serializerClasses.size (); i++) { - final Class ppClass = (Class) serializerClasses.elementAt (i); - try { - final wind.v1.XmlSerializer ser = (wind.v1.XmlSerializer) ppClass.newInstance(); - - // for (Enumeration e = features.keys (); e.hasMoreElements ();) { - // String key = (String) e.nextElement(); - // Boolean value = (Boolean) features.get(key); - // if(value != null && value.booleanValue()) { - // ser.setFeature(key, true); - // } - // } - return ser; - - } catch(Exception ex) { - issues.append (ppClass.getName () + ": "+ ex.toString ()+"; "); - } - } - - throw new XmlPullParserException ("could not create serializer: "+issues); - } - - /** - * Create a new instance of a PullParserFactory that can be used - * to create XML pull parsers (see class description for more - * details). - * - * @return a new instance of a PullParserFactory, as returned by newInstance (null, null); - */ - public static XmlPullParserFactory newInstance () throws XmlPullParserException { - return newInstance(null, null); - } - - public static XmlPullParserFactory newInstance (String classNames, Class context) - throws XmlPullParserException { - - if (context == null) { - //NOTE: make sure context uses the same class loader as API classes - // this is the best we can do without having access to context classloader in J2ME - // if API is in the same classloader as implementation then this will work - context = referenceContextClass; - } - - String classNamesLocation = null; - - if (classNames == null || classNames.length() == 0 || "DEFAULT".equals(classNames)) { - try { - InputStream is = context.getResourceAsStream (RESOURCE_NAME); - - if (is == null) throw new XmlPullParserException - ("resource not found: "+RESOURCE_NAME - +" make sure that parser implementing XmlPull API is available"); - final StringBuffer sb = new StringBuffer(); - - while (true) { - final int ch = is.read(); - if (ch < 0) break; - else if (ch > ' ') - sb.append((char) ch); - } - is.close (); - - classNames = sb.toString (); - } - catch (Exception e) { - throw new XmlPullParserException (null, null, e); - } - classNamesLocation = "resource "+RESOURCE_NAME+" that contained '"+classNames+"'"; - } else { - classNamesLocation = - "parameter classNames to newInstance() that contained '"+classNames+"'"; - } - - XmlPullParserFactory factory = null; - final Vector parserClasses = new Vector (); - final Vector serializerClasses = new Vector (); - int pos = 0; - - while (pos < classNames.length ()) { - int cut = classNames.indexOf (',', pos); - - if (cut == -1) cut = classNames.length (); - final String name = classNames.substring (pos, cut); - - Class candidate = null; - Object instance = null; - - try { - candidate = Class.forName (name); - // necessary because of J2ME .class issue - instance = candidate.newInstance (); - } - catch (Exception e) {} - - if (candidate != null) { - boolean recognized = false; - if (instance instanceof XmlPullParser) { - parserClasses.addElement (candidate); - recognized = true; - } - if (instance instanceof XmlSerializer) { - serializerClasses.addElement (candidate); - recognized = true; - } - if (instance instanceof XmlPullParserFactory) { - if (factory == null) { - factory = (XmlPullParserFactory) instance; - } - recognized = true; - } - if (!recognized) { - throw new XmlPullParserException ("incompatible class: "+name); - } - } - pos = cut + 1; - } - - if (factory == null) { - factory = new XmlPullParserFactory (); - } - factory.parserClasses = parserClasses; - factory.serializerClasses = serializerClasses; - factory.classNamesLocation = classNamesLocation; - return factory; - } -} - - diff --git a/axmlprinter/src/main/java/wind/v1/XmlSerializer.java b/axmlprinter/src/main/java/wind/v1/XmlSerializer.java deleted file mode 100644 index c176123..0000000 --- a/axmlprinter/src/main/java/wind/v1/XmlSerializer.java +++ /dev/null @@ -1,326 +0,0 @@ -package wind.v1; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.Writer; - -/** - * Define an interface to serialziation of XML Infoset. - * This interface abstracts away if serialized XML is XML 1.0 comaptible text or - * other formats of XML 1.0 serializations (such as binary XML for example with WBXML). - * - *

    PLEASE NOTE: This interface will be part of XmlPull 1.2 API. - * It is included as basis for discussion. It may change in any way. - * - *

    Exceptions that may be thrown are: IOException or runtime exception - * (more runtime exceptions can be thrown but are not declared and as such - * have no semantics defined for this interface): - *

      - *
    • IllegalArgumentException - for almost all methods to signal that - * argument is illegal - *
    • IllegalStateException - to signal that call has good arguments but - * is not expected here (violation of contract) and for features/properties - * when requesting setting unimplemented feature/property - * (UnsupportedOperationException would be better but it is not in MIDP) - *
    - * - *

    NOTE: writing CDSECT, ENTITY_REF, IGNORABLE_WHITESPACE, - * PROCESSING_INSTRUCTION, COMMENT, and DOCDECL in some implementations - * may not be supported (for example when serializing to WBXML). - * In such case IllegalStateException will be thrown and it is recommened - * to use an optional feature to signal that implementation is not - * supporting this kind of output. - */ - -public interface XmlSerializer { - - /** - * Set feature identified by name (recommended to be URI for uniqueness). - * Some well known optional features are defined in - * - * http://www.xmlpull.org/v1/doc/features.html. - * - * If feature is not recocgnized or can not be set - * then IllegalStateException MUST be thrown. - * - * @exception IllegalStateException If the feature is not supported or can not be set - */ - void setFeature(String name, - boolean state) - throws IllegalArgumentException, IllegalStateException; - - - /** - * Return the current value of the feature with given name. - *

    NOTE: unknown properties are always returned as null - * - * @param name The name of feature to be retrieved. - * @return The value of named feature. - * @exception IllegalArgumentException if feature string is null - */ - boolean getFeature(String name); - - - /** - * Set the value of a property. - * (the property name is recommened to be URI for uniqueness). - * Some well known optional properties are defined in - * - * http://www.xmlpull.org/v1/doc/properties.html. - * - * If property is not recocgnized or can not be set - * then IllegalStateException MUST be thrown. - * - * @exception IllegalStateException if the property is not supported or can not be set - */ - void setProperty(String name, - Object value) - throws IllegalArgumentException, IllegalStateException; - - /** - * Look up the value of a property. - * - * The property name is any fully-qualified URI. I - *

    NOTE: unknown properties are always returned as null - * - * @param name The name of property to be retrieved. - * @return The value of named property. - */ - Object getProperty(String name); - - /** - * Set to use binary output stream with given encoding. - */ - void setOutput(OutputStream os, String encoding) - throws IOException, IllegalArgumentException, IllegalStateException; - - /** - * Set the output to the given writer. - *

    WARNING no information about encoding is available! - */ - void setOutput(Writer writer) - throws IOException, IllegalArgumentException, IllegalStateException; - - /** - * Write <?xml declaration with encoding (if encoding not null) - * and standalone flag (if standalone not null) - * This method can only be called just after setOutput. - */ - void startDocument(String encoding, Boolean standalone) - throws IOException, IllegalArgumentException, IllegalStateException; - - /** - * Finish writing. All unclosed start tags will be closed and output - * will be flushed. After calling this method no more output can be - * serialized until next call to setOutput() - */ - void endDocument() - throws IOException, IllegalArgumentException, IllegalStateException; - - /** - * Binds the given prefix to the given namespace. - * This call is valid for the next element including child elements. - * The prefix and namespace MUST be always declared even if prefix - * is not used in element (startTag() or attribute()) - for XML 1.0 - * it must result in declaring xmlns:prefix='namespace' - * (or xmlns:prefix="namespace" depending what character is used - * to quote attribute value). - * - *

    NOTE: this method MUST be called directly before startTag() - * and if anything but startTag() or setPrefix() is called next there will be exception. - *

    NOTE: prefixes "xml" and "xmlns" are already bound - * and can not be redefined see: - * Namespaces in XML Errata. - *

    NOTE: to set default namespace use as prefix empty string. - * - * @param prefix must be not null (or IllegalArgumentException is thrown) - * @param namespace must be not null - */ - void setPrefix(String prefix, String namespace) - throws IOException, IllegalArgumentException, IllegalStateException; - - /** - * Return namespace that corresponds to given prefix - * If there is no prefix bound to this namespace return null - * but if generatePrefix is false then return generated prefix. - * - *

    NOTE: if the prefix is empty string "" and defualt namespace is bound - * to this prefix then empty string ("") is returned. - * - *

    NOTE: prefixes "xml" and "xmlns" are already bound - * will have values as defined - * Namespaces in XML specification - */ - String getPrefix(String namespace, boolean generatePrefix) - throws IllegalArgumentException; - - /** - * Returns the current depth of the element. - * Outside the root element, the depth is 0. The - * depth is incremented by 1 when startTag() is called. - * The depth is decremented after the call to endTag() - * event was observed. - * - *

    -     * <!-- outside -->     0
    -     * <root>               1
    -     *   sometext                 1
    -     *     <foobar>         2
    -     *     </foobar>        2
    -     * </root>              1
    -     * <!-- outside -->     0
    -     * 
    - */ - int getDepth(); - - /** - * Returns the namespace URI of the current element as set by startTag(). - * - *

    NOTE: that measn in particaulr that:

      - *
    • if there was startTag("", ...) then getNamespace() returns "" - *
    • if there was startTag(null, ...) then getNamespace() returns null - *
    - * - * @return namespace set by startTag() that is currently in scope - */ - String getNamespace(); - - /** - * Returns the name of the current element as set by startTag(). - * It can only be null before first call to startTag() - * or when last endTag() is called to close first startTag(). - * - * @return namespace set by startTag() that is currently in scope - */ - String getName(); - - /** - * Writes a start tag with the given namespace and name. - * If there is no prefix defined for the given namespace, - * a prefix will be defined automatically. - * The explicit prefixes for namespaces can be established by calling setPrefix() - * immediately before this method. - * If namespace is null no namespace prefix is printed but just name. - * If namespace is empty string then serialzier will make sure that - * default empty namespace is declared (in XML 1.0 xmlns='') - * or throw IllegalStateException if default namespace is already bound - * to non-empty string. - */ - XmlSerializer startTag(String namespace, String name) - throws IOException, IllegalArgumentException, IllegalStateException; - - /** - * Write an attribute. Calls to attribute() MUST follow a call to - * startTag() immediately. If there is no prefix defined for the - * given namespace, a prefix will be defined automatically. - * If namespace is null or empty string - * no namespace prefix is printed but just name. - */ - XmlSerializer attribute(String namespace, String name, String value) - throws IOException, IllegalArgumentException, IllegalStateException; - - /** - * Write end tag. Repetition of namespace and name is just for avoiding errors. - *

    Background: in kXML endTag had no arguments, and non matching tags were - * very difficult to find... - * If namespace is null no namespace prefix is printed but just name. - * If namespace is empty string then serialzier will make sure that - * default empty namespace is declared (in XML 1.0 xmlns=''). - */ - XmlSerializer endTag(String namespace, String name) - throws IOException, IllegalArgumentException, IllegalStateException; - - - // /** - // * Writes a start tag with the given namespace and name. - // *
    If there is no prefix defined (prefix == null) for the given namespace, - // * a prefix will be defined automatically. - // *
    If explicit prefixes is passed (prefix != null) then it will be used - // *and namespace declared if not already declared or - // * throw IllegalStateException the same prefix was already set on this - // * element (setPrefix()) and was bound to different namespace. - // *
    If namespace is null then prefix must be null too or IllegalStateException is thrown. - // *
    If namespace is null then no namespace prefix is printed but just name. - // *
    If namespace is empty string then serializer will make sure that - // * default empty namespace is declared (in XML 1.0 xmlns='') - // * or throw IllegalStateException if default namespace is already bound - // * to non-empty string. - // */ - // XmlSerializer startTag (String prefix, String namespace, String name) - // throws IOException, IllegalArgumentException, IllegalStateException; - // - // /** - // * Write an attribute. Calls to attribute() MUST follow a call to - // * startTag() immediately. - // *
    If there is no prefix defined (prefix == null) for the given namespace, - // * a prefix will be defined automatically. - // *
    If explicit prefixes is passed (prefix != null) then it will be used - // * and namespace declared if not already declared or - // * throw IllegalStateException the same prefix was already set on this - // * element (setPrefix()) and was bound to different namespace. - // *
    If namespace is null then prefix must be null too or IllegalStateException is thrown. - // *
    If namespace is null then no namespace prefix is printed but just name. - // *
    If namespace is empty string then serializer will make sure that - // * default empty namespace is declared (in XML 1.0 xmlns='') - // * or throw IllegalStateException if default namespace is already bound - // * to non-empty string. - // */ - // XmlSerializer attribute (String prefix, String namespace, String name, String value) - // throws IOException, IllegalArgumentException, IllegalStateException; - // - // /** - // * Write end tag. Repetition of namespace, prefix, and name is just for avoiding errors. - // *
    If namespace or name arguments are different from corresponding startTag call - // * then IllegalArgumentException is thrown, if prefix argument is not null and is different - // * from corresponding starTag then IllegalArgumentException is thrown. - // *
    If namespace is null then prefix must be null too or IllegalStateException is thrown. - // *
    If namespace is null then no namespace prefix is printed but just name. - // *
    If namespace is empty string then serializer will make sure that - // * default empty namespace is declared (in XML 1.0 xmlns=''). - // *

    Background: in kXML endTag had no arguments, and non matching tags were - // * very difficult to find...

    - // */ - // ALEK: This is really optional as prefix in end tag MUST correspond to start tag but good for error checking - // XmlSerializer endTag (String prefix, String namespace, String name) - // throws IOException, IllegalArgumentException, IllegalStateException; - - /** - * Writes text, where special XML chars are escaped automatically - */ - XmlSerializer text(String text) - throws IOException, IllegalArgumentException, IllegalStateException; - - /** - * Writes text, where special XML chars are escaped automatically - */ - XmlSerializer text(char[] buf, int start, int len) - throws IOException, IllegalArgumentException, IllegalStateException; - - void cdsect(String text) - throws IOException, IllegalArgumentException, IllegalStateException; - void entityRef(String text) throws IOException, - IllegalArgumentException, IllegalStateException; - void processingInstruction(String text) - throws IOException, IllegalArgumentException, IllegalStateException; - void comment(String text) - throws IOException, IllegalArgumentException, IllegalStateException; - void docdecl(String text) - throws IOException, IllegalArgumentException, IllegalStateException; - void ignorableWhitespace(String text) - throws IOException, IllegalArgumentException, IllegalStateException; - - /** - * Write all pending output to the stream. - * If method startTag() or attribute() was called then start tag is closed (final >) - * before flush() is called on underlying output stream. - * - *

    NOTE: if there is need to close start tag - * (so no more attribute() calls are allowed) but without flushinging output - * call method text() with empty string (text("")). - * - */ - void flush() - throws IOException; - -} - diff --git a/patch/build.gradle.kts b/patch/build.gradle.kts index 9e9ac14..be56c5f 100644 --- a/patch/build.gradle.kts +++ b/patch/build.gradle.kts @@ -18,7 +18,6 @@ java { dependencies { implementation(projects.apkzlib) - implementation(projects.axmlprinter) implementation(projects.share.java) implementation("commons-io:commons-io:2.11.0") diff --git a/patch/src/main/java/org/lsposed/patch/util/ManifestParser.java b/patch/src/main/java/org/lsposed/patch/util/ManifestParser.java index 16b216b..5ee2e60 100644 --- a/patch/src/main/java/org/lsposed/patch/util/ManifestParser.java +++ b/patch/src/main/java/org/lsposed/patch/util/ManifestParser.java @@ -1,13 +1,13 @@ package org.lsposed.patch.util; +import com.wind.meditor.utils.Utils; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import wind.android.content.res.AXmlResourceParser; -import wind.v1.XmlPullParser; -import wind.v1.XmlPullParserException; +import pxb.android.axml.AxmlParser; /** * Created by Wind @@ -15,40 +15,39 @@ import wind.v1.XmlPullParserException; public class ManifestParser { public static Pair parseManifestFile(InputStream is) throws IOException { - AXmlResourceParser parser = new AXmlResourceParser(); + AxmlParser parser = new AxmlParser(Utils.getBytesFromInputStream(is)); String packageName = null; String appComponentFactory = null; int minSdkVersion = 0; try { - parser.open(is); while (true) { int type = parser.next(); - if (type == XmlPullParser.END_DOCUMENT) { + if (type == AxmlParser.END_FILE) { break; } - if (type == XmlPullParser.START_TAG) { + if (type == AxmlParser.START_TAG) { int attrCount = parser.getAttributeCount(); for (int i = 0; i < attrCount; i++) { - String attrName = parser.getAttributeName(i); - int attrNameRes = parser.getAttributeNameResource(i); + String attrName = parser.getAttrName(i); + int attrNameRes = parser.getAttrResId(i); String name = parser.getName(); - + if ("manifest".equals(name)) { if ("package".equals(attrName)) { - packageName = parser.getAttributeValue(i); + packageName = parser.getAttrValue(i).toString(); } } if ("uses-sdk".equals(name)) { - if ("android:minSdkVersion".equals(attrName)) { - minSdkVersion = Integer.parseInt(parser.getAttributeValue(i)); + if ("minSdkVersion".equals(attrName)) { + minSdkVersion = Integer.parseInt(parser.getAttrValue(i).toString()); } } if ("appComponentFactory".equals(attrName) || attrNameRes == 0x0101057a) { - appComponentFactory = parser.getAttributeValue(i); + appComponentFactory = parser.getAttrValue(i).toString(); } if (packageName != null && packageName.length() > 0 && @@ -58,13 +57,14 @@ public class ManifestParser { return new Pair(packageName, appComponentFactory, minSdkVersion); } } - } else if (type == XmlPullParser.END_TAG) { + } else if (type == AxmlParser.END_TAG) { // ignored } } - } catch (XmlPullParserException | IOException e) { + } catch (Exception e) { return null; } + return new Pair(packageName, appComponentFactory, minSdkVersion); } diff --git a/settings.gradle.kts b/settings.gradle.kts index 1ee2288..b5f7c3d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,7 +26,6 @@ dependencyResolutionManagement { rootProject.name = "LSPatch" include( ":apkzlib", - ":axmlprinter", ":core", ":hiddenapi:bridge", ":hiddenapi:stubs",