001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (c) 2000-2005 INRIA, France Telecom
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: * 2. Redistributions in binary form must reproduce the above copyright
012: * notice, this list of conditions and the following disclaimer in the
013: * documentation and/or other materials provided with the distribution.
014: * 3. Neither the name of the copyright holders nor the names of its
015: * contributors may be used to endorse or promote products derived from
016: * this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028: * THE POSSIBILITY OF SUCH DAMAGE.
029: */package com.tc.asm.util;
030:
031: import java.util.HashMap;
032:
033: import com.tc.asm.AnnotationVisitor;
034: import com.tc.asm.Attribute;
035: import com.tc.asm.Type;
036:
037: /**
038: * An abstract ASMifier visitor.
039: *
040: * @author Eric Bruneton
041: */
042: public class ASMifierAbstractVisitor extends AbstractVisitor {
043:
044: /**
045: * The name of the variable for this visitor in the produced code.
046: */
047: protected String name;
048:
049: /**
050: * The label names. This map associates String values to Label keys. It is
051: * used only in ASMifierMethodVisitor.
052: */
053: HashMap labelNames;
054:
055: /**
056: * Constructs a new {@link ASMifierAbstractVisitor}.
057: *
058: * @param name the name of the variable for this visitor in the produced
059: * code.
060: */
061: protected ASMifierAbstractVisitor(final String name) {
062: this .name = name;
063: }
064:
065: /**
066: * Prints the ASM code that generates the given annotation.
067: *
068: * @param desc the class descriptor of the annotation class.
069: * @param visible <tt>true</tt> if the annotation is visible at runtime.
070: * @return a visitor to visit the annotation values.
071: */
072: public AnnotationVisitor visitAnnotation(final String desc,
073: final boolean visible) {
074: buf.setLength(0);
075: buf.append("{\n").append("av0 = ").append(name).append(
076: ".visitAnnotation(");
077: appendConstant(desc);
078: buf.append(", ").append(visible).append(");\n");
079: text.add(buf.toString());
080: ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
081: text.add(av.getText());
082: text.add("}\n");
083: return av;
084: }
085:
086: /**
087: * Prints the ASM code that generates the given attribute.
088: *
089: * @param attr an attribute.
090: */
091: public void visitAttribute(final Attribute attr) {
092: buf.setLength(0);
093: buf.append("// ATTRIBUTE ").append(attr.type).append("\n");
094: if (attr instanceof ASMifiable) {
095: buf.append("{\n");
096: ((ASMifiable) attr).asmify(buf, "attr", labelNames);
097: buf.append(name).append(".visitAttribute(attr);\n");
098: buf.append("}\n");
099: }
100: text.add(buf.toString());
101: }
102:
103: /**
104: * Prints the ASM code to end the visit.
105: */
106: public void visitEnd() {
107: buf.setLength(0);
108: buf.append(name).append(".visitEnd();\n");
109: text.add(buf.toString());
110: }
111:
112: /**
113: * Appends a string representation of the given constant to the given
114: * buffer.
115: *
116: * @param cst an {@link Integer}, {@link Float}, {@link Long},
117: * {@link Double} or {@link String} object. May be <tt>null</tt>.
118: */
119: void appendConstant(final Object cst) {
120: appendConstant(buf, cst);
121: }
122:
123: /**
124: * Appends a string representation of the given constant to the given
125: * buffer.
126: *
127: * @param buf a string buffer.
128: * @param cst an {@link Integer}, {@link Float}, {@link Long},
129: * {@link Double} or {@link String} object. May be <tt>null</tt>.
130: */
131: static void appendConstant(final StringBuffer buf, final Object cst) {
132: if (cst == null) {
133: buf.append("null");
134: } else if (cst instanceof String) {
135: appendString(buf, (String) cst);
136: } else if (cst instanceof Type) {
137: buf.append("Type.getType(\"");
138: buf.append(((Type) cst).getDescriptor());
139: buf.append("\")");
140: } else if (cst instanceof Byte) {
141: buf.append("new Byte((byte)").append(cst).append(')');
142: } else if (cst instanceof Boolean) {
143: buf.append(((Boolean) cst).booleanValue() ? "Boolean.TRUE"
144: : "Boolean.FALSE");
145: } else if (cst instanceof Short) {
146: buf.append("new Short((short)").append(cst).append(')');
147: } else if (cst instanceof Character) {
148: int c = ((Character) cst).charValue();
149: buf.append("new Character((char)").append(c).append(')');
150: } else if (cst instanceof Integer) {
151: buf.append("new Integer(").append(cst).append(')');
152: } else if (cst instanceof Float) {
153: buf.append("new Float(\"").append(cst).append("\")");
154: } else if (cst instanceof Long) {
155: buf.append("new Long(").append(cst).append("L)");
156: } else if (cst instanceof Double) {
157: buf.append("new Double(\"").append(cst).append("\")");
158: } else if (cst instanceof byte[]) {
159: byte[] v = (byte[]) cst;
160: buf.append("new byte[] {");
161: for (int i = 0; i < v.length; i++) {
162: buf.append(i == 0 ? "" : ",").append(v[i]);
163: }
164: buf.append('}');
165: } else if (cst instanceof boolean[]) {
166: boolean[] v = (boolean[]) cst;
167: buf.append("new boolean[] {");
168: for (int i = 0; i < v.length; i++) {
169: buf.append(i == 0 ? "" : ",").append(v[i]);
170: }
171: buf.append('}');
172: } else if (cst instanceof short[]) {
173: short[] v = (short[]) cst;
174: buf.append("new short[] {");
175: for (int i = 0; i < v.length; i++) {
176: buf.append(i == 0 ? "" : ",").append("(short)").append(
177: v[i]);
178: }
179: buf.append('}');
180: } else if (cst instanceof char[]) {
181: char[] v = (char[]) cst;
182: buf.append("new char[] {");
183: for (int i = 0; i < v.length; i++) {
184: buf.append(i == 0 ? "" : ",").append("(char)").append(
185: (int) v[i]);
186: }
187: buf.append('}');
188: } else if (cst instanceof int[]) {
189: int[] v = (int[]) cst;
190: buf.append("new int[] {");
191: for (int i = 0; i < v.length; i++) {
192: buf.append(i == 0 ? "" : ",").append(v[i]);
193: }
194: buf.append('}');
195: } else if (cst instanceof long[]) {
196: long[] v = (long[]) cst;
197: buf.append("new long[] {");
198: for (int i = 0; i < v.length; i++) {
199: buf.append(i == 0 ? "" : ",").append(v[i]).append('L');
200: }
201: buf.append('}');
202: } else if (cst instanceof float[]) {
203: float[] v = (float[]) cst;
204: buf.append("new float[] {");
205: for (int i = 0; i < v.length; i++) {
206: buf.append(i == 0 ? "" : ",").append(v[i]).append('f');
207: }
208: buf.append('}');
209: } else if (cst instanceof double[]) {
210: double[] v = (double[]) cst;
211: buf.append("new double[] {");
212: for (int i = 0; i < v.length; i++) {
213: buf.append(i == 0 ? "" : ",").append(v[i]).append('d');
214: }
215: buf.append('}');
216: }
217: }
218: }
|