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