001 /* 002 * (c) 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 24-Feb-2005 010 */ 011 package com.thoughtworks.proxy.toys.dispatch; 012 013 import com.thoughtworks.proxy.ProxyFactory; 014 import com.thoughtworks.proxy.factory.StandardProxyFactory; 015 import com.thoughtworks.proxy.kit.ObjectReference; 016 import com.thoughtworks.proxy.kit.ReflectionUtils; 017 import com.thoughtworks.proxy.kit.SimpleReference; 018 019 /** 020 * Proxy factory for dispatching proxy instances. 021 * 022 * @author Jörg Schaible 023 * @author Juan Li 024 * @author Paul Hammant 025 * @see com.thoughtworks.proxy.toys.dispatch 026 * @since 0.2 027 */ 028 public class Dispatching<T> { 029 030 private Class<?>[] types; 031 private Object[] delegates; 032 033 private Dispatching(Class<?>[] types) { 034 this.types = types; 035 } 036 037 /** 038 * Creates a builder for proxy instances that allow delegation. 039 * 040 * @param primaryType the primary type of the proxy that will not have to be cast to 041 * @param types the other types of the proxy 042 * @return a builder that will proxy instances of the supplied type. 043 * @since 1.0 044 */ 045 public static <T> DispatchingWith<T> proxy(Class<T> primaryType, Class<?>... types) { 046 return new DispatchingWith<T>(primaryType, types); 047 } 048 049 private T build(ProxyFactory factory) { 050 @SuppressWarnings("unchecked") 051 final ObjectReference<Object>[] references = new ObjectReference[delegates.length]; 052 for (int i = 0; i < references.length; i++) { 053 references[i] = new SimpleReference<Object>(delegates[i]); 054 } 055 return factory.<T>createProxy(new DispatchingInvoker(factory, types, references), types); 056 } 057 058 public static class DispatchingWith<T> { 059 private final Dispatching<T> dispatching; 060 061 private DispatchingWith(Class<T> primaryType, Class<?>[] types) { 062 this.dispatching = new Dispatching<T>(ReflectionUtils.makeTypesArray(primaryType, types)); 063 } 064 065 /** 066 * Defines the object that shall be delegated to. This delegate must implement the types used to create the 067 * dispatching proxy or have signature compatible methods. 068 * 069 * @param delegates the objects that will receive the calls. 070 * @return the factory that will proxy instances of the supplied type. 071 * @since 1.0 072 */ 073 public DispatchingBuild<T> with(final Object... delegates) { 074 dispatching.delegates = delegates; 075 return new DispatchingBuild<T>(dispatching); 076 } 077 } 078 079 public static class DispatchingBuild<T> { 080 private final Dispatching<T> dispatching; 081 082 private DispatchingBuild(Dispatching<T> dispatching) { 083 this.dispatching = dispatching; 084 } 085 086 /** 087 * Create a dispatching proxy of given types for the given objects using the {@link StandardProxyFactory} 088 * 089 * @return the created proxy 090 * @since 1.0 091 */ 092 public T build() { 093 return build(new StandardProxyFactory()); 094 } 095 096 /** 097 * Create a dispatching proxy of given types for the given objects using a special {@link ProxyFactory}. 098 * 099 * @param factory the {@link ProxyFactory} to use 100 * @return the created proxy 101 * @since 1.0 102 */ 103 public T build(ProxyFactory factory) { 104 return dispatching.build(factory); 105 } 106 } 107 }