KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jeantessier > classreader > XMLPrinter


1 /*
2  * Copyright (c) 2001-2005, Jean Tessier
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of Jean Tessier nor the names of his contributors
17  * may be used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */

32
33 package com.jeantessier.classreader;
34
35 import java.io.*;
36 import java.util.*;
37
38 import org.apache.oro.text.perl.*;
39
40 public class XMLPrinter extends Printer {
41     public static final String JavaDoc DEFAULT_ENCODING = "utf-8";
42     public static final String JavaDoc DEFAULT_DTD_PREFIX = "http://depfind.sourceforge.net/dtd";
43
44     private static final BitFormat format = new BitFormat(16);
45     private static final Perl5Util perl = new Perl5Util();
46
47     private boolean top = true;
48
49     public XMLPrinter(PrintWriter out) {
50         this(out, DEFAULT_ENCODING, DEFAULT_DTD_PREFIX);
51     }
52     
53     public XMLPrinter(PrintWriter out, String JavaDoc encoding, String JavaDoc dtdPrefix) {
54         super(out);
55         
56         appendHeader(encoding, dtdPrefix);
57     }
58
59     private void appendHeader(String JavaDoc encoding, String JavaDoc dtdPrefix) {
60         append("<?xml version=\"1.0\" encoding=\"").append(encoding).append("\" ?>").eol();
61         eol();
62         append("<!DOCTYPE classfiles SYSTEM \"").append(dtdPrefix).append("/classfile.dtd\">").eol();
63         eol();
64     }
65
66     public void visitClassfiles(Collection classfiles) {
67         indent().append("<classfiles>").eol();
68         raiseIndent();
69
70         super.visitClassfiles(classfiles);
71
72         lowerIndent();
73         indent().append("</classfiles>").eol();
74     }
75     
76     public void visitClassfile(Classfile classfile) {
77         Iterator i;
78
79         indent().append("<classfile magic-number=\"").append(classfile.getMagicNumber()).append("\" minor-version=\"").append(classfile.getMinorVersion()).append("\" major-version=\"").append(classfile.getMajorVersion()).append("\" access-flag=\"").append(format.format(classfile.getAccessFlag())).append("\">").eol();
80         raiseIndent();
81
82         top = true;
83         classfile.getConstantPool().accept(this);
84         top = false;
85         
86         if (classfile.isPublic()) indent().append("<public/>").eol();
87         if (classfile.isFinal()) indent().append("<final/>").eol();
88         if (classfile.isSuper()) indent().append("<super/>").eol();
89         if (classfile.isInterface()) indent().append("<is-interface/>").eol();
90         if (classfile.isAbstract()) indent().append("<abstract/>").eol();
91
92         indent();
93         append("<this-class>");
94         classfile.getRawClass().accept(this);
95         append("</this-class>").eol();
96
97         indent();
98         append("<superclass>");
99         if (classfile.getSuperclassIndex() != 0) {
100             classfile.getRawSuperclass().accept(this);
101         }
102         append("</superclass>").eol();
103
104         if (!classfile.getAllInterfaces().isEmpty()) {
105             indent().append("<interfaces>").eol();
106             raiseIndent();
107             i = classfile.getAllInterfaces().iterator();
108             while (i.hasNext()) {
109                 indent();
110                 append("<interface>");
111                 ((Visitable) i.next()).accept(this);
112                 append("</interface>").eol();
113             }
114             lowerIndent();
115             indent().append("</interfaces>").eol();
116         }
117         
118         if (!classfile.getAllFields().isEmpty()) {
119             indent().append("<fields>").eol();
120             raiseIndent();
121             i = classfile.getAllFields().iterator();
122             while (i.hasNext()) {
123                 ((Visitable) i.next()).accept(this);
124             }
125             lowerIndent();
126             indent().append("</fields>").eol();
127         }
128
129         if (!classfile.getAllMethods().isEmpty()) {
130             indent().append("<methods>").eol();
131             raiseIndent();
132             i = classfile.getAllMethods().iterator();
133             while (i.hasNext()) {
134                 ((Visitable) i.next()).accept(this);
135             }
136             lowerIndent();
137             indent().append("</methods>").eol();
138         }
139
140         if (!classfile.getAttributes().isEmpty()) {
141             indent().append("<attributes>").eol();
142             raiseIndent();
143             i = classfile.getAttributes().iterator();
144             while (i.hasNext()) {
145                 ((Visitable) i.next()).accept(this);
146             }
147             lowerIndent();
148             indent().append("</attributes>").eol();
149         }
150
151         lowerIndent();
152         indent().append("</classfile>").eol();
153     }
154
155     public void visitConstantPool(ConstantPool constantPool) {
156         resetCount();
157
158         indent().append("<constant-pool>").eol();
159         raiseIndent();
160
161         Iterator i = constantPool.iterator();
162         while (i.hasNext()) {
163             Visitable entry = (Visitable) i.next();
164             if (entry != null) {
165                 entry.accept(this);
166             }
167             raiseCount();
168         }
169
170         lowerIndent();
171         indent().append("</constant-pool>").eol();
172     }
173
174     public void visitClass_info(Class_info entry) {
175         if (top) {
176             top = false;
177             indent();
178             append("<class id=\"").append(currentCount()).append("\">");
179             // entry.getRawName().accept(this);
180
append(entry.getName());
181             append("</class>").eol();
182             top = true;
183         } else {
184             // entry.getRawName().accept(this);
185
append(entry.getName());
186         }
187     }
188
189     public void visitFieldRef_info(FieldRef_info entry) {
190         Class_info c = entry.getRawClass();
191         NameAndType_info nat = entry.getRawNameAndType();
192
193         if (top) {
194             top = false;
195             indent();
196             append("<field-ref-info id=\"").append(currentCount()).append("\">");
197             append("<class>");
198             c.accept(this);
199             append("</class>");
200             append("<type>");
201             nat.getRawType().accept(this);
202             append("</type>");
203             append("<name>");
204             nat.getRawName().accept(this);
205             append("</name>");
206             append("</field-ref-info>").eol();
207             top = true;
208         } else {
209             append(SignatureHelper.getType(nat.getType()));
210             append(" ");
211             append(entry.getFullSignature());
212         }
213     }
214
215     public void visitMethodRef_info(MethodRef_info entry) {
216         Class_info c = entry.getRawClass();
217         NameAndType_info nat = entry.getRawNameAndType();
218
219         if (top) {
220             top = false;
221             indent();
222             append("<method-ref-info id=\"").append(currentCount()).append("\">");
223             append("<class>");
224             c.accept(this);
225             append("</class>");
226             append("<name>");
227             nat.getRawName().accept(this);
228             append("</name>");
229             append("<type>");
230             nat.getRawType().accept(this);
231             append("</type>");
232             append("</method-ref-info>").eol();
233             top = true;
234         } else {
235             if (!entry.isConstructor() && !entry.isStaticInitializer()) {
236                 append(SignatureHelper.getReturnType(nat.getType())).append(" ");
237             }
238             append(entry.getFullSignature());
239         }
240     }
241
242     public void visitInterfaceMethodRef_info(InterfaceMethodRef_info entry) {
243         Class_info c = entry.getRawClass();
244         NameAndType_info nat = entry.getRawNameAndType();
245
246         if (top) {
247             top = false;
248             indent();
249             append("<interface-method-ref-info id=\"").append(currentCount()).append("\">");
250             append("<class>");
251             c.accept(this);
252             append("</class>");
253             append("<name>");
254             nat.getRawName().accept(this);
255             append("</name>");
256             append("<type>");
257             nat.getRawType().accept(this);
258             append("</type>");
259             append("</interface-method-ref-info>").eol();
260             top = true;
261         } else {
262             append(SignatureHelper.getReturnType(nat.getType()));
263             append(" ");
264             append(entry.getFullSignature());
265         }
266     }
267
268     public void visitString_info(String_info entry) {
269         if (top) {
270             top = false;
271             indent();
272             append("<string-info id=\"").append(currentCount()).append("\">");
273             entry.getRawValue().accept(this);
274             append("</string-info>").eol();
275             top = true;
276         } else {
277             entry.getRawValue().accept(this);
278         }
279     }
280
281     public void visitInteger_info(Integer_info entry) {
282         if (top) {
283             top = false;
284             indent();
285             append("<integer-info id=\"").append(currentCount()).append("\">");
286             append(entry.getValue());
287             append("</integer-info>").eol();
288             top = true;
289         } else {
290             append(entry.getValue());
291         }
292     }
293
294     public void visitFloat_info(Float_info entry) {
295         if (top) {
296             top = false;
297             indent();
298             append("<float-info id=\"").append(currentCount()).append("\">");
299             append(entry.getValue());
300             append("</float-info>").eol();
301             top = true;
302         } else {
303             append(entry.getValue());
304         }
305     }
306
307     public void visitLong_info(Long_info entry) {
308         if (top) {
309             top = false;
310             indent();
311             append("<long-info id=\"").append(currentCount()).append("\">");
312             append(entry.getValue());
313             append("</long-info>").eol();
314             top = true;
315         } else {
316             append(entry.getValue());
317         }
318     }
319
320     public void visitDouble_info(Double_info entry) {
321         if (top) {
322             top = false;
323             indent();
324             append("<double-info id=\"").append(currentCount()).append("\">");
325             append(entry.getValue());
326             append("</double-info>").eol();
327             top = true;
328         } else {
329             append(entry.getValue());
330         }
331     }
332
333     public void visitNameAndType_info(NameAndType_info entry) {
334         if (top) {
335             top = false;
336             indent();
337             append("<name-and-type-info id=\"").append(currentCount()).append("\">");
338             append("<name>");
339             entry.getRawName().accept(this);
340             append("</name>");
341             append("<type>");
342             entry.getRawType().accept(this);
343             append("</type>");
344             append("</name-and-type-info>").eol();
345             top = true;
346         } else {
347             entry.getRawName().accept(this);
348             append(" ");
349             entry.getRawType().accept(this);
350         }
351     }
352
353     public void visitUTF8_info(UTF8_info entry) {
354         if (top) {
355             top = false;
356             indent().append("<utf8-info id=\"").append(currentCount()).append("\">");
357             append(escapeXMLCharacters(entry.getValue()));
358             append("</utf8-info>").eol();
359             top = true;
360         } else {
361             append(escapeXMLCharacters(entry.getValue()));
362         }
363     }
364
365     public void visitField_info(Field_info entry) {
366         indent().append("<field-info access-flag=\"").append(format.format(entry.getAccessFlag())).append("\">").eol();
367         raiseIndent();
368
369         if (entry.isPublic()) indent().append("<public/>").eol();
370         if (entry.isProtected()) indent().append("<protected/>").eol();
371         if (entry.isPrivate()) indent().append("<private/>").eol();
372         if (entry.isStatic()) indent().append("<static/>").eol();
373         if (entry.isFinal()) indent().append("<final/>").eol();
374         if (entry.isVolatile()) indent().append("<volatile/>").eol();
375         if (entry.isTransient()) indent().append("<transient/>").eol();
376     
377         indent();
378         append("<name>");
379         entry.getRawName().accept(this);
380         append("</name>").eol();
381         
382         indent().append("<type>").append(entry.getType()).append("</type>").eol();
383
384         if (!entry.getAttributes().isEmpty()) {
385             indent().append("<attributes>").eol();
386             raiseIndent();
387             super.visitField_info(entry);
388             lowerIndent();
389             indent().append("</attributes>").eol();
390         }
391
392         lowerIndent();
393         indent().append("</field-info>").eol();
394     }
395
396     public void visitMethod_info(Method_info entry) {
397         indent().append("<method-info access-flag=\"").append(format.format(entry.getAccessFlag())).append("\">").eol();
398         raiseIndent();
399
400         if (entry.isPublic()) indent().append("<public/>").eol();
401         if (entry.isProtected()) indent().append("<protected/>").eol();
402         if (entry.isPrivate()) indent().append("<private/>").eol();
403         if (entry.isStatic()) indent().append("<static/>").eol();
404         if (entry.isFinal()) indent().append("<final/>").eol();
405         if (entry.isSynchronized()) indent().append("<synchronized/>").eol();
406         if (entry.isNative()) indent().append("<native/>").eol();
407         if (entry.isAbstract()) indent().append("<abstract/>").eol();
408         if (entry.isStrict()) indent().append("<strict/>").eol();
409
410         indent();
411         append("<name>");
412         entry.getRawName().accept(this);
413         append("</name>").eol();
414         
415         if (!entry.getName().equals("<init>") && !entry.getName().equals("<clinit>")) {
416             indent().append("<return-type>").append((entry.getReturnType() != null) ? entry.getReturnType() : "void").append("</return-type>").eol();
417         }
418         indent().append("<signature>").append(entry.getSignature()).append("</signature>").eol();
419
420         if (!entry.getAttributes().isEmpty()) {
421             indent().append("<attributes>").eol();
422             raiseIndent();
423             super.visitMethod_info(entry);
424             lowerIndent();
425             indent().append("</attributes>").eol();
426         }
427
428         lowerIndent();
429         indent().append("</method-info>").eol();
430     }
431
432     public void visitConstantValue_attribute(ConstantValue_attribute attribute) {
433         indent().append("<constant-value-attribute>").eol();
434         raiseIndent();
435
436         attribute.getRawValue().accept(this);
437
438         lowerIndent();
439         indent().append("</constant-value-attribute>").eol();
440     }
441
442     public void visitCode_attribute(Code_attribute attribute) {
443         Iterator i;
444         
445         indent().append("<code-attribute>").eol();
446         raiseIndent();
447
448         indent().append("<length>").append(attribute.getCode().length).append("</length>").eol();
449
450         indent().append("<instructions>").eol();
451         raiseIndent();
452         i = attribute.iterator();
453         while (i.hasNext()) {
454             Instruction instr = (Instruction) i.next();
455             indent();
456             append("<instruction pc=\"").append(instr.getStart()).append("\" length=\"").append(instr.getLength()).append("\">");
457             switch (instr.getOpcode()) {
458                 case 0xb2: // getstatic
459
case 0xb3: // putstatic
460
case 0xb4: // getfield
461
case 0xb5: // putfield
462
case 0xb6: // invokevirtual
463
case 0xb7: // invokespecial
464
case 0xb8: // invokestatic
465
case 0xb9: // invokeinterface
466
case 0xbb: // new
467
case 0xbd: // anewarray
468
case 0xc0: // checkcast
469
case 0xc1: // instanceof
470
case 0xc5: // multianewarray
471
int index = ((instr.getCode()[instr.getStart()+1] & 0xff) << 8) | (instr.getCode()[instr.getStart()+2] & 0xff);
472                     append(instr);
473                     append(" ");
474                     ((ConstantPoolEntry) attribute.getClassfile().getConstantPool().get(index)).accept(this);
475                     break;
476                 default:
477                     append(instr);
478                     break;
479             }
480             append("</instruction>").eol();
481         }
482         lowerIndent();
483         indent().append("</instructions>").eol();
484
485         if (!attribute.getExceptionHandlers().isEmpty()) {
486             indent().append("<exception-handlers>").eol();
487             raiseIndent();
488             i = attribute.getExceptionHandlers().iterator();
489             while (i.hasNext()) {
490                 ((Visitable) i.next()).accept(this);
491             }
492             lowerIndent();
493             indent().append("</exception-handlers>").eol();
494         }
495         
496         if (!attribute.getAttributes().isEmpty()) {
497             indent().append("<attributes>").eol();
498             raiseIndent();
499             i = attribute.getAttributes().iterator();
500             while (i.hasNext()) {
501                 ((Visitable) i.next()).accept(this);
502             }
503             lowerIndent();
504             indent().append("</attributes>").eol();
505         }
506         
507         lowerIndent();
508         indent().append("</code-attribute>").eol();
509     }
510
511     public void visitExceptions_attribute(Exceptions_attribute attribute) {
512         indent().append("<exceptions-attribute>").eol();
513         raiseIndent();
514
515         Iterator i = attribute.getExceptions().iterator();
516         while (i.hasNext()) {
517             indent();
518             append("<exception>");
519             ((Visitable) i.next()).accept(this);
520             append("</exception>").eol();
521         }
522
523         lowerIndent();
524         indent().append("</exceptions-attribute>").eol();
525     }
526
527     public void visitInnerClasses_attribute(InnerClasses_attribute attribute) {
528         indent().append("<inner-classes-attribute>").eol();
529         raiseIndent();
530
531         Iterator i = attribute.getClasses().iterator();
532         while (i.hasNext()) {
533             ((Visitable) i.next()).accept(this);
534         }
535
536         lowerIndent();
537         indent().append("</inner-classes-attribute>").eol();
538     }
539
540     public void visitSynthetic_attribute(Synthetic_attribute attribute) {
541         indent().append("<synthetic-attribute/>").eol();
542     }
543
544     public void visitSourceFile_attribute(SourceFile_attribute attribute) {
545         indent().append("<source-file-attribute>").append(attribute.getSourceFile()).append("</source-file-attribute>").eol();
546     }
547
548     public void visitLineNumberTable_attribute(LineNumberTable_attribute attribute) {
549         indent().append("<line-number-table-attribute>").eol();
550         raiseIndent();
551
552         Iterator i = attribute.getLineNumbers().iterator();
553         while (i.hasNext()) {
554             ((Visitable) i.next()).accept(this);
555         }
556
557         lowerIndent();
558         indent().append("</line-number-table-attribute>").eol();
559     }
560
561     public void visitLocalVariableTable_attribute(LocalVariableTable_attribute attribute) {
562         indent().append("<local-variable-table-attribute>").eol();
563         raiseIndent();
564
565         Iterator i = attribute.getLocalVariables().iterator();
566         while (i.hasNext()) {
567             ((Visitable) i.next()).accept(this);
568         }
569
570         lowerIndent();
571         indent().append("</local-variable-table-attribute>").eol();
572     }
573
574     public void visitDeprecated_attribute(Deprecated_attribute attribute) {
575         indent().append("<deprecated-attribute/>").eol();
576     }
577
578     public void visitExceptionHandler(ExceptionHandler helper) {
579         indent();
580         append("<exception-handler>");
581         append("<start-pc>").append(helper.getStartPC()).append("</start-pc>");
582         append("<end-pc>").append(helper.getEndPC()).append("</end-pc>");
583         append("<handler-pc>").append(helper.getHandlerPC()).append("</handler-pc>");
584
585         append("<catch-type>");
586         if (helper.getCatchTypeIndex() != 0) {
587             helper.getRawCatchType().accept(this);
588         }
589         append("</catch-type>");
590
591         append("</exception-handler>").eol();
592     }
593
594     public void visitInnerClass(InnerClass helper) {
595         indent().append("<inner-class access-flag=\"").append(format.format(helper.getAccessFlag())).append("\">").eol();
596         raiseIndent();
597
598         if (helper.isPublic()) indent().append("<public/>").eol();
599         if (helper.isProtected()) indent().append("<protected/>").eol();
600         if (helper.isPrivate()) indent().append("<private/>").eol();
601         if (helper.isStatic()) indent().append("<static/>").eol();
602         if (helper.isFinal()) indent().append("<final/>").eol();
603         if (helper.isInterface()) indent().append("<is-interface/>").eol();
604         if (helper.isAbstract()) indent().append("<abstract/>").eol();
605
606         indent();
607         append("<inner-class-info>");
608         if (helper.getInnerClassInfoIndex() != 0) {
609             helper.getRawInnerClassInfo().accept(this);
610         }
611         append("</inner-class-info>").eol();
612
613         indent();
614         append("<outer-class-info>");
615         if (helper.getOuterClassInfoIndex() != 0) {
616             helper.getRawOuterClassInfo().accept(this);
617         }
618         append("</outer-class-info>").eol();
619
620         indent();
621         append("<inner-name>");
622         if (helper.getInnerNameIndex() != 0) {
623             helper.getRawInnerName().accept(this);
624         }
625         append("</inner-name>").eol();
626
627         lowerIndent();
628         indent().append("</inner-class>").eol();
629     }
630
631     public void visitLineNumber(LineNumber helper) {
632         indent();
633         append("<line-number>");
634         append("<start-pc>").append(helper.getStartPC()).append("</start-pc>");
635         append("<line>").append(helper.getLineNumber()).append("</line>");
636         append("</line-number>").eol();
637     }
638
639     public void visitLocalVariable(LocalVariable helper) {
640         indent();
641         append("<local-variable pc=\"").append(helper.getStartPC()).append("\" length=\"").append(helper.getLength()).append("\">");
642         append("<name>");
643         helper.getRawName().accept(this);
644         append("</name>");
645         
646         append("<type>").append(SignatureHelper.getType(helper.getDescriptor())).append("</type>");
647         append("</local-variable>").eol();
648     }
649
650     private String JavaDoc escapeXMLCharacters(String JavaDoc text) {
651         String JavaDoc result = text;
652
653         result = perl.substitute("s/&/&amp;/g", result);
654         result = perl.substitute("s/</&lt;/g", result);
655         result = perl.substitute("s/>/&gt;/g", result);
656         
657         return result;
658     }
659 }
660
Popular Tags