    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 *   https://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019package org.apache.bcel.verifier.statics;
    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.ConstantDynamic;
    030import org.apache.bcel.classfile.ConstantFieldref;
    031import org.apache.bcel.classfile.ConstantFloat;
    032import org.apache.bcel.classfile.ConstantInteger;
    033import org.apache.bcel.classfile.ConstantInterfaceMethodref;
    034import org.apache.bcel.classfile.ConstantInvokeDynamic;
    035import org.apache.bcel.classfile.ConstantLong;
    036import org.apache.bcel.classfile.ConstantMethodHandle;
    037import org.apache.bcel.classfile.ConstantMethodType;
    038import org.apache.bcel.classfile.ConstantMethodref;
    039import org.apache.bcel.classfile.ConstantModule;
    040import org.apache.bcel.classfile.ConstantNameAndType;
    041import org.apache.bcel.classfile.ConstantPackage;
    042import org.apache.bcel.classfile.ConstantPool;
    043import org.apache.bcel.classfile.ConstantString;
    044import org.apache.bcel.classfile.ConstantUtf8;
    045import org.apache.bcel.classfile.ConstantValue;
    046import org.apache.bcel.classfile.Deprecated;
    047import org.apache.bcel.classfile.EnclosingMethod;
    048import org.apache.bcel.classfile.ExceptionTable;
    049import org.apache.bcel.classfile.Field;
    050import org.apache.bcel.classfile.InnerClass;
    051import org.apache.bcel.classfile.InnerClasses;
    052import org.apache.bcel.classfile.JavaClass;
    053import org.apache.bcel.classfile.LineNumber;
    054import org.apache.bcel.classfile.LineNumberTable;
    055import org.apache.bcel.classfile.LocalVariable;
    056import org.apache.bcel.classfile.LocalVariableTable;
    057import org.apache.bcel.classfile.LocalVariableTypeTable;
    058import org.apache.bcel.classfile.Method;
    059import org.apache.bcel.classfile.MethodParameters;
    060import org.apache.bcel.classfile.NestMembers;
    061import org.apache.bcel.classfile.Node;
    062import org.apache.bcel.classfile.ParameterAnnotationEntry;
    063import org.apache.bcel.classfile.ParameterAnnotations;
    064import org.apache.bcel.classfile.Record;
    065import org.apache.bcel.classfile.RecordComponentInfo;
    066import org.apache.bcel.classfile.Signature;
    067import org.apache.bcel.classfile.SourceFile;
    068import org.apache.bcel.classfile.StackMap;
    069import org.apache.bcel.classfile.StackMapEntry;
    070import org.apache.bcel.classfile.Synthetic;
    071import org.apache.bcel.classfile.Unknown;
    072import org.apache.bcel.verifier.exc.AssertionViolatedException;
    073
    074/**
    075 * BCEL's Node classes (those from the classfile API that <B>accept()</B> Visitor instances) have <B>toString()</B>
    076 * methods that were not designed to be robust, this gap is closed by this class. When performing class file
    077 * verification, it may be useful to output which entity (for example a <B>Code</B> instance) is not satisfying the verifier's
    078 * constraints, but in this case it could be possible for the <B>toString()</B> method to throw a RuntimeException. A
    079 * (new StringRepresentation(Node n)).toString() never throws any exception. Note that this class also serves as a
    080 * placeholder for more sophisticated message handling in future versions of JustIce.
    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("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; this is obj.toString() if it does not throw any
    117     * RuntimeException, or else it is a string derived only from obj's class name.
    118     */
    119    private String toString(final Node obj) {
    120        String ret;
    121        try {
    122            ret = obj.toString();
    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    // for example 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 visitRecord(final Record obj) {
    404        tostring = toString(obj);
    405    }
    406
    407    @Override
    408    public void visitRecordComponent(final RecordComponentInfo obj) {
    409        tostring = toString(obj);
    410    }
    411
    412    @Override
    413    public void visitSignature(final Signature obj) {
    414        tostring = toString(obj);
    415    }
    416
    417    @Override
    418    public void visitSourceFile(final SourceFile obj) {
    419        tostring = toString(obj);
    420    }
    421
    422    @Override
    423    public void visitStackMap(final StackMap obj) {
    424        tostring = toString(obj);
    425    }
    426
    427    /**
    428     * @since 6.0
    429     */
    430    @Override
    431    public void visitStackMapEntry(final StackMapEntry obj) {
    432        tostring = toString(obj);
    433    }
    434
    435    @Override
    436    public void visitSynthetic(final Synthetic obj) {
    437        tostring = toString(obj);
    438    }
    439
    440    @Override
    441    public void visitUnknown(final Unknown obj) {
    442        tostring = toString(obj);
    443    }
    444
    445}