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