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