1
2
3
4
5
6
7
8
9
10
11 package org.mule.providers;
12
13 import org.mule.config.ExceptionHelper;
14 import org.mule.config.i18n.CoreMessages;
15 import org.mule.umo.provider.UMOConnectable;
16 import org.mule.util.ObjectUtils;
17
18 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
19
20
21
22
23
24
25
26 public class SimpleRetryConnectionStrategy extends AbstractConnectionStrategy
27 {
28 public static final int DEFAULT_FREQUENCY = 2000;
29 public static final int DEFAULT_RETRY_COUNT = 2;
30 public static final int RETRY_COUNT_FOREVER = -1;
31
32 protected static class RetryCounter extends ThreadLocal
33 {
34 public int countRetry()
35 {
36 return ((AtomicInteger) get()).incrementAndGet();
37 }
38
39 public void reset()
40 {
41 ((AtomicInteger) get()).set(0);
42 }
43
44 public AtomicInteger current()
45 {
46 return (AtomicInteger) get();
47 }
48
49
50 protected Object initialValue()
51 {
52 return new AtomicInteger(0);
53 }
54 }
55
56 protected static final RetryCounter retryCounter = new RetryCounter();
57
58 protected static final ThreadLocal called = new ThreadLocal();
59
60 private volatile int retryCount = DEFAULT_RETRY_COUNT;
61 private volatile long frequency = DEFAULT_FREQUENCY;
62
63 protected void doConnect(UMOConnectable connectable) throws FatalConnectException
64 {
65 while (true)
66 {
67 final Boolean recursiveCallDetected = (Boolean) ObjectUtils.defaultIfNull(called.get(), Boolean.FALSE);
68 if (!recursiveCallDetected.booleanValue())
69 {
70 retryCounter.countRetry();
71 }
72 called.set(Boolean.TRUE);
73
74 try
75 {
76 connectable.connect();
77 if (logger.isDebugEnabled())
78 {
79 logger.debug("Successfully connected to " + getDescription(connectable));
80 }
81 break;
82 }
83 catch (InterruptedException ie)
84 {
85
86
87 throw new FatalConnectException(
88
89 CoreMessages.reconnectStrategyFailed(this.getClass(),
90 this.getDescription(connectable)), ie, connectable);
91 }
92 catch (Exception e)
93 {
94 if (e instanceof FatalConnectException)
95 {
96
97 throw (FatalConnectException) e;
98 }
99 if (retryCount != RETRY_COUNT_FOREVER && retryCounter.current().get() >= retryCount)
100 {
101 throw new FatalConnectException(
102
103 CoreMessages.reconnectStrategyFailed(this.getClass(),
104 this.getDescription(connectable)), e, connectable);
105 }
106
107 if (logger.isErrorEnabled())
108 {
109 StringBuffer msg = new StringBuffer(512);
110 msg.append("Failed to connect/reconnect: ").append(
111 getDescription(connectable));
112 Throwable t = ExceptionHelper.getRootException(e);
113 msg.append(". Root Exception was: ").append(ExceptionHelper.writeException(t));
114 logger.error(msg.toString(), e);
115 }
116
117 if (logger.isInfoEnabled())
118 {
119 logger.info("Waiting for " + frequency + "ms before reconnecting. Failed attempt "
120 + retryCounter.current().get() + " of " +
121 (retryCount != RETRY_COUNT_FOREVER ? String.valueOf(retryCount) : "unlimited"));
122 }
123
124 try
125 {
126 Thread.sleep(frequency);
127 }
128 catch (InterruptedException e1)
129 {
130 throw new FatalConnectException(
131
132 CoreMessages.reconnectStrategyFailed(this.getClass(),
133 this.getDescription(connectable)), e, connectable);
134 }
135 }
136 finally
137 {
138 called.set(Boolean.FALSE);
139 }
140 }
141 }
142
143
144
145
146 public synchronized void resetState()
147 {
148 retryCounter.reset();
149 }
150
151 public int getRetryCount()
152 {
153 return retryCount;
154 }
155
156
157
158
159
160 public void setRetryCount(int retryCount)
161 {
162 this.retryCount = retryCount;
163 }
164
165 public long getFrequency()
166 {
167 return frequency;
168 }
169
170 public void setFrequency(long frequency)
171 {
172 this.frequency = frequency;
173 }
174 }