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