| // ASM: a very small and fast Java bytecode manipulation framework |
| // Copyright (c) 2000-2011 INRIA, France Telecom |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions |
| // are met: |
| // 1. Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // 2. Redistributions in binary form must reproduce the above copyright |
| // notice, this list of conditions and the following disclaimer in the |
| // documentation and/or other materials provided with the distribution. |
| // 3. Neither the name of the copyright holders nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
| // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| // THE POSSIBILITY OF SUCH DAMAGE. |
| package org.apache.tapestry5.internal.plastic.asm.util; |
| |
| import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor; |
| import org.apache.tapestry5.internal.plastic.asm.Attribute; |
| import org.apache.tapestry5.internal.plastic.asm.Handle; |
| import org.apache.tapestry5.internal.plastic.asm.Label; |
| import org.apache.tapestry5.internal.plastic.asm.MethodVisitor; |
| import org.apache.tapestry5.internal.plastic.asm.Opcodes; |
| import org.apache.tapestry5.internal.plastic.asm.TypePath; |
| |
| /** |
| * A {@link MethodVisitor} that prints the methods it visits with a {@link Printer}. |
| * |
| * @author Eric Bruneton |
| */ |
| public final class TraceMethodVisitor extends MethodVisitor { |
| |
| /** The printer to convert the visited method into text. */ |
| // DontCheck(MemberName): can't be renamed (for backward binary compatibility). |
| public final Printer p; |
| |
| /** |
| * Constructs a new {@link TraceMethodVisitor}. |
| * |
| * @param printer the printer to convert the visited method into text. |
| */ |
| public TraceMethodVisitor(final Printer printer) { |
| this(null, printer); |
| } |
| |
| /** |
| * Constructs a new {@link TraceMethodVisitor}. |
| * |
| * @param methodVisitor the method visitor to which to delegate calls. May be {@literal null}. |
| * @param printer the printer to convert the visited method into text. |
| */ |
| public TraceMethodVisitor(final MethodVisitor methodVisitor, final Printer printer) { |
| super(/* latest api = */ Opcodes.ASM8, methodVisitor); |
| this.p = printer; |
| } |
| |
| @Override |
| public void visitParameter(final String name, final int access) { |
| p.visitParameter(name, access); |
| super.visitParameter(name, access); |
| } |
| |
| @Override |
| public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { |
| Printer annotationPrinter = p.visitMethodAnnotation(descriptor, visible); |
| return new TraceAnnotationVisitor( |
| super.visitAnnotation(descriptor, visible), annotationPrinter); |
| } |
| |
| @Override |
| public AnnotationVisitor visitTypeAnnotation( |
| final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { |
| Printer annotationPrinter = p.visitMethodTypeAnnotation(typeRef, typePath, descriptor, visible); |
| return new TraceAnnotationVisitor( |
| super.visitTypeAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter); |
| } |
| |
| @Override |
| public void visitAttribute(final Attribute attribute) { |
| p.visitMethodAttribute(attribute); |
| super.visitAttribute(attribute); |
| } |
| |
| @Override |
| public AnnotationVisitor visitAnnotationDefault() { |
| Printer annotationPrinter = p.visitAnnotationDefault(); |
| return new TraceAnnotationVisitor(super.visitAnnotationDefault(), annotationPrinter); |
| } |
| |
| @Override |
| public void visitAnnotableParameterCount(final int parameterCount, final boolean visible) { |
| p.visitAnnotableParameterCount(parameterCount, visible); |
| super.visitAnnotableParameterCount(parameterCount, visible); |
| } |
| |
| @Override |
| public AnnotationVisitor visitParameterAnnotation( |
| final int parameter, final String descriptor, final boolean visible) { |
| Printer annotationPrinter = p.visitParameterAnnotation(parameter, descriptor, visible); |
| return new TraceAnnotationVisitor( |
| super.visitParameterAnnotation(parameter, descriptor, visible), annotationPrinter); |
| } |
| |
| @Override |
| public void visitCode() { |
| p.visitCode(); |
| super.visitCode(); |
| } |
| |
| @Override |
| public void visitFrame( |
| final int type, |
| final int numLocal, |
| final Object[] local, |
| final int numStack, |
| final Object[] stack) { |
| p.visitFrame(type, numLocal, local, numStack, stack); |
| super.visitFrame(type, numLocal, local, numStack, stack); |
| } |
| |
| @Override |
| public void visitInsn(final int opcode) { |
| p.visitInsn(opcode); |
| super.visitInsn(opcode); |
| } |
| |
| @Override |
| public void visitIntInsn(final int opcode, final int operand) { |
| p.visitIntInsn(opcode, operand); |
| super.visitIntInsn(opcode, operand); |
| } |
| |
| @Override |
| public void visitVarInsn(final int opcode, final int var) { |
| p.visitVarInsn(opcode, var); |
| super.visitVarInsn(opcode, var); |
| } |
| |
| @Override |
| public void visitTypeInsn(final int opcode, final String type) { |
| p.visitTypeInsn(opcode, type); |
| super.visitTypeInsn(opcode, type); |
| } |
| |
| @Override |
| public void visitFieldInsn( |
| final int opcode, final String owner, final String name, final String descriptor) { |
| p.visitFieldInsn(opcode, owner, name, descriptor); |
| super.visitFieldInsn(opcode, owner, name, descriptor); |
| } |
| |
| @Override |
| @SuppressWarnings("deprecation") |
| public void visitMethodInsn( |
| final int opcode, |
| final String owner, |
| final String name, |
| final String descriptor, |
| final boolean isInterface) { |
| // Call the method that p is supposed to implement, depending on its api version. |
| if (p.api < Opcodes.ASM5) { |
| if (isInterface != (opcode == Opcodes.INVOKEINTERFACE)) { |
| throw new IllegalArgumentException("INVOKESPECIAL/STATIC on interfaces require ASM5"); |
| } |
| // If p is an ASMifier (resp. Textifier), or a subclass that does not override the old |
| // visitMethodInsn method, the default implementation in Printer will redirect this to the |
| // new method in ASMifier (resp. Textifier). In all other cases, p overrides the old method |
| // and this call executes it. |
| p.visitMethodInsn(opcode, owner, name, descriptor); |
| } else { |
| p.visitMethodInsn(opcode, owner, name, descriptor, isInterface); |
| } |
| if (mv != null) { |
| mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface); |
| } |
| } |
| |
| @Override |
| public void visitInvokeDynamicInsn( |
| final String name, |
| final String descriptor, |
| final Handle bootstrapMethodHandle, |
| final Object... bootstrapMethodArguments) { |
| p.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); |
| super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); |
| } |
| |
| @Override |
| public void visitJumpInsn(final int opcode, final Label label) { |
| p.visitJumpInsn(opcode, label); |
| super.visitJumpInsn(opcode, label); |
| } |
| |
| @Override |
| public void visitLabel(final Label label) { |
| p.visitLabel(label); |
| super.visitLabel(label); |
| } |
| |
| @Override |
| public void visitLdcInsn(final Object value) { |
| p.visitLdcInsn(value); |
| super.visitLdcInsn(value); |
| } |
| |
| @Override |
| public void visitIincInsn(final int var, final int increment) { |
| p.visitIincInsn(var, increment); |
| super.visitIincInsn(var, increment); |
| } |
| |
| @Override |
| public void visitTableSwitchInsn( |
| final int min, final int max, final Label dflt, final Label... labels) { |
| p.visitTableSwitchInsn(min, max, dflt, labels); |
| super.visitTableSwitchInsn(min, max, dflt, labels); |
| } |
| |
| @Override |
| public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { |
| p.visitLookupSwitchInsn(dflt, keys, labels); |
| super.visitLookupSwitchInsn(dflt, keys, labels); |
| } |
| |
| @Override |
| public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) { |
| p.visitMultiANewArrayInsn(descriptor, numDimensions); |
| super.visitMultiANewArrayInsn(descriptor, numDimensions); |
| } |
| |
| @Override |
| public AnnotationVisitor visitInsnAnnotation( |
| final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { |
| Printer annotationPrinter = p.visitInsnAnnotation(typeRef, typePath, descriptor, visible); |
| return new TraceAnnotationVisitor( |
| super.visitInsnAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter); |
| } |
| |
| @Override |
| public void visitTryCatchBlock( |
| final Label start, final Label end, final Label handler, final String type) { |
| p.visitTryCatchBlock(start, end, handler, type); |
| super.visitTryCatchBlock(start, end, handler, type); |
| } |
| |
| @Override |
| public AnnotationVisitor visitTryCatchAnnotation( |
| final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { |
| Printer annotationPrinter = p.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible); |
| return new TraceAnnotationVisitor( |
| super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible), annotationPrinter); |
| } |
| |
| @Override |
| public void visitLocalVariable( |
| final String name, |
| final String descriptor, |
| final String signature, |
| final Label start, |
| final Label end, |
| final int index) { |
| p.visitLocalVariable(name, descriptor, signature, start, end, index); |
| super.visitLocalVariable(name, descriptor, signature, start, end, index); |
| } |
| |
| @Override |
| public AnnotationVisitor visitLocalVariableAnnotation( |
| final int typeRef, |
| final TypePath typePath, |
| final Label[] start, |
| final Label[] end, |
| final int[] index, |
| final String descriptor, |
| final boolean visible) { |
| Printer annotationPrinter = |
| p.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible); |
| return new TraceAnnotationVisitor( |
| super.visitLocalVariableAnnotation( |
| typeRef, typePath, start, end, index, descriptor, visible), |
| annotationPrinter); |
| } |
| |
| @Override |
| public void visitLineNumber(final int line, final Label start) { |
| p.visitLineNumber(line, start); |
| super.visitLineNumber(line, start); |
| } |
| |
| @Override |
| public void visitMaxs(final int maxStack, final int maxLocals) { |
| p.visitMaxs(maxStack, maxLocals); |
| super.visitMaxs(maxStack, maxLocals); |
| } |
| |
| @Override |
| public void visitEnd() { |
| p.visitMethodEnd(); |
| super.visitEnd(); |
| } |
| } |