1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.rest.client;
21
22 import java.io.IOException;
23 import java.util.Collections;
24 import java.util.Map;
25 import java.util.concurrent.ConcurrentHashMap;
26
27 import org.apache.commons.httpclient.Header;
28 import org.apache.commons.httpclient.HttpClient;
29 import org.apache.commons.httpclient.HttpMethod;
30 import org.apache.commons.httpclient.HttpVersion;
31 import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
32 import org.apache.commons.httpclient.URI;
33 import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
34 import org.apache.commons.httpclient.methods.DeleteMethod;
35 import org.apache.commons.httpclient.methods.GetMethod;
36 import org.apache.commons.httpclient.methods.HeadMethod;
37 import org.apache.commons.httpclient.methods.PostMethod;
38 import org.apache.commons.httpclient.methods.PutMethod;
39 import org.apache.commons.httpclient.params.HttpClientParams;
40 import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.apache.hadoop.classification.InterfaceAudience;
44 import org.apache.hadoop.classification.InterfaceStability;
45
46
47
48
49
50 @InterfaceAudience.Public
51 @InterfaceStability.Stable
52 public class Client {
53 public static final Header[] EMPTY_HEADER_ARRAY = new Header[0];
54
55 private static final Log LOG = LogFactory.getLog(Client.class);
56
57 private HttpClient httpClient;
58 private Cluster cluster;
59
60 private Map<String, String> extraHeaders;
61
62
63
64
65 public Client() {
66 this(null);
67 }
68
69
70
71
72
73 public Client(Cluster cluster) {
74 this.cluster = cluster;
75 MultiThreadedHttpConnectionManager manager =
76 new MultiThreadedHttpConnectionManager();
77 HttpConnectionManagerParams managerParams = manager.getParams();
78 managerParams.setConnectionTimeout(2000);
79 managerParams.setDefaultMaxConnectionsPerHost(10);
80 managerParams.setMaxTotalConnections(100);
81 extraHeaders = new ConcurrentHashMap<String, String>();
82 this.httpClient = new HttpClient(manager);
83 HttpClientParams clientParams = httpClient.getParams();
84 clientParams.setVersion(HttpVersion.HTTP_1_1);
85 }
86
87
88
89
90 public void shutdown() {
91 MultiThreadedHttpConnectionManager manager =
92 (MultiThreadedHttpConnectionManager) httpClient.getHttpConnectionManager();
93 manager.shutdown();
94 }
95
96
97
98
99 public HttpClient getHttpClient() {
100 return httpClient;
101 }
102
103
104
105
106
107
108 public void addExtraHeader(final String name, final String value) {
109 extraHeaders.put(name, value);
110 }
111
112
113
114
115 public String getExtraHeader(final String name) {
116 return extraHeaders.get(name);
117 }
118
119
120
121
122 public Map<String, String> getExtraHeaders() {
123 return Collections.unmodifiableMap(extraHeaders);
124 }
125
126
127
128
129 public void removeExtraHeader(final String name) {
130 extraHeaders.remove(name);
131 }
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146 public int executePathOnly(Cluster cluster, HttpMethod method,
147 Header[] headers, String path) throws IOException {
148 IOException lastException;
149 if (cluster.nodes.size() < 1) {
150 throw new IOException("Cluster is empty");
151 }
152 int start = (int)Math.round((cluster.nodes.size() - 1) * Math.random());
153 int i = start;
154 do {
155 cluster.lastHost = cluster.nodes.get(i);
156 try {
157 StringBuilder sb = new StringBuilder();
158 sb.append("http://");
159 sb.append(cluster.lastHost);
160 sb.append(path);
161 URI uri = new URI(sb.toString(), true);
162 return executeURI(method, headers, uri.toString());
163 } catch (IOException e) {
164 lastException = e;
165 }
166 } while (++i != start && i < cluster.nodes.size());
167 throw lastException;
168 }
169
170
171
172
173
174
175
176
177
178 public int executeURI(HttpMethod method, Header[] headers, String uri)
179 throws IOException {
180 method.setURI(new URI(uri, true));
181 for (Map.Entry<String, String> e: extraHeaders.entrySet()) {
182 method.addRequestHeader(e.getKey(), e.getValue());
183 }
184 if (headers != null) {
185 for (Header header: headers) {
186 method.addRequestHeader(header);
187 }
188 }
189 long startTime = System.currentTimeMillis();
190 int code = httpClient.executeMethod(method);
191 long endTime = System.currentTimeMillis();
192 if (LOG.isDebugEnabled()) {
193 LOG.debug(method.getName() + " " + uri + " " + code + " " +
194 method.getStatusText() + " in " + (endTime - startTime) + " ms");
195 }
196 return code;
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210 public int execute(Cluster cluster, HttpMethod method, Header[] headers,
211 String path) throws IOException {
212 if (path.startsWith("/")) {
213 return executePathOnly(cluster, method, headers, path);
214 }
215 return executeURI(method, headers, path);
216 }
217
218
219
220
221 public Cluster getCluster() {
222 return cluster;
223 }
224
225
226
227
228 public void setCluster(Cluster cluster) {
229 this.cluster = cluster;
230 }
231
232
233
234
235
236
237
238 public Response head(String path) throws IOException {
239 return head(cluster, path, null);
240 }
241
242
243
244
245
246
247
248
249
250 public Response head(Cluster cluster, String path, Header[] headers)
251 throws IOException {
252 HeadMethod method = new HeadMethod();
253 try {
254 int code = execute(cluster, method, null, path);
255 headers = method.getResponseHeaders();
256 return new Response(code, headers, null);
257 } finally {
258 method.releaseConnection();
259 }
260 }
261
262
263
264
265
266
267
268 public Response get(String path) throws IOException {
269 return get(cluster, path);
270 }
271
272
273
274
275
276
277
278
279 public Response get(Cluster cluster, String path) throws IOException {
280 return get(cluster, path, EMPTY_HEADER_ARRAY);
281 }
282
283
284
285
286
287
288
289
290 public Response get(String path, String accept) throws IOException {
291 return get(cluster, path, accept);
292 }
293
294
295
296
297
298
299
300
301
302 public Response get(Cluster cluster, String path, String accept)
303 throws IOException {
304 Header[] headers = new Header[1];
305 headers[0] = new Header("Accept", accept);
306 return get(cluster, path, headers);
307 }
308
309
310
311
312
313
314
315
316
317 public Response get(String path, Header[] headers) throws IOException {
318 return get(cluster, path, headers);
319 }
320
321
322
323
324
325
326
327
328
329 public Response get(Cluster c, String path, Header[] headers)
330 throws IOException {
331 GetMethod method = new GetMethod();
332 try {
333 int code = execute(c, method, headers, path);
334 headers = method.getResponseHeaders();
335 byte[] body = method.getResponseBody();
336 return new Response(code, headers, body);
337 } finally {
338 method.releaseConnection();
339 }
340 }
341
342
343
344
345
346
347
348
349
350 public Response put(String path, String contentType, byte[] content)
351 throws IOException {
352 return put(cluster, path, contentType, content);
353 }
354
355
356
357
358
359
360
361
362
363
364 public Response put(Cluster cluster, String path, String contentType,
365 byte[] content) throws IOException {
366 Header[] headers = new Header[1];
367 headers[0] = new Header("Content-Type", contentType);
368 return put(cluster, path, headers, content);
369 }
370
371
372
373
374
375
376
377
378
379
380 public Response put(String path, Header[] headers, byte[] content)
381 throws IOException {
382 return put(cluster, path, headers, content);
383 }
384
385
386
387
388
389
390
391
392
393
394
395 public Response put(Cluster cluster, String path, Header[] headers,
396 byte[] content) throws IOException {
397 PutMethod method = new PutMethod();
398 try {
399 method.setRequestEntity(new ByteArrayRequestEntity(content));
400 int code = execute(cluster, method, headers, path);
401 headers = method.getResponseHeaders();
402 content = method.getResponseBody();
403 return new Response(code, headers, content);
404 } finally {
405 method.releaseConnection();
406 }
407 }
408
409
410
411
412
413
414
415
416
417 public Response post(String path, String contentType, byte[] content)
418 throws IOException {
419 return post(cluster, path, contentType, content);
420 }
421
422
423
424
425
426
427
428
429
430
431 public Response post(Cluster cluster, String path, String contentType,
432 byte[] content) throws IOException {
433 Header[] headers = new Header[1];
434 headers[0] = new Header("Content-Type", contentType);
435 return post(cluster, path, headers, content);
436 }
437
438
439
440
441
442
443
444
445
446
447 public Response post(String path, Header[] headers, byte[] content)
448 throws IOException {
449 return post(cluster, path, headers, content);
450 }
451
452
453
454
455
456
457
458
459
460
461
462 public Response post(Cluster cluster, String path, Header[] headers,
463 byte[] content) throws IOException {
464 PostMethod method = new PostMethod();
465 try {
466 method.setRequestEntity(new ByteArrayRequestEntity(content));
467 int code = execute(cluster, method, headers, path);
468 headers = method.getResponseHeaders();
469 content = method.getResponseBody();
470 return new Response(code, headers, content);
471 } finally {
472 method.releaseConnection();
473 }
474 }
475
476
477
478
479
480
481
482 public Response delete(String path) throws IOException {
483 return delete(cluster, path);
484 }
485
486
487
488
489
490
491
492
493 public Response delete(Cluster cluster, String path) throws IOException {
494 DeleteMethod method = new DeleteMethod();
495 try {
496 int code = execute(cluster, method, null, path);
497 Header[] headers = method.getResponseHeaders();
498 byte[] content = method.getResponseBody();
499 return new Response(code, headers, content);
500 } finally {
501 method.releaseConnection();
502 }
503 }
504 }