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.Attribute;
     36 import org.objectweb.asm.TypeAnnotationVisitor;
     37 import org.objectweb.asm.Type;
     38 import org.objectweb.asm.util.attrs.ASMifiable;
     39 
     40 /**
     41  * An abstract ASMifier visitor.
     42  *
     43  * @author Eric Bruneton
     44  */
     45 public class ASMifierAbstractVisitor extends AbstractVisitor {
     46 
     47     /**
     48      * The name of the variable for this visitor in the produced code.
     49      */
     50     protected String name;
     51 
     52     /**
     53      * The label names. This map associates String values to Label keys. It is
     54      * used only in ASMifierMethodVisitor.
     55      */
     56     HashMap labelNames;
     57 
     58     /**
     59      * Constructs a new {@link ASMifierAbstractVisitor}.
     60      *
     61      * @param name the name of the variable for this visitor in the produced
     62      *        code.
     63      */
     64     protected ASMifierAbstractVisitor(final String name) {
     65         this.name = name;
     66     }
     67 
     68     /**
     69      * Prints the ASM code that generates the given annotation.
     70      *
     71      * @param desc the class descriptor of the annotation class.
     72      * @param visible <tt>true</tt> if the annotation is visible at runtime.
     73      * @return a visitor to visit the annotation values.
     74      */
     75     public AnnotationVisitor visitAnnotation(
     76         final String desc,
     77         final boolean visible)
     78     {
     79         buf.setLength(0);
     80         buf.append("{\n")
     81                 .append("av0 = ")
     82                 .append(name)
     83                 .append(".visitAnnotation(");
     84         appendConstant(desc);
     85         buf.append(", ").append(visible).append(");\n");
     86         text.add(buf.toString());
     87         ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
     88         text.add(av.getText());
     89         text.add("}\n");
     90         return av;
     91     }
     92 
     93     /**
     94      * Prints the ASM code that generates the given extended annotation.
     95      *
     96      * @param desc the class descriptor of the annotation class.
     97      * @param visible <tt>true</tt> if the annotation is visible at runtime.
     98      * @return a visitor to visit the annotation values.
     99      */
    100     public TypeAnnotationVisitor visitTypeAnnotation(
    101         final String desc,
    102         final boolean visible,
    103         final boolean inCode)
    104     {
    105         buf.setLength(0);
    106         buf.append("{\n")
    107                 .append("xav0 = ")
    108                 .append(name)
    109                 .append(".visitTypeAnnotation(");
    110         appendConstant(desc);
    111         buf.append(", ").append(visible);
    112         buf.append(", ").append(inCode).append(");\n");
    113         text.add(buf.toString());
    114         ASMifierTypeAnnotationVisitor xav =
    115           new ASMifierTypeAnnotationVisitor(0);
    116         text.add(xav.getText());
    117         text.add("}\n");
    118         return xav;
    119     }
    120 
    121 
    122     /**
    123      * Prints the ASM code that generates the given attribute.
    124      *
    125      * @param attr an attribute.
    126      */
    127     public void visitAttribute(final Attribute attr) {
    128         buf.setLength(0);
    129         if (attr instanceof ASMifiable) {
    130             buf.append("{\n");
    131             buf.append("// ATTRIBUTE\n");
    132             ((ASMifiable) attr).asmify(buf, "attr", labelNames);
    133             buf.append(name).append(".visitAttribute(attr);\n");
    134             buf.append("}\n");
    135         } else {
    136             buf.append("// WARNING! skipped a non standard attribute of type \"");
    137             buf.append(attr.type).append("\"\n");
    138         }
    139         text.add(buf.toString());
    140     }
    141 
    142     /**
    143      * Prints the ASM code to end the visit.
    144      */
    145     public void visitEnd() {
    146         buf.setLength(0);
    147         buf.append(name).append(".visitEnd();\n");
    148         text.add(buf.toString());
    149     }
    150 
    151     /**
    152      * Appends a string representation of the given constant to the given
    153      * buffer.
    154      *
    155      * @param cst an {@link Integer}, {@link Float}, {@link Long},
    156      *        {@link Double} or {@link String} object. May be <tt>null</tt>.
    157      */
    158     void appendConstant(final Object cst) {
    159         appendConstant(buf, cst);
    160     }
    161 
    162     /**
    163      * Appends a string representation of the given constant to the given
    164      * buffer.
    165      *
    166      * @param buf a string buffer.
    167      * @param cst an {@link Integer}, {@link Float}, {@link Long},
    168      *        {@link Double} or {@link String} object. May be <tt>null</tt>.
    169      */
    170     static void appendConstant(final StringBuffer buf, final Object cst) {
    171         if (cst == null) {
    172             buf.append("null");
    173         } else if (cst instanceof String) {
    174             appendString(buf, (String) cst);
    175         } else if (cst instanceof Type) {
    176             buf.append("Type.getType(\"");
    177             buf.append(((Type) cst).getDescriptor());
    178             buf.append("\")");
    179         } else if (cst instanceof Byte) {
    180             buf.append("new Byte((byte)").append(cst).append(")");
    181         } else if (cst instanceof Boolean) {
    182             buf.append("new Boolean(").append(cst).append(")");
    183         } else if (cst instanceof Short) {
    184             buf.append("new Short((short)").append(cst).append(")");
    185         } else if (cst instanceof Character) {
    186             int c = ((Character) cst).charValue();
    187             buf.append("new Character((char)").append(c).append(")");
    188         } else if (cst instanceof Integer) {
    189             buf.append("new Integer(").append(cst).append(")");
    190         } else if (cst instanceof Float) {
    191             buf.append("new Float(\"").append(cst).append("\")");
    192         } else if (cst instanceof Long) {
    193             buf.append("new Long(").append(cst).append("L)");
    194         } else if (cst instanceof Double) {
    195             buf.append("new Double(\"").append(cst).append("\")");
    196         } else if (cst instanceof byte[]) {
    197             byte[] v = (byte[]) cst;
    198             buf.append("new byte[] {");
    199             for (int i = 0; i < v.length; i++) {
    200                 buf.append(i == 0 ? "" : ",").append(v[i]);
    201             }
    202             buf.append("}");
    203         } else if (cst instanceof boolean[]) {
    204             boolean[] v = (boolean[]) cst;
    205             buf.append("new boolean[] {");
    206             for (int i = 0; i < v.length; i++) {
    207                 buf.append(i == 0 ? "" : ",").append(v[i]);
    208             }
    209             buf.append("}");
    210         } else if (cst instanceof short[]) {
    211             short[] v = (short[]) cst;
    212             buf.append("new short[] {");
    213             for (int i = 0; i < v.length; i++) {
    214                 buf.append(i == 0 ? "" : ",").append("(short)").append(v[i]);
    215             }
    216             buf.append("}");
    217         } else if (cst instanceof char[]) {
    218             char[] v = (char[]) cst;
    219             buf.append("new char[] {");
    220             for (int i = 0; i < v.length; i++) {
    221                 buf.append(i == 0 ? "" : ",")
    222                         .append("(char)")
    223                         .append((int) v[i]);
    224             }
    225             buf.append("}");
    226         } else if (cst instanceof int[]) {
    227             int[] v = (int[]) cst;
    228             buf.append("new int[] {");
    229             for (int i = 0; i < v.length; i++) {
    230                 buf.append(i == 0 ? "" : ",").append(v[i]);
    231             }
    232             buf.append("}");
    233         } else if (cst instanceof long[]) {
    234             long[] v = (long[]) cst;
    235             buf.append("new long[] {");
    236             for (int i = 0; i < v.length; i++) {
    237                 buf.append(i == 0 ? "" : ",").append(v[i]).append("L");
    238             }
    239             buf.append("}");
    240         } else if (cst instanceof float[]) {
    241             float[] v = (float[]) cst;
    242             buf.append("new float[] {");
    243             for (int i = 0; i < v.length; i++) {
    244                 buf.append(i == 0 ? "" : ",").append(v[i]).append("f");
    245             }
    246             buf.append("}");
    247         } else if (cst instanceof double[]) {
    248             double[] v = (double[]) cst;
    249             buf.append("new double[] {");
    250             for (int i = 0; i < v.length; i++) {
    251                 buf.append(i == 0 ? "" : ",").append(v[i]).append("d");
    252             }
    253             buf.append("}");
    254         }
    255     }
    256 }
    257