1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 package org.apache.bcel.verifier.statics; 19 20 21 import org.apache.bcel.classfile.AnnotationDefault; 22 import org.apache.bcel.classfile.AnnotationEntry; 23 import org.apache.bcel.classfile.Annotations; 24 import org.apache.bcel.classfile.BootstrapMethods; 25 import org.apache.bcel.classfile.Code; 26 import org.apache.bcel.classfile.CodeException; 27 import org.apache.bcel.classfile.ConstantClass; 28 import org.apache.bcel.classfile.ConstantDouble; 29 import org.apache.bcel.classfile.ConstantFieldref; 30 import org.apache.bcel.classfile.ConstantFloat; 31 import org.apache.bcel.classfile.ConstantInteger; 32 import org.apache.bcel.classfile.ConstantInterfaceMethodref; 33 import org.apache.bcel.classfile.ConstantInvokeDynamic; 34 import org.apache.bcel.classfile.ConstantLong; 35 import org.apache.bcel.classfile.ConstantMethodHandle; 36 import org.apache.bcel.classfile.ConstantMethodType; 37 import org.apache.bcel.classfile.ConstantMethodref; 38 import org.apache.bcel.classfile.ConstantNameAndType; 39 import org.apache.bcel.classfile.ConstantPool; 40 import org.apache.bcel.classfile.ConstantString; 41 import org.apache.bcel.classfile.ConstantUtf8; 42 import org.apache.bcel.classfile.ConstantValue; 43 import org.apache.bcel.classfile.Deprecated; 44 import org.apache.bcel.classfile.EnclosingMethod; 45 import org.apache.bcel.classfile.ExceptionTable; 46 import org.apache.bcel.classfile.Field; 47 import org.apache.bcel.classfile.InnerClass; 48 import org.apache.bcel.classfile.InnerClasses; 49 import org.apache.bcel.classfile.JavaClass; 50 import org.apache.bcel.classfile.LineNumber; 51 import org.apache.bcel.classfile.LineNumberTable; 52 import org.apache.bcel.classfile.LocalVariable; 53 import org.apache.bcel.classfile.LocalVariableTable; 54 import org.apache.bcel.classfile.LocalVariableTypeTable; 55 import org.apache.bcel.classfile.Method; 56 import org.apache.bcel.classfile.MethodParameters; 57 import org.apache.bcel.classfile.Node; 58 import org.apache.bcel.classfile.ParameterAnnotationEntry; 59 import org.apache.bcel.classfile.ParameterAnnotations; 60 import org.apache.bcel.classfile.Signature; 61 import org.apache.bcel.classfile.SourceFile; 62 import org.apache.bcel.classfile.StackMap; 63 import org.apache.bcel.classfile.StackMapEntry; 64 import org.apache.bcel.classfile.Synthetic; 65 import org.apache.bcel.classfile.Unknown; 66 import org.apache.bcel.verifier.exc.AssertionViolatedException; 67 68 /** 69 * BCEL's Node classes (those from the classfile API that <B>accept()</B> Visitor 70 * instances) have <B>toString()</B> methods that were not designed to be robust, 71 * this gap is closed by this class. 72 * When performing class file verification, it may be useful to output which 73 * entity (e.g. a <B>Code</B> instance) is not satisfying the verifier's 74 * constraints, but in this case it could be possible for the <B>toString()</B> 75 * method to throw a RuntimeException. 76 * A (new StringRepresentation(Node n)).toString() never throws any exception. 77 * Note that this class also serves as a placeholder for more sophisticated message 78 * handling in future versions of JustIce. 79 * 80 * @version $Id$ 81 */ 82 public class StringRepresentation extends org.apache.bcel.classfile.EmptyVisitor { 83 /** The string representation, created by a visitXXX() method, output by toString(). */ 84 private String tostring; 85 /** The node we ask for its string representation. Not really needed; only for debug output. */ 86 private final Node n; 87 88 /** 89 * Creates a new StringRepresentation object which is the representation of n. 90 * 91 * @see #toString() 92 */ StringRepresentation(final Node n)93 public StringRepresentation(final Node n) { 94 this.n = n; 95 n.accept(this); // assign a string representation to field 'tostring' if we know n's class. 96 } 97 98 /** 99 * Returns the String representation. 100 */ 101 @Override toString()102 public String toString() { 103 // The run-time check below is needed because we don't want to omit inheritance 104 // of "EmptyVisitor" and provide a thousand empty methods. 105 // However, in terms of performance this would be a better idea. 106 // If some new "Node" is defined in BCEL (such as some concrete "Attribute"), we 107 // want to know that this class has also to be adapted. 108 if (tostring == null) { 109 throw new AssertionViolatedException( 110 "Please adapt '" + getClass() + "' to deal with objects of class '" + n.getClass() + "'."); 111 } 112 return tostring; 113 } 114 115 /** 116 * Returns the String representation of the Node object obj; 117 * this is obj.toString() if it does not throw any RuntimeException, 118 * or else it is a string derived only from obj's class name. 119 */ toString(final Node obj)120 private String toString(final Node obj) { 121 String ret; 122 try { 123 ret = obj.toString(); 124 } 125 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 // Visitor methods start here // 138 //////////////////////////////// 139 // We don't of course need to call some default implementation: 140 // e.g. we could also simply output "Code" instead of a possibly 141 // lengthy Code attribute's toString(). 142 @Override visitCode(final Code obj)143 public void visitCode(final Code obj) { 144 //tostring = toString(obj); 145 tostring = "<CODE>"; // We don't need real code outputs. 146 } 147 148 /** 149 * @since 6.0 150 */ 151 @Override visitAnnotation(final Annotations obj)152 public void visitAnnotation(final Annotations obj) 153 { 154 //this is invoked whenever an annotation is found 155 //when verifier is passed over a class 156 tostring = toString(obj); 157 } 158 159 /** 160 * @since 6.0 161 */ 162 @Override visitLocalVariableTypeTable(final LocalVariableTypeTable obj)163 public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj) 164 { 165 //this is invoked whenever a local variable type is found 166 //when verifier is passed over a class 167 tostring = toString(obj); 168 } 169 170 @Override visitCodeException(final CodeException obj)171 public void visitCodeException(final CodeException obj) { 172 tostring = toString(obj); 173 } 174 175 @Override visitConstantClass(final ConstantClass obj)176 public void visitConstantClass(final ConstantClass obj) { 177 tostring = toString(obj); 178 } 179 180 @Override visitConstantDouble(final ConstantDouble obj)181 public void visitConstantDouble(final ConstantDouble obj) { 182 tostring = toString(obj); 183 } 184 185 @Override visitConstantFieldref(final ConstantFieldref obj)186 public void visitConstantFieldref(final ConstantFieldref obj) { 187 tostring = toString(obj); 188 } 189 190 @Override visitConstantFloat(final ConstantFloat obj)191 public void visitConstantFloat(final ConstantFloat obj) { 192 tostring = toString(obj); 193 } 194 195 @Override visitConstantInteger(final ConstantInteger obj)196 public void visitConstantInteger(final ConstantInteger obj) { 197 tostring = toString(obj); 198 } 199 200 @Override visitConstantInterfaceMethodref(final ConstantInterfaceMethodref obj)201 public void visitConstantInterfaceMethodref(final ConstantInterfaceMethodref obj) { 202 tostring = toString(obj); 203 } 204 205 @Override visitConstantLong(final ConstantLong obj)206 public void visitConstantLong(final ConstantLong obj) { 207 tostring = toString(obj); 208 } 209 210 @Override visitConstantMethodref(final ConstantMethodref obj)211 public void visitConstantMethodref(final ConstantMethodref obj) { 212 tostring = toString(obj); 213 } 214 215 @Override visitConstantNameAndType(final ConstantNameAndType obj)216 public void visitConstantNameAndType(final ConstantNameAndType obj) { 217 tostring = toString(obj); 218 } 219 220 @Override visitConstantPool(final ConstantPool obj)221 public void visitConstantPool(final ConstantPool obj) { 222 tostring = toString(obj); 223 } 224 225 @Override visitConstantString(final ConstantString obj)226 public void visitConstantString(final ConstantString obj) { 227 tostring = toString(obj); 228 } 229 230 @Override visitConstantUtf8(final ConstantUtf8 obj)231 public void visitConstantUtf8(final ConstantUtf8 obj) { 232 tostring = toString(obj); 233 } 234 235 @Override visitConstantValue(final ConstantValue obj)236 public void visitConstantValue(final ConstantValue obj) { 237 tostring = toString(obj); 238 } 239 240 @Override visitDeprecated(final Deprecated obj)241 public void visitDeprecated(final Deprecated obj) { 242 tostring = toString(obj); 243 } 244 245 @Override visitExceptionTable(final ExceptionTable obj)246 public void visitExceptionTable(final ExceptionTable obj) { 247 tostring = toString(obj); 248 } 249 250 @Override visitField(final Field obj)251 public void visitField(final Field obj) { 252 tostring = toString(obj); 253 } 254 255 @Override visitInnerClass(final InnerClass obj)256 public void visitInnerClass(final InnerClass obj) { 257 tostring = toString(obj); 258 } 259 260 @Override visitInnerClasses(final InnerClasses obj)261 public void visitInnerClasses(final InnerClasses obj) { 262 tostring = toString(obj); 263 } 264 265 @Override visitJavaClass(final JavaClass obj)266 public void visitJavaClass(final JavaClass obj) { 267 tostring = toString(obj); 268 } 269 270 @Override visitLineNumber(final LineNumber obj)271 public void visitLineNumber(final LineNumber obj) { 272 tostring = toString(obj); 273 } 274 275 @Override visitLineNumberTable(final LineNumberTable obj)276 public void visitLineNumberTable(final LineNumberTable obj) { 277 tostring = "<LineNumberTable: " + toString(obj) + ">"; 278 } 279 280 @Override visitLocalVariable(final LocalVariable obj)281 public void visitLocalVariable(final LocalVariable obj) { 282 tostring = toString(obj); 283 } 284 285 @Override visitLocalVariableTable(final LocalVariableTable obj)286 public void visitLocalVariableTable(final LocalVariableTable obj) { 287 tostring = "<LocalVariableTable: " + toString(obj) + ">"; 288 } 289 290 @Override visitMethod(final Method obj)291 public void visitMethod(final Method obj) { 292 tostring = toString(obj); 293 } 294 295 @Override visitSignature(final Signature obj)296 public void visitSignature(final Signature obj) { 297 tostring = toString(obj); 298 } 299 300 @Override visitSourceFile(final SourceFile obj)301 public void visitSourceFile(final SourceFile obj) { 302 tostring = toString(obj); 303 } 304 305 @Override visitStackMap(final StackMap obj)306 public void visitStackMap(final StackMap obj) { 307 tostring = toString(obj); 308 } 309 310 @Override visitSynthetic(final Synthetic obj)311 public void visitSynthetic(final Synthetic obj) { 312 tostring = toString(obj); 313 } 314 315 @Override visitUnknown(final Unknown obj)316 public void visitUnknown(final Unknown obj) { 317 tostring = toString(obj); 318 } 319 320 /** 321 * @since 6.0 322 */ 323 @Override visitEnclosingMethod(final EnclosingMethod obj)324 public void visitEnclosingMethod(final EnclosingMethod obj) { 325 tostring = toString(obj); 326 } 327 328 /** 329 * @since 6.0 330 */ 331 @Override visitBootstrapMethods(final BootstrapMethods obj)332 public void visitBootstrapMethods(final BootstrapMethods obj) { 333 tostring = toString(obj); 334 } 335 336 /** 337 * @since 6.0 338 */ 339 @Override visitMethodParameters(final MethodParameters obj)340 public void visitMethodParameters(final MethodParameters obj) { 341 tostring = toString(obj); 342 } 343 344 /** 345 * @since 6.0 346 */ 347 @Override visitConstantInvokeDynamic(final ConstantInvokeDynamic obj)348 public void visitConstantInvokeDynamic(final ConstantInvokeDynamic obj) { 349 tostring = toString(obj); 350 } 351 352 /** 353 * @since 6.0 354 */ 355 @Override visitStackMapEntry(final StackMapEntry obj)356 public void visitStackMapEntry(final StackMapEntry obj) { 357 tostring = toString(obj); 358 } 359 /** 360 * @since 6.0 361 */ 362 363 @Override visitParameterAnnotation(final ParameterAnnotations obj)364 public void visitParameterAnnotation(final ParameterAnnotations obj) { 365 tostring = toString(obj); 366 } 367 368 /** 369 * @since 6.0 370 */ 371 @Override visitAnnotationEntry(final AnnotationEntry obj)372 public void visitAnnotationEntry(final AnnotationEntry obj) { 373 tostring = toString(obj); 374 } 375 376 /** 377 * @since 6.0 378 */ 379 @Override visitAnnotationDefault(final AnnotationDefault obj)380 public void visitAnnotationDefault(final AnnotationDefault obj) { 381 tostring = toString(obj); 382 } 383 384 /** 385 * @since 6.0 386 */ 387 @Override visitConstantMethodType(final ConstantMethodType obj)388 public void visitConstantMethodType(final ConstantMethodType obj) { 389 tostring = toString(obj); 390 } 391 392 /** 393 * @since 6.0 394 */ 395 @Override visitConstantMethodHandle(final ConstantMethodHandle obj)396 public void visitConstantMethodHandle(final ConstantMethodHandle obj) { 397 tostring = toString(obj); 398 } 399 400 /** 401 * @since 6.0 402 */ 403 @Override visitParameterAnnotationEntry(final ParameterAnnotationEntry obj)404 public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) { 405 tostring = toString(obj); 406 } 407 } 408