1 package de.loskutov.bco.asm; 2 3 import java.io.IOException ; 4 import java.io.InputStream ; 5 import java.util.ArrayList ; 6 import java.util.BitSet ; 7 import java.util.List ; 8 9 import org.objectweb.asm.AnnotationVisitor; 10 import org.objectweb.asm.Attribute; 11 import org.objectweb.asm.ClassAdapter; 12 import org.objectweb.asm.ClassReader; 13 import org.objectweb.asm.ClassVisitor; 14 import org.objectweb.asm.FieldVisitor; 15 import org.objectweb.asm.MethodVisitor; 16 import org.objectweb.asm.tree.ClassNode; 17 import org.objectweb.asm.tree.MethodNode; 18 import org.objectweb.asm.util.AbstractVisitor; 19 20 import de.loskutov.bco.asm.CommentedClassVisitor.CommentedAnnotationVisitor; 21 import de.loskutov.bco.asm.CommentedClassVisitor.CommentedFieldVisitor; 22 import de.loskutov.bco.preferences.BCOConstants; 23 24 27 28 public class DecompilerClassVisitor extends ClassAdapter { 29 30 private final String fieldFilter; 31 32 private final String methodFilter; 33 34 private String name; 35 36 private final List methods; 37 38 private AnnotationVisitor dummyAnnVisitor; 39 40 private String javaVersion; 41 42 private final BitSet modes; 43 44 private int accessFlags; 45 46 private ClassNode classNode; 47 48 public DecompilerClassVisitor(final ClassVisitor cv, final String field, 49 final String method, final BitSet modes) { 50 super(cv); 51 this.classNode = new ClassNode(); 52 this.fieldFilter = field; 53 this.methodFilter = method; 54 this.modes = modes; 55 this.methods = new ArrayList (); 56 } 57 58 public static DecompiledClass getDecompiledClass(final InputStream is, 59 final String field, final String method, final BitSet modes, final ClassLoader cl) 60 throws IOException , UnsupportedClassVersionError { 61 ClassReader cr = new ClassReader(is); 62 int crFlags = 0; 63 if(modes.get(BCOConstants.F_EXPAND_STACKMAP)) { 64 crFlags |= ClassReader.EXPAND_FRAMES; 65 } 66 ClassVisitor cv; 67 if (modes.get(BCOConstants.F_SHOW_ASMIFIER_CODE)) { 68 cv = new CommentedASMifierClassVisitor(modes); 69 } else { 70 cv = new CommentedClassVisitor(modes); 71 } 72 DecompilerClassVisitor dcv = new DecompilerClassVisitor( 73 cv, field, method, modes); 74 cr.accept(dcv, crFlags); 75 return dcv.getResult(cl); 76 } 77 78 public DecompiledClass getResult(final ClassLoader cl) { 79 List text = new ArrayList (); 80 formatText(((AbstractVisitor) cv).getText(), new StringBuffer (), text, cl); 81 while (text.size() > 0 && text.get(0).equals("\n")) { 82 text.remove(0); 83 } 84 DecompiledClass dc = new DecompiledClass(text); 85 dc.setAttribute(DecompiledClass.ATTR_JAVA_VERSION, javaVersion); 86 dc.setAttribute(DecompiledClass.ATTR_ACCESS_FLAGS, String.valueOf(accessFlags)); 87 dc.setClassNode(classNode); 88 return dc; 89 } 90 91 private void formatText(final List input, StringBuffer line, final List result, 92 final ClassLoader cl) { 93 for (int i = 0; i < input.size(); ++i) { 94 Object o = input.get(i); 95 if (o instanceof List ) { 96 formatText((List ) o, line, result, cl); 97 } else if (o instanceof DecompilerMethodVisitor) { 98 result.add(((DecompilerMethodVisitor) o).getResult(cl)); 99 } else { 100 String s = o.toString(); 101 int p; 102 do { 103 p = s.indexOf('\n'); 104 if (p == -1) { 105 line.append(s); 106 } else { 107 result.add(line.toString() + s.substring(0, p + 1)); 108 s = s.substring(p + 1); 109 line.setLength(0); 110 } 111 } while (p != -1); 112 } 113 } 114 } 115 116 public void visit(final int version, final int access, final String name1, 117 final String signature, final String superName, 118 final String [] interfaces) { 119 if (methodFilter == null && fieldFilter == null) { 120 super 121 .visit(version, access, name1, signature, superName, interfaces); 122 classNode.visit(version, access, name1, signature, superName, interfaces); 123 } 124 this.name = name1; 125 int major = version & 0xFFFF; 126 int javaV = major % 44; 129 if (javaV > 0 && javaV < 10) { 130 javaVersion = "1." + javaV; } 132 133 this.accessFlags = access; 134 } 135 136 public void visitSource(final String source, final String debug) { 137 if (methodFilter == null && fieldFilter == null) { 138 super.visitSource(source, debug); 139 classNode.visitSource(source, debug); 140 } 141 } 142 143 public void visitOuterClass(final String owner, final String name1, 144 final String desc) { 145 if (methodFilter == null && fieldFilter == null) { 146 super.visitOuterClass(owner, name1, desc); 147 classNode.visitOuterClass(owner, name1, desc); 148 } 149 } 150 151 public AnnotationVisitor visitAnnotation(final String desc, 152 final boolean visible) { 153 if (methodFilter == null && fieldFilter == null) { 154 AnnotationVisitor cav = classNode.visitAnnotation(desc, visible); 155 AnnotationVisitor av = super.visitAnnotation(desc, visible); 156 if(av instanceof CommentedAnnotationVisitor){ 157 CommentedAnnotationVisitor visitor = (CommentedAnnotationVisitor) av; 158 visitor.setAnnotationVisitor(cav); 159 } 160 return av; 161 } 162 return getDummyAnnotationVisitor(); 163 } 164 165 public void visitAttribute(final Attribute attr) { 166 if (methodFilter == null && fieldFilter == null) { 167 super.visitAttribute(attr); 168 classNode.visitAttribute(attr); 169 } 170 } 171 172 public void visitInnerClass(final String name1, final String outerName, 173 final String innerName, final int access) { 174 if (methodFilter == null && fieldFilter == null) { 175 super.visitInnerClass(name1, outerName, innerName, access); 176 classNode.visitInnerClass(name1, outerName, innerName, access); 177 } 178 } 179 180 public FieldVisitor visitField(final int access, final String name1, 181 final String desc, final String signature, final Object value) { 182 if (methodFilter != null) { 183 return null; 184 } 185 if (fieldFilter != null && !name1.equals(fieldFilter)) { 186 return null; 187 } 188 FieldVisitor cfv = classNode.visitField(access, name1, desc, signature, value); 189 FieldVisitor fieldVisitor = super.visitField(access, name1, desc, signature, value); 190 if(fieldVisitor instanceof CommentedFieldVisitor){ 191 CommentedFieldVisitor visitor = (CommentedFieldVisitor) fieldVisitor; 192 visitor.setFieldVisitor(cfv); 193 } 194 return fieldVisitor; 195 } 196 197 public MethodVisitor visitMethod(final int access, final String name1, 198 final String desc, final String signature, final String [] exceptions) { 199 if (fieldFilter != null) { 200 return null; 201 } 202 if (methodFilter != null && !(name1 + desc).equals(methodFilter)) { 203 return null; 204 } 205 MethodNode meth = (MethodNode) classNode.visitMethod( 206 access, name1, desc, signature, exceptions); 207 List text = ((AbstractVisitor) cv).getText(); 208 int size = text.size(); 209 MethodVisitor mv = cv.visitMethod( 210 access, name1, desc, signature, exceptions); 211 mv = new DecompilerMethodVisitor(this.name, meth, mv, modes); 212 methods.add(mv); 213 for (int i = size; i < text.size(); ++i) { 214 if (text.get(i) instanceof List ) { 215 text.set(i, mv); 216 } 217 } 218 return mv; 219 } 220 221 public void visitEnd() { 222 if (methodFilter == null && fieldFilter == null) { 223 classNode.visitEnd(); 224 super.visitEnd(); 225 } 226 } 227 228 private AnnotationVisitor getDummyAnnotationVisitor(){ 229 if (dummyAnnVisitor == null) { 230 dummyAnnVisitor = new AnnotationVisitor() { 231 public void visit(String n, Object value) { 232 233 } 234 public void visitEnum(String n, String desc, String value) { 235 236 } 237 public AnnotationVisitor visitAnnotation(String n, String desc) { 238 return this; 239 } 240 public AnnotationVisitor visitArray(String n) { 241 return this; 242 } 243 public void visitEnd() { 244 245 } 246 }; 247 } 248 return dummyAnnVisitor; 249 } 250 } 251 | Popular Tags |