01: /*****************************************************************************
02: * Copyright (C) PicoContainer Organization. All rights reserved. *
03: * ------------------------------------------------------------------------- *
04: * The software in this package is published under the terms of the BSD *
05: * style license a copy of which has been included with this distribution in *
06: * the LICENSE.txt file. *
07: *****************************************************************************/package org.picocontainer.visitors;
08:
09: import org.picocontainer.PicoVisitor;
10: import org.picocontainer.PicoException;
11:
12: import java.lang.reflect.InvocationTargetException;
13: import java.lang.reflect.Method;
14: import java.security.AccessController;
15: import java.security.PrivilegedAction;
16:
17: /**
18: * Abstract PicoVisitor implementation. A generic traverse method is implemented, that
19: * accepts any object with a method named "accept", that takes a
20: * {@link PicoVisitor} as argument and and invokes it. Additionally it provides the
21: * {@link #checkTraversal()} method, that throws a {@link PicoVisitorTraversalException},
22: * if currently no traversal is running.
23: *
24: * @author Jörg Schaible
25: */
26: public abstract class AbstractPicoVisitor implements PicoVisitor {
27: private boolean traversal;
28:
29: public Object traverse(final Object node) {
30: traversal = true;
31: Object retval = AccessController
32: .doPrivileged(new PrivilegedAction() {
33: public Object run() {
34: try {
35: return node.getClass().getMethod("accept",
36: PicoVisitor.class);
37: } catch (NoSuchMethodException e) {
38: return e;
39: }
40: }
41: });
42: try {
43: if (retval instanceof NoSuchMethodException) {
44: throw (NoSuchMethodException) retval;
45: }
46: Method accept = (Method) retval;
47: accept.invoke(node, this );
48: return Void.TYPE;
49: } catch (NoSuchMethodException e) {
50: } catch (IllegalAccessException e) {
51: } catch (InvocationTargetException e) {
52: Throwable cause = e.getTargetException();
53: if (cause instanceof RuntimeException) {
54: throw (RuntimeException) cause;
55: } else if (cause instanceof Error) {
56: throw (Error) cause;
57: }
58: } finally {
59: traversal = false;
60: }
61: throw new IllegalArgumentException(node.getClass().getName()
62: + " is not a valid type for traversal");
63: }
64:
65: /**
66: * Checks the traversal flag, indicating a currently running traversal of the visitor.
67: * @throws PicoVisitorTraversalException if no traversal is active.
68: */
69: protected void checkTraversal() {
70: if (!traversal) {
71: throw new PicoVisitorTraversalException(this );
72: }
73: }
74:
75: /**
76: * Exception for a PicoVisitor, that is dependent on a defined starting point of the traversal.
77: * If the traversal is not initiated with a call of {@link PicoVisitor#traverse}
78: *
79: * @author joehni
80: */
81: public static class PicoVisitorTraversalException extends
82: PicoException {
83:
84: /**
85: * Construct the PicoVisitorTraversalException.
86: *
87: * @param visitor The visitor casing the exception.
88: */
89: public PicoVisitorTraversalException(PicoVisitor visitor) {
90: super ("Traversal for PicoVisitor of type "
91: + visitor.getClass().getName()
92: + " must start with the visitor's traverse method");
93: }
94: }
95:
96: }
|