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 */ 30package org.objectweb.asm.xml; 31 32import org.objectweb.asm.AnnotationVisitor; 33import org.objectweb.asm.Attribute; 34import org.objectweb.asm.ClassVisitor; 35import org.objectweb.asm.TypeAnnotationVisitor; 36import org.objectweb.asm.FieldVisitor; 37import org.objectweb.asm.MethodVisitor; 38import org.objectweb.asm.Opcodes; 39import org.xml.sax.ContentHandler; 40import 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 */ 53public 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