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