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 */ SAXClassAdapter(ContentHandler h, boolean singleDocument)64 public SAXClassAdapter(ContentHandler h, boolean singleDocument) { 65 super(h); 66 this.singleDocument = singleDocument; 67 if (!singleDocument) { 68 addDocumentStart(); 69 } 70 } 71 visitSource(String source, String debug)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 visitOuterClass(String owner, String name, String desc)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 visitAttribute(Attribute attr)97 public final void visitAttribute(Attribute attr) { 98 // TODO Auto-generated SAXClassAdapter.visitAttribute 99 } 100 visitAnnotation(String desc, boolean visible)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 visitTypeAnnotation( String desc, boolean visible, boolean inCode)109 public TypeAnnotationVisitor visitTypeAnnotation( 110 String desc, boolean visible, boolean inCode) { 111 throw new RuntimeException("Jaime did not implement yet"); 112 } 113 visit( int version, int access, String name, String signature, String superName, String[] interfaces)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 visitField( int access, String name, String desc, String signature, Object value)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 visitMethod( int access, String name, String desc, String signature, String[] exceptions)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 visitInnerClass( String name, String outerName, String innerName, int access)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 visitEnd()327 public final void visitEnd() { 328 addEnd("class"); 329 if (!singleDocument) { 330 addDocumentEnd(); 331 } 332 } 333 encode(String s)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