1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.filter;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.hadoop.hbase.classification.InterfaceAudience;
24 import org.apache.hadoop.hbase.classification.InterfaceStability;
25 import org.apache.hadoop.hbase.KeyValue;
26 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
27 import org.apache.hadoop.hbase.util.Bytes;
28
29 import java.lang.reflect.InvocationTargetException;
30 import java.lang.reflect.Method;
31 import java.nio.ByteBuffer;
32 import java.nio.charset.CharacterCodingException;
33 import java.nio.charset.StandardCharsets;
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.EmptyStackException;
37 import java.util.HashMap;
38 import java.util.Map;
39 import java.util.regex.Pattern;
40 import java.util.Set;
41 import java.util.Stack;
42
43
44
45
46
47
48
49
50
51
52 @InterfaceAudience.Public
53 @InterfaceStability.Stable
54 public class ParseFilter {
55 private static final Log LOG = LogFactory.getLog(ParseFilter.class);
56
57 private static HashMap<ByteBuffer, Integer> operatorPrecedenceHashMap;
58 private static HashMap<String, String> filterHashMap;
59
60 static {
61
62 filterHashMap = new HashMap<String, String>();
63 filterHashMap.put("KeyOnlyFilter", ParseConstants.FILTER_PACKAGE + "." +
64 "KeyOnlyFilter");
65 filterHashMap.put("FirstKeyOnlyFilter", ParseConstants.FILTER_PACKAGE + "." +
66 "FirstKeyOnlyFilter");
67 filterHashMap.put("PrefixFilter", ParseConstants.FILTER_PACKAGE + "." +
68 "PrefixFilter");
69 filterHashMap.put("ColumnPrefixFilter", ParseConstants.FILTER_PACKAGE + "." +
70 "ColumnPrefixFilter");
71 filterHashMap.put("MultipleColumnPrefixFilter", ParseConstants.FILTER_PACKAGE + "." +
72 "MultipleColumnPrefixFilter");
73 filterHashMap.put("ColumnCountGetFilter", ParseConstants.FILTER_PACKAGE + "." +
74 "ColumnCountGetFilter");
75 filterHashMap.put("PageFilter", ParseConstants.FILTER_PACKAGE + "." +
76 "PageFilter");
77 filterHashMap.put("ColumnPaginationFilter", ParseConstants.FILTER_PACKAGE + "." +
78 "ColumnPaginationFilter");
79 filterHashMap.put("InclusiveStopFilter", ParseConstants.FILTER_PACKAGE + "." +
80 "InclusiveStopFilter");
81 filterHashMap.put("TimestampsFilter", ParseConstants.FILTER_PACKAGE + "." +
82 "TimestampsFilter");
83 filterHashMap.put("RowFilter", ParseConstants.FILTER_PACKAGE + "." +
84 "RowFilter");
85 filterHashMap.put("FamilyFilter", ParseConstants.FILTER_PACKAGE + "." +
86 "FamilyFilter");
87 filterHashMap.put("QualifierFilter", ParseConstants.FILTER_PACKAGE + "." +
88 "QualifierFilter");
89 filterHashMap.put("ValueFilter", ParseConstants.FILTER_PACKAGE + "." +
90 "ValueFilter");
91 filterHashMap.put("ColumnRangeFilter", ParseConstants.FILTER_PACKAGE + "." +
92 "ColumnRangeFilter");
93 filterHashMap.put("SingleColumnValueFilter", ParseConstants.FILTER_PACKAGE + "." +
94 "SingleColumnValueFilter");
95 filterHashMap.put("SingleColumnValueExcludeFilter", ParseConstants.FILTER_PACKAGE + "." +
96 "SingleColumnValueExcludeFilter");
97 filterHashMap.put("DependentColumnFilter", ParseConstants.FILTER_PACKAGE + "." +
98 "DependentColumnFilter");
99
100
101 operatorPrecedenceHashMap = new HashMap<ByteBuffer, Integer>();
102 operatorPrecedenceHashMap.put(ParseConstants.SKIP_BUFFER, 1);
103 operatorPrecedenceHashMap.put(ParseConstants.WHILE_BUFFER, 1);
104 operatorPrecedenceHashMap.put(ParseConstants.AND_BUFFER, 2);
105 operatorPrecedenceHashMap.put(ParseConstants.OR_BUFFER, 3);
106 }
107
108
109
110
111
112
113
114 public Filter parseFilterString (String filterString)
115 throws CharacterCodingException {
116 return parseFilterString(Bytes.toBytes(filterString));
117 }
118
119
120
121
122
123
124
125 public Filter parseFilterString (byte [] filterStringAsByteArray)
126 throws CharacterCodingException {
127
128 Stack <ByteBuffer> operatorStack = new Stack<ByteBuffer>();
129
130 Stack <Filter> filterStack = new Stack<Filter>();
131
132 Filter filter = null;
133 for (int i=0; i<filterStringAsByteArray.length; i++) {
134 if (filterStringAsByteArray[i] == ParseConstants.LPAREN) {
135
136 operatorStack.push(ParseConstants.LPAREN_BUFFER);
137 } else if (filterStringAsByteArray[i] == ParseConstants.WHITESPACE ||
138 filterStringAsByteArray[i] == ParseConstants.TAB) {
139
140 continue;
141 } else if (checkForOr(filterStringAsByteArray, i)) {
142
143 i += ParseConstants.OR_ARRAY.length - 1;
144 reduce(operatorStack, filterStack, ParseConstants.OR_BUFFER);
145 operatorStack.push(ParseConstants.OR_BUFFER);
146 } else if (checkForAnd(filterStringAsByteArray, i)) {
147
148 i += ParseConstants.AND_ARRAY.length - 1;
149 reduce(operatorStack, filterStack, ParseConstants.AND_BUFFER);
150 operatorStack.push(ParseConstants.AND_BUFFER);
151 } else if (checkForSkip(filterStringAsByteArray, i)) {
152
153 i += ParseConstants.SKIP_ARRAY.length - 1;
154 reduce(operatorStack, filterStack, ParseConstants.SKIP_BUFFER);
155 operatorStack.push(ParseConstants.SKIP_BUFFER);
156 } else if (checkForWhile(filterStringAsByteArray, i)) {
157
158 i += ParseConstants.WHILE_ARRAY.length - 1;
159 reduce(operatorStack, filterStack, ParseConstants.WHILE_BUFFER);
160 operatorStack.push(ParseConstants.WHILE_BUFFER);
161 } else if (filterStringAsByteArray[i] == ParseConstants.RPAREN) {
162
163 if (operatorStack.empty()) {
164 throw new IllegalArgumentException("Mismatched parenthesis");
165 }
166 ByteBuffer argumentOnTopOfStack = operatorStack.peek();
167 if (argumentOnTopOfStack.equals(ParseConstants.LPAREN_BUFFER)) {
168 operatorStack.pop();
169 continue;
170 }
171 while (!(argumentOnTopOfStack.equals(ParseConstants.LPAREN_BUFFER))) {
172 filterStack.push(popArguments(operatorStack, filterStack));
173 if (operatorStack.empty()) {
174 throw new IllegalArgumentException("Mismatched parenthesis");
175 }
176 argumentOnTopOfStack = operatorStack.pop();
177 }
178 } else {
179
180 byte [] filterSimpleExpression = extractFilterSimpleExpression(filterStringAsByteArray, i);
181 i+= (filterSimpleExpression.length - 1);
182 filter = parseSimpleFilterExpression(filterSimpleExpression);
183 filterStack.push(filter);
184 }
185 }
186
187
188 while (!operatorStack.empty()) {
189 filterStack.push(popArguments(operatorStack, filterStack));
190 }
191 if (filterStack.empty()) {
192 throw new IllegalArgumentException("Incorrect Filter String");
193 }
194 filter = filterStack.pop();
195 if (!filterStack.empty()) {
196 throw new IllegalArgumentException("Incorrect Filter String");
197 }
198 return filter;
199 }
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215 public byte [] extractFilterSimpleExpression (byte [] filterStringAsByteArray,
216 int filterExpressionStartOffset)
217 throws CharacterCodingException {
218 int quoteCount = 0;
219 for (int i=filterExpressionStartOffset; i<filterStringAsByteArray.length; i++) {
220 if (filterStringAsByteArray[i] == ParseConstants.SINGLE_QUOTE) {
221 if (isQuoteUnescaped(filterStringAsByteArray, i)) {
222 quoteCount ++;
223 } else {
224
225 i++;
226 }
227 }
228 if (filterStringAsByteArray[i] == ParseConstants.RPAREN && (quoteCount %2 ) == 0) {
229 byte [] filterSimpleExpression = new byte [i - filterExpressionStartOffset + 1];
230 Bytes.putBytes(filterSimpleExpression, 0, filterStringAsByteArray,
231 filterExpressionStartOffset, i-filterExpressionStartOffset + 1);
232 return filterSimpleExpression;
233 }
234 }
235 throw new IllegalArgumentException("Incorrect Filter String");
236 }
237
238
239
240
241
242
243
244 public Filter parseSimpleFilterExpression (byte [] filterStringAsByteArray)
245 throws CharacterCodingException {
246
247 String filterName = Bytes.toString(getFilterName(filterStringAsByteArray));
248 ArrayList<byte []> filterArguments = getFilterArguments(filterStringAsByteArray);
249 if (!filterHashMap.containsKey(filterName)) {
250 throw new IllegalArgumentException("Filter Name " + filterName + " not supported");
251 }
252 try {
253 filterName = filterHashMap.get(filterName);
254 Class<?> c = Class.forName(filterName);
255 Class<?>[] argTypes = new Class [] {ArrayList.class};
256 Method m = c.getDeclaredMethod("createFilterFromArguments", argTypes);
257 return (Filter) m.invoke(null,filterArguments);
258 } catch (ClassNotFoundException e) {
259 e.printStackTrace();
260 } catch (NoSuchMethodException e) {
261 e.printStackTrace();
262 } catch (IllegalAccessException e) {
263 e.printStackTrace();
264 } catch (InvocationTargetException e) {
265 e.printStackTrace();
266 }
267 throw new IllegalArgumentException("Incorrect filter string " +
268 new String(filterStringAsByteArray, StandardCharsets.UTF_8));
269 }
270
271
272
273
274
275
276
277 public static byte [] getFilterName (byte [] filterStringAsByteArray) {
278 int filterNameStartIndex = 0;
279 int filterNameEndIndex = 0;
280
281 for (int i=filterNameStartIndex; i<filterStringAsByteArray.length; i++) {
282 if (filterStringAsByteArray[i] == ParseConstants.LPAREN ||
283 filterStringAsByteArray[i] == ParseConstants.WHITESPACE) {
284 filterNameEndIndex = i;
285 break;
286 }
287 }
288
289 if (filterNameEndIndex == 0) {
290 throw new IllegalArgumentException("Incorrect Filter Name");
291 }
292
293 byte [] filterName = new byte[filterNameEndIndex - filterNameStartIndex];
294 Bytes.putBytes(filterName, 0, filterStringAsByteArray, 0,
295 filterNameEndIndex - filterNameStartIndex);
296 return filterName;
297 }
298
299
300
301
302
303
304
305 public static ArrayList<byte []> getFilterArguments (byte [] filterStringAsByteArray) {
306 int argumentListStartIndex = KeyValue.getDelimiter(filterStringAsByteArray, 0,
307 filterStringAsByteArray.length,
308 ParseConstants.LPAREN);
309 if (argumentListStartIndex == -1) {
310 throw new IllegalArgumentException("Incorrect argument list");
311 }
312
313 int argumentStartIndex = 0;
314 int argumentEndIndex = 0;
315 ArrayList<byte []> filterArguments = new ArrayList<byte []>();
316
317 for (int i = argumentListStartIndex + 1; i<filterStringAsByteArray.length; i++) {
318
319 if (filterStringAsByteArray[i] == ParseConstants.WHITESPACE ||
320 filterStringAsByteArray[i] == ParseConstants.COMMA ||
321 filterStringAsByteArray[i] == ParseConstants.RPAREN) {
322 continue;
323 }
324
325
326 if (filterStringAsByteArray[i] == ParseConstants.SINGLE_QUOTE) {
327 argumentStartIndex = i;
328 for (int j = argumentStartIndex+1; j < filterStringAsByteArray.length; j++) {
329 if (filterStringAsByteArray[j] == ParseConstants.SINGLE_QUOTE) {
330 if (isQuoteUnescaped(filterStringAsByteArray,j)) {
331 argumentEndIndex = j;
332 i = j+1;
333 byte [] filterArgument = createUnescapdArgument(filterStringAsByteArray,
334 argumentStartIndex, argumentEndIndex);
335 filterArguments.add(filterArgument);
336 break;
337 } else {
338
339 j++;
340 }
341 } else if (j == filterStringAsByteArray.length - 1) {
342 throw new IllegalArgumentException("Incorrect argument list");
343 }
344 }
345 } else {
346
347 argumentStartIndex = i;
348 for (int j = argumentStartIndex; j < filterStringAsByteArray.length; j++) {
349 if (filterStringAsByteArray[j] == ParseConstants.WHITESPACE ||
350 filterStringAsByteArray[j] == ParseConstants.COMMA ||
351 filterStringAsByteArray[j] == ParseConstants.RPAREN) {
352 argumentEndIndex = j - 1;
353 i = j;
354 byte [] filterArgument = new byte [argumentEndIndex - argumentStartIndex + 1];
355 Bytes.putBytes(filterArgument, 0, filterStringAsByteArray,
356 argumentStartIndex, argumentEndIndex - argumentStartIndex + 1);
357 filterArguments.add(filterArgument);
358 break;
359 } else if (j == filterStringAsByteArray.length - 1) {
360 throw new IllegalArgumentException("Incorrect argument list");
361 }
362 }
363 }
364 }
365 return filterArguments;
366 }
367
368
369
370
371
372
373
374
375 public void reduce(Stack<ByteBuffer> operatorStack,
376 Stack<Filter> filterStack,
377 ByteBuffer operator) {
378 while (!operatorStack.empty() &&
379 !(ParseConstants.LPAREN_BUFFER.equals(operatorStack.peek())) &&
380 hasHigherPriority(operatorStack.peek(), operator)) {
381 filterStack.push(popArguments(operatorStack, filterStack));
382 }
383 }
384
385
386
387
388
389
390
391
392
393 public static Filter popArguments (Stack<ByteBuffer> operatorStack, Stack <Filter> filterStack) {
394 ByteBuffer argumentOnTopOfStack = operatorStack.peek();
395
396 if (argumentOnTopOfStack.equals(ParseConstants.OR_BUFFER)) {
397
398 try {
399 ArrayList<Filter> listOfFilters = new ArrayList<Filter>();
400 while (!operatorStack.empty() && operatorStack.peek().equals(ParseConstants.OR_BUFFER)) {
401 Filter filter = filterStack.pop();
402 listOfFilters.add(0, filter);
403 operatorStack.pop();
404 }
405 Filter filter = filterStack.pop();
406 listOfFilters.add(0, filter);
407 Filter orFilter = new FilterList(FilterList.Operator.MUST_PASS_ONE, listOfFilters);
408 return orFilter;
409 } catch (EmptyStackException e) {
410 throw new IllegalArgumentException("Incorrect input string - an OR needs two filters");
411 }
412
413 } else if (argumentOnTopOfStack.equals(ParseConstants.AND_BUFFER)) {
414
415 try {
416 ArrayList<Filter> listOfFilters = new ArrayList<Filter>();
417 while (!operatorStack.empty() && operatorStack.peek().equals(ParseConstants.AND_BUFFER)) {
418 Filter filter = filterStack.pop();
419 listOfFilters.add(0, filter);
420 operatorStack.pop();
421 }
422 Filter filter = filterStack.pop();
423 listOfFilters.add(0, filter);
424 Filter andFilter = new FilterList(FilterList.Operator.MUST_PASS_ALL, listOfFilters);
425 return andFilter;
426 } catch (EmptyStackException e) {
427 throw new IllegalArgumentException("Incorrect input string - an AND needs two filters");
428 }
429
430 } else if (argumentOnTopOfStack.equals(ParseConstants.SKIP_BUFFER)) {
431
432 try {
433 Filter wrappedFilter = filterStack.pop();
434 Filter skipFilter = new SkipFilter(wrappedFilter);
435 operatorStack.pop();
436 return skipFilter;
437 } catch (EmptyStackException e) {
438 throw new IllegalArgumentException("Incorrect input string - a SKIP wraps a filter");
439 }
440
441 } else if (argumentOnTopOfStack.equals(ParseConstants.WHILE_BUFFER)) {
442
443 try {
444 Filter wrappedFilter = filterStack.pop();
445 Filter whileMatchFilter = new WhileMatchFilter(wrappedFilter);
446 operatorStack.pop();
447 return whileMatchFilter;
448 } catch (EmptyStackException e) {
449 throw new IllegalArgumentException("Incorrect input string - a WHILE wraps a filter");
450 }
451
452 } else if (argumentOnTopOfStack.equals(ParseConstants.LPAREN_BUFFER)) {
453
454 try {
455 Filter filter = filterStack.pop();
456 operatorStack.pop();
457 return filter;
458 } catch (EmptyStackException e) {
459 throw new IllegalArgumentException("Incorrect Filter String");
460 }
461
462 } else {
463 throw new IllegalArgumentException("Incorrect arguments on operatorStack");
464 }
465 }
466
467
468
469
470
471
472
473 public boolean hasHigherPriority(ByteBuffer a, ByteBuffer b) {
474 if ((operatorPrecedenceHashMap.get(a) - operatorPrecedenceHashMap.get(b)) < 0) {
475 return true;
476 }
477 return false;
478 }
479
480
481
482
483
484
485
486
487
488 public static byte [] createUnescapdArgument (byte [] filterStringAsByteArray,
489 int argumentStartIndex, int argumentEndIndex) {
490 int unescapedArgumentLength = 2;
491 for (int i = argumentStartIndex + 1; i <= argumentEndIndex - 1; i++) {
492 unescapedArgumentLength ++;
493 if (filterStringAsByteArray[i] == ParseConstants.SINGLE_QUOTE &&
494 i != (argumentEndIndex - 1) &&
495 filterStringAsByteArray[i+1] == ParseConstants.SINGLE_QUOTE) {
496 i++;
497 continue;
498 }
499 }
500
501 byte [] unescapedArgument = new byte [unescapedArgumentLength];
502 int count = 1;
503 unescapedArgument[0] = '\'';
504 for (int i = argumentStartIndex + 1; i <= argumentEndIndex - 1; i++) {
505 if (filterStringAsByteArray [i] == ParseConstants.SINGLE_QUOTE &&
506 i != (argumentEndIndex - 1) &&
507 filterStringAsByteArray [i+1] == ParseConstants.SINGLE_QUOTE) {
508 unescapedArgument[count++] = filterStringAsByteArray [i+1];
509 i++;
510 }
511 else {
512 unescapedArgument[count++] = filterStringAsByteArray [i];
513 }
514 }
515 unescapedArgument[unescapedArgumentLength - 1] = '\'';
516 return unescapedArgument;
517 }
518
519
520
521
522
523
524
525
526 public static boolean checkForOr (byte [] filterStringAsByteArray, int indexOfOr)
527 throws CharacterCodingException, ArrayIndexOutOfBoundsException {
528
529 try {
530 if (filterStringAsByteArray[indexOfOr] == ParseConstants.O &&
531 filterStringAsByteArray[indexOfOr+1] == ParseConstants.R &&
532 (filterStringAsByteArray[indexOfOr-1] == ParseConstants.WHITESPACE ||
533 filterStringAsByteArray[indexOfOr-1] == ParseConstants.RPAREN) &&
534 (filterStringAsByteArray[indexOfOr+2] == ParseConstants.WHITESPACE ||
535 filterStringAsByteArray[indexOfOr+2] == ParseConstants.LPAREN)) {
536 return true;
537 } else {
538 return false;
539 }
540 } catch (ArrayIndexOutOfBoundsException e) {
541 return false;
542 }
543 }
544
545
546
547
548
549
550
551
552 public static boolean checkForAnd (byte [] filterStringAsByteArray, int indexOfAnd)
553 throws CharacterCodingException {
554
555 try {
556 if (filterStringAsByteArray[indexOfAnd] == ParseConstants.A &&
557 filterStringAsByteArray[indexOfAnd+1] == ParseConstants.N &&
558 filterStringAsByteArray[indexOfAnd+2] == ParseConstants.D &&
559 (filterStringAsByteArray[indexOfAnd-1] == ParseConstants.WHITESPACE ||
560 filterStringAsByteArray[indexOfAnd-1] == ParseConstants.RPAREN) &&
561 (filterStringAsByteArray[indexOfAnd+3] == ParseConstants.WHITESPACE ||
562 filterStringAsByteArray[indexOfAnd+3] == ParseConstants.LPAREN)) {
563 return true;
564 } else {
565 return false;
566 }
567 } catch (ArrayIndexOutOfBoundsException e) {
568 return false;
569 }
570 }
571
572
573
574
575
576
577
578
579 public static boolean checkForSkip (byte [] filterStringAsByteArray, int indexOfSkip)
580 throws CharacterCodingException {
581
582 try {
583 if (filterStringAsByteArray[indexOfSkip] == ParseConstants.S &&
584 filterStringAsByteArray[indexOfSkip+1] == ParseConstants.K &&
585 filterStringAsByteArray[indexOfSkip+2] == ParseConstants.I &&
586 filterStringAsByteArray[indexOfSkip+3] == ParseConstants.P &&
587 (indexOfSkip == 0 ||
588 filterStringAsByteArray[indexOfSkip-1] == ParseConstants.WHITESPACE ||
589 filterStringAsByteArray[indexOfSkip-1] == ParseConstants.RPAREN ||
590 filterStringAsByteArray[indexOfSkip-1] == ParseConstants.LPAREN) &&
591 (filterStringAsByteArray[indexOfSkip+4] == ParseConstants.WHITESPACE ||
592 filterStringAsByteArray[indexOfSkip+4] == ParseConstants.LPAREN)) {
593 return true;
594 } else {
595 return false;
596 }
597 } catch (ArrayIndexOutOfBoundsException e) {
598 return false;
599 }
600 }
601
602
603
604
605
606
607
608
609 public static boolean checkForWhile (byte [] filterStringAsByteArray, int indexOfWhile)
610 throws CharacterCodingException {
611
612 try {
613 if (filterStringAsByteArray[indexOfWhile] == ParseConstants.W &&
614 filterStringAsByteArray[indexOfWhile+1] == ParseConstants.H &&
615 filterStringAsByteArray[indexOfWhile+2] == ParseConstants.I &&
616 filterStringAsByteArray[indexOfWhile+3] == ParseConstants.L &&
617 filterStringAsByteArray[indexOfWhile+4] == ParseConstants.E &&
618 (indexOfWhile == 0 || filterStringAsByteArray[indexOfWhile-1] == ParseConstants.WHITESPACE
619 || filterStringAsByteArray[indexOfWhile-1] == ParseConstants.RPAREN ||
620 filterStringAsByteArray[indexOfWhile-1] == ParseConstants.LPAREN) &&
621 (filterStringAsByteArray[indexOfWhile+5] == ParseConstants.WHITESPACE ||
622 filterStringAsByteArray[indexOfWhile+5] == ParseConstants.LPAREN)) {
623 return true;
624 } else {
625 return false;
626 }
627 } catch (ArrayIndexOutOfBoundsException e) {
628 return false;
629 }
630 }
631
632
633
634
635
636
637
638
639 public static boolean isQuoteUnescaped (byte [] array, int quoteIndex) {
640 if (array == null) {
641 throw new IllegalArgumentException("isQuoteUnescaped called with a null array");
642 }
643
644 if (quoteIndex == array.length - 1 || array[quoteIndex+1] != ParseConstants.SINGLE_QUOTE) {
645 return true;
646 }
647 else {
648 return false;
649 }
650 }
651
652
653
654
655
656
657
658
659
660 public static byte [] removeQuotesFromByteArray (byte [] quotedByteArray) {
661 if (quotedByteArray == null ||
662 quotedByteArray.length < 2 ||
663 quotedByteArray[0] != ParseConstants.SINGLE_QUOTE ||
664 quotedByteArray[quotedByteArray.length - 1] != ParseConstants.SINGLE_QUOTE) {
665 throw new IllegalArgumentException("removeQuotesFromByteArray needs a quoted byte array");
666 } else {
667 byte [] targetString = new byte [quotedByteArray.length - 2];
668 Bytes.putBytes(targetString, 0, quotedByteArray, 1, quotedByteArray.length - 2);
669 return targetString;
670 }
671 }
672
673
674
675
676
677
678
679
680
681
682 public static int convertByteArrayToInt (byte [] numberAsByteArray) {
683
684 long tempResult = ParseFilter.convertByteArrayToLong(numberAsByteArray);
685
686 if (tempResult > Integer.MAX_VALUE) {
687 throw new IllegalArgumentException("Integer Argument too large");
688 } else if (tempResult < Integer.MIN_VALUE) {
689 throw new IllegalArgumentException("Integer Argument too small");
690 }
691
692 int result = (int) tempResult;
693 return result;
694 }
695
696
697
698
699
700
701
702
703
704
705 public static long convertByteArrayToLong (byte [] numberAsByteArray) {
706 if (numberAsByteArray == null) {
707 throw new IllegalArgumentException("convertByteArrayToLong called with a null array");
708 }
709
710 int i = 0;
711 long result = 0;
712 boolean isNegative = false;
713
714 if (numberAsByteArray[i] == ParseConstants.MINUS_SIGN) {
715 i++;
716 isNegative = true;
717 }
718
719 while (i != numberAsByteArray.length) {
720 if (numberAsByteArray[i] < ParseConstants.ZERO ||
721 numberAsByteArray[i] > ParseConstants.NINE) {
722 throw new IllegalArgumentException("Byte Array should only contain digits");
723 }
724 result = result*10 + (numberAsByteArray[i] - ParseConstants.ZERO);
725 if (result < 0) {
726 throw new IllegalArgumentException("Long Argument too large");
727 }
728 i++;
729 }
730
731 if (isNegative) {
732 return -result;
733 } else {
734 return result;
735 }
736 }
737
738
739
740
741
742
743
744
745
746
747
748 public static boolean convertByteArrayToBoolean (byte [] booleanAsByteArray) {
749 if (booleanAsByteArray == null) {
750 throw new IllegalArgumentException("convertByteArrayToBoolean called with a null array");
751 }
752
753 if (booleanAsByteArray.length == 4 &&
754 (booleanAsByteArray[0] == 't' || booleanAsByteArray[0] == 'T') &&
755 (booleanAsByteArray[1] == 'r' || booleanAsByteArray[1] == 'R') &&
756 (booleanAsByteArray[2] == 'u' || booleanAsByteArray[2] == 'U') &&
757 (booleanAsByteArray[3] == 'e' || booleanAsByteArray[3] == 'E')) {
758 return true;
759 }
760 else if (booleanAsByteArray.length == 5 &&
761 (booleanAsByteArray[0] == 'f' || booleanAsByteArray[0] == 'F') &&
762 (booleanAsByteArray[1] == 'a' || booleanAsByteArray[1] == 'A') &&
763 (booleanAsByteArray[2] == 'l' || booleanAsByteArray[2] == 'L') &&
764 (booleanAsByteArray[3] == 's' || booleanAsByteArray[3] == 'S') &&
765 (booleanAsByteArray[4] == 'e' || booleanAsByteArray[4] == 'E')) {
766 return false;
767 }
768 else {
769 throw new IllegalArgumentException("Incorrect Boolean Expression");
770 }
771 }
772
773
774
775
776
777
778
779 public static CompareFilter.CompareOp createCompareOp (byte [] compareOpAsByteArray) {
780 ByteBuffer compareOp = ByteBuffer.wrap(compareOpAsByteArray);
781 if (compareOp.equals(ParseConstants.LESS_THAN_BUFFER))
782 return CompareOp.LESS;
783 else if (compareOp.equals(ParseConstants.LESS_THAN_OR_EQUAL_TO_BUFFER))
784 return CompareOp.LESS_OR_EQUAL;
785 else if (compareOp.equals(ParseConstants.GREATER_THAN_BUFFER))
786 return CompareOp.GREATER;
787 else if (compareOp.equals(ParseConstants.GREATER_THAN_OR_EQUAL_TO_BUFFER))
788 return CompareOp.GREATER_OR_EQUAL;
789 else if (compareOp.equals(ParseConstants.NOT_EQUAL_TO_BUFFER))
790 return CompareOp.NOT_EQUAL;
791 else if (compareOp.equals(ParseConstants.EQUAL_TO_BUFFER))
792 return CompareOp.EQUAL;
793 else
794 throw new IllegalArgumentException("Invalid compare operator");
795 }
796
797
798
799
800
801
802
803 public static ByteArrayComparable createComparator (byte [] comparator) {
804 if (comparator == null)
805 throw new IllegalArgumentException("Incorrect Comparator");
806 byte [][] parsedComparator = ParseFilter.parseComparator(comparator);
807 byte [] comparatorType = parsedComparator[0];
808 byte [] comparatorValue = parsedComparator[1];
809
810
811 if (Bytes.equals(comparatorType, ParseConstants.binaryType))
812 return new BinaryComparator(comparatorValue);
813 else if (Bytes.equals(comparatorType, ParseConstants.binaryPrefixType))
814 return new BinaryPrefixComparator(comparatorValue);
815 else if (Bytes.equals(comparatorType, ParseConstants.regexStringType))
816 return new RegexStringComparator(new String(comparatorValue, StandardCharsets.UTF_8));
817 else if (Bytes.equals(comparatorType, ParseConstants.regexStringNoCaseType))
818 return new RegexStringComparator(new String(comparatorValue, StandardCharsets.UTF_8),
819 Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
820 else if (Bytes.equals(comparatorType, ParseConstants.substringType))
821 return new SubstringComparator(new String(comparatorValue, StandardCharsets.UTF_8));
822 else
823 throw new IllegalArgumentException("Incorrect comparatorType");
824 }
825
826
827
828
829
830
831
832 public static byte [][] parseComparator (byte [] comparator) {
833 final int index = KeyValue.getDelimiter(comparator, 0, comparator.length, ParseConstants.COLON);
834 if (index == -1) {
835 throw new IllegalArgumentException("Incorrect comparator");
836 }
837
838 byte [][] result = new byte [2][0];
839 result[0] = new byte [index];
840 System.arraycopy(comparator, 0, result[0], 0, index);
841
842 final int len = comparator.length - (index + 1);
843 result[1] = new byte[len];
844 System.arraycopy(comparator, index + 1, result[1], 0, len);
845
846 return result;
847 }
848
849
850
851
852 public Set<String> getSupportedFilters () {
853 return filterHashMap.keySet();
854 }
855
856
857
858
859
860 public static Map<String, String> getAllFilters() {
861 return Collections.unmodifiableMap(filterHashMap);
862 }
863
864
865
866
867
868
869
870
871 public static void registerFilter(String name, String filterClass) {
872 if(LOG.isInfoEnabled())
873 LOG.info("Registering new filter " + name);
874
875 filterHashMap.put(name, filterClass);
876 }
877 }