Author: ctubbsii Date: Sat May 4 05:19:57 2013 New Revision: 1479040 URL: http://svn.apache.org/r1479040 Log: ACCUMULO-1005, ACCUMULO-1316 merge to trunk
Modified: accumulo/trunk/ (props changed) accumulo/trunk/assemble/ (props changed) accumulo/trunk/assemble/pom.xml accumulo/trunk/core/ (props changed) accumulo/trunk/core/src/main/java/org/apache/accumulo/core/security/Authorizations.java accumulo/trunk/core/src/main/java/org/apache/accumulo/core/security/ColumnVisibility.java accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/AuthorizationsTest.java accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/ColumnVisibilityTest.java accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/VisibilityEvaluatorTest.java accumulo/trunk/examples/ (props changed) accumulo/trunk/fate/src/main/java/org/apache/accumulo/fate/ZooStore.java (props changed) accumulo/trunk/fate/src/main/java/org/apache/accumulo/fate/zookeeper/ZooSession.java (props changed) accumulo/trunk/pom.xml (props changed) accumulo/trunk/server/ (props changed) accumulo/trunk/src/ (props changed) Propchange: accumulo/trunk/ ------------------------------------------------------------------------------ Merged /accumulo/branches/1.5:r1479001-1479039 Propchange: accumulo/trunk/assemble/ ------------------------------------------------------------------------------ Merged /accumulo/branches/1.5/assemble:r1479001-1479039 Modified: accumulo/trunk/assemble/pom.xml URL: http://svn.apache.org/viewvc/accumulo/trunk/assemble/pom.xml?rev=1479040&r1=1479039&r2=1479040&view=diff ============================================================================== --- accumulo/trunk/assemble/pom.xml (original) +++ accumulo/trunk/assemble/pom.xml Sat May 4 05:19:57 2013 @@ -332,7 +332,7 @@ </goals> <phase>package</phase> <configuration> - <deb>${project.build.directory}/accumulo-${version}.deb</deb> + <deb>${project.build.directory}/accumulo-${project.version}.deb</deb> <classifier>bin</classifier> <controlDir>assemble/deb/accumulo</controlDir> <installDir>/usr/lib/accumulo</installDir> @@ -417,7 +417,7 @@ </goals> <phase>package</phase> <configuration> - <deb>${project.build.directory}/accumulo-native-${version}.deb</deb> + <deb>${project.build.directory}/accumulo-native-${project.version}.deb</deb> <controlDir>assemble/deb/accumulo-native</controlDir> <installDir>/usr/lib/accumulo</installDir> <classifier>native</classifier> @@ -457,7 +457,7 @@ </goals> <phase>package</phase> <configuration> - <deb>${project.build.directory}/accumulo-test-${version}.deb</deb> + <deb>${project.build.directory}/accumulo-test-${project.version}.deb</deb> <controlDir>assemble/deb/accumulo-test</controlDir> <installDir>/usr/lib/accumulo</installDir> <classifier>test</classifier> Propchange: accumulo/trunk/core/ ------------------------------------------------------------------------------ Merged /accumulo/branches/1.5/core:r1479001-1479039 Modified: accumulo/trunk/core/src/main/java/org/apache/accumulo/core/security/Authorizations.java URL: http://svn.apache.org/viewvc/accumulo/trunk/core/src/main/java/org/apache/accumulo/core/security/Authorizations.java?rev=1479040&r1=1479039&r2=1479040&view=diff ============================================================================== --- accumulo/trunk/core/src/main/java/org/apache/accumulo/core/security/Authorizations.java (original) +++ accumulo/trunk/core/src/main/java/org/apache/accumulo/core/security/Authorizations.java Sat May 4 05:19:57 2013 @@ -17,9 +17,7 @@ package org.apache.accumulo.core.security; import java.io.Serializable; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -29,6 +27,7 @@ import java.util.List; import java.util.Set; import java.util.TreeSet; +import org.apache.accumulo.core.Constants; import org.apache.accumulo.core.data.ArrayByteSequence; import org.apache.accumulo.core.data.ByteSequence; import org.apache.accumulo.core.util.ArgumentChecker; @@ -46,7 +45,7 @@ public class Authorizations implements I private static final boolean[] validAuthChars = new boolean[256]; public static final String HEADER = "!AUTH1:"; - + static { for (int i = 0; i < 256; i++) { validAuthChars[i] = false; @@ -87,6 +86,11 @@ public class Authorizations implements I } } + /** + * A convenience constructor that accepts a collection of string authorizations that have each already been encoded as UTF-8 bytes. + * + * @see #Authorizations(String...) + */ public Authorizations(Collection<byte[]> authorizations) { ArgumentChecker.notNull(authorizations); for (byte[] auth : authorizations) @@ -94,6 +98,11 @@ public class Authorizations implements I checkAuths(); } + /** + * A convenience constructor that accepts a collection of string authorizations that have each already been encoded as UTF-8 bytes. + * + * @see #Authorizations(String...) + */ public Authorizations(List<ByteBuffer> authorizations) { ArgumentChecker.notNull(authorizations); for (ByteBuffer buffer : authorizations) { @@ -103,102 +112,124 @@ public class Authorizations implements I } /** + * Constructs an authorizations object a serialized form. This is NOT a constructor for a set of authorizations of size one. + * * @param authorizations - * a serialized authorizations string produced by {@link #getAuthorizationsArray()} or {@link #serialize()} + * a serialized authorizations string produced by {@link #getAuthorizationsArray()} or {@link #serialize()} (converted to UTF-8 bytes) */ - public Authorizations(byte[] authorizations) { ArgumentChecker.notNull(authorizations); - - String authsString = new String(authorizations); + + String authsString = new String(authorizations, Constants.UTF8); if (authsString.startsWith(HEADER)) { - // its the new format + // it's the new format authsString = authsString.substring(HEADER.length()); if (authsString.length() > 0) { for (String encAuth : authsString.split(",")) { - byte[] auth = Base64.decodeBase64(encAuth.getBytes()); + byte[] auth = Base64.decodeBase64(encAuth.getBytes(Constants.UTF8)); auths.add(new ArrayByteSequence(auth)); } checkAuths(); } } else { - // its the old format + // it's the old format ArgumentChecker.notNull(authorizations); 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 charset - * used to convert each authorization to a byte array * @param authorizations * array of authorizations */ - - public Authorizations(Charset charset, String... authorizations) { - setAuthorizations(charset, authorizations); - } - public Authorizations(String... authorizations) { setAuthorizations(authorizations); } private void setAuthorizations(String... authorizations) { - setAuthorizations(Charset.defaultCharset(), authorizations); - } - - private void setAuthorizations(Charset charset, String... authorizations) { ArgumentChecker.notNull(authorizations); auths.clear(); for (String str : authorizations) { str = str.trim(); - try { - auths.add(new ArrayByteSequence(str.getBytes(charset.name()))); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } + auths.add(new ArrayByteSequence(str.getBytes(Constants.UTF8))); } checkAuths(); } + /** + * Retrieve a serialized form of the underlying set of authorizations. + * + * @see #Authorizations(byte[]) + */ public byte[] getAuthorizationsArray() { - return serialize().getBytes(); + return serialize().getBytes(Constants.UTF8); } + /** + * Retrieve authorizations as a list of strings that have been encoded as UTF-8 bytes. + * + * @see #Authorizations(Collection) + */ public List<byte[]> getAuthorizations() { return immutableList; } + /** + * Retrieve authorizations as a list of strings that have been encoded as UTF-8 bytes. + * + * @see #Authorizations(List) + */ public List<ByteBuffer> getAuthorizationsBB() { return ByteBufferUtil.toByteBuffers(immutableList); } + @Override public String toString() { StringBuilder sb = new StringBuilder(); String sep = ""; for (ByteSequence auth : auths) { sb.append(sep); sep = ","; - sb.append(new String(auth.toArray())); + sb.append(new String(auth.toArray(), Constants.UTF8)); } return sb.toString(); } + /** + * Checks for the existence of this UTF-8 encoded authorization. + */ public boolean contains(byte[] auth) { return auths.contains(new ArrayByteSequence(auth)); } + /** + * Checks for the existence of this UTF-8 encoded authorization. + */ public boolean contains(ByteSequence auth) { return auths.contains(auth); } + /** + * Checks for the existence of this authorization. + */ + public boolean contains(String auth) { + return auths.contains(auth.getBytes(Constants.UTF8)); + } + + @Override public boolean equals(Object o) { if (o == null) { return false; @@ -213,6 +244,7 @@ public class Authorizations implements I return false; } + @Override public int hashCode() { int result = 0; for (ByteSequence b : auths) @@ -233,13 +265,16 @@ public class Authorizations implements I return immutableList.iterator(); } + /** + * Returns a serialized form of these authorizations. Convert to UTF-8 bytes to deserialize with {@link #Authorizations(byte[])} + */ public String serialize() { StringBuilder sb = new StringBuilder(HEADER); String sep = ""; for (byte[] auth : immutableList) { sb.append(sep); sep = ","; - sb.append(new String(Base64.encodeBase64(auth))); + sb.append(new String(Base64.encodeBase64(auth), Constants.UTF8)); } return sb.toString(); Modified: accumulo/trunk/core/src/main/java/org/apache/accumulo/core/security/ColumnVisibility.java URL: http://svn.apache.org/viewvc/accumulo/trunk/core/src/main/java/org/apache/accumulo/core/security/ColumnVisibility.java?rev=1479040&r1=1479039&r2=1479040&view=diff ============================================================================== --- accumulo/trunk/core/src/main/java/org/apache/accumulo/core/security/ColumnVisibility.java (original) +++ accumulo/trunk/core/src/main/java/org/apache/accumulo/core/security/ColumnVisibility.java Sat May 4 05:19:57 2013 @@ -16,7 +16,6 @@ */ package org.apache.accumulo.core.security; -import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -24,6 +23,7 @@ import java.util.Comparator; import java.util.List; import java.util.TreeSet; +import org.apache.accumulo.core.Constants; import org.apache.accumulo.core.data.ArrayByteSequence; import org.apache.accumulo.core.data.ByteSequence; import org.apache.accumulo.core.util.BadArgumentException; @@ -96,7 +96,7 @@ public class ColumnVisibility { public ByteSequence getTerm(byte expression[]) { if (type != NodeType.TERM) throw new RuntimeException(); - + if (expression[start] == '"') { // its a quoted term int qStart = start + 1; @@ -138,26 +138,29 @@ public class ColumnVisibility { return 0; } } - - /* Convience method that delegates to normalize with a new - * NodeComparator constructed using the supplied expression. + + /* + * Convience method that delegates to normalize with a new NodeComparator constructed using the supplied expression. */ private static Node normalize(Node root, byte[] expression) { return normalize(root, expression, new NodeComparator(expression)); - } - - /* Walks an expression's AST in order to: + } + + // @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 private static Node normalize(Node root, byte[] expression, NodeComparator comparator) { - if(root.type != NodeType.TERM) { + if (root.type != NodeType.TERM) { TreeSet<Node> rolledUp = new TreeSet<Node>(comparator); java.util.Iterator<Node> itr = root.children.iterator(); - while(itr.hasNext()) { + while (itr.hasNext()) { Node c = normalize(itr.next(), expression, comparator); - if(c.type == root.type) { + if (c.type == root.type) { rolledUp.addAll(c.children); itr.remove(); } @@ -166,23 +169,22 @@ public class ColumnVisibility { root.children.clear(); root.children.addAll(rolledUp); - //need to promote a child if it's an only child - if(root.children.size() == 1) { + // 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. + + /* + * Walks an expression's AST and appends a string representation to a supplied StringBuilder. This method adds parens where necessary. */ private static void stringify(Node root, byte[] expression, StringBuilder out) { if (root.type == NodeType.TERM) { out.append(new String(expression, root.start, root.end - root.start)); - } - else { + } else { String sep = ""; for (Node c : root.children) { out.append(sep); @@ -196,11 +198,10 @@ public class ColumnVisibility { } } } - + /** - * Generates a byte[] that represents a normalized, but logically equivalent, - * form of the supplied expression. - * + * Generates a byte[] that represents a normalized, but logically equivalent, form of the supplied expression. + * * @return normalized expression in byte[] form */ public byte[] flatten() { @@ -208,7 +209,7 @@ public class ColumnVisibility { StringBuilder builder = new StringBuilder(expression.length); stringify(normRoot, expression, builder); return builder.toString().getBytes(); - } + } private static class ColumnVisibilityParser { private int index = 0; @@ -246,7 +247,7 @@ public class ColumnVisibility { Node expr = null; int termStart = index; boolean termComplete = false; - + while (index < expression.length) { switch (expression[index++]) { case '&': { @@ -304,7 +305,7 @@ public class ColumnVisibility { case '"': { if (termStart != index - 1) throw new BadArgumentException("expression needs & or |", new String(expression), index - 1); - + while (index < expression.length && expression[index] != '"') { if (expression[index] == '\\') { index++; @@ -319,17 +320,17 @@ public class ColumnVisibility { if (termStart + 1 == index) throw new BadArgumentException("empty term", new String(expression), termStart); - + index++; termComplete = true; - + break; } default: { if (termComplete) throw new BadArgumentException("expression needs & or |", new String(expression), index - 1); - + byte c = expression[index - 1]; if (!Authorizations.isValidAuthChar(c)) throw new BadArgumentException("bad character (" + c + ")", new String(expression), index - 1); @@ -358,37 +359,14 @@ public class ColumnVisibility { /** * 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() { expression = new byte[0]; } /** - * See {@link #ColumnVisibility(byte[])} - * - * @param expression - */ - public ColumnVisibility(String expression) { - this(expression.getBytes()); - } - - /** - * See {@link #ColumnVisibility(byte[])} - * - * @param expression - * @param encoding - * uses this encoding to convert the expression to a byte array - * @throws UnsupportedEncodingException - */ - public ColumnVisibility(String expression, String encoding) throws UnsupportedEncodingException { - this(expression.getBytes(encoding)); - } - - public ColumnVisibility(Text expression) { - this(TextUtil.getBytes(expression)); - } - - /** * Set the column visibility for a Mutation. * * @param expression @@ -422,17 +400,35 @@ public class ColumnVisibility { * them with '\'. The {@link #quote(String)} method will properly quote and escape terms for you. * * <pre> - * "A#C"&B + * "A#C"<span />&<span />B * </pre> * */ + public ColumnVisibility(String expression) { + this(expression.getBytes(Constants.UTF8)); + } + + /** + * A convenience method for constructing from a string already encoded in UTF-8 bytes and contained in a {@link Text} object. + * + * @see #ColumnVisibility(String) + */ + public ColumnVisibility(Text expression) { + this(TextUtil.getBytes(expression)); + } + + /** + * A convenience method for constructing from a string already encoded in UTF-8 bytes. + * + * @see #ColumnVisibility(String) + */ public ColumnVisibility(byte[] expression) { validate(expression); } @Override public String toString() { - return "[" + new String(expression) + "]"; + return "[" + new String(expression, Constants.UTF8) + "]"; } /** @@ -462,26 +458,6 @@ public class ColumnVisibility { } /** - * see {@link #quote(byte[])} - * - */ - public static String quote(String term) { - return quote(term, "UTF-8"); - } - - /** - * see {@link #quote(byte[])} - * - */ - public static String quote(String term, String encoding) { - try { - return new String(quote(term.getBytes(encoding)), encoding); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - - /** * Use to properly quote terms in a column visibility expression. If no quoting is needed, then nothing is done. * * <p> @@ -496,7 +472,15 @@ public class ColumnVisibility { * </pre> * */ - + public static String quote(String term) { + return new String(quote(term.getBytes(Constants.UTF8)), Constants.UTF8); + } + + /** + * A convenience method to quote terms which are already encoded as UTF-8 bytes. + * + * @see #quote(String) + */ public static byte[] quote(byte[] term) { boolean needsQuote = false; Modified: accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/AuthorizationsTest.java URL: http://svn.apache.org/viewvc/accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/AuthorizationsTest.java?rev=1479040&r1=1479039&r2=1479040&view=diff ============================================================================== --- accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/AuthorizationsTest.java (original) +++ accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/AuthorizationsTest.java Sat May 4 05:19:57 2013 @@ -41,6 +41,12 @@ public class AuthorizationsTest { array = a.getAuthorizationsArray(); b = new Authorizations(array); assertEquals(a, b); + + // test encoding multi-byte auths + a = new Authorizations("äº", "b", "c", "ä¹"); + array = a.getAuthorizationsArray(); + b = new Authorizations(array); + assertEquals(a, b); } @Test Modified: accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/ColumnVisibilityTest.java URL: http://svn.apache.org/viewvc/accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/ColumnVisibilityTest.java?rev=1479040&r1=1479039&r2=1479040&view=diff ============================================================================== --- accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/ColumnVisibilityTest.java (original) +++ accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/ColumnVisibilityTest.java Sat May 4 05:19:57 2013 @@ -16,7 +16,9 @@ */ package org.apache.accumulo.core.security; +import static org.apache.accumulo.core.security.ColumnVisibility.quote; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import org.junit.Test; @@ -84,7 +86,7 @@ public class ColumnVisibilityTest { normalized("a", "a", "(a)", "a", "b|a", "a|b", "(b)|a", "a|b", "(b|(a|c))&x", "x&(a|b|c)", "(((a)))", "a"); final String normForm = "a&b&c"; normalized("b&c&a", normForm, "c&b&a", normForm, "a&(b&c)", normForm, "(a&c)&b", normForm); - + // this an expression that's basically `expr | expr` normalized("(d&c&b&a)|(b&c&a&d)", "a&b&c&d"); } @@ -133,4 +135,14 @@ public class ColumnVisibilityTest { shouldNotThrow("A&\"B\\\\D\""); shouldNotThrow("A&\"B\\\"D\""); } + + @Test + public void testToString() { + ColumnVisibility cv = new ColumnVisibility(quote("a")); + assertEquals("[a]", cv.toString()); + + // multi-byte + cv = new ColumnVisibility(quote("äº")); + assertEquals("[\"äº\"]", cv.toString()); + } } Modified: accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/VisibilityEvaluatorTest.java URL: http://svn.apache.org/viewvc/accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/VisibilityEvaluatorTest.java?rev=1479040&r1=1479039&r2=1479040&view=diff ============================================================================== --- accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/VisibilityEvaluatorTest.java (original) +++ accumulo/trunk/core/src/test/java/org/apache/accumulo/core/security/VisibilityEvaluatorTest.java Sat May 4 05:19:57 2013 @@ -22,9 +22,6 @@ import static org.junit.Assert.assertFal import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; - import org.apache.accumulo.core.util.BadArgumentException; import org.apache.accumulo.core.util.ByteArraySet; import org.junit.Test; @@ -116,14 +113,14 @@ public class VisibilityEvaluatorTest { } @Test - public void testNonAscii() throws VisibilityParseException, UnsupportedEncodingException { - VisibilityEvaluator ct = new VisibilityEvaluator(new Authorizations(Charset.forName("UTF-8"), "äº", "å ", "å «", "ä¹", "äºå")); + public void testNonAscii() throws VisibilityParseException { + VisibilityEvaluator ct = new VisibilityEvaluator(new Authorizations("äº", "å ", "å «", "ä¹", "äºå")); - assertTrue(ct.evaluate(new ColumnVisibility(quote("äº") + "|" + quote("å"), "UTF-8"))); - assertFalse(ct.evaluate(new ColumnVisibility(quote("äº") + "&" + quote("å"), "UTF-8"))); - assertTrue(ct.evaluate(new ColumnVisibility(quote("äº") + "&(" + quote("å") + "|" + quote("ä¹") + ")", "UTF-8"))); - assertTrue(ct.evaluate(new ColumnVisibility("\"äº\"&(\"å\"|\"äºå\")", "UTF-8"))); - assertFalse(ct.evaluate(new ColumnVisibility(quote("äº") + "&(" + quote("å") + "|" + quote("ä¸") + ")", "UTF-8"))); - assertFalse(ct.evaluate(new ColumnVisibility("\"äº\"&(\"å\"|\"ä¸\")", "UTF-8"))); + assertTrue(ct.evaluate(new ColumnVisibility(quote("äº") + "|" + quote("å")))); + assertFalse(ct.evaluate(new ColumnVisibility(quote("äº") + "&" + quote("å")))); + assertTrue(ct.evaluate(new ColumnVisibility(quote("äº") + "&(" + quote("å") + "|" + quote("ä¹") + ")"))); + assertTrue(ct.evaluate(new ColumnVisibility("\"äº\"&(\"å\"|\"äºå\")"))); + assertFalse(ct.evaluate(new ColumnVisibility(quote("äº") + "&(" + quote("å") + "|" + quote("ä¸") + ")"))); + assertFalse(ct.evaluate(new ColumnVisibility("\"äº\"&(\"å\"|\"ä¸\")"))); } } Propchange: accumulo/trunk/examples/ ------------------------------------------------------------------------------ Merged /accumulo/branches/1.5/examples:r1479001-1479039 Propchange: accumulo/trunk/fate/src/main/java/org/apache/accumulo/fate/ZooStore.java ------------------------------------------------------------------------------ Merged /accumulo/branches/1.5/fate/src/main/java/org/apache/accumulo/fate/ZooStore.java:r1479001-1479039 Propchange: accumulo/trunk/fate/src/main/java/org/apache/accumulo/fate/zookeeper/ZooSession.java ------------------------------------------------------------------------------ Merged /accumulo/branches/1.5/fate/src/main/java/org/apache/accumulo/fate/zookeeper/ZooSession.java:r1479001-1479039 Propchange: accumulo/trunk/pom.xml ------------------------------------------------------------------------------ Merged /accumulo/branches/1.5/pom.xml:r1479001-1479039 Propchange: accumulo/trunk/server/ ------------------------------------------------------------------------------ Merged /accumulo/branches/1.5/server:r1479001-1479039 Propchange: accumulo/trunk/src/ ------------------------------------------------------------------------------ Merged /accumulo/branches/1.5/src:r1479001-1479039