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 }