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-Feb-2004 010 */ 011 package com.thoughtworks.proxy.toys.delegate; 012 013 import com.thoughtworks.proxy.ProxyFactory; 014 import com.thoughtworks.proxy.factory.StandardProxyFactory; 015 import com.thoughtworks.proxy.kit.SimpleReference; 016 017 /** 018 * Toy factory to create proxies delegating to another object. 019 * <p> 020 * Such a proxy is used to mask the methods of an object, that are not part of a public interface. Or it is used to make 021 * an object compatible, e.g. when an object implements the methods of an interface, but does not implement the 022 * interface itself. 023 * </p> 024 * 025 * @author Dan North 026 * @author Jian Li 027 * @author Paul Hammant 028 * @see com.thoughtworks.proxy.toys.delegate 029 * @since 0.1 030 */ 031 public class Delegating<T> { 032 033 private Class<T> type; 034 private Object delegate; 035 private DelegationMode delegationMode = DelegationMode.SIGNATURE; 036 037 private Delegating(Class<T> type) { 038 this.type = type; 039 } 040 041 /** 042 * Creates a factory for proxy instances that allow delegation. 043 * 044 * @param type the type of the proxy when it is finally created. 045 * @return a factory that will proxy instances of the supplied type. 046 * @since 1.0 047 */ 048 public static <T> DelegatingWith<T> proxy(Class<T> type) { 049 return new DelegatingWith<T>(new Delegating<T>(type)); 050 } 051 052 public static class DelegatingWith<T> { 053 private Delegating<T> delegating; 054 055 private DelegatingWith(Delegating<T> delegating) { 056 this.delegating = delegating; 057 } 058 059 /** 060 * With this delegate 061 * 062 * @param delegate the object the proxy delegates to. 063 * @return the factory that will route calls to the supplied delegate. 064 * @since 1.0 065 */ 066 public DelegatingModeOrBuild<T> with(Object delegate) { 067 delegating.delegate = delegate; 068 return new DelegatingModeOrBuild<T>(delegating); 069 } 070 071 } 072 073 public static class DelegatingModeOrBuild<T> extends DelegatingBuild<T>{ 074 075 private DelegatingModeOrBuild(Delegating<T> delegating) { 076 super(delegating); 077 } 078 079 /** 080 * Forces a particular delegation mode to be used. 081 * 082 * @param mode refer to {@link DelegationMode#DIRECT} or 083 * {@link DelegationMode#SIGNATURE} for allowed values. 084 * @return the factory that will proxy instances of the supplied type. 085 */ 086 public DelegatingBuild<T> mode(DelegationMode mode) { 087 delegating.delegationMode = mode; 088 return new DelegatingBuild<T>(delegating); 089 } 090 091 } 092 093 public static class DelegatingBuild<T> { 094 protected Delegating<T> delegating; 095 096 private DelegatingBuild(Delegating<T> delegating) { 097 this.delegating = delegating; 098 } 099 100 /** 101 * Creating a delegating proxy for an object using the {@link StandardProxyFactory}. 102 * 103 * @return the created proxy implementing the <tt>type</tt> 104 * @since 1.0 105 */ 106 public T build() { 107 return build(new StandardProxyFactory()); 108 } 109 110 /** 111 * Creating a delegating proxy for an object using a special {@link ProxyFactory}. 112 * 113 * @param factory the {@link ProxyFactory} to use. 114 * @return the created proxy implementing the <tt>type</tt> 115 * @since 1.0 116 */ 117 public T build(ProxyFactory factory) { 118 return factory.<T>createProxy(new DelegatingInvoker<Object>(factory, 119 new SimpleReference<Object>(delegating.delegate), delegating.delegationMode), delegating.type); 120 } 121 } 122 }