001: /***
002: * ASM XML Adapter
003: * Copyright (c) 2004, Eugene Kuleshov
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.ejb3unit.asm.xml;
030:
031: import java.util.HashMap;
032: import java.util.Map;
033:
034: import org.ejb3unit.asm.AnnotationVisitor;
035: import org.ejb3unit.asm.Attribute;
036: import org.ejb3unit.asm.Label;
037: import org.ejb3unit.asm.MethodVisitor;
038: import org.ejb3unit.asm.Opcodes;
039: import org.ejb3unit.asm.Type;
040: import org.ejb3unit.asm.util.AbstractVisitor;
041: import org.xml.sax.ContentHandler;
042: import org.xml.sax.helpers.AttributesImpl;
043:
044: /**
045: * A {@link MethodVisitor} that generates SAX 2.0 events from the visited
046: * method.
047: *
048: * @see org.ejb3unit.asm.xml.SAXClassAdapter
049: * @see org.ejb3unit.asm.xml.Processor
050: *
051: * @author Eugene Kuleshov
052: */
053: public final class SAXCodeAdapter extends SAXAdapter implements
054: MethodVisitor {
055:
056: static String[] TYPES = { "top", "int", "float", "double", "long",
057: "null", "uninitializedThis" };
058:
059: private Map labelNames;
060:
061: /**
062: * Constructs a new {@link SAXCodeAdapter SAXCodeAdapter} object.
063: *
064: * @param h content handler that will be used to send SAX 2.0 events.
065: * @param access
066: */
067: public SAXCodeAdapter(final ContentHandler h, final int access) {
068: super (h);
069: labelNames = new HashMap();
070:
071: if ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_NATIVE)) == 0) {
072: addStart("code", new AttributesImpl());
073: }
074: }
075:
076: public final void visitCode() {
077: }
078:
079: public void visitFrame(final int type, final int nLocal,
080: final Object[] local, final int nStack, final Object[] stack) {
081: AttributesImpl attrs = new AttributesImpl();
082: switch (type) {
083: case Opcodes.F_NEW:
084: case Opcodes.F_FULL:
085: if (type == Opcodes.F_NEW) {
086: attrs.addAttribute("", "type", "type", "", "NEW");
087: } else {
088: attrs.addAttribute("", "type", "type", "", "FULL");
089: }
090: addStart("frame", attrs);
091: appendFrameTypes(true, nLocal, local);
092: appendFrameTypes(false, nStack, stack);
093: break;
094: case Opcodes.F_APPEND:
095: attrs.addAttribute("", "type", "type", "", "APPEND");
096: addStart("frame", attrs);
097: appendFrameTypes(true, nLocal, local);
098: break;
099: case Opcodes.F_CHOP:
100: attrs.addAttribute("", "type", "type", "", "CHOP");
101: attrs.addAttribute("", "count", "count", "", Integer
102: .toString(nLocal));
103: addStart("frame", attrs);
104: break;
105: case Opcodes.F_SAME:
106: attrs.addAttribute("", "type", "type", "", "SAME");
107: addStart("frame", attrs);
108: break;
109: case Opcodes.F_SAME1:
110: attrs.addAttribute("", "type", "type", "", "SAME1");
111: addStart("frame", attrs);
112: appendFrameTypes(false, 1, stack);
113: break;
114: }
115: addEnd("frame");
116: }
117:
118: private void appendFrameTypes(final boolean local, final int n,
119: final Object[] types) {
120: for (int i = 0; i < n; ++i) {
121: Object type = types[i];
122: AttributesImpl attrs = new AttributesImpl();
123: if (type instanceof String) {
124: attrs.addAttribute("", "type", "type", "",
125: (String) type);
126: } else if (type instanceof Integer) {
127: attrs.addAttribute("", "type", "type", "",
128: TYPES[((Integer) type).intValue()]);
129: } else {
130: attrs.addAttribute("", "type", "type", "",
131: "uninitialized");
132: attrs.addAttribute("", "label", "label", "",
133: getLabel((Label) type));
134: }
135: addElement(local ? "local" : "stack", attrs);
136: }
137: }
138:
139: public final void visitInsn(final int opcode) {
140: addElement(AbstractVisitor.OPCODES[opcode],
141: new AttributesImpl());
142: }
143:
144: public final void visitIntInsn(final int opcode, final int operand) {
145: AttributesImpl attrs = new AttributesImpl();
146: attrs.addAttribute("", "value", "value", "", Integer
147: .toString(operand));
148: addElement(AbstractVisitor.OPCODES[opcode], attrs);
149: }
150:
151: public final void visitVarInsn(final int opcode, final int var) {
152: AttributesImpl attrs = new AttributesImpl();
153: attrs.addAttribute("", "var", "var", "", Integer.toString(var));
154: addElement(AbstractVisitor.OPCODES[opcode], attrs);
155: }
156:
157: public final void visitTypeInsn(final int opcode, final String desc) {
158: AttributesImpl attrs = new AttributesImpl();
159: attrs.addAttribute("", "desc", "desc", "", desc);
160: addElement(AbstractVisitor.OPCODES[opcode], attrs);
161: }
162:
163: public final void visitFieldInsn(final int opcode,
164: final String owner, final String name, final String desc) {
165: AttributesImpl attrs = new AttributesImpl();
166: attrs.addAttribute("", "owner", "owner", "", owner);
167: attrs.addAttribute("", "name", "name", "", name);
168: attrs.addAttribute("", "desc", "desc", "", desc);
169: addElement(AbstractVisitor.OPCODES[opcode], attrs);
170: }
171:
172: public final void visitMethodInsn(final int opcode,
173: final String owner, final String name, final String desc) {
174: AttributesImpl attrs = new AttributesImpl();
175: attrs.addAttribute("", "owner", "owner", "", owner);
176: attrs.addAttribute("", "name", "name", "", name);
177: attrs.addAttribute("", "desc", "desc", "", desc);
178: addElement(AbstractVisitor.OPCODES[opcode], attrs);
179: }
180:
181: public final void visitJumpInsn(final int opcode, final Label label) {
182: AttributesImpl attrs = new AttributesImpl();
183: attrs.addAttribute("", "label", "label", "", getLabel(label));
184: addElement(AbstractVisitor.OPCODES[opcode], attrs);
185: }
186:
187: public final void visitLabel(final Label label) {
188: AttributesImpl attrs = new AttributesImpl();
189: attrs.addAttribute("", "name", "name", "", getLabel(label));
190: addElement("Label", attrs);
191: }
192:
193: public final void visitLdcInsn(final Object cst) {
194: AttributesImpl attrs = new AttributesImpl();
195: attrs.addAttribute("", "cst", "cst", "", SAXClassAdapter
196: .encode(cst.toString()));
197: attrs.addAttribute("", "desc", "desc", "", Type
198: .getDescriptor(cst.getClass()));
199: addElement(AbstractVisitor.OPCODES[Opcodes.LDC], attrs);
200: }
201:
202: public final void visitIincInsn(final int var, final int increment) {
203: AttributesImpl attrs = new AttributesImpl();
204: attrs.addAttribute("", "var", "var", "", Integer.toString(var));
205: attrs.addAttribute("", "inc", "inc", "", Integer
206: .toString(increment));
207: addElement(AbstractVisitor.OPCODES[Opcodes.IINC], attrs);
208: }
209:
210: public final void visitTableSwitchInsn(final int min,
211: final int max, final Label dflt, final Label[] labels) {
212: AttributesImpl attrs = new AttributesImpl();
213: attrs.addAttribute("", "min", "min", "", Integer.toString(min));
214: attrs.addAttribute("", "max", "max", "", Integer.toString(max));
215: attrs.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
216: String o = AbstractVisitor.OPCODES[Opcodes.TABLESWITCH];
217: addStart(o, attrs);
218: for (int i = 0; i < labels.length; i++) {
219: AttributesImpl att2 = new AttributesImpl();
220: att2.addAttribute("", "name", "name", "",
221: getLabel(labels[i]));
222: addElement("label", att2);
223: }
224: addEnd(o);
225: }
226:
227: public final void visitLookupSwitchInsn(final Label dflt,
228: final int[] keys, final Label[] labels) {
229: AttributesImpl att = new AttributesImpl();
230: att.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
231: String o = AbstractVisitor.OPCODES[Opcodes.LOOKUPSWITCH];
232: addStart(o, att);
233: for (int i = 0; i < labels.length; i++) {
234: AttributesImpl att2 = new AttributesImpl();
235: att2.addAttribute("", "name", "name", "",
236: getLabel(labels[i]));
237: att2.addAttribute("", "key", "key", "", Integer
238: .toString(keys[i]));
239: addElement("label", att2);
240: }
241: addEnd(o);
242: }
243:
244: public final void visitMultiANewArrayInsn(final String desc,
245: final int dims) {
246: AttributesImpl attrs = new AttributesImpl();
247: attrs.addAttribute("", "desc", "desc", "", desc);
248: attrs.addAttribute("", "dims", "dims", "", Integer
249: .toString(dims));
250: addElement(AbstractVisitor.OPCODES[Opcodes.MULTIANEWARRAY],
251: attrs);
252: }
253:
254: public final void visitTryCatchBlock(final Label start,
255: final Label end, final Label handler, final String type) {
256: AttributesImpl attrs = new AttributesImpl();
257: attrs.addAttribute("", "start", "start", "", getLabel(start));
258: attrs.addAttribute("", "end", "end", "", getLabel(end));
259: attrs.addAttribute("", "handler", "handler", "",
260: getLabel(handler));
261: if (type != null) {
262: attrs.addAttribute("", "type", "type", "", type);
263: }
264: addElement("TryCatch", attrs);
265: }
266:
267: public final void visitMaxs(final int maxStack, final int maxLocals) {
268: AttributesImpl attrs = new AttributesImpl();
269: attrs.addAttribute("", "maxStack", "maxStack", "", Integer
270: .toString(maxStack));
271: attrs.addAttribute("", "maxLocals", "maxLocals", "", Integer
272: .toString(maxLocals));
273: addElement("Max", attrs);
274:
275: addEnd("code");
276: }
277:
278: public void visitLocalVariable(final String name,
279: final String desc, final String signature,
280: final Label start, final Label end, final int index) {
281: AttributesImpl attrs = new AttributesImpl();
282: attrs.addAttribute("", "name", "name", "", name);
283: attrs.addAttribute("", "desc", "desc", "", desc);
284: if (signature != null) {
285: attrs.addAttribute("", "signature", "signature", "",
286: SAXClassAdapter.encode(signature));
287: }
288: attrs.addAttribute("", "start", "start", "", getLabel(start));
289: attrs.addAttribute("", "end", "end", "", getLabel(end));
290: attrs.addAttribute("", "var", "var", "", Integer
291: .toString(index));
292: addElement("LocalVar", attrs);
293: }
294:
295: public final void visitLineNumber(final int line, final Label start) {
296: AttributesImpl attrs = new AttributesImpl();
297: attrs.addAttribute("", "line", "line", "", Integer
298: .toString(line));
299: attrs.addAttribute("", "start", "start", "", getLabel(start));
300: addElement("LineNumber", attrs);
301: }
302:
303: public AnnotationVisitor visitAnnotationDefault() {
304: return new SAXAnnotationAdapter(getContentHandler(),
305: "annotationDefault", 0, null, null);
306: }
307:
308: public AnnotationVisitor visitAnnotation(final String desc,
309: final boolean visible) {
310: return new SAXAnnotationAdapter(getContentHandler(),
311: "annotation", visible ? 1 : -1, null, desc);
312: }
313:
314: public AnnotationVisitor visitParameterAnnotation(
315: final int parameter, final String desc,
316: final boolean visible) {
317: return new SAXAnnotationAdapter(getContentHandler(),
318: "parameterAnnotation", visible ? 1 : -1, parameter,
319: desc);
320: }
321:
322: public void visitEnd() {
323: addEnd("method");
324: }
325:
326: public final void visitAttribute(final Attribute attr) {
327: // TODO Auto-generated SAXCodeAdapter.visitAttribute
328: }
329:
330: private final String getLabel(final Label label) {
331: String name = (String) labelNames.get(label);
332: if (name == null) {
333: name = Integer.toString(labelNames.size());
334: labelNames.put(label, name);
335: }
336: return name;
337: }
338:
339: }
|