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 11-May-2004 010 */ 011 package com.thoughtworks.proxy.toys.failover; 012 013 import java.util.ArrayList; 014 import java.util.List; 015 016 import com.thoughtworks.proxy.ProxyFactory; 017 import com.thoughtworks.proxy.kit.ReflectionUtils; 018 019 /** 020 * Factory for proxy instances handling failover. Delegates to one object as long as there is no exception, fails over 021 * to the next when an exception occurs. 022 * 023 * @author Aslak Hellesøy 024 * @author Paul Hammant 025 * @see com.thoughtworks.proxy.toys.failover 026 * @since 0.1 027 */ 028 public class Failover<T> { 029 private Class<?>[] types; 030 private T[] delegates; 031 private Class<? extends Throwable> exceptionClass; 032 033 private Failover(Class<T> primaryType, Class<?>... types) { 034 this.types = ReflectionUtils.makeTypesArray(primaryType, types); 035 } 036 037 /** 038 * Creates a factory for proxy instances handling failover situations. 039 * 040 * @param type the types of the proxy 041 * @return a factory that will proxy instances of the supplied type. 042 * @since 1.0 043 */ 044 public static <T> FailoverWithOrExceptingOrBuild<T> proxy(Class<T> type) { 045 return new FailoverWithOrExceptingOrBuild<T>(new Failover<T>(type)); 046 } 047 048 /** 049 * Creates a factory for proxy instances handling failover situations. 050 * 051 * @param primaryType the primary type implemented by the proxy 052 * @param types other types that are implemented by the proxy 053 * @return a factory that will proxy instances of the supplied type. 054 * @since 1.0 055 */ 056 public static <T> FailoverWithOrExceptingOrBuild<T> proxy(final Class<T> primaryType, final Class<?> ... types) { 057 return new FailoverWithOrExceptingOrBuild<T>(new Failover<T>(primaryType, types)); 058 } 059 060 /** 061 * Creates a factory for proxy instances handling failover situations. 062 * 063 * @param delegates the array with the delegates in a failover situation 064 * @return a factory that will proxy instances of the supplied type. 065 * @since 1.0 066 */ 067 public static <T> FailoverExceptingOrBuild<T> proxy(final T... delegates) { 068 Failover<T> failover = new Failover<T>(null); 069 failover.delegates = delegates; 070 return new FailoverExceptingOrBuild<T>(failover); 071 } 072 073 public static class FailoverWithOrExceptingOrBuild<T> extends FailoverExceptingOrBuild<T> { 074 075 private FailoverWithOrExceptingOrBuild(Failover<T> failover) { 076 super(failover); 077 } 078 079 /** 080 * With these delegates. 081 * 082 * @param delegates the delegates used for failover 083 * @return a factory that will use the supplied delegates in case of a failure. 084 * @since 1.0 085 */ 086 public FailoverExceptingOrBuild<T> with(final T... delegates) { 087 failover.delegates = delegates; 088 return new FailoverExceptingOrBuild<T>(failover); 089 } 090 } 091 092 public static class FailoverExceptingOrBuild<T> extends FailoverBuild<T> { 093 094 private FailoverExceptingOrBuild(Failover<T> failover) { 095 super(failover); 096 } 097 098 /** 099 * Excepting this exception class. 100 * 101 * @param exceptionClass the type of the exceptions triggering failover 102 * @return a factory that will trigger the usage of the next delegate based on the supplied Throwable type. 103 * @since 1.0 104 */ 105 public FailoverBuild<T> excepting(Class<? extends Throwable> exceptionClass) { 106 failover.exceptionClass = exceptionClass; 107 return new FailoverBuild<T>(failover); 108 } 109 } 110 111 public static class FailoverBuild<T> { 112 protected Failover<T> failover; 113 114 private FailoverBuild(Failover<T> failover) { 115 this.failover = failover; 116 } 117 118 /** 119 * Create a proxy of a specific types with failover capability using the given objects. The provided exception type 120 * determines the type of exceptions that trigger the failover. 121 * 122 * @param proxyFactory the {@link ProxyFactory} to use 123 * @return the created proxy 124 * @since 1.0 125 */ 126 public T build(final ProxyFactory proxyFactory) { 127 return new FailoverInvoker<T>(failover.types, proxyFactory, failover.delegates, failover.exceptionClass).proxy(); 128 } 129 } 130 }