    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$
    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}