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