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 */ 20package com.sun.org.apache.bcel.internal.classfile; 21 22import 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 * @version $Id: DescendingVisitor.java 1749603 2016-06-21 20:50:19Z ggregory $ 30 */ 31public class DescendingVisitor implements Visitor { 32 33 private final JavaClass clazz; 34 35 private final Visitor visitor; 36 37 private final Stack<Object> stack = new Stack<>(); 38 39 /** 40 * @return container of current entitity, i.e., predecessor during traversal 41 */ 42 public Object predecessor() { 43 return predecessor(0); 44 } 45 46 /** 47 * @param level nesting level, i.e., 0 returns the direct predecessor 48 * @return container of current entitity, i.e., predecessor during traversal 49 */ 50 public Object predecessor(final int level) { 51 final int size = stack.size(); 52 if ((size < 2) || (level < 0)) { 53 return null; 54 } 55 return stack.elementAt(size - (level + 2)); // size - 1 == current 56 } 57 58 /** 59 * @return current object 60 */ 61 public Object current() { 62 return stack.peek(); 63 } 64 65 /** 66 * @param clazz Class to traverse 67 * @param visitor visitor object to apply to all components 68 */ 69 public DescendingVisitor(final JavaClass clazz, final Visitor visitor) { 70 this.clazz = clazz; 71 this.visitor = visitor; 72 } 73 74 /** 75 * Start traversal. 76 */ 77 public void visit() { 78 clazz.accept(this); 79 } 80 81 @Override 82 public void visitJavaClass(final JavaClass _clazz) { 83 stack.push(_clazz); 84 _clazz.accept(visitor); 85 final Field[] fields = _clazz.getFields(); 86 for (final Field field : fields) { 87 field.accept(this); 88 } 89 final Method[] methods = _clazz.getMethods(); 90 for (final Method method : methods) { 91 method.accept(this); 92 } 93 final Attribute[] attributes = _clazz.getAttributes(); 94 for (final Attribute attribute : attributes) { 95 attribute.accept(this); 96 } 97 _clazz.getConstantPool().accept(this); 98 stack.pop(); 99 } 100 101 /** 102 * @since 6.0 103 */ 104 @Override 105 public void visitAnnotation(final Annotations annotation) { 106 stack.push(annotation); 107 annotation.accept(visitor); 108 final AnnotationEntry[] entries = annotation.getAnnotationEntries(); 109 for (final AnnotationEntry entrie : entries) { 110 entrie.accept(this); 111 } 112 stack.pop(); 113 } 114 115 /** 116 * @since 6.0 117 */ 118 @Override 119 public void visitAnnotationEntry(final AnnotationEntry annotationEntry) { 120 stack.push(annotationEntry); 121 annotationEntry.accept(visitor); 122 stack.pop(); 123 } 124 125 @Override 126 public void visitField(final Field field) { 127 stack.push(field); 128 field.accept(visitor); 129 final Attribute[] attributes = field.getAttributes(); 130 for (final Attribute attribute : attributes) { 131 attribute.accept(this); 132 } 133 stack.pop(); 134 } 135 136 @Override 137 public void visitConstantValue(final ConstantValue cv) { 138 stack.push(cv); 139 cv.accept(visitor); 140 stack.pop(); 141 } 142 143 @Override 144 public void visitMethod(final Method method) { 145 stack.push(method); 146 method.accept(visitor); 147 final Attribute[] attributes = method.getAttributes(); 148 for (final Attribute attribute : attributes) { 149 attribute.accept(this); 150 } 151 stack.pop(); 152 } 153 154 @Override 155 public void visitExceptionTable(final ExceptionTable table) { 156 stack.push(table); 157 table.accept(visitor); 158 stack.pop(); 159 } 160 161 @Override 162 public void visitCode(final Code code) { 163 stack.push(code); 164 code.accept(visitor); 165 final CodeException[] table = code.getExceptionTable(); 166 for (final CodeException element : table) { 167 element.accept(this); 168 } 169 final Attribute[] attributes = code.getAttributes(); 170 for (final Attribute attribute : attributes) { 171 attribute.accept(this); 172 } 173 stack.pop(); 174 } 175 176 @Override 177 public void visitCodeException(final CodeException ce) { 178 stack.push(ce); 179 ce.accept(visitor); 180 stack.pop(); 181 } 182 183 @Override 184 public void visitLineNumberTable(final LineNumberTable table) { 185 stack.push(table); 186 table.accept(visitor); 187 final LineNumber[] numbers = table.getLineNumberTable(); 188 for (final LineNumber number : numbers) { 189 number.accept(this); 190 } 191 stack.pop(); 192 } 193 194 @Override 195 public void visitLineNumber(final LineNumber number) { 196 stack.push(number); 197 number.accept(visitor); 198 stack.pop(); 199 } 200 201 @Override 202 public void visitLocalVariableTable(final LocalVariableTable table) { 203 stack.push(table); 204 table.accept(visitor); 205 final LocalVariable[] vars = table.getLocalVariableTable(); 206 for (final LocalVariable var : vars) { 207 var.accept(this); 208 } 209 stack.pop(); 210 } 211 212 @Override 213 public void visitStackMap(final StackMap table) { 214 stack.push(table); 215 table.accept(visitor); 216 final StackMapEntry[] vars = table.getStackMap(); 217 for (final StackMapEntry var : vars) { 218 var.accept(this); 219 } 220 stack.pop(); 221 } 222 223 @Override 224 public void visitStackMapEntry(final StackMapEntry var) { 225 stack.push(var); 226 var.accept(visitor); 227 stack.pop(); 228 } 229 230 @Override 231 public void visitLocalVariable(final LocalVariable var) { 232 stack.push(var); 233 var.accept(visitor); 234 stack.pop(); 235 } 236 237 @Override 238 public void visitConstantPool(final ConstantPool cp) { 239 stack.push(cp); 240 cp.accept(visitor); 241 final Constant[] constants = cp.getConstantPool(); 242 for (int i = 1; i < constants.length; i++) { 243 if (constants[i] != null) { 244 constants[i].accept(this); 245 } 246 } 247 stack.pop(); 248 } 249 250 @Override 251 public void visitConstantClass(final ConstantClass constant) { 252 stack.push(constant); 253 constant.accept(visitor); 254 stack.pop(); 255 } 256 257 @Override 258 public void visitConstantDouble(final ConstantDouble constant) { 259 stack.push(constant); 260 constant.accept(visitor); 261 stack.pop(); 262 } 263 264 @Override 265 public void visitConstantFieldref(final ConstantFieldref constant) { 266 stack.push(constant); 267 constant.accept(visitor); 268 stack.pop(); 269 } 270 271 @Override 272 public void visitConstantFloat(final ConstantFloat constant) { 273 stack.push(constant); 274 constant.accept(visitor); 275 stack.pop(); 276 } 277 278 @Override 279 public void visitConstantInteger(final ConstantInteger constant) { 280 stack.push(constant); 281 constant.accept(visitor); 282 stack.pop(); 283 } 284 285 @Override 286 public void visitConstantInterfaceMethodref( 287 final ConstantInterfaceMethodref constant) { 288 stack.push(constant); 289 constant.accept(visitor); 290 stack.pop(); 291 } 292 293 /** 294 * @since 6.0 295 */ 296 @Override 297 public void visitConstantInvokeDynamic( 298 final ConstantInvokeDynamic constant) { 299 stack.push(constant); 300 constant.accept(visitor); 301 stack.pop(); 302 } 303 304 @Override 305 public void visitConstantLong(final ConstantLong constant) { 306 stack.push(constant); 307 constant.accept(visitor); 308 stack.pop(); 309 } 310 311 @Override 312 public void visitConstantMethodref(final ConstantMethodref constant) { 313 stack.push(constant); 314 constant.accept(visitor); 315 stack.pop(); 316 } 317 318 @Override 319 public void visitConstantNameAndType(final ConstantNameAndType constant) { 320 stack.push(constant); 321 constant.accept(visitor); 322 stack.pop(); 323 } 324 325 @Override 326 public void visitConstantString(final ConstantString constant) { 327 stack.push(constant); 328 constant.accept(visitor); 329 stack.pop(); 330 } 331 332 @Override 333 public void visitConstantUtf8(final ConstantUtf8 constant) { 334 stack.push(constant); 335 constant.accept(visitor); 336 stack.pop(); 337 } 338 339 @Override 340 public void visitInnerClasses(final InnerClasses ic) { 341 stack.push(ic); 342 ic.accept(visitor); 343 final InnerClass[] ics = ic.getInnerClasses(); 344 for (final InnerClass ic2 : ics) { 345 ic2.accept(this); 346 } 347 stack.pop(); 348 } 349 350 @Override 351 public void visitInnerClass(final InnerClass inner) { 352 stack.push(inner); 353 inner.accept(visitor); 354 stack.pop(); 355 } 356 357 /** 358 * @since 6.0 359 */ 360 @Override 361 public void visitBootstrapMethods(final BootstrapMethods bm) { 362 stack.push(bm); 363 bm.accept(visitor); 364 // BootstrapMethod[] bms = bm.getBootstrapMethods(); 365 // for (int i = 0; i < bms.length; i++) 366 // { 367 // bms[i].accept(this); 368 // } 369 stack.pop(); 370 } 371 372 @Override 373 public void visitDeprecated(final Deprecated attribute) { 374 stack.push(attribute); 375 attribute.accept(visitor); 376 stack.pop(); 377 } 378 379 @Override 380 public void visitSignature(final Signature attribute) { 381 stack.push(attribute); 382 attribute.accept(visitor); 383 stack.pop(); 384 } 385 386 @Override 387 public void visitSourceFile(final SourceFile attribute) { 388 stack.push(attribute); 389 attribute.accept(visitor); 390 stack.pop(); 391 } 392 393 @Override 394 public void visitSynthetic(final Synthetic attribute) { 395 stack.push(attribute); 396 attribute.accept(visitor); 397 stack.pop(); 398 } 399 400 @Override 401 public void visitUnknown(final Unknown attribute) { 402 stack.push(attribute); 403 attribute.accept(visitor); 404 stack.pop(); 405 } 406 407 /** 408 * @since 6.0 409 */ 410 @Override 411 public void visitAnnotationDefault(final AnnotationDefault obj) { 412 stack.push(obj); 413 obj.accept(visitor); 414 stack.pop(); 415 } 416 417 /** 418 * @since 6.0 419 */ 420 @Override 421 public void visitEnclosingMethod(final EnclosingMethod obj) { 422 stack.push(obj); 423 obj.accept(visitor); 424 stack.pop(); 425 } 426 427 /** 428 * @since 6.0 429 */ 430 @Override 431 public void visitLocalVariableTypeTable(final LocalVariableTypeTable obj) { 432 stack.push(obj); 433 obj.accept(visitor); 434 LocalVariable[] vars = obj.getLocalVariableTypeTable(); 435 for (LocalVariable var : vars) { 436 var.accept(this); 437 } 438 stack.pop(); 439 } 440 441 /** 442 * @since 6.0 443 */ 444 @Override 445 public void visitParameterAnnotation(final ParameterAnnotations obj) { 446 stack.push(obj); 447 obj.accept(visitor); 448 stack.pop(); 449 } 450 451 /** 452 * @since 6.0 453 */ 454 @Override 455 public void visitMethodParameters(final MethodParameters obj) { 456 stack.push(obj); 457 obj.accept(visitor); 458 stack.pop(); 459 } 460 461 /** 462 * @since 6.0 463 */ 464 @Override 465 public void visitConstantMethodType(final ConstantMethodType obj) { 466 stack.push(obj); 467 obj.accept(visitor); 468 stack.pop(); 469 } 470 471 /** 472 * @since 6.0 473 */ 474 @Override 475 public void visitConstantMethodHandle(final ConstantMethodHandle obj) { 476 stack.push(obj); 477 obj.accept(visitor); 478 stack.pop(); 479 } 480 481 /** 482 * @since 6.0 483 */ 484 @Override 485 public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) { 486 stack.push(obj); 487 obj.accept(visitor); 488 stack.pop(); 489 } 490 491} 492