This is an automated email from the ASF dual-hosted git repository.

domgarguilo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/accumulo-access.git


The following commit(s) were added to refs/heads/main by this push:
     new 261b5c3  Miscellaneous Improvements (#27)
261b5c3 is described below

commit 261b5c303df3bae0d311689e14e1e029ae43d849
Author: Dom G <domgargu...@apache.org>
AuthorDate: Thu Oct 26 15:17:41 2023 -0400

    Miscellaneous Improvements (#27)
    
    * Misc cleanup
    * Remove mentions of mutations and visibility
    * Add byte constant class and helper methods
    
    ---------
    
    Co-authored-by: Dave Marion <dlmar...@apache.org>
    Co-authored-by: Keith Turner <ktur...@apache.org>
---
 README.md                                          |  2 +-
 .../apache/accumulo/access/AccessEvaluator.java    | 10 ++--
 .../accumulo/access/AccessEvaluatorImpl.java       | 67 +++++++++++-----------
 .../apache/accumulo/access/AccessExpression.java   | 18 +++---
 .../accumulo/access/AccessExpressionImpl.java      | 21 +++----
 .../java/org/apache/accumulo/access/AeNode.java    |  7 ++-
 .../org/apache/accumulo/access/Authorizations.java |  1 +
 .../java/org/apache/accumulo/access/ByteUtils.java | 58 +++++++++++++++++++
 .../org/apache/accumulo/access/BytesWrapper.java   | 14 ++++-
 .../java/org/apache/accumulo/access/Parser.java    | 14 +++--
 .../java/org/apache/accumulo/access/Tokenizer.java | 49 +++++++---------
 11 files changed, 165 insertions(+), 96 deletions(-)

diff --git a/README.md b/README.md
index e43991c..a754d7f 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ Apache Accumulo [ColumnVisibility][1] and 
[VisibilityEvaluator][2] classes.
 This functionality is provided in a standalone java library that has no
 dependencies (for example no Hadoop, Zookeeper, Thrift, etc dependencies).
 
-For a conceptual overview of what an access expression is see the
+For a conceptual overview of what an access expression is, see the
 [specification](SPECIFICATION.md) document. See the [getting started
 guide](contrib/getting-started/README.md) for an example of how to use
 this java library.
diff --git a/src/main/java/org/apache/accumulo/access/AccessEvaluator.java 
b/src/main/java/org/apache/accumulo/access/AccessEvaluator.java
index ecf1f3e..c0123ed 100644
--- a/src/main/java/org/apache/accumulo/access/AccessEvaluator.java
+++ b/src/main/java/org/apache/accumulo/access/AccessEvaluator.java
@@ -86,7 +86,7 @@ public interface AccessEvaluator {
 
   interface AuthorizationsBuilder {
 
-    FinalBuilder authorizations(Authorizations authorizations);
+    EvaluatorBuilder authorizations(Authorizations authorizations);
 
     /**
      * Allows providing multiple sets of authorizations. Each expression will 
be evaluated
@@ -139,20 +139,20 @@ public interface AccessEvaluator {
      *
      *
      */
-    FinalBuilder authorizations(Collection<Authorizations> authorizations);
+    EvaluatorBuilder authorizations(Collection<Authorizations> authorizations);
 
     /**
      * Allows specifying a single set of authorizations.
      */
-    FinalBuilder authorizations(String... authorizations);
+    EvaluatorBuilder authorizations(String... authorizations);
 
     /**
      * Allows specifying an authorizer that is analogous to a single set of 
authorization.
      */
-    FinalBuilder authorizations(Authorizer authorizer);
+    EvaluatorBuilder authorizations(Authorizer authorizer);
   }
 
-  interface FinalBuilder {
+  interface EvaluatorBuilder {
     AccessEvaluator build();
   }
 
diff --git a/src/main/java/org/apache/accumulo/access/AccessEvaluatorImpl.java 
b/src/main/java/org/apache/accumulo/access/AccessEvaluatorImpl.java
index c27e9da..eb25206 100644
--- a/src/main/java/org/apache/accumulo/access/AccessEvaluatorImpl.java
+++ b/src/main/java/org/apache/accumulo/access/AccessEvaluatorImpl.java
@@ -21,6 +21,10 @@ package org.apache.accumulo.access;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.stream.Collectors.toSet;
 import static java.util.stream.Collectors.toUnmodifiableList;
+import static org.apache.accumulo.access.ByteUtils.BACKSLASH;
+import static org.apache.accumulo.access.ByteUtils.QUOTE;
+import static org.apache.accumulo.access.ByteUtils.isQuoteOrSlash;
+import static org.apache.accumulo.access.ByteUtils.isQuoteSymbol;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -43,14 +47,14 @@ class AccessEvaluatorImpl implements AccessEvaluator {
             .map(auth -> AccessEvaluatorImpl.escape(auth, 
false)).map(BytesWrapper::new)
             .collect(toSet()))
         .map(escapedAuths -> (Predicate<BytesWrapper>) escapedAuths::contains)
-        .collect(Collectors.toList());
+        .collect(Collectors.toUnmodifiableList());
   }
 
   static String unescape(BytesWrapper auth) {
     int escapeCharCount = 0;
     for (int i = 0; i < auth.length(); i++) {
       byte b = auth.byteAt(i);
-      if (b == '"' || b == '\\') {
+      if (isQuoteOrSlash(b)) {
         escapeCharCount++;
       }
     }
@@ -67,12 +71,13 @@ class AccessEvaluatorImpl implements AccessEvaluator {
         if (b == '\\') {
           i++;
           b = auth.byteAt(i);
-          if (b != '"' && b != '\\') {
+          if (!isQuoteOrSlash(b)) {
             throw new IllegalArgumentException("Illegal escape sequence in 
auth : " + auth);
           }
-        } else if (b == '"') {
+        } else if (isQuoteSymbol(b)) {
           // should only see quote after a slash
-          throw new IllegalArgumentException("Illegal escape sequence in auth 
: " + auth);
+          throw new IllegalArgumentException(
+              "Illegal character after slash in auth String : " + auth);
         }
 
         unescapedCopy[pos++] = b;
@@ -88,31 +93,31 @@ class AccessEvaluatorImpl implements AccessEvaluator {
    * Properly escapes an authorization string. The string can be quoted if 
desired.
    *
    * @param auth authorization string, as UTF-8 encoded bytes
-   * @param quote true to wrap escaped authorization in quotes
+   * @param shouldQuote true to wrap escaped authorization in quotes
    * @return escaped authorization string
    */
-  static byte[] escape(byte[] auth, boolean quote) {
+  static byte[] escape(byte[] auth, boolean shouldQuote) {
     int escapeCount = 0;
 
     for (byte value : auth) {
-      if (value == '"' || value == '\\') {
+      if (isQuoteOrSlash(value)) {
         escapeCount++;
       }
     }
 
-    if (escapeCount > 0 || quote) {
-      byte[] escapedAuth = new byte[auth.length + escapeCount + (quote ? 2 : 
0)];
-      int index = quote ? 1 : 0;
+    if (escapeCount > 0 || shouldQuote) {
+      byte[] escapedAuth = new byte[auth.length + escapeCount + (shouldQuote ? 
2 : 0)];
+      int index = shouldQuote ? 1 : 0;
       for (byte b : auth) {
-        if (b == '"' || b == '\\') {
-          escapedAuth[index++] = '\\';
+        if (isQuoteOrSlash(b)) {
+          escapedAuth[index++] = BACKSLASH;
         }
         escapedAuth[index++] = b;
       }
 
-      if (quote) {
-        escapedAuth[0] = '"';
-        escapedAuth[escapedAuth.length - 1] = '"';
+      if (shouldQuote) {
+        escapedAuth[0] = QUOTE;
+        escapedAuth[escapedAuth.length - 1] = QUOTE;
       }
 
       auth = escapedAuth;
@@ -121,25 +126,19 @@ class AccessEvaluatorImpl implements AccessEvaluator {
   }
 
   @Override
-  public boolean canAccess(String expression) throws IllegalArgumentException {
-
+  public boolean canAccess(String expression) throws 
IllegalAccessExpressionException {
     return evaluate(new AccessExpressionImpl(expression));
-
   }
 
   @Override
-  public boolean canAccess(byte[] expression) throws IllegalArgumentException {
-
+  public boolean canAccess(byte[] expression) throws 
IllegalAccessExpressionException {
     return evaluate(new AccessExpressionImpl(expression));
-
   }
 
   @Override
-  public boolean canAccess(AccessExpression expression) throws 
IllegalArgumentException {
+  public boolean canAccess(AccessExpression expression) throws 
IllegalAccessExpressionException {
     if (expression instanceof AccessExpressionImpl) {
-
       return evaluate((AccessExpressionImpl) expression);
-
     } else {
       return canAccess(expression.getExpression());
     }
@@ -147,12 +146,12 @@ class AccessEvaluatorImpl implements AccessEvaluator {
 
   public boolean evaluate(AccessExpressionImpl accessExpression)
       throws IllegalAccessExpressionException {
-    // The VisibilityEvaluator computes a trie from the given Authorizations, 
that ColumnVisibility
-    // expressions can be evaluated against.
+    // The AccessEvaluator computes a trie from the given Authorizations, that 
AccessExpressions can
+    // be evaluated against.
     return 
authorizedPredicates.stream().allMatch(accessExpression.aeNode::canAccess);
   }
 
-  private static class BuilderImpl implements AuthorizationsBuilder, 
FinalBuilder {
+  private static class BuilderImpl implements AuthorizationsBuilder, 
EvaluatorBuilder {
 
     private Authorizer authorizationsChecker;
 
@@ -178,14 +177,14 @@ class AccessEvaluatorImpl implements AccessEvaluator {
     }
 
     @Override
-    public FinalBuilder authorizations(Authorizations authorizations) {
+    public EvaluatorBuilder authorizations(Authorizations authorizations) {
       setAuthorizations(authorizations.asSet().stream().map(auth -> 
auth.getBytes(UTF_8))
           .collect(toUnmodifiableList()));
       return this;
     }
 
     @Override
-    public FinalBuilder authorizations(Collection<Authorizations> 
authorizationSets) {
+    public EvaluatorBuilder authorizations(Collection<Authorizations> 
authorizationSets) {
       setAuthorizations(authorizationSets
           .stream().map(authorizations -> authorizations.asSet().stream()
               .map(auth -> auth.getBytes(UTF_8)).collect(toUnmodifiableList()))
@@ -194,14 +193,14 @@ class AccessEvaluatorImpl implements AccessEvaluator {
     }
 
     @Override
-    public FinalBuilder authorizations(String... authorizations) {
+    public EvaluatorBuilder authorizations(String... authorizations) {
       setAuthorizations(Stream.of(authorizations).map(auth -> 
auth.getBytes(UTF_8))
           .collect(toUnmodifiableList()));
       return this;
     }
 
     @Override
-    public FinalBuilder authorizations(Authorizer authorizationChecker) {
+    public EvaluatorBuilder authorizations(Authorizer authorizationChecker) {
       if (authorizationSets != null) {
         throw new IllegalStateException("Cannot set checker and 
authorizations");
       }
@@ -212,7 +211,8 @@ class AccessEvaluatorImpl implements AccessEvaluator {
     @Override
     public AccessEvaluator build() {
       if (authorizationSets != null ^ authorizationsChecker == null) {
-        throw new IllegalStateException();
+        throw new IllegalStateException(
+            "Exactly one of authorizationSets or authorizationsChecker must be 
set, not both or none.");
       }
 
       AccessEvaluator accessEvaluator;
@@ -230,4 +230,5 @@ class AccessEvaluatorImpl implements AccessEvaluator {
   public static AuthorizationsBuilder builder() {
     return new BuilderImpl();
   }
+
 }
diff --git a/src/main/java/org/apache/accumulo/access/AccessExpression.java 
b/src/main/java/org/apache/accumulo/access/AccessExpression.java
index fa20807..c940e7c 100644
--- a/src/main/java/org/apache/accumulo/access/AccessExpression.java
+++ b/src/main/java/org/apache/accumulo/access/AccessExpression.java
@@ -71,14 +71,14 @@ public interface AccessExpression {
    * <p>
    * As an example of deduplication, the expression {@code X&Y&X} is 
equivalent to {@code X&Y}
    *
-   * @return A normalized version of the visibility expression that removes 
duplicates and orders
-   *         the expression in a consistent way.
+   * @return A normalized version of the access expression that removes 
duplicates and orders the
+   *         expression in a consistent way.
    */
   String normalize();
 
   /**
-   * @return the unique authorizations that occur in the expression. For 
example, for the expression
-   *         {@code (A&B)|(A&C)|(A&D)} this method would return {@code 
[A,B,C,D]]}
+   * @return the unique set of authorizations that occur in the expression. 
For example, for the
+   *         expression {@code (A&B)|(A&C)|(A&D)}, this method would return 
{@code [A,B,C,D]}.
    */
   Authorizations getAuthorizations();
 
@@ -94,7 +94,7 @@ public interface AccessExpression {
   }
 
   /**
-   * @return an empty VisibilityExpression.
+   * @return an empty AccessExpression.
    */
   static AccessExpression of() {
     return AccessExpressionImpl.EMPTY;
@@ -104,8 +104,8 @@ public interface AccessExpression {
    * Authorizations occurring in an access expression can only contain the 
characters listed in the
    * <a href=
    * 
"https://github.com/apache/accumulo-access/blob/main/SPECIFICATION.md";>specification</a>
 unless
-   * quoted. Use this method to quote authorizations that occur in an access 
expression. This method
-   * will only quote if it is needed.
+   * quoted (surrounded by quotation marks). Use this method to quote 
authorizations that occur in
+   * an access expression. This method will only quote if it is needed.
    */
   static byte[] quote(byte[] authorization) {
     return AccessExpressionImpl.quote(authorization);
@@ -115,8 +115,8 @@ public interface AccessExpression {
    * Authorizations occurring in an access expression can only contain the 
characters listed in the
    * <a href=
    * 
"https://github.com/apache/accumulo-access/blob/main/SPECIFICATION.md";>specification</a>
 unless
-   * quoted. Use this method to quote authorizations that occur in an access 
expression. This method
-   * will only quote if it is needed.
+   * quoted (surrounded by quotation marks). Use this method to quote 
authorizations that occur in
+   * an access expression. This method will only quote if it is needed.
    */
   static String quote(String authorization) {
     return AccessExpressionImpl.quote(authorization);
diff --git a/src/main/java/org/apache/accumulo/access/AccessExpressionImpl.java 
b/src/main/java/org/apache/accumulo/access/AccessExpressionImpl.java
index 3285f5a..3f82004 100644
--- a/src/main/java/org/apache/accumulo/access/AccessExpressionImpl.java
+++ b/src/main/java/org/apache/accumulo/access/AccessExpressionImpl.java
@@ -60,10 +60,12 @@ class AccessExpressionImpl implements AccessExpression {
   }
 
   /**
-   * Creates a column visibility for a Mutation.
+   * Creates an AccessExpression.
    *
-   * @param expression An expression of the rights needed to see this 
mutation. The expression
-   *        syntax is defined at the class-level documentation
+   * @param expression An expression of the rights needed to see specific 
data. The expression
+   *        syntax is defined within the <a href=
+   *        
"https://github.com/apache/accumulo-access/blob/main/SPECIFICATION.md";>specification
+   *        doc</a>
    */
   AccessExpressionImpl(String expression) {
     this(expression.getBytes(UTF_8));
@@ -71,9 +73,9 @@ class AccessExpressionImpl implements AccessExpression {
   }
 
   /**
-   * Creates a column visibility for a Mutation from a string already encoded 
in UTF-8 bytes.
+   * Creates an AccessExpression from a string already encoded in UTF-8 bytes.
    *
-   * @param expression visibility expression, encoded as UTF-8 bytes
+   * @param expression AccessExpression, encoded as UTF-8 bytes
    * @see #AccessExpressionImpl(String)
    */
   AccessExpressionImpl(byte[] expression) {
@@ -98,11 +100,11 @@ class AccessExpressionImpl implements AccessExpression {
   }
 
   /**
-   * Compares two ColumnVisibilities for string equivalence, not as a 
meaningful comparison of terms
+   * Compares two AccessExpressions for string equivalence, not as a 
meaningful comparison of terms
    * and conditions.
    *
-   * @param otherLe other column visibility
-   * @return true if this visibility equals the other via string comparison
+   * @param otherLe other AccessExpression
+   * @return true if this AccessExpression equals the other via string 
comparison
    */
   boolean equals(AccessExpressionImpl otherLe) {
     return Arrays.equals(expression, otherLe.expression);
@@ -118,8 +120,7 @@ class AccessExpressionImpl implements AccessExpression {
   }
 
   /**
-   * Properly quotes terms in a column visibility expression. If no quoting is 
needed, then nothing
-   * is done.
+   * Properly quotes terms in an AccessExpression. If no quoting is needed, 
then nothing is done.
    *
    * @param term term to quote, encoded as UTF-8 bytes
    * @return quoted term (unquoted if unnecessary), encoded as UTF-8 bytes
diff --git a/src/main/java/org/apache/accumulo/access/AeNode.java 
b/src/main/java/org/apache/accumulo/access/AeNode.java
index 65023b4..dc04f6f 100644
--- a/src/main/java/org/apache/accumulo/access/AeNode.java
+++ b/src/main/java/org/apache/accumulo/access/AeNode.java
@@ -18,6 +18,9 @@
  */
 package org.apache.accumulo.access;
 
+import static org.apache.accumulo.access.ByteUtils.AND_OPERATOR;
+import static org.apache.accumulo.access.ByteUtils.OR_OPERATOR;
+
 import java.util.List;
 import java.util.TreeSet;
 import java.util.function.Consumer;
@@ -300,9 +303,9 @@ abstract class AeNode implements Comparable<AeNode> {
 
   static AeNode of(byte operator, List<AeNode> children) {
     switch (operator) {
-      case '&':
+      case AND_OPERATOR:
         return new AndNode(children);
-      case '|':
+      case OR_OPERATOR:
         return new OrNode(children);
       default:
         throw new IllegalArgumentException();
diff --git a/src/main/java/org/apache/accumulo/access/Authorizations.java 
b/src/main/java/org/apache/accumulo/access/Authorizations.java
index cbeccb9..33f3f87 100644
--- a/src/main/java/org/apache/accumulo/access/Authorizations.java
+++ b/src/main/java/org/apache/accumulo/access/Authorizations.java
@@ -22,6 +22,7 @@ import java.util.Collection;
 import java.util.Set;
 
 /**
+ * A collection of authorization strings.
  *
  * @since 1.0.0
  */
diff --git a/src/main/java/org/apache/accumulo/access/ByteUtils.java 
b/src/main/java/org/apache/accumulo/access/ByteUtils.java
new file mode 100644
index 0000000..4f75410
--- /dev/null
+++ b/src/main/java/org/apache/accumulo/access/ByteUtils.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.accumulo.access;
+
+/**
+ * This class exists to avoid repeat conversions from byte to char as well as 
to provide helper
+ * methods for comparing them.
+ */
+public final class ByteUtils {
+  public static final byte QUOTE = (byte) '"';
+  public static final byte BACKSLASH = (byte) '\\';
+  public static final byte AND_OPERATOR = (byte) '&';
+  public static final byte OR_OPERATOR = (byte) '|';
+
+  private ByteUtils() {
+    // private constructor to prevent instantiation
+  }
+
+  public static boolean isQuoteSymbol(byte b) {
+    return b == QUOTE;
+  }
+
+  public static boolean isBackslashSymbol(byte b) {
+    return b == BACKSLASH;
+  }
+
+  public static boolean isQuoteOrSlash(byte b) {
+    return isQuoteSymbol(b) || isBackslashSymbol(b);
+  }
+
+  public static boolean isAndOperator(byte b) {
+    return b == AND_OPERATOR;
+  }
+
+  public static boolean isOrOperator(byte b) {
+    return b == OR_OPERATOR;
+  }
+
+  public static boolean isAndOrOperator(byte b) {
+    return isAndOperator(b) || isOrOperator(b);
+  }
+}
diff --git a/src/main/java/org/apache/accumulo/access/BytesWrapper.java 
b/src/main/java/org/apache/accumulo/access/BytesWrapper.java
index ff5bb07..998a452 100644
--- a/src/main/java/org/apache/accumulo/access/BytesWrapper.java
+++ b/src/main/java/org/apache/accumulo/access/BytesWrapper.java
@@ -53,9 +53,17 @@ class BytesWrapper implements Comparable<BytesWrapper> {
    */
   public BytesWrapper(byte[] data, int offset, int length) {
 
-    if (offset < 0 || offset > data.length || length < 0 || (offset + length) 
> data.length) {
-      throw new IllegalArgumentException(" Bad offset and/or length 
data.length = " + data.length
-          + " offset = " + offset + " length = " + length);
+    if (offset < 0 || offset > data.length) {
+      throw new IllegalArgumentException(
+          "Offset out of bounds. data.length = " + data.length + ", offset = " 
+ offset);
+    }
+    if (length < 0) {
+      throw new IllegalArgumentException("Length cannot be negative. length = 
" + length);
+    }
+    if ((offset + length) > data.length) {
+      throw new IllegalArgumentException(
+          "Sum of offset and length exceeds data length. data.length = " + 
data.length
+              + ", offset = " + offset + ", length = " + length);
     }
 
     this.data = data;
diff --git a/src/main/java/org/apache/accumulo/access/Parser.java 
b/src/main/java/org/apache/accumulo/access/Parser.java
index 8eb822e..17b7f7a 100644
--- a/src/main/java/org/apache/accumulo/access/Parser.java
+++ b/src/main/java/org/apache/accumulo/access/Parser.java
@@ -18,12 +18,18 @@
  */
 package org.apache.accumulo.access;
 
+import static org.apache.accumulo.access.ByteUtils.isAndOrOperator;
+
 import java.util.ArrayList;
 
 /**
  * Code for parsing an access expression and creating a parse tree of type 
{@link AeNode}
  */
 final class Parser {
+
+  public static final byte OPEN_PAREN = (byte) '(';
+  public static final byte CLOSE_PAREN = (byte) ')';
+
   public static AeNode parseAccessExpression(byte[] expression) {
 
     Tokenizer tokenizer = new Tokenizer(expression);
@@ -46,7 +52,7 @@ final class Parser {
 
     AeNode first = parseParenExpressionOrAuthorization(tokenizer);
 
-    if (tokenizer.hasNext() && (tokenizer.peek() == '&' || tokenizer.peek() == 
'|')) {
+    if (tokenizer.hasNext() && isAndOrOperator(tokenizer.peek())) {
       var nodes = new ArrayList<AeNode>();
       nodes.add(first);
 
@@ -59,7 +65,7 @@ final class Parser {
 
       } while (tokenizer.hasNext() && tokenizer.peek() == operator);
 
-      if (tokenizer.hasNext() && (tokenizer.peek() == '|' || tokenizer.peek() 
== '&')) {
+      if (tokenizer.hasNext() && isAndOrOperator(tokenizer.peek())) {
         // A case of mixed operators, lets give a clear error message
         tokenizer.error("Cannot mix '|' and '&'");
       }
@@ -76,10 +82,10 @@ final class Parser {
           .error("Expected a '(' character or an authorization token instead 
saw end of input");
     }
 
-    if (tokenizer.peek() == '(') {
+    if (tokenizer.peek() == OPEN_PAREN) {
       tokenizer.advance();
       var node = parseExpression(tokenizer);
-      tokenizer.next(')');
+      tokenizer.next(CLOSE_PAREN);
       return node;
     } else {
       return AeNode.of(tokenizer.nextAuthorization());
diff --git a/src/main/java/org/apache/accumulo/access/Tokenizer.java 
b/src/main/java/org/apache/accumulo/access/Tokenizer.java
index de5e21f..b5e3f14 100644
--- a/src/main/java/org/apache/accumulo/access/Tokenizer.java
+++ b/src/main/java/org/apache/accumulo/access/Tokenizer.java
@@ -19,6 +19,11 @@
 package org.apache.accumulo.access;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.accumulo.access.ByteUtils.isBackslashSymbol;
+import static org.apache.accumulo.access.ByteUtils.isQuoteOrSlash;
+import static org.apache.accumulo.access.ByteUtils.isQuoteSymbol;
+
+import java.util.stream.IntStream;
 
 /**
  * A simple wrapper around a byte array that keeps some state and provides 
high level operations to
@@ -30,37 +35,24 @@ final class Tokenizer {
   private static final boolean[] validAuthChars = new boolean[256];
 
   static {
-    for (int i = 0; i < 256; i++) {
-      validAuthChars[i] = false;
-    }
-
-    for (int i = 'a'; i <= 'z'; i++) {
-      validAuthChars[i] = true;
-    }
+    IntStream.range(0, 256).forEach(i -> validAuthChars[i] = false);
 
-    for (int i = 'A'; i <= 'Z'; i++) {
-      validAuthChars[i] = true;
-    }
-
-    for (int i = '0'; i <= '9'; i++) {
-      validAuthChars[i] = true;
-    }
+    IntStream numbers = IntStream.rangeClosed('0', '9');
+    IntStream letters =
+        IntStream.concat(IntStream.rangeClosed('A', 'Z'), 
IntStream.rangeClosed('a', 'z'));
+    IntStream.concat(numbers, letters).forEach(i -> validAuthChars[i] = true);
 
-    validAuthChars['_'] = true;
-    validAuthChars['-'] = true;
-    validAuthChars[':'] = true;
-    validAuthChars['.'] = true;
-    validAuthChars['/'] = true;
+    "_-:./".chars().forEach(c -> validAuthChars[c] = true);
   }
 
   static boolean isValidAuthChar(byte b) {
     return validAuthChars[0xff & b];
   }
 
-  private byte[] expression;
+  private final byte[] expression;
   private int index;
 
-  private AuthorizationToken authorizationToken = new AuthorizationToken();
+  private final AuthorizationToken authorizationToken = new 
AuthorizationToken();
 
   static class AuthorizationToken {
     byte[] data;
@@ -81,13 +73,13 @@ final class Tokenizer {
     index++;
   }
 
-  public void next(char expected) {
+  public void next(byte expected) {
     if (!hasNext()) {
-      error("Expected '" + expected + "' instead saw end of input");
+      error("Expected '" + (char) expected + "' instead saw end of input");
     }
 
     if (expression[index] != expected) {
-      error("Expected '" + expected + "' instead saw '" + (char) 
(expression[index]) + "'");
+      error("Expected '" + (char) expected + "' instead saw '" + (char) 
(expression[index]) + "'");
     }
     index++;
   }
@@ -105,14 +97,13 @@ final class Tokenizer {
   }
 
   AuthorizationToken nextAuthorization() {
-    if (expression[index] == '"') {
+    if (isQuoteSymbol(expression[index])) {
       int start = ++index;
 
-      while (index < expression.length && expression[index] != '"') {
-        if (expression[index] == '\\') {
+      while (index < expression.length && !isQuoteSymbol(expression[index])) {
+        if (isBackslashSymbol(expression[index])) {
           index++;
-          if (index == expression.length
-              || (expression[index] != '\\' && expression[index] != '"')) {
+          if (index == expression.length || 
!isQuoteOrSlash(expression[index])) {
             error("Invalid escaping within quotes", index - 1);
           }
         }

Reply via email to