1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.rest;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertNotNull;
23 import static org.junit.Assert.assertTrue;
24
25 import java.io.DataInputStream;
26 import java.io.EOFException;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.Serializable;
30 import java.net.URLEncoder;
31 import java.nio.charset.StandardCharsets;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.List;
35
36 import javax.ws.rs.core.MediaType;
37 import javax.xml.bind.JAXBContext;
38 import javax.xml.bind.JAXBException;
39 import javax.xml.bind.Unmarshaller;
40 import javax.xml.bind.annotation.XmlAccessType;
41 import javax.xml.bind.annotation.XmlAccessorType;
42 import javax.xml.bind.annotation.XmlElement;
43 import javax.xml.bind.annotation.XmlRootElement;
44 import javax.xml.parsers.SAXParserFactory;
45 import javax.xml.stream.XMLStreamException;
46
47 import org.apache.hadoop.conf.Configuration;
48 import org.apache.hadoop.hbase.HBaseTestingUtility;
49 import org.apache.hadoop.hbase.HColumnDescriptor;
50 import org.apache.hadoop.hbase.HTableDescriptor;
51 import org.apache.hadoop.hbase.testclassification.MediumTests;
52 import org.apache.hadoop.hbase.TableName;
53 import org.apache.hadoop.hbase.client.Admin;
54 import org.apache.hadoop.hbase.filter.Filter;
55 import org.apache.hadoop.hbase.filter.ParseFilter;
56 import org.apache.hadoop.hbase.filter.PrefixFilter;
57 import org.apache.hadoop.hbase.rest.client.Client;
58 import org.apache.hadoop.hbase.rest.client.Cluster;
59 import org.apache.hadoop.hbase.rest.client.Response;
60 import org.apache.hadoop.hbase.rest.model.CellModel;
61 import org.apache.hadoop.hbase.rest.model.CellSetModel;
62 import org.apache.hadoop.hbase.rest.model.RowModel;
63 import org.apache.hadoop.hbase.rest.provider.JacksonProvider;
64 import org.apache.hadoop.hbase.util.Bytes;
65 import org.codehaus.jackson.JsonFactory;
66 import org.codehaus.jackson.JsonParser;
67 import org.codehaus.jackson.JsonToken;
68 import org.codehaus.jackson.map.ObjectMapper;
69 import org.junit.AfterClass;
70 import org.junit.BeforeClass;
71 import org.junit.Test;
72 import org.junit.experimental.categories.Category;
73 import org.xml.sax.InputSource;
74 import org.xml.sax.XMLReader;
75
76 @Category(MediumTests.class)
77 public class TestTableScan {
78
79 private static final TableName TABLE = TableName.valueOf("TestScanResource");
80 private static final String CFA = "a";
81 private static final String CFB = "b";
82 private static final String COLUMN_1 = CFA + ":1";
83 private static final String COLUMN_2 = CFB + ":2";
84 private static final String COLUMN_EMPTY = CFA + ":";
85 private static Client client;
86 private static int expectedRows1;
87 private static int expectedRows2;
88 private static int expectedRows3;
89 private static Configuration conf;
90
91 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
92 private static final HBaseRESTTestingUtility REST_TEST_UTIL =
93 new HBaseRESTTestingUtility();
94
95 @BeforeClass
96 public static void setUpBeforeClass() throws Exception {
97 conf = TEST_UTIL.getConfiguration();
98 conf.set(Constants.CUSTOM_FILTERS, "CustomFilter:" + CustomFilter.class.getName());
99 TEST_UTIL.startMiniCluster();
100 REST_TEST_UTIL.startServletContainer(conf);
101 client = new Client(new Cluster().add("localhost",
102 REST_TEST_UTIL.getServletPort()));
103 Admin admin = TEST_UTIL.getHBaseAdmin();
104 if (!admin.tableExists(TABLE)) {
105 HTableDescriptor htd = new HTableDescriptor(TABLE);
106 htd.addFamily(new HColumnDescriptor(CFA));
107 htd.addFamily(new HColumnDescriptor(CFB));
108 admin.createTable(htd);
109 expectedRows1 = TestScannerResource.insertData(conf, TABLE, COLUMN_1, 1.0);
110 expectedRows2 = TestScannerResource.insertData(conf, TABLE, COLUMN_2, 0.5);
111 expectedRows3 = TestScannerResource.insertData(conf, TABLE, COLUMN_EMPTY, 1.0);
112 }
113 }
114
115 @AfterClass
116 public static void tearDownAfterClass() throws Exception {
117 TEST_UTIL.getHBaseAdmin().disableTable(TABLE);
118 TEST_UTIL.getHBaseAdmin().deleteTable(TABLE);
119 REST_TEST_UTIL.shutdownServletContainer();
120 TEST_UTIL.shutdownMiniCluster();
121 }
122
123 @Test
124 public void testSimpleScannerXML() throws IOException, JAXBException, XMLStreamException {
125
126 StringBuilder builder = new StringBuilder();
127 builder.append("/*");
128 builder.append("?");
129 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
130 builder.append("&");
131 builder.append(Constants.SCAN_LIMIT + "=10");
132 Response response = client.get("/" + TABLE + builder.toString(),
133 Constants.MIMETYPE_XML);
134 assertEquals(200, response.getCode());
135 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
136 JAXBContext ctx = JAXBContext.newInstance(CellSetModel.class);
137 Unmarshaller ush = ctx.createUnmarshaller();
138 CellSetModel model = (CellSetModel) ush.unmarshal(response.getStream());
139 int count = TestScannerResource.countCellSet(model);
140 assertEquals(10, count);
141 checkRowsNotNull(model);
142
143
144 builder = new StringBuilder();
145 builder.append("/*");
146 builder.append("?");
147 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
148 response = client.get("/" + TABLE + builder.toString(),
149 Constants.MIMETYPE_XML);
150 assertEquals(200, response.getCode());
151 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
152 model = (CellSetModel) ush.unmarshal(response.getStream());
153 count = TestScannerResource.countCellSet(model);
154 assertEquals(expectedRows1, count);
155 checkRowsNotNull(model);
156
157
158 builder = new StringBuilder();
159 builder.append("/*");
160 builder.append("?");
161 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
162 builder.append("&");
163 builder.append(Constants.SCAN_START_ROW + "=aaa");
164 builder.append("&");
165 builder.append(Constants.SCAN_END_ROW + "=aay");
166 response = client.get("/" + TABLE + builder.toString(),
167 Constants.MIMETYPE_XML);
168 assertEquals(200, response.getCode());
169 model = (CellSetModel) ush.unmarshal(response.getStream());
170 count = TestScannerResource.countCellSet(model);
171 RowModel startRow = model.getRows().get(0);
172 assertEquals("aaa", Bytes.toString(startRow.getKey()));
173 RowModel endRow = model.getRows().get(model.getRows().size() - 1);
174 assertEquals("aax", Bytes.toString(endRow.getKey()));
175 assertEquals(24, count);
176 checkRowsNotNull(model);
177
178
179 builder = new StringBuilder();
180 builder.append("/*");
181 builder.append("?");
182 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
183 builder.append("&");
184 builder.append(Constants.SCAN_START_ROW + "=aaa");
185 builder.append("&");
186 builder.append(Constants.SCAN_LIMIT + "=15");
187 response = client.get("/" + TABLE + builder.toString(),
188 Constants.MIMETYPE_XML);
189 assertEquals(200, response.getCode());
190 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
191 model = (CellSetModel) ush.unmarshal(response.getStream());
192 startRow = model.getRows().get(0);
193 assertEquals("aaa", Bytes.toString(startRow.getKey()));
194 count = TestScannerResource.countCellSet(model);
195 assertEquals(15, count);
196 checkRowsNotNull(model);
197 }
198
199 @Test
200 public void testSimpleScannerJson() throws IOException, JAXBException {
201
202 StringBuilder builder = new StringBuilder();
203 builder.append("/*");
204 builder.append("?");
205 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
206 builder.append("&");
207 builder.append(Constants.SCAN_LIMIT + "=20");
208 Response response = client.get("/" + TABLE + builder.toString(),
209 Constants.MIMETYPE_JSON);
210 assertEquals(200, response.getCode());
211 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
212 ObjectMapper mapper = new JacksonProvider()
213 .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
214 CellSetModel model = mapper.readValue(response.getStream(), CellSetModel.class);
215 int count = TestScannerResource.countCellSet(model);
216 assertEquals(20, count);
217 checkRowsNotNull(model);
218
219
220 builder = new StringBuilder();
221 builder.append("/*");
222 builder.append("?");
223 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_2);
224 response = client.get("/" + TABLE + builder.toString(),
225 Constants.MIMETYPE_JSON);
226 assertEquals(200, response.getCode());
227 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
228 model = mapper.readValue(response.getStream(), CellSetModel.class);
229 count = TestScannerResource.countCellSet(model);
230 assertEquals(expectedRows2, count);
231 checkRowsNotNull(model);
232
233
234 builder = new StringBuilder();
235 builder.append("/*");
236 builder.append("?");
237 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
238 builder.append("&");
239 builder.append(Constants.SCAN_START_ROW + "=aaa");
240 builder.append("&");
241 builder.append(Constants.SCAN_END_ROW + "=aay");
242 response = client.get("/" + TABLE + builder.toString(),
243 Constants.MIMETYPE_JSON);
244 assertEquals(200, response.getCode());
245 model = mapper.readValue(response.getStream(), CellSetModel.class);
246 RowModel startRow = model.getRows().get(0);
247 assertEquals("aaa", Bytes.toString(startRow.getKey()));
248 RowModel endRow = model.getRows().get(model.getRows().size() - 1);
249 assertEquals("aax", Bytes.toString(endRow.getKey()));
250 count = TestScannerResource.countCellSet(model);
251 assertEquals(24, count);
252 checkRowsNotNull(model);
253 }
254
255
256
257
258
259 @Test
260 public void testScanUsingListenerUnmarshallerXML() throws Exception {
261 StringBuilder builder = new StringBuilder();
262 builder.append("/*");
263 builder.append("?");
264 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
265 builder.append("&");
266 builder.append(Constants.SCAN_LIMIT + "=10");
267 Response response = client.get("/" + TABLE + builder.toString(),
268 Constants.MIMETYPE_XML);
269 assertEquals(200, response.getCode());
270 assertEquals(Constants.MIMETYPE_XML, response.getHeader("content-type"));
271 JAXBContext context = JAXBContext.newInstance(ClientSideCellSetModel.class, RowModel.class,
272 CellModel.class);
273 Unmarshaller unmarshaller = context.createUnmarshaller();
274
275 final ClientSideCellSetModel.Listener listener = new ClientSideCellSetModel.Listener() {
276 @Override
277 public void handleRowModel(ClientSideCellSetModel helper, RowModel row) {
278 assertTrue(row.getKey() != null);
279 assertTrue(row.getCells().size() > 0);
280 }
281 };
282
283
284 unmarshaller.setListener(new Unmarshaller.Listener() {
285 @Override
286 public void beforeUnmarshal(Object target, Object parent) {
287 if (target instanceof ClientSideCellSetModel) {
288 ((ClientSideCellSetModel) target).setCellSetModelListener(listener);
289 }
290 }
291
292 @Override
293 public void afterUnmarshal(Object target, Object parent) {
294 if (target instanceof ClientSideCellSetModel) {
295 ((ClientSideCellSetModel) target).setCellSetModelListener(null);
296 }
297 }
298 });
299
300
301 SAXParserFactory factory = SAXParserFactory.newInstance();
302 factory.setNamespaceAware(true);
303 XMLReader reader = factory.newSAXParser().getXMLReader();
304 reader.setContentHandler(unmarshaller.getUnmarshallerHandler());
305 assertFalse(ClientSideCellSetModel.listenerInvoked);
306 reader.parse(new InputSource(response.getStream()));
307 assertTrue(ClientSideCellSetModel.listenerInvoked);
308
309 }
310
311 @Test
312 public void testStreamingJSON() throws Exception {
313
314 StringBuilder builder = new StringBuilder();
315 builder.append("/*");
316 builder.append("?");
317 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
318 builder.append("&");
319 builder.append(Constants.SCAN_LIMIT + "=20");
320 Response response = client.get("/" + TABLE + builder.toString(),
321 Constants.MIMETYPE_JSON);
322 assertEquals(200, response.getCode());
323 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
324 ObjectMapper mapper = new JacksonProvider()
325 .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
326 CellSetModel model = mapper.readValue(response.getStream(), CellSetModel.class);
327 int count = TestScannerResource.countCellSet(model);
328 assertEquals(20, count);
329 checkRowsNotNull(model);
330
331
332 builder = new StringBuilder();
333 builder.append("/*");
334 builder.append("?");
335 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_2);
336 response = client.get("/" + TABLE + builder.toString(),
337 Constants.MIMETYPE_JSON);
338 assertEquals(200, response.getCode());
339 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
340 model = mapper.readValue(response.getStream(), CellSetModel.class);
341 count = TestScannerResource.countCellSet(model);
342 assertEquals(expectedRows2, count);
343 checkRowsNotNull(model);
344
345
346 builder = new StringBuilder();
347 builder.append("/*");
348 builder.append("?");
349 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
350 builder.append("&");
351 builder.append(Constants.SCAN_START_ROW + "=aaa");
352 builder.append("&");
353 builder.append(Constants.SCAN_END_ROW + "=aay");
354 response = client.get("/" + TABLE + builder.toString(),
355 Constants.MIMETYPE_JSON);
356 assertEquals(200, response.getCode());
357
358 count = 0;
359 JsonFactory jfactory = new JsonFactory(mapper);
360 JsonParser jParser = jfactory.createJsonParser(response.getStream());
361 boolean found = false;
362 while (jParser.nextToken() != JsonToken.END_OBJECT) {
363 if(jParser.getCurrentToken() == JsonToken.START_OBJECT && found) {
364 RowModel row = jParser.readValueAs(RowModel.class);
365 assertNotNull(row.getKey());
366 for (int i = 0; i < row.getCells().size(); i++) {
367 if (count == 0) {
368 assertEquals("aaa", Bytes.toString(row.getKey()));
369 }
370 if (count == 23) {
371 assertEquals("aax", Bytes.toString(row.getKey()));
372 }
373 count++;
374 }
375 jParser.skipChildren();
376 } else {
377 found = jParser.getCurrentToken() == JsonToken.START_ARRAY;
378 }
379 }
380 assertEquals(24, count);
381 }
382
383 @Test
384 public void testSimpleScannerProtobuf() throws Exception {
385 StringBuilder builder = new StringBuilder();
386 builder.append("/*");
387 builder.append("?");
388 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
389 builder.append("&");
390 builder.append(Constants.SCAN_LIMIT + "=15");
391 Response response = client.get("/" + TABLE + builder.toString(),
392 Constants.MIMETYPE_PROTOBUF);
393 assertEquals(200, response.getCode());
394 assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type"));
395 int rowCount = readProtobufStream(response.getStream());
396 assertEquals(15, rowCount);
397
398
399 builder = new StringBuilder();
400 builder.append("/*");
401 builder.append("?");
402 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
403 builder.append("&");
404 builder.append(Constants.SCAN_START_ROW + "=aaa");
405 builder.append("&");
406 builder.append(Constants.SCAN_END_ROW + "=aay");
407 response = client.get("/" + TABLE + builder.toString(),
408 Constants.MIMETYPE_PROTOBUF);
409 assertEquals(200, response.getCode());
410 assertEquals(Constants.MIMETYPE_PROTOBUF, response.getHeader("content-type"));
411 rowCount = readProtobufStream(response.getStream());
412 assertEquals(24, rowCount);
413 }
414
415 private void checkRowsNotNull(CellSetModel model) {
416 for (RowModel row: model.getRows()) {
417 assertTrue(row.getKey() != null);
418 assertTrue(row.getCells().size() > 0);
419 }
420 }
421
422
423
424
425
426
427
428 public int readProtobufStream(InputStream inputStream) throws IOException{
429 DataInputStream stream = new DataInputStream(inputStream);
430 CellSetModel model = null;
431 int rowCount = 0;
432 try {
433 while (true) {
434 byte[] lengthBytes = new byte[2];
435 int readBytes = stream.read(lengthBytes);
436 if (readBytes == -1) {
437 break;
438 }
439 assertEquals(2, readBytes);
440 int length = Bytes.toShort(lengthBytes);
441 byte[] cellset = new byte[length];
442 stream.read(cellset);
443 model = new CellSetModel();
444 model.getObjectFromMessage(cellset);
445 checkRowsNotNull(model);
446 rowCount = rowCount + TestScannerResource.countCellSet(model);
447 }
448 } catch (EOFException exp) {
449 exp.printStackTrace();
450 } finally {
451 stream.close();
452 }
453 return rowCount;
454 }
455
456 @Test
457 public void testScanningUnknownColumnJson() throws IOException, JAXBException {
458
459 StringBuilder builder = new StringBuilder();
460 builder.append("/*");
461 builder.append("?");
462 builder.append(Constants.SCAN_COLUMN + "=a:test");
463 Response response = client.get("/" + TABLE + builder.toString(),
464 Constants.MIMETYPE_JSON);
465 assertEquals(200, response.getCode());
466 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
467 ObjectMapper mapper = new JacksonProvider().locateMapper(CellSetModel.class,
468 MediaType.APPLICATION_JSON_TYPE);
469 CellSetModel model = mapper.readValue(response.getStream(), CellSetModel.class);
470 int count = TestScannerResource.countCellSet(model);
471 assertEquals(0, count);
472 }
473
474 @Test
475 public void testSimpleFilter() throws IOException, JAXBException {
476 StringBuilder builder = new StringBuilder();
477 builder.append("/*");
478 builder.append("?");
479 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
480 builder.append("&");
481 builder.append(Constants.SCAN_START_ROW + "=aaa");
482 builder.append("&");
483 builder.append(Constants.SCAN_END_ROW + "=aay");
484 builder.append("&");
485 builder.append(Constants.SCAN_FILTER + "=" + URLEncoder.encode("PrefixFilter('aab')", "UTF-8"));
486 Response response =
487 client.get("/" + TABLE + builder.toString(), Constants.MIMETYPE_XML);
488 assertEquals(200, response.getCode());
489 JAXBContext ctx = JAXBContext.newInstance(CellSetModel.class);
490 Unmarshaller ush = ctx.createUnmarshaller();
491 CellSetModel model = (CellSetModel) ush.unmarshal(response.getStream());
492 int count = TestScannerResource.countCellSet(model);
493 assertEquals(1, count);
494 assertEquals("aab", new String(model.getRows().get(0).getCells().get(0).getValue(),
495 StandardCharsets.UTF_8));
496 }
497
498 @Test
499 public void testQualifierAndPrefixFilters() throws IOException, JAXBException {
500 StringBuilder builder = new StringBuilder();
501 builder.append("/abc*");
502 builder.append("?");
503 builder.append(Constants.SCAN_FILTER + "="
504 + URLEncoder.encode("QualifierFilter(=,'binary:1')", "UTF-8"));
505 Response response =
506 client.get("/" + TABLE + builder.toString(), Constants.MIMETYPE_XML);
507 assertEquals(200, response.getCode());
508 JAXBContext ctx = JAXBContext.newInstance(CellSetModel.class);
509 Unmarshaller ush = ctx.createUnmarshaller();
510 CellSetModel model = (CellSetModel) ush.unmarshal(response.getStream());
511 int count = TestScannerResource.countCellSet(model);
512 assertEquals(1, count);
513 assertEquals("abc", new String(model.getRows().get(0).getCells().get(0).getValue(),
514 StandardCharsets.UTF_8));
515 }
516
517
518 @Test
519 public void testCompoundFilter() throws IOException, JAXBException {
520 StringBuilder builder = new StringBuilder();
521 builder.append("/*");
522 builder.append("?");
523 builder.append(Constants.SCAN_FILTER + "="
524 + URLEncoder.encode("PrefixFilter('abc') AND QualifierFilter(=,'binary:1')", "UTF-8"));
525 Response response =
526 client.get("/" + TABLE + builder.toString(), Constants.MIMETYPE_XML);
527 assertEquals(200, response.getCode());
528 JAXBContext ctx = JAXBContext.newInstance(CellSetModel.class);
529 Unmarshaller ush = ctx.createUnmarshaller();
530 CellSetModel model = (CellSetModel) ush.unmarshal(response.getStream());
531 int count = TestScannerResource.countCellSet(model);
532 assertEquals(1, count);
533 assertEquals("abc", new String(model.getRows().get(0).getCells().get(0).getValue(),
534 StandardCharsets.UTF_8));
535 }
536
537 @Test
538 public void testCustomFilter() throws IOException, JAXBException {
539 StringBuilder builder = new StringBuilder();
540 builder.append("/a*");
541 builder.append("?");
542 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
543 builder.append("&");
544 builder.append(Constants.SCAN_FILTER + "=" + URLEncoder.encode("CustomFilter('abc')", "UTF-8"));
545 Response response =
546 client.get("/" + TABLE + builder.toString(), Constants.MIMETYPE_XML);
547 assertEquals(200, response.getCode());
548 JAXBContext ctx = JAXBContext.newInstance(CellSetModel.class);
549 Unmarshaller ush = ctx.createUnmarshaller();
550 CellSetModel model = (CellSetModel) ush.unmarshal(response.getStream());
551 int count = TestScannerResource.countCellSet(model);
552 assertEquals(1, count);
553 assertEquals("abc", new String(model.getRows().get(0).getCells().get(0).getValue(),
554 StandardCharsets.UTF_8));
555 }
556
557 @Test
558 public void testNegativeCustomFilter() throws IOException, JAXBException {
559 StringBuilder builder = new StringBuilder();
560 builder.append("/b*");
561 builder.append("?");
562 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
563 builder.append("&");
564 builder.append(Constants.SCAN_FILTER + "=" + URLEncoder.encode("CustomFilter('abc')", "UTF-8"));
565 Response response =
566 client.get("/" + TABLE + builder.toString(), Constants.MIMETYPE_XML);
567 assertEquals(200, response.getCode());
568 JAXBContext ctx = JAXBContext.newInstance(CellSetModel.class);
569 Unmarshaller ush = ctx.createUnmarshaller();
570 CellSetModel model = (CellSetModel) ush.unmarshal(response.getStream());
571 int count = TestScannerResource.countCellSet(model);
572
573 assertEquals(0, count);
574 }
575
576 @Test
577 public void testReversed() throws IOException, JAXBException {
578 StringBuilder builder = new StringBuilder();
579 builder.append("/*");
580 builder.append("?");
581 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
582 builder.append("&");
583 builder.append(Constants.SCAN_START_ROW + "=aaa");
584 builder.append("&");
585 builder.append(Constants.SCAN_END_ROW + "=aay");
586 Response response = client.get("/" + TABLE + builder.toString(), Constants.MIMETYPE_XML);
587 assertEquals(200, response.getCode());
588 JAXBContext ctx = JAXBContext.newInstance(CellSetModel.class);
589 Unmarshaller ush = ctx.createUnmarshaller();
590 CellSetModel model = (CellSetModel) ush.unmarshal(response.getStream());
591 int count = TestScannerResource.countCellSet(model);
592 assertEquals(24, count);
593 List<RowModel> rowModels = model.getRows().subList(1, count);
594
595
596 builder = new StringBuilder();
597 builder.append("/*");
598 builder.append("?");
599 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
600 builder.append("&");
601 builder.append(Constants.SCAN_START_ROW + "=aay");
602 builder.append("&");
603 builder.append(Constants.SCAN_END_ROW + "=aaa");
604 builder.append("&");
605 builder.append(Constants.SCAN_REVERSED + "=true");
606 response = client.get("/" + TABLE + builder.toString(), Constants.MIMETYPE_XML);
607 assertEquals(200, response.getCode());
608 model = (CellSetModel) ush.unmarshal(response.getStream());
609 count = TestScannerResource.countCellSet(model);
610 assertEquals(24, count);
611 List<RowModel> reversedRowModels = model.getRows().subList(1, count);
612
613 Collections.reverse(reversedRowModels);
614 assertEquals(rowModels.size(), reversedRowModels.size());
615 for (int i = 0; i < rowModels.size(); i++) {
616 RowModel rowModel = rowModels.get(i);
617 RowModel reversedRowModel = reversedRowModels.get(i);
618
619 assertEquals(new String(rowModel.getKey(), StandardCharsets.UTF_8),
620 new String(reversedRowModel.getKey(), StandardCharsets.UTF_8));
621 assertEquals(new String(rowModel.getCells().get(0).getValue(), StandardCharsets.UTF_8),
622 new String(reversedRowModel.getCells().get(0).getValue(), StandardCharsets.UTF_8));
623 }
624 }
625
626 @Test
627 public void testColumnWithEmptyQualifier() throws IOException, JAXBException {
628
629 StringBuilder builder = new StringBuilder();
630 builder.append("/*");
631 builder.append("?");
632 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_EMPTY);
633 Response response = client.get("/" + TABLE + builder.toString(),
634 Constants.MIMETYPE_JSON);
635 assertEquals(200, response.getCode());
636 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
637 ObjectMapper mapper = new JacksonProvider()
638 .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
639 CellSetModel model = mapper.readValue(response.getStream(), CellSetModel.class);
640 int count = TestScannerResource.countCellSet(model);
641 assertEquals(expectedRows3, count);
642 checkRowsNotNull(model);
643 RowModel startRow = model.getRows().get(0);
644 assertEquals("aaa", Bytes.toString(startRow.getKey()));
645 assertEquals(1, startRow.getCells().size());
646
647
648 builder = new StringBuilder();
649 builder.append("/*");
650 builder.append("?");
651 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
652 builder.append("&");
653 builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_EMPTY);
654 response = client.get("/" + TABLE + builder.toString(),
655 Constants.MIMETYPE_JSON);
656 assertEquals(200, response.getCode());
657 assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
658 mapper = new JacksonProvider()
659 .locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
660 model = mapper.readValue(response.getStream(), CellSetModel.class);
661 count = TestScannerResource.countCellSet(model);
662 assertEquals(expectedRows1 + expectedRows3, count);
663 checkRowsNotNull(model);
664 }
665
666 public static class CustomFilter extends PrefixFilter {
667 private byte[] key = null;
668
669 public CustomFilter(byte[] key) {
670 super(key);
671 }
672
673 @Override
674 public boolean filterRowKey(byte[] buffer, int offset, int length) {
675 int cmp = Bytes.compareTo(buffer, offset, length, this.key, 0, this.key.length);
676 return cmp != 0;
677 }
678
679 public static Filter createFilterFromArguments(ArrayList<byte[]> filterArguments) {
680 byte[] prefix = ParseFilter.removeQuotesFromByteArray(filterArguments.get(0));
681 return new CustomFilter(prefix);
682 }
683 }
684
685
686
687
688
689 @XmlRootElement(name = "CellSet")
690 @XmlAccessorType(XmlAccessType.FIELD)
691 public static class ClientSideCellSetModel implements Serializable {
692
693 private static final long serialVersionUID = 1L;
694
695
696
697
698
699 @XmlElement(name="Row")
700 private List<RowModel> row;
701
702 static boolean listenerInvoked = false;
703
704
705
706
707
708 public void setCellSetModelListener(final Listener l) {
709 row = (l == null) ? null : new ArrayList<RowModel>() {
710 private static final long serialVersionUID = 1L;
711 @Override
712 public boolean add(RowModel o) {
713 l.handleRowModel(ClientSideCellSetModel.this, o);
714 listenerInvoked = true;
715 return false;
716 }
717 };
718 }
719
720
721
722
723 public static interface Listener {
724 void handleRowModel(ClientSideCellSetModel helper, RowModel rowModel);
725 }
726 }
727 }
728
729
730