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