Home | History | Annotate | Download | only in xml
      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.TypeAnnotationVisitor;
     36 import org.objectweb.asm.FieldVisitor;
     37 import org.objectweb.asm.MethodVisitor;
     38 import org.objectweb.asm.Opcodes;
     39 import org.xml.sax.ContentHandler;
     40 import org.xml.sax.helpers.AttributesImpl;
     41 
     42 /**
     43  * A {@link org.objectweb.asm.ClassVisitor ClassVisitor} that generates SAX 2.0
     44  * events from the visited class. It can feed any kind of
     45  * {@link org.xml.sax.ContentHandler ContentHandler}, e.g. XML serializer, XSLT
     46  * or XQuery engines.
     47  *
     48  * @see org.objectweb.asm.xml.Processor
     49  * @see org.objectweb.asm.xml.ASMContentHandler
     50  *
     51  * @author Eugene Kuleshov
     52  */
     53 public final class SAXClassAdapter extends SAXAdapter implements ClassVisitor {
     54     private boolean singleDocument;
     55 
     56     /**
     57      * Constructs a new {@link SAXClassAdapter SAXClassAdapter} object.
     58      *
     59      * @param h content handler that will be used to send SAX 2.0 events.
     60      * @param singleDocument if <tt>true</tt> adapter will not produce
     61      *        {@link ContentHandler#startDocument() startDocument()} and
     62      *        {@link ContentHandler#endDocument() endDocument()} events.
     63      */
     64     public SAXClassAdapter(ContentHandler h, boolean singleDocument) {
     65         super(h);
     66         this.singleDocument = singleDocument;
     67         if (!singleDocument) {
     68             addDocumentStart();
     69         }
     70     }
     71 
     72     public void visitSource(String source, String debug) {
     73         if (source == null && debug == null) {
     74             return;
     75         }
     76 
     77         AttributesImpl att = new AttributesImpl();
     78         if (source != null)
     79             att.addAttribute("", "file", "file", "", encode(source));
     80         if (debug != null)
     81             att.addAttribute("", "debug", "debug", "", encode(debug));
     82 
     83         addElement("source", att);
     84     }
     85 
     86     public void visitOuterClass(String owner, String name, String desc) {
     87         AttributesImpl att = new AttributesImpl();
     88         att.addAttribute("", "owner", "owner", "", owner);
     89         if (name != null)
     90             att.addAttribute("", "name", "name", "", name);
     91         if (desc != null)
     92             att.addAttribute("", "desc", "desc", "", desc);
     93 
     94         addElement("outerclass", att);
     95     }
     96 
     97     public final void visitAttribute(Attribute attr) {
     98         // TODO Auto-generated SAXClassAdapter.visitAttribute
     99     }
    100 
    101     public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
    102         return new SAXAnnotationAdapter(getContentHandler(),
    103                 "annotation",
    104                 visible ? 1 : -1,
    105                 null,
    106                 desc);
    107     }
    108 
    109     public TypeAnnotationVisitor visitTypeAnnotation(
    110         String desc, boolean visible, boolean inCode) {
    111         throw new RuntimeException("Jaime did not implement yet");
    112     }
    113 
    114     public void visit(
    115         int version,
    116         int access,
    117         String name,
    118         String signature,
    119         String superName,
    120         String[] interfaces)
    121     {
    122         StringBuffer sb = new StringBuffer();
    123         if ((access & Opcodes.ACC_PUBLIC) != 0)
    124             sb.append("public ");
    125         if ((access & Opcodes.ACC_PRIVATE) != 0)
    126             sb.append("private ");
    127         if ((access & Opcodes.ACC_PROTECTED) != 0)
    128             sb.append("protected ");
    129         if ((access & Opcodes.ACC_FINAL) != 0)
    130             sb.append("final ");
    131         if ((access & Opcodes.ACC_SUPER) != 0)
    132             sb.append("super ");
    133         if ((access & Opcodes.ACC_INTERFACE) != 0)
    134             sb.append("interface ");
    135         if ((access & Opcodes.ACC_ABSTRACT) != 0)
    136             sb.append("abstract ");
    137         if ((access & Opcodes.ACC_SYNTHETIC) != 0)
    138             sb.append("synthetic ");
    139         if ((access & Opcodes.ACC_ANNOTATION) != 0)
    140             sb.append("annotation ");
    141         if ((access & Opcodes.ACC_ENUM) != 0)
    142             sb.append("enum ");
    143         if ((access & Opcodes.ACC_DEPRECATED) != 0)
    144             sb.append("deprecated ");
    145 
    146         AttributesImpl att = new AttributesImpl();
    147         att.addAttribute("", "access", "access", "", sb.toString());
    148         if (name != null)
    149             att.addAttribute("", "name", "name", "", name);
    150         if (signature != null)
    151             att.addAttribute("",
    152                     "signature",
    153                     "signature",
    154                     "",
    155                     encode(signature));
    156         if (superName != null)
    157             att.addAttribute("", "parent", "parent", "", superName);
    158         att.addAttribute("",
    159                 "major",
    160                 "major",
    161                 "",
    162                 Integer.toString(version & 0xFFFF));
    163         att.addAttribute("",
    164                 "minor",
    165                 "minor",
    166                 "",
    167                 Integer.toString(version >>> 16));
    168         addStart("class", att);
    169 
    170         addStart("interfaces", new AttributesImpl());
    171         if (interfaces != null && interfaces.length > 0) {
    172             for (int i = 0; i < interfaces.length; i++) {
    173                 AttributesImpl att2 = new AttributesImpl();
    174                 att2.addAttribute("", "name", "name", "", interfaces[i]);
    175                 addElement("interface", att2);
    176             }
    177         }
    178         addEnd("interfaces");
    179     }
    180 
    181     public FieldVisitor visitField(
    182         int access,
    183         String name,
    184         String desc,
    185         String signature,
    186         Object value)
    187     {
    188         StringBuffer sb = new StringBuffer();
    189         if ((access & Opcodes.ACC_PUBLIC) != 0)
    190             sb.append("public ");
    191         if ((access & Opcodes.ACC_PRIVATE) != 0)
    192             sb.append("private ");
    193         if ((access & Opcodes.ACC_PROTECTED) != 0)
    194             sb.append("protected ");
    195         if ((access & Opcodes.ACC_STATIC) != 0)
    196             sb.append("static ");
    197         if ((access & Opcodes.ACC_FINAL) != 0)
    198             sb.append("final ");
    199         if ((access & Opcodes.ACC_VOLATILE) != 0)
    200             sb.append("volatile ");
    201         if ((access & Opcodes.ACC_TRANSIENT) != 0)
    202             sb.append("transient ");
    203         if ((access & Opcodes.ACC_SYNTHETIC) != 0)
    204             sb.append("synthetic ");
    205         if ((access & Opcodes.ACC_ENUM) != 0)
    206             sb.append("enum ");
    207         if ((access & Opcodes.ACC_DEPRECATED) != 0)
    208             sb.append("deprecated ");
    209 
    210         AttributesImpl att = new AttributesImpl();
    211         att.addAttribute("", "access", "access", "", sb.toString());
    212         att.addAttribute("", "name", "name", "", name);
    213         att.addAttribute("", "desc", "desc", "", desc);
    214         if (signature != null)
    215             att.addAttribute("",
    216                     "signature",
    217                     "signature",
    218                     "",
    219                     encode(signature));
    220         if (value != null) {
    221             att.addAttribute("", "value", "value", "", encode(value.toString()));
    222         }
    223 
    224         return new SAXFieldAdapter(getContentHandler(), att);
    225     }
    226 
    227     public MethodVisitor visitMethod(
    228         int access,
    229         String name,
    230         String desc,
    231         String signature,
    232         String[] exceptions)
    233     {
    234         StringBuffer sb = new StringBuffer();
    235         if ((access & Opcodes.ACC_PUBLIC) != 0)
    236             sb.append("public ");
    237         if ((access & Opcodes.ACC_PRIVATE) != 0)
    238             sb.append("private ");
    239         if ((access & Opcodes.ACC_PROTECTED) != 0)
    240             sb.append("protected ");
    241         if ((access & Opcodes.ACC_STATIC) != 0)
    242             sb.append("static ");
    243         if ((access & Opcodes.ACC_FINAL) != 0)
    244             sb.append("final ");
    245         if ((access & Opcodes.ACC_SYNCHRONIZED) != 0)
    246             sb.append("synchronized ");
    247         if ((access & Opcodes.ACC_BRIDGE) != 0)
    248             sb.append("bridge ");
    249         if ((access & Opcodes.ACC_VARARGS) != 0)
    250             sb.append("varargs ");
    251         if ((access & Opcodes.ACC_NATIVE) != 0)
    252             sb.append("native ");
    253         if ((access & Opcodes.ACC_ABSTRACT) != 0)
    254             sb.append("abstract ");
    255         if ((access & Opcodes.ACC_STRICT) != 0)
    256             sb.append("strict ");
    257         if ((access & Opcodes.ACC_SYNTHETIC) != 0)
    258             sb.append("synthetic ");
    259         if ((access & Opcodes.ACC_DEPRECATED) != 0)
    260             sb.append("deprecated ");
    261 
    262         AttributesImpl att = new AttributesImpl();
    263         att.addAttribute("", "access", "access", "", sb.toString());
    264         att.addAttribute("", "name", "name", "", name);
    265         att.addAttribute("", "desc", "desc", "", desc);
    266         if (signature != null) {
    267             att.addAttribute("", "signature", "signature", "", signature);
    268         }
    269         addStart("method", att);
    270 
    271         addStart("exceptions", new AttributesImpl());
    272         if (exceptions != null && exceptions.length > 0) {
    273             for (int i = 0; i < exceptions.length; i++) {
    274                 AttributesImpl att2 = new AttributesImpl();
    275                 att2.addAttribute("", "name", "name", "", exceptions[i]);
    276                 addElement("exception", att2);
    277             }
    278         }
    279         addEnd("exceptions");
    280 
    281         return new SAXCodeAdapter(getContentHandler(), access);
    282     }
    283 
    284     public final void visitInnerClass(
    285         String name,
    286         String outerName,
    287         String innerName,
    288         int access)
    289     {
    290         StringBuffer sb = new StringBuffer();
    291         if ((access & Opcodes.ACC_PUBLIC) != 0)
    292             sb.append("public ");
    293         if ((access & Opcodes.ACC_PRIVATE) != 0)
    294             sb.append("private ");
    295         if ((access & Opcodes.ACC_PROTECTED) != 0)
    296             sb.append("protected ");
    297         if ((access & Opcodes.ACC_STATIC) != 0)
    298             sb.append("static ");
    299         if ((access & Opcodes.ACC_FINAL) != 0)
    300             sb.append("final ");
    301         if ((access & Opcodes.ACC_SUPER) != 0)
    302             sb.append("super ");
    303         if ((access & Opcodes.ACC_INTERFACE) != 0)
    304             sb.append("interface ");
    305         if ((access & Opcodes.ACC_ABSTRACT) != 0)
    306             sb.append("abstract ");
    307         if ((access & Opcodes.ACC_SYNTHETIC) != 0)
    308             sb.append("synthetic ");
    309         if ((access & Opcodes.ACC_ANNOTATION) != 0)
    310             sb.append("annotation ");
    311         if ((access & Opcodes.ACC_ENUM) != 0)
    312             sb.append("enum ");
    313         if ((access & Opcodes.ACC_DEPRECATED) != 0)
    314             sb.append("deprecated ");
    315 
    316         AttributesImpl att = new AttributesImpl();
    317         att.addAttribute("", "access", "access", "", sb.toString());
    318         if (name != null)
    319             att.addAttribute("", "name", "name", "", name);
    320         if (outerName != null)
    321             att.addAttribute("", "outerName", "outerName", "", outerName);
    322         if (innerName != null)
    323             att.addAttribute("", "innerName", "innerName", "", innerName);
    324         addElement("innerclass", att);
    325     }
    326 
    327     public final void visitEnd() {
    328         addEnd("class");
    329         if (!singleDocument) {
    330             addDocumentEnd();
    331         }
    332     }
    333 
    334     static final String encode(String s) {
    335         StringBuffer sb = new StringBuffer();
    336         for (int i = 0; i < s.length(); i++) {
    337             char c = s.charAt(i);
    338             if (c == '\\') {
    339                 sb.append("\\\\");
    340             } else if (c < 0x20 || c > 0x7f) {
    341                 sb.append("\\u");
    342                 if (c < 0x10) {
    343                     sb.append("000");
    344                 } else if (c < 0x100) {
    345                     sb.append("00");
    346                 } else if (c < 0x1000) {
    347                     sb.append("0");
    348                 }
    349                 sb.append(Integer.toString(c, 16));
    350             } else {
    351                 sb.append(c);
    352             }
    353         }
    354         return sb.toString();
    355     }
    356 
    357 }
    358