You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by ct...@apache.org on 2014/04/09 19:58:32 UTC

[61/64] [abbrv] Merge branch '1.5.2-SNAPSHOT' into 1.6.0-SNAPSHOT

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/core/src/main/java/org/apache/accumulo/core/security/crypto/CryptoModuleParameters.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/apache/accumulo/core/security/crypto/CryptoModuleParameters.java
index 5ae072a,0000000..244a877
mode 100644,000000..100644
--- a/core/src/main/java/org/apache/accumulo/core/security/crypto/CryptoModuleParameters.java
+++ b/core/src/main/java/org/apache/accumulo/core/security/crypto/CryptoModuleParameters.java
@@@ -1,643 -1,0 +1,637 @@@
 +/*
 + * 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.accumulo.core.security.crypto;
 +
 +import java.io.FilterOutputStream;
 +import java.io.InputStream;
 +import java.io.OutputStream;
 +import java.security.SecureRandom;
 +import java.util.Map;
 +
 +import javax.crypto.Cipher;
 +import javax.crypto.CipherOutputStream;
 +
 +/**
 + * This class defines several parameters needed by by a module providing cryptographic stream support in Accumulo. The following Javadoc details which
 + * parameters are used for which operations (encryption vs. decryption), which ones return values (i.e. are "out" parameters from the {@link CryptoModule}), and
 + * which ones are required versus optional in certain situations.
 + * 
 + * Most of the time, these classes can be constructed using
 + * {@link CryptoModuleFactory#createParamsObjectFromAccumuloConfiguration(org.apache.accumulo.core.conf.AccumuloConfiguration)}.
 + */
 +public class CryptoModuleParameters {
 +  
 +  /**
 +   * Gets the name of the symmetric algorithm to use for encryption.
 +   * 
 +   * @see CryptoModuleParameters#setAlgorithmName(String)
 +   */
 +  
 +  public String getAlgorithmName() {
 +    return algorithmName;
 +  }
 +  
 +  /**
 +   * Sets the name of the symmetric algorithm to use for an encryption stream.
 +   * <p>
 +   * Valid names are names recognized by your cryptographic engine provider. For the default Java provider, valid names would include things like "AES", "RC4",
 +   * "DESede", etc.
 +   * <p>
 +   * For <b>encryption</b>, this value is <b>required</b> and is always used. Its value should be prepended or otherwise included with the ciphertext for future
 +   * decryption. <br>
 +   * For <b>decryption</b>, this value is often disregarded in favor of the value encoded with the ciphertext.
 +   * 
 +   * @param algorithmName
 +   *          the name of the cryptographic algorithm to use.
 +   * @see <a href="http://docs.oracle.com/javase/1.5.0/docs/guide/security/jce/JCERefGuide.html#AppA">Standard Algorithm Names in JCE</a>
 +   * 
 +   */
 +  
 +  public void setAlgorithmName(String algorithmName) {
 +    this.algorithmName = algorithmName;
 +  }
 +  
 +  /**
 +   * Gets the name of the encryption mode to use for encryption.
 +   * 
 +   * @see CryptoModuleParameters#setEncryptionMode(String)
 +   */
 +  
 +  public String getEncryptionMode() {
 +    return encryptionMode;
 +  }
 +  
 +  /**
 +   * Sets the name of the encryption mode to use for an encryption stream.
 +   * <p>
 +   * Valid names are names recognized by your cryptographic engine provider. For the default Java provider, valid names would include things like "EBC", "CBC",
 +   * "CFB", etc.
 +   * <p>
 +   * For <b>encryption</b>, this value is <b>required</b> and is always used. Its value should be prepended or otherwise included with the ciphertext for future
 +   * decryption. <br>
 +   * For <b>decryption</b>, this value is often disregarded in favor of the value encoded with the ciphertext.
 +   * 
 +   * @param encryptionMode
 +   *          the name of the encryption mode to use.
 +   * @see <a href="http://docs.oracle.com/javase/1.5.0/docs/guide/security/jce/JCERefGuide.html#AppA">Standard Mode Names in JCE</a>
 +   * 
 +   */
 +  
 +  public void setEncryptionMode(String encryptionMode) {
 +    this.encryptionMode = encryptionMode;
 +  }
 +  
 +  /**
 +   * Gets the name of the padding type to use for encryption.
 +   * 
 +   * @see CryptoModuleParameters#setPadding(String)
 +   */
 +  
 +  public String getPadding() {
 +    return padding;
 +  }
 +  
 +  /**
 +   * Sets the name of the padding type to use for an encryption stream.
 +   * <p>
 +   * Valid names are names recognized by your cryptographic engine provider. For the default Java provider, valid names would include things like "NoPadding",
 +   * "None", etc.
 +   * <p>
 +   * For <b>encryption</b>, this value is <b>required</b> and is always used. Its value should be prepended or otherwise included with the ciphertext for future
 +   * decryption. <br>
 +   * For <b>decryption</b>, this value is often disregarded in favor of the value encoded with the ciphertext.
 +   * 
 +   * @param padding
 +   *          the name of the padding type to use.
 +   * @see <a href="http://docs.oracle.com/javase/1.5.0/docs/guide/security/jce/JCERefGuide.html#AppA">Standard Padding Names in JCE</a>
 +   * 
 +   */
 +  public void setPadding(String padding) {
 +    this.padding = padding;
 +  }
 +  
 +  /**
 +   * Gets the plaintext secret key.
 +   * <p>
 +   * For <b>decryption</b>, this value is often the out parameter of using a secret key encryption strategy to decrypt an encrypted version of this secret key.
 +   * (See {@link CryptoModuleParameters#setKeyEncryptionStrategyClass(String)}.)
 +   * 
 +   * 
 +   * @see CryptoModuleParameters#setPlaintextKey(byte[])
 +   */
 +  public byte[] getPlaintextKey() {
 +    return plaintextKey;
 +  }
 +  
 +  /**
 +   * Sets the plaintext secret key that will be used to encrypt and decrypt bytes.
 +   * <p>
 +   * Valid values and lengths for this secret key depend entirely on the algorithm type. Refer to the documentation about the algorithm for further information.
 +   * <p>
 +   * For <b>encryption</b>, this value is <b>optional</b>. If it is not provided, it will be automatically generated by the underlying cryptographic module. <br>
 +   * For <b>decryption</b>, this value is often obtained from the underlying cipher stream, or derived from the encrypted version of the key (see
 +   * {@link CryptoModuleParameters#setEncryptedKey(byte[])}).
 +   * 
 +   * @param plaintextKey
 +   *          the value of the plaintext secret key
 +   */
 +  
 +  public void setPlaintextKey(byte[] plaintextKey) {
 +    this.plaintextKey = plaintextKey;
 +  }
 +  
 +  /**
 +   * Gets the length of the secret key.
 +   * 
 +   * @see CryptoModuleParameters#setKeyLength(int)
 +   */
 +  public int getKeyLength() {
 +    return keyLength;
 +  }
 +  
 +  /**
 +   * Sets the length of the secret key that will be used to encrypt and decrypt bytes.
 +   * <p>
 +   * Valid lengths depend entirely on the algorithm type. Refer to the documentation about the algorithm for further information. (For example, AES may use
 +   * either 128 or 256 bit keys in the default Java cryptography provider.)
 +   * <p>
 +   * For <b>encryption</b>, this value is <b>required if the secret key is not set</b>. <br>
 +   * For <b>decryption</b>, this value is often obtained from the underlying cipher stream, or derived from the encrypted version of the key (see
 +   * {@link CryptoModuleParameters#setEncryptedKey(byte[])}).
 +   * 
 +   * @param keyLength
 +   *          the length of the secret key to be generated
 +   */
 +  
 +  public void setKeyLength(int keyLength) {
 +    this.keyLength = keyLength;
 +  }
 +  
 +  /**
 +   * Gets the random number generator name.
 +   * 
 +   * @see CryptoModuleParameters#setRandomNumberGenerator(String)
 +   */
 +  
 +  public String getRandomNumberGenerator() {
 +    return randomNumberGenerator;
 +  }
 +  
 +  /**
 +   * Sets the name of the random number generator to use. The default for this for the baseline JCE implementation is "SHA1PRNG".
 +   * <p>
 +   * 
 +   * <p>
 +   * For <b>encryption</b>, this value is <b>required</b>. <br>
 +   * For <b>decryption</b>, this value is often obtained from the underlying cipher stream.
 +   * 
 +   * @param randomNumberGenerator
 +   *          the name of the random number generator to use
 +   */
 +  
 +  public void setRandomNumberGenerator(String randomNumberGenerator) {
 +    this.randomNumberGenerator = randomNumberGenerator;
 +  }
 +  
 +  /**
 +   * Gets the random number generator provider name.
 +   * 
 +   * @see CryptoModuleParameters#setRandomNumberGeneratorProvider(String)
 +   */
 +  public String getRandomNumberGeneratorProvider() {
 +    return randomNumberGeneratorProvider;
 +  }
 +  
 +  /**
 +   * Sets the name of the random number generator provider to use. The default for this for the baseline JCE implementation is "SUN".
 +   * <p>
 +   * The provider, as the name implies, provides the RNG implementation specified by {@link CryptoModuleParameters#getRandomNumberGenerator()}.
 +   * <p>
 +   * For <b>encryption</b>, this value is <b>required</b>. <br>
 +   * For <b>decryption</b>, this value is often obtained from the underlying cipher stream.
 +   * 
 +   * @param randomNumberGeneratorProvider
 +   *          the name of the provider to use
 +   */
 +  
 +  public void setRandomNumberGeneratorProvider(String randomNumberGeneratorProvider) {
 +    this.randomNumberGeneratorProvider = randomNumberGeneratorProvider;
 +  }
 +  
 +  /**
 +   * Gets the key encryption strategy class.
 +   * 
 +   * @see CryptoModuleParameters#setKeyEncryptionStrategyClass(String)
 +   */
 +  
 +  public String getKeyEncryptionStrategyClass() {
 +    return keyEncryptionStrategyClass;
 +  }
 +  
 +  /**
 +   * Sets the class name of the key encryption strategy class. The class obeys the {@link SecretKeyEncryptionStrategy} interface. It instructs the
 +   * {@link DefaultCryptoModule} on how to encrypt the keys it uses to secure the streams.
 +   * <p>
 +   * The default implementation of this interface, {@link CachingHDFSSecretKeyEncryptionStrategy}, creates a random key encryption key (KEK) as another symmetric
 +   * key and places the KEK into HDFS. <i>This is not really very secure.</i> Users of the crypto modules are encouraged to either safeguard that KEK carefully
 +   * or to obtain and use another {@link SecretKeyEncryptionStrategy} class.
 +   * <p>
 +   * For <b>encryption</b>, this value is <b>optional</b>. If it is not specified, then it assumed that the secret keys used for encrypting files will not be
 +   * encrypted. This is not a secure approach, thus setting this is highly recommended.<br>
 +   * For <b>decryption</b>, this value is often obtained from the underlying cipher stream. However, the underlying stream's value can be overridden (at least
 +   * when using {@link DefaultCryptoModule}) by setting the {@link CryptoModuleParameters#setOverrideStreamsSecretKeyEncryptionStrategy(boolean)} to true.
 +   * 
 +   * @param keyEncryptionStrategyClass
 +   *          the name of the key encryption strategy class to use
 +   */
 +  public void setKeyEncryptionStrategyClass(String keyEncryptionStrategyClass) {
 +    this.keyEncryptionStrategyClass = keyEncryptionStrategyClass;
 +  }
 +  
 +  /**
 +   * Gets the encrypted version of the plaintext key. This parameter is generally either obtained from an underlying stream or computed in the process of
 +   * employed the {@link CryptoModuleParameters#getKeyEncryptionStrategyClass()}.
 +   * 
 +   * @see CryptoModuleParameters#setEncryptedKey(byte[])
 +   */
 +  public byte[] getEncryptedKey() {
 +    return encryptedKey;
 +  }
 +  
 +  /**
 +   * Sets the encrypted version of the plaintext key ({@link CryptoModuleParameters#getPlaintextKey()}). Generally this operation will be done either by:
 +   * <p>
 +   * <ul>
 +   * <li>the code reading an encrypted stream and coming across the encrypted version of one of these keys, OR
 +   * <li>the {@link CryptoModuleParameters#getKeyEncryptionStrategyClass()} that encrypted the plaintext key (see
 +   * {@link CryptoModuleParameters#getPlaintextKey()}).
 +   * <ul>
 +   * <p>
 +   * For <b>encryption</b>, this value is generally not required, but is usually set by the underlying module during encryption. <br>
 +   * For <b>decryption</b>, this value is <b>usually required</b>.
 +   * 
 +   * 
 +   * @param encryptedKey
 +   *          the encrypted value of the plaintext key
 +   */
 +  
 +  public void setEncryptedKey(byte[] encryptedKey) {
 +    this.encryptedKey = encryptedKey;
 +  }
 +  
 +  /**
 +   * Gets the opaque ID associated with the encrypted version of the plaintext key.
 +   * 
 +   * @see CryptoModuleParameters#setOpaqueKeyEncryptionKeyID(String)
 +   */
 +  public String getOpaqueKeyEncryptionKeyID() {
 +    return opaqueKeyEncryptionKeyID;
 +  }
 +  
 +  /**
 +   * Sets an opaque ID assocaited with the encrypted version of the plaintext key.
 +   * <p>
 +   * Often, implementors of the {@link SecretKeyEncryptionStrategy} will need to record some information about how they encrypted a particular plaintext key.
 +   * For example, if the strategy employs several keys for its encryption, it will want to record which key it used. The caller should not have to worry about
 +   * the format or contents of this internal ID; thus, the strategy class will encode whatever information it needs into this string. It is then beholden to the
 +   * calling code to record this opqaue string properly to the underlying cryptographically-encoded stream, and then set the opaque ID back into this parameter
 +   * object upon reading.
 +   * <p>
 +   * For <b>encryption</b>, this value is generally not required, but will be typically generated and set by the {@link SecretKeyEncryptionStrategy} class (see
 +   * {@link CryptoModuleParameters#getKeyEncryptionStrategyClass()}). <br>
 +   * For <b>decryption</b>, this value is <b>required</b>, though it will typically be read from the underlying stream.
 +   * 
 +   * @param opaqueKeyEncryptionKeyID
 +   *          the opaque ID assoicated with the encrypted version of the plaintext key (see {@link CryptoModuleParameters#getEncryptedKey()}).
 +   */
 +  
 +  public void setOpaqueKeyEncryptionKeyID(String opaqueKeyEncryptionKeyID) {
 +    this.opaqueKeyEncryptionKeyID = opaqueKeyEncryptionKeyID;
 +  }
 +  
 +  /**
 +   * Gets the flag that indicates whether or not the module should record its cryptographic parameters to the stream automatically, or rely on the calling code
 +   * to do so.
 +   * 
 +   * @see CryptoModuleParameters#setRecordParametersToStream(boolean)
 +   */
 +  public boolean getRecordParametersToStream() {
 +    return recordParametersToStream;
 +  }
 +  
 +  /**
 +   * Gets the flag that indicates whether or not the module should record its cryptographic parameters to the stream automatically, or rely on the calling code
 +   * to do so.
 +   * 
 +   * <p>
 +   * 
 +   * If this is set to <i>true</i>, then the stream passed to {@link CryptoModule#getEncryptingOutputStream(CryptoModuleParameters)} will be <i>written to by
 +   * the module</i> before it is returned to the caller. There are situations where it is easier to let the crypto module do this writing on behalf of the
 +   * caller, and other times where it is not appropriate (if the format of the underlying stream must be carefully maintained, for instance).
 +   * 
 +   * @param recordParametersToStream
 +   *          whether or not to require the module to record its parameters to the stream by itself
 +   */
 +  public void setRecordParametersToStream(boolean recordParametersToStream) {
 +    this.recordParametersToStream = recordParametersToStream;
 +  }
 +  
 +  /**
 +   * Gets the flag that indicates whether or not to close the underlying stream when the cipher stream is closed.
 +   * 
 +   * @see CryptoModuleParameters#setCloseUnderylingStreamAfterCryptoStreamClose(boolean)
 +   */
 +  public boolean getCloseUnderylingStreamAfterCryptoStreamClose() {
 +    return closeUnderylingStreamAfterCryptoStreamClose;
 +  }
 +  
 +  /**
 +   * Sets the flag that indicates whether or not to close the underlying stream when the cipher stream is closed.
 +   * 
 +   * <p>
 +   * 
 +   * {@link CipherOutputStream} will only output its padding bytes when its {@link CipherOutputStream#close()} method is called. However, there are times when a
 +   * caller doesn't want its underlying stream closed at the time that the {@link CipherOutputStream} is closed. This flag indicates that the
 +   * {@link CryptoModule} should wrap the underlying stream in a basic {@link FilterOutputStream} which will swallow any close() calls and prevent them from
 +   * propogating to the underlying stream.
 +   * 
 +   * @param closeUnderylingStreamAfterCryptoStreamClose
 +   *          the flag that indicates whether or not to close the underlying stream when the cipher stream is closed
 +   */
 +  public void setCloseUnderylingStreamAfterCryptoStreamClose(boolean closeUnderylingStreamAfterCryptoStreamClose) {
 +    this.closeUnderylingStreamAfterCryptoStreamClose = closeUnderylingStreamAfterCryptoStreamClose;
 +  }
 +  
 +  /**
 +   * Gets the flag that indicates if the underlying stream's key encryption strategy should be overridden by the currently configured key encryption strategy.
 +   * 
 +   * @see CryptoModuleParameters#setOverrideStreamsSecretKeyEncryptionStrategy(boolean)
 +   */
 +  public boolean getOverrideStreamsSecretKeyEncryptionStrategy() {
 +    return overrideStreamsSecretKeyEncryptionStrategy;
 +  }
 +  
 +  /**
 +   * Sets the flag that indicates if the underlying stream's key encryption strategy should be overridden by the currently configured key encryption strategy.
 +   * 
 +   * <p>
 +   * 
 +   * So, why is this important? Say you started out with the default secret key encryption strategy. So, now you have a secret key in HDFS that encrypts all the
 +   * other secret keys. <i>Then</i> you deploy a key management solution. You want to move that secret key up to the key management server. Great! No problem.
 +   * Except, all your encrypted files now contain a setting that says
 +   * "hey I was encrypted by the default strategy, so find decrypt my key using that, not the key management server". This setting signals the
 +   * {@link CryptoModule} that it should ignore the setting in the file and prefer the one from the configuration.
 +   * 
 +   * @param overrideStreamsSecretKeyEncryptionStrategy
 +   *          the flag that indicates if the underlying stream's key encryption strategy should be overridden by the currently configured key encryption
 +   *          strategy
 +   */
 +  
 +  public void setOverrideStreamsSecretKeyEncryptionStrategy(boolean overrideStreamsSecretKeyEncryptionStrategy) {
 +    this.overrideStreamsSecretKeyEncryptionStrategy = overrideStreamsSecretKeyEncryptionStrategy;
 +  }
 +  
 +  /**
 +   * Gets the plaintext output stream to wrap for encryption.
 +   * 
 +   * @see CryptoModuleParameters#setPlaintextOutputStream(OutputStream)
 +   */
 +  public OutputStream getPlaintextOutputStream() {
 +    return plaintextOutputStream;
 +  }
 +  
 +  /**
 +   * Sets the plaintext output stream to wrap for encryption.
 +   * 
 +   * <p>
 +   * 
 +   * For <b>encryption</b>, this parameter is <b>required</b>. <br>
 +   * For <b>decryption</b>, this parameter is ignored.
-    * 
-    * @param plaintextOutputStream
 +   */
 +  public void setPlaintextOutputStream(OutputStream plaintextOutputStream) {
 +    this.plaintextOutputStream = plaintextOutputStream;
 +  }
 +  
 +  /**
 +   * Gets the encrypted output stream, which is nearly always a wrapped version of the output stream from
 +   * {@link CryptoModuleParameters#getPlaintextOutputStream()}.
 +   * 
 +   * <p>
 +   * 
 +   * Generally this method is used by {@link CryptoModule} classes as an <i>out</i> parameter from calling
 +   * {@link CryptoModule#getEncryptingOutputStream(CryptoModuleParameters)}.
 +   * 
 +   * @see CryptoModuleParameters#setEncryptedOutputStream(OutputStream)
 +   */
 +  
 +  public OutputStream getEncryptedOutputStream() {
 +    return encryptedOutputStream;
 +  }
 +  
 +  /**
 +   * Sets the encrypted output stream. This method should really only be called by {@link CryptoModule} implementations unless something very unusual is going
 +   * on.
 +   * 
 +   * @param encryptedOutputStream
 +   *          the encrypted version of the stream from output stream from {@link CryptoModuleParameters#getPlaintextOutputStream()}.
 +   */
 +  public void setEncryptedOutputStream(OutputStream encryptedOutputStream) {
 +    this.encryptedOutputStream = encryptedOutputStream;
 +  }
 +  
 +  /**
 +   * Gets the plaintext input stream, which is nearly always a wrapped version of the output from {@link CryptoModuleParameters#getEncryptedInputStream()}.
 +   * 
 +   * <p>
 +   * 
 +   * Generally this method is used by {@link CryptoModule} classes as an <i>out</i> parameter from calling
 +   * {@link CryptoModule#getDecryptingInputStream(CryptoModuleParameters)}.
 +   * 
 +   * 
 +   * @see CryptoModuleParameters#setPlaintextInputStream(InputStream)
 +   */
 +  public InputStream getPlaintextInputStream() {
 +    return plaintextInputStream;
 +  }
 +  
 +  /**
 +   * Sets the plaintext input stream, which is nearly always a wrapped version of the output from {@link CryptoModuleParameters#getEncryptedInputStream()}.
 +   * 
 +   * <p>
 +   * 
 +   * This method should really only be called by {@link CryptoModule} implementations.
-    * 
-    * @param plaintextInputStream
 +   */
 +  
 +  public void setPlaintextInputStream(InputStream plaintextInputStream) {
 +    this.plaintextInputStream = plaintextInputStream;
 +  }
 +  
 +  /**
 +   * Gets the encrypted input stream to wrap for decryption.
 +   * 
 +   * @see CryptoModuleParameters#setEncryptedInputStream(InputStream)
 +   */
 +  public InputStream getEncryptedInputStream() {
 +    return encryptedInputStream;
 +  }
 +  
 +  /**
 +   * Sets the encrypted input stream to wrap for decryption.
-    * 
-    * @param encryptedInputStream
 +   */
 +  
 +  public void setEncryptedInputStream(InputStream encryptedInputStream) {
 +    this.encryptedInputStream = encryptedInputStream;
 +  }
 +  
 +  /**
 +   * Gets the initialized cipher object.
 +   * 
 +   * 
 +   * @see CryptoModuleParameters#setCipher(Cipher)
 +   */
 +  public Cipher getCipher() {
 +    return cipher;
 +  }
 +  
 +  /**
 +   * Sets the initialized cipher object. Generally speaking, callers do not have to create and set this object. There may be circumstances where the cipher
 +   * object is created outside of the module (to determine IV lengths, for one). If it is created and you want the module to use the cipher you already
 +   * initialized, set it here.
 +   * 
 +   * @param cipher
 +   *          the cipher object
 +   */
 +  public void setCipher(Cipher cipher) {
 +    this.cipher = cipher;
 +  }
 +  
 +  /**
 +   * Gets the initialized secure random object.
 +   * 
 +   * @see CryptoModuleParameters#setSecureRandom(SecureRandom)
 +   */
 +  public SecureRandom getSecureRandom() {
 +    return secureRandom;
 +  }
 +  
 +  /**
 +   * Sets the initialized secure random object. Generally speaking, callers do not have to create and set this object. There may be circumstances where the
 +   * random object is created outside of the module (for instance, to create a random secret key). If it is created outside the module and you want the module
 +   * to use the random object you already created, set it here.
 +   * 
 +   * @param secureRandom
 +   *          the {@link SecureRandom} object
 +   */
 +  
 +  public void setSecureRandom(SecureRandom secureRandom) {
 +    this.secureRandom = secureRandom;
 +  }
 +  
 +  /**
 +   * Gets the initialization vector to use for this crypto module.
 +   * 
 +   * @see CryptoModuleParameters#setInitializationVector(byte[])
 +   */
 +  public byte[] getInitializationVector() {
 +    return initializationVector;
 +  }
 +  
 +  /**
 +   * Sets the initialization vector to use for this crypto module.
 +   * 
 +   * <p>
 +   * 
 +   * For <b>encryption</b>, this parameter is <i>optional</i>. If the initialization vector is created by the caller, for whatever reasons, it can be set here
 +   * and the crypto module will use it. <br>
 +   * 
 +   * For <b>decryption</b>, this parameter is <b>required</b>. It should be read from the underlying stream that contains the encrypted data.
 +   * 
 +   * @param initializationVector
 +   *          the initialization vector to use for this crypto operation.
 +   */
 +  public void setInitializationVector(byte[] initializationVector) {
 +    this.initializationVector = initializationVector;
 +  }
 +  
 +  /**
 +   * Gets the size of the buffering stream that sits above the cipher stream
 +   */
 +  public int getBlockStreamSize() {
 +    return blockStreamSize;
 +  }
 +
 +  /**
 +   * Sets the size of the buffering stream that sits above the cipher stream
 +   */
 +  public void setBlockStreamSize(int blockStreamSize) {
 +    this.blockStreamSize = blockStreamSize;
 +  }
 +
 +  /**
 +   * Gets the overall set of options for the {@link CryptoModule}.
 +   * 
 +   * @see CryptoModuleParameters#setAllOptions(Map)
 +   */
 +  public Map<String,String> getAllOptions() {
 +    return allOptions;
 +  }
 +  
 +  /**
 +   * Sets the overall set of options for the {@link CryptoModule}.
 +   * 
 +   * <p>
 +   * 
 +   * Often, options for the cryptographic modules will be encoded as key/value pairs in a configuration file. This map represents those values. It may include
 +   * some of the parameters already called out as members of this class. It may contain any number of additional parameters which may be required by different
 +   * module or key encryption strategy implementations.
 +   * 
 +   * @param allOptions
 +   *          the set of key/value pairs that confiure a module, based on a configuration file
 +   */
 +  public void setAllOptions(Map<String,String> allOptions) {
 +    this.allOptions = allOptions;
 +  }
 +  
 +  private String algorithmName = null;
 +  private String encryptionMode = null;
 +  private String padding = null;
 +  private byte[] plaintextKey;
 +  private int keyLength = 0;
 +  private String randomNumberGenerator = null;
 +  private String randomNumberGeneratorProvider = null;
 +  
 +  private String keyEncryptionStrategyClass;
 +  private byte[] encryptedKey;
 +  private String opaqueKeyEncryptionKeyID;
 +  
 +  private boolean recordParametersToStream = true;
 +  private boolean closeUnderylingStreamAfterCryptoStreamClose = true;
 +  private boolean overrideStreamsSecretKeyEncryptionStrategy = false;
 +  
 +  private OutputStream plaintextOutputStream;
 +  private OutputStream encryptedOutputStream;
 +  private InputStream plaintextInputStream;
 +  private InputStream encryptedInputStream;
 +  
 +  private Cipher cipher;
 +  private SecureRandom secureRandom;
 +  private byte[] initializationVector;
 +  
 +  private Map<String,String> allOptions;
 +  private int blockStreamSize;
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/core/src/test/java/org/apache/accumulo/core/client/lexicoder/ReverseLexicoderTest.java
----------------------------------------------------------------------
diff --cc core/src/test/java/org/apache/accumulo/core/client/lexicoder/ReverseLexicoderTest.java
index cc363c7,0000000..e6bfca8
mode 100644,000000..100644
--- a/core/src/test/java/org/apache/accumulo/core/client/lexicoder/ReverseLexicoderTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/client/lexicoder/ReverseLexicoderTest.java
@@@ -1,62 -1,0 +1,60 @@@
 +/*
 + * 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.accumulo.core.client.lexicoder;
 +
 +import java.io.UnsupportedEncodingException;
 +import java.util.Collections;
 +import java.util.Comparator;
 +import java.util.Date;
 +
 +import org.junit.Test;
 +
 +public class ReverseLexicoderTest extends LexicoderTest {
 +  public void testSortOrder() {
 +    Comparator<Long> comp = Collections.reverseOrder();
 +    assertSortOrder(new ReverseLexicoder<Long>(new LongLexicoder()), comp, Long.MIN_VALUE, 0xff1234567890abcdl, 0xffff1234567890abl, 0xffffff567890abcdl,
 +        0xffffffff7890abcdl, 0xffffffffff90abcdl, 0xffffffffffffabcdl, 0xffffffffffffffcdl, -1l, 0l, 0x01l, 0x1234l, 0x123456l, 0x12345678l, 0x1234567890l,
 +        0x1234567890abl, 0x1234567890abcdl, 0x1234567890abcdefl, Long.MAX_VALUE);
 +    
 +    Comparator<String> comp2 = Collections.reverseOrder();
 +    assertSortOrder(new ReverseLexicoder<String>(new StringLexicoder()), comp2, "a", "aa", "ab", "b", "aab");
 +    
 +  }
 +  
 +  /**
 +   * Just a simple test verifying reverse indexed dates
-    * 
-    * @throws UnsupportedEncodingException
 +   */
 +  @Test
 +  public void testReverseSortDates() throws UnsupportedEncodingException {
 +    
 +    ReverseLexicoder<Date> revLex = new ReverseLexicoder<Date>(new DateLexicoder());
 +    
 +    Date date1 = new Date();
 +    Date date2 = new Date(System.currentTimeMillis() + 10000);
 +    Date date3 = new Date(System.currentTimeMillis() + 500);
 +    
 +    Comparator<Date> comparator = Collections.reverseOrder();
 +    assertSortOrder(revLex, comparator, date1, date2, date3);
 +    
 +    // truncate date to hours
 +    long time = System.currentTimeMillis() - (System.currentTimeMillis() % 3600000);
 +    Date date = new Date(time);
 +    
 +    System.out.println(date);
 +    
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/core/src/test/java/org/apache/accumulo/core/client/mapred/AccumuloInputFormatTest.java
----------------------------------------------------------------------
diff --cc core/src/test/java/org/apache/accumulo/core/client/mapred/AccumuloInputFormatTest.java
index e83453e,3ec9bb1..13490e0
--- a/core/src/test/java/org/apache/accumulo/core/client/mapred/AccumuloInputFormatTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/client/mapred/AccumuloInputFormatTest.java
@@@ -57,23 -55,9 +57,21 @@@ public class AccumuloInputFormatTest 
    private static final String PREFIX = AccumuloInputFormatTest.class.getSimpleName();
    private static final String INSTANCE_NAME = PREFIX + "_mapred_instance";
    private static final String TEST_TABLE_1 = PREFIX + "_mapred_table_1";
 -  
 +
 +  private JobConf job;
 +
 +  @BeforeClass
 +  public static void setupClass() {
 +    System.setProperty("hadoop.tmp.dir", System.getProperty("user.dir") + "/target/hadoop-tmp");
 +  }
 +
 +  @Before
 +  public void createJob() {
 +    job = new JobConf();
 +  }
 +
    /**
     * Check that the iterator configuration is getting stored in the Job conf correctly.
-    * 
-    * @throws IOException
     */
    @Test
    public void testSetIterator() throws IOException {
@@@ -152,11 -141,9 +150,9 @@@
      assertEquals(list.get(1).getOptions().get(key), value);
      assertEquals(list.get(1).getOptions().get(key + "2"), value);
    }
 -  
 +
    /**
     * Test getting iterator settings for multiple iterators set
-    * 
-    * @throws IOException
     */
    @Test
    public void testGetIteratorSettings() throws IOException {

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/core/src/test/java/org/apache/accumulo/core/client/mapreduce/AccumuloInputFormatTest.java
----------------------------------------------------------------------
diff --cc core/src/test/java/org/apache/accumulo/core/client/mapreduce/AccumuloInputFormatTest.java
index 54bd127,ae5e395..2500972
--- a/core/src/test/java/org/apache/accumulo/core/client/mapreduce/AccumuloInputFormatTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/client/mapreduce/AccumuloInputFormatTest.java
@@@ -64,9 -64,45 +64,7 @@@ public class AccumuloInputFormatTest 
    private static final String PREFIX = AccumuloInputFormatTest.class.getSimpleName();
  
    /**
 -   * Test basic setting & getting of max versions.
 -   * 
 -   * @throws IOException
 -   *           Signals that an I/O exception has occurred.
 -   */
 -  @Deprecated
 -  @Test
 -  public void testMaxVersions() throws IOException {
 -    Job job = new Job();
 -    AccumuloInputFormat.setMaxVersions(job.getConfiguration(), 1);
 -    int version = AccumuloInputFormat.getMaxVersions(job.getConfiguration());
 -    assertEquals(1, version);
 -  }
 -
 -  /**
 -   * Test max versions with an invalid value.
 -   * 
 -   * @throws IOException
 -   *           Signals that an I/O exception has occurred.
 -   */
 -  @Deprecated
 -  @Test(expected = IOException.class)
 -  public void testMaxVersionsLessThan1() throws IOException {
 -    Job job = new Job();
 -    AccumuloInputFormat.setMaxVersions(job.getConfiguration(), 0);
 -  }
 -
 -  /**
 -   * Test no max version configured.
 -   */
 -  @Deprecated
 -  @Test
 -  public void testNoMaxVersion() throws IOException {
 -    Job job = new Job();
 -    assertEquals(-1, AccumuloInputFormat.getMaxVersions(job.getConfiguration()));
 -  }
 -
 -  /**
     * Check that the iterator configuration is getting stored in the Job conf correctly.
-    * 
-    * @throws IOException
     */
    @Test
    public void testSetIterator() throws IOException {

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/core/src/test/java/org/apache/accumulo/core/client/mock/MockNamespacesTest.java
----------------------------------------------------------------------
diff --cc core/src/test/java/org/apache/accumulo/core/client/mock/MockNamespacesTest.java
index 009be17,0000000..c06df51
mode 100644,000000..100644
--- a/core/src/test/java/org/apache/accumulo/core/client/mock/MockNamespacesTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/client/mock/MockNamespacesTest.java
@@@ -1,317 -1,0 +1,309 @@@
 +/*
 + * 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.accumulo.core.client.mock;
 +
 +import static org.junit.Assert.assertTrue;
 +import static org.junit.Assert.fail;
 +
 +import java.io.File;
 +import java.util.EnumSet;
 +import java.util.HashSet;
 +import java.util.Map.Entry;
 +import java.util.Random;
 +
 +import org.apache.accumulo.core.Constants;
 +import org.apache.accumulo.core.client.AccumuloException;
 +import org.apache.accumulo.core.client.AccumuloSecurityException;
 +import org.apache.accumulo.core.client.BatchWriter;
 +import org.apache.accumulo.core.client.BatchWriterConfig;
 +import org.apache.accumulo.core.client.Connector;
 +import org.apache.accumulo.core.client.Instance;
 +import org.apache.accumulo.core.client.IteratorSetting;
 +import org.apache.accumulo.core.client.NamespaceNotEmptyException;
 +import org.apache.accumulo.core.client.NamespaceNotFoundException;
 +import org.apache.accumulo.core.client.Scanner;
 +import org.apache.accumulo.core.client.TableNotFoundException;
 +import org.apache.accumulo.core.client.admin.NamespaceOperations;
 +import org.apache.accumulo.core.client.impl.Namespaces;
 +import org.apache.accumulo.core.client.security.tokens.PasswordToken;
 +import org.apache.accumulo.core.conf.Property;
 +import org.apache.accumulo.core.data.Key;
 +import org.apache.accumulo.core.data.Mutation;
 +import org.apache.accumulo.core.data.Value;
 +import org.apache.accumulo.core.iterators.Filter;
 +import org.apache.accumulo.core.iterators.IteratorUtil.IteratorScope;
 +import org.apache.accumulo.core.security.Authorizations;
 +import org.junit.Test;
 +import org.junit.rules.TemporaryFolder;
 +
 +public class MockNamespacesTest {
 +
 +  Random random = new Random();
 +  public static TemporaryFolder folder = new TemporaryFolder(new File(System.getProperty("user.dir") + "/target"));
 +
 +  /**
 +   * This test creates a table without specifying a namespace. In this case, it puts the table into the default namespace.
-    * 
-    * @throws Exception
 +   */
 +  @Test
 +  public void testDefaultNamespace() throws Exception {
 +    String tableName = "test";
 +    Instance instance = new MockInstance("default");
 +    Connector c = instance.getConnector("user", new PasswordToken("pass"));
 +
 +    assertTrue(c.namespaceOperations().exists(Namespaces.DEFAULT_NAMESPACE));
 +    c.tableOperations().create(tableName);
 +    assertTrue(c.tableOperations().exists(tableName));
 +  }
 +
 +  /**
 +   * This test creates a new namespace "testing" and a table "testing.table1" which puts "table1" into the "testing" namespace. Then we create "testing.table2"
 +   * which creates "table2" and puts it into "testing" as well. Then we make sure that you can't delete a namespace with tables in it, and then we delete the
 +   * tables and delete the namespace.
-    * 
-    * @throws Exception
 +   */
 +  @Test
 +  public void testCreateAndDeleteNamespace() throws Exception {
 +    String namespace = "testing";
 +    String tableName1 = namespace + ".table1";
 +    String tableName2 = namespace + ".table2";
 +
 +    Instance instance = new MockInstance("createdelete");
 +    Connector c = instance.getConnector("user", new PasswordToken("pass"));
 +
 +    c.namespaceOperations().create(namespace);
 +    assertTrue(c.namespaceOperations().exists(namespace));
 +
 +    c.tableOperations().create(tableName1);
 +    assertTrue(c.tableOperations().exists(tableName1));
 +
 +    c.tableOperations().create(tableName2);
 +    assertTrue(c.tableOperations().exists(tableName2));
 +
 +    // deleting
 +    try {
 +      // can't delete a namespace with tables in it
 +      c.namespaceOperations().delete(namespace);
 +      fail();
 +    } catch (NamespaceNotEmptyException e) {
 +      // ignore, supposed to happen
 +    }
 +    assertTrue(c.namespaceOperations().exists(namespace));
 +    assertTrue(c.tableOperations().exists(tableName1));
 +    assertTrue(c.tableOperations().exists(tableName2));
 +
 +    c.tableOperations().delete(tableName2);
 +    assertTrue(!c.tableOperations().exists(tableName2));
 +    assertTrue(c.namespaceOperations().exists(namespace));
 +
 +    c.tableOperations().delete(tableName1);
 +    assertTrue(!c.tableOperations().exists(tableName1));
 +    c.namespaceOperations().delete(namespace);
 +    assertTrue(!c.namespaceOperations().exists(namespace));
 +  }
 +
 +  /**
 +   * This test creates a namespace, modifies it's properties, and checks to make sure that those properties are applied to its tables. To do something on a
 +   * namespace-wide level, use {@link NamespaceOperations}.
 +   * 
 +   * Checks to make sure namespace-level properties are overridden by table-level properties.
 +   * 
 +   * Checks to see if the default namespace's properties work as well.
-    * 
-    * @throws Exception
 +   */
 +
 +  @Test
 +  public void testNamespaceProperties() throws Exception {
 +    String namespace = "propchange";
 +    String tableName1 = namespace + ".table1";
 +    String tableName2 = namespace + ".table2";
 +
 +    String propKey = Property.TABLE_SCAN_MAXMEM.getKey();
 +    String propVal = "42K";
 +
 +    Instance instance = new MockInstance("props");
 +    Connector c = instance.getConnector("user", new PasswordToken("pass"));
 +
 +    c.namespaceOperations().create(namespace);
 +    c.tableOperations().create(tableName1);
 +    c.namespaceOperations().setProperty(namespace, propKey, propVal);
 +
 +    // check the namespace has the property
 +    assertTrue(checkNamespaceHasProp(c, namespace, propKey, propVal));
 +
 +    // check that the table gets it from the namespace
 +    assertTrue(checkTableHasProp(c, tableName1, propKey, propVal));
 +
 +    // test a second table to be sure the first wasn't magical
 +    // (also, changed the order, the namespace has the property already)
 +    c.tableOperations().create(tableName2);
 +    assertTrue(checkTableHasProp(c, tableName2, propKey, propVal));
 +
 +    // test that table properties override namespace properties
 +    String propKey2 = Property.TABLE_FILE_MAX.getKey();
 +    String propVal2 = "42";
 +    String tablePropVal = "13";
 +
 +    c.tableOperations().setProperty(tableName2, propKey2, tablePropVal);
 +    c.namespaceOperations().setProperty("propchange", propKey2, propVal2);
 +
 +    assertTrue(checkTableHasProp(c, tableName2, propKey2, tablePropVal));
 +
 +    // now check that you can change the default namespace's properties
 +    propVal = "13K";
 +    String tableName = "some_table";
 +    c.tableOperations().create(tableName);
 +    c.namespaceOperations().setProperty(Namespaces.DEFAULT_NAMESPACE, propKey, propVal);
 +
 +    assertTrue(checkTableHasProp(c, tableName, propKey, propVal));
 +
 +    // test the properties server-side by configuring an iterator.
 +    // should not show anything with column-family = 'a'
 +    String tableName3 = namespace + ".table3";
 +    c.tableOperations().create(tableName3);
 +
 +    IteratorSetting setting = new IteratorSetting(250, "thing", SimpleFilter.class.getName());
 +    c.namespaceOperations().attachIterator(namespace, setting);
 +
 +    BatchWriter bw = c.createBatchWriter(tableName3, new BatchWriterConfig());
 +    Mutation m = new Mutation("r");
 +    m.put("a", "b", new Value("abcde".getBytes()));
 +    bw.addMutation(m);
 +    bw.flush();
 +    bw.close();
 +
 +    // Scanner s = c.createScanner(tableName3, Authorizations.EMPTY);
 +    // do scanners work correctly in mock?
 +    // assertTrue(!s.iterator().hasNext());
 +  }
 +
 +  /**
 +   * This test renames and clones two separate table into different namespaces. different namespace.
-    * 
-    * @throws Exception
 +   */
 +  @Test
 +  public void testRenameAndCloneTableToNewNamespace() throws Exception {
 +    String namespace1 = "renamed";
 +    String namespace2 = "cloned";
 +    String tableName = "table";
 +    String tableName1 = "renamed.table1";
 +    // String tableName2 = "cloned.table2";
 +
 +    Instance instance = new MockInstance("renameclone");
 +    Connector c = instance.getConnector("user", new PasswordToken("pass"));
 +
 +    c.tableOperations().create(tableName);
 +    c.namespaceOperations().create(namespace1);
 +    c.namespaceOperations().create(namespace2);
 +
 +    c.tableOperations().rename(tableName, tableName1);
 +
 +    assertTrue(c.tableOperations().exists(tableName1));
 +    assertTrue(!c.tableOperations().exists(tableName));
 +
 +    // TODO implement clone in mock
 +    /*
 +     * c.tableOperations().clone(tableName1, tableName2, false, null, null);
 +     * 
 +     * assertTrue(c.tableOperations().exists(tableName1)); assertTrue(c.tableOperations().exists(tableName2));
 +     */
 +    return;
 +  }
 +
 +  /**
 +   * This test renames a namespace and ensures that its tables are still correct
 +   */
 +  @Test
 +  public void testNamespaceRename() throws Exception {
 +    String namespace1 = "n1";
 +    String namespace2 = "n2";
 +    String table = "t";
 +
 +    Instance instance = new MockInstance("rename");
 +    Connector c = instance.getConnector("user", new PasswordToken("pass"));
 +
 +    c.namespaceOperations().create(namespace1);
 +    c.tableOperations().create(namespace1 + "." + table);
 +
 +    c.namespaceOperations().rename(namespace1, namespace2);
 +
 +    assertTrue(!c.namespaceOperations().exists(namespace1));
 +    assertTrue(c.namespaceOperations().exists(namespace2));
 +    assertTrue(!c.tableOperations().exists(namespace1 + "." + table));
 +    assertTrue(c.tableOperations().exists(namespace2 + "." + table));
 +  }
 +
 +  /**
 +   * This tests adding iterators to a namespace, listing them, and removing them
 +   */
 +  @Test
 +  public void testNamespaceIterators() throws Exception {
 +    Instance instance = new MockInstance("Iterators");
 +    Connector c = instance.getConnector("user", new PasswordToken("pass"));
 +
 +    String namespace = "iterator";
 +    String tableName = namespace + ".table";
 +    String iter = "thing";
 +
 +    c.namespaceOperations().create(namespace);
 +    c.tableOperations().create(tableName);
 +
 +    IteratorSetting setting = new IteratorSetting(250, iter, SimpleFilter.class.getName());
 +    HashSet<IteratorScope> scope = new HashSet<IteratorScope>();
 +    scope.add(IteratorScope.scan);
 +    c.namespaceOperations().attachIterator(namespace, setting, EnumSet.copyOf(scope));
 +
 +    BatchWriter bw = c.createBatchWriter(tableName, new BatchWriterConfig());
 +    Mutation m = new Mutation("r");
 +    m.put("a", "b", new Value("abcde".getBytes(Constants.UTF8)));
 +    bw.addMutation(m);
 +    bw.flush();
 +
 +    Scanner s = c.createScanner(tableName, Authorizations.EMPTY);
 +    System.out.println(s.iterator().next());
 +    // do scanners work correctly in mock?
 +    // assertTrue(!s.iterator().hasNext());
 +
 +    assertTrue(c.namespaceOperations().listIterators(namespace).containsKey(iter));
 +    c.namespaceOperations().removeIterator(namespace, iter, EnumSet.copyOf(scope));
 +  }
 +
 +  private boolean checkTableHasProp(Connector c, String t, String propKey, String propVal) throws AccumuloException, TableNotFoundException {
 +    for (Entry<String,String> e : c.tableOperations().getProperties(t)) {
 +      if (e.getKey().equals(propKey) && e.getValue().equals(propVal)) {
 +        return true;
 +      }
 +    }
 +    return false;
 +  }
 +
 +  private boolean checkNamespaceHasProp(Connector c, String n, String propKey, String propVal) throws AccumuloException, NamespaceNotFoundException,
 +      AccumuloSecurityException {
 +    for (Entry<String,String> e : c.namespaceOperations().getProperties(n)) {
 +      if (e.getKey().equals(propKey) && e.getValue().equals(propVal)) {
 +        return true;
 +      }
 +    }
 +    return false;
 +  }
 +
 +  public static class SimpleFilter extends Filter {
 +    @Override
 +    public boolean accept(Key k, Value v) {
 +      if (k.getColumnFamily().toString().equals("a"))
 +        return false;
 +      return true;
 +    }
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/core/src/test/java/org/apache/accumulo/core/security/VisibilityConstraintTest.java
----------------------------------------------------------------------
diff --cc core/src/test/java/org/apache/accumulo/core/security/VisibilityConstraintTest.java
index de6ca21,0000000..d31a788
mode 100644,000000..100644
--- a/core/src/test/java/org/apache/accumulo/core/security/VisibilityConstraintTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/security/VisibilityConstraintTest.java
@@@ -1,106 -1,0 +1,103 @@@
 +/*
 + * 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.accumulo.core.security;
 +
 +import static org.easymock.EasyMock.createMock;
 +import static org.easymock.EasyMock.createNiceMock;
 +import static org.easymock.EasyMock.expect;
 +import static org.easymock.EasyMock.replay;
 +import static org.junit.Assert.assertEquals;
 +import static org.junit.Assert.assertNull;
 +
 +import java.util.Arrays;
 +import java.util.List;
 +
 +import org.apache.accumulo.core.Constants;
 +import org.apache.accumulo.core.constraints.Constraint.Environment;
 +import org.apache.accumulo.core.data.ArrayByteSequence;
 +import org.apache.accumulo.core.data.Mutation;
 +import org.junit.Before;
 +import org.junit.Ignore;
 +import org.junit.Test;
 +
 +public class VisibilityConstraintTest {
 +
 +  VisibilityConstraint vc;
 +  Environment env;
 +  Mutation mutation;
 +
 +  static final ColumnVisibility good = new ColumnVisibility("good");
 +  static final ColumnVisibility bad = new ColumnVisibility("bad");
 +
 +  static final String D = "don't care";
 +
 +  static final List<Short> ENOAUTH = Arrays.asList((short) 2);
 +
-   /**
-    * @throws java.lang.Exception
-    */
 +  @Before
 +  public void setUp() throws Exception {
 +    vc = new VisibilityConstraint();
 +    mutation = new Mutation("r");
 +
 +    ArrayByteSequence bs = new ArrayByteSequence("good".getBytes(Constants.UTF8));
 +
 +    AuthorizationContainer ac = createNiceMock(AuthorizationContainer.class);
 +    expect(ac.contains(bs)).andReturn(true);
 +    replay(ac);
 +
 +    env = createMock(Environment.class);
 +    expect(env.getAuthorizationsContainer()).andReturn(ac);
 +    replay(env);
 +  }
 +
 +  @Test
 +  public void testNoVisibility() {
 +    mutation.put(D, D, D);
 +    assertNull("authorized", vc.check(env, mutation));
 +  }
 +
 +  @Test
 +  public void testVisibilityNoAuth() {
 +    mutation.put(D, D, bad, D);
 +    assertEquals("unauthorized", ENOAUTH, vc.check(env, mutation));
 +  }
 +
 +  @Test
 +  public void testGoodVisibilityAuth() {
 +    mutation.put(D, D, good, D);
 +    assertNull("authorized", vc.check(env, mutation));
 +  }
 +
 +  @Test
 +  public void testCachedVisibilities() {
 +    mutation.put(D, D, good, "v");
 +    mutation.put(D, D, good, "v2");
 +    assertNull("authorized", vc.check(env, mutation));
 +  }
 +
 +  @Test
 +  public void testMixedVisibilities() {
 +    mutation.put(D, D, bad, D);
 +    mutation.put(D, D, good, D);
 +    assertEquals("unauthorized", ENOAUTH, vc.check(env, mutation));
 +  }
 +
 +  @Test
 +  @Ignore
 +  public void testMalformedVisibility() {
 +    // TODO: ACCUMULO-1006 Should test for returning error code 1, but not sure how since ColumnVisibility won't let us construct a bad one in the first place
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/examples/simple/src/main/java/org/apache/accumulo/examples/simple/client/RandomBatchScanner.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/examples/simple/src/main/java/org/apache/accumulo/examples/simple/client/RandomBatchWriter.java
----------------------------------------------------------------------
diff --cc examples/simple/src/main/java/org/apache/accumulo/examples/simple/client/RandomBatchWriter.java
index 4607fdb,e76352a..44947d1
--- a/examples/simple/src/main/java/org/apache/accumulo/examples/simple/client/RandomBatchWriter.java
+++ b/examples/simple/src/main/java/org/apache/accumulo/examples/simple/client/RandomBatchWriter.java
@@@ -89,40 -89,29 +89,36 @@@ public class RandomBatchWriter 
      // create a random value that is a function of the
      // row id for verification purposes
      byte value[] = createValue(rowid, dataSize);
 -    
 +
      m.put(new Text("foo"), new Text("1"), visibility, new Value(value));
 -    
 +
      return m;
    }
 -  
 +
    static class Opts extends ClientOnRequiredTable {
 -    @Parameter(names="--num", required=true)
 +    @Parameter(names = "--num", required = true)
      int num = 0;
 -    @Parameter(names="--min")
 +    @Parameter(names = "--min")
      long min = 0;
 -    @Parameter(names="--max")
 +    @Parameter(names = "--max")
      long max = Long.MAX_VALUE;
 -    @Parameter(names="--size", required=true, description="size of the value to write")
 +    @Parameter(names = "--size", required = true, description = "size of the value to write")
      int size = 0;
 -    @Parameter(names="--vis", converter=VisibilityConverter.class)
 +    @Parameter(names = "--vis", converter = VisibilityConverter.class)
      ColumnVisibility visiblity = new ColumnVisibility("");
 -    @Parameter(names="--seed", description="seed for pseudo-random number generator")
 +    @Parameter(names = "--seed", description = "seed for pseudo-random number generator")
      Long seed = null;
    }
 - 
 +
 +  public static long abs(long l) {
 +    l = Math.abs(l);  // abs(Long.MIN_VALUE) == Long.MIN_VALUE... 
 +    if (l < 0)
 +      return 0;
 +    return l;
 +  }
 +
    /**
     * Writes a specified number of entries to Accumulo using a {@link BatchWriter}.
-    * 
-    * @throws AccumuloException
-    * @throws AccumuloSecurityException
-    * @throws TableNotFoundException
     */
    public static void main(String[] args) throws AccumuloException, AccumuloSecurityException, TableNotFoundException {
      Opts opts = new Opts();

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/examples/simple/src/main/java/org/apache/accumulo/examples/simple/dirlist/QueryUtil.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/examples/simple/src/main/java/org/apache/accumulo/examples/simple/mapreduce/NGramIngest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/examples/simple/src/main/java/org/apache/accumulo/examples/simple/mapreduce/TableToFile.java
----------------------------------------------------------------------
diff --cc examples/simple/src/main/java/org/apache/accumulo/examples/simple/mapreduce/TableToFile.java
index 3a211e2,669c76d..30ebd06
--- a/examples/simple/src/main/java/org/apache/accumulo/examples/simple/mapreduce/TableToFile.java
+++ b/examples/simple/src/main/java/org/apache/accumulo/examples/simple/mapreduce/TableToFile.java
@@@ -121,9 -120,10 +121,8 @@@ public class TableToFile extends Config
     * 
     * @param args
     *          instanceName zookeepers username password table columns outputpath
-    * @throws Exception
     */
    public static void main(String[] args) throws Exception {
 -    int res = ToolRunner.run(CachedConfiguration.getInstance(), new TableToFile(), args);
 -    if (res != 0)
 -      System.exit(res);
 +    ToolRunner.run(new Configuration(), new TableToFile(), args);
    }
  }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/examples/simple/src/main/java/org/apache/accumulo/examples/simple/shard/Query.java
----------------------------------------------------------------------
diff --cc examples/simple/src/main/java/org/apache/accumulo/examples/simple/shard/Query.java
index add4c4c,d98d78b..aa12c71
--- a/examples/simple/src/main/java/org/apache/accumulo/examples/simple/shard/Query.java
+++ b/examples/simple/src/main/java/org/apache/accumulo/examples/simple/shard/Query.java
@@@ -59,26 -66,10 +59,23 @@@ public class Query 
      IntersectingIterator.setColumnFamilies(ii, columns);
      bs.addScanIterator(ii);
      bs.setRanges(Collections.singleton(new Range()));
 +    List<String> result = new ArrayList<String>();
      for (Entry<Key,Value> entry : bs) {
 -      System.out.println("  " + entry.getKey().getColumnQualifier());
 +      result.add(entry.getKey().getColumnQualifier().toString());
      }
 -    
 +    return result;
 +  }
 +  
-   /**
-    * @param args
-    */
 +  public static void main(String[] args) throws Exception {
 +    Opts opts = new Opts();
 +    BatchScannerOpts bsOpts = new BatchScannerOpts();
 +    opts.parseArgs(Query.class.getName(), args, bsOpts);
 +    Connector conn = opts.getConnector();
 +    BatchScanner bs = conn.createBatchScanner(opts.tableName, opts.auths, bsOpts.scanThreads);
 +    bs.setTimeout(bsOpts.scanTimeout, TimeUnit.MILLISECONDS);
 +
 +    for (String entry : query(bs, opts.terms))
 +      System.out.println("  " + entry);
    }
    
  }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/minicluster/src/main/java/org/apache/accumulo/minicluster/MiniAccumuloRunner.java
----------------------------------------------------------------------
diff --cc minicluster/src/main/java/org/apache/accumulo/minicluster/MiniAccumuloRunner.java
index f7070dc,0000000..ab84d37
mode 100644,000000..100644
--- a/minicluster/src/main/java/org/apache/accumulo/minicluster/MiniAccumuloRunner.java
+++ b/minicluster/src/main/java/org/apache/accumulo/minicluster/MiniAccumuloRunner.java
@@@ -1,264 -1,0 +1,262 @@@
 +/*
 + * 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.accumulo.minicluster;
 +
 +import java.io.File;
 +import java.io.FileInputStream;
 +import java.io.IOException;
 +import java.io.InputStream;
 +import java.net.ServerSocket;
 +import java.util.Date;
 +import java.util.HashMap;
 +import java.util.Map;
 +import java.util.Properties;
 +import java.util.regex.Pattern;
 +
 +import org.apache.accumulo.core.cli.Help;
 +import org.apache.accumulo.core.util.Pair;
 +import org.apache.commons.io.FileUtils;
 +
 +import com.beust.jcommander.IStringConverter;
 +import com.beust.jcommander.Parameter;
 +import com.google.common.io.Files;
 +
 +/**
 + * A runner for starting up a {@link MiniAccumuloCluster} from the command line using an optional configuration properties file. An example property file looks
 + * like the following:
 + * 
 + * <pre>
 + * rootPassword=secret
 + * instanceName=testInstance
 + * numTServers=1
 + * zooKeeperPort=3191
 + * jdwpEnabled=true
 + * zooKeeperMemory=128M
 + * tserverMemory=256M
 + * masterMemory=128M
 + * defaultMemory=256M
 + * shutdownPort=4446
 + * site.instance.secret=HUSH
 + * </pre>
 + * 
 + * All items in the properties file above are optional and a default value will be provided in their absence. Any site configuration properties (typically found
 + * in the accumulo-site.xml file) should be prefixed with "site." in the properties file.
 + * 
 + * @since 1.6.0
 + */
 +public class MiniAccumuloRunner {
 +  private static final String ROOT_PASSWORD_PROP = "rootPassword";
 +  private static final String SHUTDOWN_PORT_PROP = "shutdownPort";
 +  private static final String DEFAULT_MEMORY_PROP = "defaultMemory";
 +  private static final String MASTER_MEMORY_PROP = "masterMemory";
 +  private static final String TSERVER_MEMORY_PROP = "tserverMemory";
 +  private static final String ZOO_KEEPER_MEMORY_PROP = "zooKeeperMemory";
 +  private static final String JDWP_ENABLED_PROP = "jdwpEnabled";
 +  private static final String ZOO_KEEPER_PORT_PROP = "zooKeeperPort";
 +  private static final String NUM_T_SERVERS_PROP = "numTServers";
 +  private static final String DIRECTORY_PROP = "directory";
 +  private static final String INSTANCE_NAME_PROP = "instanceName";
 +
 +  private static void printProperties() {
 +    System.out.println("#mini Accumulo cluster runner properties.");
 +    System.out.println("#");
 +    System.out.println("#uncomment following propeties to use, propeties not set will use default or random value");
 +    System.out.println();
 +    System.out.println("#" + INSTANCE_NAME_PROP + "=devTest");
 +    System.out.println("#" + DIRECTORY_PROP + "=/tmp/mac1");
 +    System.out.println("#" + ROOT_PASSWORD_PROP + "=secret");
 +    System.out.println("#" + NUM_T_SERVERS_PROP + "=2");
 +    System.out.println("#" + ZOO_KEEPER_PORT_PROP + "=40404");
 +    System.out.println("#" + SHUTDOWN_PORT_PROP + "=41414");
 +    System.out.println("#" + DEFAULT_MEMORY_PROP + "=128M");
 +    System.out.println("#" + MASTER_MEMORY_PROP + "=128M");
 +    System.out.println("#" + TSERVER_MEMORY_PROP + "=128M");
 +    System.out.println("#" + ZOO_KEEPER_MEMORY_PROP + "=128M");
 +    System.out.println("#" + JDWP_ENABLED_PROP + "=false");
 +
 +    System.out.println();
 +    System.out.println("# Configuration normally placed in accumulo-site.xml can be added using a site. prefix.");
 +    System.out.println("# For example the following line will set tserver.compaction.major.concurrent.max");
 +    System.out.println();
 +    System.out.println("#site.tserver.compaction.major.concurrent.max=4");
 +
 +  }
 +
 +  public static class PropertiesConverter implements IStringConverter<Properties> {
 +    @Override
 +    public Properties convert(String fileName) {
 +      Properties prop = new Properties();
 +      InputStream is;
 +      try {
 +        is = new FileInputStream(fileName);
 +        try {
 +          prop.load(is);
 +        } finally {
 +          is.close();
 +        }
 +      } catch (IOException e) {
 +        throw new RuntimeException(e);
 +      }
 +      return prop;
 +    }
 +  }
 +
 +  private static final String FORMAT_STRING = "  %-21s %s";
 +
 +  public static class Opts extends Help {
 +    @Parameter(names = "-p", required = false, description = "properties file name", converter = PropertiesConverter.class)
 +    Properties prop = new Properties();
 +
 +    @Parameter(names = {"-c", "--printProperties"}, required = false, description = "prints an example propeties file, redirect to file to use")
 +    boolean printProps = false;
 +  }
 +
 +  /**
 +   * Runs the {@link MiniAccumuloCluster} given a -p argument with a property file. Establishes a shutdown port for asynchronous operation.
 +   * 
 +   * @param args
 +   *          An optional -p argument can be specified with the path to a valid properties file.
-    * 
-    * @throws Exception
 +   */
 +  public static void main(String[] args) throws Exception {
 +    Opts opts = new Opts();
 +    opts.parseArgs(MiniAccumuloRunner.class.getName(), args);
 +
 +    if (opts.printProps) {
 +      printProperties();
 +      System.exit(0);
 +    }
 +
 +    int shutdownPort = 4445;
 +
 +    final File miniDir;
 +
 +    if (opts.prop.containsKey(DIRECTORY_PROP))
 +      miniDir = new File(opts.prop.getProperty(DIRECTORY_PROP));
 +    else
 +      miniDir = Files.createTempDir();
 +
 +    String rootPass = opts.prop.containsKey(ROOT_PASSWORD_PROP) ? opts.prop.getProperty(ROOT_PASSWORD_PROP) : "secret";
 +
 +    MiniAccumuloConfig config = new MiniAccumuloConfig(miniDir, rootPass);
 +
 +    if (opts.prop.containsKey(INSTANCE_NAME_PROP))
 +      config.setInstanceName(opts.prop.getProperty(INSTANCE_NAME_PROP));
 +    if (opts.prop.containsKey(NUM_T_SERVERS_PROP))
 +      config.setNumTservers(Integer.parseInt(opts.prop.getProperty(NUM_T_SERVERS_PROP)));
 +    if (opts.prop.containsKey(ZOO_KEEPER_PORT_PROP))
 +      config.setZooKeeperPort(Integer.parseInt(opts.prop.getProperty(ZOO_KEEPER_PORT_PROP)));
 +    if (opts.prop.containsKey(JDWP_ENABLED_PROP))
 +      config.setJDWPEnabled(Boolean.parseBoolean(opts.prop.getProperty(JDWP_ENABLED_PROP)));
 +    if (opts.prop.containsKey(ZOO_KEEPER_MEMORY_PROP))
 +      setMemoryOnConfig(config, opts.prop.getProperty(ZOO_KEEPER_MEMORY_PROP), ServerType.ZOOKEEPER);
 +    if (opts.prop.containsKey(TSERVER_MEMORY_PROP))
 +      setMemoryOnConfig(config, opts.prop.getProperty(TSERVER_MEMORY_PROP), ServerType.TABLET_SERVER);
 +    if (opts.prop.containsKey(MASTER_MEMORY_PROP))
 +      setMemoryOnConfig(config, opts.prop.getProperty(MASTER_MEMORY_PROP), ServerType.MASTER);
 +    if (opts.prop.containsKey(DEFAULT_MEMORY_PROP))
 +      setMemoryOnConfig(config, opts.prop.getProperty(DEFAULT_MEMORY_PROP));
 +    if (opts.prop.containsKey(SHUTDOWN_PORT_PROP))
 +      shutdownPort = Integer.parseInt(opts.prop.getProperty(SHUTDOWN_PORT_PROP));
 +
 +    Map<String,String> siteConfig = new HashMap<String,String>();
 +    for (Map.Entry<Object,Object> entry : opts.prop.entrySet()) {
 +      String key = (String) entry.getKey();
 +      if (key.startsWith("site."))
 +        siteConfig.put(key.replaceFirst("site.", ""), (String) entry.getValue());
 +    }
 +
 +    config.setSiteConfig(siteConfig);
 +
 +    final MiniAccumuloCluster accumulo = new MiniAccumuloCluster(config);
 +
 +    Runtime.getRuntime().addShutdownHook(new Thread() {
 +      @Override
 +      public void run() {
 +        try {
 +          accumulo.stop();
 +          FileUtils.deleteDirectory(miniDir);
 +          System.out.println("\nShut down gracefully on " + new Date());
 +        } catch (IOException e) {
 +          e.printStackTrace();
 +        } catch (InterruptedException e) {
 +          e.printStackTrace();
 +        }
 +      }
 +    });
 +
 +    accumulo.start();
 +
 +    printInfo(accumulo, shutdownPort);
 +
 +    // start a socket on the shutdown port and block- anything connected to this port will activate the shutdown
 +    ServerSocket shutdownServer = new ServerSocket(shutdownPort);
 +    shutdownServer.accept();
 +
 +    System.exit(0);
 +  }
 +
 +  private static boolean validateMemoryString(String memoryString) {
 +    String unitsRegex = "[";
 +    MemoryUnit[] units = MemoryUnit.values();
 +    for (int i = 0; i < units.length; i++) {
 +      unitsRegex += units[i].suffix();
 +      if (i < units.length - 1)
 +        unitsRegex += "|";
 +    }
 +    unitsRegex += "]";
 +    Pattern p = Pattern.compile("\\d+" + unitsRegex);
 +    return p.matcher(memoryString).matches();
 +  }
 +
 +  private static void setMemoryOnConfig(MiniAccumuloConfig config, String memoryString) {
 +    setMemoryOnConfig(config, memoryString, null);
 +  }
 +
 +  private static void setMemoryOnConfig(MiniAccumuloConfig config, String memoryString, ServerType serverType) {
 +    if (!validateMemoryString(memoryString))
 +      throw new IllegalArgumentException(memoryString + " is not a valid memory string");
 +
 +    long memSize = Long.parseLong(memoryString.substring(0, memoryString.length() - 1));
 +    MemoryUnit memUnit = MemoryUnit.fromSuffix(memoryString.substring(memoryString.length() - 1));
 +
 +    if (serverType != null)
 +      config.setMemory(serverType, memSize, memUnit);
 +    else
 +      config.setDefaultMemory(memSize, memUnit);
 +  }
 +
 +  private static void printInfo(MiniAccumuloCluster accumulo, int shutdownPort) {
 +    System.out.println("Mini Accumulo Cluster\n");
 +    System.out.println(String.format(FORMAT_STRING, "Directory:", accumulo.getConfig().getDir().getAbsoluteFile()));
 +    System.out.println(String.format(FORMAT_STRING, "Logs:", accumulo.getConfig().getImpl().getLogDir().getAbsoluteFile()));
 +    System.out.println(String.format(FORMAT_STRING, "Instance Name:", accumulo.getConfig().getInstanceName()));
 +    System.out.println(String.format(FORMAT_STRING, "Root Password:", accumulo.getConfig().getRootPassword()));
 +    System.out.println(String.format(FORMAT_STRING, "ZooKeeper:", accumulo.getZooKeepers()));
 +
 +    for (Pair<ServerType,Integer> pair : accumulo.getDebugPorts()) {
 +      System.out.println(String.format(FORMAT_STRING, pair.getFirst().prettyPrint() + " JDWP Host:", "localhost:" + pair.getSecond()));
 +    }
 +
 +    System.out.println(String.format(FORMAT_STRING, "Shutdown Port:", shutdownPort));
 +
 +    System.out.println();
 +    System.out.println("  To connect with shell, use the following command : ");
 +    System.out.println("    accumulo shell -zh " + accumulo.getZooKeepers() + " -zi " + accumulo.getConfig().getInstanceName() + " -u root ");
 +
 +    System.out.println("\n\nSuccessfully started on " + new Date());
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/server/base/src/main/java/org/apache/accumulo/server/conf/ConfigSanityCheck.java
----------------------------------------------------------------------
diff --cc server/base/src/main/java/org/apache/accumulo/server/conf/ConfigSanityCheck.java
index 442294f,0000000..05806ca
mode 100644,000000..100644
--- a/server/base/src/main/java/org/apache/accumulo/server/conf/ConfigSanityCheck.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/conf/ConfigSanityCheck.java
@@@ -1,30 -1,0 +1,27 @@@
 +/*
 + * 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.accumulo.server.conf;
 +
 +import org.apache.accumulo.server.client.HdfsZooInstance;
 +
 +public class ConfigSanityCheck {
 +  
-   /**
-    * @param args
-    */
 +  public static void main(String[] args) {
 +    new ServerConfiguration(HdfsZooInstance.getInstance()).getConfiguration();
 +  }
 +  
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/server/base/src/main/java/org/apache/accumulo/server/master/balancer/TabletBalancer.java
----------------------------------------------------------------------
diff --cc server/base/src/main/java/org/apache/accumulo/server/master/balancer/TabletBalancer.java
index fd76ce2,0000000..5bd1632
mode 100644,000000..100644
--- a/server/base/src/main/java/org/apache/accumulo/server/master/balancer/TabletBalancer.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/balancer/TabletBalancer.java
@@@ -1,151 -1,0 +1,149 @@@
 +/*
 + * 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.accumulo.server.master.balancer;
 +
 +import java.util.ArrayList;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Set;
 +import java.util.SortedMap;
 +
 +import org.apache.accumulo.core.client.impl.thrift.ThriftSecurityException;
 +import org.apache.accumulo.core.data.KeyExtent;
 +import org.apache.accumulo.core.master.thrift.TabletServerStatus;
 +import org.apache.accumulo.core.tabletserver.thrift.TabletClientService;
 +import org.apache.accumulo.core.tabletserver.thrift.TabletClientService.Client;
 +import org.apache.accumulo.core.tabletserver.thrift.TabletStats;
 +import org.apache.accumulo.core.util.ThriftUtil;
 +import org.apache.accumulo.server.conf.ServerConfiguration;
 +import org.apache.accumulo.server.master.state.TServerInstance;
 +import org.apache.accumulo.server.master.state.TabletMigration;
 +import org.apache.accumulo.server.security.SystemCredentials;
 +import org.apache.accumulo.trace.instrument.Tracer;
 +import org.apache.log4j.Logger;
 +import org.apache.thrift.TException;
 +import org.apache.thrift.transport.TTransportException;
 +
 +public abstract class TabletBalancer {
 +  
 +  private static final Logger log = Logger.getLogger(TabletBalancer.class);
 +  
 +  protected ServerConfiguration configuration;
 +  
 +  /**
 +   * Initialize the TabletBalancer. This gives the balancer the opportunity to read the configuration.
 +   */
 +  public void init(ServerConfiguration conf) {
 +    configuration = conf;
 +  }
 +  
 +  /**
 +   * Assign tablets to tablet servers. This method is called whenever the master finds tablets that are unassigned.
 +   * 
 +   * @param current
 +   *          The current table-summary state of all the online tablet servers. Read-only. The TabletServerStatus for each server may be null if the tablet
 +   *          server has not yet responded to a recent request for status.
 +   * @param unassigned
 +   *          A map from unassigned tablet to the last known tablet server. Read-only.
 +   * @param assignments
 +   *          A map from tablet to assigned server. Write-only.
 +   */
 +  abstract public void getAssignments(SortedMap<TServerInstance,TabletServerStatus> current, Map<KeyExtent,TServerInstance> unassigned,
 +      Map<KeyExtent,TServerInstance> assignments);
 +  
 +  /**
 +   * Ask the balancer if any migrations are necessary.
 +   * 
 +   * @param current
 +   *          The current table-summary state of all the online tablet servers. Read-only.
 +   * @param migrations
 +   *          the current set of migrations. Read-only.
 +   * @param migrationsOut
 +   *          new migrations to perform; should not contain tablets in the current set of migrations. Write-only.
 +   * @return the time, in milliseconds, to wait before re-balancing.
 +   * 
 +   *         This method will not be called when there are unassigned tablets.
 +   */
 +  public abstract long balance(SortedMap<TServerInstance,TabletServerStatus> current, Set<KeyExtent> migrations, List<TabletMigration> migrationsOut);
 +  
 +  /**
 +   * Fetch the tablets for the given table by asking the tablet server. Useful if your balance strategy needs details at the tablet level to decide what tablets
 +   * to move.
 +   * 
 +   * @param tserver
 +   *          The tablet server to ask.
 +   * @param tableId
 +   *          The table id
 +   * @return a list of tablet statistics
 +   * @throws ThriftSecurityException
 +   *           tablet server disapproves of your internal System password.
 +   * @throws TException
 +   *           any other problem
 +   */
 +  public List<TabletStats> getOnlineTabletsForTable(TServerInstance tserver, String tableId) throws ThriftSecurityException, TException {
 +    log.debug("Scanning tablet server " + tserver + " for table " + tableId);
 +    Client client = ThriftUtil.getClient(new TabletClientService.Client.Factory(), tserver.getLocation(), configuration.getConfiguration());
 +    try {
 +      List<TabletStats> onlineTabletsForTable = client.getTabletStats(Tracer.traceInfo(), SystemCredentials.get().toThrift(configuration.getInstance()),
 +          tableId);
 +      return onlineTabletsForTable;
 +    } catch (TTransportException e) {
 +      log.error("Unable to connect to " + tserver + ": " + e);
 +    } finally {
 +      ThriftUtil.returnClient(client);
 +    }
 +    return null;
 +  }
 +  
 +  /**
 +   * Utility to ensure that the migrations from balance() are consistent:
 +   * <ul>
 +   * <li>Tablet objects are not null
 +   * <li>Source and destination tablet servers are not null and current
 +   * </ul>
 +   * 
-    * @param current
-    * @param migrations
 +   * @return A list of TabletMigration object that passed sanity checks.
 +   */
 +  public static List<TabletMigration> checkMigrationSanity(Set<TServerInstance> current, List<TabletMigration> migrations) {
 +    List<TabletMigration> result = new ArrayList<TabletMigration>(migrations.size());
 +    for (TabletMigration m : migrations) {
 +      if (m.tablet == null) {
 +        log.warn("Balancer gave back a null tablet " + m);
 +        continue;
 +      }
 +      if (m.newServer == null) {
 +        log.warn("Balancer did not set the destination " + m);
 +        continue;
 +      }
 +      if (m.oldServer == null) {
 +        log.warn("Balancer did not set the source " + m);
 +        continue;
 +      }
 +      if (!current.contains(m.oldServer)) {
 +        log.warn("Balancer wants to move a tablet from a server that is not current: " + m);
 +        continue;
 +      }
 +      if (!current.contains(m.newServer)) {
 +        log.warn("Balancer wants to move a tablet to a server that is not current: " + m);
 +        continue;
 +      }
 +      result.add(m);
 +    }
 +    return result;
 +  }
 +  
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/716ea0ee/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateStore.java
----------------------------------------------------------------------
diff --cc server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateStore.java
index e898109,0000000..7c75454
mode 100644,000000..100644
--- a/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateStore.java
+++ b/server/base/src/main/java/org/apache/accumulo/server/master/state/TabletStateStore.java
@@@ -1,91 -1,0 +1,84 @@@
 +/*
 + * 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.accumulo.server.master.state;
 +
 +import java.util.Collection;
 +import java.util.Collections;
 +
 +/**
 + * Interface for storing information about tablet assignments. There are three implementations:
 + * 
 + * ZooTabletStateStore: information about the root tablet is stored in ZooKeeper MetaDataStateStore: information about the other tablets are stored in the
 + * metadata table
 + * 
 + */
 +public abstract class TabletStateStore implements Iterable<TabletLocationState> {
 +  
 +  /**
 +   * Identifying name for this tablet state store.
 +   */
 +  abstract public String name();
 +  
 +  /**
 +   * Scan the information about the tablets covered by this store
 +   */
 +  @Override
 +  abstract public ClosableIterator<TabletLocationState> iterator();
 +  
 +  /**
 +   * Store the assigned locations in the data store.
-    * 
-    * @param assignments
-    * @throws DistributedStoreException
 +   */
 +  abstract public void setFutureLocations(Collection<Assignment> assignments) throws DistributedStoreException;
 +  
 +  /**
 +   * Tablet servers will update the data store with the location when they bring the tablet online
-    * 
-    * @param assignments
-    * @throws DistributedStoreException
 +   */
 +  abstract public void setLocations(Collection<Assignment> assignments) throws DistributedStoreException;
 +  
 +  /**
 +   * Mark the tablets as having no known or future location.
 +   * 
 +   * @param tablets
 +   *          the tablets' current information
-    * @throws DistributedStoreException
 +   */
 +  abstract public void unassign(Collection<TabletLocationState> tablets) throws DistributedStoreException;
 +  
 +  public static void unassign(TabletLocationState tls) throws DistributedStoreException {
 +    TabletStateStore store;
 +    if (tls.extent.isRootTablet()) {
 +      store = new ZooTabletStateStore();
 +    } else if (tls.extent.isMeta()) {
 +      store = new RootTabletStateStore();
 +    } else {
 +      store = new MetaDataStateStore();
 +    }
 +    store.unassign(Collections.singletonList(tls));
 +  }
 +  
 +  public static void setLocation(Assignment assignment) throws DistributedStoreException {
 +    TabletStateStore store;
 +    if (assignment.tablet.isRootTablet()) {
 +      store = new ZooTabletStateStore();
 +    } else if (assignment.tablet.isMeta()) {
 +      store = new RootTabletStateStore();
 +    } else {
 +      store = new MetaDataStateStore();
 +    }
 +    store.setLocations(Collections.singletonList(assignment));
 +  }
 +  
 +}