1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.rest;
22
23 import java.io.ByteArrayInputStream;
24 import java.io.IOException;
25 import java.io.StringWriter;
26 import java.net.URLEncoder;
27
28 import javax.xml.bind.JAXBContext;
29 import javax.xml.bind.JAXBException;
30 import javax.xml.bind.Marshaller;
31 import javax.xml.bind.Unmarshaller;
32
33 import org.apache.commons.httpclient.Header;
34 import org.apache.hadoop.hbase.HColumnDescriptor;
35 import org.apache.hadoop.hbase.HConstants;
36 import org.apache.hadoop.hbase.HTableDescriptor;
37 import org.apache.hadoop.hbase.client.HBaseAdmin;
38 import org.apache.hadoop.hbase.rest.client.Client;
39 import org.apache.hadoop.hbase.rest.client.Cluster;
40 import org.apache.hadoop.hbase.rest.client.Response;
41 import org.apache.hadoop.hbase.rest.model.CellModel;
42 import org.apache.hadoop.hbase.rest.model.CellSetModel;
43 import org.apache.hadoop.hbase.rest.model.RowModel;
44 import org.apache.hadoop.hbase.util.Bytes;
45
46 public class TestRowResource extends HBaseRESTClusterTestBase {
47 static final String TABLE = "TestRowResource";
48 static final String CFA = "a";
49 static final String CFB = "b";
50 static final String COLUMN_1 = CFA + ":1";
51 static final String COLUMN_2 = CFB + ":2";
52 static final String ROW_1 = "testrow1";
53 static final String VALUE_1 = "testvalue1";
54 static final String ROW_2 = "testrow2";
55 static final String VALUE_2 = "testvalue2";
56 static final String ROW_3 = "testrow3";
57 static final String VALUE_3 = "testvalue3";
58 static final String ROW_4 = "testrow4";
59 static final String VALUE_4 = "testvalue4";
60
61 Client client;
62 JAXBContext context;
63 Marshaller marshaller;
64 Unmarshaller unmarshaller;
65 HBaseAdmin admin;
66
67 @Override
68 protected void setUp() throws Exception {
69 super.setUp();
70 context = JAXBContext.newInstance(
71 CellModel.class,
72 CellSetModel.class,
73 RowModel.class);
74 marshaller = context.createMarshaller();
75 unmarshaller = context.createUnmarshaller();
76 client = new Client(new Cluster().add("localhost", testServletPort));
77 admin = new HBaseAdmin(conf);
78 if (admin.tableExists(TABLE)) {
79 return;
80 }
81 HTableDescriptor htd = new HTableDescriptor(TABLE);
82 htd.addFamily(new HColumnDescriptor(CFA));
83 htd.addFamily(new HColumnDescriptor(CFB));
84 admin.createTable(htd);
85 }
86
87 @Override
88 protected void tearDown() throws Exception {
89 client.shutdown();
90 super.tearDown();
91 }
92
93 Response deleteRow(String table, String row) throws IOException {
94 StringBuilder path = new StringBuilder();
95 path.append('/');
96 path.append(table);
97 path.append('/');
98 path.append(row);
99 Response response = client.delete(path.toString());
100 Thread.yield();
101 return response;
102 }
103
104 Response deleteValue(String table, String row, String column)
105 throws IOException {
106 StringBuilder path = new StringBuilder();
107 path.append('/');
108 path.append(table);
109 path.append('/');
110 path.append(row);
111 path.append('/');
112 path.append(column);
113 Response response = client.delete(path.toString());
114 Thread.yield();
115 return response;
116 }
117
118 Response getValueXML(String table, String row, String column)
119 throws IOException {
120 StringBuilder path = new StringBuilder();
121 path.append('/');
122 path.append(table);
123 path.append('/');
124 path.append(row);
125 path.append('/');
126 path.append(column);
127 Response response = client.get(path.toString(), MIMETYPE_XML);
128 return response;
129 }
130
131 Response getValuePB(String table, String row, String column)
132 throws IOException {
133 StringBuilder path = new StringBuilder();
134 path.append('/');
135 path.append(table);
136 path.append('/');
137 path.append(row);
138 path.append('/');
139 path.append(column);
140 Response response = client.get(path.toString(), MIMETYPE_PROTOBUF);
141 return response;
142 }
143
144 Response putValueXML(String table, String row, String column, String value)
145 throws IOException, JAXBException {
146 StringBuilder path = new StringBuilder();
147 path.append('/');
148 path.append(table);
149 path.append('/');
150 path.append(row);
151 path.append('/');
152 path.append(column);
153 RowModel rowModel = new RowModel(row);
154 rowModel.addCell(new CellModel(Bytes.toBytes(column),
155 Bytes.toBytes(value)));
156 CellSetModel cellSetModel = new CellSetModel();
157 cellSetModel.addRow(rowModel);
158 StringWriter writer = new StringWriter();
159 marshaller.marshal(cellSetModel, writer);
160 Response response = client.put(path.toString(), MIMETYPE_XML,
161 Bytes.toBytes(writer.toString()));
162 Thread.yield();
163 return response;
164 }
165
166 void checkValueXML(String table, String row, String column, String value)
167 throws IOException, JAXBException {
168 Response response = getValueXML(table, row, column);
169 assertEquals(response.getCode(), 200);
170 CellSetModel cellSet = (CellSetModel)
171 unmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
172 RowModel rowModel = cellSet.getRows().get(0);
173 CellModel cell = rowModel.getCells().get(0);
174 assertEquals(Bytes.toString(cell.getColumn()), column);
175 assertEquals(Bytes.toString(cell.getValue()), value);
176 }
177
178 Response putValuePB(String table, String row, String column, String value)
179 throws IOException {
180 StringBuilder path = new StringBuilder();
181 path.append('/');
182 path.append(table);
183 path.append('/');
184 path.append(row);
185 path.append('/');
186 path.append(column);
187 RowModel rowModel = new RowModel(row);
188 rowModel.addCell(new CellModel(Bytes.toBytes(column),
189 Bytes.toBytes(value)));
190 CellSetModel cellSetModel = new CellSetModel();
191 cellSetModel.addRow(rowModel);
192 Response response = client.put(path.toString(), MIMETYPE_PROTOBUF,
193 cellSetModel.createProtobufOutput());
194 Thread.yield();
195 return response;
196 }
197
198 void checkValuePB(String table, String row, String column, String value)
199 throws IOException {
200 Response response = getValuePB(table, row, column);
201 assertEquals(response.getCode(), 200);
202 CellSetModel cellSet = new CellSetModel();
203 cellSet.getObjectFromMessage(response.getBody());
204 RowModel rowModel = cellSet.getRows().get(0);
205 CellModel cell = rowModel.getCells().get(0);
206 assertEquals(Bytes.toString(cell.getColumn()), column);
207 assertEquals(Bytes.toString(cell.getValue()), value);
208 }
209
210 void doTestDelete() throws IOException, JAXBException {
211 Response response;
212
213 response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
214 assertEquals(response.getCode(), 200);
215 response = putValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
216 assertEquals(response.getCode(), 200);
217 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
218 checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
219
220 response = deleteValue(TABLE, ROW_1, COLUMN_1);
221 assertEquals(response.getCode(), 200);
222 response = getValueXML(TABLE, ROW_1, COLUMN_1);
223 assertEquals(response.getCode(), 404);
224 checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
225
226 response = deleteRow(TABLE, ROW_1);
227 assertEquals(response.getCode(), 200);
228 response = getValueXML(TABLE, ROW_1, COLUMN_1);
229 assertEquals(response.getCode(), 404);
230 response = getValueXML(TABLE, ROW_1, COLUMN_2);
231 assertEquals(response.getCode(), 404);
232 }
233
234 void doTestSingleCellGetPutXML() throws IOException, JAXBException {
235 Response response = getValueXML(TABLE, ROW_1, COLUMN_1);
236 assertEquals(response.getCode(), 404);
237
238 response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
239 assertEquals(response.getCode(), 200);
240 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
241 response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
242 assertEquals(response.getCode(), 200);
243 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
244
245 response = deleteRow(TABLE, ROW_1);
246 assertEquals(response.getCode(), 200);
247 }
248
249 void doTestSingleCellGetPutPB() throws IOException, JAXBException {
250 Response response = getValuePB(TABLE, ROW_1, COLUMN_1);
251 assertEquals(response.getCode(), 404);
252
253 response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
254 assertEquals(response.getCode(), 200);
255 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
256
257 response = putValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
258 assertEquals(response.getCode(), 200);
259 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
260 response = putValueXML(TABLE, ROW_1, COLUMN_1, VALUE_2);
261 assertEquals(response.getCode(), 200);
262 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_2);
263
264 response = deleteRow(TABLE, ROW_1);
265 assertEquals(response.getCode(), 200);
266 }
267
268 void doTestSingleCellGetPutBinary() throws IOException {
269 final String path = "/" + TABLE + "/" + ROW_3 + "/" + COLUMN_1;
270 final byte[] body = Bytes.toBytes(VALUE_3);
271 Response response = client.put(path, MIMETYPE_BINARY, body);
272 assertEquals(response.getCode(), 200);
273 Thread.yield();
274
275 response = client.get(path, MIMETYPE_BINARY);
276 assertEquals(response.getCode(), 200);
277 assertTrue(Bytes.equals(response.getBody(), body));
278 boolean foundTimestampHeader = false;
279 for (Header header: response.getHeaders()) {
280 if (header.getName().equals("X-Timestamp")) {
281 foundTimestampHeader = true;
282 break;
283 }
284 }
285 assertTrue(foundTimestampHeader);
286
287 response = deleteRow(TABLE, ROW_3);
288 assertEquals(response.getCode(), 200);
289 }
290
291 void doTestSingleCellGetJSON() throws IOException, JAXBException {
292 final String path = "/" + TABLE + "/" + ROW_4 + "/" + COLUMN_1;
293 Response response = client.put(path, MIMETYPE_BINARY,
294 Bytes.toBytes(VALUE_4));
295 assertEquals(response.getCode(), 200);
296 Thread.yield();
297 response = client.get(path, MIMETYPE_JSON);
298 assertEquals(response.getCode(), 200);
299 response = deleteRow(TABLE, ROW_4);
300 assertEquals(response.getCode(), 200);
301 }
302
303 void doTestURLEncodedKey() throws IOException, JAXBException {
304 String encodedKey = URLEncoder.encode("http://www.google.com/",
305 HConstants.UTF8_ENCODING);
306 Response response;
307 response = putValueXML(TABLE, encodedKey, COLUMN_1, VALUE_1);
308 assertEquals(response.getCode(), 200);
309 response = putValuePB(TABLE, encodedKey, COLUMN_2, VALUE_2);
310 assertEquals(response.getCode(), 200);
311 checkValuePB(TABLE, encodedKey, COLUMN_1, VALUE_1);
312 checkValueXML(TABLE, encodedKey, COLUMN_2, VALUE_2);
313 }
314
315 public void testNoSuchCF() throws IOException, JAXBException {
316 final String goodPath = "/" + TABLE + "/" + ROW_1 + "/" + CFA+":";
317 final String badPath = "/" + TABLE + "/" + ROW_1 + "/" + "BAD";
318 Response response = client.post(goodPath, MIMETYPE_BINARY,
319 Bytes.toBytes(VALUE_1));
320 assertEquals(response.getCode(), 200);
321 assertEquals(client.get(goodPath, MIMETYPE_BINARY).getCode(), 200);
322 assertEquals(client.get(badPath, MIMETYPE_BINARY).getCode(), 404);
323 assertEquals(client.get(goodPath, MIMETYPE_BINARY).getCode(), 200);
324 }
325
326 void doTestMultiCellGetPutXML() throws IOException, JAXBException {
327 String path = "/" + TABLE + "/fakerow";
328
329 CellSetModel cellSetModel = new CellSetModel();
330 RowModel rowModel = new RowModel(ROW_1);
331 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
332 Bytes.toBytes(VALUE_1)));
333 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
334 Bytes.toBytes(VALUE_2)));
335 cellSetModel.addRow(rowModel);
336 rowModel = new RowModel(ROW_2);
337 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
338 Bytes.toBytes(VALUE_3)));
339 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
340 Bytes.toBytes(VALUE_4)));
341 cellSetModel.addRow(rowModel);
342 StringWriter writer = new StringWriter();
343 marshaller.marshal(cellSetModel, writer);
344 Response response = client.put(path, MIMETYPE_XML,
345 Bytes.toBytes(writer.toString()));
346 Thread.yield();
347
348
349 response = client.get(path, MIMETYPE_XML);
350 assertEquals(response.getCode(), 404);
351
352
353 checkValueXML(TABLE, ROW_1, COLUMN_1, VALUE_1);
354 checkValueXML(TABLE, ROW_1, COLUMN_2, VALUE_2);
355 checkValueXML(TABLE, ROW_2, COLUMN_1, VALUE_3);
356 checkValueXML(TABLE, ROW_2, COLUMN_2, VALUE_4);
357
358 response = deleteRow(TABLE, ROW_1);
359 assertEquals(response.getCode(), 200);
360 response = deleteRow(TABLE, ROW_2);
361 assertEquals(response.getCode(), 200);
362 }
363
364 void doTestMultiCellGetPutPB() throws IOException {
365 String path = "/" + TABLE + "/fakerow";
366
367 CellSetModel cellSetModel = new CellSetModel();
368 RowModel rowModel = new RowModel(ROW_1);
369 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
370 Bytes.toBytes(VALUE_1)));
371 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
372 Bytes.toBytes(VALUE_2)));
373 cellSetModel.addRow(rowModel);
374 rowModel = new RowModel(ROW_2);
375 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_1),
376 Bytes.toBytes(VALUE_3)));
377 rowModel.addCell(new CellModel(Bytes.toBytes(COLUMN_2),
378 Bytes.toBytes(VALUE_4)));
379 cellSetModel.addRow(rowModel);
380 Response response = client.put(path, MIMETYPE_PROTOBUF,
381 cellSetModel.createProtobufOutput());
382 Thread.yield();
383
384
385 response = client.get(path, MIMETYPE_PROTOBUF);
386 assertEquals(response.getCode(), 404);
387
388
389 checkValuePB(TABLE, ROW_1, COLUMN_1, VALUE_1);
390 checkValuePB(TABLE, ROW_1, COLUMN_2, VALUE_2);
391 checkValuePB(TABLE, ROW_2, COLUMN_1, VALUE_3);
392 checkValuePB(TABLE, ROW_2, COLUMN_2, VALUE_4);
393
394 response = deleteRow(TABLE, ROW_1);
395 assertEquals(response.getCode(), 200);
396 response = deleteRow(TABLE, ROW_2);
397 assertEquals(response.getCode(), 200);
398 }
399
400 public void testRowResource() throws Exception {
401 doTestDelete();
402 doTestSingleCellGetPutXML();
403 doTestSingleCellGetPutPB();
404 doTestSingleCellGetPutBinary();
405 doTestSingleCellGetJSON();
406 doTestURLEncodedKey();
407 doTestMultiCellGetPutXML();
408 doTestMultiCellGetPutPB();
409 }
410 }