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