From a1d9766a904d254c4a931ca461c454e073253d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryszard=20Wi=C5=9Bniewski?= Date: Tue, 23 Mar 2010 21:07:07 +0100 Subject: [PATCH] Decoding XML files using pure-Java AXmlResourceParser instead of ResXmlStreamDecoder. --- src/brut/androlib/res/AndrolibResources.java | 45 +++++----- .../res/decoder/ResXmlSerializer.java | 85 ------------------- .../res/decoder/ResXmlStreamDecoder.java | 2 +- 3 files changed, 25 insertions(+), 107 deletions(-) diff --git a/src/brut/androlib/res/AndrolibResources.java b/src/brut/androlib/res/AndrolibResources.java index 85ba2429..8ae939c7 100644 --- a/src/brut/androlib/res/AndrolibResources.java +++ b/src/brut/androlib/res/AndrolibResources.java @@ -17,7 +17,7 @@ package brut.androlib.res; -import brut.androlib.*; +import brut.androlib.AndrolibException; import brut.androlib.res.data.*; import brut.androlib.res.data.value.ResFileValue; import brut.androlib.res.data.value.ResXmlSerializable; @@ -25,16 +25,11 @@ import brut.androlib.res.decoder.*; import brut.androlib.res.jni.JniPackage; import brut.androlib.res.jni.JniPackageGroup; import brut.common.BrutException; -import brut.directory.Directory; -import brut.directory.DirectoryException; -import brut.directory.FileDirectory; -import brut.directory.ZipRODirectory; -import brut.util.Jar; -import brut.util.OS; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; +import brut.directory.*; +import brut.util.*; +import java.io.*; import java.util.Arrays; +import org.xmlpull.v1.XmlSerializer; /** * @author Ryszard Wiśniewski @@ -53,9 +48,11 @@ final public class AndrolibResources { public void decode(ResTable resTable, File apkFile, File outDir) throws AndrolibException { - ResXmlSerializer serial = getResXmlSerializer(resTable); - ResFileDecoder fileDecoder = getResFileDecoder(serial); - serial.setCurrentPackage( + Duo duo = getResFileDecoder(); + ResFileDecoder fileDecoder = duo.m1; + ResAttrDecoder attrDecoder = duo.m2; + + attrDecoder.setCurrentPackage( resTable.listMainPackages().iterator().next()); Directory in, out; @@ -72,15 +69,16 @@ final public class AndrolibResources { throw new AndrolibException(ex); } + ResXmlSerializer xmlSerializer = getResXmlSerializer(); for (ResPackage pkg : resTable.listMainPackages()) { - serial.setCurrentPackage(pkg); + attrDecoder.setCurrentPackage(pkg); for (ResResource res : pkg.listFiles()) { ResFileValue fileValue = (ResFileValue) res.getValue(); fileDecoder.decode(in, fileValue.getStrippedPath(), out, res.getFilePath()); } for (ResValuesFile valuesFile : pkg.listValuesFiles()) { - generateValuesFile(valuesFile, out, serial); + generateValuesFile(valuesFile, out, xmlSerializer); } } } @@ -131,27 +129,32 @@ final public class AndrolibResources { new ResSmaliUpdater().updateResIDs(resTable, smaliDir); } - public ResFileDecoder getResFileDecoder(ResXmlSerializer serializer) { + public Duo getResFileDecoder() { ResStreamDecoderContainer decoders = new ResStreamDecoderContainer(); decoders.setDecoder("raw", new ResRawStreamDecoder()); + + ResAttrDecoder attrDecoder = new ResAttrDecoder(); + AXmlResourceParser axmlParser = new AXmlResourceParser(); + axmlParser.setAttrDecoder(attrDecoder); decoders.setDecoder("xml", - new ResXmlStreamDecoder(serializer)); - return new ResFileDecoder(decoders); + new XmlPullStreamDecoder(axmlParser, getResXmlSerializer())); + + return new Duo( + new ResFileDecoder(decoders), attrDecoder); } - public ResXmlSerializer getResXmlSerializer(ResTable resTable) { + public ResXmlSerializer getResXmlSerializer() { ResXmlSerializer serial = new ResXmlSerializer(); serial.setProperty(serial.PROPERTY_SERIALIZER_INDENTATION, " "); return serial; } private void generateValuesFile(ResValuesFile valuesFile, Directory out, - ResXmlSerializer serial) throws AndrolibException { + XmlSerializer serial) throws AndrolibException { try { OutputStream outStream = out.getFileOutput(valuesFile.getPath()); serial.setOutput((outStream), null); - serial.setDecodingEnabled(false); serial.startDocument(null, null); serial.startTag(null, "resources"); diff --git a/src/brut/androlib/res/decoder/ResXmlSerializer.java b/src/brut/androlib/res/decoder/ResXmlSerializer.java index a39b345c..afce19c9 100644 --- a/src/brut/androlib/res/decoder/ResXmlSerializer.java +++ b/src/brut/androlib/res/decoder/ResXmlSerializer.java @@ -17,102 +17,17 @@ package brut.androlib.res.decoder; -import brut.androlib.*; -import brut.androlib.err.UndefinedResObject; -import brut.androlib.res.AndrolibResources; -import brut.androlib.res.data.ResPackage; -import brut.androlib.res.data.value.ResAttr; -import brut.androlib.res.data.value.ResScalarValue; import java.io.IOException; import org.xmlpull.mxp1_serializer.MXSerializer; -import org.xmlpull.v1.XmlSerializer; /** * @author Ryszard Wiśniewski */ public class ResXmlSerializer extends MXSerializer { - private final static String RES_NAMESPACE = - "http://schemas.android.com/apk/res/android"; - - private ResPackage mCurrentPackage; - private boolean mDecodingEnabled = true; - - @Override - public XmlSerializer attribute(String namespace, String name, String value) - throws IOException, IllegalArgumentException, IllegalStateException - { - if (! mDecodingEnabled) { - return super.attribute(namespace, name, value); - } - String origVal = value; - - try { - ResScalarValue resValue = - mCurrentPackage.getValueFactory().factory(value); - value = null; - - if (namespace != null && ! namespace.isEmpty()) { - String pkgName = RES_NAMESPACE.equals(namespace) ? - "android" : mCurrentPackage.getName(); - try { - ResAttr attr = (ResAttr) mCurrentPackage.getResTable() - .getValue(pkgName, "attr", name); - value = attr.convertToResXmlFormat(resValue); - } catch (UndefinedResObject ex) { - System.err.println(String.format( - "warning: udefined attr when decoding: " + - "ns=%s, name=%s, value=%s", - namespace, name, origVal)); - } - } - - if (value == null) { - value = resValue.toResXmlFormat(); - } - } catch (AndrolibException ex) { - throw new IllegalArgumentException(String.format( - "could not decode attribute: ns=%s, name=%s, value=%s", - namespace, name, origVal), ex); - } - - if (value == null) { - return this; - } - - return super.attribute(namespace, name, value); - } - - @Override - public XmlSerializer text(String text) throws IOException { - if (mDecodingEnabled) { - text = AndrolibResources.escapeForResXml(text); - } - return super.text(text); - } - - @Override - public XmlSerializer text(char[] buf, int start, int len) throws IOException { - if (mDecodingEnabled) { - return this.text(new String(buf, start, len)); - } - return super.text(buf, start, len); - } - @Override public void startDocument(String encoding, Boolean standalone) throws IOException, IllegalArgumentException, IllegalStateException { super.startDocument(encoding != null ? encoding : "UTF-8", standalone); super.out.write("\n"); - super.setPrefix("android", RES_NAMESPACE); - } - - public void setCurrentPackage(ResPackage package_) { - mCurrentPackage = package_; - } - - public boolean setDecodingEnabled(boolean escapeRefs) { - boolean oldVal = mDecodingEnabled; - this.mDecodingEnabled = escapeRefs; - return oldVal; } } diff --git a/src/brut/androlib/res/decoder/ResXmlStreamDecoder.java b/src/brut/androlib/res/decoder/ResXmlStreamDecoder.java index 83863c1b..9eaf1815 100644 --- a/src/brut/androlib/res/decoder/ResXmlStreamDecoder.java +++ b/src/brut/androlib/res/decoder/ResXmlStreamDecoder.java @@ -42,7 +42,7 @@ public class ResXmlStreamDecoder implements ResStreamDecoder { XmlSerializerWrapper ser = getXmlWrapperFactory().newSerializerWrapper(mSerializer); ser.setOutput(out, null); - mSerializer.setDecodingEnabled(true); +// mSerializer.setDecodingEnabled(true); while (par.nextToken() != XmlPullParser.END_DOCUMENT) { ser.event(par);