AbstractVisitor.java revision 674060f01e9090cd21b3c5656cc3204912ad17a6
1/*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2007 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 */ 30package org.mockito.asm.util; 31 32import java.io.PrintWriter; 33import java.util.ArrayList; 34import java.util.List; 35 36import org.mockito.asm.Attribute; 37 38/** 39 * An abstract visitor. 40 * 41 * @author Eric Bruneton 42 */ 43public abstract class AbstractVisitor { 44 45 /** 46 * The names of the Java Virtual Machine opcodes. 47 */ 48 public static final String[] OPCODES; 49 /** 50 * Types for <code>operand</code> parameter of the 51 * {@link org.mockito.asm.MethodVisitor#visitIntInsn} method when 52 * <code>opcode</code> is <code>NEWARRAY</code>. 53 */ 54 public static final String[] TYPES; 55 56 static { 57 String s = "NOP,ACONST_NULL,ICONST_M1,ICONST_0,ICONST_1,ICONST_2," 58 + "ICONST_3,ICONST_4,ICONST_5,LCONST_0,LCONST_1,FCONST_0," 59 + "FCONST_1,FCONST_2,DCONST_0,DCONST_1,BIPUSH,SIPUSH,LDC,,," 60 + "ILOAD,LLOAD,FLOAD,DLOAD,ALOAD,,,,,,,,,,,,,,,,,,,,,IALOAD," 61 + "LALOAD,FALOAD,DALOAD,AALOAD,BALOAD,CALOAD,SALOAD,ISTORE," 62 + "LSTORE,FSTORE,DSTORE,ASTORE,,,,,,,,,,,,,,,,,,,,,IASTORE," 63 + "LASTORE,FASTORE,DASTORE,AASTORE,BASTORE,CASTORE,SASTORE,POP," 64 + "POP2,DUP,DUP_X1,DUP_X2,DUP2,DUP2_X1,DUP2_X2,SWAP,IADD,LADD," 65 + "FADD,DADD,ISUB,LSUB,FSUB,DSUB,IMUL,LMUL,FMUL,DMUL,IDIV,LDIV," 66 + "FDIV,DDIV,IREM,LREM,FREM,DREM,INEG,LNEG,FNEG,DNEG,ISHL,LSHL," 67 + "ISHR,LSHR,IUSHR,LUSHR,IAND,LAND,IOR,LOR,IXOR,LXOR,IINC,I2L," 68 + "I2F,I2D,L2I,L2F,L2D,F2I,F2L,F2D,D2I,D2L,D2F,I2B,I2C,I2S,LCMP," 69 + "FCMPL,FCMPG,DCMPL,DCMPG,IFEQ,IFNE,IFLT,IFGE,IFGT,IFLE," 70 + "IF_ICMPEQ,IF_ICMPNE,IF_ICMPLT,IF_ICMPGE,IF_ICMPGT,IF_ICMPLE," 71 + "IF_ACMPEQ,IF_ACMPNE,GOTO,JSR,RET,TABLESWITCH,LOOKUPSWITCH," 72 + "IRETURN,LRETURN,FRETURN,DRETURN,ARETURN,RETURN,GETSTATIC," 73 + "PUTSTATIC,GETFIELD,PUTFIELD,INVOKEVIRTUAL,INVOKESPECIAL," 74 + "INVOKESTATIC,INVOKEINTERFACE,,NEW,NEWARRAY,ANEWARRAY," 75 + "ARRAYLENGTH,ATHROW,CHECKCAST,INSTANCEOF,MONITORENTER," 76 + "MONITOREXIT,,MULTIANEWARRAY,IFNULL,IFNONNULL,"; 77 OPCODES = new String[200]; 78 int i = 0; 79 int j = 0; 80 int l; 81 while ((l = s.indexOf(',', j)) > 0) { 82 OPCODES[i++] = j + 1 == l ? null : s.substring(j, l); 83 j = l + 1; 84 } 85 86 s = "T_BOOLEAN,T_CHAR,T_FLOAT,T_DOUBLE,T_BYTE,T_SHORT,T_INT,T_LONG,"; 87 TYPES = new String[12]; 88 j = 0; 89 i = 4; 90 while ((l = s.indexOf(',', j)) > 0) { 91 TYPES[i++] = s.substring(j, l); 92 j = l + 1; 93 } 94 } 95 96 /** 97 * The text to be printed. Since the code of methods is not necessarily 98 * visited in sequential order, one method after the other, but can be 99 * interlaced (some instructions from method one, then some instructions 100 * from method two, then some instructions from method one again...), it is 101 * not possible to print the visited instructions directly to a sequential 102 * stream. A class is therefore printed in a two steps process: a string 103 * tree is constructed during the visit, and printed to a sequential stream 104 * at the end of the visit. This string tree is stored in this field, as a 105 * string list that can contain other string lists, which can themselves 106 * contain other string lists, and so on. 107 */ 108 public final List text; 109 110 /** 111 * A buffer that can be used to create strings. 112 */ 113 protected final StringBuffer buf; 114 115 /** 116 * Constructs a new {@link AbstractVisitor}. 117 */ 118 protected AbstractVisitor() { 119 this.text = new ArrayList(); 120 this.buf = new StringBuffer(); 121 } 122 123 /** 124 * Returns the text constructed by this visitor. 125 * 126 * @return the text constructed by this visitor. 127 */ 128 public List getText() { 129 return text; 130 } 131 132 /** 133 * Prints the text constructed by this visitor. 134 * 135 * @param pw the print writer to be used. 136 */ 137 public void print(final PrintWriter pw) { 138 printList(pw, text); 139 } 140 141 /** 142 * Appends a quoted string to a given buffer. 143 * 144 * @param buf the buffer where the string must be added. 145 * @param s the string to be added. 146 */ 147 public static void appendString(final StringBuffer buf, final String s) { 148 buf.append('\"'); 149 for (int i = 0; i < s.length(); ++i) { 150 char c = s.charAt(i); 151 if (c == '\n') { 152 buf.append("\\n"); 153 } else if (c == '\r') { 154 buf.append("\\r"); 155 } else if (c == '\\') { 156 buf.append("\\\\"); 157 } else if (c == '"') { 158 buf.append("\\\""); 159 } else if (c < 0x20 || c > 0x7f) { 160 buf.append("\\u"); 161 if (c < 0x10) { 162 buf.append("000"); 163 } else if (c < 0x100) { 164 buf.append("00"); 165 } else if (c < 0x1000) { 166 buf.append('0'); 167 } 168 buf.append(Integer.toString(c, 16)); 169 } else { 170 buf.append(c); 171 } 172 } 173 buf.append('\"'); 174 } 175 176 /** 177 * Prints the given string tree. 178 * 179 * @param pw the writer to be used to print the tree. 180 * @param l a string tree, i.e., a string list that can contain other string 181 * lists, and so on recursively. 182 */ 183 static void printList(final PrintWriter pw, final List l) { 184 for (int i = 0; i < l.size(); ++i) { 185 Object o = l.get(i); 186 if (o instanceof List) { 187 printList(pw, (List) o); 188 } else { 189 pw.print(o.toString()); 190 } 191 } 192 } 193 194 /** 195 * Returns the default {@link ASMifiable} prototypes. 196 * 197 * @return the default {@link ASMifiable} prototypes. 198 */ 199 public static Attribute[] getDefaultAttributes() { 200 return new Attribute[0]; 201 } 202} 203