1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 package org.apache.bcel.classfile; 19 20 import java.util.Stack; 21 22 /** 23 * Traverses a JavaClass with another Visitor object 'piggy-backed' that is 24 * applied to all components of a JavaClass object. I.e. this class supplies the 25 * traversal strategy, other classes can make use of it. 26 * 27 * @version $Id$ 28 */ 29 public class DescendingVisitor implements Visitor 30 { 31 private final JavaClass clazz; 32 33 private final Visitor visitor; 34 35 private final Stack<Object> stack = new Stack<>(); 36 37 /** 38 * @return container of current entitity, i.e., predecessor during traversal 39 */ predecessor()40 public Object predecessor() 41 { 42 return predecessor(0); 43 } 44 45 /** 46 * @param level 47 * nesting level, i.e., 0 returns the direct predecessor 48 * @return container of current entitity, i.e., predecessor during traversal 49 */ predecessor(final int level)50 public Object predecessor(final int level) 51 { 52 final int size = stack.size(); 53 if ((size < 2) || (level < 0)) 54 { 55 return null; 56 } 57 return stack.elementAt(size - (level + 2)); // size - 1 == current 58 } 59 60 /** 61 * @return current object 62 */ current()63 public Object current() 64 { 65 return stack.peek(); 66 } 67 68 /** 69 * @param clazz 70 * Class to traverse 71 * @param visitor 72 * visitor object to apply to all components 73 */ DescendingVisitor(final JavaClass clazz, final Visitor visitor)74 public DescendingVisitor(final JavaClass clazz, final Visitor visitor) 75 { 76 this.clazz = clazz; 77 this.visitor = visitor; 78 } 79 80 /** 81 * Start traversal. 82 */ visit()83 public void visit() 84 { 85 clazz.accept(this); 86 } 87 88 @Override visitJavaClass(final JavaClass _clazz)89 public void visitJavaClass(final JavaClass _clazz) 90 { 91 stack.push(_clazz); 92 _clazz.accept(visitor); 93 final Field[] fields = _clazz.getFields(); 94 for (final Field field : fields) { 95 field.accept(this); 96 } 97 final Method[] methods = _clazz.getMethods(); 98 for (final Method method : methods) { 99 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 visitAnnotation(final Annotations annotation)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 visitAnnotationEntry(final AnnotationEntry annotationEntry)128 public void visitAnnotationEntry(final AnnotationEntry annotationEntry) 129 { 130 stack.push(annotationEntry); 131 annotationEntry.accept(visitor); 132 stack.pop(); 133 } 134 135 @Override visitField(final Field field)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 visitConstantValue(final ConstantValue cv)148 public void visitConstantValue(final ConstantValue cv) 149 { 150 stack.push(cv); 151 cv.accept(visitor); 152 stack.pop(); 153 } 154 155 @Override visitMethod(final Method method)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 visitExceptionTable(final ExceptionTable table)168 public void visitExceptionTable(final ExceptionTable table) 169 { 170 stack.push(table); 171 table.accept(visitor); 172 stack.pop(); 173 } 174 175 @Override visitCode(final Code code)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 visitCodeException(final CodeException ce)192 public void visitCodeException(final CodeException ce) 193 { 194 stack.push(ce); 195 ce.accept(visitor); 196 stack.pop(); 197 } 198 199 @Override visitLineNumberTable(final LineNumberTable table)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 visitLineNumber(final LineNumber number)212 public void visitLineNumber(final LineNumber number) 213 { 214 stack.push(number); 215 number.accept(visitor); 216 stack.pop(); 217 } 218 219 @Override visitLocalVariableTable(final LocalVariableTable table)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 visitStackMap(final StackMap table)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 visitStackMapEntry(final StackMapEntry var)244 public void visitStackMapEntry(final StackMapEntry var) 245 { 246 stack.push(var); 247 var.accept(visitor); 248 stack.pop(); 249 } 250 251 @Override visitLocalVariable(final LocalVariable var)252 public void visitLocalVariable(final LocalVariable var) 253 { 254 stack.push(var); 255 var.accept(visitor); 256 stack.pop(); 257 } 258 259 @Override visitConstantPool(final ConstantPool cp)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 visitConstantClass(final ConstantClass constant)276 public void visitConstantClass(final ConstantClass constant) 277 { 278 stack.push(constant); 279 constant.accept(visitor); 280 stack.pop(); 281 } 282 283 @Override visitConstantDouble(final ConstantDouble constant)284 public void visitConstantDouble(final ConstantDouble constant) 285 { 286 stack.push(constant); 287 constant.accept(visitor); 288 stack.pop(); 289 } 290 291 @Override visitConstantFieldref(final ConstantFieldref constant)292 public void visitConstantFieldref(final ConstantFieldref constant) 293 { 294 stack.push(constant); 295 constant.accept(visitor); 296 stack.pop(); 297 } 298 299 @Override visitConstantFloat(final ConstantFloat constant)300 public void visitConstantFloat(final ConstantFloat constant) 301 { 302 stack.push(constant); 303 constant.accept(visitor); 304 stack.pop(); 305 } 306 307 @Override visitConstantInteger(final ConstantInteger constant)308 public void visitConstantInteger(final ConstantInteger constant) 309 { 310 stack.push(constant); 311 constant.accept(visitor); 312 stack.pop(); 313 } 314 315 @Override visitConstantInterfaceMethodref( final ConstantInterfaceMethodref constant)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 visitConstantInvokeDynamic( final ConstantInvokeDynamic constant)328 public void visitConstantInvokeDynamic( 329 final ConstantInvokeDynamic constant) 330 { 331 stack.push(constant); 332 constant.accept(visitor); 333 stack.pop(); 334 } 335 336 @Override visitConstantLong(final ConstantLong constant)337 public void visitConstantLong(final ConstantLong constant) 338 { 339 stack.push(constant); 340 constant.accept(visitor); 341 stack.pop(); 342 } 343 344 @Override visitConstantMethodref(final ConstantMethodref constant)345 public void visitConstantMethodref(final ConstantMethodref constant) 346 { 347 stack.push(constant); 348 constant.accept(visitor); 349 stack.pop(); 350 } 351 352 @Override visitConstantNameAndType(final ConstantNameAndType constant)353 public void visitConstantNameAndType(final ConstantNameAndType constant) 354 { 355 stack.push(constant); 356 constant.accept(visitor); 357 stack.pop(); 358 } 359 360 @Override visitConstantString(final ConstantString constant)361 public void visitConstantString(final ConstantString constant) 362 { 363 stack.push(constant); 364 constant.accept(visitor); 365 stack.pop(); 366 } 367 368 @Override visitConstantUtf8(final ConstantUtf8 constant)369 public void visitConstantUtf8(final ConstantUtf8 constant) 370 { 371 stack.push(constant); 372 constant.accept(visitor); 373 stack.pop(); 374 } 375 376 @Override visitInnerClasses(final InnerClasses ic)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 visitInnerClass(final InnerClass inner)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 visitBootstrapMethods(final BootstrapMethods bm)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 visitDeprecated(final Deprecated attribute)413 public void visitDeprecated(final Deprecated attribute) 414 { 415 stack.push(attribute); 416 attribute.accept(visitor); 417 stack.pop(); 418 } 419 420 @Override visitSignature(final Signature attribute)421 public void visitSignature(final Signature attribute) 422 { 423 stack.push(attribute); 424 attribute.accept(visitor); 425 stack.pop(); 426 } 427 428 @Override visitSourceFile(final SourceFile attribute)429 public void visitSourceFile(final SourceFile attribute) 430 { 431 stack.push(attribute); 432 attribute.accept(visitor); 433 stack.pop(); 434 } 435 436 @Override visitSynthetic(final Synthetic attribute)437 public void visitSynthetic(final Synthetic attribute) 438 { 439 stack.push(attribute); 440 attribute.accept(visitor); 441 stack.pop(); 442 } 443 444 @Override visitUnknown(final Unknown attribute)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 visitAnnotationDefault(final AnnotationDefault obj)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 visitEnclosingMethod(final EnclosingMethod obj)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 visitLocalVariableTypeTable(final LocalVariableTypeTable obj)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 visitParameterAnnotation(final ParameterAnnotations obj)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 visitMethodParameters(final MethodParameters obj)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 visitConstantMethodType(final ConstantMethodType obj)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 visitConstantMethodHandle(final ConstantMethodHandle obj)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 visitParameterAnnotationEntry(final ParameterAnnotationEntry obj)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 visitConstantPackage(final ConstantPackage obj)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 visitConstantModule(final ConstantModule obj)541 public void visitConstantModule(final ConstantModule obj) { 542 stack.push(obj); 543 obj.accept(visitor); 544 stack.pop(); 545 } 546 } 547