1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.impl.client;
29
30 import java.io.IOException;
31 import java.io.InterruptedIOException;
32 import java.net.URI;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.http.HttpHost;
37 import org.apache.http.HttpRequest;
38 import org.apache.http.HttpResponse;
39 import org.apache.http.annotation.ThreadSafe;
40 import org.apache.http.client.HttpClient;
41 import org.apache.http.client.ResponseHandler;
42 import org.apache.http.client.ServiceUnavailableRetryStrategy;
43 import org.apache.http.client.methods.HttpUriRequest;
44 import org.apache.http.conn.ClientConnectionManager;
45 import org.apache.http.params.HttpParams;
46 import org.apache.http.protocol.HttpContext;
47 import org.apache.http.util.EntityUtils;
48
49
50
51
52
53
54
55 @ThreadSafe
56 public class AutoRetryHttpClient implements HttpClient {
57
58 private final HttpClient backend;
59
60 private final ServiceUnavailableRetryStrategy retryStrategy;
61
62 private final Log log = LogFactory.getLog(getClass());
63
64 public AutoRetryHttpClient(
65 final HttpClient client, final ServiceUnavailableRetryStrategy retryStrategy) {
66 super();
67 if (client == null) {
68 throw new IllegalArgumentException("HttpClient may not be null");
69 }
70 if (retryStrategy == null) {
71 throw new IllegalArgumentException(
72 "ServiceUnavailableRetryStrategy may not be null");
73 }
74 this.backend = client;
75 this.retryStrategy = retryStrategy;
76 }
77
78
79
80
81
82
83 public AutoRetryHttpClient() {
84 this(new DefaultHttpClient(), new DefaultServiceUnavailableRetryStrategy());
85 }
86
87
88
89
90
91
92
93
94
95 public AutoRetryHttpClient(ServiceUnavailableRetryStrategy config) {
96 this(new DefaultHttpClient(), config);
97 }
98
99
100
101
102
103
104
105
106
107 public AutoRetryHttpClient(HttpClient client) {
108 this(client, new DefaultServiceUnavailableRetryStrategy());
109 }
110
111 public HttpResponse execute(HttpHost target, HttpRequest request)
112 throws IOException {
113 HttpContext defaultContext = null;
114 return execute(target, request, defaultContext);
115 }
116
117 public <T> T execute(HttpHost target, HttpRequest request,
118 ResponseHandler<? extends T> responseHandler) throws IOException {
119 return execute(target, request, responseHandler, null);
120 }
121
122 public <T> T execute(HttpHost target, HttpRequest request,
123 ResponseHandler<? extends T> responseHandler, HttpContext context)
124 throws IOException {
125 HttpResponse resp = execute(target, request, context);
126 return responseHandler.handleResponse(resp);
127 }
128
129 public HttpResponse execute(HttpUriRequest request) throws IOException {
130 HttpContext context = null;
131 return execute(request, context);
132 }
133
134 public HttpResponse execute(HttpUriRequest request, HttpContext context)
135 throws IOException {
136 URI uri = request.getURI();
137 HttpHost httpHost = new HttpHost(uri.getHost(), uri.getPort(),
138 uri.getScheme());
139 return execute(httpHost, request, context);
140 }
141
142 public <T> T execute(HttpUriRequest request,
143 ResponseHandler<? extends T> responseHandler) throws IOException {
144 return execute(request, responseHandler, null);
145 }
146
147 public <T> T execute(HttpUriRequest request,
148 ResponseHandler<? extends T> responseHandler, HttpContext context)
149 throws IOException {
150 HttpResponse resp = execute(request, context);
151 return responseHandler.handleResponse(resp);
152 }
153
154 public HttpResponse execute(HttpHost target, HttpRequest request,
155 HttpContext context) throws IOException {
156 for (int c = 1;; c++) {
157 HttpResponse response = backend.execute(target, request, context);
158 try {
159 if (retryStrategy.retryRequest(response, c, context)) {
160 EntityUtils.consume(response.getEntity());
161 long nextInterval = retryStrategy.getRetryInterval();
162 try {
163 log.trace("Wait for " + nextInterval);
164 Thread.sleep(nextInterval);
165 } catch (InterruptedException e) {
166 Thread.currentThread().interrupt();
167 throw new InterruptedIOException();
168 }
169 } else {
170 return response;
171 }
172 } catch (RuntimeException ex) {
173 try {
174 EntityUtils.consume(response.getEntity());
175 } catch (IOException ioex) {
176 log.warn("I/O error consuming response content", ioex);
177 }
178 throw ex;
179 }
180 }
181 }
182
183 public ClientConnectionManager getConnectionManager() {
184 return backend.getConnectionManager();
185 }
186
187 public HttpParams getParams() {
188 return backend.getParams();
189 }
190
191 }