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