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.execchain;
29
30 import java.io.IOException;
31 import java.lang.reflect.UndeclaredThrowableException;
32
33 import org.apache.http.HttpException;
34 import org.apache.http.annotation.Contract;
35 import org.apache.http.annotation.ThreadingBehavior;
36 import org.apache.http.client.BackoffManager;
37 import org.apache.http.client.ConnectionBackoffStrategy;
38 import org.apache.http.client.methods.CloseableHttpResponse;
39 import org.apache.http.client.methods.HttpExecutionAware;
40 import org.apache.http.client.methods.HttpRequestWrapper;
41 import org.apache.http.client.protocol.HttpClientContext;
42 import org.apache.http.conn.routing.HttpRoute;
43 import org.apache.http.util.Args;
44
45
46
47
48 @Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
49 public class BackoffStrategyExec implements ClientExecChain {
50
51 private final ClientExecChain requestExecutor;
52 private final ConnectionBackoffStrategy connectionBackoffStrategy;
53 private final BackoffManager backoffManager;
54
55 public BackoffStrategyExec(
56 final ClientExecChain requestExecutor,
57 final ConnectionBackoffStrategy connectionBackoffStrategy,
58 final BackoffManager backoffManager) {
59 super();
60 Args.notNull(requestExecutor, "HTTP client request executor");
61 Args.notNull(connectionBackoffStrategy, "Connection backoff strategy");
62 Args.notNull(backoffManager, "Backoff manager");
63 this.requestExecutor = requestExecutor;
64 this.connectionBackoffStrategy = connectionBackoffStrategy;
65 this.backoffManager = backoffManager;
66 }
67
68 @Override
69 public CloseableHttpResponse execute(
70 final HttpRoute route,
71 final HttpRequestWrapper request,
72 final HttpClientContext context,
73 final HttpExecutionAware execAware) throws IOException, HttpException {
74 Args.notNull(route, "HTTP route");
75 Args.notNull(request, "HTTP request");
76 Args.notNull(context, "HTTP context");
77 CloseableHttpResponse out = null;
78 try {
79 out = this.requestExecutor.execute(route, request, context, execAware);
80 } catch (final Exception ex) {
81 if (out != null) {
82 out.close();
83 }
84 if (this.connectionBackoffStrategy.shouldBackoff(ex)) {
85 this.backoffManager.backOff(route);
86 }
87 if (ex instanceof RuntimeException) {
88 throw (RuntimeException) ex;
89 }
90 if (ex instanceof HttpException) {
91 throw (HttpException) ex;
92 }
93 if (ex instanceof IOException) {
94 throw (IOException) ex;
95 }
96 throw new UndeclaredThrowableException(ex);
97 }
98 if (this.connectionBackoffStrategy.shouldBackoff(out)) {
99 this.backoffManager.backOff(route);
100 } else {
101 this.backoffManager.probe(route);
102 }
103 return out;
104 }
105
106 }