incubator-blur-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From amccu...@apache.org
Subject [3/3] git commit: Fixed BLUR-434
Date Mon, 15 Jun 2015 13:39:29 GMT
Fixed BLUR-434


Project: http://git-wip-us.apache.org/repos/asf/incubator-blur/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-blur/commit/49390b52
Tree: http://git-wip-us.apache.org/repos/asf/incubator-blur/tree/49390b52
Diff: http://git-wip-us.apache.org/repos/asf/incubator-blur/diff/49390b52

Branch: refs/heads/master
Commit: 49390b52a76971037ec0027c2b039a29c1bd4c75
Parents: 90625d0
Author: Aaron McCurry <amccurry@gmail.com>
Authored: Mon Jun 15 09:39:02 2015 -0400
Committer: Aaron McCurry <amccurry@gmail.com>
Committed: Mon Jun 15 09:39:02 2015 -0400

----------------------------------------------------------------------
 .../org/apache/blur/manager/IndexManager.java   |   3 +-
 .../manager/writer/BlurIndexSimpleWriter.java   |   3 +-
 .../blur/server/BlurSecureIndexSearcher.java    |   5 +-
 .../IndexSearcherCloseableSecureBase.java       |   3 +-
 .../org/apache/blur/server/TableContext.java    |   5 +-
 .../server/BlurSecureIndexSearcherTest.java     |   5 +-
 blur-document-security/pom.xml                  | 169 ++++++
 .../lucene/security/DocumentAuthorizations.java |  39 ++
 .../lucene/security/DocumentVisibility.java     |  35 ++
 .../security/DocumentVisibilityEvaluator.java   |  40 ++
 .../security/accumulo/ArrayByteSequence.java    | 171 ++++++
 .../accumulo/AuthorizationContainer.java        |  36 ++
 .../security/accumulo/Authorizations.java       | 340 +++++++++++
 .../security/accumulo/BadArgumentException.java |  31 +
 .../blur/lucene/security/accumulo/Base64.java   |  82 +++
 .../lucene/security/accumulo/ByteSequence.java  | 167 ++++++
 .../security/accumulo/ColumnVisibility.java     | 568 +++++++++++++++++++
 .../blur/lucene/security/accumulo/UTFUtil.java  |  46 ++
 .../security/accumulo/VisibilityEvaluator.java  | 145 +++++
 .../accumulo/VisibilityParseException.java      |  51 ++
 .../analysis/DocumentVisibilityTokenStream.java | 108 ++++
 .../document/DocumentVisiblityField.java        |  78 +++
 .../security/index/AccessControlFactory.java    |  32 ++
 .../security/index/AccessControlReader.java     |  57 ++
 .../security/index/AccessControlWriter.java     |  52 ++
 .../index/DocValueAccessControlFactory.java     | 262 +++++++++
 .../index/FilterAccessControlFactory.java       | 288 ++++++++++
 .../blur/lucene/security/index/ReadType.java    |  21 +
 .../security/index/SecureAtomicReader.java      | 416 ++++++++++++++
 .../security/index/SecureDirectoryReader.java   |  66 +++
 ...etDocumentVisibilityFilterCacheStrategy.java | 152 +++++
 .../search/DocumentVisibilityFilter.java        | 232 ++++++++
 .../DocumentVisibilityFilterCacheStrategy.java  |  39 ++
 .../security/search/SecureIndexSearcher.java    | 170 ++++++
 .../blur/lucene/security/IndexSearcherTest.java | 235 ++++++++
 .../apache/blur/lucene/security/LoadTest.java   | 122 ++++
 .../DocumentVisibilityTokenStreamTest.java      |  50 ++
 .../index/DocValueSecureAtomicReaderTest.java   |  31 +
 .../index/FilterSecureAtomicReaderTest.java     |  31 +
 .../index/SecureAtomicReaderTestBase.java       | 333 +++++++++++
 .../blur/mapreduce/lib/BlurMapReduceUtil.java   |   3 +-
 .../type/AclDiscoverFieldTypeDefinition.java    |   3 +-
 .../type/AclReadFieldTypeDefinition.java        |   3 +-
 .../AclDiscoverFieldTypeDefinitionTest.java     |   7 +-
 .../type/AclReadFieldTypeDefinitionTest.java    |   7 +-
 blur-store/pom.xml                              |  10 +-
 .../org/apache/blur/index/AtomicReaderUtil.java |   3 +-
 .../lucene-document-security-0.1.4-sources.jar  | Bin 44017 -> 0 bytes
 .../lucene-document-security-0.1.4-tests.jar    | Bin 18478 -> 0 bytes
 .../0.1.4/lucene-document-security-0.1.4.jar    | Bin 81781 -> 0 bytes
 .../0.1.4/lucene-document-security-0.1.4.pom    | 128 -----
 pom.xml                                         |   4 +
 52 files changed, 4723 insertions(+), 164 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-core/src/main/java/org/apache/blur/manager/IndexManager.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/manager/IndexManager.java b/blur-core/src/main/java/org/apache/blur/manager/IndexManager.java
index d42218d..1cba196 100644
--- a/blur-core/src/main/java/org/apache/blur/manager/IndexManager.java
+++ b/blur-core/src/main/java/org/apache/blur/manager/IndexManager.java
@@ -46,8 +46,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLongArray;
 
-import lucene.security.index.SecureDirectoryReader;
-
 import org.apache.blur.analysis.FieldManager;
 import org.apache.blur.concurrent.Executors;
 import org.apache.blur.index.AtomicReaderUtil;
@@ -60,6 +58,7 @@ import org.apache.blur.lucene.search.FacetExecutor;
 import org.apache.blur.lucene.search.FacetQuery;
 import org.apache.blur.lucene.search.IndexSearcherCloseable;
 import org.apache.blur.lucene.search.StopExecutionCollector.StopExecutionCollectorException;
+import org.apache.blur.lucene.security.index.SecureDirectoryReader;
 import org.apache.blur.manager.clusterstatus.ClusterStatus;
 import org.apache.blur.manager.results.BlurResultIterable;
 import org.apache.blur.manager.results.BlurResultIterableSearcher;

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-core/src/main/java/org/apache/blur/manager/writer/BlurIndexSimpleWriter.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/manager/writer/BlurIndexSimpleWriter.java b/blur-core/src/main/java/org/apache/blur/manager/writer/BlurIndexSimpleWriter.java
index 2930344..3c12c9f 100644
--- a/blur-core/src/main/java/org/apache/blur/manager/writer/BlurIndexSimpleWriter.java
+++ b/blur-core/src/main/java/org/apache/blur/manager/writer/BlurIndexSimpleWriter.java
@@ -49,8 +49,6 @@ import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
 
-import lucene.security.index.AccessControlFactory;
-
 import org.apache.blur.BlurConfiguration;
 import org.apache.blur.analysis.FieldManager;
 import org.apache.blur.index.ExitableReader;
@@ -61,6 +59,7 @@ import org.apache.blur.lucene.codec.Blur024Codec;
 import org.apache.blur.lucene.search.IndexSearcherCloseable;
 import org.apache.blur.lucene.search.IndexSearcherCloseableBase;
 import org.apache.blur.lucene.search.SuperQuery;
+import org.apache.blur.lucene.security.index.AccessControlFactory;
 import org.apache.blur.memory.MemoryLeakDetector;
 import org.apache.blur.server.IndexSearcherCloseableSecureBase;
 import org.apache.blur.server.ShardContext;

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-core/src/main/java/org/apache/blur/server/BlurSecureIndexSearcher.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/server/BlurSecureIndexSearcher.java b/blur-core/src/main/java/org/apache/blur/server/BlurSecureIndexSearcher.java
index 222577f..9df0142 100644
--- a/blur-core/src/main/java/org/apache/blur/server/BlurSecureIndexSearcher.java
+++ b/blur-core/src/main/java/org/apache/blur/server/BlurSecureIndexSearcher.java
@@ -22,10 +22,9 @@ import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 
-import lucene.security.index.AccessControlFactory;
-import lucene.security.search.SecureIndexSearcher;
-
 import org.apache.blur.lucene.search.SuperQuery;
+import org.apache.blur.lucene.security.index.AccessControlFactory;
+import org.apache.blur.lucene.security.search.SecureIndexSearcher;
 import org.apache.blur.thrift.generated.ScoreType;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Term;

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-core/src/main/java/org/apache/blur/server/IndexSearcherCloseableSecureBase.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/server/IndexSearcherCloseableSecureBase.java b/blur-core/src/main/java/org/apache/blur/server/IndexSearcherCloseableSecureBase.java
index ac58229..40951a7 100644
--- a/blur-core/src/main/java/org/apache/blur/server/IndexSearcherCloseableSecureBase.java
+++ b/blur-core/src/main/java/org/apache/blur/server/IndexSearcherCloseableSecureBase.java
@@ -27,10 +27,9 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 
-import lucene.security.index.AccessControlFactory;
-
 import org.apache.blur.lucene.search.CloneableCollector;
 import org.apache.blur.lucene.search.IndexSearcherCloseable;
+import org.apache.blur.lucene.security.index.AccessControlFactory;
 import org.apache.blur.trace.Trace;
 import org.apache.blur.trace.Tracer;
 import org.apache.lucene.index.AtomicReaderContext;

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-core/src/main/java/org/apache/blur/server/TableContext.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/server/TableContext.java b/blur-core/src/main/java/org/apache/blur/server/TableContext.java
index f4bae7c..d8cf3e2 100644
--- a/blur-core/src/main/java/org/apache/blur/server/TableContext.java
+++ b/blur-core/src/main/java/org/apache/blur/server/TableContext.java
@@ -39,9 +39,6 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
 
-import lucene.security.index.AccessControlFactory;
-import lucene.security.index.FilterAccessControlFactory;
-
 import org.apache.blur.BlurConfiguration;
 import org.apache.blur.analysis.FieldManager;
 import org.apache.blur.analysis.FieldTypeDefinition;
@@ -51,6 +48,8 @@ import org.apache.blur.analysis.ThriftFieldManager;
 import org.apache.blur.log.Log;
 import org.apache.blur.log.LogFactory;
 import org.apache.blur.lucene.search.FairSimilarity;
+import org.apache.blur.lucene.security.index.AccessControlFactory;
+import org.apache.blur.lucene.security.index.FilterAccessControlFactory;
 import org.apache.blur.manager.ReadInterceptor;
 import org.apache.blur.manager.writer.BlurIndex;
 import org.apache.blur.manager.writer.BlurIndexCloser;

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-core/src/test/java/org/apache/blur/server/BlurSecureIndexSearcherTest.java
----------------------------------------------------------------------
diff --git a/blur-core/src/test/java/org/apache/blur/server/BlurSecureIndexSearcherTest.java b/blur-core/src/test/java/org/apache/blur/server/BlurSecureIndexSearcherTest.java
index 6c015ec..89b3f44 100644
--- a/blur-core/src/test/java/org/apache/blur/server/BlurSecureIndexSearcherTest.java
+++ b/blur-core/src/test/java/org/apache/blur/server/BlurSecureIndexSearcherTest.java
@@ -25,10 +25,9 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
 
-import lucene.security.index.AccessControlFactory;
-import lucene.security.index.FilterAccessControlFactory;
-
 import org.apache.blur.lucene.search.SuperQuery;
+import org.apache.blur.lucene.security.index.AccessControlFactory;
+import org.apache.blur.lucene.security.index.FilterAccessControlFactory;
 import org.apache.blur.thrift.generated.ScoreType;
 import org.apache.blur.utils.BlurConstants;
 import org.apache.lucene.analysis.core.KeywordAnalyzer;

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/pom.xml
----------------------------------------------------------------------
diff --git a/blur-document-security/pom.xml b/blur-document-security/pom.xml
new file mode 100644
index 0000000..16e851b
--- /dev/null
+++ b/blur-document-security/pom.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- 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 http://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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.blur</groupId>
+		<artifactId>blur</artifactId>
+		<version>0.2.4-incubating-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<groupId>org.apache.blur</groupId>
+	<artifactId>blur-document-security</artifactId>
+	<version>${projectVersion}</version>
+	<packaging>jar</packaging>
+	<name>Blur Document Security</name>
+	<description>The Blur document security module contains the document level security logic.</description>
+
+	<dependencies>
+			<dependency>
+				<groupId>org.apache.blur</groupId>
+				<artifactId>blur-util</artifactId>
+				<version>${project.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>org.apache.lucene</groupId>
+				<artifactId>lucene-core</artifactId>
+				<version>${lucene.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>org.apache.lucene</groupId>
+				<artifactId>lucene-codecs</artifactId>
+				<version>${lucene.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>org.apache.lucene</groupId>
+				<artifactId>lucene-highlighter</artifactId>
+				<version>${lucene.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>org.apache.lucene</groupId>
+				<artifactId>lucene-analyzers-common</artifactId>
+				<version>${lucene.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>org.apache.lucene</groupId>
+				<artifactId>lucene-queryparser</artifactId>
+				<version>${lucene.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>org.apache.lucene</groupId>
+				<artifactId>lucene-spatial</artifactId>
+				<version>${lucene.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>commons-cli</groupId>
+				<artifactId>commons-cli</artifactId>
+				<version>${commons-cli.version}</version>
+				<scope>compile</scope>
+			</dependency>
+			<dependency>
+				<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
+				<artifactId>concurrentlinkedhashmap-lru</artifactId>
+				<version>${concurrentlinkedhashmap-lru.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>log4j</groupId>
+				<artifactId>log4j</artifactId>
+				<scope>provided</scope>
+			</dependency>
+			<dependency>
+	 			<groupId>com.google.guava</groupId>
+	 			<artifactId>guava</artifactId>
+	 			<version>${guava.version}</version>
+	 		</dependency>
+			<dependency>
+				<groupId>commons-codec</groupId>
+				<artifactId>commons-codec</artifactId>
+				<version>${commons-codec.version}</version>
+			</dependency>
+	</dependencies>
+
+	<repositories>
+		<repository>
+			<id>libdir</id>
+			<url>file://${basedir}/../lib</url>
+		</repository>
+	</repositories>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<executions>
+					<execution>
+						<goals>
+							<goal>test-jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-source-plugin</artifactId>
+				<executions>
+					<execution>
+						<id>attach-sources</id>
+						<goals>
+							<goal>jar</goal>
+							<goal>test-jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-help-plugin</artifactId>
+				<version>2.2</version>
+				<executions>
+					<execution>
+						<phase>generate-resources</phase>
+						<goals>
+							<goal>effective-pom</goal>
+						</goals>
+						<configuration>
+							<output>${project.build.directory}/effective-pom.xml</output>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-install-plugin</artifactId>
+				<version>2.3.1</version>
+				<executions>
+					<execution>
+						<phase>install</phase>
+						<goals>
+							<goal>install-file</goal>
+						</goals>
+						<configuration>
+							<file>${project.build.directory}/${artifactId}-${project.version}.jar</file>
+							<pomFile>${project.build.directory}/effective-pom.xml</pomFile>
+							<!-- sources></sources -->
+							<!-- javadoc></javadoc -->
+							<groupId>${project.groupId}</groupId>
+							<artifactId>${project.artifactId}</artifactId>
+							<version>${project.version}</version>
+							<packaging>jar</packaging>
+							<!--classifier></classifier -->
+							<generatePom>true</generatePom>
+							<createChecksum>true</createChecksum>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentAuthorizations.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentAuthorizations.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentAuthorizations.java
new file mode 100644
index 0000000..aa433a8
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentAuthorizations.java
@@ -0,0 +1,39 @@
+/**
+ * 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
+ *
+ *     http://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.blur.lucene.security;
+
+import java.util.Collection;
+
+import org.apache.blur.lucene.security.accumulo.Authorizations;
+
+public class DocumentAuthorizations extends Authorizations {
+
+  private static final long serialVersionUID = 2919269465244708278L;
+
+  public DocumentAuthorizations() {
+    super();
+  }
+
+  public DocumentAuthorizations(String... authorizations) {
+    super(authorizations);
+  }
+
+  public DocumentAuthorizations(Collection<String> authorizations) {
+    super(authorizations.toArray(new String[authorizations.size()]));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentVisibility.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentVisibility.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentVisibility.java
new file mode 100644
index 0000000..41fe019
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentVisibility.java
@@ -0,0 +1,35 @@
+/**
+ * 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
+ *
+ *     http://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.blur.lucene.security;
+
+import org.apache.blur.lucene.security.accumulo.ColumnVisibility;
+
+public class DocumentVisibility extends ColumnVisibility {
+
+  public DocumentVisibility() {
+    super();
+  }
+
+  public DocumentVisibility(byte[] expression) {
+    super(expression);
+  }
+
+  public DocumentVisibility(String expression) {
+    super(expression);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentVisibilityEvaluator.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentVisibilityEvaluator.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentVisibilityEvaluator.java
new file mode 100644
index 0000000..d18027b
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/DocumentVisibilityEvaluator.java
@@ -0,0 +1,40 @@
+/**
+ * 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
+ *
+ *     http://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.blur.lucene.security;
+
+import java.io.IOException;
+
+import org.apache.blur.lucene.security.accumulo.VisibilityEvaluator;
+import org.apache.blur.lucene.security.accumulo.VisibilityParseException;
+
+public class DocumentVisibilityEvaluator {
+
+  private VisibilityEvaluator _evaluator;
+
+  public DocumentVisibilityEvaluator(DocumentAuthorizations authorizations) {
+    _evaluator = new VisibilityEvaluator(authorizations);
+  }
+
+  public boolean evaluate(DocumentVisibility visibility) throws IOException {
+    try {
+      return _evaluator.evaluate(visibility);
+    } catch (VisibilityParseException e) {
+      throw new IOException(e);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ArrayByteSequence.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ArrayByteSequence.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ArrayByteSequence.java
new file mode 100644
index 0000000..12b6256
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ArrayByteSequence.java
@@ -0,0 +1,171 @@
+/*
+ * 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
+ *
+ *     http://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.blur.lucene.security.accumulo;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+
+/**
+ * This code was originally create in the Apache Accumulo project.  It has
+ * been slightly modified from it's original form to allow for easier reuse.  
+ */
+/**
+ * An implementation of {@link ByteSequence} that uses a backing byte array.
+ */
+public class ArrayByteSequence extends ByteSequence implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  protected byte data[];
+  protected int offset;
+  protected int length;
+
+  /**
+   * Creates a new sequence. The given byte array is used directly as the
+   * backing array, so later changes made to the array reflect into the new
+   * sequence.
+   * 
+   * @param data
+   *          byte data
+   */
+  public ArrayByteSequence(byte data[]) {
+    this.data = data;
+    this.offset = 0;
+    this.length = data.length;
+  }
+
+  /**
+   * Creates a new sequence from a subsequence of the given byte array. The
+   * given byte array is used directly as the backing array, so later changes
+   * made to the (relevant portion of the) array reflect into the new sequence.
+   * 
+   * @param data
+   *          byte data
+   * @param offset
+   *          starting offset in byte array (inclusive)
+   * @param length
+   *          number of bytes to include in sequence
+   * @throws IllegalArgumentException
+   *           if the offset or length are out of bounds for the given byte
+   *           array
+   */
+  public ArrayByteSequence(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);
+    }
+
+    this.data = data;
+    this.offset = offset;
+    this.length = length;
+
+  }
+
+  /**
+   * Creates a new sequence from the given string. The bytes are determined from
+   * the string using the default platform encoding.
+   * 
+   * @param s
+   *          string to represent as bytes
+   */
+  public ArrayByteSequence(String s) {
+    this(UTFUtil.toBytes(s));
+  }
+
+  /**
+   * Creates a new sequence based on a byte buffer. If the byte buffer has an
+   * array, that array (and the buffer's offset and limit) are used; otherwise,
+   * a new backing array is created and a relative bulk get is performed to
+   * transfer the buffer's contents (starting at its current position and not
+   * beyond its limit).
+   * 
+   * @param buffer
+   *          byte buffer
+   */
+  public ArrayByteSequence(ByteBuffer buffer) {
+    this.length = buffer.remaining();
+
+    if (buffer.hasArray()) {
+      this.data = buffer.array();
+      this.offset = buffer.position();
+    } else {
+      this.data = new byte[length];
+      this.offset = 0;
+      buffer.get(data);
+    }
+  }
+
+  @Override
+  public byte byteAt(int i) {
+
+    if (i < 0) {
+      throw new IllegalArgumentException("i < 0, " + i);
+    }
+
+    if (i >= length) {
+      throw new IllegalArgumentException("i >= length, " + i + " >= " + length);
+    }
+
+    return data[offset + i];
+  }
+
+  @Override
+  public byte[] getBackingArray() {
+    return data;
+  }
+
+  @Override
+  public boolean isBackedByArray() {
+    return true;
+  }
+
+  @Override
+  public int length() {
+    return length;
+  }
+
+  @Override
+  public int offset() {
+    return offset;
+  }
+
+  @Override
+  public ByteSequence subSequence(int start, int end) {
+
+    if (start > end || start < 0 || end > length) {
+      throw new IllegalArgumentException("Bad start and/end start = " + start + " end=" + end + " offset=" + offset
+          + " length=" + length);
+    }
+
+    return new ArrayByteSequence(data, offset + start, end - start);
+  }
+
+  @Override
+  public byte[] toArray() {
+    if (offset == 0 && length == data.length)
+      return data;
+
+    byte[] copy = new byte[length];
+    System.arraycopy(data, offset, copy, 0, length);
+    return copy;
+  }
+
+  public String toString() {
+    return UTFUtil.toString(data, offset, length);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/AuthorizationContainer.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/AuthorizationContainer.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/AuthorizationContainer.java
new file mode 100644
index 0000000..a4726f6
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/AuthorizationContainer.java
@@ -0,0 +1,36 @@
+/*
+ * 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
+ *
+ *     http://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.blur.lucene.security.accumulo;
+
+
+/**
+ * This code was originally create in the Apache Accumulo project.  It has
+ * been slightly modified from it's original form to allow for easier reuse.  
+ */
+/**
+ * An interface for classes that contain a collection of authorizations.
+ */
+public interface AuthorizationContainer {
+  /**
+   * Checks whether this object contains the given authorization.
+   * 
+   * @param auth
+   *          authorization, as a string encoded in UTF-8
+   * @return true if authorization is in this collection
+   */
+  boolean contains(ByteSequence auth);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/Authorizations.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/Authorizations.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/Authorizations.java
new file mode 100644
index 0000000..4d9e22c
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/Authorizations.java
@@ -0,0 +1,340 @@
+/*
+ * 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
+ *
+ *     http://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.blur.lucene.security.accumulo;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * This code was originally create in the Apache Accumulo project.  It has
+ * been slightly modified from it's original form to allow for easier reuse.  
+ */
+/**
+ * A collection of authorization strings.
+ */
+public class Authorizations implements Iterable<byte[]>, Serializable, AuthorizationContainer {
+
+  private static final long serialVersionUID = 1L;
+
+  private Set<ByteSequence> auths = new HashSet<ByteSequence>();
+  private List<byte[]> authsList = new ArrayList<byte[]>(); // sorted order
+
+  /**
+   * An empty set of authorizations.
+   */
+  public static final Authorizations EMPTY = new Authorizations();
+
+  private static final boolean[] validAuthChars = new boolean[256];
+
+  /**
+   * A special header string used when serializing instances of this class.
+   * 
+   * @see #serialize()
+   */
+  public static final String HEADER = "!AUTH1:";
+
+  static {
+    for (int i = 0; i < 256; i++) {
+      validAuthChars[i] = false;
+    }
+
+    for (int i = 'a'; i <= 'z'; i++) {
+      validAuthChars[i] = true;
+    }
+
+    for (int i = 'A'; i <= 'Z'; i++) {
+      validAuthChars[i] = true;
+    }
+
+    for (int i = '0'; i <= '9'; i++) {
+      validAuthChars[i] = true;
+    }
+
+    validAuthChars['_'] = true;
+    validAuthChars['-'] = true;
+    validAuthChars[':'] = true;
+    validAuthChars['.'] = true;
+    validAuthChars['/'] = true;
+  }
+
+  static final boolean isValidAuthChar(byte b) {
+    return validAuthChars[0xff & b];
+  }
+
+  private void checkAuths() {
+    Set<ByteSequence> sortedAuths = new TreeSet<ByteSequence>(auths);
+
+    for (ByteSequence bs : sortedAuths) {
+      if (bs.length() == 0) {
+        throw new IllegalArgumentException("Empty authorization");
+      }
+
+      authsList.add(bs.toArray());
+    }
+  }
+
+  /**
+   * Constructs an authorization object from a collection of string
+   * authorizations that have each already been encoded as UTF-8 bytes. Warning:
+   * This method does not verify that each encoded string is valid UTF-8.
+   * 
+   * @param authorizations
+   *          collection of authorizations, as strings encoded in UTF-8
+   * @throws IllegalArgumentException
+   *           if authorizations is null
+   * @see #Authorizations(String...)
+   */
+  public Authorizations(Collection<byte[]> authorizations) {
+    checkArgument(authorizations != null, "authorizations is null");
+    for (byte[] auth : authorizations)
+      auths.add(new ArrayByteSequence(auth));
+    checkAuths();
+  }
+
+  /**
+   * Constructs an authorizations object from a serialized form. This is NOT a
+   * constructor for a set of authorizations of size one. Warning: This method
+   * does not verify that the encoded serialized form is valid UTF-8.
+   * 
+   * @param authorizations
+   *          a serialized authorizations string produced by
+   *          {@link #getAuthorizationsArray()} or {@link #serialize()},
+   *          converted to UTF-8 bytes
+   * @throws IllegalArgumentException
+   *           if authorizations is null
+   */
+  public Authorizations(byte[] authorizations) {
+
+    checkArgument(authorizations != null, "authorizations is null");
+
+    String authsString = UTFUtil.toString(authorizations);
+    if (authsString.startsWith(HEADER)) {
+      // it's the new format
+      authsString = authsString.substring(HEADER.length());
+      if (authsString.length() > 0) {
+        for (String encAuth : authsString.split(",")) {
+          byte[] auth = Base64.decodeBase64(UTFUtil.toBytes(encAuth));
+          auths.add(new ArrayByteSequence(auth));
+        }
+        checkAuths();
+      }
+    } else {
+      // it's the old format
+      if (authorizations.length > 0)
+        setAuthorizations(authsString.split(","));
+    }
+  }
+
+  /**
+   * Constructs an empty set of authorizations.
+   * 
+   * @see #Authorizations(String...)
+   */
+  public Authorizations() {
+  }
+
+  /**
+   * Constructs an authorizations object from a set of human-readable
+   * authorizations.
+   * 
+   * @param authorizations
+   *          array of authorizations
+   * @throws IllegalArgumentException
+   *           if authorizations is null
+   */
+  public Authorizations(String... authorizations) {
+    setAuthorizations(authorizations);
+  }
+
+  private void setAuthorizations(String... authorizations) {
+    checkArgument(authorizations != null, "authorizations is null");
+    auths.clear();
+    for (String str : authorizations) {
+      str = str.trim();
+      auths.add(new ArrayByteSequence(UTFUtil.toBytes(str)));
+    }
+
+    checkAuths();
+  }
+
+  /**
+   * Returns a serialized form of these authorizations.
+   * 
+   * @return serialized form of these authorizations, as a string encoded in
+   *         UTF-8
+   * @see #serialize()
+   */
+  public byte[] getAuthorizationsArray() {
+    return UTFUtil.toBytes(serialize());
+  }
+
+  /**
+   * Gets the authorizations in sorted order. The returned list is not
+   * modifiable.
+   * 
+   * @return authorizations, each as a string encoded in UTF-8
+   * @see #Authorizations(Collection)
+   */
+  public List<byte[]> getAuthorizations() {
+    ArrayList<byte[]> copy = new ArrayList<byte[]>(authsList.size());
+    for (byte[] auth : authsList) {
+      byte[] bytes = new byte[auth.length];
+      System.arraycopy(auth, 0, bytes, 0, auth.length);
+      copy.add(bytes);
+    }
+    return Collections.unmodifiableList(copy);
+  }
+
+  /**
+   * Gets the authorizations in sorted order. The returned list is not
+   * modifiable.
+   * 
+   * @return authorizations, each as a string encoded in UTF-8 and within a
+   *         buffer
+   */
+  public List<ByteBuffer> getAuthorizationsBB() {
+    ArrayList<ByteBuffer> copy = new ArrayList<ByteBuffer>(authsList.size());
+    for (byte[] auth : authsList) {
+      byte[] bytes = new byte[auth.length];
+      System.arraycopy(auth, 0, bytes, 0, auth.length);
+      copy.add(ByteBuffer.wrap(bytes));
+    }
+    return Collections.unmodifiableList(copy);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    String sep = "";
+    for (ByteSequence auth : auths) {
+      sb.append(sep);
+      sep = ",";
+      sb.append(UTFUtil.toString(auth.toArray()));
+    }
+
+    return sb.toString();
+  }
+
+  /**
+   * Checks whether this object contains the given authorization.
+   * 
+   * @param auth
+   *          authorization, as a string encoded in UTF-8
+   * @return true if authorization is in this collection
+   */
+  public boolean contains(byte[] auth) {
+    return auths.contains(new ArrayByteSequence(auth));
+  }
+
+  /**
+   * Checks whether this object contains the given authorization. Warning: This
+   * method does not verify that the encoded string is valid UTF-8.
+   * 
+   * @param auth
+   *          authorization, as a string encoded in UTF-8
+   * @return true if authorization is in this collection
+   */
+  @Override
+  public boolean contains(ByteSequence auth) {
+    return auths.contains(auth);
+  }
+
+  /**
+   * Checks whether this object contains the given authorization.
+   * 
+   * @param auth
+   *          authorization
+   * @return true if authorization is in this collection
+   */
+  public boolean contains(String auth) {
+    return auths.contains(new ArrayByteSequence(auth));
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o == null) {
+      return false;
+    }
+
+    if (o instanceof Authorizations) {
+      Authorizations ao = (Authorizations) o;
+
+      return auths.equals(ao.auths);
+    }
+
+    return false;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = 0;
+    for (ByteSequence b : auths)
+      result += b.hashCode();
+    return result;
+  }
+
+  /**
+   * Gets the size of this collection of authorizations.
+   * 
+   * @return collection size
+   */
+  public int size() {
+    return auths.size();
+  }
+
+  /**
+   * Checks if this collection of authorizations is empty.
+   * 
+   * @return true if this collection contains no authorizations
+   */
+  public boolean isEmpty() {
+    return auths.isEmpty();
+  }
+
+  @Override
+  public Iterator<byte[]> iterator() {
+    return getAuthorizations().iterator();
+  }
+
+  /**
+   * Returns a serialized form of these authorizations. Convert the returned
+   * string to UTF-8 bytes to deserialize with {@link #Authorizations(byte[])}.
+   * 
+   * @return serialized form of authorizations
+   */
+  public String serialize() {
+    StringBuilder sb = new StringBuilder(HEADER);
+    String sep = "";
+    for (byte[] auth : authsList) {
+      sb.append(sep);
+      sep = ",";
+      sb.append(Base64.encodeBase64String(auth));
+    }
+
+    return sb.toString();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/BadArgumentException.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/BadArgumentException.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/BadArgumentException.java
new file mode 100644
index 0000000..cb8aab3
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/BadArgumentException.java
@@ -0,0 +1,31 @@
+/*
+ * 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
+ *
+ *     http://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.blur.lucene.security.accumulo;
+
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * This code was originally create in the Apache Accumulo project. It has been
+ * slightly modified from it's original form to allow for easier reuse.
+ */
+public final class BadArgumentException extends PatternSyntaxException {
+  private static final long serialVersionUID = 1L;
+
+  public BadArgumentException(String desc, String badarg, int index) {
+    super(desc, badarg, index);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/Base64.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/Base64.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/Base64.java
new file mode 100644
index 0000000..0c102b1
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/Base64.java
@@ -0,0 +1,82 @@
+/*
+ * 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
+ *
+ *     http://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.blur.lucene.security.accumulo;
+
+import org.apache.commons.codec.binary.StringUtils;
+
+/**
+ * This code was originally create in the Apache Accumulo project.  It has
+ * been slightly modified from it's original form to allow for easier reuse.  
+ */
+/**
+ * A wrapper around commons-codec's Base64 to make sure we get the non-chunked
+ * behavior that became the default in commons-codec version 1.5+ while relying
+ * on the commons-codec version 1.4 that Hadoop Client provides.
+ */
+public final class Base64 {
+
+  /**
+   * Private to prevent instantiation.
+   */
+  private Base64() {
+  }
+
+  /**
+   * Serialize to Base64 byte array, non-chunked.
+   */
+  public static byte[] encodeBase64(byte[] data) {
+    return org.apache.commons.codec.binary.Base64.encodeBase64(data, false);
+  }
+
+  /**
+   * Serialize to Base64 as a String, non-chunked.
+   */
+  public static String encodeBase64String(byte[] data) {
+    /*
+     * Based on implementation of this same name function in commons-codec 1.5+.
+     * in commons-codec 1.4, the second param sets chunking to true.
+     */
+    return StringUtils.newStringUtf8(org.apache.commons.codec.binary.Base64.encodeBase64(data, false));
+  }
+
+  /**
+   * Serialize to Base64 as a String using the URLSafe alphabet, non-chunked.
+   * 
+   * The URLSafe alphabet uses - instead of + and _ instead of /.
+   */
+  public static String encodeBase64URLSafeString(byte[] data) {
+    return org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(data);
+  }
+
+  /**
+   * Decode, presuming bytes are base64.
+   * 
+   * Transparently handles either the standard alphabet or the URL Safe one.
+   */
+  public static byte[] decodeBase64(byte[] base64) {
+    return org.apache.commons.codec.binary.Base64.decodeBase64(base64);
+  }
+
+  /**
+   * Decode, presuming String is base64.
+   * 
+   * Transparently handles either the standard alphabet or the URL Safe one.
+   */
+  public static byte[] decodeBase64(String base64String) {
+    return org.apache.commons.codec.binary.Base64.decodeBase64(base64String);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ByteSequence.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ByteSequence.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ByteSequence.java
new file mode 100644
index 0000000..5e94b09
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ByteSequence.java
@@ -0,0 +1,167 @@
+/*
+ * 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
+ *
+ *     http://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.blur.lucene.security.accumulo;
+
+
+/**
+ * This code was originally create in the Apache Accumulo project.  It has
+ * been slightly modified from it's original form to allow for easier reuse.  
+ */
+/**
+ * A sequence of bytes.
+ */
+public abstract class ByteSequence implements Comparable<ByteSequence> {
+
+  /**
+   * Gets a byte within this sequence.
+   * 
+   * @param i
+   *          index into sequence
+   * @return byte
+   * @throws IllegalArgumentException
+   *           if i is out of range
+   */
+  public abstract byte byteAt(int i);
+
+  /**
+   * Gets the length of this sequence.
+   * 
+   * @return sequence length
+   */
+  public abstract int length();
+
+  /**
+   * Returns a portion of this sequence.
+   * 
+   * @param start
+   *          index of subsequence start (inclusive)
+   * @param end
+   *          index of subsequence end (exclusive)
+   */
+  public abstract ByteSequence subSequence(int start, int end);
+
+  /**
+   * Returns a byte array containing the bytes in this sequence. This method may
+   * copy the sequence data or may return a backing byte array directly.
+   * 
+   * @return byte array
+   */
+  public abstract byte[] toArray();
+
+  /**
+   * Determines whether this sequence is backed by a byte array.
+   * 
+   * @return true if sequence is backed by a byte array
+   */
+  public abstract boolean isBackedByArray();
+
+  /**
+   * Gets the backing byte array for this sequence.
+   * 
+   * @return byte array
+   */
+  public abstract byte[] getBackingArray();
+
+  /**
+   * Gets the offset for this sequence. This value represents the starting point
+   * for the sequence in the backing array, if there is one.
+   * 
+   * @return offset (inclusive)
+   */
+  public abstract int offset();
+
+  /**
+   * Compares the two given byte sequences, byte by byte, returning a negative,
+   * zero, or positive result if the first sequence is less than, equal to, or
+   * greater than the second. The comparison is performed starting with the
+   * first byte of each sequence, and proceeds until a pair of bytes differs, or
+   * one sequence runs out of byte (is shorter). A shorter sequence is
+   * considered less than a longer one.
+   * 
+   * @param bs1
+   *          first byte sequence to compare
+   * @param bs2
+   *          second byte sequence to compare
+   * @return comparison result
+   */
+  public static int compareBytes(ByteSequence bs1, ByteSequence bs2) {
+
+    int minLen = Math.min(bs1.length(), bs2.length());
+
+    for (int i = 0; i < minLen; i++) {
+      int a = (bs1.byteAt(i) & 0xff);
+      int b = (bs2.byteAt(i) & 0xff);
+
+      if (a != b) {
+        return a - b;
+      }
+    }
+
+    return bs1.length() - bs2.length();
+  }
+
+  /**
+   * Compares this byte sequence to another.
+   * 
+   * @param obs
+   *          byte sequence to compare
+   * @return comparison result
+   * @see #compareBytes(ByteSequence, ByteSequence)
+   */
+  public int compareTo(ByteSequence obs) {
+    if (isBackedByArray() && obs.isBackedByArray()) {
+      return ColumnVisibility.compareBytes(getBackingArray(), offset(), length(), obs.getBackingArray(),
+          obs.offset(), obs.length());
+    }
+
+    return compareBytes(this, obs);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o instanceof ByteSequence) {
+      ByteSequence obs = (ByteSequence) o;
+
+      if (this == o)
+        return true;
+
+      if (length() != obs.length())
+        return false;
+
+      return compareTo(obs) == 0;
+    }
+
+    return false;
+
+  }
+
+  @Override
+  public int hashCode() {
+    int hash = 1;
+    if (isBackedByArray()) {
+      byte[] data = getBackingArray();
+      int end = offset() + length();
+      for (int i = offset(); i < end; i++)
+        hash = (31 * hash) + data[i];
+    } else {
+      for (int i = 0; i < length(); i++)
+        hash = (31 * hash) + byteAt(i);
+    }
+    return hash;
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ColumnVisibility.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ColumnVisibility.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ColumnVisibility.java
new file mode 100644
index 0000000..b04a9bf
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/ColumnVisibility.java
@@ -0,0 +1,568 @@
+/*
+ * 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
+ *
+ *     http://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.blur.lucene.security.accumulo;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.TreeSet;
+
+/**
+ * This code was originally create in the Apache Accumulo project.  It has
+ * been slightly modified from it's original form to allow for easier reuse.  
+ */
+/**
+ * Validate the column visibility is a valid expression and set the visibility
+ * for a Mutation. See {@link ColumnVisibility#ColumnVisibility(byte[])} for the
+ * definition of an expression.
+ * 
+ * <P>
+ * The expression is a sequence of characters from the set [A-Za-z0-9_-.] along
+ * with the binary operators "&amp;" and "|" indicating that both operands are
+ * necessary, or the either is necessary. The following are valid expressions
+ * for visibility:
+ * 
+ * <pre>
+ * A
+ * A|B
+ * (A|B)&amp;(C|D)
+ * orange|(red&amp;yellow)
+ * </pre>
+ * 
+ * <P>
+ * The following are not valid expressions for visibility:
+ * 
+ * <pre>
+ * A|B&amp;C
+ * A=B
+ * A|B|
+ * A&amp;|B
+ * ()
+ * )
+ * dog|!cat
+ * </pre>
+ * 
+ * <P>
+ * In addition to the base set of visibilities, any character can be used in the
+ * expression if it is quoted. If the quoted term contains '&quot;' or '\', then
+ * escape the character with '\'. The {@link #quote(String)} method can be used
+ * to properly quote and escape terms automatically. The following is an example
+ * of a quoted term:
+ * 
+ * <pre>
+ * &quot;A#C&quot;<span />&amp;<span />B
+ * </pre>
+ */
+public class ColumnVisibility {
+
+  Node node = null;
+  private byte[] expression;
+
+  /**
+   * Accessor for the underlying byte string.
+   * 
+   * @return byte array representation of a visibility expression
+   */
+  public byte[] getExpression() {
+    return expression;
+  }
+
+  /**
+   * The node types in a parse tree for a visibility expression.
+   */
+  public static enum NodeType {
+    EMPTY, TERM, OR, AND,
+  }
+
+  /**
+   * All empty nodes are equal and represent the same value.
+   */
+  private static final Node EMPTY_NODE = new Node(NodeType.EMPTY, 0);
+
+  /**
+   * A node in the parse tree for a visibility expression.
+   */
+  public static class Node {
+    /**
+     * An empty list of nodes.
+     */
+    public final static List<Node> EMPTY = Collections.emptyList();
+    NodeType type;
+    int start;
+    int end;
+    List<Node> children = EMPTY;
+
+    public Node(NodeType type, int start) {
+      this.type = type;
+      this.start = start;
+      this.end = start + 1;
+    }
+
+    public Node(int start, int end) {
+      this.type = NodeType.TERM;
+      this.start = start;
+      this.end = end;
+    }
+
+    public void add(Node child) {
+      if (children == EMPTY)
+        children = new ArrayList<Node>();
+
+      children.add(child);
+    }
+
+    public NodeType getType() {
+      return type;
+    }
+
+    public List<Node> getChildren() {
+      return children;
+    }
+
+    public int getTermStart() {
+      return start;
+    }
+
+    public int getTermEnd() {
+      return end;
+    }
+
+    public ByteSequence getTerm(byte expression[]) {
+      if (type != NodeType.TERM)
+        throw new RuntimeException();
+
+      if (expression[start] == '"') {
+        // its a quoted term
+        int qStart = start + 1;
+        int qEnd = end - 1;
+
+        return new ArrayByteSequence(expression, qStart, qEnd - qStart);
+      }
+      return new ArrayByteSequence(expression, start, end - start);
+    }
+  }
+
+  /**
+   * A node comparator. Nodes sort according to node type, terms sort
+   * lexicographically. AND and OR nodes sort by number of children, or if the
+   * same by corresponding children.
+   */
+  public static class NodeComparator implements Comparator<Node>, Serializable {
+
+    private static final long serialVersionUID = 1L;
+    byte[] text;
+
+    /**
+     * Creates a new comparator.
+     * 
+     * @param text
+     *          expression string, encoded in UTF-8
+     */
+    public NodeComparator(byte[] text) {
+      this.text = text;
+    }
+
+    @Override
+    public int compare(Node a, Node b) {
+      int diff = a.type.ordinal() - b.type.ordinal();
+      if (diff != 0)
+        return diff;
+      switch (a.type) {
+      case EMPTY:
+        return 0; // All empty nodes are the same
+      case TERM:
+        return compareBytes(text, a.start, a.end - a.start, text, b.start, b.end - b.start);
+      case OR:
+      case AND:
+        diff = a.children.size() - b.children.size();
+        if (diff != 0)
+          return diff;
+        for (int i = 0; i < a.children.size(); i++) {
+          diff = compare(a.children.get(i), b.children.get(i));
+          if (diff != 0)
+            return diff;
+        }
+      }
+      return 0;
+    }
+  }
+
+  public static int compareBytes(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
+    int end1 = s1 + l1;
+    int end2 = s2 + l2;
+    for (int i = s1, j = s2; i < end1 && j < end2; i++, j++) {
+      int a = (b1[i] & 0xff);
+      int b = (b2[j] & 0xff);
+      if (a != b) {
+        return a - b;
+      }
+    }
+    return l1 - l2;
+  }
+
+  /*
+   * Convience method that delegates to normalize with a new NodeComparator
+   * constructed using the supplied expression.
+   */
+  public static Node normalize(Node root, byte[] expression) {
+    return normalize(root, expression, new NodeComparator(expression));
+  }
+
+  // @formatter:off
+  /*
+   * Walks an expression's AST in order to: 1) roll up expressions with the same
+   * operant (`a&(b&c) becomes a&b&c`) 2) sorts labels lexicographically
+   * (permutations of `a&b&c` are re-ordered to appear as `a&b&c`) 3) dedupes
+   * labels (`a&b&a` becomes `a&b`)
+   */
+  // @formatter:on
+  public static Node normalize(Node root, byte[] expression, NodeComparator comparator) {
+    if (root.type != NodeType.TERM) {
+      TreeSet<Node> rolledUp = new TreeSet<Node>(comparator);
+      java.util.Iterator<Node> itr = root.children.iterator();
+      while (itr.hasNext()) {
+        Node c = normalize(itr.next(), expression, comparator);
+        if (c.type == root.type) {
+          rolledUp.addAll(c.children);
+          itr.remove();
+        }
+      }
+      rolledUp.addAll(root.children);
+      root.children.clear();
+      root.children.addAll(rolledUp);
+
+      // need to promote a child if it's an only child
+      if (root.children.size() == 1) {
+        return root.children.get(0);
+      }
+    }
+
+    return root;
+  }
+
+  /*
+   * Walks an expression's AST and appends a string representation to a supplied
+   * StringBuilder. This method adds parens where necessary.
+   */
+  public static void stringify(Node root, byte[] expression, StringBuilder out) {
+    if (root.type == NodeType.TERM) {
+      out.append(UTFUtil.toString(expression, root.start, root.end - root.start));
+    } else {
+      String sep = "";
+      for (Node c : root.children) {
+        out.append(sep);
+        boolean parens = (c.type != NodeType.TERM && root.type != c.type);
+        if (parens)
+          out.append("(");
+        stringify(c, expression, out);
+        if (parens)
+          out.append(")");
+        sep = root.type == NodeType.AND ? "&" : "|";
+      }
+    }
+  }
+
+  /**
+   * Generates a byte[] that represents a normalized, but logically equivalent,
+   * form of this evaluator's expression.
+   * 
+   * @return normalized expression in byte[] form
+   */
+  public byte[] flatten() {
+    Node normRoot = normalize(node, expression);
+    StringBuilder builder = new StringBuilder(expression.length);
+    stringify(normRoot, expression, builder);
+    return UTFUtil.toBytes(builder.toString());
+  }
+
+  private static class ColumnVisibilityParser {
+    private int index = 0;
+    private int parens = 0;
+
+    public ColumnVisibilityParser() {
+    }
+
+    Node parse(byte[] expression) {
+      if (expression.length > 0) {
+        Node node = parse_(expression);
+        if (node == null) {
+          throw new BadArgumentException("operator or missing parens", UTFUtil.toString(expression), index - 1);
+        }
+        if (parens != 0) {
+          throw new BadArgumentException("parenthesis mis-match", UTFUtil.toString(expression), index - 1);
+        }
+        return node;
+      }
+      return null;
+    }
+
+    Node processTerm(int start, int end, Node expr, byte[] expression) {
+      if (start != end) {
+        if (expr != null)
+          throw new BadArgumentException("expression needs | or &", UTFUtil.toString(expression), start);
+        return new Node(start, end);
+      }
+      if (expr == null)
+        throw new BadArgumentException("empty term", UTFUtil.toString(expression), start);
+      return expr;
+    }
+
+    Node parse_(byte[] expression) {
+      Node result = null;
+      Node expr = null;
+      int wholeTermStart = index;
+      int subtermStart = index;
+      boolean subtermComplete = false;
+
+      while (index < expression.length) {
+        switch (expression[index++]) {
+        case '&': {
+          expr = processTerm(subtermStart, index - 1, expr, expression);
+          if (result != null) {
+            if (!result.type.equals(NodeType.AND))
+              throw new BadArgumentException("cannot mix & and |", UTFUtil.toString(expression), index - 1);
+          } else {
+            result = new Node(NodeType.AND, wholeTermStart);
+          }
+          result.add(expr);
+          expr = null;
+          subtermStart = index;
+          subtermComplete = false;
+          break;
+        }
+        case '|': {
+          expr = processTerm(subtermStart, index - 1, expr, expression);
+          if (result != null) {
+            if (!result.type.equals(NodeType.OR))
+              throw new BadArgumentException("cannot mix | and &", UTFUtil.toString(expression), index - 1);
+          } else {
+            result = new Node(NodeType.OR, wholeTermStart);
+          }
+          result.add(expr);
+          expr = null;
+          subtermStart = index;
+          subtermComplete = false;
+          break;
+        }
+        case '(': {
+          parens++;
+          if (subtermStart != index - 1 || expr != null)
+            throw new BadArgumentException("expression needs & or |", UTFUtil.toString(expression), index - 1);
+          expr = parse_(expression);
+          subtermStart = index;
+          subtermComplete = false;
+          break;
+        }
+        case ')': {
+          parens--;
+          Node child = processTerm(subtermStart, index - 1, expr, expression);
+          if (child == null && result == null)
+            throw new BadArgumentException("empty expression not allowed", UTFUtil.toString(expression), index);
+          if (result == null)
+            return child;
+          if (result.type == child.type)
+            for (Node c : child.children)
+              result.add(c);
+          else
+            result.add(child);
+          result.end = index - 1;
+          return result;
+        }
+        case '"': {
+          if (subtermStart != index - 1)
+            throw new BadArgumentException("expression needs & or |", UTFUtil.toString(expression), index - 1);
+
+          while (index < expression.length && expression[index] != '"') {
+            if (expression[index] == '\\') {
+              index++;
+              if (expression[index] != '\\' && expression[index] != '"')
+                throw new BadArgumentException("invalid escaping within quotes", UTFUtil.toString(expression),
+                    index - 1);
+            }
+            index++;
+          }
+
+          if (index == expression.length)
+            throw new BadArgumentException("unclosed quote", UTFUtil.toString(expression), subtermStart);
+
+          if (subtermStart + 1 == index)
+            throw new BadArgumentException("empty term", UTFUtil.toString(expression), subtermStart);
+
+          index++;
+
+          subtermComplete = true;
+
+          break;
+        }
+        default: {
+          if (subtermComplete)
+            throw new BadArgumentException("expression needs & or |", UTFUtil.toString(expression), index - 1);
+
+          byte c = expression[index - 1];
+          if (!Authorizations.isValidAuthChar(c))
+            throw new BadArgumentException("bad character (" + c + ")", UTFUtil.toString(expression), index - 1);
+        }
+        }
+      }
+      Node child = processTerm(subtermStart, index, expr, expression);
+      if (result != null) {
+        result.add(child);
+        result.end = index;
+      } else
+        result = child;
+      if (result.type != NodeType.TERM)
+        if (result.children.size() < 2)
+          throw new BadArgumentException("missing term", UTFUtil.toString(expression), index);
+      return result;
+    }
+  }
+
+  private void validate(byte[] expression) {
+    if (expression != null && expression.length > 0) {
+      ColumnVisibilityParser p = new ColumnVisibilityParser();
+      node = p.parse(expression);
+    } else {
+      node = EMPTY_NODE;
+    }
+    this.expression = expression;
+  }
+
+  /**
+   * Creates an empty visibility. Normally, elements with empty visibility can
+   * be seen by everyone. Though, one could change this behavior with filters.
+   * 
+   * @see #ColumnVisibility(String)
+   */
+  public ColumnVisibility() {
+    this(new byte[] {});
+  }
+
+  /**
+   * Creates a column visibility for a Mutation.
+   * 
+   * @param expression
+   *          An expression of the rights needed to see this mutation. The
+   *          expression syntax is defined at the class-level documentation
+   */
+  public ColumnVisibility(String expression) {
+    this(UTFUtil.toBytes(expression));
+  }
+
+  /**
+   * Creates a column visibility for a Mutation from a string already encoded in
+   * UTF-8 bytes.
+   * 
+   * @param expression
+   *          visibility expression, encoded as UTF-8 bytes
+   * @see #ColumnVisibility(String)
+   */
+  public ColumnVisibility(byte[] expression) {
+    validate(expression);
+  }
+
+  @Override
+  public String toString() {
+    return "[" + UTFUtil.toString(expression) + "]";
+  }
+
+  /**
+   * See {@link #equals(ColumnVisibility)}
+   */
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ColumnVisibility)
+      return equals((ColumnVisibility) obj);
+    return false;
+  }
+
+  /**
+   * Compares two ColumnVisibilities 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
+   */
+  public boolean equals(ColumnVisibility otherLe) {
+    return Arrays.equals(expression, otherLe.expression);
+  }
+
+  @Override
+  public int hashCode() {
+    return Arrays.hashCode(expression);
+  }
+
+  /**
+   * Gets the parse tree for this column visibility.
+   * 
+   * @return parse tree node
+   */
+  public Node getParseTree() {
+    return node;
+  }
+
+  /**
+   * Properly quotes terms in a column visibility expression. If no quoting is
+   * needed, then nothing is done.
+   * 
+   * <p>
+   * Examples of using quote :
+   * 
+   * <pre>
+   * import static org.apache.accumulo.core.security.ColumnVisibility.quote;
+   *   .
+   *   .
+   *   .
+   * ColumnVisibility cv = new ColumnVisibility(quote(&quot;A#C&quot;) + &quot;&amp;&quot; + quote(&quot;FOO&quot;));
+   * </pre>
+   * 
+   * @param term
+   *          term to quote
+   * @return quoted term (unquoted if unnecessary)
+   */
+  public static String quote(String term) {
+    return UTFUtil.toString(quote(UTFUtil.toBytes(term)));
+  }
+
+  /**
+   * Properly quotes terms in a column visibility expression. 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
+   * @see #quote(String)
+   */
+  public static byte[] quote(byte[] term) {
+    boolean needsQuote = false;
+
+    for (int i = 0; i < term.length; i++) {
+      if (!Authorizations.isValidAuthChar(term[i])) {
+        needsQuote = true;
+        break;
+      }
+    }
+
+    if (!needsQuote)
+      return term;
+
+    return VisibilityEvaluator.escape(term, true);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/UTFUtil.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/UTFUtil.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/UTFUtil.java
new file mode 100644
index 0000000..9e47079
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/UTFUtil.java
@@ -0,0 +1,46 @@
+package org.apache.blur.lucene.security.accumulo;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * 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
+ * 
+ * http://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.
+ */
+
+public class UTFUtil {
+
+  private static final String UTF_8 = "UTF-8";
+
+  public static byte[] toBytes(String s) {
+    try {
+      return s.getBytes(UTF_8);
+    } catch (UnsupportedEncodingException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public static String toString(byte[] b, int off, int len) {
+    try {
+      return new String(b, off, len, UTF_8);
+    } catch (UnsupportedEncodingException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public static String toString(byte[] b) {
+    return toString(b, 0, b.length);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/VisibilityEvaluator.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/VisibilityEvaluator.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/VisibilityEvaluator.java
new file mode 100644
index 0000000..f225920
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/VisibilityEvaluator.java
@@ -0,0 +1,145 @@
+/*
+ * 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
+ *
+ *     http://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.blur.lucene.security.accumulo;
+
+import java.util.ArrayList;
+
+import org.apache.blur.lucene.security.accumulo.ColumnVisibility.Node;
+
+/**
+ * This code was originally create in the Apache Accumulo project.  It has
+ * been slightly modified from it's original form to allow for easier reuse.  
+ */
+/**
+ * A class which evaluates visibility expressions against a set of
+ * authorizations.
+ */
+public class VisibilityEvaluator {
+  private AuthorizationContainer auths;
+
+  /**
+   * Creates a new {@link Authorizations} object with escaped forms of the
+   * authorizations in the given object.
+   * 
+   * @param auths
+   *          original authorizations
+   * @return authorizations object with escaped authorization strings
+   * @see #escape(byte[], boolean)
+   */
+  static Authorizations escape(Authorizations auths) {
+    ArrayList<byte[]> retAuths = new ArrayList<byte[]>(auths.getAuthorizations().size());
+
+    for (byte[] auth : auths.getAuthorizations())
+      retAuths.add(escape(auth, false));
+
+    return new Authorizations(retAuths);
+  }
+
+  /**
+   * 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
+   * @return escaped authorization string
+   */
+  public static byte[] escape(byte[] auth, boolean quote) {
+    int escapeCount = 0;
+
+    for (int i = 0; i < auth.length; i++)
+      if (auth[i] == '"' || auth[i] == '\\')
+        escapeCount++;
+
+    if (escapeCount > 0 || quote) {
+      byte[] escapedAuth = new byte[auth.length + escapeCount + (quote ? 2 : 0)];
+      int index = quote ? 1 : 0;
+      for (int i = 0; i < auth.length; i++) {
+        if (auth[i] == '"' || auth[i] == '\\')
+          escapedAuth[index++] = '\\';
+        escapedAuth[index++] = auth[i];
+      }
+
+      if (quote) {
+        escapedAuth[0] = '"';
+        escapedAuth[escapedAuth.length - 1] = '"';
+      }
+
+      auth = escapedAuth;
+    }
+    return auth;
+  }
+
+  /**
+   * Creates a new evaluator for the given collection of authorizations. Each
+   * authorization string is escaped before handling, and the original strings
+   * are unchanged.
+   * 
+   * @param authorizations
+   *          authorizations object
+   */
+  public VisibilityEvaluator(Authorizations authorizations) {
+    this.auths = escape((Authorizations) authorizations);
+  }
+
+  /**
+   * Evaluates the given column visibility against the authorizations provided
+   * to this evaluator. A visibility passes evaluation if all authorizations in
+   * it are contained in those known to the evaluator, and all AND and OR
+   * subexpressions have at least two children.
+   * 
+   * @param visibility
+   *          column visibility to evaluate
+   * @return true if visibility passes evaluation
+   * @throws VisibilityParseException
+   *           if an AND or OR subexpression has less than two children, or a
+   *           subexpression is of an unknown type
+   */
+  public boolean evaluate(ColumnVisibility visibility) throws VisibilityParseException {
+    // The VisibilityEvaluator computes a trie from the given Authorizations,
+    // that ColumnVisibility expressions can be evaluated against.
+    return evaluate(visibility.getExpression(), visibility.getParseTree());
+  }
+
+  private final boolean evaluate(final byte[] expression, final Node root) throws VisibilityParseException {
+    if (expression.length == 0)
+      return true;
+    switch (root.type) {
+    case TERM:
+      return auths.contains(root.getTerm(expression));
+    case AND:
+      if (root.children == null || root.children.size() < 2)
+        throw new VisibilityParseException("AND has less than 2 children", expression, root.start);
+      for (Node child : root.children) {
+        if (!evaluate(expression, child))
+          return false;
+      }
+      return true;
+    case OR:
+      if (root.children == null || root.children.size() < 2)
+        throw new VisibilityParseException("OR has less than 2 children", expression, root.start);
+      for (Node child : root.children) {
+        if (evaluate(expression, child))
+          return true;
+      }
+      return false;
+    default:
+      throw new VisibilityParseException("No such node type", expression, root.start);
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/VisibilityParseException.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/VisibilityParseException.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/VisibilityParseException.java
new file mode 100644
index 0000000..7ce4d0f
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/accumulo/VisibilityParseException.java
@@ -0,0 +1,51 @@
+/*
+ * 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
+ *
+ *     http://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.blur.lucene.security.accumulo;
+
+import java.text.ParseException;
+
+/**
+ * This code was originally create in the Apache Accumulo project.  It has
+ * been slightly modified from it's original form to allow for easier reuse.  
+ */
+/**
+ * An exception thrown when a visibility string cannot be parsed.
+ */
+public class VisibilityParseException extends ParseException {
+  private static final long serialVersionUID = 1L;
+  private String visibility;
+
+  /**
+   * Creates a new exception.
+   * 
+   * @param reason
+   *          reason string
+   * @param visibility
+   *          visibility that could not be parsed
+   * @param errorOffset
+   *          offset into visibility where parsing failed
+   */
+  public VisibilityParseException(String reason, byte[] visibility, int errorOffset) {
+    super(reason, errorOffset);
+    this.visibility = UTFUtil.toString(visibility);
+  }
+
+  @Override
+  public String getMessage() {
+    return super.getMessage() + " in string '" + visibility + "' at position " + super.getErrorOffset();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/analysis/DocumentVisibilityTokenStream.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/analysis/DocumentVisibilityTokenStream.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/analysis/DocumentVisibilityTokenStream.java
new file mode 100644
index 0000000..8c15305
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/analysis/DocumentVisibilityTokenStream.java
@@ -0,0 +1,108 @@
+/**
+ * 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
+ *
+ *     http://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.blur.lucene.security.analysis;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.blur.lucene.security.DocumentVisibility;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+
+public class DocumentVisibilityTokenStream extends TokenStream {
+
+  private static final String UTF_8 = "UTF-8";
+
+  private final String _visiblity;
+  private final CharTermAttribute _tokenAtt;
+  private final int _length;
+  
+  private int _position;
+  private boolean more = true;
+
+  public DocumentVisibilityTokenStream(String visibility) {
+    _tokenAtt = addAttribute(CharTermAttribute.class);
+    _visiblity = visibility;
+    _length = _visiblity.length();
+  }
+
+  public DocumentVisibilityTokenStream(DocumentVisibility visibility) {
+    this(toString(visibility.flatten()));
+  }
+
+  @Override
+  public final boolean incrementToken() throws IOException {
+    if (more) {
+      int next = findNextPipe(_position);
+      if (next < 0) {
+        more = false;
+        next = _length;
+      }
+      _tokenAtt.setLength(0);
+      if (hasSurroundingParens(next)) {
+        _tokenAtt.append(_visiblity, _position + 1, next - 1);
+      } else {
+        _tokenAtt.append(_visiblity, _position, next);
+      }
+      _position = next + 1;
+      return true;
+    }
+    return false;
+  }
+
+  private boolean hasSurroundingParens(int end) {
+    if (_visiblity.charAt(_position) == '(') {
+      if (_visiblity.charAt(end - 1) == ')') {
+        return true;
+      } else {
+        throw new RuntimeException("This should never happen");
+      }
+    }
+    return false;
+  }
+
+  private int findNextPipe(int position) {
+    int p = 0;
+    for (int i = position; i < _length; i++) {
+      char c = _visiblity.charAt(i);
+      switch (c) {
+      case '(':
+        p++;
+        break;
+      case ')':
+        p--;
+        break;
+      case '|':
+        if (p == 0) {
+          return i;
+        }
+      default:
+        break;
+      }
+    }
+    return -1;
+  }
+
+  public static String toString(byte[] bs) {
+    try {
+      return new String(bs, UTF_8);
+    } catch (UnsupportedEncodingException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/49390b52/blur-document-security/src/main/java/org/apache/blur/lucene/security/document/DocumentVisiblityField.java
----------------------------------------------------------------------
diff --git a/blur-document-security/src/main/java/org/apache/blur/lucene/security/document/DocumentVisiblityField.java b/blur-document-security/src/main/java/org/apache/blur/lucene/security/document/DocumentVisiblityField.java
new file mode 100644
index 0000000..d3fd4f8
--- /dev/null
+++ b/blur-document-security/src/main/java/org/apache/blur/lucene/security/document/DocumentVisiblityField.java
@@ -0,0 +1,78 @@
+/**
+ * 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
+ *
+ *     http://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.blur.lucene.security.document;
+
+import java.io.IOException;
+
+import org.apache.blur.lucene.security.DocumentVisibility;
+import org.apache.blur.lucene.security.analysis.DocumentVisibilityTokenStream;
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.index.IndexableField;
+
+public class DocumentVisiblityField extends Field implements IndexableField {
+
+  public static final FieldType TYPE_NOT_STORED = new FieldType();
+  public static final FieldType TYPE_STORED = new FieldType();
+
+  static {
+    boolean tokenized = true;
+    TYPE_NOT_STORED.setIndexed(true);
+    TYPE_NOT_STORED.setOmitNorms(true);
+    TYPE_NOT_STORED.setIndexOptions(IndexOptions.DOCS_ONLY);
+    TYPE_NOT_STORED.setTokenized(tokenized);
+    TYPE_NOT_STORED.freeze();
+
+    TYPE_STORED.setIndexed(true);
+    TYPE_STORED.setOmitNorms(true);
+    TYPE_STORED.setIndexOptions(IndexOptions.DOCS_ONLY);
+    TYPE_STORED.setStored(true);
+    TYPE_STORED.setTokenized(tokenized);
+    TYPE_STORED.freeze();
+  }
+
+  private DocumentVisibilityTokenStream _visibilityTokenStream;
+
+  public DocumentVisiblityField(String name, String visibility) {
+    this(name, visibility, Store.YES);
+  }
+
+  public DocumentVisiblityField(String name, String visibility, Store store) {
+    this(name, new DocumentVisibility(visibility), store);
+  }
+
+  public DocumentVisiblityField(String name, DocumentVisibility visibility) {
+    super(name, DocumentVisibilityTokenStream.toString(visibility.flatten()), TYPE_STORED);
+  }
+
+  public DocumentVisiblityField(String name, DocumentVisibility visibility, Store store) {
+    super(name, DocumentVisibilityTokenStream.toString(visibility.flatten()), store == Store.YES ? TYPE_STORED
+        : TYPE_NOT_STORED);
+  }
+
+  @Override
+  public TokenStream tokenStream(Analyzer analyzer) throws IOException {
+    if (!(_visibilityTokenStream instanceof DocumentVisibilityTokenStream)) {
+      _visibilityTokenStream = new DocumentVisibilityTokenStream(stringValue());
+    }
+    return _visibilityTokenStream;
+  }
+
+}
\ No newline at end of file


Mime
View raw message