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