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