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