1 /*
   2  * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package com.sun.org.apache.bcel.internal.classfile;
  21 
  22 import java.util.Stack;
  23 
  24 /**
  25  * Traverses a JavaClass with another Visitor object 'piggy-backed' that is
  26  * applied to all components of a JavaClass object. I.e. this class supplies the
  27  * traversal strategy, other classes can make use of it.
  28  *
  29  */
  30 public class DescendingVisitor implements Visitor
  31 {
  32     private final JavaClass clazz;
  33 
  34     private final Visitor visitor;
  35 
  36     private final Stack<Object> stack = new Stack<>();
  37 
  38     /**
  39      * @return container of current entitity, i.e., predecessor during traversal
  40      */
  41     public Object predecessor()
  42     {
  43         return predecessor(0);
  44     }
  45 
  46     /**
  47      * @param level
  48      *            nesting level, i.e., 0 returns the direct predecessor
  49      * @return container of current entitity, i.e., predecessor during traversal
  50      */
  51     public Object predecessor(final int level)
  52     {
  53         final int size = stack.size();
  54         if ((size < 2) || (level < 0))
  55         {
  56             return null;
  57         }
  58         return stack.elementAt(size - (level + 2)); // size - 1 == current
  59     }
  60 
  61     /**
  62      * @return current object
  63      */
  64     public Object current()
  65     {
  66         return stack.peek();
  67     }
  68 
  69     /**
  70      * @param clazz
  71      *            Class to traverse
  72      * @param visitor
  73      *            visitor object to apply to all components
  74      */
  75     public DescendingVisitor(final JavaClass clazz, final Visitor visitor)
  76     {
  77         this.clazz = clazz;
  78         this.visitor = visitor;
  79     }
  80 
  81     /**
  82      * Start traversal.
  83      */
  84     public void visit()
  85     {
  86         clazz.accept(this);
  87     }
  88 
  89     @Override
  90     public void visitJavaClass(final JavaClass _clazz)
  91     {
  92         stack.push(_clazz);
  93         _clazz.accept(visitor);
  94         final Field[] fields = _clazz.getFields();
  95         for (final Field field : fields) {
  96             field.accept(this);
  97         }
  98         final Method[] methods = _clazz.getMethods();
  99         for (final Method method : methods) {
 100             method.accept(this);
 101         }
 102         final Attribute[] attributes = _clazz.getAttributes();
 103         for (final Attribute attribute : attributes) {
 104             attribute.accept(this);
 105         }
 106         _clazz.getConstantPool().accept(this);
 107         stack.pop();
 108     }
 109 
 110     /**
 111      * @since 6.0
 112      */
 113     @Override
 114     public void visitAnnotation(final Annotations annotation)
 115     {
 116         stack.push(annotation);
 117         annotation.accept(visitor);
 118         final AnnotationEntry[] entries = annotation.getAnnotationEntries();
 119         for (final AnnotationEntry entrie : entries) {
 120             entrie.accept(this);
 121         }
 122         stack.pop();
 123     }
 124 
 125     /**
 126      * @since 6.0
 127      */
 128     @Override
 129     public void visitAnnotationEntry(final AnnotationEntry annotationEntry)
 130     {
 131         stack.push(annotationEntry);
 132         annotationEntry.accept(visitor);
 133         stack.pop();
 134     }
 135 
 136     @Override
 137     public void visitField(final Field field)
 138     {
 139         stack.push(field);
 140         field.accept(visitor);
 141         final Attribute[] attributes = field.getAttributes();
 142         for (final Attribute attribute : attributes) {
 143             attribute.accept(this);
 144         }
 145         stack.pop();
 146     }
 147 
 148     @Override
 149     public void visitConstantValue(final ConstantValue cv)
 150     {
 151         stack.push(cv);
 152         cv.accept(visitor);
 153         stack.pop();
 154     }
 155 
 156     @Override
 157     public void visitMethod(final Method method)
 158     {
 159         stack.push(method);
 160         method.accept(visitor);
 161         final Attribute[] attributes = method.getAttributes();
 162         for (final Attribute attribute : attributes) {
 163             attribute.accept(this);
 164         }
 165         stack.pop();
 166     }
 167 
 168     @Override
 169     public void visitExceptionTable(final ExceptionTable table)
 170     {
 171         stack.push(table);
 172         table.accept(visitor);
 173         stack.pop();
 174     }
 175 
 176     @Override
 177     public void visitCode(final Code code)
 178     {
 179         stack.push(code);
 180         code.accept(visitor);
 181         final CodeException[] table = code.getExceptionTable();
 182         for (final CodeException element : table) {
 183             element.accept(this);
 184         }
 185         final Attribute[] attributes = code.getAttributes();
 186         for (final Attribute attribute : attributes) {
 187             attribute.accept(this);
 188         }
 189         stack.pop();
 190     }
 191 
 192     @Override
 193     public void visitCodeException(final CodeException ce)
 194     {
 195         stack.push(ce);
 196         ce.accept(visitor);
 197         stack.pop();
 198     }
 199 
 200     @Override
 201     public void visitLineNumberTable(final LineNumberTable table)
 202     {
 203         stack.push(table);
 204         table.accept(visitor);
 205         final LineNumber[] numbers = table.getLineNumberTable();
 206         for (final LineNumber number : numbers) {
 207             number.accept(this);
 208         }
 209         stack.pop();
 210     }
 211 
 212     @Override
 213     public void visitLineNumber(final LineNumber number)
 214     {
 215         stack.push(number);
 216         number.accept(visitor);
 217         stack.pop();
 218     }
 219 
 220     @Override
 221     public void visitLocalVariableTable(final LocalVariableTable table)
 222     {
 223         stack.push(table);
 224         table.accept(visitor);
 225         final LocalVariable[] vars = table.getLocalVariableTable();
 226         for (final LocalVariable var : vars) {
 227             var.accept(this);
 228         }
 229         stack.pop();
 230     }
 231 
 232     @Override
 233     public void visitStackMap(final StackMap table)
 234     {
 235         stack.push(table);
 236         table.accept(visitor);
 237         final StackMapEntry[] vars = table.getStackMap();
 238         for (final StackMapEntry var : vars) {
 239             var.accept(this);
 240         }
 241         stack.pop();
 242     }
 243 
 244     @Override
 245     public void visitStackMapEntry(final StackMapEntry var)
 246     {
 247         stack.push(var);
 248         var.accept(visitor);
 249         stack.pop();
 250     }
 251 
 252     @Override
 253     public void visitLocalVariable(final LocalVariable var)
 254     {
 255         stack.push(var);
 256         var.accept(visitor);
 257         stack.pop();
 258     }
 259 
 260     @Override
 261     public void visitConstantPool(final ConstantPool cp)
 262     {
 263         stack.push(cp);
 264         cp.accept(visitor);
 265         final Constant[] constants = cp.getConstantPool();
 266         for (int i = 1; i < constants.length; i++)
 267         {
 268             if (constants[i] != null)
 269             {
 270                 constants[i].accept(this);
 271             }
 272         }
 273         stack.pop();
 274     }
 275 
 276     @Override
 277     public void visitConstantClass(final ConstantClass constant)
 278     {
 279         stack.push(constant);
 280         constant.accept(visitor);
 281         stack.pop();
 282     }
 283 
 284     @Override
 285     public void visitConstantDouble(final ConstantDouble constant)
 286     {
 287         stack.push(constant);
 288         constant.accept(visitor);
 289         stack.pop();
 290     }
 291 
 292     @Override
 293     public void visitConstantFieldref(final ConstantFieldref constant)
 294     {
 295         stack.push(constant);
 296         constant.accept(visitor);
 297         stack.pop();
 298     }
 299 
 300     @Override
 301     public void visitConstantFloat(final ConstantFloat constant)
 302     {
 303         stack.push(constant);
 304         constant.accept(visitor);
 305         stack.pop();
 306     }
 307 
 308     @Override
 309     public void visitConstantInteger(final ConstantInteger constant)
 310     {
 311         stack.push(constant);
 312         constant.accept(visitor);
 313         stack.pop();
 314     }
 315 
 316     @Override
 317     public void visitConstantInterfaceMethodref(
 318             final ConstantInterfaceMethodref constant)
 319     {
 320         stack.push(constant);
 321         constant.accept(visitor);
 322         stack.pop();
 323     }
 324 
 325     /**
 326      * @since 6.0
 327      */
 328     @Override
 329     public void visitConstantInvokeDynamic(
 330             final ConstantInvokeDynamic constant)
 331     {
 332         stack.push(constant);
 333         constant.accept(visitor);
 334         stack.pop();
 335     }
 336 
 337     @Override
 338     public void visitConstantLong(final ConstantLong constant)
 339     {
 340         stack.push(constant);
 341         constant.accept(visitor);
 342         stack.pop();
 343     }
 344 
 345     @Override
 346     public void visitConstantMethodref(final ConstantMethodref constant)
 347     {
 348         stack.push(constant);
 349         constant.accept(visitor);
 350         stack.pop();
 351     }
 352 
 353     @Override
 354     public void visitConstantNameAndType(final ConstantNameAndType constant)
 355     {
 356         stack.push(constant);
 357         constant.accept(visitor);
 358         stack.pop();
 359     }
 360 
 361     @Override
 362     public void visitConstantString(final ConstantString constant)
 363     {
 364         stack.push(constant);
 365         constant.accept(visitor);
 366         stack.pop();
 367     }
 368 
 369     @Override
 370     public void visitConstantUtf8(final ConstantUtf8 constant)
 371     {
 372         stack.push(constant);
 373         constant.accept(visitor);
 374         stack.pop();
 375     }
 376 
 377     @Override
 378     public void visitInnerClasses(final InnerClasses ic)
 379     {
 380         stack.push(ic);
 381         ic.accept(visitor);
 382         final InnerClass[] ics = ic.getInnerClasses();
 383         for (final InnerClass ic2 : ics) {
 384             ic2.accept(this);
 385         }
 386         stack.pop();
 387     }
 388 
 389     @Override
 390     public void visitInnerClass(final InnerClass inner)
 391     {
 392         stack.push(inner);
 393         inner.accept(visitor);
 394         stack.pop();
 395     }
 396 
 397     /**
 398      * @since 6.0
 399      */
 400     @Override
 401     public void visitBootstrapMethods(final BootstrapMethods bm)
 402     {
 403         stack.push(bm);
 404         bm.accept(visitor);
 405         // BootstrapMethod[] bms = bm.getBootstrapMethods();
 406         // for (int i = 0; i < bms.length; i++)
 407         // {
 408         //     bms[i].accept(this);
 409         // }
 410         stack.pop();
 411     }
 412 
 413     @Override
 414     public void visitDeprecated(final Deprecated attribute)
 415     {
 416         stack.push(attribute);
 417         attribute.accept(visitor);
 418         stack.pop();
 419     }
 420 
 421     @Override
 422     public void visitSignature(final Signature attribute)
 423     {
 424         stack.push(attribute);
 425         attribute.accept(visitor);
 426         stack.pop();
 427     }
 428 
 429     @Override
 430     public void visitSourceFile(final SourceFile attribute)
 431     {
 432         stack.push(attribute);
 433         attribute.accept(visitor);
 434         stack.pop();
 435     }
 436 
 437     @Override
 438     public void visitSynthetic(final Synthetic attribute)
 439     {
 440         stack.push(attribute);
 441         attribute.accept(visitor);
 442         stack.pop();
 443     }
 444 
 445     @Override
 446     public void visitUnknown(final Unknown attribute)
 447     {
 448         stack.push(attribute);
 449         attribute.accept(visitor);
 450         stack.pop();
 451     }
 452 
 453     /**
 454      * @since 6.0
 455      */
 456     @Override
 457     public void visitAnnotationDefault(final AnnotationDefault obj)
 458     {
 459         stack.push(obj);
 460         obj.accept(visitor);
 461         stack.pop();
 462     }
 463 
 464     /**
 465      * @since 6.0
 466      */
 467     @Override
 468     public void visitEnclosingMethod(final EnclosingMethod obj)
 469     {
 470         stack.push(obj);
 471         obj.accept(visitor);
 472         stack.pop();
 473     }
 474 
 475     /**
 476      * @since 6.0
 477      */
 478     @Override
 479     public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj)
 480     {
 481         stack.push(obj);
 482         obj.accept(visitor);
 483         stack.pop();
 484     }
 485 
 486     /**
 487      * @since 6.0
 488      */
 489     @Override
 490     public void visitParameterAnnotation(final ParameterAnnotations obj)
 491     {
 492         stack.push(obj);
 493         obj.accept(visitor);
 494         stack.pop();
 495     }
 496 
 497     /**
 498      * @since 6.0
 499      */
 500     @Override
 501     public void visitMethodParameters(final MethodParameters obj)
 502     {
 503         stack.push(obj);
 504         obj.accept(visitor);
 505         final MethodParameter[] table = obj.getParameters();
 506         for (final MethodParameter element : table) {
 507             element.accept(this);
 508         }
 509         stack.pop();
 510     }
 511 
 512     /**
 513      * @since 6.4.0
 514      */
 515     @Override
 516     public void visitMethodParameter(final MethodParameter obj)
 517     {
 518         stack.push(obj);
 519         obj.accept(visitor);
 520         stack.pop();
 521     }
 522 
 523     /** @since 6.0 */
 524     @Override
 525     public void visitConstantMethodType(final ConstantMethodType obj) {
 526         stack.push(obj);
 527         obj.accept(visitor);
 528         stack.pop();
 529     }
 530 
 531     /** @since 6.0 */
 532     @Override
 533     public void visitConstantMethodHandle(final ConstantMethodHandle obj) {
 534         stack.push(obj);
 535         obj.accept(visitor);
 536         stack.pop();
 537     }
 538 
 539     /** @since 6.0 */
 540     @Override
 541     public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) {
 542         stack.push(obj);
 543         obj.accept(visitor);
 544         stack.pop();
 545     }
 546 
 547     /** @since 6.1 */
 548     @Override
 549     public void visitConstantPackage(final ConstantPackage obj) {
 550         stack.push(obj);
 551         obj.accept(visitor);
 552         stack.pop();
 553     }
 554 
 555     /** @since 6.1 */
 556     @Override
 557     public void visitConstantModule(final ConstantModule obj) {
 558         stack.push(obj);
 559         obj.accept(visitor);
 560         stack.pop();
 561     }
 562 
 563     /** @since 6.3 */
 564     @Override
 565     public void visitConstantDynamic(final ConstantDynamic obj) {
 566         stack.push(obj);
 567         obj.accept(visitor);
 568         stack.pop();
 569     }
 570 
 571     /** @since 6.4.0 */
 572     @Override
 573     public void visitModule(final Module obj) {
 574         stack.push(obj);
 575         obj.accept(visitor);
 576         final ModuleRequires[] rtable = obj.getRequiresTable();
 577         for (final ModuleRequires element : rtable) {
 578             element.accept(this);
 579         }
 580         final ModuleExports[] etable = obj.getExportsTable();
 581         for (final ModuleExports element : etable) {
 582             element.accept(this);
 583         }
 584         final ModuleOpens[] otable = obj.getOpensTable();
 585         for (final ModuleOpens element : otable) {
 586             element.accept(this);
 587         }
 588         final ModuleProvides[] ptable = obj.getProvidesTable();
 589         for (final ModuleProvides element : ptable) {
 590             element.accept(this);
 591         }
 592         stack.pop();
 593     }
 594 
 595     /** @since 6.4.0 */
 596     @Override
 597     public void visitModuleRequires(final ModuleRequires obj) {
 598         stack.push(obj);
 599         obj.accept(visitor);
 600         stack.pop();
 601     }
 602 
 603     /** @since 6.4.0 */
 604     @Override
 605     public void visitModuleExports(final ModuleExports obj) {
 606         stack.push(obj);
 607         obj.accept(visitor);
 608         stack.pop();
 609     }
 610 
 611     /** @since 6.4.0 */
 612     @Override
 613     public void visitModuleOpens(final ModuleOpens obj) {
 614         stack.push(obj);
 615         obj.accept(visitor);
 616         stack.pop();
 617     }
 618 
 619     /** @since 6.4.0 */
 620     @Override
 621     public void visitModuleProvides(final ModuleProvides obj) {
 622         stack.push(obj);
 623         obj.accept(visitor);
 624         stack.pop();
 625     }
 626 
 627     /** @since 6.4.0 */
 628     @Override
 629     public void visitModulePackages(final ModulePackages obj) {
 630         stack.push(obj);
 631         obj.accept(visitor);
 632         stack.pop();
 633     }
 634 
 635     /** @since 6.4.0 */
 636     @Override
 637     public void visitModuleMainClass(final ModuleMainClass obj) {
 638         stack.push(obj);
 639         obj.accept(visitor);
 640         stack.pop();
 641     }
 642 
 643     /** @since 6.4.0 */
 644     @Override
 645     public void visitNestHost(final NestHost obj) {
 646         stack.push(obj);
 647         obj.accept(visitor);
 648         stack.pop();
 649     }
 650 
 651     /** @since 6.4.0 */
 652     @Override
 653     public void visitNestMembers(final NestMembers obj) {
 654         stack.push(obj);
 655         obj.accept(visitor);
 656         stack.pop();
 657     }
 658 }