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 03-May-2004 010 */ 011 package com.thoughtworks.proxy.toys.decorate; 012 013 import com.thoughtworks.proxy.ProxyFactory; 014 import com.thoughtworks.proxy.factory.StandardProxyFactory; 015 import com.thoughtworks.proxy.kit.ReflectionUtils; 016 017 018 /** 019 * Toy factory to create proxies decorating an object in an AOP style. 020 * <p> 021 * An InvocationDecorator is used for the additional functionality. It is called before the original method is called, 022 * after the original method was called, after the original method has thrown an exception or when an exception occurs, 023 * calling the method of the decorated object. 024 * </p> 025 * 026 * @author Dan North 027 * @author Aslak Hellesøy 028 * @author Jörg Schaible 029 * @author Jian Li 030 * @author Paul Hammant 031 * @see com.thoughtworks.proxy.toys.decorate 032 * @since 0.1 033 */ 034 public class Decorating<U, T> { 035 036 private U delegate; 037 private Class<?>[] types; 038 private Decorator<T> decorator; 039 040 private Decorating(final U delegate, final Class<T>primaryType, final Class<?>... types) { 041 this.delegate = delegate; 042 this.types = ReflectionUtils.makeTypesArray(primaryType, types); 043 } 044 045 /** 046 * Creates a factory for proxy instances that allow decoration. 047 * 048 * @return a factory that will proxy instances of the supplied type. 049 * @since 1.0 050 */ 051 public static <T> DecoratingWith<T> proxy(final Class<T> type) { 052 return new DecoratingWith<T>(new Decorating<T, T>((T)null, type)); 053 } 054 055 /** 056 * Creates a factory for proxy instances that allow decoration. 057 * 058 * @param primaryType the primary type implemented by the proxy 059 * @param types other types that are implemented by the proxy 060 * @return a factory that will proxy instances of the supplied type. 061 * @since 1.0 062 */ 063 public static <T> DecoratingWith<T> proxy(final Class<T> primaryType, final Class<?> ... types) { 064 return new DecoratingWith<T>(new Decorating<T, T>((T)null, primaryType, types)); 065 } 066 067 /** 068 * Creates a factory for proxy instances that allow decoration. 069 * 070 * @param delegate the delegate 071 * @return a factory that will proxy instances of the supplied type. 072 * @since 1.0 073 */ 074 public static <U> DecoratingVisitor<U, U> proxy(final U delegate) { 075 @SuppressWarnings("unchecked") 076 final Class<U> type = (Class<U>)delegate.getClass(); 077 return new DecoratingVisitor<U, U>(new Decorating<U, U>(delegate, type)); 078 } 079 080 /** 081 * Creates a factory for proxy instances that allow decoration. 082 * 083 * @param delegate the delegate 084 * @param type the type of the proxy when it is finally created. 085 * @return a factory that will proxy instances of the supplied type. 086 * @since 1.0 087 */ 088 public static <U, T> DecoratingVisitor<U, T> proxy(final U delegate, final Class<T> type) { 089 return new DecoratingVisitor<U, T>(new Decorating<U, T>(delegate, type)); 090 } 091 092 /** 093 * Creates a factory for proxy instances that allow decoration. 094 * 095 * @param delegate the delegate 096 * @param primaryType the primary type implemented by the proxy 097 * @param types other types that are implemented by the proxy 098 * @return a factory that will proxy instances of the supplied type. 099 * @since 1.0 100 */ 101 public static <U, T> DecoratingVisitor<U, T> proxy(final U delegate, final Class<T> primaryType, final Class<?> ... types) { 102 return new DecoratingVisitor<U, T>(new Decorating<U, T>(delegate, primaryType, types)); 103 } 104 105 public static class DecoratingWith<T> { 106 private Decorating<T, T> decorating; 107 108 private DecoratingWith(Decorating<T, T> decorating) { 109 this.decorating = decorating; 110 } 111 112 /** 113 * specify the delegate 114 * 115 * @param delegate the delegate 116 * @return the factory that will proxy instances of the supplied type. 117 * @since 1.0 118 */ 119 public DecoratingVisitor<T, T> with(T delegate) { 120 decorating.delegate = delegate; 121 return new DecoratingVisitor<T, T>(decorating); 122 } 123 } 124 125 public static class DecoratingVisitor<U, T> { 126 private Decorating<U, T> decorating; 127 128 private DecoratingVisitor(Decorating<U, T> decorating) { 129 this.decorating = decorating; 130 } 131 132 /** 133 * specify the visited decorator 134 * 135 * @param decorator the decorator 136 * @return the factory that will proxy instances of the supplied type. 137 * @since 1.0 138 */ 139 public DecoratingBuild<U, T> visiting(Decorator<T> decorator) { 140 decorating.decorator = decorator; 141 return new DecoratingBuild<U, T>(decorating); 142 } 143 } 144 145 public static class DecoratingBuild<U, T> { 146 private Decorating<U, T> decorating; 147 148 private DecoratingBuild(Decorating<U, T> decorating) { 149 this.decorating = decorating; 150 } 151 152 /** 153 * Creating a decorating proxy for an object using the {@link StandardProxyFactory}. 154 * 155 * @return the created proxy implementing the <tt>type</tt> 156 * @since 1.0 157 */ 158 public T build() { 159 return build(new StandardProxyFactory()); 160 } 161 162 /** 163 * Creating a decorating proxy for an object using a special {@link ProxyFactory}. 164 * 165 * @param proxyFactory the {@link ProxyFactory} to use. 166 * @return the created proxy implementing the <tt>type</tt> 167 * @since 1.0 168 */ 169 public T build(final ProxyFactory proxyFactory) { 170 DecoratingInvoker<T> invoker = new DecoratingInvoker<T>(decorating.delegate, decorating.decorator); 171 return proxyFactory.<T>createProxy(invoker, decorating.types); 172 } 173 } 174 }