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 org.drools.asm.util;
030:
031: import java.util.HashMap;
032:
033: import org.drools.asm.AnnotationVisitor;
034: import org.drools.asm.Label;
035: import org.drools.asm.MethodVisitor;
036: import org.drools.asm.Opcodes;
037:
038: /**
039: * A {@link MethodVisitor} that prints the ASM code that generates the methods
040: * it visits.
041: *
042: * @author Eric Bruneton
043: * @author Eugene Kuleshov
044: */
045: public class ASMifierMethodVisitor extends ASMifierAbstractVisitor
046: implements MethodVisitor {
047:
048: /**
049: * Constructs a new {@link ASMifierMethodVisitor} object.
050: */
051: public ASMifierMethodVisitor() {
052: super ("mv");
053: this .labelNames = new HashMap();
054: }
055:
056: public AnnotationVisitor visitAnnotationDefault() {
057: this .buf.setLength(0);
058: this .buf.append("{\n").append(
059: "av0 = mv.visitAnnotationDefault();\n");
060: this .text.add(this .buf.toString());
061: final ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(
062: 0);
063: this .text.add(av.getText());
064: this .text.add("}\n");
065: return av;
066: }
067:
068: public AnnotationVisitor visitParameterAnnotation(
069: final int parameter, final String desc,
070: final boolean visible) {
071: this .buf.setLength(0);
072: this .buf.append("{\n").append(
073: "av0 = mv.visitParameterAnnotation(").append(parameter)
074: .append(", ");
075: appendConstant(desc);
076: this .buf.append(", ").append(visible).append(");\n");
077: this .text.add(this .buf.toString());
078: final ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(
079: 0);
080: this .text.add(av.getText());
081: this .text.add("}\n");
082: return av;
083: }
084:
085: public void visitCode() {
086: this .text.add("mv.visitCode();\n");
087: }
088:
089: public void visitInsn(final int opcode) {
090: this .buf.setLength(0);
091: this .buf.append("mv.visitInsn(").append(
092: AbstractVisitor.OPCODES[opcode]).append(");\n");
093: this .text.add(this .buf.toString());
094: }
095:
096: public void visitIntInsn(final int opcode, final int operand) {
097: this .buf.setLength(0);
098: this .buf
099: .append("mv.visitIntInsn(")
100: .append(AbstractVisitor.OPCODES[opcode])
101: .append(", ")
102: .append(
103: opcode == Opcodes.NEWARRAY ? AbstractVisitor.TYPES[operand]
104: : Integer.toString(operand)).append(
105: ");\n");
106: this .text.add(this .buf.toString());
107: }
108:
109: public void visitVarInsn(final int opcode, final int var) {
110: this .buf.setLength(0);
111: this .buf.append("mv.visitVarInsn(").append(
112: AbstractVisitor.OPCODES[opcode]).append(", ").append(
113: var).append(");\n");
114: this .text.add(this .buf.toString());
115: }
116:
117: public void visitTypeInsn(final int opcode, final String desc) {
118: this .buf.setLength(0);
119: this .buf.append("mv.visitTypeInsn(").append(
120: AbstractVisitor.OPCODES[opcode]).append(", ");
121: appendConstant(desc);
122: this .buf.append(");\n");
123: this .text.add(this .buf.toString());
124: }
125:
126: public void visitFieldInsn(final int opcode, final String owner,
127: final String name, final String desc) {
128: this .buf.setLength(0);
129: this .buf.append("mv.visitFieldInsn(").append(
130: AbstractVisitor.OPCODES[opcode]).append(", ");
131: appendConstant(owner);
132: this .buf.append(", ");
133: appendConstant(name);
134: this .buf.append(", ");
135: appendConstant(desc);
136: this .buf.append(");\n");
137: this .text.add(this .buf.toString());
138: }
139:
140: public void visitMethodInsn(final int opcode, final String owner,
141: final String name, final String desc) {
142: this .buf.setLength(0);
143: this .buf.append("mv.visitMethodInsn(").append(
144: AbstractVisitor.OPCODES[opcode]).append(", ");
145: appendConstant(owner);
146: this .buf.append(", ");
147: appendConstant(name);
148: this .buf.append(", ");
149: appendConstant(desc);
150: this .buf.append(");\n");
151: this .text.add(this .buf.toString());
152: }
153:
154: public void visitJumpInsn(final int opcode, final Label label) {
155: this .buf.setLength(0);
156: declareLabel(label);
157: this .buf.append("mv.visitJumpInsn(").append(
158: AbstractVisitor.OPCODES[opcode]).append(", ");
159: appendLabel(label);
160: this .buf.append(");\n");
161: this .text.add(this .buf.toString());
162: }
163:
164: public void visitLabel(final Label label) {
165: this .buf.setLength(0);
166: declareLabel(label);
167: this .buf.append("mv.visitLabel(");
168: appendLabel(label);
169: this .buf.append(");\n");
170: this .text.add(this .buf.toString());
171: }
172:
173: public void visitLdcInsn(final Object cst) {
174: this .buf.setLength(0);
175: this .buf.append("mv.visitLdcInsn(");
176: appendConstant(cst);
177: this .buf.append(");\n");
178: this .text.add(this .buf.toString());
179: }
180:
181: public void visitIincInsn(final int var, final int increment) {
182: this .buf.setLength(0);
183: this .buf.append("mv.visitIincInsn(").append(var).append(", ")
184: .append(increment).append(");\n");
185: this .text.add(this .buf.toString());
186: }
187:
188: public void visitTableSwitchInsn(final int min, final int max,
189: final Label dflt, final Label labels[]) {
190: this .buf.setLength(0);
191: for (int i = 0; i < labels.length; ++i) {
192: declareLabel(labels[i]);
193: }
194: declareLabel(dflt);
195:
196: this .buf.append("mv.visitTableSwitchInsn(").append(min).append(
197: ", ").append(max).append(", ");
198: appendLabel(dflt);
199: this .buf.append(", new Label[] {");
200: for (int i = 0; i < labels.length; ++i) {
201: this .buf.append(i == 0 ? " " : ", ");
202: appendLabel(labels[i]);
203: }
204: this .buf.append(" });\n");
205: this .text.add(this .buf.toString());
206: }
207:
208: public void visitLookupSwitchInsn(final Label dflt,
209: final int keys[], final Label labels[]) {
210: this .buf.setLength(0);
211: for (int i = 0; i < labels.length; ++i) {
212: declareLabel(labels[i]);
213: }
214: declareLabel(dflt);
215:
216: this .buf.append("mv.visitLookupSwitchInsn(");
217: appendLabel(dflt);
218: this .buf.append(", new int[] {");
219: for (int i = 0; i < keys.length; ++i) {
220: this .buf.append(i == 0 ? " " : ", ").append(keys[i]);
221: }
222: this .buf.append(" }, new Label[] {");
223: for (int i = 0; i < labels.length; ++i) {
224: this .buf.append(i == 0 ? " " : ", ");
225: appendLabel(labels[i]);
226: }
227: this .buf.append(" });\n");
228: this .text.add(this .buf.toString());
229: }
230:
231: public void visitMultiANewArrayInsn(final String desc,
232: final int dims) {
233: this .buf.setLength(0);
234: this .buf.append("mv.visitMultiANewArrayInsn(");
235: appendConstant(desc);
236: this .buf.append(", ").append(dims).append(");\n");
237: this .text.add(this .buf.toString());
238: }
239:
240: public void visitTryCatchBlock(final Label start, final Label end,
241: final Label handler, final String type) {
242: this .buf.setLength(0);
243: declareLabel(start);
244: declareLabel(end);
245: declareLabel(handler);
246: this .buf.append("mv.visitTryCatchBlock(");
247: appendLabel(start);
248: this .buf.append(", ");
249: appendLabel(end);
250: this .buf.append(", ");
251: appendLabel(handler);
252: this .buf.append(", ");
253: appendConstant(type);
254: this .buf.append(");\n");
255: this .text.add(this .buf.toString());
256: }
257:
258: public void visitLocalVariable(final String name,
259: final String desc, final String signature,
260: final Label start, final Label end, final int index) {
261: this .buf.setLength(0);
262: this .buf.append("mv.visitLocalVariable(");
263: appendConstant(name);
264: this .buf.append(", ");
265: appendConstant(desc);
266: this .buf.append(", ");
267: appendConstant(signature);
268: this .buf.append(", ");
269: appendLabel(start);
270: this .buf.append(", ");
271: appendLabel(end);
272: this .buf.append(", ").append(index).append(");\n");
273: this .text.add(this .buf.toString());
274: }
275:
276: public void visitLineNumber(final int line, final Label start) {
277: this .buf.setLength(0);
278: this .buf.append("mv.visitLineNumber(").append(line)
279: .append(", ");
280: appendLabel(start);
281: this .buf.append(");\n");
282: this .text.add(this .buf.toString());
283: }
284:
285: public void visitMaxs(final int maxStack, final int maxLocals) {
286: this .buf.setLength(0);
287: this .buf.append("mv.visitMaxs(").append(maxStack).append(", ")
288: .append(maxLocals).append(");\n");
289: this .text.add(this .buf.toString());
290: }
291:
292: /**
293: * Appends a declaration of the given label to {@link #buf buf}. This
294: * declaration is of the form "Label lXXX = new Label();". Does nothing if
295: * the given label has already been declared.
296: *
297: * @param l a label.
298: */
299: private void declareLabel(final Label l) {
300: String name = (String) this .labelNames.get(l);
301: if (name == null) {
302: name = "l" + this .labelNames.size();
303: this .labelNames.put(l, name);
304: this .buf.append("Label ").append(name).append(
305: " = new Label();\n");
306: }
307: }
308:
309: /**
310: * Appends the name of the given label to {@link #buf buf}. The given label
311: * <i>must</i> already have a name. One way to ensure this is to always
312: * call {@link #declareLabel declared} before calling this method.
313: *
314: * @param l a label.
315: */
316: private void appendLabel(final Label l) {
317: this .buf.append((String) this.labelNames.get(l));
318: }
319: }
|