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   * @version $Id: DescendingVisitor.html 1018313 2017-09-18 09:03:04Z britter $
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       */
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       */
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       */
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       */
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       */
83      public void visit()
84      {
85          clazz.accept(this);
86      }
87  
88      @Override
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
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
128     public void visitAnnotationEntry(final AnnotationEntry annotationEntry)
129     {
130         stack.push(annotationEntry);
131         annotationEntry.accept(visitor);
132         stack.pop();
133     }
134 
135     @Override
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
148     public void visitConstantValue(final ConstantValue cv)
149     {
150         stack.push(cv);
151         cv.accept(visitor);
152         stack.pop();
153     }
154 
155     @Override
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
168     public void visitExceptionTable(final ExceptionTable table)
169     {
170         stack.push(table);
171         table.accept(visitor);
172         stack.pop();
173     }
174 
175     @Override
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
192     public void visitCodeException(final CodeException ce)
193     {
194         stack.push(ce);
195         ce.accept(visitor);
196         stack.pop();
197     }
198 
199     @Override
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
212     public void visitLineNumber(final LineNumber number)
213     {
214         stack.push(number);
215         number.accept(visitor);
216         stack.pop();
217     }
218 
219     @Override
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
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
244     public void visitStackMapEntry(final StackMapEntry var)
245     {
246         stack.push(var);
247         var.accept(visitor);
248         stack.pop();
249     }
250 
251     @Override
252     public void visitLocalVariable(final LocalVariable var)
253     {
254         stack.push(var);
255         var.accept(visitor);
256         stack.pop();
257     }
258 
259     @Override
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
276     public void visitConstantClass(final ConstantClass constant)
277     {
278         stack.push(constant);
279         constant.accept(visitor);
280         stack.pop();
281     }
282 
283     @Override
284     public void visitConstantDouble(final ConstantDouble constant)
285     {
286         stack.push(constant);
287         constant.accept(visitor);
288         stack.pop();
289     }
290 
291     @Override
292     public void visitConstantFieldref(final ConstantFieldref constant)
293     {
294         stack.push(constant);
295         constant.accept(visitor);
296         stack.pop();
297     }
298 
299     @Override
300     public void visitConstantFloat(final ConstantFloat constant)
301     {
302         stack.push(constant);
303         constant.accept(visitor);
304         stack.pop();
305     }
306 
307     @Override
308     public void visitConstantInteger(final ConstantInteger constant)
309     {
310         stack.push(constant);
311         constant.accept(visitor);
312         stack.pop();
313     }
314 
315     @Override
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
328     public void visitConstantInvokeDynamic(
329             final ConstantInvokeDynamic constant)
330     {
331         stack.push(constant);
332         constant.accept(visitor);
333         stack.pop();
334     }
335 
336     @Override
337     public void visitConstantLong(final ConstantLong constant)
338     {
339         stack.push(constant);
340         constant.accept(visitor);
341         stack.pop();
342     }
343 
344     @Override
345     public void visitConstantMethodref(final ConstantMethodref constant)
346     {
347         stack.push(constant);
348         constant.accept(visitor);
349         stack.pop();
350     }
351 
352     @Override
353     public void visitConstantNameAndType(final ConstantNameAndType constant)
354     {
355         stack.push(constant);
356         constant.accept(visitor);
357         stack.pop();
358     }
359 
360     @Override
361     public void visitConstantString(final ConstantString constant)
362     {
363         stack.push(constant);
364         constant.accept(visitor);
365         stack.pop();
366     }
367 
368     @Override
369     public void visitConstantUtf8(final ConstantUtf8 constant)
370     {
371         stack.push(constant);
372         constant.accept(visitor);
373         stack.pop();
374     }
375 
376     @Override
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
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
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
413     public void visitDeprecated(final Deprecated attribute)
414     {
415         stack.push(attribute);
416         attribute.accept(visitor);
417         stack.pop();
418     }
419 
420     @Override
421     public void visitSignature(final Signature attribute)
422     {
423         stack.push(attribute);
424         attribute.accept(visitor);
425         stack.pop();
426     }
427 
428     @Override
429     public void visitSourceFile(final SourceFile attribute)
430     {
431         stack.push(attribute);
432         attribute.accept(visitor);
433         stack.pop();
434     }
435 
436     @Override
437     public void visitSynthetic(final Synthetic attribute)
438     {
439         stack.push(attribute);
440         attribute.accept(visitor);
441         stack.pop();
442     }
443 
444     @Override
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
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
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
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
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
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
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
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
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
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
541     public void visitConstantModule(final ConstantModule obj) {
542         stack.push(obj);
543         obj.accept(visitor);
544         stack.pop();
545     }
546 }