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