Index: hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestRowKeyBuilder.java
===================================================================
--- hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestRowKeyBuilder.java (revision 0)
+++ hbase-common/src/test/java/org/apache/hadoop/hbase/util/TestRowKeyBuilder.java (revision 0)
@@ -0,0 +1,93 @@
+/*
+ * 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.hadoop.hbase.util;
+
+import java.nio.ByteBuffer;
+
+import org.apache.hadoop.hbase.util.Bytes;
+import org.junit.Assert;
+import org.junit.Test;
+import org.apache.hadoop.hbase.SmallTests;
+import org.junit.experimental.categories.Category;
+
+@Category(SmallTests.class)
+public class TestRowKeyBuilder {
+
+ private int a = 5;
+ private long b = 6;
+
+
+ @Test
+ public void testInt() {
+ RowKey key = RowKey.create(RowKey.SIZEOF_INT);
+ key.add(a);
+
+ byte bytes[] = key.getBytes();
+ Assert.assertEquals("key length", RowKey.SIZEOF_INT, bytes.length);
+
+ byte aBytes[] = Bytes.toBytes(a);
+ compareArrays(bytes, aBytes);
+ }
+
+ @Test
+ public void testLong() {
+ RowKey key = RowKey.create(RowKey.SIZEOF_LONG);
+ key.add(b);
+
+ byte bytes[] = key.getBytes();
+ Assert.assertEquals("key length", RowKey.SIZEOF_LONG, bytes.length);
+
+ byte aBytes[] = Bytes.toBytes(b);
+ compareArrays(bytes, aBytes);
+ }
+
+ @Test
+ public void testHash() throws Exception {
+ RowKey key = RowKey.create(RowKey.SIZEOF_MD5_HASH);
+ key.addHash(a);
+
+ byte bytes[] = key.getBytes();
+ Assert.assertEquals("key length", RowKey.SIZEOF_MD5_HASH, bytes.length);
+ }
+
+ @Test
+ public void testHashComposite() throws Exception {
+ //
+ // this tests creating a composite key with an MD5 hash in the lead position, followed by a long.
+ //
+ int expectedLength = RowKey.SIZEOF_MD5_HASH + RowKey.SIZEOF_LONG;
+
+ RowKey key = RowKey.create(expectedLength);
+ key.addHash(b);
+ key.add(b);
+
+ byte bytes[] = key.getBytes();
+ Assert.assertEquals("key length", expectedLength, bytes.length);
+ }
+
+
+ private void compareArrays(byte a[], byte[] b) {
+ if (a.length != b.length) {
+ Assert.fail("Byte arrays not the same length");
+ }
+ for (int i = 0; i < a.length; i++) {
+ if (a[i] != b[i]) {
+ Assert.fail("Byte arrays not the same at position " + i);
+ }
+ }
+ }
+}
Index: hbase-common/src/main/java/org/apache/hadoop/hbase/util/RowKeyBuilder.java
===================================================================
--- hbase-common/src/main/java/org/apache/hadoop/hbase/util/RowKeyBuilder.java (revision 0)
+++ hbase-common/src/main/java/org/apache/hadoop/hbase/util/RowKeyBuilder.java (revision 0)
@@ -0,0 +1,168 @@
+/**
+ *
+ * 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.hadoop.hbase.util;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.hadoop.hbase.util.Bytes;
+
+/**
+ * A stateful utility class for creating rowkeys for HBase tables, particularly composite keys.
+ * The length of the key must be known upon construction of each RowKeyBuilder instance and will not auto-expand.
+ * RowKeyBuilder instances can be constructed and used as follows:
+ *
+ * RowKeyBuilder key = RowKeyBuilder.create(RowKey.SIZEOF_MD5_HASH + RowKey.SIZEOF_LONG); + * key.addHash(a); + * key.add(b); + * byte bytes[] = key.getBytes(); + *+ * The above example specifies that the key is comprised of an MD5 hash followed by a long. + * + */ +public class RowKeyBuilder { + + private static final String MD5 = "MD5"; + + public static final int SIZEOF_MD5_HASH = 16; + public static final int SIZEOF_BYTE = Bytes.SIZEOF_BYTE; + public static final int SIZEOF_INT = Bytes.SIZEOF_INT; + public static final int SIZEOF_LONG = Bytes.SIZEOF_LONG; + + private byte bytes[] = null; + int pos = 0; + private MessageDigest digest = null; + + private RowKeyBuilder(int length) { + bytes = new byte[length]; + } + + /** + * Addds a byte to the rowkey. + * + * @param b byte + */ + public void add(byte b) { + add(b); + } + + /** + * Adds an int to the rowkey + * + * @param i (int) + */ + public void add(int i) { + add(Bytes.toBytes(i)); + } + + /** + * Adds a long to the rowkey + * + * @param l (long) + */ + public void add(long l) { + add(Bytes.toBytes(l)); + } + + /** + * Adds a bytearray to the rowkey + * + * @param b (bytes) + */ + public void add(byte[] b) { + System.arraycopy(b, 0, bytes, pos, b.length); + pos += b.length; + } + + /** + * Adds an int, which will be MD5 hashed, to the rowkey. + * + * @param i (int that will be hashed) + * @throws NoSuchAlgorithmException + */ + public void addHash(int i) throws NoSuchAlgorithmException { + addHash(Bytes.toBytes(i)); + } + + /** + * Adds a long, which will be MD5 hashed, to the rowkey. + * + * @param l (long that will be hashed) + * @throws NoSuchAlgorithmException + */ + public void addHash(long l) throws NoSuchAlgorithmException { + addHash(Bytes.toBytes(l)); + } + + /** + * Adds a String, which will be MD5 hashed, to the rowkey. + * + * @param s (String that will be hashed) + * @throws NoSuchAlgorithmException + */ + public void addHash(String s) throws NoSuchAlgorithmException { + addHash(s.getBytes()); + } + + /** + * Adds an array of bytes, which will be MD5 hashed, to the rowkey. + * + * @param b (bytes that will be hashed) + * @throws NoSuchAlgorithmException + */ + public void addHash(byte[] b) throws NoSuchAlgorithmException { + if (digest == null) { + digest = MessageDigest.getInstance(MD5); + } + byte[] dig = digest.digest(b); + add(dig); + } + + /** + * + * @return byte array backing the RowKeyBuilder. These are the bytes that can be used as the rowkey in your HBase table. + */ + public byte[] getBytes() { + return bytes; + } + + /** + * Resets and empties the backing byte array to the same length originally specified when constructed. + */ + public void reset() { + int l = bytes.length; + bytes = new byte[l]; + } + + /** + * Factory method for creating a RowKeyBuilder instance. The length of the key must be known upon construction of each + * RowKeyBuilder instance and will not auto-resize. RowKeyBuilder instances can be created as follows: + *
+ * RowKeyBuilder key = RowKeyBuilder.create(RowKey.SIZEOF_MD5_HASH + RowKey.SIZEOF_LONG); + *+ * The above example specifies that the key is to be comprised of an MD5 hash followed by a long. + * + * @param length The total length of the RowKey + * @return RowKeyBuilder + */ + public static RowKeyBuilder create(int length) { + return new RowKeyBuilder(length); + } + +}