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