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.MethodParameters; 060import org.apache.bcel.classfile.NestMembers; 061import org.apache.bcel.classfile.Node; 062import org.apache.bcel.classfile.ParameterAnnotationEntry; 063import org.apache.bcel.classfile.ParameterAnnotations; 064import org.apache.bcel.classfile.PermittedSubclasses; 065import org.apache.bcel.classfile.Record; 066import org.apache.bcel.classfile.RecordComponentInfo; 067import org.apache.bcel.classfile.Signature; 068import org.apache.bcel.classfile.SourceFile; 069import org.apache.bcel.classfile.StackMap; 070import org.apache.bcel.classfile.StackMapEntry; 071import org.apache.bcel.classfile.Synthetic; 072import org.apache.bcel.classfile.Unknown; 073import org.apache.bcel.verifier.exc.AssertionViolatedException; 074 075/** 076 * BCEL's Node classes (those from the classfile API that {@code accept()} Visitor instances) have {@code toString()} 077 * methods that were not designed to be robust, this gap is closed by this class. When performing class file 078 * verification, it may be useful to output which entity (for example a {@code Code} instance) is not satisfying the verifier's 079 * constraints, but in this case it could be possible for the {@code toString()} method to throw a RuntimeException. A 080 * (new StringRepresentation(Node n)).toString() never throws any exception. Note that this class also serves as a 081 * placeholder for more sophisticated message handling in future versions of JustIce. 082 */ 083public class StringRepresentation extends org.apache.bcel.classfile.EmptyVisitor { 084 085 /** The string representation, created by a visitXXX() method, output by toString(). */ 086 private String tostring; 087 088 /** The node we ask for its string representation. Not really needed; only for debug output. */ 089 private final Node n; 090 091 /** 092 * Creates a new StringRepresentation object which is the representation of n. 093 * 094 * @param n The node to represent. 095 * @see #toString() 096 */ 097 public StringRepresentation(final Node n) { 098 this.n = n; 099 n.accept(this); // assign a string representation to field 'tostring' if we know n's class. 100 } 101 102 /** 103 * Returns the String representation. 104 */ 105 @Override 106 public String toString() { 107// The run-time check below is needed because we don't want to omit inheritance 108// of "EmptyVisitor" and provide a thousand empty methods. 109// However, in terms of performance this would be a better idea. 110// If some new "Node" is defined in BCEL (such as some concrete "Attribute"), we 111// want to know that this class has also to be adapted. 112 if (tostring == null) { 113 throw new AssertionViolatedException("Please adapt '" + getClass() + "' to deal with objects of class '" + n.getClass() + "'."); 114 } 115 return tostring; 116 } 117 118 /** 119 * Returns the String representation of the Node object obj; this is obj.toString() if it does not throw any 120 * RuntimeException, or else it is a string derived only from obj's class name. 121 */ 122 private String toString(final Node obj) { 123 String ret; 124 try { 125 ret = obj.toString(); 126 } catch (final RuntimeException e) { 127 // including ClassFormatException, trying to convert the "signature" of a ReturnaddressType LocalVariable 128 // (shouldn't occur, but people do crazy things) 129 String s = obj.getClass().getName(); 130 s = s.substring(s.lastIndexOf(".") + 1); 131 ret = "<<" + s + ">>"; 132 } 133 return ret; 134 } 135 136 /** 137 * @since 6.0 138 */ 139 @Override 140 public void visitAnnotation(final Annotations obj) { 141 // this is invoked whenever an annotation is found 142 // when verifier is passed over a class 143 tostring = toString(obj); 144 } 145 146 /** 147 * @since 6.0 148 */ 149 @Override 150 public void visitAnnotationDefault(final AnnotationDefault obj) { 151 tostring = toString(obj); 152 } 153 154 /** 155 * @since 6.0 156 */ 157 @Override 158 public void visitAnnotationEntry(final AnnotationEntry obj) { 159 tostring = toString(obj); 160 } 161 162 /** 163 * @since 6.0 164 */ 165 @Override 166 public void visitBootstrapMethods(final BootstrapMethods obj) { 167 tostring = toString(obj); 168 } 169 170 //////////////////////////////// 171 // Visitor methods start here // 172 //////////////////////////////// 173 // We don't of course need to call some default implementation: 174 // for example we could also simply output "Code" instead of a possibly 175 // lengthy Code attribute's toString(). 176 @Override 177 public void visitCode(final Code obj) { 178 // tostring = toString(obj); 179 tostring = "<CODE>"; // We don't need real code outputs. 180 } 181 182 @Override 183 public void visitCodeException(final CodeException obj) { 184 tostring = toString(obj); 185 } 186 187 @Override 188 public void visitConstantClass(final ConstantClass obj) { 189 tostring = toString(obj); 190 } 191 192 @Override 193 public void visitConstantDouble(final ConstantDouble obj) { 194 tostring = toString(obj); 195 } 196 197 /** 198 * @since 6.6.0 199 */ 200 @Override 201 public void visitConstantDynamic(final ConstantDynamic obj) { 202 tostring = toString(obj); 203 } 204 205 @Override 206 public void visitConstantFieldref(final ConstantFieldref obj) { 207 tostring = toString(obj); 208 } 209 210 @Override 211 public void visitConstantFloat(final ConstantFloat obj) { 212 tostring = toString(obj); 213 } 214 215 @Override 216 public void visitConstantInteger(final ConstantInteger obj) { 217 tostring = toString(obj); 218 } 219 220 @Override 221 public void visitConstantInterfaceMethodref(final ConstantInterfaceMethodref obj) { 222 tostring = toString(obj); 223 } 224 225 /** 226 * @since 6.0 227 */ 228 @Override 229 public void visitConstantInvokeDynamic(final ConstantInvokeDynamic obj) { 230 tostring = toString(obj); 231 } 232 233 @Override 234 public void visitConstantLong(final ConstantLong obj) { 235 tostring = toString(obj); 236 } 237 238 /** 239 * @since 6.0 240 */ 241 @Override 242 public void visitConstantMethodHandle(final ConstantMethodHandle obj) { 243 tostring = toString(obj); 244 } 245 246 @Override 247 public void visitConstantMethodref(final ConstantMethodref obj) { 248 tostring = toString(obj); 249 } 250 251 /** 252 * @since 6.0 253 */ 254 @Override 255 public void visitConstantMethodType(final ConstantMethodType obj) { 256 tostring = toString(obj); 257 } 258 259 /** 260 * @since 6.6.0 261 */ 262 @Override 263 public void visitConstantModule(final ConstantModule obj) { 264 tostring = toString(obj); 265 } 266 267 @Override 268 public void visitConstantNameAndType(final ConstantNameAndType obj) { 269 tostring = toString(obj); 270 } 271 272 /** 273 * @since 6.6.0 274 */ 275 @Override 276 public void visitConstantPackage(final ConstantPackage obj) { 277 tostring = toString(obj); 278 } 279 280 @Override 281 public void visitConstantPool(final ConstantPool obj) { 282 tostring = toString(obj); 283 } 284 285 @Override 286 public void visitConstantString(final ConstantString obj) { 287 tostring = toString(obj); 288 } 289 290 @Override 291 public void visitConstantUtf8(final ConstantUtf8 obj) { 292 tostring = toString(obj); 293 } 294 295 @Override 296 public void visitConstantValue(final ConstantValue obj) { 297 tostring = toString(obj); 298 } 299 300 @Override 301 public void visitDeprecated(final Deprecated obj) { 302 tostring = toString(obj); 303 } 304 305 /** 306 * @since 6.0 307 */ 308 @Override 309 public void visitEnclosingMethod(final EnclosingMethod obj) { 310 tostring = toString(obj); 311 } 312 313 @Override 314 public void visitExceptionTable(final ExceptionTable obj) { 315 tostring = toString(obj); 316 } 317 318 @Override 319 public void visitField(final Field obj) { 320 tostring = toString(obj); 321 } 322 323 @Override 324 public void visitInnerClass(final InnerClass obj) { 325 tostring = toString(obj); 326 } 327 328 @Override 329 public void visitInnerClasses(final InnerClasses obj) { 330 tostring = toString(obj); 331 } 332 333 @Override 334 public void visitJavaClass(final JavaClass obj) { 335 tostring = toString(obj); 336 } 337 338 @Override 339 public void visitLineNumber(final LineNumber obj) { 340 tostring = toString(obj); 341 } 342 343 @Override 344 public void visitLineNumberTable(final LineNumberTable obj) { 345 tostring = "<LineNumberTable: " + toString(obj) + ">"; 346 } 347 348 @Override 349 public void visitLocalVariable(final LocalVariable obj) { 350 tostring = toString(obj); 351 } 352 353 @Override 354 public void visitLocalVariableTable(final LocalVariableTable obj) { 355 tostring = "<LocalVariableTable: " + toString(obj) + ">"; 356 } 357 358 /** 359 * @since 6.0 360 */ 361 @Override 362 public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj) { 363 // this is invoked whenever a local variable type is found 364 // when verifier is passed over a class 365 tostring = toString(obj); 366 } 367 368 @Override 369 public void visitMethod(final Method obj) { 370 tostring = toString(obj); 371 } 372 373 /** 374 * @since 6.0 375 */ 376 @Override 377 public void visitMethodParameters(final MethodParameters obj) { 378 tostring = toString(obj); 379 } 380 381 /** 382 * @since 6.4.0 383 */ 384 @Override 385 public void visitNestMembers(final NestMembers obj) { 386 tostring = toString(obj); 387 } 388 389 /** 390 * @since 6.0 391 */ 392 @Override 393 public void visitParameterAnnotation(final ParameterAnnotations obj) { 394 tostring = toString(obj); 395 } 396 397 /** 398 * @since 6.0 399 */ 400 @Override 401 public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) { 402 tostring = toString(obj); 403 } 404 405 /** 406 * Visits PermittedSubclasses attribute. 407 * 408 * @since 6.13.0 409 */ 410 @Override 411 public void visitPermittedSubclasses(final PermittedSubclasses obj) { 412 tostring = toString(obj); 413 } 414 415 @Override 416 public void visitRecord(final Record obj) { 417 tostring = toString(obj); 418 } 419 420 @Override 421 public void visitRecordComponent(final RecordComponentInfo obj) { 422 tostring = toString(obj); 423 } 424 425 @Override 426 public void visitSignature(final Signature obj) { 427 tostring = toString(obj); 428 } 429 430 @Override 431 public void visitSourceFile(final SourceFile obj) { 432 tostring = toString(obj); 433 } 434 435 @Override 436 public void visitStackMap(final StackMap obj) { 437 tostring = toString(obj); 438 } 439 440 /** 441 * @since 6.0 442 */ 443 @Override 444 public void visitStackMapEntry(final StackMapEntry obj) { 445 tostring = toString(obj); 446 } 447 448 @Override 449 public void visitSynthetic(final Synthetic obj) { 450 tostring = toString(obj); 451 } 452 453 @Override 454 public void visitUnknown(final Unknown obj) { 455 tostring = toString(obj); 456 } 457 458}