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