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.ConnectException;
33 import java.net.UnknownHostException;
34 import java.util.Arrays;
35 import java.util.Collection;
36 import java.util.HashSet;
37 import java.util.Set;
38
39 import javax.net.ssl.SSLException;
40
41 import org.apache.http.HttpEntityEnclosingRequest;
42 import org.apache.http.HttpRequest;
43 import org.apache.http.annotation.Immutable;
44 import org.apache.http.client.HttpRequestRetryHandler;
45 import org.apache.http.client.methods.HttpUriRequest;
46 import org.apache.http.client.protocol.HttpClientContext;
47 import org.apache.http.protocol.HttpContext;
48 import org.apache.http.util.Args;
49
50
51
52
53
54
55 @Immutable
56 public class DefaultHttpRequestRetryHandler implements HttpRequestRetryHandler {
57
58 public static final DefaultHttpRequestRetryHandler INSTANCE = new DefaultHttpRequestRetryHandler();
59
60
61 private final int retryCount;
62
63
64 private final boolean requestSentRetryEnabled;
65
66 private final Set<Class<? extends IOException>> nonRetriableClasses;
67
68
69
70
71 protected DefaultHttpRequestRetryHandler(
72 final int retryCount,
73 final boolean requestSentRetryEnabled,
74 final Collection<Class<? extends IOException>> clazzes) {
75 super();
76 this.retryCount = retryCount;
77 this.requestSentRetryEnabled = requestSentRetryEnabled;
78 this.nonRetriableClasses = new HashSet<Class<? extends IOException>>();
79 for (final Class<? extends IOException> clazz: clazzes) {
80 this.nonRetriableClasses.add(clazz);
81 }
82 }
83
84
85
86
87 @SuppressWarnings("unchecked")
88 public DefaultHttpRequestRetryHandler(final int retryCount, final boolean requestSentRetryEnabled) {
89 this(retryCount, requestSentRetryEnabled, Arrays.asList(
90 InterruptedIOException.class,
91 UnknownHostException.class,
92 ConnectException.class,
93 SSLException.class));
94 }
95
96
97
98
99 public DefaultHttpRequestRetryHandler() {
100 this(3, false);
101 }
102
103
104
105
106 public boolean retryRequest(
107 final IOException exception,
108 final int executionCount,
109 final HttpContext context) {
110 Args.notNull(exception, "Exception parameter");
111 Args.notNull(context, "HTTP context");
112 if (executionCount > this.retryCount) {
113
114 return false;
115 }
116 if (this.nonRetriableClasses.contains(exception.getClass())) {
117 return false;
118 } else {
119 for (final Class<? extends IOException> rejectException : this.nonRetriableClasses) {
120 if (rejectException.isInstance(exception)) {
121 return false;
122 }
123 }
124 }
125 final HttpClientContext clientContext = HttpClientContext.adapt(context);
126 final HttpRequest request = clientContext.getRequest();
127
128 if(requestIsAborted(request)){
129 return false;
130 }
131
132 if (handleAsIdempotent(request)) {
133
134 return true;
135 }
136
137 if (!clientContext.isRequestSent() || this.requestSentRetryEnabled) {
138
139
140 return true;
141 }
142
143 return false;
144 }
145
146
147
148
149
150 public boolean isRequestSentRetryEnabled() {
151 return requestSentRetryEnabled;
152 }
153
154
155
156
157 public int getRetryCount() {
158 return retryCount;
159 }
160
161
162
163
164 protected boolean handleAsIdempotent(final HttpRequest request) {
165 return !(request instanceof HttpEntityEnclosingRequest);
166 }
167
168
169
170
171
172
173 @Deprecated
174 protected boolean requestIsAborted(final HttpRequest request) {
175 HttpRequest req = request;
176 if (request instanceof RequestWrapper) {
177 req = ((RequestWrapper) request).getOriginal();
178 }
179 return (req instanceof HttpUriRequest && ((HttpUriRequest)req).isAborted());
180 }
181
182 }