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}