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