1 20 21 package com.tonicsystems.jarjar; 22 23 import com.tonicsystems.jarjar.util.*; 24 import java.util.*; 25 import org.objectweb.asm.Attribute; 26 import org.objectweb.asm.ClassAdapter; 27 import org.objectweb.asm.ClassVisitor; 28 import org.objectweb.asm.FieldVisitor; 29 import org.objectweb.asm.Label; 30 import org.objectweb.asm.MethodAdapter; 31 import org.objectweb.asm.MethodVisitor; 32 import org.objectweb.asm.Opcodes; 33 import org.objectweb.asm.Type; 34 35 class DepKillTransformer extends ClassAdapter implements ClassTransformer 37 { 38 private static final Type TYPE_OBJECT = Type.getType(Object .class); 39 private Wildcard[] wildcards; 40 41 public DepKillTransformer(List patterns) { 42 super(null); 43 wildcards = PatternElement.createWildcards(patterns); 44 } 45 46 public void setTarget(ClassVisitor target) { 47 cv = target; 48 } 49 50 private boolean checkDesc(String desc) { 51 for (int i = 0; i < wildcards.length; i++) { 52 if (wildcards[i].matches(desc, Wildcard.STYLE_DESC)) 53 return true; 54 } 55 return false; 56 } 57 58 private String fixMethodDesc(String methodDesc) { 59 if (wildcards.length == 0) 60 return methodDesc; 61 Type[] args = Type.getArgumentTypes(methodDesc); 62 for (int i = 0; i < args.length; i++) 63 args[i] = eraseType(args[i]); 64 return Type.getMethodDescriptor(eraseType(Type.getReturnType(methodDesc)), args); 65 } 66 67 private Type eraseType(Type type) { 68 return checkDesc(type.getDescriptor()) ? TYPE_OBJECT : type; 69 } 70 71 private boolean checkName(String name) { 72 if (wildcards.length == 0) 73 return false; 74 return checkDesc("L" + name + ";"); 75 } 76 77 private static void replace(MethodVisitor mv, String desc) { 78 switch (desc.charAt(0)) { 79 case 'V': 80 break; 81 case 'D': 82 mv.visitInsn(Opcodes.DCONST_0); 83 break; 84 case 'F': 85 mv.visitInsn(Opcodes.FCONST_0); 86 break; 87 case 'J': 88 mv.visitInsn(Opcodes.LCONST_0); 89 break; 90 case 'C': 91 case 'S': 92 case 'B': 93 case 'I': 94 case 'Z': 95 mv.visitInsn(Opcodes.ICONST_0); 96 break; 97 case 'L': 98 case '[': 99 mv.visitInsn(Opcodes.ACONST_NULL); 100 break; 101 } 102 } 103 104 private static void pop(MethodVisitor mv, String desc) { 105 switch (desc.charAt(0)) { 106 case 'D': 107 case 'J': 108 mv.visitInsn(Opcodes.POP2); 109 default: 110 mv.visitInsn(Opcodes.POP); 111 } 112 } 113 114 public MethodVisitor visitMethod(int access, String name, String desc, String signature, String [] exceptions) { 115 if (exceptions != null && wildcards.length > 0) { 116 List exceptionList = new ArrayList(exceptions.length); 117 for (int i = 0; i < exceptions.length; i++) { 118 if (!checkName(exceptions[i])) 119 exceptionList.add(exceptions[i]); 120 } 121 exceptions = (String [])exceptionList.toArray(new String [exceptionList.size()]); 122 } 123 return new DepKillMethodVisitor(cv.visitMethod(access, name, fixMethodDesc(desc), signature, exceptions)); 124 } 125 126 public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { 127 if (checkDesc(desc)) { 128 desc = TYPE_OBJECT.getDescriptor(); 130 } 131 return super.visitField(access, name, desc, signature, value); 132 } 133 134 private class DepKillMethodVisitor extends MethodAdapter 135 { 136 public DepKillMethodVisitor(MethodVisitor mv) { 137 super(mv); 138 } 139 140 public void visitTypeInsn(int opcode, String desc) { 141 if ((desc.charAt(0) == '[') ? checkDesc(desc) : checkName(desc)) { 142 switch (opcode) { 144 case Opcodes.NEW: 145 case Opcodes.ANEWARRAY: 146 mv.visitInsn(Opcodes.ACONST_NULL); 147 break; 148 case Opcodes.CHECKCAST: 149 case Opcodes.INSTANCEOF: 150 mv.visitInsn(Opcodes.ICONST_0); 151 break; 152 } 153 } else { 154 mv.visitTypeInsn(opcode, desc); 155 } 156 } 157 158 public void visitFieldInsn(int opcode, String owner, String name, String desc) { 159 if (checkName(owner) || checkDesc(desc)) { 160 switch (opcode) { 162 case Opcodes.GETFIELD: 163 mv.visitInsn(Opcodes.POP); 164 replace(mv, desc); 165 break; 166 case Opcodes.PUTFIELD: 167 pop(mv, desc); 168 mv.visitInsn(Opcodes.POP); 169 break; 170 case Opcodes.GETSTATIC: 171 replace(mv, desc); 172 break; 173 case Opcodes.PUTSTATIC: 174 pop(mv, desc); 175 break; 176 } 177 } else { 178 mv.visitFieldInsn(opcode, owner, name, desc); 179 } 180 } 181 182 public void visitMethodInsn(int opcode, String owner, String name, String desc) { 183 if (checkName(owner)) { 184 switch (opcode) { 186 case Opcodes.INVOKEINTERFACE: 187 case Opcodes.INVOKEVIRTUAL: 188 mv.visitInsn(Opcodes.POP); 189 break; 190 case Opcodes.INVOKESPECIAL: 191 throw new IllegalStateException ("Cannot remove invocation of " + owner + "." + desc); 192 case Opcodes.INVOKESTATIC: 193 } 194 195 Type[] args = Type.getArgumentTypes(desc); 196 for (int i = 0; i < args.length; i++) 197 mv.visitInsn((args[i].getSize() == 2) ? Opcodes.POP2 : Opcodes.POP); 198 replace(mv, Type.getReturnType(desc).getDescriptor()); 199 200 } else { 201 mv.visitMethodInsn(opcode, owner, name, fixMethodDesc(desc)); 202 } 203 } 204 205 public void visitMultiANewArrayInsn(String desc, int dims) { 206 if (checkDesc(desc)) { 207 mv.visitInsn(Opcodes.ACONST_NULL); 209 } else { 210 mv.visitMultiANewArrayInsn(desc, dims); 211 } 212 } 213 214 public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { 215 if (!checkName(type)) 216 mv.visitTryCatchBlock(start, end, handler, type); 217 } 218 219 public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { 220 if (checkDesc(desc)) { 221 desc = TYPE_OBJECT.getDescriptor(); 223 } 224 mv.visitLocalVariable(name, desc, signature, start, end, index); 225 } 226 227 public void visitAttribute(Attribute attr) { 228 mv.visitAttribute(attr); 229 } 230 } 231 } 232 | Popular Tags |