001    /*
002     * (c) 2010 ThoughtWorks Ltd
003     * All rights reserved.
004     *
005     * The software in this package is published under the terms of the BSD
006     * style license a copy of which has been included with this distribution in
007     * the LICENSE.txt file.
008     * 
009     * Created on 19-03-2010.
010     */
011    package com.thoughtworks.proxy.toys.privilege;
012    
013    import java.lang.reflect.InvocationTargetException;
014    import java.lang.reflect.Method;
015    import java.security.PrivilegedActionException;
016    import java.security.PrivilegedExceptionAction;
017    
018    import com.thoughtworks.proxy.ProxyFactory;
019    import com.thoughtworks.proxy.factory.StandardProxyFactory;
020    import com.thoughtworks.proxy.kit.ObjectReference;
021    import com.thoughtworks.proxy.kit.SimpleReference;
022    import com.thoughtworks.proxy.toys.delegate.DelegatingInvoker;
023    import com.thoughtworks.proxy.toys.delegate.DelegationMode;
024    
025    
026    /**
027     * {@link com.thoughtworks.proxy.Invoker Invoker} that creates for the invoked method a
028     * {@link PrivilegedExceptionAction} and runs this action with the provided
029     * {@link ActionExecutor}.
030     * 
031     * @author Jörg Schaible
032     * @since 1.0
033     */
034    public class PrivilegingInvoker<T> extends DelegatingInvoker<T> {
035        private static final long serialVersionUID = 5352672950789740381L;
036        private final ActionExecutor executor;
037    
038        /**
039         * Construct the invoker.
040         * 
041         * @param proxyFactory the proxy factory used to create the proxy
042         * @param delegateReference the reference object managing the delegate for the call
043         * @param executor the executor of the {@link PrivilegedExceptionAction}
044         * @since 1.0
045         */
046        public PrivilegingInvoker(
047            ProxyFactory proxyFactory, ObjectReference<T> delegateReference, ActionExecutor executor) {
048            super(proxyFactory, delegateReference, DelegationMode.DIRECT);
049            this.executor = executor == null ? new AccessControllerExecutor() : executor;
050        }
051    
052        /**
053         * Construct the invoker.
054         * 
055         * @param delegate the delegate for the call
056         * @param executor the executor of the {@link PrivilegedExceptionAction}
057         * @since 1.0
058         */
059        public PrivilegingInvoker(T delegate, ActionExecutor executor) {
060            this(new StandardProxyFactory(), new SimpleReference<T>(delegate), executor);
061        }
062    
063        /**
064         * Construct the invoker using a {@link AccessControllerExecutor}.
065         * 
066         * @param delegate the delegate for the call
067         * @since 1.0
068         */
069        public PrivilegingInvoker(T delegate) {
070            this(delegate, null);
071        }
072    
073        @Override
074        protected Object invokeOnDelegate(final Method method, final Object[] args)
075            throws InvocationTargetException {
076            try {
077                return executor.execute(new PrivilegedExceptionAction<Object>() {
078                    public Object run() throws Exception {
079                        return PrivilegingInvoker.super.invokeOnDelegate(method, args);
080                    }
081                });
082            } catch (PrivilegedActionException e) {
083                final Throwable cause = e.getCause();
084                if (cause instanceof InvocationTargetException) {
085                    throw InvocationTargetException.class.cast(cause);
086                } else {
087                    throw new InvocationTargetException(cause);
088                }
089            }
090        }
091    }