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