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