001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 */
018 package org.apache.bcel.classfile;
019
020 import java.util.Stack;
021
022 /**
023 * Traverses a JavaClass with another Visitor object 'piggy-backed' that is
024 * applied to all components of a JavaClass object. I.e. this class supplies the
025 * traversal strategy, other classes can make use of it.
026 *
027 * @version $Id: DescendingVisitor.java 1149459 2011-07-22 04:34:27Z dbrosius $
028 * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
029 */
030 public class DescendingVisitor implements Visitor
031 {
032 private JavaClass clazz;
033
034 private Visitor visitor;
035
036 private Stack<Object> stack = new Stack<Object>();
037
038 /**
039 * @return container of current entitity, i.e., predecessor during traversal
040 */
041 public Object predecessor()
042 {
043 return predecessor(0);
044 }
045
046 /**
047 * @param level
048 * nesting level, i.e., 0 returns the direct predecessor
049 * @return container of current entitity, i.e., predecessor during traversal
050 */
051 public Object predecessor(int level)
052 {
053 int size = stack.size();
054 if ((size < 2) || (level < 0))
055 {
056 return null;
057 }
058 else
059 {
060 return stack.elementAt(size - (level + 2)); // size - 1 == current
061 }
062 }
063
064 /**
065 * @return current object
066 */
067 public Object current()
068 {
069 return stack.peek();
070 }
071
072 /**
073 * @param clazz
074 * Class to traverse
075 * @param visitor
076 * visitor object to apply to all components
077 */
078 public DescendingVisitor(JavaClass clazz, Visitor visitor)
079 {
080 this.clazz = clazz;
081 this.visitor = visitor;
082 }
083
084 /**
085 * Start traversal.
086 */
087 public void visit()
088 {
089 clazz.accept(this);
090 }
091
092 public void visitJavaClass(JavaClass _clazz)
093 {
094 stack.push(_clazz);
095 _clazz.accept(visitor);
096 Field[] fields = _clazz.getFields();
097 for (int i = 0; i < fields.length; i++)
098 {
099 fields[i].accept(this);
100 }
101 Method[] methods = _clazz.getMethods();
102 for (int i = 0; i < methods.length; i++)
103 {
104 methods[i].accept(this);
105 }
106 Attribute[] attributes = _clazz.getAttributes();
107 for (int i = 0; i < attributes.length; i++)
108 {
109 attributes[i].accept(this);
110 }
111 _clazz.getConstantPool().accept(this);
112 stack.pop();
113 }
114
115 public void visitAnnotation(Annotations annotation)
116 {
117 stack.push(annotation);
118 annotation.accept(visitor);
119 AnnotationEntry[] entries = annotation.getAnnotationEntries();
120 for (int i = 0; i < entries.length; i++)
121 {
122 entries[i].accept(this);
123 }
124 stack.pop();
125 }
126
127 public void visitAnnotationEntry(AnnotationEntry annotationEntry)
128 {
129 stack.push(annotationEntry);
130 annotationEntry.accept(visitor);
131 stack.pop();
132 }
133
134 public void visitField(Field field)
135 {
136 stack.push(field);
137 field.accept(visitor);
138 Attribute[] attributes = field.getAttributes();
139 for (int i = 0; i < attributes.length; i++)
140 {
141 attributes[i].accept(this);
142 }
143 stack.pop();
144 }
145
146 public void visitConstantValue(ConstantValue cv)
147 {
148 stack.push(cv);
149 cv.accept(visitor);
150 stack.pop();
151 }
152
153 public void visitMethod(Method method)
154 {
155 stack.push(method);
156 method.accept(visitor);
157 Attribute[] attributes = method.getAttributes();
158 for (int i = 0; i < attributes.length; i++)
159 {
160 attributes[i].accept(this);
161 }
162 stack.pop();
163 }
164
165 public void visitExceptionTable(ExceptionTable table)
166 {
167 stack.push(table);
168 table.accept(visitor);
169 stack.pop();
170 }
171
172 public void visitCode(Code code)
173 {
174 stack.push(code);
175 code.accept(visitor);
176 CodeException[] table = code.getExceptionTable();
177 for (int i = 0; i < table.length; i++)
178 {
179 table[i].accept(this);
180 }
181 Attribute[] attributes = code.getAttributes();
182 for (int i = 0; i < attributes.length; i++)
183 {
184 attributes[i].accept(this);
185 }
186 stack.pop();
187 }
188
189 public void visitCodeException(CodeException ce)
190 {
191 stack.push(ce);
192 ce.accept(visitor);
193 stack.pop();
194 }
195
196 public void visitLineNumberTable(LineNumberTable table)
197 {
198 stack.push(table);
199 table.accept(visitor);
200 LineNumber[] numbers = table.getLineNumberTable();
201 for (int i = 0; i < numbers.length; i++)
202 {
203 numbers[i].accept(this);
204 }
205 stack.pop();
206 }
207
208 public void visitLineNumber(LineNumber number)
209 {
210 stack.push(number);
211 number.accept(visitor);
212 stack.pop();
213 }
214
215 public void visitLocalVariableTable(LocalVariableTable table)
216 {
217 stack.push(table);
218 table.accept(visitor);
219 LocalVariable[] vars = table.getLocalVariableTable();
220 for (int i = 0; i < vars.length; i++)
221 {
222 vars[i].accept(this);
223 }
224 stack.pop();
225 }
226
227 public void visitStackMap(StackMap table)
228 {
229 stack.push(table);
230 table.accept(visitor);
231 StackMapEntry[] vars = table.getStackMap();
232 for (int i = 0; i < vars.length; i++)
233 {
234 vars[i].accept(this);
235 }
236 stack.pop();
237 }
238
239 public void visitStackMapEntry(StackMapEntry var)
240 {
241 stack.push(var);
242 var.accept(visitor);
243 stack.pop();
244 }
245
246 public void visitStackMapTable(StackMapTable table)
247 {
248 stack.push(table);
249 table.accept(visitor);
250 StackMapTableEntry[] vars = table.getStackMapTable();
251 for (int i = 0; i < vars.length; i++)
252 {
253 vars[i].accept(this);
254 }
255 stack.pop();
256 }
257
258 public void visitStackMapTableEntry(StackMapTableEntry var)
259 {
260 stack.push(var);
261 var.accept(visitor);
262 stack.pop();
263 }
264
265 public void visitLocalVariable(LocalVariable var)
266 {
267 stack.push(var);
268 var.accept(visitor);
269 stack.pop();
270 }
271
272 public void visitConstantPool(ConstantPool cp)
273 {
274 stack.push(cp);
275 cp.accept(visitor);
276 Constant[] constants = cp.getConstantPool();
277 for (int i = 1; i < constants.length; i++)
278 {
279 if (constants[i] != null)
280 {
281 constants[i].accept(this);
282 }
283 }
284 stack.pop();
285 }
286
287 public void visitConstantClass(ConstantClass constant)
288 {
289 stack.push(constant);
290 constant.accept(visitor);
291 stack.pop();
292 }
293
294 public void visitConstantDouble(ConstantDouble constant)
295 {
296 stack.push(constant);
297 constant.accept(visitor);
298 stack.pop();
299 }
300
301 public void visitConstantFieldref(ConstantFieldref constant)
302 {
303 stack.push(constant);
304 constant.accept(visitor);
305 stack.pop();
306 }
307
308 public void visitConstantFloat(ConstantFloat constant)
309 {
310 stack.push(constant);
311 constant.accept(visitor);
312 stack.pop();
313 }
314
315 public void visitConstantInteger(ConstantInteger constant)
316 {
317 stack.push(constant);
318 constant.accept(visitor);
319 stack.pop();
320 }
321
322 public void visitConstantInterfaceMethodref(
323 ConstantInterfaceMethodref constant)
324 {
325 stack.push(constant);
326 constant.accept(visitor);
327 stack.pop();
328 }
329
330 public void visitConstantLong(ConstantLong constant)
331 {
332 stack.push(constant);
333 constant.accept(visitor);
334 stack.pop();
335 }
336
337 public void visitConstantMethodref(ConstantMethodref constant)
338 {
339 stack.push(constant);
340 constant.accept(visitor);
341 stack.pop();
342 }
343
344 public void visitConstantNameAndType(ConstantNameAndType constant)
345 {
346 stack.push(constant);
347 constant.accept(visitor);
348 stack.pop();
349 }
350
351 public void visitConstantString(ConstantString constant)
352 {
353 stack.push(constant);
354 constant.accept(visitor);
355 stack.pop();
356 }
357
358 public void visitConstantUtf8(ConstantUtf8 constant)
359 {
360 stack.push(constant);
361 constant.accept(visitor);
362 stack.pop();
363 }
364
365 public void visitInnerClasses(InnerClasses ic)
366 {
367 stack.push(ic);
368 ic.accept(visitor);
369 InnerClass[] ics = ic.getInnerClasses();
370 for (int i = 0; i < ics.length; i++)
371 {
372 ics[i].accept(this);
373 }
374 stack.pop();
375 }
376
377 public void visitInnerClass(InnerClass inner)
378 {
379 stack.push(inner);
380 inner.accept(visitor);
381 stack.pop();
382 }
383
384 public void visitDeprecated(Deprecated attribute)
385 {
386 stack.push(attribute);
387 attribute.accept(visitor);
388 stack.pop();
389 }
390
391 public void visitSignature(Signature attribute)
392 {
393 stack.push(attribute);
394 attribute.accept(visitor);
395 stack.pop();
396 }
397
398 public void visitSourceFile(SourceFile attribute)
399 {
400 stack.push(attribute);
401 attribute.accept(visitor);
402 stack.pop();
403 }
404
405 public void visitSynthetic(Synthetic attribute)
406 {
407 stack.push(attribute);
408 attribute.accept(visitor);
409 stack.pop();
410 }
411
412 public void visitUnknown(Unknown attribute)
413 {
414 stack.push(attribute);
415 attribute.accept(visitor);
416 stack.pop();
417 }
418
419 public void visitAnnotationDefault(AnnotationDefault obj)
420 {
421 stack.push(obj);
422 obj.accept(visitor);
423 stack.pop();
424 }
425
426 public void visitEnclosingMethod(EnclosingMethod obj)
427 {
428 stack.push(obj);
429 obj.accept(visitor);
430 stack.pop();
431 }
432
433 public void visitLocalVariableTypeTable(LocalVariableTypeTable obj)
434 {
435 stack.push(obj);
436 obj.accept(visitor);
437 stack.pop();
438 }
439
440 public void visitParameterAnnotation(ParameterAnnotations obj)
441 {
442 stack.push(obj);
443 obj.accept(visitor);
444 stack.pop();
445 }
446 }