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