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