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