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