1 package com.guinetik.rr.interceptor;
2
3 import com.guinetik.rr.http.RocketClient;
4 import com.guinetik.rr.http.RocketRestException;
5 import com.guinetik.rr.request.RequestSpec;
6 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory;
8
9 import javax.net.ssl.SSLContext;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.Comparator;
13 import java.util.List;
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class InterceptingClient implements RocketClient {
51
52 private static final Logger logger = LoggerFactory.getLogger(InterceptingClient.class);
53
54 private final RocketClient delegate;
55 private final List<RequestInterceptor> interceptors;
56 private final int maxRetries;
57
58
59
60
61
62
63
64 public InterceptingClient(RocketClient delegate, List<RequestInterceptor> interceptors) {
65 this(delegate, interceptors, 3);
66 }
67
68
69
70
71
72
73
74
75 public InterceptingClient(RocketClient delegate, List<RequestInterceptor> interceptors, int maxRetries) {
76 if (delegate == null) {
77 throw new NullPointerException("delegate must not be null");
78 }
79 this.delegate = delegate;
80 this.maxRetries = maxRetries;
81
82
83 List<RequestInterceptor> sorted = new ArrayList<RequestInterceptor>(
84 interceptors != null ? interceptors : Collections.<RequestInterceptor>emptyList()
85 );
86 Collections.sort(sorted, new Comparator<RequestInterceptor>() {
87 @Override
88 public int compare(RequestInterceptor a, RequestInterceptor b) {
89 return Integer.compare(a.getOrder(), b.getOrder());
90 }
91 });
92 this.interceptors = Collections.unmodifiableList(sorted);
93 }
94
95 @Override
96 public <Req, Res> Res execute(RequestSpec<Req, Res> requestSpec) throws RocketRestException {
97 return executeWithRetry(requestSpec, 0);
98 }
99
100
101
102
103 private <Req, Res> Res executeWithRetry(RequestSpec<Req, Res> requestSpec, int retryCount)
104 throws RocketRestException {
105
106 final int currentRetry = retryCount;
107
108
109 InterceptorChain chain = new InterceptorChain() {
110 @Override
111 public <R, S> S retry(RequestSpec<R, S> request) throws RocketRestException {
112 if (currentRetry >= maxRetries) {
113 throw new RocketRestException("Maximum retry count exceeded: " + maxRetries);
114 }
115 logger.debug("Retrying request (attempt {}): {} {}",
116 currentRetry + 1, request.getMethod(), request.getEndpoint());
117 return executeWithRetry(request, currentRetry + 1);
118 }
119
120 @Override
121 public int getRetryCount() {
122 return currentRetry;
123 }
124
125 @Override
126 public int getMaxRetries() {
127 return maxRetries;
128 }
129 };
130
131
132 RequestSpec<Req, Res> currentRequest = requestSpec;
133 for (RequestInterceptor interceptor : interceptors) {
134 currentRequest = interceptor.beforeRequest(currentRequest);
135 }
136
137 try {
138
139 Res response = delegate.execute(currentRequest);
140
141
142 for (int i = interceptors.size() - 1; i >= 0; i--) {
143 response = interceptors.get(i).afterResponse(response, currentRequest);
144 }
145
146 return response;
147
148 } catch (RocketRestException e) {
149
150 for (RequestInterceptor interceptor : interceptors) {
151 try {
152 Res recovered = interceptor.onError(e, currentRequest, chain);
153
154 for (int i = interceptors.size() - 1; i >= 0; i--) {
155 recovered = interceptors.get(i).afterResponse(recovered, currentRequest);
156 }
157 return recovered;
158 } catch (RocketRestException rethrown) {
159
160 e = rethrown;
161 }
162 }
163
164 throw e;
165 }
166 }
167
168 @Override
169 public void configureSsl(SSLContext sslContext) {
170 delegate.configureSsl(sslContext);
171 }
172
173 @Override
174 public void setBaseUrl(String baseUrl) {
175 delegate.setBaseUrl(baseUrl);
176 }
177
178
179
180
181
182
183 public List<RequestInterceptor> getInterceptors() {
184 return interceptors;
185 }
186 }