001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License.
016 *
017 */
018package org.apache.bcel.verifier.statics;
019
020
021import org.apache.bcel.classfile.AnnotationDefault;
022import org.apache.bcel.classfile.AnnotationEntry;
023import org.apache.bcel.classfile.Annotations;
024import org.apache.bcel.classfile.BootstrapMethods;
025import org.apache.bcel.classfile.Code;
026import org.apache.bcel.classfile.CodeException;
027import org.apache.bcel.classfile.ConstantClass;
028import org.apache.bcel.classfile.ConstantDouble;
029import org.apache.bcel.classfile.ConstantFieldref;
030import org.apache.bcel.classfile.ConstantFloat;
031import org.apache.bcel.classfile.ConstantInteger;
032import org.apache.bcel.classfile.ConstantInterfaceMethodref;
033import org.apache.bcel.classfile.ConstantInvokeDynamic;
034import org.apache.bcel.classfile.ConstantLong;
035import org.apache.bcel.classfile.ConstantMethodHandle;
036import org.apache.bcel.classfile.ConstantMethodType;
037import org.apache.bcel.classfile.ConstantMethodref;
038import org.apache.bcel.classfile.ConstantNameAndType;
039import org.apache.bcel.classfile.ConstantPool;
040import org.apache.bcel.classfile.ConstantString;
041import org.apache.bcel.classfile.ConstantUtf8;
042import org.apache.bcel.classfile.ConstantValue;
043import org.apache.bcel.classfile.Deprecated;
044import org.apache.bcel.classfile.EnclosingMethod;
045import org.apache.bcel.classfile.ExceptionTable;
046import org.apache.bcel.classfile.Field;
047import org.apache.bcel.classfile.InnerClass;
048import org.apache.bcel.classfile.InnerClasses;
049import org.apache.bcel.classfile.JavaClass;
050import org.apache.bcel.classfile.LineNumber;
051import org.apache.bcel.classfile.LineNumberTable;
052import org.apache.bcel.classfile.LocalVariable;
053import org.apache.bcel.classfile.LocalVariableTable;
054import org.apache.bcel.classfile.LocalVariableTypeTable;
055import org.apache.bcel.classfile.Method;
056import org.apache.bcel.classfile.MethodParameters;
057import org.apache.bcel.classfile.NestMembers;
058import org.apache.bcel.classfile.Node;
059import org.apache.bcel.classfile.ParameterAnnotationEntry;
060import org.apache.bcel.classfile.ParameterAnnotations;
061import org.apache.bcel.classfile.Signature;
062import org.apache.bcel.classfile.SourceFile;
063import org.apache.bcel.classfile.StackMap;
064import org.apache.bcel.classfile.StackMapEntry;
065import org.apache.bcel.classfile.Synthetic;
066import org.apache.bcel.classfile.Unknown;
067import org.apache.bcel.verifier.exc.AssertionViolatedException;
068
069/**
070 * BCEL's Node classes (those from the classfile API that <B>accept()</B> Visitor
071 * instances) have <B>toString()</B> methods that were not designed to be robust,
072 * this gap is closed by this class.
073 * When performing class file verification, it may be useful to output which
074 * entity (e.g. a <B>Code</B> instance) is not satisfying the verifier's
075 * constraints, but in this case it could be possible for the <B>toString()</B>
076 * method to throw a RuntimeException.
077 * A (new StringRepresentation(Node n)).toString() never throws any exception.
078 * Note that this class also serves as a placeholder for more sophisticated message
079 * handling in future versions of JustIce.
080 *
081 */
082public class StringRepresentation extends org.apache.bcel.classfile.EmptyVisitor {
083    /** The string representation, created by a visitXXX() method, output by toString(). */
084    private String tostring;
085    /** The node we ask for its string representation. Not really needed; only for debug output. */
086    private final Node n;
087
088    /**
089     * Creates a new StringRepresentation object which is the representation of n.
090     *
091     * @param n The node to represent.
092     * @see #toString()
093     */
094    public StringRepresentation(final Node n) {
095        this.n = n;
096        n.accept(this); // assign a string representation to field 'tostring' if we know n's class.
097    }
098
099    /**
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}