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