package com.github.nukc.plugin.axml.decode;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import static java.lang.System.out;
public class AXMLDoc {
private final int MAGIC_NUMBER = 0X00080003;
private final int CHUNK_STRING_BLOCK = 0X001C0001;
private final int CHUNK_RESOURCE_ID = 0X00080180;
private final int CHUNK_XML_TREE = 0X00100100;
private final String MANIFEST = "manifest";
private final String APPLICATION = "application";
private int mDocSize ;
private StringBlock mStringBlock;
private ResBlock mResBlock;
private BXMLTree mXMLTree;
public AXMLDoc(){
}
public StringBlock getStringBlock(){
return mStringBlock;
}
public ResBlock getResBlock(){
return mResBlock;
}
public BXMLTree getBXMLTree(){
return mXMLTree;
}
public BXMLNode getManifestNode(){
List<BXMLNode> children = mXMLTree.getRoot().getChildren();
for(BXMLNode node : children){
if( MANIFEST.equals( mStringBlock.getStringFor(((BTagNode)node).getName() ) )){
return node;
}
}
return null;
}
public BXMLNode getApplicationNode(){
BXMLNode manifest = getManifestNode();
if(manifest == null){
return null;
}
for(BXMLNode node : manifest.getChildren()){
if( APPLICATION.equals( mStringBlock.getStringFor(((BTagNode)node).getName() ))){
return node;
}
}
return null;
}
/**
* Prepare() should be called, if any resource has changes.
* @param os
* @throws IOException
*/
public void build(OutputStream os) throws IOException{
IntWriter writer = new IntWriter(os, false);
mStringBlock.prepare();
mResBlock.prepare();
mXMLTree.prepare();
int base = 8;
mDocSize = base + mStringBlock.getSize() + mResBlock.getSize() + mXMLTree.getSize();
writer.writeInt(MAGIC_NUMBER);
writer.writeInt(mDocSize);
mStringBlock.write(writer);
mResBlock.write(writer);
mXMLTree.write(writer);
os.flush();
os.close();
}
public void testSize() throws IOException{
out.println("string block size:" + mStringBlock.getSize());
mStringBlock.prepare();
out.println("string block size:" + mStringBlock.getSize());
out.println("res block size:" + mResBlock.getSize());
mResBlock.prepare();
out.println("res size:" + mResBlock.getSize());
out.println("xml size:" + mXMLTree.getSize());
mXMLTree.prepare();
out.println("xml size:" + mXMLTree.getSize());
out.println("doc size:" + mDocSize);
int base = 8;
int size = base + mStringBlock.getSize() + mResBlock.getSize() + mXMLTree.getSize();
out.println("doc size:" + size);
}
public void print(){
out.println("size:" + mDocSize);
mXMLTree.print(new XMLVisitor(mStringBlock));
}
public void parse(InputStream is) throws Exception{
IntReader reader = new IntReader(is, false);
int magicNum = reader.readInt();
if(magicNum != MAGIC_NUMBER){
throw new RuntimeException("Not valid AXML format");
}
int size = reader.readInt();
mDocSize = size;
int chunkType = reader.readInt();
if(chunkType == CHUNK_STRING_BLOCK){
parseStringBlock(reader);
}
chunkType = reader.readInt();
if(chunkType == CHUNK_RESOURCE_ID){
parseResourceBlock(reader);
}
chunkType = reader.readInt();
if(chunkType == CHUNK_XML_TREE){
parseXMLTree(reader);
}
}
private void parseStringBlock(IntReader reader) throws Exception{
StringBlock block = new StringBlock();
block.read(reader);
mStringBlock = block;
}
private void parseResourceBlock(IntReader reader) throws IOException{
ResBlock block = new ResBlock();
block.read(reader);
mResBlock = block;
}
private void parseXMLTree(IntReader reader) throws Exception{
BXMLTree tree = new BXMLTree();
tree.read(reader);
mXMLTree = tree;
}
}