001 /*
002 * (c) 2003-2005, 2009, 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 04-May-2004
010 */
011 package com.thoughtworks.proxy.toys.decorate;
012
013 import java.lang.reflect.InvocationTargetException;
014 import java.lang.reflect.Method;
015
016 import com.thoughtworks.proxy.Invoker;
017 import com.thoughtworks.proxy.kit.PrivateInvoker;
018
019
020 /**
021 * Invoker implementation for the decorating proxy. The implementation may decorate an object or another {@link Invoker}.
022 *
023 * @author Dan North
024 * @author Aslak Hellesøy
025 * @author Jörg Schaible
026 * @since 0.1
027 */
028 public class DecoratingInvoker<T> implements Invoker {
029 private static final long serialVersionUID = 8293471912861497447L;
030 private Invoker decorated;
031 private Decorator<T> decorator;
032
033 /**
034 * Construct a DecoratingInvoker decorating another Invoker.
035 *
036 * @param decorated the decorated {@link Invoker}.
037 * @param decorator the decorating instance.
038 * @since 1.0
039 */
040 public DecoratingInvoker(final Invoker decorated, final Decorator<T> decorator) {
041 this.decorated = decorated;
042 this.decorator = decorator;
043 }
044
045 /**
046 * Construct a DecoratingInvoker decorating another object.
047 *
048 * @param delegate the decorated object.
049 * @param decorator the decorating instance.
050 * @since 1.0
051 */
052 public DecoratingInvoker(final Object delegate, final Decorator<T> decorator) {
053 this(new PrivateInvoker(delegate), decorator);
054 }
055
056 public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
057 @SuppressWarnings("unchecked")
058 final T typedProxy = (T)proxy;
059 final Object[] decoratedArgs = decorator.beforeMethodStarts(typedProxy, method, args);
060 try {
061 final Object result = decorated.invoke(proxy, method, decoratedArgs);
062 return decorator.decorateResult(typedProxy, method, decoratedArgs, result);
063 } catch (InvocationTargetException e) {
064 throw decorator.decorateTargetException(typedProxy, method, decoratedArgs, e.getTargetException());
065 } catch (Exception e) {
066 throw decorator.decorateInvocationException(typedProxy, method, decoratedArgs, e);
067 }
068 }
069 }