Home | History | Annotate | Download | only in util
      1 /***
      2  * ASM: a very small and fast Java bytecode manipulation framework
      3  * Copyright (c) 2000-2005 INRIA, France Telecom
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. Neither the name of the copyright holders nor the names of its
     15  *    contributors may be used to endorse or promote products derived from
     16  *    this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     28  * THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 package org.objectweb.asm.util;
     31 
     32 import java.util.HashMap;
     33 
     34 import org.objectweb.asm.AnnotationVisitor;
     35 import org.objectweb.asm.Handle;
     36 import org.objectweb.asm.Label;
     37 import org.objectweb.asm.MethodVisitor;
     38 import org.objectweb.asm.Opcodes;
     39 import org.objectweb.asm.TypePath;
     40 
     41 /**
     42  * A {@link MethodVisitor} that prints the ASM code that generates the methods
     43  * it visits.
     44  *
     45  * @author Eric Bruneton
     46  * @author Eugene Kuleshov
     47  */
     48 public class ASMifierMethodVisitor extends ASMifierAbstractVisitor implements
     49         MethodVisitor
     50 {
     51     /**
     52      * Constructs a new {@link ASMifierMethodVisitor} object.
     53      */
     54     public ASMifierMethodVisitor() {
     55         super("mv");
     56         this.labelNames = new HashMap();
     57     }
     58 
     59     @Override
     60     public AnnotationVisitor visitAnnotationDefault() {
     61         buf.setLength(0);
     62         buf.append("{\n").append("av0 = mv.visitAnnotationDefault();\n");
     63         text.add(buf.toString());
     64         ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
     65         text.add(av.getText());
     66         text.add("}\n");
     67         return av;
     68     }
     69 
     70     @Override
     71     public AnnotationVisitor visitParameterAnnotation(
     72         final int parameter,
     73         final String desc,
     74         final boolean visible)
     75     {
     76         buf.setLength(0);
     77         buf.append("{\n")
     78                 .append("av0 = mv.visitParameterAnnotation(")
     79                 .append(parameter)
     80                 .append(", ");
     81         appendConstant(desc);
     82         buf.append(", ").append(visible).append(");\n");
     83         text.add(buf.toString());
     84         ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
     85         text.add(av.getText());
     86         text.add("}\n");
     87         return av;
     88     }
     89 
     90     @Override
     91     public void visitCode() {
     92         text.add("mv.visitCode();\n");
     93     }
     94 
     95     @Override
     96     public void visitInsn(final int opcode) {
     97         buf.setLength(0);
     98         buf.append("mv.visitInsn(").append(OPCODES[opcode]).append(");\n");
     99         text.add(buf.toString());
    100     }
    101 
    102     @Override
    103     public void visitIntInsn(final int opcode, final int operand) {
    104         buf.setLength(0);
    105         buf.append("mv.visitIntInsn(")
    106                 .append(OPCODES[opcode])
    107                 .append(", ")
    108                 .append(opcode == Opcodes.NEWARRAY
    109                         ? TYPES[operand]
    110                         : Integer.toString(operand))
    111                 .append(");\n");
    112         text.add(buf.toString());
    113     }
    114 
    115     @Override
    116     public void visitVarInsn(final int opcode, final int var) {
    117         buf.setLength(0);
    118         buf.append("mv.visitVarInsn(")
    119                 .append(OPCODES[opcode])
    120                 .append(", ")
    121                 .append(var)
    122                 .append(");\n");
    123         text.add(buf.toString());
    124     }
    125 
    126     @Override
    127     public void visitTypeInsn(final int opcode, final String desc) {
    128         buf.setLength(0);
    129         buf.append("mv.visitTypeInsn(").append(OPCODES[opcode]).append(", ");
    130         appendConstant(desc);
    131         buf.append(");\n");
    132         text.add(buf.toString());
    133     }
    134 
    135     @Override
    136     public void visitFieldInsn(
    137         final int opcode,
    138         final String owner,
    139         final String name,
    140         final String desc)
    141     {
    142         buf.setLength(0);
    143         buf.append("mv.visitFieldInsn(").append(OPCODES[opcode]).append(", ");
    144         appendConstant(owner);
    145         buf.append(", ");
    146         appendConstant(name);
    147         buf.append(", ");
    148         appendConstant(desc);
    149         buf.append(");\n");
    150         text.add(buf.toString());
    151     }
    152 
    153     @Override
    154     public void visitMethodInsn(
    155         final int opcode,
    156         final String owner,
    157         final String name,
    158         final String desc)
    159     {
    160         buf.setLength(0);
    161         buf.append("mv.visitMethodInsn(").append(OPCODES[opcode]).append(", ");
    162         appendConstant(owner);
    163         buf.append(", ");
    164         appendConstant(name);
    165         buf.append(", ");
    166         appendConstant(desc);
    167         buf.append(");\n");
    168         text.add(buf.toString());
    169     }
    170 
    171     @Override
    172     public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
    173         Object... bsmArgs) {
    174       // TODO Auto-generated method stub
    175 
    176     }
    177 
    178     @Override
    179     public AnnotationVisitor visitInsnAnnotation(int typeRef,
    180         TypePath typePath, String desc, boolean visible) {
    181       // TODO Auto-generated method stub
    182       return null;
    183     }
    184 
    185     @Override
    186     public void visitJumpInsn(final int opcode, final Label label) {
    187         buf.setLength(0);
    188         declareLabel(label);
    189         buf.append("mv.visitJumpInsn(").append(OPCODES[opcode]).append(", ");
    190         appendLabel(label);
    191         buf.append(");\n");
    192         text.add(buf.toString());
    193     }
    194 
    195     @Override
    196     public void visitLabel(final Label label) {
    197         buf.setLength(0);
    198         declareLabel(label);
    199         buf.append("mv.visitLabel(");
    200         appendLabel(label);
    201         buf.append(");\n");
    202         text.add(buf.toString());
    203     }
    204 
    205     @Override
    206     public void visitLdcInsn(final Object cst) {
    207         buf.setLength(0);
    208         buf.append("mv.visitLdcInsn(");
    209         appendConstant(cst);
    210         buf.append(");\n");
    211         text.add(buf.toString());
    212     }
    213 
    214     @Override
    215     public void visitIincInsn(final int var, final int increment) {
    216         buf.setLength(0);
    217         buf.append("mv.visitIincInsn(")
    218                 .append(var)
    219                 .append(", ")
    220                 .append(increment)
    221                 .append(");\n");
    222         text.add(buf.toString());
    223     }
    224 
    225     @Override
    226     public void visitTableSwitchInsn(
    227         final int min,
    228         final int max,
    229         final Label dflt,
    230         final Label labels[])
    231     {
    232         buf.setLength(0);
    233         for (int i = 0; i < labels.length; ++i) {
    234             declareLabel(labels[i]);
    235         }
    236         declareLabel(dflt);
    237 
    238         buf.append("mv.visitTableSwitchInsn(")
    239                 .append(min)
    240                 .append(", ")
    241                 .append(max)
    242                 .append(", ");
    243         appendLabel(dflt);
    244         buf.append(", new Label[] {");
    245         for (int i = 0; i < labels.length; ++i) {
    246             buf.append(i == 0 ? " " : ", ");
    247             appendLabel(labels[i]);
    248         }
    249         buf.append(" });\n");
    250         text.add(buf.toString());
    251     }
    252 
    253     @Override
    254     public void visitLookupSwitchInsn(
    255         final Label dflt,
    256         final int keys[],
    257         final Label labels[])
    258     {
    259         buf.setLength(0);
    260         for (int i = 0; i < labels.length; ++i) {
    261             declareLabel(labels[i]);
    262         }
    263         declareLabel(dflt);
    264 
    265         buf.append("mv.visitLookupSwitchInsn(");
    266         appendLabel(dflt);
    267         buf.append(", new int[] {");
    268         for (int i = 0; i < keys.length; ++i) {
    269             buf.append(i == 0 ? " " : ", ").append(keys[i]);
    270         }
    271         buf.append(" }, new Label[] {");
    272         for (int i = 0; i < labels.length; ++i) {
    273             buf.append(i == 0 ? " " : ", ");
    274             appendLabel(labels[i]);
    275         }
    276         buf.append(" });\n");
    277         text.add(buf.toString());
    278     }
    279 
    280     @Override
    281     public void visitMultiANewArrayInsn(final String desc, final int dims) {
    282         buf.setLength(0);
    283         buf.append("mv.visitMultiANewArrayInsn(");
    284         appendConstant(desc);
    285         buf.append(", ").append(dims).append(");\n");
    286         text.add(buf.toString());
    287     }
    288 
    289     @Override
    290     public void visitTryCatchBlock(
    291         final Label start,
    292         final Label end,
    293         final Label handler,
    294         final String type)
    295     {
    296         buf.setLength(0);
    297         declareLabel(start);
    298         declareLabel(end);
    299         declareLabel(handler);
    300         buf.append("mv.visitTryCatchBlock(");
    301         appendLabel(start);
    302         buf.append(", ");
    303         appendLabel(end);
    304         buf.append(", ");
    305         appendLabel(handler);
    306         buf.append(", ");
    307         appendConstant(type);
    308         buf.append(");\n");
    309         text.add(buf.toString());
    310     }
    311 
    312     @Override
    313     public void visitLocalVariable(
    314         final String name,
    315         final String desc,
    316         final String signature,
    317         final Label start,
    318         final Label end,
    319         final int index)
    320     {
    321         buf.setLength(0);
    322         buf.append("mv.visitLocalVariable(");
    323         appendConstant(name);
    324         buf.append(", ");
    325         appendConstant(desc);
    326         buf.append(", ");
    327         appendConstant(signature);
    328         buf.append(", ");
    329         appendLabel(start);
    330         buf.append(", ");
    331         appendLabel(end);
    332         buf.append(", ").append(index).append(");\n");
    333         text.add(buf.toString());
    334     }
    335 
    336     @Override
    337     public void visitLineNumber(final int line, final Label start) {
    338         buf.setLength(0);
    339         buf.append("mv.visitLineNumber(").append(line).append(", ");
    340         appendLabel(start);
    341         buf.append(");\n");
    342         text.add(buf.toString());
    343     }
    344 
    345     @Override
    346     public void visitMaxs(final int maxStack, final int maxLocals) {
    347         buf.setLength(0);
    348         buf.append("mv.visitMaxs(")
    349                 .append(maxStack)
    350                 .append(", ")
    351                 .append(maxLocals)
    352                 .append(");\n");
    353         text.add(buf.toString());
    354     }
    355 
    356     /**
    357      * Appends a declaration of the given label to {@link #buf buf}. This
    358      * declaration is of the form "Label lXXX = new Label();". Does nothing if
    359      * the given label has already been declared.
    360      *
    361      * @param l a label.
    362      */
    363     private void declareLabel(final Label l) {
    364         String name = (String) labelNames.get(l);
    365         if (name == null) {
    366             name = "l" + labelNames.size();
    367             labelNames.put(l, name);
    368             buf.append("Label ").append(name).append(" = new Label();\n");
    369         }
    370     }
    371 
    372     /**
    373      * Appends the name of the given label to {@link #buf buf}. The given label
    374      * <i>must</i> already have a name. One way to ensure this is to always
    375      * call {@link #declareLabel declared} before calling this method.
    376      *
    377      * @param l a label.
    378      */
    379     private void appendLabel(final Label l) {
    380         buf.append((String) labelNames.get(l));
    381     }
    382 }
    383