1 /***
2  * ASM XML Adapter
3  * Copyright (c) 2004, Eugene Kuleshov
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  *    contributors may be used to endorse or promote products derived from
16  *    this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 package org.objectweb.asm.xml;
31 
32 import org.objectweb.asm.AnnotationVisitor;
33 import org.objectweb.asm.Attribute;
34 import org.objectweb.asm.ClassVisitor;
35 import org.objectweb.asm.FieldVisitor;
36 import org.objectweb.asm.MethodVisitor;
37 import org.objectweb.asm.Opcodes;
38 import org.xml.sax.ContentHandler;
39 import org.xml.sax.helpers.AttributesImpl;
40 
41 /**
42  * A {@link org.objectweb.asm.ClassVisitor ClassVisitor} that generates SAX 2.0
43  * events from the visited class. It can feed any kind of
44  * {@link org.xml.sax.ContentHandler ContentHandler}, e.g. XML serializer, XSLT
45  * or XQuery engines.
46  *
47  * @see org.objectweb.asm.xml.Processor
48  * @see org.objectweb.asm.xml.ASMContentHandler
49  *
50  * @author Eugene Kuleshov
51  */
52 public final class SAXClassAdapter extends SAXAdapter implements ClassVisitor {
53     private boolean singleDocument;
54 
55     /**
56      * Constructs a new {@link SAXClassAdapter SAXClassAdapter} object.
57      *
58      * @param h content handler that will be used to send SAX 2.0 events.
59      * @param singleDocument if <tt>true</tt> adapter will not produce
60      *        {@link ContentHandler#startDocument() startDocument()} and
61      *        {@link ContentHandler#endDocument() endDocument()} events.
62      */
SAXClassAdapter(ContentHandler h, boolean singleDocument)63     public SAXClassAdapter(ContentHandler h, boolean singleDocument) {
64         super(h);
65         this.singleDocument = singleDocument;
66         if (!singleDocument) {
67             addDocumentStart();
68         }
69     }
70 
visitSource(String source, String debug)71     public void visitSource(String source, String debug) {
72         if (source == null && debug == null) {
73             return;
74         }
75 
76         AttributesImpl att = new AttributesImpl();
77         if (source != null)
78             att.addAttribute("", "file", "file", "", encode(source));
79         if (debug != null)
80             att.addAttribute("", "debug", "debug", "", encode(debug));
81 
82         addElement("source", att);
83     }
84 
visitOuterClass(String owner, String name, String desc)85     public void visitOuterClass(String owner, String name, String desc) {
86         AttributesImpl att = new AttributesImpl();
87         att.addAttribute("", "owner", "owner", "", owner);
88         if (name != null)
89             att.addAttribute("", "name", "name", "", name);
90         if (desc != null)
91             att.addAttribute("", "desc", "desc", "", desc);
92 
93         addElement("outerclass", att);
94     }
95 
visitAttribute(Attribute attr)96     public final void visitAttribute(Attribute attr) {
97         // TODO Auto-generated SAXClassAdapter.visitAttribute
98     }
99 
visitAnnotation(String desc, boolean visible)100     public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
101         return new SAXAnnotationAdapter(getContentHandler(),
102                 "annotation",
103                 visible ? 1 : -1,
104                 null,
105                 desc);
106     }
107 
visit( int version, int access, String name, String signature, String superName, String[] interfaces)108     public void visit(
109         int version,
110         int access,
111         String name,
112         String signature,
113         String superName,
114         String[] interfaces)
115     {
116         StringBuffer sb = new StringBuffer();
117         if ((access & Opcodes.ACC_PUBLIC) != 0)
118             sb.append("public ");
119         if ((access & Opcodes.ACC_PRIVATE) != 0)
120             sb.append("private ");
121         if ((access & Opcodes.ACC_PROTECTED) != 0)
122             sb.append("protected ");
123         if ((access & Opcodes.ACC_FINAL) != 0)
124             sb.append("final ");
125         if ((access & Opcodes.ACC_SUPER) != 0)
126             sb.append("super ");
127         if ((access & Opcodes.ACC_INTERFACE) != 0)
128             sb.append("interface ");
129         if ((access & Opcodes.ACC_ABSTRACT) != 0)
130             sb.append("abstract ");
131         if ((access & Opcodes.ACC_SYNTHETIC) != 0)
132             sb.append("synthetic ");
133         if ((access & Opcodes.ACC_ANNOTATION) != 0)
134             sb.append("annotation ");
135         if ((access & Opcodes.ACC_ENUM) != 0)
136             sb.append("enum ");
137         if ((access & Opcodes.ACC_DEPRECATED) != 0)
138             sb.append("deprecated ");
139 
140         AttributesImpl att = new AttributesImpl();
141         att.addAttribute("", "access", "access", "", sb.toString());
142         if (name != null)
143             att.addAttribute("", "name", "name", "", name);
144         if (signature != null)
145             att.addAttribute("",
146                     "signature",
147                     "signature",
148                     "",
149                     encode(signature));
150         if (superName != null)
151             att.addAttribute("", "parent", "parent", "", superName);
152         att.addAttribute("",
153                 "major",
154                 "major",
155                 "",
156                 Integer.toString(version & 0xFFFF));
157         att.addAttribute("",
158                 "minor",
159                 "minor",
160                 "",
161                 Integer.toString(version >>> 16));
162         addStart("class", att);
163 
164         addStart("interfaces", new AttributesImpl());
165         if (interfaces != null && interfaces.length > 0) {
166             for (int i = 0; i < interfaces.length; i++) {
167                 AttributesImpl att2 = new AttributesImpl();
168                 att2.addAttribute("", "name", "name", "", interfaces[i]);
169                 addElement("interface", att2);
170             }
171         }
172         addEnd("interfaces");
173     }
174 
visitField( int access, String name, String desc, String signature, Object value)175     public FieldVisitor visitField(
176         int access,
177         String name,
178         String desc,
179         String signature,
180         Object value)
181     {
182         StringBuffer sb = new StringBuffer();
183         if ((access & Opcodes.ACC_PUBLIC) != 0)
184             sb.append("public ");
185         if ((access & Opcodes.ACC_PRIVATE) != 0)
186             sb.append("private ");
187         if ((access & Opcodes.ACC_PROTECTED) != 0)
188             sb.append("protected ");
189         if ((access & Opcodes.ACC_STATIC) != 0)
190             sb.append("static ");
191         if ((access & Opcodes.ACC_FINAL) != 0)
192             sb.append("final ");
193         if ((access & Opcodes.ACC_VOLATILE) != 0)
194             sb.append("volatile ");
195         if ((access & Opcodes.ACC_TRANSIENT) != 0)
196             sb.append("transient ");
197         if ((access & Opcodes.ACC_SYNTHETIC) != 0)
198             sb.append("synthetic ");
199         if ((access & Opcodes.ACC_ENUM) != 0)
200             sb.append("enum ");
201         if ((access & Opcodes.ACC_DEPRECATED) != 0)
202             sb.append("deprecated ");
203 
204         AttributesImpl att = new AttributesImpl();
205         att.addAttribute("", "access", "access", "", sb.toString());
206         att.addAttribute("", "name", "name", "", name);
207         att.addAttribute("", "desc", "desc", "", desc);
208         if (signature != null)
209             att.addAttribute("",
210                     "signature",
211                     "signature",
212                     "",
213                     encode(signature));
214         if (value != null) {
215             att.addAttribute("", "value", "value", "", encode(value.toString()));
216         }
217 
218         return new SAXFieldAdapter(getContentHandler(), att);
219     }
220 
visitMethod( int access, String name, String desc, String signature, String[] exceptions)221     public MethodVisitor visitMethod(
222         int access,
223         String name,
224         String desc,
225         String signature,
226         String[] exceptions)
227     {
228         StringBuffer sb = new StringBuffer();
229         if ((access & Opcodes.ACC_PUBLIC) != 0)
230             sb.append("public ");
231         if ((access & Opcodes.ACC_PRIVATE) != 0)
232             sb.append("private ");
233         if ((access & Opcodes.ACC_PROTECTED) != 0)
234             sb.append("protected ");
235         if ((access & Opcodes.ACC_STATIC) != 0)
236             sb.append("static ");
237         if ((access & Opcodes.ACC_FINAL) != 0)
238             sb.append("final ");
239         if ((access & Opcodes.ACC_SYNCHRONIZED) != 0)
240             sb.append("synchronized ");
241         if ((access & Opcodes.ACC_BRIDGE) != 0)
242             sb.append("bridge ");
243         if ((access & Opcodes.ACC_VARARGS) != 0)
244             sb.append("varargs ");
245         if ((access & Opcodes.ACC_NATIVE) != 0)
246             sb.append("native ");
247         if ((access & Opcodes.ACC_ABSTRACT) != 0)
248             sb.append("abstract ");
249         if ((access & Opcodes.ACC_STRICT) != 0)
250             sb.append("strict ");
251         if ((access & Opcodes.ACC_SYNTHETIC) != 0)
252             sb.append("synthetic ");
253         if ((access & Opcodes.ACC_DEPRECATED) != 0)
254             sb.append("deprecated ");
255 
256         AttributesImpl att = new AttributesImpl();
257         att.addAttribute("", "access", "access", "", sb.toString());
258         att.addAttribute("", "name", "name", "", name);
259         att.addAttribute("", "desc", "desc", "", desc);
260         if (signature != null) {
261             att.addAttribute("", "signature", "signature", "", signature);
262         }
263         addStart("method", att);
264 
265         addStart("exceptions", new AttributesImpl());
266         if (exceptions != null && exceptions.length > 0) {
267             for (int i = 0; i < exceptions.length; i++) {
268                 AttributesImpl att2 = new AttributesImpl();
269                 att2.addAttribute("", "name", "name", "", exceptions[i]);
270                 addElement("exception", att2);
271             }
272         }
273         addEnd("exceptions");
274 
275         return new SAXCodeAdapter(getContentHandler(), access);
276     }
277 
visitInnerClass( String name, String outerName, String innerName, int access)278     public final void visitInnerClass(
279         String name,
280         String outerName,
281         String innerName,
282         int access)
283     {
284         StringBuffer sb = new StringBuffer();
285         if ((access & Opcodes.ACC_PUBLIC) != 0)
286             sb.append("public ");
287         if ((access & Opcodes.ACC_PRIVATE) != 0)
288             sb.append("private ");
289         if ((access & Opcodes.ACC_PROTECTED) != 0)
290             sb.append("protected ");
291         if ((access & Opcodes.ACC_STATIC) != 0)
292             sb.append("static ");
293         if ((access & Opcodes.ACC_FINAL) != 0)
294             sb.append("final ");
295         if ((access & Opcodes.ACC_SUPER) != 0)
296             sb.append("super ");
297         if ((access & Opcodes.ACC_INTERFACE) != 0)
298             sb.append("interface ");
299         if ((access & Opcodes.ACC_ABSTRACT) != 0)
300             sb.append("abstract ");
301         if ((access & Opcodes.ACC_SYNTHETIC) != 0)
302             sb.append("synthetic ");
303         if ((access & Opcodes.ACC_ANNOTATION) != 0)
304             sb.append("annotation ");
305         if ((access & Opcodes.ACC_ENUM) != 0)
306             sb.append("enum ");
307         if ((access & Opcodes.ACC_DEPRECATED) != 0)
308             sb.append("deprecated ");
309 
310         AttributesImpl att = new AttributesImpl();
311         att.addAttribute("", "access", "access", "", sb.toString());
312         if (name != null)
313             att.addAttribute("", "name", "name", "", name);
314         if (outerName != null)
315             att.addAttribute("", "outerName", "outerName", "", outerName);
316         if (innerName != null)
317             att.addAttribute("", "innerName", "innerName", "", innerName);
318         addElement("innerclass", att);
319     }
320 
visitEnd()321     public final void visitEnd() {
322         addEnd("class");
323         if (!singleDocument) {
324             addDocumentEnd();
325         }
326     }
327 
encode(String s)328     static final String encode(String s) {
329         StringBuffer sb = new StringBuffer();
330         for (int i = 0; i < s.length(); i++) {
331             char c = s.charAt(i);
332             if (c == '\\') {
333                 sb.append("\\\\");
334             } else if (c < 0x20 || c > 0x7f) {
335                 sb.append("\\u");
336                 if (c < 0x10) {
337                     sb.append("000");
338                 } else if (c < 0x100) {
339                     sb.append("00");
340                 } else if (c < 0x1000) {
341                     sb.append("0");
342                 }
343                 sb.append(Integer.toString(c, 16));
344             } else {
345                 sb.append(c);
346             }
347         }
348         return sb.toString();
349     }
350 
351 }
352