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