    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.classfile;
    019
    020import java.util.Stack;
    021
    022/**
    023 * Traverses a JavaClass with another Visitor object 'piggy-backed' that is
    024 * applied to all components of a JavaClass object. I.e. this class supplies the
    025 * traversal strategy, other classes can make use of it.
    026 *
    027 * @version $Id: DescendingVisitor.java 1829452 2018-04-18 14:17:34Z markt $
    028 */
    029public class DescendingVisitor implements Visitor
    030{
    031    private final JavaClass clazz;
    032
    033    private final Visitor visitor;
    034
    035    private final Stack<Object> stack = new Stack<>();
    036
    037    /**
    038     * @return container of current entitity, i.e., predecessor during traversal
    039     */
    040    public Object predecessor()
    041    {
    042        return predecessor(0);
    043    }
    044
    045    /**
    046     * @param level
    047     *            nesting level, i.e., 0 returns the direct predecessor
    048     * @return container of current entitity, i.e., predecessor during traversal
    049     */
    050    public Object predecessor(final int level)
    051    {
    052        final int size = stack.size();
    053        if ((size < 2) || (level < 0))
    054        {
    055            return null;
    056        }
    057        return stack.elementAt(size - (level + 2)); // size - 1 == current
    058    }
    059
    060    /**
    061     * @return current object
    062     */
    063    public Object current()
    064    {
    065        return stack.peek();
    066    }
    067
    068    /**
    069     * @param clazz
    070     *            Class to traverse
    071     * @param visitor
    072     *            visitor object to apply to all components
    073     */
    074    public DescendingVisitor(final JavaClass clazz, final Visitor visitor)
    075    {
    076        this.clazz = clazz;
    077        this.visitor = visitor;
    078    }
    079
    080    /**
    081     * Start traversal.
    082     */
    083    public void visit()
    084    {
    085        clazz.accept(this);
    086    }
    087
    088    @Override
    089    public void visitJavaClass(final JavaClass _clazz)
    090    {
    091        stack.push(_clazz);
    092        _clazz.accept(visitor);
    093        final Field[] fields = _clazz.getFields();
    094        for (final Field field : fields) {
    095            field.accept(this);
    096        }
    097        final Method[] methods = _clazz.getMethods();
    098        for (final Method method : methods) {
    099            method.accept(this);
    100        }
    101        final Attribute[] attributes = _clazz.getAttributes();
    102        for (final Attribute attribute : attributes) {
    103            attribute.accept(this);
    104        }
    105        _clazz.getConstantPool().accept(this);
    106        stack.pop();
    107    }
    108
    109    /**
    110     * @since 6.0
    111     */
    112    @Override
    113    public void visitAnnotation(final Annotations annotation)
    114    {
    115        stack.push(annotation);
    116        annotation.accept(visitor);
    117        final AnnotationEntry[] entries = annotation.getAnnotationEntries();
    118        for (final AnnotationEntry entrie : entries) {
    119            entrie.accept(this);
    120        }
    121        stack.pop();
    122    }
    123
    124    /**
    125     * @since 6.0
    126     */
    127    @Override
    128    public void visitAnnotationEntry(final AnnotationEntry annotationEntry)
    129    {
    130        stack.push(annotationEntry);
    131        annotationEntry.accept(visitor);
    132        stack.pop();
    133    }
    134
    135    @Override
    136    public void visitField(final Field field)
    137    {
    138        stack.push(field);
    139        field.accept(visitor);
    140        final Attribute[] attributes = field.getAttributes();
    141        for (final Attribute attribute : attributes) {
    142            attribute.accept(this);
    143        }
    144        stack.pop();
    145    }
    146
    147    @Override
    148    public void visitConstantValue(final ConstantValue cv)
    149    {
    150        stack.push(cv);
    151        cv.accept(visitor);
    152        stack.pop();
    153    }
    154
    155    @Override
    156    public void visitMethod(final Method method)
    157    {
    158        stack.push(method);
    159        method.accept(visitor);
    160        final Attribute[] attributes = method.getAttributes();
    161        for (final Attribute attribute : attributes) {
    162            attribute.accept(this);
    163        }
    164        stack.pop();
    165    }
    166
    167    @Override
    168    public void visitExceptionTable(final ExceptionTable table)
    169    {
    170        stack.push(table);
    171        table.accept(visitor);
    172        stack.pop();
    173    }
    174
    175    @Override
    176    public void visitCode(final Code code)
    177    {
    178        stack.push(code);
    179        code.accept(visitor);
    180        final CodeException[] table = code.getExceptionTable();
    181        for (final CodeException element : table) {
    182            element.accept(this);
    183        }
    184        final Attribute[] attributes = code.getAttributes();
    185        for (final Attribute attribute : attributes) {
    186            attribute.accept(this);
    187        }
    188        stack.pop();
    189    }
    190
    191    @Override
    192    public void visitCodeException(final CodeException ce)
    193    {
    194        stack.push(ce);
    195        ce.accept(visitor);
    196        stack.pop();
    197    }
    198
    199    @Override
    200    public void visitLineNumberTable(final LineNumberTable table)
    201    {
    202        stack.push(table);
    203        table.accept(visitor);
    204        final LineNumber[] numbers = table.getLineNumberTable();
    205        for (final LineNumber number : numbers) {
    206            number.accept(this);
    207        }
    208        stack.pop();
    209    }
    210
    211    @Override
    212    public void visitLineNumber(final LineNumber number)
    213    {
    214        stack.push(number);
    215        number.accept(visitor);
    216        stack.pop();
    217    }
    218
    219    @Override
    220    public void visitLocalVariableTable(final LocalVariableTable table)
    221    {
    222        stack.push(table);
    223        table.accept(visitor);
    224        final LocalVariable[] vars = table.getLocalVariableTable();
    225        for (final LocalVariable var : vars) {
    226            var.accept(this);
    227        }
    228        stack.pop();
    229    }
    230
    231    @Override
    232    public void visitStackMap(final StackMap table)
    233    {
    234        stack.push(table);
    235        table.accept(visitor);
    236        final StackMapEntry[] vars = table.getStackMap();
    237        for (final StackMapEntry var : vars) {
    238            var.accept(this);
    239        }
    240        stack.pop();
    241    }
    242
    243    @Override
    244    public void visitStackMapEntry(final StackMapEntry var)
    245    {
    246        stack.push(var);
    247        var.accept(visitor);
    248        stack.pop();
    249    }
    250
    251    @Override
    252    public void visitLocalVariable(final LocalVariable var)
    253    {
    254        stack.push(var);
    255        var.accept(visitor);
    256        stack.pop();
    257    }
    258
    259    @Override
    260    public void visitConstantPool(final ConstantPool cp)
    261    {
    262        stack.push(cp);
    263        cp.accept(visitor);
    264        final Constant[] constants = cp.getConstantPool();
    265        for (int i = 1; i < constants.length; i++)
    266        {
    267            if (constants[i] != null)
    268            {
    269                constants[i].accept(this);
    270            }
    271        }
    272        stack.pop();
    273    }
    274
    275    @Override
    276    public void visitConstantClass(final ConstantClass constant)
    277    {
    278        stack.push(constant);
    279        constant.accept(visitor);
    280        stack.pop();
    281    }
    282
    283    @Override
    284    public void visitConstantDouble(final ConstantDouble constant)
    285    {
    286        stack.push(constant);
    287        constant.accept(visitor);
    288        stack.pop();
    289    }
    290
    291    @Override
    292    public void visitConstantFieldref(final ConstantFieldref constant)
    293    {
    294        stack.push(constant);
    295        constant.accept(visitor);
    296        stack.pop();
    297    }
    298
    299    @Override
    300    public void visitConstantFloat(final ConstantFloat constant)
    301    {
    302        stack.push(constant);
    303        constant.accept(visitor);
    304        stack.pop();
    305    }
    306
    307    @Override
    308    public void visitConstantInteger(final ConstantInteger constant)
    309    {
    310        stack.push(constant);
    311        constant.accept(visitor);
    312        stack.pop();
    313    }
    314
    315    @Override
    316    public void visitConstantInterfaceMethodref(
    317            final ConstantInterfaceMethodref constant)
    318    {
    319        stack.push(constant);
    320        constant.accept(visitor);
    321        stack.pop();
    322    }
    323
    324    /**
    325     * @since 6.0
    326     */
    327    @Override
    328    public void visitConstantInvokeDynamic(
    329            final ConstantInvokeDynamic constant)
    330    {
    331        stack.push(constant);
    332        constant.accept(visitor);
    333        stack.pop();
    334    }
    335
    336    @Override
    337    public void visitConstantLong(final ConstantLong constant)
    338    {
    339        stack.push(constant);
    340        constant.accept(visitor);
    341        stack.pop();
    342    }
    343
    344    @Override
    345    public void visitConstantMethodref(final ConstantMethodref constant)
    346    {
    347        stack.push(constant);
    348        constant.accept(visitor);
    349        stack.pop();
    350    }
    351
    352    @Override
    353    public void visitConstantNameAndType(final ConstantNameAndType constant)
    354    {
    355        stack.push(constant);
    356        constant.accept(visitor);
    357        stack.pop();
    358    }
    359
    360    @Override
    361    public void visitConstantString(final ConstantString constant)
    362    {
    363        stack.push(constant);
    364        constant.accept(visitor);
    365        stack.pop();
    366    }
    367
    368    @Override
    369    public void visitConstantUtf8(final ConstantUtf8 constant)
    370    {
    371        stack.push(constant);
    372        constant.accept(visitor);
    373        stack.pop();
    374    }
    375
    376    @Override
    377    public void visitInnerClasses(final InnerClasses ic)
    378    {
    379        stack.push(ic);
    380        ic.accept(visitor);
    381        final InnerClass[] ics = ic.getInnerClasses();
    382        for (final InnerClass ic2 : ics) {
    383            ic2.accept(this);
    384        }
    385        stack.pop();
    386    }
    387
    388    @Override
    389    public void visitInnerClass(final InnerClass inner)
    390    {
    391        stack.push(inner);
    392        inner.accept(visitor);
    393        stack.pop();
    394    }
    395
    396    /**
    397     * @since 6.0
    398     */
    399    @Override
    400    public void visitBootstrapMethods(final BootstrapMethods bm)
    401    {
    402        stack.push(bm);
    403        bm.accept(visitor);
    404        // BootstrapMethod[] bms = bm.getBootstrapMethods();
    405        // for (int i = 0; i < bms.length; i++)
    406        // {
    407        //     bms[i].accept(this);
    408        // }
    409        stack.pop();
    410    }
    411
    412    @Override
    413    public void visitDeprecated(final Deprecated attribute)
    414    {
    415        stack.push(attribute);
    416        attribute.accept(visitor);
    417        stack.pop();
    418    }
    419
    420    @Override
    421    public void visitSignature(final Signature attribute)
    422    {
    423        stack.push(attribute);
    424        attribute.accept(visitor);
    425        stack.pop();
    426    }
    427
    428    @Override
    429    public void visitSourceFile(final SourceFile attribute)
    430    {
    431        stack.push(attribute);
    432        attribute.accept(visitor);
    433        stack.pop();
    434    }
    435
    436    @Override
    437    public void visitSynthetic(final Synthetic attribute)
    438    {
    439        stack.push(attribute);
    440        attribute.accept(visitor);
    441        stack.pop();
    442    }
    443
    444    @Override
    445    public void visitUnknown(final Unknown attribute)
    446    {
    447        stack.push(attribute);
    448        attribute.accept(visitor);
    449        stack.pop();
    450    }
    451
    452    /**
    453     * @since 6.0
    454     */
    455    @Override
    456    public void visitAnnotationDefault(final AnnotationDefault obj)
    457    {
    458        stack.push(obj);
    459        obj.accept(visitor);
    460        stack.pop();
    461    }
    462
    463    /**
    464     * @since 6.0
    465     */
    466    @Override
    467    public void visitEnclosingMethod(final EnclosingMethod obj)
    468    {
    469        stack.push(obj);
    470        obj.accept(visitor);
    471        stack.pop();
    472    }
    473
    474    /**
    475     * @since 6.0
    476     */
    477    @Override
    478    public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj)
    479    {
    480        stack.push(obj);
    481        obj.accept(visitor);
    482        stack.pop();
    483    }
    484
    485    /**
    486     * @since 6.0
    487     */
    488    @Override
    489    public void visitParameterAnnotation(final ParameterAnnotations obj)
    490    {
    491        stack.push(obj);
    492        obj.accept(visitor);
    493        stack.pop();
    494    }
    495
    496    /**
    497     * @since 6.0
    498     */
    499    @Override
    500    public void visitMethodParameters(final MethodParameters obj)
    501    {
    502        stack.push(obj);
    503        obj.accept(visitor);
    504        stack.pop();
    505    }
    506
    507    /** @since 6.0 */
    508    @Override
    509    public void visitConstantMethodType(final ConstantMethodType obj) {
    510        stack.push(obj);
    511        obj.accept(visitor);
    512        stack.pop();
    513    }
    514
    515    /** @since 6.0 */
    516    @Override
    517    public void visitConstantMethodHandle(final ConstantMethodHandle obj) {
    518        stack.push(obj);
    519        obj.accept(visitor);
    520        stack.pop();
    521    }
    522
    523    /** @since 6.0 */
    524    @Override
    525    public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) {
    526        stack.push(obj);
    527        obj.accept(visitor);
    528        stack.pop();
    529    }
    530
    531    /** @since 6.1 */
    532    @Override
    533    public void visitConstantPackage(final ConstantPackage obj) {
    534        stack.push(obj);
    535        obj.accept(visitor);
    536        stack.pop();
    537    }
    538
    539    /** @since 6.1 */
    540    @Override
    541    public void visitConstantModule(final ConstantModule obj) {
    542        stack.push(obj);
    543        obj.accept(visitor);
    544        stack.pop();
    545    }
    546
    547    /** @since 6.3 */
    548    @Override
    549    public void visitConstantDynamic(final ConstantDynamic obj) {
    550        stack.push(obj);
    551        obj.accept(visitor);
    552        stack.pop();
    553    }
    554}