    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 */
    017package org.apache.bcel.verifier.statics;
    018
    019import org.apache.bcel.classfile.AnnotationDefault;
    020import org.apache.bcel.classfile.AnnotationEntry;
    021import org.apache.bcel.classfile.Annotations;
    022import org.apache.bcel.classfile.BootstrapMethods;
    023import org.apache.bcel.classfile.Code;
    024import org.apache.bcel.classfile.CodeException;
    025import org.apache.bcel.classfile.ConstantClass;
    026import org.apache.bcel.classfile.ConstantDouble;
    027import org.apache.bcel.classfile.ConstantDynamic;
    028import org.apache.bcel.classfile.ConstantFieldref;
    029import org.apache.bcel.classfile.ConstantFloat;
    030import org.apache.bcel.classfile.ConstantInteger;
    031import org.apache.bcel.classfile.ConstantInterfaceMethodref;
    032import org.apache.bcel.classfile.ConstantInvokeDynamic;
    033import org.apache.bcel.classfile.ConstantLong;
    034import org.apache.bcel.classfile.ConstantMethodHandle;
    035import org.apache.bcel.classfile.ConstantMethodType;
    036import org.apache.bcel.classfile.ConstantMethodref;
    037import org.apache.bcel.classfile.ConstantModule;
    038import org.apache.bcel.classfile.ConstantNameAndType;
    039import org.apache.bcel.classfile.ConstantPackage;
    040import org.apache.bcel.classfile.ConstantPool;
    041import org.apache.bcel.classfile.ConstantString;
    042import org.apache.bcel.classfile.ConstantUtf8;
    043import org.apache.bcel.classfile.ConstantValue;
    044import org.apache.bcel.classfile.Deprecated;
    045import org.apache.bcel.classfile.EnclosingMethod;
    046import org.apache.bcel.classfile.ExceptionTable;
    047import org.apache.bcel.classfile.Field;
    048import org.apache.bcel.classfile.InnerClass;
    049import org.apache.bcel.classfile.InnerClasses;
    050import org.apache.bcel.classfile.JavaClass;
    051import org.apache.bcel.classfile.LineNumber;
    052import org.apache.bcel.classfile.LineNumberTable;
    053import org.apache.bcel.classfile.LocalVariable;
    054import org.apache.bcel.classfile.LocalVariableTable;
    055import org.apache.bcel.classfile.LocalVariableTypeTable;
    056import org.apache.bcel.classfile.Method;
    057import org.apache.bcel.classfile.MethodParameters;
    058import org.apache.bcel.classfile.NestMembers;
    059import org.apache.bcel.classfile.Node;
    060import org.apache.bcel.classfile.ParameterAnnotationEntry;
    061import org.apache.bcel.classfile.ParameterAnnotations;
    062import org.apache.bcel.classfile.Signature;
    063import org.apache.bcel.classfile.SourceFile;
    064import org.apache.bcel.classfile.StackMap;
    065import org.apache.bcel.classfile.StackMapEntry;
    066import org.apache.bcel.classfile.Synthetic;
    067import org.apache.bcel.classfile.Unknown;
    068import org.apache.bcel.verifier.exc.AssertionViolatedException;
    069
    070/**
    071 * BCEL's Node classes (those from the classfile API that <B>accept()</B> Visitor instances) have <B>toString()</B>
    072 * methods that were not designed to be robust, this gap is closed by this class. When performing class file
    073 * verification, it may be useful to output which 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> method to throw a RuntimeException. A
    075 * (new StringRepresentation(Node n)).toString() never throws any exception. Note that this class also serves as a
    076 * placeholder for more sophisticated message handling in future versions of JustIce.
    077 */
    078public class StringRepresentation extends org.apache.bcel.classfile.EmptyVisitor {
    079    /** The string representation, created by a visitXXX() method, output by toString(). */
    080    private String tostring;
    081    /** The node we ask for its string representation. Not really needed; only for debug output. */
    082    private final Node n;
    083
    084    /**
    085     * Creates a new StringRepresentation object which is the representation of n.
    086     *
    087     * @param n The node to represent.
    088     * @see #toString()
    089     */
    090    public StringRepresentation(final Node n) {
    091        this.n = n;
    092        n.accept(this); // assign a string representation to field 'tostring' if we know n's class.
    093    }
    094
    095    /**
    096     * Returns the String representation.
    097     */
    098    @Override
    099    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}