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.Node; 058import org.apache.bcel.classfile.ParameterAnnotationEntry; 059import org.apache.bcel.classfile.ParameterAnnotations; 060import org.apache.bcel.classfile.Signature; 061import org.apache.bcel.classfile.SourceFile; 062import org.apache.bcel.classfile.StackMap; 063import org.apache.bcel.classfile.StackMapEntry; 064import org.apache.bcel.classfile.Synthetic; 065import org.apache.bcel.classfile.Unknown; 066import org.apache.bcel.verifier.exc.AssertionViolatedException; 067 068/** 069 * BCEL's Node classes (those from the classfile API that <B>accept()</B> Visitor 070 * instances) have <B>toString()</B> methods that were not designed to be robust, 071 * this gap is closed by this class. 072 * When performing class file verification, it may be useful to output which 073 * 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> 075 * method to throw a RuntimeException. 076 * A (new StringRepresentation(Node n)).toString() never throws any exception. 077 * Note that this class also serves as a placeholder for more sophisticated message 078 * handling in future versions of JustIce. 079 * 080 * @version $Id: StringRepresentation.java 1806200 2017-08-25 16:33:06Z ggregory $ 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 * @see #toString() 092 */ 093 public StringRepresentation(final Node n) { 094 this.n = n; 095 n.accept(this); // assign a string representation to field 'tostring' if we know n's class. 096 } 097 098 /** 099 * Returns the String representation. 100 */ 101 @Override 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 */ 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 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 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 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 171 public void visitCodeException(final CodeException obj) { 172 tostring = toString(obj); 173 } 174 175 @Override 176 public void visitConstantClass(final ConstantClass obj) { 177 tostring = toString(obj); 178 } 179 180 @Override 181 public void visitConstantDouble(final ConstantDouble obj) { 182 tostring = toString(obj); 183 } 184 185 @Override 186 public void visitConstantFieldref(final ConstantFieldref obj) { 187 tostring = toString(obj); 188 } 189 190 @Override 191 public void visitConstantFloat(final ConstantFloat obj) { 192 tostring = toString(obj); 193 } 194 195 @Override 196 public void visitConstantInteger(final ConstantInteger obj) { 197 tostring = toString(obj); 198 } 199 200 @Override 201 public void visitConstantInterfaceMethodref(final ConstantInterfaceMethodref obj) { 202 tostring = toString(obj); 203 } 204 205 @Override 206 public void visitConstantLong(final ConstantLong obj) { 207 tostring = toString(obj); 208 } 209 210 @Override 211 public void visitConstantMethodref(final ConstantMethodref obj) { 212 tostring = toString(obj); 213 } 214 215 @Override 216 public void visitConstantNameAndType(final ConstantNameAndType obj) { 217 tostring = toString(obj); 218 } 219 220 @Override 221 public void visitConstantPool(final ConstantPool obj) { 222 tostring = toString(obj); 223 } 224 225 @Override 226 public void visitConstantString(final ConstantString obj) { 227 tostring = toString(obj); 228 } 229 230 @Override 231 public void visitConstantUtf8(final ConstantUtf8 obj) { 232 tostring = toString(obj); 233 } 234 235 @Override 236 public void visitConstantValue(final ConstantValue obj) { 237 tostring = toString(obj); 238 } 239 240 @Override 241 public void visitDeprecated(final Deprecated obj) { 242 tostring = toString(obj); 243 } 244 245 @Override 246 public void visitExceptionTable(final ExceptionTable obj) { 247 tostring = toString(obj); 248 } 249 250 @Override 251 public void visitField(final Field obj) { 252 tostring = toString(obj); 253 } 254 255 @Override 256 public void visitInnerClass(final InnerClass obj) { 257 tostring = toString(obj); 258 } 259 260 @Override 261 public void visitInnerClasses(final InnerClasses obj) { 262 tostring = toString(obj); 263 } 264 265 @Override 266 public void visitJavaClass(final JavaClass obj) { 267 tostring = toString(obj); 268 } 269 270 @Override 271 public void visitLineNumber(final LineNumber obj) { 272 tostring = toString(obj); 273 } 274 275 @Override 276 public void visitLineNumberTable(final LineNumberTable obj) { 277 tostring = "<LineNumberTable: " + toString(obj) + ">"; 278 } 279 280 @Override 281 public void visitLocalVariable(final LocalVariable obj) { 282 tostring = toString(obj); 283 } 284 285 @Override 286 public void visitLocalVariableTable(final LocalVariableTable obj) { 287 tostring = "<LocalVariableTable: " + toString(obj) + ">"; 288 } 289 290 @Override 291 public void visitMethod(final Method obj) { 292 tostring = toString(obj); 293 } 294 295 @Override 296 public void visitSignature(final Signature obj) { 297 tostring = toString(obj); 298 } 299 300 @Override 301 public void visitSourceFile(final SourceFile obj) { 302 tostring = toString(obj); 303 } 304 305 @Override 306 public void visitStackMap(final StackMap obj) { 307 tostring = toString(obj); 308 } 309 310 @Override 311 public void visitSynthetic(final Synthetic obj) { 312 tostring = toString(obj); 313 } 314 315 @Override 316 public void visitUnknown(final Unknown obj) { 317 tostring = toString(obj); 318 } 319 320 /** 321 * @since 6.0 322 */ 323 @Override 324 public void visitEnclosingMethod(final EnclosingMethod obj) { 325 tostring = toString(obj); 326 } 327 328 /** 329 * @since 6.0 330 */ 331 @Override 332 public void visitBootstrapMethods(final BootstrapMethods obj) { 333 tostring = toString(obj); 334 } 335 336 /** 337 * @since 6.0 338 */ 339 @Override 340 public void visitMethodParameters(final MethodParameters obj) { 341 tostring = toString(obj); 342 } 343 344 /** 345 * @since 6.0 346 */ 347 @Override 348 public void visitConstantInvokeDynamic(final ConstantInvokeDynamic obj) { 349 tostring = toString(obj); 350 } 351 352 /** 353 * @since 6.0 354 */ 355 @Override 356 public void visitStackMapEntry(final StackMapEntry obj) { 357 tostring = toString(obj); 358 } 359 /** 360 * @since 6.0 361 */ 362 363 @Override 364 public void visitParameterAnnotation(final ParameterAnnotations obj) { 365 tostring = toString(obj); 366 } 367 368 /** 369 * @since 6.0 370 */ 371 @Override 372 public void visitAnnotationEntry(final AnnotationEntry obj) { 373 tostring = toString(obj); 374 } 375 376 /** 377 * @since 6.0 378 */ 379 @Override 380 public void visitAnnotationDefault(final AnnotationDefault obj) { 381 tostring = toString(obj); 382 } 383 384 /** 385 * @since 6.0 386 */ 387 @Override 388 public void visitConstantMethodType(final ConstantMethodType obj) { 389 tostring = toString(obj); 390 } 391 392 /** 393 * @since 6.0 394 */ 395 @Override 396 public void visitConstantMethodHandle(final ConstantMethodHandle obj) { 397 tostring = toString(obj); 398 } 399 400 /** 401 * @since 6.0 402 */ 403 @Override 404 public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) { 405 tostring = toString(obj); 406 } 407}