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 org.ejb3unit.asm.AnnotationVisitor;
032: import org.ejb3unit.asm.Attribute;
033: import org.ejb3unit.asm.ClassVisitor;
034: import org.ejb3unit.asm.FieldVisitor;
035: import org.ejb3unit.asm.MethodVisitor;
036: import org.ejb3unit.asm.Opcodes;
037: import org.xml.sax.ContentHandler;
038: import org.xml.sax.helpers.AttributesImpl;
039:
040: /**
041: * A {@link org.ejb3unit.asm.ClassVisitor ClassVisitor} that generates SAX 2.0
042: * events from the visited class. It can feed any kind of
043: * {@link org.xml.sax.ContentHandler ContentHandler}, e.g. XML serializer, XSLT
044: * or XQuery engines.
045: *
046: * @see org.ejb3unit.asm.xml.Processor
047: * @see org.ejb3unit.asm.xml.ASMContentHandler
048: *
049: * @author Eugene Kuleshov
050: */
051: public final class SAXClassAdapter extends SAXAdapter implements
052: ClassVisitor {
053: private boolean singleDocument;
054:
055: /**
056: * Pseudo access flag used to distinguish class access flags.
057: */
058: private final static int ACCESS_CLASS = 262144;
059:
060: /**
061: * Pseudo access flag used to distinguish field access flags.
062: */
063: private final static int ACCESS_FIELD = 524288;
064:
065: /**
066: * Pseudo access flag used to distinguish inner class flags.
067: */
068: private static final int ACCESS_INNER = 1048576;
069:
070: /**
071: * Constructs a new {@link SAXClassAdapter SAXClassAdapter} object.
072: *
073: * @param h content handler that will be used to send SAX 2.0 events.
074: * @param singleDocument if <tt>true</tt> adapter will not produce
075: * {@link ContentHandler#startDocument() startDocument()} and
076: * {@link ContentHandler#endDocument() endDocument()} events.
077: */
078: public SAXClassAdapter(final ContentHandler h,
079: boolean singleDocument) {
080: super (h);
081: this .singleDocument = singleDocument;
082: if (!singleDocument) {
083: addDocumentStart();
084: }
085: }
086:
087: public void visitSource(final String source, final String debug) {
088: AttributesImpl att = new AttributesImpl();
089: if (source != null) {
090: att.addAttribute("", "file", "file", "", encode(source));
091: }
092: if (debug != null) {
093: att.addAttribute("", "debug", "debug", "", encode(debug));
094: }
095:
096: addElement("source", att);
097: }
098:
099: public void visitOuterClass(final String owner, final String name,
100: final String desc) {
101: AttributesImpl att = new AttributesImpl();
102: att.addAttribute("", "owner", "owner", "", owner);
103: if (name != null) {
104: att.addAttribute("", "name", "name", "", name);
105: }
106: if (desc != null) {
107: att.addAttribute("", "desc", "desc", "", desc);
108: }
109:
110: addElement("outerclass", att);
111: }
112:
113: public final void visitAttribute(final Attribute attr) {
114: // TODO Auto-generated SAXClassAdapter.visitAttribute
115: }
116:
117: public AnnotationVisitor visitAnnotation(final String desc,
118: final boolean visible) {
119: return new SAXAnnotationAdapter(getContentHandler(),
120: "annotation", visible ? 1 : -1, null, desc);
121: }
122:
123: public void visit(final int version, final int access,
124: final String name, final String signature,
125: final String super Name, final String[] interfaces) {
126: StringBuffer sb = new StringBuffer();
127: appendAccess(access | ACCESS_CLASS, sb);
128:
129: AttributesImpl att = new AttributesImpl();
130: att.addAttribute("", "access", "access", "", sb.toString());
131: if (name != null) {
132: att.addAttribute("", "name", "name", "", name);
133: }
134: if (signature != null) {
135: att.addAttribute("", "signature", "signature", "",
136: encode(signature));
137: }
138: if (super Name != null) {
139: att.addAttribute("", "parent", "parent", "", super Name);
140: }
141: att.addAttribute("", "major", "major", "", Integer
142: .toString(version & 0xFFFF));
143: att.addAttribute("", "minor", "minor", "", Integer
144: .toString(version >>> 16));
145: addStart("class", att);
146:
147: addStart("interfaces", new AttributesImpl());
148: if (interfaces != null && interfaces.length > 0) {
149: for (int i = 0; i < interfaces.length; i++) {
150: AttributesImpl att2 = new AttributesImpl();
151: att2
152: .addAttribute("", "name", "name", "",
153: interfaces[i]);
154: addElement("interface", att2);
155: }
156: }
157: addEnd("interfaces");
158: }
159:
160: public FieldVisitor visitField(final int access, final String name,
161: final String desc, final String signature,
162: final Object value) {
163: StringBuffer sb = new StringBuffer();
164: appendAccess(access | ACCESS_FIELD, sb);
165:
166: AttributesImpl att = new AttributesImpl();
167: att.addAttribute("", "access", "access", "", sb.toString());
168: att.addAttribute("", "name", "name", "", name);
169: att.addAttribute("", "desc", "desc", "", desc);
170: if (signature != null) {
171: att.addAttribute("", "signature", "signature", "",
172: encode(signature));
173: }
174: if (value != null) {
175: att.addAttribute("", "value", "value", "", encode(value
176: .toString()));
177: }
178:
179: return new SAXFieldAdapter(getContentHandler(), att);
180: }
181:
182: public MethodVisitor visitMethod(final int access,
183: final String name, final String desc,
184: final String signature, final String[] exceptions) {
185: StringBuffer sb = new StringBuffer();
186: appendAccess(access, sb);
187:
188: AttributesImpl att = new AttributesImpl();
189: att.addAttribute("", "access", "access", "", sb.toString());
190: att.addAttribute("", "name", "name", "", name);
191: att.addAttribute("", "desc", "desc", "", desc);
192: if (signature != null) {
193: att.addAttribute("", "signature", "signature", "",
194: signature);
195: }
196: addStart("method", att);
197:
198: addStart("exceptions", new AttributesImpl());
199: if (exceptions != null && exceptions.length > 0) {
200: for (int i = 0; i < exceptions.length; i++) {
201: AttributesImpl att2 = new AttributesImpl();
202: att2
203: .addAttribute("", "name", "name", "",
204: exceptions[i]);
205: addElement("exception", att2);
206: }
207: }
208: addEnd("exceptions");
209:
210: return new SAXCodeAdapter(getContentHandler(), access);
211: }
212:
213: public final void visitInnerClass(final String name,
214: final String outerName, final String innerName,
215: final int access) {
216: StringBuffer sb = new StringBuffer();
217: appendAccess(access | ACCESS_INNER, sb);
218:
219: AttributesImpl att = new AttributesImpl();
220: att.addAttribute("", "access", "access", "", sb.toString());
221: if (name != null) {
222: att.addAttribute("", "name", "name", "", name);
223: }
224: if (outerName != null) {
225: att.addAttribute("", "outerName", "outerName", "",
226: outerName);
227: }
228: if (innerName != null) {
229: att.addAttribute("", "innerName", "innerName", "",
230: innerName);
231: }
232: addElement("innerclass", att);
233: }
234:
235: public final void visitEnd() {
236: addEnd("class");
237: if (!singleDocument) {
238: addDocumentEnd();
239: }
240: }
241:
242: static final String encode(final String s) {
243: StringBuffer sb = new StringBuffer();
244: for (int i = 0; i < s.length(); i++) {
245: char c = s.charAt(i);
246: if (c == '\\') {
247: sb.append("\\\\");
248: } else if (c < 0x20 || c > 0x7f) {
249: sb.append("\\u");
250: if (c < 0x10) {
251: sb.append("000");
252: } else if (c < 0x100) {
253: sb.append("00");
254: } else if (c < 0x1000) {
255: sb.append('0');
256: }
257: sb.append(Integer.toString(c, 16));
258: } else {
259: sb.append(c);
260: }
261: }
262: return sb.toString();
263: }
264:
265: static void appendAccess(final int access, final StringBuffer sb) {
266: if ((access & Opcodes.ACC_PUBLIC) != 0) {
267: sb.append("public ");
268: }
269: if ((access & Opcodes.ACC_PRIVATE) != 0) {
270: sb.append("private ");
271: }
272: if ((access & Opcodes.ACC_PROTECTED) != 0) {
273: sb.append("protected ");
274: }
275: if ((access & Opcodes.ACC_FINAL) != 0) {
276: sb.append("final ");
277: }
278: if ((access & Opcodes.ACC_STATIC) != 0) {
279: sb.append("static ");
280: }
281: if ((access & Opcodes.ACC_SUPER) != 0) {
282: if ((access & ACCESS_CLASS) != 0) {
283: sb.append("super ");
284: } else {
285: sb.append("synchronized ");
286: }
287: }
288: if ((access & Opcodes.ACC_VOLATILE) != 0) {
289: if ((access & ACCESS_FIELD) != 0) {
290: sb.append("volatile ");
291: } else {
292: sb.append("bridge ");
293: }
294: }
295: if ((access & Opcodes.ACC_TRANSIENT) != 0) {
296: if ((access & ACCESS_FIELD) != 0) {
297: sb.append("transient ");
298: } else {
299: sb.append("varargs ");
300: }
301: }
302: if ((access & Opcodes.ACC_NATIVE) != 0) {
303: sb.append("native ");
304: }
305: if ((access & Opcodes.ACC_STRICT) != 0) {
306: sb.append("strict ");
307: }
308: if ((access & Opcodes.ACC_INTERFACE) != 0) {
309: sb.append("interface ");
310: }
311: if ((access & Opcodes.ACC_ABSTRACT) != 0) {
312: sb.append("abstract ");
313: }
314: if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
315: sb.append("synthetic ");
316: }
317: if ((access & Opcodes.ACC_ANNOTATION) != 0) {
318: sb.append("annotation ");
319: }
320: if ((access & Opcodes.ACC_ENUM) != 0) {
321: sb.append("enum ");
322: }
323: if ((access & Opcodes.ACC_DEPRECATED) != 0) {
324: sb.append("deprecated ");
325: }
326: }
327: }
|