001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.bcel.verifier.statics; 020 021import org.apache.bcel.classfile.AnnotationDefault; 022import org.apache.bcel.classfile.AnnotationEntry; 023import org.apache.bcel.classfile.Annotations; 024import org.apache.bcel.classfile.BootstrapMethods; 025import org.apache.bcel.classfile.Code; 026import org.apache.bcel.classfile.CodeException; 027import org.apache.bcel.classfile.ConstantClass; 028import org.apache.bcel.classfile.ConstantDouble; 029import org.apache.bcel.classfile.ConstantDynamic; 030import org.apache.bcel.classfile.ConstantFieldref; 031import org.apache.bcel.classfile.ConstantFloat; 032import org.apache.bcel.classfile.ConstantInteger; 033import org.apache.bcel.classfile.ConstantInterfaceMethodref; 034import org.apache.bcel.classfile.ConstantInvokeDynamic; 035import org.apache.bcel.classfile.ConstantLong; 036import org.apache.bcel.classfile.ConstantMethodHandle; 037import org.apache.bcel.classfile.ConstantMethodType; 038import org.apache.bcel.classfile.ConstantMethodref; 039import org.apache.bcel.classfile.ConstantModule; 040import org.apache.bcel.classfile.ConstantNameAndType; 041import org.apache.bcel.classfile.ConstantPackage; 042import org.apache.bcel.classfile.ConstantPool; 043import org.apache.bcel.classfile.ConstantString; 044import org.apache.bcel.classfile.ConstantUtf8; 045import org.apache.bcel.classfile.ConstantValue; 046import org.apache.bcel.classfile.Deprecated; 047import org.apache.bcel.classfile.EnclosingMethod; 048import org.apache.bcel.classfile.ExceptionTable; 049import org.apache.bcel.classfile.Field; 050import org.apache.bcel.classfile.InnerClass; 051import org.apache.bcel.classfile.InnerClasses; 052import org.apache.bcel.classfile.JavaClass; 053import org.apache.bcel.classfile.LineNumber; 054import org.apache.bcel.classfile.LineNumberTable; 055import org.apache.bcel.classfile.LocalVariable; 056import org.apache.bcel.classfile.LocalVariableTable; 057import org.apache.bcel.classfile.LocalVariableTypeTable; 058import org.apache.bcel.classfile.Method; 059import org.apache.bcel.classfile.MethodParameter; 060import org.apache.bcel.classfile.MethodParameters; 061import org.apache.bcel.classfile.Module; 062import org.apache.bcel.classfile.ModuleExports; 063import org.apache.bcel.classfile.ModuleMainClass; 064import org.apache.bcel.classfile.ModuleOpens; 065import org.apache.bcel.classfile.ModulePackages; 066import org.apache.bcel.classfile.ModuleProvides; 067import org.apache.bcel.classfile.ModuleRequires; 068import org.apache.bcel.classfile.NestHost; 069import org.apache.bcel.classfile.NestMembers; 070import org.apache.bcel.classfile.Node; 071import org.apache.bcel.classfile.ParameterAnnotationEntry; 072import org.apache.bcel.classfile.ParameterAnnotations; 073import org.apache.bcel.classfile.PermittedSubclasses; 074import org.apache.bcel.classfile.Record; 075import org.apache.bcel.classfile.RecordComponentInfo; 076import org.apache.bcel.classfile.Signature; 077import org.apache.bcel.classfile.SourceFile; 078import org.apache.bcel.classfile.StackMap; 079import org.apache.bcel.classfile.StackMapEntry; 080import org.apache.bcel.classfile.StackMapType; 081import org.apache.bcel.classfile.Synthetic; 082import org.apache.bcel.classfile.TypeAnnotations; 083import org.apache.bcel.classfile.Unknown; 084import org.apache.bcel.verifier.exc.AssertionViolatedException; 085 086/** 087 * BCEL's Node classes (those from the classfile API that {@code accept()} Visitor instances) have {@code toString()} 088 * methods that were not designed to be robust, this gap is closed by this class. When performing class file 089 * verification, it may be useful to output which entity (for example a {@code Code} instance) is not satisfying the verifier's 090 * constraints, but in this case it could be possible for the {@code toString()} method to throw a RuntimeException. A 091 * (new StringRepresentation(Node n)).toString() never throws any exception. Note that this class also serves as a 092 * placeholder for more sophisticated message handling in future versions of JustIce. 093 */ 094public class StringRepresentation extends org.apache.bcel.classfile.EmptyVisitor { 095 096 /** The string representation, created by a visitXXX() method, output by toString(). */ 097 private String tostring; 098 099 /** The node we ask for its string representation. Not really needed; only for debug output. */ 100 private final Node n; 101 102 /** 103 * Creates a new StringRepresentation object which is the representation of n. 104 * 105 * @param n The node to represent. 106 * @see #toString() 107 */ 108 public StringRepresentation(final Node n) { 109 this.n = n; 110 n.accept(this); // assign a string representation to field 'tostring' if we know n's class. 111 } 112 113 /** 114 * Returns the String representation. 115 */ 116 @Override 117 public String toString() { 118 // The run-time check below is needed because we don't want to omit inheritance 119 // of "EmptyVisitor" and provide a thousand empty methods. 120 // However, in terms of performance this would be a better idea. 121 // If some new "Node" is defined in BCEL (such as some concrete "Attribute"), we 122 // want to know that this class has also to be adapted. 123 if (tostring == null) { 124 throw new AssertionViolatedException("Please adapt '" + getClass() + "' to deal with objects of class '" + n.getClass() + "'."); 125 } 126 return tostring; 127 } 128 129 /** 130 * Returns the String representation of the Node object obj; this is obj.toString() if it does not throw any 131 * RuntimeException, or else it is a string derived only from obj's class name. 132 */ 133 private String toString(final Node obj) { 134 String ret; 135 try { 136 ret = obj.toString(); 137 } catch (final RuntimeException e) { 138 // including ClassFormatException, trying to convert the "signature" of a ReturnaddressType LocalVariable 139 // (shouldn't occur, but people do crazy things) 140 String s = obj.getClass().getName(); 141 s = s.substring(s.lastIndexOf(".") + 1); 142 ret = "<<" + s + ">>"; 143 } 144 return ret; 145 } 146 147 /** 148 * @since 6.0 149 */ 150 @Override 151 public void visitAnnotation(final Annotations obj) { 152 // this is invoked whenever an annotation is found 153 // when verifier is passed over a class 154 tostring = toString(obj); 155 } 156 157 /** 158 * @since 6.0 159 */ 160 @Override 161 public void visitAnnotationDefault(final AnnotationDefault obj) { 162 tostring = toString(obj); 163 } 164 165 /** 166 * @since 6.0 167 */ 168 @Override 169 public void visitAnnotationEntry(final AnnotationEntry obj) { 170 tostring = toString(obj); 171 } 172 173 /** 174 * @since 6.0 175 */ 176 @Override 177 public void visitBootstrapMethods(final BootstrapMethods obj) { 178 tostring = toString(obj); 179 } 180 181 //////////////////////////////// 182 // Visitor methods start here // 183 //////////////////////////////// 184 // We don't of course need to call some default implementation: 185 // for example we could also simply output "Code" instead of a possibly 186 // lengthy Code attribute's toString(). 187 @Override 188 public void visitCode(final Code obj) { 189 // tostring = toString(obj); 190 tostring = "<CODE>"; // We don't need real code outputs. 191 } 192 193 @Override 194 public void visitCodeException(final CodeException obj) { 195 tostring = toString(obj); 196 } 197 198 @Override 199 public void visitConstantClass(final ConstantClass obj) { 200 tostring = toString(obj); 201 } 202 203 @Override 204 public void visitConstantDouble(final ConstantDouble obj) { 205 tostring = toString(obj); 206 } 207 208 /** 209 * @since 6.6.0 210 */ 211 @Override 212 public void visitConstantDynamic(final ConstantDynamic obj) { 213 tostring = toString(obj); 214 } 215 216 @Override 217 public void visitConstantFieldref(final ConstantFieldref obj) { 218 tostring = toString(obj); 219 } 220 221 @Override 222 public void visitConstantFloat(final ConstantFloat obj) { 223 tostring = toString(obj); 224 } 225 226 @Override 227 public void visitConstantInteger(final ConstantInteger obj) { 228 tostring = toString(obj); 229 } 230 231 @Override 232 public void visitConstantInterfaceMethodref(final ConstantInterfaceMethodref obj) { 233 tostring = toString(obj); 234 } 235 236 /** 237 * @since 6.0 238 */ 239 @Override 240 public void visitConstantInvokeDynamic(final ConstantInvokeDynamic obj) { 241 tostring = toString(obj); 242 } 243 244 @Override 245 public void visitConstantLong(final ConstantLong obj) { 246 tostring = toString(obj); 247 } 248 249 /** 250 * @since 6.0 251 */ 252 @Override 253 public void visitConstantMethodHandle(final ConstantMethodHandle obj) { 254 tostring = toString(obj); 255 } 256 257 @Override 258 public void visitConstantMethodref(final ConstantMethodref obj) { 259 tostring = toString(obj); 260 } 261 262 /** 263 * @since 6.0 264 */ 265 @Override 266 public void visitConstantMethodType(final ConstantMethodType obj) { 267 tostring = toString(obj); 268 } 269 270 /** 271 * @since 6.6.0 272 */ 273 @Override 274 public void visitConstantModule(final ConstantModule obj) { 275 tostring = toString(obj); 276 } 277 278 @Override 279 public void visitConstantNameAndType(final ConstantNameAndType obj) { 280 tostring = toString(obj); 281 } 282 283 /** 284 * @since 6.6.0 285 */ 286 @Override 287 public void visitConstantPackage(final ConstantPackage obj) { 288 tostring = toString(obj); 289 } 290 291 @Override 292 public void visitConstantPool(final ConstantPool obj) { 293 tostring = toString(obj); 294 } 295 296 @Override 297 public void visitConstantString(final ConstantString obj) { 298 tostring = toString(obj); 299 } 300 301 @Override 302 public void visitConstantUtf8(final ConstantUtf8 obj) { 303 tostring = toString(obj); 304 } 305 306 @Override 307 public void visitConstantValue(final ConstantValue obj) { 308 tostring = toString(obj); 309 } 310 311 @Override 312 public void visitDeprecated(final Deprecated obj) { 313 tostring = toString(obj); 314 } 315 316 /** 317 * @since 6.0 318 */ 319 @Override 320 public void visitEnclosingMethod(final EnclosingMethod obj) { 321 tostring = toString(obj); 322 } 323 324 @Override 325 public void visitExceptionTable(final ExceptionTable obj) { 326 tostring = toString(obj); 327 } 328 329 @Override 330 public void visitField(final Field obj) { 331 tostring = toString(obj); 332 } 333 334 @Override 335 public void visitInnerClass(final InnerClass obj) { 336 tostring = toString(obj); 337 } 338 339 @Override 340 public void visitInnerClasses(final InnerClasses obj) { 341 tostring = toString(obj); 342 } 343 344 @Override 345 public void visitJavaClass(final JavaClass obj) { 346 tostring = toString(obj); 347 } 348 349 @Override 350 public void visitLineNumber(final LineNumber obj) { 351 tostring = toString(obj); 352 } 353 354 @Override 355 public void visitLineNumberTable(final LineNumberTable obj) { 356 tostring = "<LineNumberTable: " + toString(obj) + ">"; 357 } 358 359 @Override 360 public void visitLocalVariable(final LocalVariable obj) { 361 tostring = toString(obj); 362 } 363 364 @Override 365 public void visitLocalVariableTable(final LocalVariableTable obj) { 366 tostring = "<LocalVariableTable: " + toString(obj) + ">"; 367 } 368 369 /** 370 * @since 6.0 371 */ 372 @Override 373 public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj) { 374 // this is invoked whenever a local variable type is found 375 // when verifier is passed over a class 376 tostring = toString(obj); 377 } 378 379 @Override 380 public void visitMethod(final Method obj) { 381 tostring = toString(obj); 382 } 383 384 /** 385 * Visits a method parameter. 386 * 387 * @param obj The node to represent. 388 * @since 6.14.0 389 */ 390 @Override 391 public void visitMethodParameter(final MethodParameter obj) { 392 tostring = toString(obj); 393 } 394 395 /** 396 * @since 6.0 397 */ 398 @Override 399 public void visitMethodParameters(final MethodParameters obj) { 400 tostring = toString(obj); 401 } 402 403 /** 404 * Visits the Module attribute of a module descriptor. 405 * 406 * @since 6.14.0 407 */ 408 @Override 409 public void visitModule(final Module obj) { 410 tostring = toString(obj); 411 } 412 413 /** 414 * Visits a ModuleExports entry of the Module attribute. 415 * 416 * @since 6.14.0 417 */ 418 @Override 419 public void visitModuleExports(final ModuleExports obj) { 420 tostring = toString(obj); 421 } 422 423 /** 424 * Visits the ModuleMainClass attribute of a module descriptor. 425 * 426 * @since 6.14.0 427 */ 428 @Override 429 public void visitModuleMainClass(final ModuleMainClass obj) { 430 tostring = toString(obj); 431 } 432 433 /** 434 * Visits a ModuleOpens entry of the Module attribute. 435 * 436 * @since 6.14.0 437 */ 438 @Override 439 public void visitModuleOpens(final ModuleOpens obj) { 440 tostring = toString(obj); 441 } 442 443 /** 444 * Visits the ModulePackages attribute of a module descriptor. 445 * 446 * @since 6.14.0 447 */ 448 @Override 449 public void visitModulePackages(final ModulePackages obj) { 450 tostring = toString(obj); 451 } 452 453 /** 454 * Visits a ModuleProvides entry of the Module attribute. 455 * 456 * @since 6.14.0 457 */ 458 @Override 459 public void visitModuleProvides(final ModuleProvides obj) { 460 tostring = toString(obj); 461 } 462 463 /** 464 * Visits a ModuleRequires entry of the Module attribute. 465 * 466 * @since 6.14.0 467 */ 468 @Override 469 public void visitModuleRequires(final ModuleRequires obj) { 470 tostring = toString(obj); 471 } 472 473 /** 474 * Visits the NestHost attribute. 475 * 476 * @param obj The node to represent. 477 * @since 6.14.0 478 */ 479 @Override 480 public void visitNestHost(final NestHost obj) { 481 tostring = toString(obj); 482 } 483 484 /** 485 * @since 6.4.0 486 */ 487 @Override 488 public void visitNestMembers(final NestMembers obj) { 489 tostring = toString(obj); 490 } 491 492 /** 493 * @since 6.0 494 */ 495 @Override 496 public void visitParameterAnnotation(final ParameterAnnotations obj) { 497 tostring = toString(obj); 498 } 499 500 /** 501 * @since 6.0 502 */ 503 @Override 504 public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) { 505 tostring = toString(obj); 506 } 507 508 /** 509 * Visits PermittedSubclasses attribute. 510 * 511 * @since 6.13.0 512 */ 513 @Override 514 public void visitPermittedSubclasses(final PermittedSubclasses obj) { 515 tostring = toString(obj); 516 } 517 518 @Override 519 public void visitRecord(final Record obj) { 520 tostring = toString(obj); 521 } 522 523 @Override 524 public void visitRecordComponent(final RecordComponentInfo obj) { 525 tostring = toString(obj); 526 } 527 528 @Override 529 public void visitSignature(final Signature obj) { 530 tostring = toString(obj); 531 } 532 533 @Override 534 public void visitSourceFile(final SourceFile obj) { 535 tostring = toString(obj); 536 } 537 538 @Override 539 public void visitStackMap(final StackMap obj) { 540 tostring = toString(obj); 541 } 542 543 /** 544 * @since 6.0 545 */ 546 @Override 547 public void visitStackMapEntry(final StackMapEntry obj) { 548 tostring = toString(obj); 549 } 550 551 /** 552 * Visits a stack map verification type. 553 * 554 * @param obj The node to represent. 555 * @since 6.14.0 556 */ 557 @Override 558 public void visitStackMapType(final StackMapType obj) { 559 tostring = toString(obj); 560 } 561 562 @Override 563 public void visitSynthetic(final Synthetic obj) { 564 tostring = toString(obj); 565 } 566 567 /** 568 * Visits RuntimeVisibleTypeAnnotations and RuntimeInvisibleTypeAnnotations attributes. 569 * 570 * @since 6.14.0 571 */ 572 @Override 573 public void visitTypeAnnotations(final TypeAnnotations obj) { 574 tostring = toString(obj); 575 } 576 577 @Override 578 public void visitUnknown(final Unknown obj) { 579 tostring = toString(obj); 580 } 581 582}