1 // ASM: a very small and fast Java bytecode manipulation framework 2 // Copyright (c) 2000-2011 INRIA, France Telecom 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. Neither the name of the copyright holders nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 // THE POSSIBILITY OF SUCH DAMAGE. 28 package org.objectweb.asm.util; 29 30 import org.objectweb.asm.AnnotationVisitor; 31 import org.objectweb.asm.Attribute; 32 import org.objectweb.asm.Handle; 33 import org.objectweb.asm.Label; 34 import org.objectweb.asm.MethodVisitor; 35 import org.objectweb.asm.Opcodes; 36 import org.objectweb.asm.TypePath; 37 38 /** 39 * A {@link MethodVisitor} that prints the methods it visits with a {@link Printer}. 40 * 41 * @author Eric Bruneton 42 */ 43 public final class TraceMethodVisitor extends MethodVisitor { 44 45 /** The printer to convert the visited method into text. */ 46 // DontCheck(MemberName): can't be renamed (for backward binary compatibility). 47 public final Printer p; 48 49 /** 50 * Constructs a new {@link TraceMethodVisitor}. 51 * 52 * @param printer the printer to convert the visited method into text. 53 */ TraceMethodVisitor(final Printer printer)54 public TraceMethodVisitor(final Printer printer) { 55 this(null, printer); 56 } 57 58 /** 59 * Constructs a new {@link TraceMethodVisitor}. 60 * 61 * @param methodVisitor the method visitor to which to delegate calls. May be {@literal null}. 62 * @param printer the printer to convert the visited method into text. 63 */ TraceMethodVisitor(final MethodVisitor methodVisitor, final Printer printer)64 public TraceMethodVisitor(final MethodVisitor methodVisitor, final Printer printer) { 65 super(/* latest api = */ Opcodes.ASM9, methodVisitor); 66 this.p = printer; 67 } 68 69 @Override visitParameter(final String name, final int access)70 public void visitParameter(final String name, final int access) { 71 p.visitParameter(name, access); 72 super.visitParameter(name, access); 73 } 74 75 @Override visitAnnotation(final String descriptor, final boolean visible)76 public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { 77 Printer annotationPrinter = p.visitMethodAnnotation(descriptor, visible); 78 return new TraceAnnotationVisitor( 79 super.visitAnnotation(descriptor, visible), annotationPrinter); 80 } 81 82 @Override visitTypeAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)83 public AnnotationVisitor visitTypeAnnotation( 84 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 85 Printer annotationPrinter = p.visitMethodTypeAnnotation(typeRef, typePath, descriptor, visible); 86 return new TraceAnnotationVisitor( 87 super.visitTypeAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter); 88 } 89 90 @Override visitAttribute(final Attribute attribute)91 public void visitAttribute(final Attribute attribute) { 92 p.visitMethodAttribute(attribute); 93 super.visitAttribute(attribute); 94 } 95 96 @Override visitAnnotationDefault()97 public AnnotationVisitor visitAnnotationDefault() { 98 Printer annotationPrinter = p.visitAnnotationDefault(); 99 return new TraceAnnotationVisitor(super.visitAnnotationDefault(), annotationPrinter); 100 } 101 102 @Override visitAnnotableParameterCount(final int parameterCount, final boolean visible)103 public void visitAnnotableParameterCount(final int parameterCount, final boolean visible) { 104 p.visitAnnotableParameterCount(parameterCount, visible); 105 super.visitAnnotableParameterCount(parameterCount, visible); 106 } 107 108 @Override visitParameterAnnotation( final int parameter, final String descriptor, final boolean visible)109 public AnnotationVisitor visitParameterAnnotation( 110 final int parameter, final String descriptor, final boolean visible) { 111 Printer annotationPrinter = p.visitParameterAnnotation(parameter, descriptor, visible); 112 return new TraceAnnotationVisitor( 113 super.visitParameterAnnotation(parameter, descriptor, visible), annotationPrinter); 114 } 115 116 @Override visitCode()117 public void visitCode() { 118 p.visitCode(); 119 super.visitCode(); 120 } 121 122 @Override visitFrame( final int type, final int numLocal, final Object[] local, final int numStack, final Object[] stack)123 public void visitFrame( 124 final int type, 125 final int numLocal, 126 final Object[] local, 127 final int numStack, 128 final Object[] stack) { 129 p.visitFrame(type, numLocal, local, numStack, stack); 130 super.visitFrame(type, numLocal, local, numStack, stack); 131 } 132 133 @Override visitInsn(final int opcode)134 public void visitInsn(final int opcode) { 135 p.visitInsn(opcode); 136 super.visitInsn(opcode); 137 } 138 139 @Override visitIntInsn(final int opcode, final int operand)140 public void visitIntInsn(final int opcode, final int operand) { 141 p.visitIntInsn(opcode, operand); 142 super.visitIntInsn(opcode, operand); 143 } 144 145 @Override visitVarInsn(final int opcode, final int varIndex)146 public void visitVarInsn(final int opcode, final int varIndex) { 147 p.visitVarInsn(opcode, varIndex); 148 super.visitVarInsn(opcode, varIndex); 149 } 150 151 @Override visitTypeInsn(final int opcode, final String type)152 public void visitTypeInsn(final int opcode, final String type) { 153 p.visitTypeInsn(opcode, type); 154 super.visitTypeInsn(opcode, type); 155 } 156 157 @Override visitFieldInsn( final int opcode, final String owner, final String name, final String descriptor)158 public void visitFieldInsn( 159 final int opcode, final String owner, final String name, final String descriptor) { 160 p.visitFieldInsn(opcode, owner, name, descriptor); 161 super.visitFieldInsn(opcode, owner, name, descriptor); 162 } 163 164 @Override 165 @SuppressWarnings("deprecation") visitMethodInsn( final int opcode, final String owner, final String name, final String descriptor, final boolean isInterface)166 public void visitMethodInsn( 167 final int opcode, 168 final String owner, 169 final String name, 170 final String descriptor, 171 final boolean isInterface) { 172 // Call the method that p is supposed to implement, depending on its api version. 173 if (p.api < Opcodes.ASM5) { 174 if (isInterface != (opcode == Opcodes.INVOKEINTERFACE)) { 175 throw new IllegalArgumentException("INVOKESPECIAL/STATIC on interfaces require ASM5"); 176 } 177 // If p is an ASMifier (resp. Textifier), or a subclass that does not override the old 178 // visitMethodInsn method, the default implementation in Printer will redirect this to the 179 // new method in ASMifier (resp. Textifier). In all other cases, p overrides the old method 180 // and this call executes it. 181 p.visitMethodInsn(opcode, owner, name, descriptor); 182 } else { 183 p.visitMethodInsn(opcode, owner, name, descriptor, isInterface); 184 } 185 if (mv != null) { 186 mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface); 187 } 188 } 189 190 @Override visitInvokeDynamicInsn( final String name, final String descriptor, final Handle bootstrapMethodHandle, final Object... bootstrapMethodArguments)191 public void visitInvokeDynamicInsn( 192 final String name, 193 final String descriptor, 194 final Handle bootstrapMethodHandle, 195 final Object... bootstrapMethodArguments) { 196 p.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); 197 super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); 198 } 199 200 @Override visitJumpInsn(final int opcode, final Label label)201 public void visitJumpInsn(final int opcode, final Label label) { 202 p.visitJumpInsn(opcode, label); 203 super.visitJumpInsn(opcode, label); 204 } 205 206 @Override visitLabel(final Label label)207 public void visitLabel(final Label label) { 208 p.visitLabel(label); 209 super.visitLabel(label); 210 } 211 212 @Override visitLdcInsn(final Object value)213 public void visitLdcInsn(final Object value) { 214 p.visitLdcInsn(value); 215 super.visitLdcInsn(value); 216 } 217 218 @Override visitIincInsn(final int varIndex, final int increment)219 public void visitIincInsn(final int varIndex, final int increment) { 220 p.visitIincInsn(varIndex, increment); 221 super.visitIincInsn(varIndex, increment); 222 } 223 224 @Override visitTableSwitchInsn( final int min, final int max, final Label dflt, final Label... labels)225 public void visitTableSwitchInsn( 226 final int min, final int max, final Label dflt, final Label... labels) { 227 p.visitTableSwitchInsn(min, max, dflt, labels); 228 super.visitTableSwitchInsn(min, max, dflt, labels); 229 } 230 231 @Override visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels)232 public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { 233 p.visitLookupSwitchInsn(dflt, keys, labels); 234 super.visitLookupSwitchInsn(dflt, keys, labels); 235 } 236 237 @Override visitMultiANewArrayInsn(final String descriptor, final int numDimensions)238 public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) { 239 p.visitMultiANewArrayInsn(descriptor, numDimensions); 240 super.visitMultiANewArrayInsn(descriptor, numDimensions); 241 } 242 243 @Override visitInsnAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)244 public AnnotationVisitor visitInsnAnnotation( 245 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 246 Printer annotationPrinter = p.visitInsnAnnotation(typeRef, typePath, descriptor, visible); 247 return new TraceAnnotationVisitor( 248 super.visitInsnAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter); 249 } 250 251 @Override visitTryCatchBlock( final Label start, final Label end, final Label handler, final String type)252 public void visitTryCatchBlock( 253 final Label start, final Label end, final Label handler, final String type) { 254 p.visitTryCatchBlock(start, end, handler, type); 255 super.visitTryCatchBlock(start, end, handler, type); 256 } 257 258 @Override visitTryCatchAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)259 public AnnotationVisitor visitTryCatchAnnotation( 260 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 261 Printer annotationPrinter = p.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible); 262 return new TraceAnnotationVisitor( 263 super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter); 264 } 265 266 @Override visitLocalVariable( final String name, final String descriptor, final String signature, final Label start, final Label end, final int index)267 public void visitLocalVariable( 268 final String name, 269 final String descriptor, 270 final String signature, 271 final Label start, 272 final Label end, 273 final int index) { 274 p.visitLocalVariable(name, descriptor, signature, start, end, index); 275 super.visitLocalVariable(name, descriptor, signature, start, end, index); 276 } 277 278 @Override visitLocalVariableAnnotation( final int typeRef, final TypePath typePath, final Label[] start, final Label[] end, final int[] index, final String descriptor, final boolean visible)279 public AnnotationVisitor visitLocalVariableAnnotation( 280 final int typeRef, 281 final TypePath typePath, 282 final Label[] start, 283 final Label[] end, 284 final int[] index, 285 final String descriptor, 286 final boolean visible) { 287 Printer annotationPrinter = 288 p.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible); 289 return new TraceAnnotationVisitor( 290 super.visitLocalVariableAnnotation( 291 typeRef, typePath, start, end, index, descriptor, visible), 292 annotationPrinter); 293 } 294 295 @Override visitLineNumber(final int line, final Label start)296 public void visitLineNumber(final int line, final Label start) { 297 p.visitLineNumber(line, start); 298 super.visitLineNumber(line, start); 299 } 300 301 @Override visitMaxs(final int maxStack, final int maxLocals)302 public void visitMaxs(final int maxStack, final int maxLocals) { 303 p.visitMaxs(maxStack, maxLocals); 304 super.visitMaxs(maxStack, maxLocals); 305 } 306 307 @Override visitEnd()308 public void visitEnd() { 309 p.visitMethodEnd(); 310 super.visitEnd(); 311 } 312 } 313