/* * Copyright (c) 2009-2012 Panxiaobo * * 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 com.googlecode.dex2jar.util; import java.util.ArrayList; import java.util.List; import com.googlecode.dex2jar.Field; import com.googlecode.dex2jar.Method; import com.googlecode.dex2jar.visitors.DexAnnotationAble; import com.googlecode.dex2jar.visitors.DexAnnotationVisitor; import com.googlecode.dex2jar.visitors.DexClassVisitor; import com.googlecode.dex2jar.visitors.DexCodeVisitor; import com.googlecode.dex2jar.visitors.DexFieldVisitor; import com.googlecode.dex2jar.visitors.DexMethodVisitor; /** * @author <a href="mailto:pxb1988@gmail.com">Panxiaobo</a> * @version $Rev$ */ public class ASMifierClassV implements DexClassVisitor { protected ArrayOut out = new ArrayOut(); private List<ArrayOut> methodOuts = new ArrayList<ArrayOut>(); private List<ArrayOut> fieldOuts = new ArrayList<ArrayOut>(); int fCount = 0; int mCount = 0; public ASMifierClassV(String pkgName, String javaClassName, int access_flags, String className, String superClass, String[] interfaceNames) { super(); out.s("package %s;", pkgName); out.s("import com.googlecode.dex2jar.*;"); out.s("import com.googlecode.dex2jar.visitors.*;"); out.s("import static com.googlecode.dex2jar.OdexOpcodes.*;"); out.s("public class %s {", javaClassName); out.push(); out.s("public static void accept(DexFileVisitor v) {"); out.push(); out.s("DexClassVisitor cv=v.visit(%s,%s,%s,%s);", Escape.classAcc(access_flags), Escape.v(className), Escape.v(superClass), Escape.v(interfaceNames)); out.s("if(cv!=null) {"); out.push(); out.s("accept(cv);"); out.pop(); out.s("}"); out.pop(); out.s("}"); out.s("public static void accept(DexClassVisitor cv) {"); out.push(); } @Override public DexAnnotationVisitor visitAnnotation(String name, boolean visible) { return new ASMifierAnnotationV("cv", out, name, visible); } @Override public void visitSource(String file) { out.s("cv.visitSource(\"%s\");", Utf8Utils.escapeString(file)); } @Override public DexFieldVisitor visitField(int accessFlags, Field field, Object value) { String fieldName = String.format("f%03d_%s", fCount++, field.getName()); out.s("%s(cv);", fieldName); final ArrayOut f = new ArrayOut(); fieldOuts.add(f); f.s("public static void %s(DexClassVisitor cv) {", fieldName); f.push(); f.s("DexFieldVisitor fv=cv.visitField(%s, %s, %s);", Escape.fieldAcc(accessFlags), Escape.v(field), Escape.v(value)); f.s("if(fv != null) {"); f.push(); return new DexFieldVisitor() { @Override public DexAnnotationVisitor visitAnnotation(String name, boolean visible) { return new ASMifierAnnotationV("fv", f, name, visible); } @Override public void visitEnd() { f.s("fv.visitEnd();"); f.pop(); f.s("}"); f.pop(); f.s("}"); } }; } @Override public DexMethodVisitor visitMethod(int accessFlags, Method method) { String methodName = String.format("m%03d_%s", mCount++, method.getName().replace('<', '_').replace('>', '_')); out.s("%s(cv);", methodName); final ArrayOut m = new ArrayOut(); methodOuts.add(m); m.s("public static void %s(DexClassVisitor cv) {", methodName); m.push(); m.s("DexMethodVisitor mv=cv.visitMethod(%s, %s);", Escape.methodAcc(accessFlags), Escape.v(method)); m.s("if(mv != null) {"); m.push(); return new DexMethodVisitor() { @Override public DexAnnotationVisitor visitAnnotation(String name, boolean visible) { return new ASMifierAnnotationV("mv", m, name, visible); } @Override public DexAnnotationAble visitParameterAnnotation(final int index) { m.s("DexAnnotationAble pv%02d = mv.visitParameterAnnotation(%s);", index, index); return new DexAnnotationAble() { @Override public DexAnnotationVisitor visitAnnotation(String name, boolean visible) { return new ASMifierAnnotationV(String.format("pv%02d", index), m, name, visible); } }; } @Override public DexCodeVisitor visitCode() { m.s("DexCodeVisitor code=mv.visitCode();"); m.s("if(code != null) {"); m.push(); return new ASMifierCodeV(m) { @Override public void visitEnd() { super.visitEnd(); m.pop(); m.s("}"); } }; } @Override public void visitEnd() { m.s("mv.visitEnd();"); m.pop(); m.s("}"); m.pop(); m.s("}"); } }; } @Override public void visitEnd() { out.s("cv.visitEnd();"); out.pop(); out.s("}"); for (ArrayOut o : fieldOuts) { out.array.addAll(o.array); for (int i : o.is) { out.is.add(out.i + i); } } fieldOuts = null; for (ArrayOut o : methodOuts) { out.array.addAll(o.array); for (int i : o.is) { out.is.add(out.i + i); } } methodOuts = null; out.pop(); out.s("}"); } }