001 /***************************************************************************** 002 * Copyright (C) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 *****************************************************************************/ 008 package org.picocontainer.defaults; 009 010 import org.picocontainer.PicoVisitor; 011 012 import java.lang.reflect.InvocationTargetException; 013 import java.lang.reflect.Method; 014 import java.security.AccessController; 015 import java.security.PrivilegedAction; 016 017 /** 018 * Abstract PicoVisitor implementation. A generic traverse method is implemented, that 019 * accepts any object with a method named "accept", that takes a 020 * {@link PicoVisitor} as argument and and invokes it. Additionally it provides the 021 * {@link #checkTraversal()} method, that throws a {@link PicoVisitorTraversalException}, 022 * if currently no traversal is running. 023 * 024 * @author Jörg Schaible 025 * @since 1.1 026 */ 027 public abstract class AbstractPicoVisitor implements PicoVisitor { 028 private boolean traversal; 029 030 public Object traverse(final Object node) { 031 traversal = true; 032 Object retval = 033 AccessController.doPrivileged(new PrivilegedAction() { 034 public Object run() { 035 try { 036 Method method = node.getClass().getMethod("accept", new Class[]{PicoVisitor.class}); 037 return method; 038 } catch (NoSuchMethodException e) { 039 return e; 040 } 041 } 042 }); 043 try { 044 if (retval instanceof NoSuchMethodException) { 045 throw (NoSuchMethodException) retval; 046 } 047 Method accept = (Method) retval; 048 accept.invoke(node, new Object[]{this}); 049 return Void.TYPE; 050 } catch (NoSuchMethodException e) { 051 } catch (IllegalAccessException e) { 052 } catch (InvocationTargetException e) { 053 Throwable cause = e.getTargetException(); 054 if (cause instanceof RuntimeException) { 055 throw (RuntimeException)cause; 056 } else if (cause instanceof Error) { 057 throw (Error)cause; 058 } 059 } finally { 060 traversal = false; 061 } 062 throw new IllegalArgumentException(node.getClass().getName() + " is not a valid type for traversal"); 063 } 064 065 /** 066 * Checks the traversal flag, indicating a currently running traversal of the visitor. 067 * @throws PicoVisitorTraversalException if no traversal is active. 068 */ 069 protected void checkTraversal() { 070 if (!traversal) { 071 throw new PicoVisitorTraversalException(this); 072 } 073 } 074 }