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 14-May-2004 010 */ 011 package com.thoughtworks.proxy.toys.hotswap; 012 013 import static com.thoughtworks.proxy.toys.delegate.DelegationMode.DIRECT; 014 import static com.thoughtworks.proxy.toys.delegate.DelegationMode.SIGNATURE; 015 016 import com.thoughtworks.proxy.ProxyFactory; 017 import com.thoughtworks.proxy.factory.StandardProxyFactory; 018 import com.thoughtworks.proxy.kit.ObjectReference; 019 import com.thoughtworks.proxy.kit.ReflectionUtils; 020 import com.thoughtworks.proxy.kit.SimpleReference; 021 import com.thoughtworks.proxy.toys.delegate.DelegationMode; 022 023 024 /** 025 * Factory for proxy instances that allow to exchange the delegated instance. Every created proxy will implement 026 * {@link Swappable}, that is used for the hot swap operation. 027 * 028 * @author Dan North 029 * @author Aslak Hellesøy 030 * @author Jörg Schaible 031 * @author Conrad Benham 032 * @author Paul Hammant 033 * @see com.thoughtworks.proxy.toys.hotswap 034 * @since 0.1 035 */ 036 public class HotSwapping<T> { 037 038 private Object instance; 039 private Class<?>[] types; 040 private DelegationMode delegationMode; 041 042 private HotSwapping(final Class<T> primaryType, Class<?>... types) { 043 this.types = ReflectionUtils.makeTypesArray(primaryType, types); 044 } 045 046 /** 047 * Creates a factory for proxy instances that allow the exchange of delegated instances. 048 * 049 * @param type the type of the proxy when it is finally created. 050 * @return a factory that will proxy instances of the supplied type. 051 * @since 1.0 052 */ 053 public static <T> HotSwappingWith<T> proxy(final Class<T> type) { 054 return new HotSwappingWith<T>(new HotSwapping<T>(type)); 055 } 056 057 /** 058 * Creates a factory for proxy instances that allow the exchange of delegated instances. 059 * 060 * @param primaryType the primary type implemented by the proxy 061 * @param types other types that are implemented by the proxy 062 * @return a factory that will proxy instances of the supplied type. 063 * @since 1.0 064 */ 065 public static <T> HotSwappingWith<T> proxy(final Class<T> primaryType, final Class<?> ... types) { 066 return new HotSwappingWith<T>(new HotSwapping<T>(primaryType, types)); 067 } 068 069 /** 070 * Create a proxy with hot swapping capabilities for specific types of the delegate given with an 071 * {@link ObjectReference}. The delegate must implement the given types, if the invoker is in static typing mode, 072 * otherwise it must only have signature compatible methods. Proxies created by this method will implement 073 * {@link Swappable} 074 * 075 * @param factory the {@link ProxyFactory} to use. 076 * @return the created proxy implementing the <tt>types</tt> and {@link Swappable} 077 * @since 1.0 078 */ 079 private T build(final ProxyFactory factory) { 080 final ObjectReference<Object> delegateReference = new SimpleReference<Object>(instance); 081 return new HotSwappingInvoker<T>(types, factory, delegateReference, delegationMode).proxy(); 082 } 083 084 public static class HotSwappingWith<T> { 085 private final HotSwapping<T> hotswapping; 086 087 public HotSwappingWith(HotSwapping<T> hotswapping) { 088 this.hotswapping = hotswapping; 089 } 090 091 /** 092 * Defines the object that shall be proxied. This delegate must implement the types used to create the hot swap or 093 * have signature compatible methods. 094 * 095 * @param instance the object that shall be proxied. 096 * @return the factory that will proxy instances of the supplied type. 097 * @since 1.0 098 */ 099 public HotSwappingBuildOrMode<T> with(final Object instance) { 100 hotswapping.instance = instance; 101 hotswapping.delegationMode = DIRECT; 102 for (Class<?> type : hotswapping.types) { 103 if (!type.isInstance(instance)) { 104 hotswapping.delegationMode = SIGNATURE; 105 break; 106 } 107 } 108 return new HotSwappingBuildOrMode<T>(hotswapping); 109 } 110 } 111 112 public static class HotSwappingBuildOrMode<T> extends HotSwappingBuild<T>{ 113 public HotSwappingBuildOrMode(HotSwapping<T> hotswapping) { 114 super(hotswapping); 115 } 116 117 /** 118 * Forces a particular delegation mode to be used. 119 * 120 * @param delegationMode refer to {@link DelegationMode#DIRECT} or 121 * {@link DelegationMode#SIGNATURE} for allowed 122 * values. 123 * @return the factory that will proxy instances of the supplied type. 124 * @since 1.0 125 */ 126 public HotSwappingBuild<T> mode(DelegationMode delegationMode) { 127 hotswapping.delegationMode = delegationMode; 128 return new HotSwappingBuild<T>(hotswapping); 129 } 130 } 131 132 public static class HotSwappingBuild<T> { 133 protected final HotSwapping<T> hotswapping; 134 135 public HotSwappingBuild(HotSwapping<T> hotswapping) { 136 this.hotswapping = hotswapping; 137 } 138 139 /** 140 * Create a proxy with hot swapping capabilities for specific types of the delegate given with an 141 * {@link ObjectReference}. The delegate must implement the given types, if the invoker is in static typing mode, 142 * otherwise it must only have signature compatible methods. Proxies created by this method will implement 143 * {@link Swappable} 144 * 145 * @return the created proxy implementing the <tt>types</tt> and {@link Swappable} 146 * @see com.thoughtworks.proxy.toys.hotswap 147 * @since 1.0 148 */ 149 public T build() { 150 return build(new StandardProxyFactory()); 151 } 152 153 /** 154 * Create a proxy with hot swapping capabilities for specific types of the delegate given with an 155 * {@link ObjectReference}. The delegate must implement the given types, if the invoker is in static typing mode, 156 * otherwise it must only have signature compatible methods. Proxies created by this method will implement 157 * {@link Swappable} 158 * 159 * @param factory the {@link ProxyFactory} to use. 160 * @return the created proxy implementing the <tt>types</tt> and {@link Swappable} 161 * @see com.thoughtworks.proxy.toys.hotswap 162 * @since 1.0 163 */ 164 public T build(final ProxyFactory factory) { 165 return hotswapping.build(factory); 166 } 167 } 168 }