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 */
011package com.thoughtworks.proxy.toys.privilege;
012
013import java.lang.reflect.InvocationTargetException;
014import java.lang.reflect.Method;
015import java.security.PrivilegedActionException;
016import java.security.PrivilegedExceptionAction;
017
018import com.thoughtworks.proxy.ProxyFactory;
019import com.thoughtworks.proxy.factory.StandardProxyFactory;
020import com.thoughtworks.proxy.kit.ObjectReference;
021import com.thoughtworks.proxy.kit.SimpleReference;
022import com.thoughtworks.proxy.toys.delegate.DelegatingInvoker;
023import 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 */
034public 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}