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