Clover coverage report - Dependency Finder
Coverage timestamp: Mon Nov 29 2010 15:00:50 PST
file stats: LOC: 1,038   Methods: 64
NCLOC: 846   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
XMLPrinter.java 91.4% 75.9% 87.5% 79.3%
coverage coverage
 1    /*
 2    * Copyright (c) 2001-2009, 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 com.google.common.annotations.VisibleForTesting;
 36    import com.jeantessier.text.Hex;
 37   
 38    import java.io.PrintWriter;
 39    import java.util.Collection;
 40   
 41    public class XMLPrinter extends Printer {
 42    public static final String DEFAULT_ENCODING = "utf-8";
 43    public static final String DEFAULT_DTD_PREFIX = "http://depfind.sourceforge.net/dtd";
 44   
 45    private static final BitFormat format = new BitFormat(16);
 46   
 47    private boolean top = true;
 48   
 49  7 public XMLPrinter(PrintWriter out) {
 50  7 this(out, DEFAULT_ENCODING, DEFAULT_DTD_PREFIX);
 51    }
 52   
 53  124 public XMLPrinter(PrintWriter out, String encoding, String dtdPrefix) {
 54  124 super(out);
 55   
 56  124 appendHeader(encoding, dtdPrefix);
 57    }
 58   
 59  124 private void appendHeader(String encoding, String dtdPrefix) {
 60  124 append("<?xml version=\"1.0\" encoding=\"").append(encoding).append("\" ?>").eol();
 61  124 eol();
 62  124 append("<!DOCTYPE classfiles SYSTEM \"").append(dtdPrefix).append("/classfile.dtd\">").eol();
 63  124 eol();
 64    }
 65   
 66  3 public void visitClassfiles(Collection<Classfile> classfiles) {
 67  3 indent().append("<classfiles>").eol();
 68  3 raiseIndent();
 69   
 70  3 super.visitClassfiles(classfiles);
 71   
 72  3 lowerIndent();
 73  3 indent().append("</classfiles>").eol();
 74    }
 75   
 76  32 public void visitClassfile(Classfile classfile) {
 77  32 indent().append("<classfile magic-number=\"0x").append(Integer.toHexString(classfile.getMagicNumber()).toUpperCase()).append("\" minor-version=\"").append(classfile.getMinorVersion()).append("\" major-version=\"").append(classfile.getMajorVersion()).append("\" access-flag=\"").append(format.format(classfile.getAccessFlag())).append("\">").eol();
 78  32 raiseIndent();
 79   
 80  32 top = true;
 81  32 classfile.getConstantPool().accept(this);
 82  32 top = false;
 83   
 84  17 if (classfile.isPublic()) indent().append("<public/>").eol();
 85  1 if (classfile.isFinal()) indent().append("<final/>").eol();
 86  11 if (classfile.isSuper()) indent().append("<super/>").eol();
 87  7 if (classfile.isInterface()) indent().append("<is-interface/>").eol();
 88  7 if (classfile.isAbstract()) indent().append("<abstract/>").eol();
 89  1 if (classfile.isSynthetic()) indent().append("<synthetic/>").eol();
 90  1 if (classfile.isAnnotation()) indent().append("<is-annotation/>").eol();
 91  1 if (classfile.isEnum()) indent().append("<enum/>").eol();
 92   
 93  32 indent();
 94  32 append("<this-class>");
 95  32 classfile.getRawClass().accept(this);
 96  32 append("</this-class>").eol();
 97   
 98  32 indent();
 99  32 append("<superclass>");
 100  32 if (classfile.getSuperclassIndex() != 0) {
 101  16 classfile.getRawSuperclass().accept(this);
 102    }
 103  32 append("</superclass>").eol();
 104   
 105  32 if (!classfile.getAllInterfaces().isEmpty()) {
 106  18 indent().append("<interfaces>").eol();
 107  18 raiseIndent();
 108  18 for (Class_info class_info : classfile.getAllInterfaces()) {
 109  2 indent();
 110  2 append("<interface>");
 111  2 class_info.accept(this);
 112  2 append("</interface>").eol();
 113    }
 114  18 lowerIndent();
 115  18 indent().append("</interfaces>").eol();
 116    }
 117   
 118  32 if (!classfile.getAllFields().isEmpty()) {
 119  20 indent().append("<fields>").eol();
 120  20 raiseIndent();
 121  20 for (Field_info field : classfile.getAllFields()) {
 122  27 field.accept(this);
 123    }
 124  20 lowerIndent();
 125  20 indent().append("</fields>").eol();
 126    }
 127   
 128  32 if (!classfile.getAllMethods().isEmpty()) {
 129  28 indent().append("<methods>").eol();
 130  28 raiseIndent();
 131  28 for (Method_info method : classfile.getAllMethods()) {
 132  37 method.accept(this);
 133    }
 134  28 lowerIndent();
 135  28 indent().append("</methods>").eol();
 136    }
 137   
 138  32 if (!classfile.getAttributes().isEmpty()) {
 139  20 indent().append("<attributes>").eol();
 140  20 raiseIndent();
 141  20 for (Attribute_info attribute : classfile.getAttributes()) {
 142  6 attribute.accept(this);
 143    }
 144  20 lowerIndent();
 145  20 indent().append("</attributes>").eol();
 146    }
 147   
 148  32 lowerIndent();
 149  32 indent().append("</classfile>").eol();
 150    }
 151   
 152  16 public void visitConstantPool(ConstantPool constantPool) {
 153  16 resetCount();
 154   
 155  16 indent().append("<constant-pool>").eol();
 156  16 raiseIndent();
 157   
 158  16 for (ConstantPoolEntry entry : constantPool) {
 159  337 if (entry != null) {
 160  321 entry.accept(this);
 161    }
 162  337 incrementCount();
 163    }
 164   
 165  16 lowerIndent();
 166  16 indent().append("</constant-pool>").eol();
 167    }
 168   
 169  114 public void visitClass_info(Class_info entry) {
 170  114 if (top) {
 171  48 top = false;
 172  48 indent();
 173  48 append("<class index=\"").append(currentCount()).append("\">");
 174    // entry.getRawName().accept(this);
 175  48 append(entry.getName());
 176  48 append("</class>").eol();
 177  48 top = true;
 178    } else {
 179    // entry.getRawName().accept(this);
 180  66 append(entry.getName());
 181    }
 182    }
 183   
 184  26 public void visitFieldRef_info(FieldRef_info entry) {
 185  26 Class_info c = entry.getRawClass();
 186  26 NameAndType_info nat = entry.getRawNameAndType();
 187   
 188  26 if (top) {
 189  8 top = false;
 190  8 indent();
 191  8 append("<field-ref-info index=\"").append(currentCount()).append("\">");
 192  8 append("<class>");
 193  8 c.accept(this);
 194  8 append("</class>");
 195  8 append("<type>");
 196  8 nat.getRawType().accept(this);
 197  8 append("</type>");
 198  8 append("<name>");
 199  8 nat.getRawName().accept(this);
 200  8 append("</name>");
 201  8 append("</field-ref-info>").eol();
 202  8 top = true;
 203    } else {
 204  18 append(DescriptorHelper.getType(nat.getType()));
 205  18 append(" ");
 206  18 append(entry.getFullSignature());
 207    }
 208    }
 209   
 210  40 public void visitMethodRef_info(MethodRef_info entry) {
 211  40 Class_info c = entry.getRawClass();
 212  40 NameAndType_info nat = entry.getRawNameAndType();
 213   
 214  40 if (top) {
 215  16 top = false;
 216  16 indent();
 217  16 append("<method-ref-info index=\"").append(currentCount()).append("\">");
 218  16 append("<class>");
 219  16 c.accept(this);
 220  16 append("</class>");
 221  16 append("<name>");
 222  16 nat.getRawName().accept(this);
 223  16 append("</name>");
 224  16 append("<type>");
 225  16 nat.getRawType().accept(this);
 226  16 append("</type>");
 227  16 append("</method-ref-info>").eol();
 228  16 top = true;
 229    } else {
 230  24 if (!entry.isConstructor() && !entry.isStaticInitializer()) {
 231  6 append(DescriptorHelper.getReturnType(nat.getType())).append(" ");
 232    }
 233  24 append(entry.getFullSignature());
 234    }
 235    }
 236   
 237  0 public void visitInterfaceMethodRef_info(InterfaceMethodRef_info entry) {
 238  0 Class_info c = entry.getRawClass();
 239  0 NameAndType_info nat = entry.getRawNameAndType();
 240   
 241  0 if (top) {
 242  0 top = false;
 243  0 indent();
 244  0 append("<interface-method-ref-info index=\"").append(currentCount()).append("\">");
 245  0 append("<class>");
 246  0 c.accept(this);
 247  0 append("</class>");
 248  0 append("<name>");
 249  0 nat.getRawName().accept(this);
 250  0 append("</name>");
 251  0 append("<type>");
 252  0 nat.getRawType().accept(this);
 253  0 append("</type>");
 254  0 append("</interface-method-ref-info>").eol();
 255  0 top = true;
 256    } else {
 257  0 append(DescriptorHelper.getReturnType(nat.getType()));
 258  0 append(" ");
 259  0 append(entry.getFullSignature());
 260    }
 261    }
 262   
 263  18 public void visitString_info(String_info entry) {
 264  18 if (top) {
 265  6 top = false;
 266  6 indent();
 267  6 append("<string-info index=\"").append(currentCount()).append("\">");
 268  6 entry.getRawValue().accept(this);
 269  6 append("</string-info>").eol();
 270  6 top = true;
 271    } else {
 272  12 entry.getRawValue().accept(this);
 273    }
 274    }
 275   
 276  22 public void visitInteger_info(Integer_info entry) {
 277  22 if (top) {
 278  9 top = false;
 279  9 indent();
 280  9 append("<integer-info index=\"").append(currentCount()).append("\">");
 281  9 append(entry.getValue());
 282  9 append("</integer-info>").eol();
 283  9 top = true;
 284    } else {
 285  13 append(entry.getValue());
 286    }
 287    }
 288   
 289  2 public void visitFloat_info(Float_info entry) {
 290  2 if (top) {
 291  1 top = false;
 292  1 indent();
 293  1 append("<float-info index=\"").append(currentCount()).append("\">");
 294  1 append(entry.getValue());
 295  1 append("</float-info>").eol();
 296  1 top = true;
 297    } else {
 298  1 append(entry.getValue());
 299    }
 300    }
 301   
 302  0 public void visitLong_info(Long_info entry) {
 303  0 if (top) {
 304  0 top = false;
 305  0 indent();
 306  0 append("<long-info index=\"").append(currentCount()).append("\">");
 307  0 append(entry.getValue());
 308  0 append("</long-info>").eol();
 309  0 top = true;
 310    } else {
 311  0 append(entry.getValue());
 312    }
 313    }
 314   
 315  0 public void visitDouble_info(Double_info entry) {
 316  0 if (top) {
 317  0 top = false;
 318  0 indent();
 319  0 append("<double-info index=\"").append(currentCount()).append("\">");
 320  0 append(entry.getValue());
 321  0 append("</double-info>").eol();
 322  0 top = true;
 323    } else {
 324  0 append(entry.getValue());
 325    }
 326    }
 327   
 328  24 public void visitNameAndType_info(NameAndType_info entry) {
 329  24 if (top) {
 330  24 top = false;
 331  24 indent();
 332  24 append("<name-and-type-info index=\"").append(currentCount()).append("\">");
 333  24 append("<name>");
 334  24 entry.getRawName().accept(this);
 335  24 append("</name>");
 336  24 append("<type>");
 337  24 entry.getRawType().accept(this);
 338  24 append("</type>");
 339  24 append("</name-and-type-info>").eol();
 340  24 top = true;
 341    } else {
 342  0 entry.getRawName().accept(this);
 343  0 append(" ");
 344  0 entry.getRawType().accept(this);
 345    }
 346    }
 347   
 348  397 public void visitUTF8_info(UTF8_info entry) {
 349  397 if (top) {
 350  209 top = false;
 351  209 indent().append("<utf8-info index=\"").append(currentCount()).append("\">");
 352  209 append(escapeXMLCharacters(entry.getValue()));
 353  209 append("</utf8-info>").eol();
 354  209 top = true;
 355    } else {
 356  188 append(escapeXMLCharacters(entry.getValue()));
 357    }
 358    }
 359   
 360  45 public void visitField_info(Field_info entry) {
 361  45 indent().append("<field-info access-flag=\"").append(format.format(entry.getAccessFlag())).append("\">").eol();
 362  45 raiseIndent();
 363   
 364  28 if (entry.isPublic()) indent().append("<public/>").eol();
 365  1 if (entry.isProtected()) indent().append("<protected/>").eol();
 366  1 if (entry.isPrivate()) indent().append("<private/>").eol();
 367  21 if (entry.isStatic()) indent().append("<static/>").eol();
 368  21 if (entry.isFinal()) indent().append("<final/>").eol();
 369  1 if (entry.isVolatile()) indent().append("<volatile/>").eol();
 370  1 if (entry.isTransient()) indent().append("<transient/>").eol();
 371  1 if (entry.isSynthetic()) indent().append("<synthetic/>").eol();
 372  1 if (entry.isEnum()) indent().append("<enum/>").eol();
 373   
 374  45 indent();
 375  45 append("<name>");
 376  45 entry.getRawName().accept(this);
 377  45 append("</name>").eol();
 378   
 379  45 indent().append("<type>").append(entry.getType()).append("</type>").eol();
 380   
 381  45 if (!entry.getAttributes().isEmpty()) {
 382  39 indent().append("<attributes>").eol();
 383  39 raiseIndent();
 384  39 super.visitField_info(entry);
 385  39 lowerIndent();
 386  39 indent().append("</attributes>").eol();
 387    }
 388   
 389  45 lowerIndent();
 390  45 indent().append("</field-info>").eol();
 391    }
 392   
 393  61 public void visitMethod_info(Method_info entry) {
 394  61 indent().append("<method-info access-flag=\"").append(format.format(entry.getAccessFlag())).append("\">").eol();
 395  61 raiseIndent();
 396   
 397  37 if (entry.isPublic()) indent().append("<public/>").eol();
 398  1 if (entry.isProtected()) indent().append("<protected/>").eol();
 399  2 if (entry.isPrivate()) indent().append("<private/>").eol();
 400  3 if (entry.isStatic()) indent().append("<static/>").eol();
 401  1 if (entry.isFinal()) indent().append("<final/>").eol();
 402  1 if (entry.isSynchronized()) indent().append("<synchronized/>").eol();
 403  1 if (entry.isBridge()) indent().append("<bridge/>").eol();
 404  1 if (entry.isVarargs()) indent().append("<varargs/>").eol();
 405  1 if (entry.isNative()) indent().append("<native/>").eol();
 406  8 if (entry.isAbstract()) indent().append("<abstract/>").eol();
 407  1 if (entry.isStrict()) indent().append("<strict/>").eol();
 408  1 if (entry.isSynthetic()) indent().append("<synthetic/>").eol();
 409   
 410  61 indent();
 411  61 append("<name>");
 412  61 entry.getRawName().accept(this);
 413  61 append("</name>").eol();
 414   
 415  61 if (!entry.getName().equals("<init>") && !entry.getName().equals("<clinit>")) {
 416  45 indent().append("<return-type>").append((entry.getReturnType() != null) ? entry.getReturnType() : "void").append("</return-type>").eol();
 417    }
 418  61 indent().append("<signature>").append(entry.getSignature()).append("</signature>").eol();
 419   
 420  61 if (!entry.getAttributes().isEmpty()) {
 421  55 indent().append("<attributes>").eol();
 422  55 raiseIndent();
 423  55 super.visitMethod_info(entry);
 424  55 lowerIndent();
 425  55 indent().append("</attributes>").eol();
 426    }
 427   
 428  61 lowerIndent();
 429  61 indent().append("</method-info>").eol();
 430    }
 431   
 432  20 public void visitConstantValue_attribute(ConstantValue_attribute attribute) {
 433  20 indent().append("<constant-value-attribute>");
 434   
 435  20 attribute.getRawValue().accept(this);
 436   
 437  20 append("</constant-value-attribute>").eol();
 438    }
 439   
 440  30 public void visitCode_attribute(Code_attribute attribute) {
 441  30 indent().append("<code-attribute>").eol();
 442  30 raiseIndent();
 443   
 444  30 indent().append("<length>").append(attribute.getCode().length).append("</length>").eol();
 445   
 446  30 indent().append("<instructions>").eol();
 447  30 raiseIndent();
 448  30 for (Instruction instruction : attribute) {
 449  157 instruction.accept(this);
 450    }
 451  30 lowerIndent();
 452  30 indent().append("</instructions>").eol();
 453   
 454  30 if (!attribute.getExceptionHandlers().isEmpty()) {
 455  2 indent().append("<exception-handlers>").eol();
 456  2 raiseIndent();
 457  2 for (ExceptionHandler exceptionHandler : attribute.getExceptionHandlers()) {
 458  2 exceptionHandler.accept(this);
 459    }
 460  2 lowerIndent();
 461  2 indent().append("</exception-handlers>").eol();
 462    }
 463   
 464  30 if (!attribute.getAttributes().isEmpty()) {
 465  4 indent().append("<attributes>").eol();
 466  4 raiseIndent();
 467  4 for (Attribute_info attribute_info : attribute.getAttributes()) {
 468  10 attribute_info.accept(this);
 469    }
 470  4 lowerIndent();
 471  4 indent().append("</attributes>").eol();
 472    }
 473   
 474  30 lowerIndent();
 475  30 indent().append("</code-attribute>").eol();
 476    }
 477   
 478  0 public void visitExceptions_attribute(Exceptions_attribute attribute) {
 479  0 indent().append("<exceptions-attribute>").eol();
 480  0 raiseIndent();
 481   
 482  0 for (Class_info exception : attribute.getExceptions()) {
 483  0 indent();
 484  0 append("<exception>");
 485  0 exception.accept(this);
 486  0 append("</exception>").eol();
 487    }
 488   
 489  0 lowerIndent();
 490  0 indent().append("</exceptions-attribute>").eol();
 491    }
 492   
 493  2 public void visitInnerClasses_attribute(InnerClasses_attribute attribute) {
 494  2 indent().append("<inner-classes-attribute>").eol();
 495  2 raiseIndent();
 496   
 497  2 super.visitInnerClasses_attribute(attribute);
 498   
 499  2 lowerIndent();
 500  2 indent().append("</inner-classes-attribute>").eol();
 501    }
 502   
 503  0 public void visitEnclosingMethod_attribute(EnclosingMethod_attribute attribute) {
 504  0 indent().append("<enclosing-method-attribute>").eol();
 505  0 raiseIndent();
 506   
 507  0 indent().append("<class>");
 508  0 attribute.getRawClassInfo().accept(this);
 509  0 append("</class>").eol();
 510   
 511  0 indent().append("<method>");
 512  0 if (attribute.getMethodIndex() != 0) {
 513  0 NameAndType_info nat = attribute.getRawMethod();
 514  0 append(DescriptorHelper.getReturnType(nat.getType())).append(" ").append(nat.getName()).append(DescriptorHelper.getSignature(nat.getType()));
 515    }
 516  0 append("</method>").eol();
 517   
 518  0 lowerIndent();
 519  0 indent().append("</enclosing-method-attribute>").eol();
 520    }
 521   
 522  0 public void visitSynthetic_attribute(Synthetic_attribute attribute) {
 523  0 indent().append("<synthetic-attribute/>").eol();
 524    }
 525   
 526  0 public void visitSignature_attribute(Signature_attribute attribute) {
 527  0 indent().append("<signature-attribute>");
 528  0 attribute.getRawSignature().accept(this);
 529  0 append("</signature-attribute>").eol();
 530    }
 531   
 532  2 public void visitSourceFile_attribute(SourceFile_attribute attribute) {
 533  2 indent().append("<source-file-attribute>").append(attribute.getSourceFile()).append("</source-file-attribute>").eol();
 534    }
 535   
 536  4 public void visitLineNumberTable_attribute(LineNumberTable_attribute attribute) {
 537  4 indent().append("<line-number-table-attribute>").eol();
 538  4 raiseIndent();
 539   
 540  4 super.visitLineNumberTable_attribute(attribute);
 541   
 542  4 lowerIndent();
 543  4 indent().append("</line-number-table-attribute>").eol();
 544    }
 545   
 546  4 public void visitLocalVariableTable_attribute(LocalVariableTable_attribute attribute) {
 547  4 indent().append("<local-variable-table-attribute>").eol();
 548  4 raiseIndent();
 549   
 550  4 super.visitLocalVariableTable_attribute(attribute);
 551   
 552  4 lowerIndent();
 553  4 indent().append("</local-variable-table-attribute>").eol();
 554    }
 555   
 556  0 public void visitLocalVariableTypeTable_attribute(LocalVariableTypeTable_attribute attribute) {
 557  0 indent().append("<local-variable-type-table-attribute>").eol();
 558  0 raiseIndent();
 559   
 560  0 super.visitLocalVariableTypeTable_attribute(attribute);
 561   
 562  0 lowerIndent();
 563  0 indent().append("</local-variable-type-table-attribute>").eol();
 564    }
 565   
 566  7 public void visitDeprecated_attribute(Deprecated_attribute attribute) {
 567  7 indent().append("<deprecated-attribute/>").eol();
 568    }
 569   
 570  2 public void visitRuntimeVisibleAnnotations_attribute(RuntimeVisibleAnnotations_attribute attribute) {
 571  2 indent().append("<runtime-visible-annotations-attribute>").eol();
 572  2 raiseIndent();
 573   
 574  2 super.visitRuntimeVisibleAnnotations_attribute(attribute);
 575   
 576  2 lowerIndent();
 577  2 indent().append("</runtime-visible-annotations-attribute>").eol();
 578    }
 579   
 580  2 public void visitRuntimeInvisibleAnnotations_attribute(RuntimeInvisibleAnnotations_attribute attribute) {
 581  2 indent().append("<runtime-invisible-annotations-attribute>").eol();
 582  2 raiseIndent();
 583   
 584  2 super.visitRuntimeInvisibleAnnotations_attribute(attribute);
 585   
 586  2 lowerIndent();
 587  2 indent().append("</runtime-invisible-annotations-attribute>").eol();
 588    }
 589   
 590  4 protected void visitRuntimeAnnotations_attribute(RuntimeAnnotations_attribute attribute) {
 591  4 indent().append("<annotations>").eol();
 592  4 raiseIndent();
 593   
 594  4 super.visitRuntimeAnnotations_attribute(attribute);
 595   
 596  4 lowerIndent();
 597  4 indent().append("</annotations>").eol();
 598    }
 599   
 600  2 public void visitRuntimeVisibleParameterAnnotations_attribute(RuntimeVisibleParameterAnnotations_attribute attribute) {
 601  2 indent().append("<runtime-visible-parameter-annotations-attribute>").eol();
 602  2 raiseIndent();
 603   
 604  2 super.visitRuntimeVisibleParameterAnnotations_attribute(attribute);
 605   
 606  2 lowerIndent();
 607  2 indent().append("</runtime-visible-parameter-annotations-attribute>").eol();
 608    }
 609   
 610  2 public void visitRuntimeInvisibleParameterAnnotations_attribute(RuntimeInvisibleParameterAnnotations_attribute attribute) {
 611  2 indent().append("<runtime-invisible-parameter-annotations-attribute>").eol();
 612  2 raiseIndent();
 613   
 614  2 super.visitRuntimeInvisibleParameterAnnotations_attribute(attribute);
 615   
 616  2 lowerIndent();
 617  2 indent().append("</runtime-invisible-parameter-annotations-attribute>").eol();
 618    }
 619   
 620  4 protected void visitRuntimeParameterAnnotations_attribute(RuntimeParameterAnnotations_attribute attribute) {
 621  4 indent().append("<parameter-annotations>").eol();
 622  4 raiseIndent();
 623   
 624  4 super.visitRuntimeParameterAnnotations_attribute(attribute);
 625   
 626  4 lowerIndent();
 627  4 indent().append("</parameter-annotations>").eol();
 628    }
 629   
 630  1 public void visitAnnotationDefault_attribute(AnnotationDefault_attribute attribute) {
 631  1 indent().append("<annotation-default-attribute>").eol();
 632  1 raiseIndent();
 633   
 634  1 super.visitAnnotationDefault_attribute(attribute);
 635   
 636  1 lowerIndent();
 637  1 indent().append("</annotation-default-attribute>").eol();
 638    }
 639   
 640  2 public void visitCustom_attribute(Custom_attribute attribute) {
 641  2 indent().append("<custom-attribute name=\"").append(escapeXMLCharacters(attribute.getName())).append("\">").append(Hex.toString(attribute.getInfo())).append("</custom-attribute>").eol();
 642    }
 643   
 644  157 public void visitInstruction(Instruction instruction) {
 645  157 indent();
 646  157 append("<instruction pc=\"").append(instruction.getStart()).append("\" length=\"").append(instruction.getLength()).append("\"");
 647  157 switch (instruction.getOpcode()) {
 648  0 case 0x02: // iconst_m1
 649  1 case 0x03: // iconst_0
 650  8 case 0x04: // iconst_1
 651  0 case 0x05: // iconst_2
 652  0 case 0x06: // iconst_3
 653  1 case 0x07: // iconst_4
 654  0 case 0x08: // iconst_5
 655  0 case 0x09: // lconst_0
 656  0 case 0x0a: // lconst_1
 657  0 case 0x0b: // fconst_0
 658  0 case 0x0c: // fconst_1
 659  0 case 0x0d: // fconst_2
 660  0 case 0x0e: // dconst_0
 661  0 case 0x0f: // dconst_1
 662  10 append(" value=\"").append(instruction.getValue()).append("\">");
 663  10 append(instruction);
 664  10 break;
 665  0 case 0x10: // bipush
 666  2 case 0x11: // sipush
 667  2 append(" value=\"").append(instruction.getValue()).append("\">");
 668  2 append(instruction).append(" ").append(instruction.getValue());
 669  2 break;
 670  6 case 0x12: // ldc
 671  0 case 0x13: // ldc_w
 672  0 case 0x14: // ldc2_w
 673  10 case 0xb2: // getstatic
 674  0 case 0xb3: // putstatic
 675  8 case 0xb4: // getfield
 676  0 case 0xb5: // putfield
 677  4 case 0xb6: // invokevirtual
 678  18 case 0xb7: // invokespecial
 679  2 case 0xb8: // invokestatic
 680  0 case 0xb9: // invokeinterface
 681  2 case 0xbb: // new
 682  0 case 0xbd: // anewarray
 683  0 case 0xc0: // checkcast
 684  0 case 0xc1: // instanceof
 685  0 case 0xc5: // multianewarray
 686  50 append(" index=\"").append(instruction.getIndex()).append("\">");
 687  50 append(instruction);
 688  50 append(" ");
 689  50 instruction.getIndexedConstantPoolEntry().accept(this);
 690  50 break;
 691  0 case 0x1a: // iload_0
 692  0 case 0x1e: // lload_0
 693  0 case 0x22: // fload_0
 694  0 case 0x26: // dload_0
 695  18 case 0x2a: // aload_0
 696  0 case 0x3b: // istore_0
 697  0 case 0x3f: // lstore_0
 698  0 case 0x43: // fstore_0
 699  0 case 0x47: // dstore_0
 700  0 case 0x4b: // astore_0
 701  0 case 0x1b: // iload_1
 702  0 case 0x1f: // lload_1
 703  2 case 0x23: // fload_1
 704  0 case 0x27: // dload_1
 705  2 case 0x2b: // aload_1
 706  1 case 0x3c: // istore_1
 707  0 case 0x40: // lstore_1
 708  0 case 0x44: // fstore_1
 709  0 case 0x48: // dstore_1
 710  4 case 0x4c: // astore_1
 711  0 case 0x1c: // iload_2
 712  0 case 0x20: // lload_2
 713  0 case 0x24: // fload_2
 714  0 case 0x28: // dload_2
 715  0 case 0x2c: // aload_2
 716  0 case 0x3d: // istore_2
 717  0 case 0x41: // lstore_2
 718  1 case 0x45: // fstore_2
 719  0 case 0x49: // dstore_2
 720  0 case 0x4d: // astore_2
 721  0 case 0x1d: // iload_3
 722  0 case 0x21: // lload_3
 723  0 case 0x25: // fload_3
 724  0 case 0x29: // dload_3
 725  0 case 0x2d: // aload_3
 726  0 case 0x3e: // istore_3
 727  0 case 0x42: // lstore_3
 728  0 case 0x46: // fstore_3
 729  0 case 0x4a: // dstore_3
 730  0 case 0x4e: // astore_3
 731  0 case 0x15: // iload
 732  0 case 0x16: // llload
 733  0 case 0x17: // fload
 734  0 case 0x18: // dload
 735  0 case 0x19: // aload
 736  0 case 0x36: // istore
 737  0 case 0x37: // lstore
 738  0 case 0x38: // fstore
 739  0 case 0x39: // dstore
 740  0 case 0x3a: // astore
 741  0 case 0xa9: // ret
 742  28 append(" index=\"").append(instruction.getIndex()).append("\">");
 743  28 append(instruction);
 744  28 appendLocalVariable(instruction.getIndexedLocalVariable());
 745  28 break;
 746  0 case 0x99: // ifeq
 747  0 case 0x9a: // ifne
 748  0 case 0x9b: // iflt
 749  0 case 0x9c: // ifge
 750  0 case 0x9d: // ifgt
 751  0 case 0x9e: // ifle
 752  0 case 0x9f: // if_icmpeq
 753  0 case 0xa0: // if_icmpne
 754  0 case 0xa1: // if_icmplt
 755  0 case 0xa2: // if_icmpge
 756  0 case 0xa3: // if_icmpgt
 757  0 case 0xa4: // if_icmple
 758  0 case 0xa5: // if_acmpeq
 759  0 case 0xa6: // if_acmpne
 760  2 case 0xa7: // goto
 761  0 case 0xa8: // jsr
 762  0 case 0xc6: // ifnull
 763  0 case 0xc7: // ifnonnull
 764  0 case 0xc8: // goto_w
 765  0 case 0xc9: // jsr_w
 766  2 append(" offset=\"").append(instruction.getOffset()).append("\">");
 767  2 append(instruction).append(" ").append(instruction.getStart() + instruction.getOffset());
 768  2 break;
 769  0 case 0x84: // iinc
 770  0 append(" index=\"").append(instruction.getIndex()).append("\" value=\"").append(instruction.getValue()).append("\">");
 771  0 append(instruction);
 772  0 appendLocalVariable(instruction.getIndexedLocalVariable());
 773  0 break;
 774  0 case 0xc4: // wide
 775  0 if (instruction.getByte(1) == 0x84 /* iinc */) {
 776  0 append(" index=\"").append(instruction.getIndex()).append("\" value=\"").append(instruction.getValue()).append("\">");
 777    } else {
 778  0 append(" index=\"").append(instruction.getIndex()).append("\">");
 779    }
 780  0 append(instruction);
 781  0 appendLocalVariable(instruction.getIndexedLocalVariable());
 782  0 break;
 783  65 default:
 784  65 append(">");
 785  65 append(instruction);
 786  65 break;
 787    }
 788  157 append("</instruction>").eol();
 789    }
 790   
 791  2 public void visitExceptionHandler(ExceptionHandler helper) {
 792  2 indent();
 793  2 append("<exception-handler>");
 794  2 append("<start-pc>").append(helper.getStartPC()).append("</start-pc>");
 795  2 append("<end-pc>").append(helper.getEndPC()).append("</end-pc>");
 796  2 append("<handler-pc>").append(helper.getHandlerPC()).append("</handler-pc>");
 797   
 798  2 append("<catch-type>");
 799  2 if (helper.getCatchTypeIndex() != 0) {
 800  2 helper.getRawCatchType().accept(this);
 801    }
 802  2 append("</catch-type>");
 803   
 804  2 append("</exception-handler>").eol();
 805    }
 806   
 807  22 public void visitInnerClass(InnerClass helper) {
 808  22 indent().append("<inner-class access-flag=\"").append(format.format(helper.getAccessFlag())).append("\">").eol();
 809  22 raiseIndent();
 810   
 811  3 if (helper.isPublic()) indent().append("<public/>").eol();
 812  1 if (helper.isProtected()) indent().append("<protected/>").eol();
 813  1 if (helper.isPrivate()) indent().append("<private/>").eol();
 814  3 if (helper.isStatic()) indent().append("<static/>").eol();
 815  1 if (helper.isFinal()) indent().append("<final/>").eol();
 816  1 if (helper.isInterface()) indent().append("<is-interface/>").eol();
 817  1 if (helper.isAbstract()) indent().append("<abstract/>").eol();
 818  1 if (helper.isSynthetic()) indent().append("<synthetic/>").eol();
 819  1 if (helper.isAnnotation()) indent().append("<is-annotation/>").eol();
 820  1 if (helper.isEnum()) indent().append("<enum/>").eol();
 821   
 822  22 indent();
 823  22 append("<inner-class-info>");
 824  22 if (helper.getInnerClassInfoIndex() != 0) {
 825  2 helper.getRawInnerClassInfo().accept(this);
 826    }
 827  22 append("</inner-class-info>").eol();
 828   
 829  22 indent();
 830  22 append("<outer-class-info>");
 831  22 if (helper.getOuterClassInfoIndex() != 0) {
 832  2 helper.getRawOuterClassInfo().accept(this);
 833    }
 834  22 append("</outer-class-info>").eol();
 835   
 836  22 indent();
 837  22 append("<inner-name>");
 838  22 if (helper.getInnerNameIndex() != 0) {
 839  2 helper.getRawInnerName().accept(this);
 840    }
 841  22 append("</inner-name>").eol();
 842   
 843  22 lowerIndent();
 844  22 indent().append("</inner-class>").eol();
 845    }
 846   
 847  16 public void visitLineNumber(LineNumber helper) {
 848  16 indent();
 849  16 append("<line-number>");
 850  16 append("<start-pc>").append(helper.getStartPC()).append("</start-pc>");
 851  16 append("<line>").append(helper.getLineNumber()).append("</line>");
 852  16 append("</line-number>").eol();
 853    }
 854   
 855  9 public void visitLocalVariable(LocalVariable helper) {
 856  9 indent();
 857  9 append("<local-variable pc=\"").append(helper.getStartPC()).append("\" length=\"").append(helper.getLength()).append("\" index=\"").append(helper.getIndex()).append("\">");
 858  9 append("<name>");
 859  9 helper.getRawName().accept(this);
 860  9 append("</name>");
 861   
 862  9 append("<type>").append(DescriptorHelper.getType(helper.getDescriptor())).append("</type>");
 863  9 append("</local-variable>").eol();
 864    }
 865   
 866  1 public void visitLocalVariableType(LocalVariableType helper) {
 867  1 indent();
 868  1 append("<local-variable-type pc=\"").append(helper.getStartPC()).append("\" length=\"").append(helper.getLength()).append("\" index=\"").append(helper.getIndex()).append("\">");
 869  1 append("<name>");
 870  1 helper.getRawName().accept(this);
 871  1 append("</name>");
 872   
 873  1 append("<signature>");
 874  1 helper.getRawSignature().accept(this);
 875  1 append("</signature>");
 876  1 append("</local-variable-type>").eol();
 877    }
 878   
 879  2 public void visitParameter(Parameter helper) {
 880  2 indent().append("<parameter>").eol();
 881  2 raiseIndent();
 882   
 883  2 indent().append("<annotations>").eol();
 884  2 raiseIndent();
 885   
 886  2 super.visitParameter(helper);
 887   
 888  2 lowerIndent();
 889  2 indent().append("</annotations>").eol();
 890   
 891  2 lowerIndent();
 892  2 indent().append("</parameter>").eol();
 893    }
 894   
 895  2 public void visitAnnotation(Annotation helper) {
 896  2 indent().append("<annotation>").eol();
 897  2 raiseIndent();
 898   
 899  2 indent().append("<type>").append(helper.getType()).append("</type>").eol();
 900   
 901  2 indent().append("<element-value-pairs>").eol();
 902  2 raiseIndent();
 903   
 904  2 super.visitAnnotation(helper);
 905   
 906  2 lowerIndent();
 907  2 indent().append("</element-value-pairs>").eol();
 908   
 909  2 lowerIndent();
 910  2 indent().append("</annotation>").eol();
 911    }
 912   
 913  1 public void visitElementValuePair(ElementValuePair helper) {
 914  1 indent().append("<element-value-pair>").eol();
 915  1 raiseIndent();
 916   
 917  1 indent().append("<element-name>").append(helper.getElementName()).append("</element-name>").eol();
 918   
 919  1 super.visitElementValuePair(helper);
 920   
 921  1 lowerIndent();
 922  1 indent().append("</element-value-pair>").eol();
 923    }
 924   
 925  1 public void visitByteConstantElementValue(ByteConstantElementValue helper) {
 926  1 visitConstantElementValue(helper, "byte");
 927    }
 928   
 929  1 public void visitCharConstantElementValue(CharConstantElementValue helper) {
 930  1 visitConstantElementValue(helper, "char");
 931    }
 932   
 933  1 public void visitDoubleConstantElementValue(DoubleConstantElementValue helper) {
 934  1 visitConstantElementValue(helper, "double");
 935    }
 936   
 937  1 public void visitFloatConstantElementValue(FloatConstantElementValue helper) {
 938  1 visitConstantElementValue(helper, "float");
 939    }
 940   
 941  1 public void visitIntegerConstantElementValue(IntegerConstantElementValue helper) {
 942  1 visitConstantElementValue(helper, "integer");
 943    }
 944   
 945  1 public void visitLongConstantElementValue(LongConstantElementValue helper) {
 946  1 visitConstantElementValue(helper, "long");
 947    }
 948   
 949  1 public void visitShortConstantElementValue(ShortConstantElementValue helper) {
 950  1 visitConstantElementValue(helper, "short");
 951    }
 952   
 953  1 public void visitBooleanConstantElementValue(BooleanConstantElementValue helper) {
 954  1 visitConstantElementValue(helper, "boolean");
 955    }
 956   
 957  1 public void visitStringConstantElementValue(StringConstantElementValue helper) {
 958  1 visitConstantElementValue(helper, "string");
 959    }
 960   
 961  9 private void visitConstantElementValue(ConstantElementValue helper, String type) {
 962  9 indent();
 963  9 append("<").append(type).append("-element-value tag=\"").append(helper.getTag()).append("\">");
 964  9 helper.getRawConstValue().accept(this);
 965  9 append("</").append(type).append("-element-value>").eol();
 966    }
 967   
 968  1 public void visitEnumElementValue(EnumElementValue helper) {
 969  1 indent();
 970  1 append("<enum-element-value tag=\"").append(helper.getTag()).append("\">");
 971  1 append(helper.getTypeName()).append(".").append(helper.getConstName());
 972  1 append("</enum-element-value>").eol();
 973    }
 974   
 975  1 public void visitClassElementValue(ClassElementValue helper) {
 976  1 indent();
 977  1 append("<class-element-value tag=\"").append(helper.getTag()).append("\">");
 978  1 append(helper.getClassInfo());
 979  1 append("</class-element-value>").eol();
 980    }
 981   
 982  1 public void visitAnnotationElementValue(AnnotationElementValue helper) {
 983  1 indent().append("<annotation-element-value tag=\"").append(helper.getTag()).append("\">").eol();
 984  1 raiseIndent();
 985   
 986  1 super.visitAnnotationElementValue(helper);
 987   
 988  1 lowerIndent();
 989  1 indent().append("</annotation-element-value>").eol();
 990    }
 991   
 992  1 public void visitArrayElementValue(ArrayElementValue helper) {
 993  1 indent().append("<array-element-value tag=\"").append(helper.getTag()).append("\">").eol();
 994  1 raiseIndent();
 995   
 996  1 super.visitArrayElementValue(helper);
 997   
 998  1 lowerIndent();
 999  1 indent().append("</array-element-value>").eol();
 1000    }
 1001   
 1002  28 private void appendLocalVariable(LocalVariable localVariable) {
 1003  28 if (localVariable != null) {
 1004  8 append(" ");
 1005  8 append(DescriptorHelper.getType(localVariable.getDescriptor())).append(" ").append(localVariable.getName());
 1006    }
 1007    }
 1008   
 1009  404 @VisibleForTesting
 1010    String escapeXMLCharacters(String text) {
 1011  404 StringBuilder result = new StringBuilder();
 1012  404 boolean containsControlCharacters = false;
 1013   
 1014  404 for (int i=0; i<text.length(); i++) {
 1015  4618 char c = text.charAt(i);
 1016  4618 if (c == '&') {
 1017  4 result.append("&amp;");
 1018  4614 } else if (c == '<') {
 1019  51 result.append("&lt;");
 1020  4563 } else if (c == '>') {
 1021  51 result.append("&gt;");
 1022  4512 } else if (Character.isISOControl(c) || c > 0x9F) {
 1023  7 containsControlCharacters = true;
 1024  7 result.append("&#x");
 1025  7 result.append(Integer.toString(c, 16).toUpperCase());
 1026  7 result.append(";");
 1027    } else {
 1028  4505 result.append(c);
 1029    }
 1030    }
 1031   
 1032  404 if (containsControlCharacters) {
 1033  7 return "<![CDATA[" + result.toString() + "]]>";
 1034    } else {
 1035  397 return result.toString();
 1036    }
 1037    }
 1038    }