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