http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/stream/CTRCryptoOutputStream.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/crypto/stream/CTRCryptoOutputStream.java 
b/src/main/java/org/apache/commons/crypto/stream/CTRCryptoOutputStream.java
index 1b76db2..2b86c6d 100644
--- a/src/main/java/org/apache/commons/crypto/stream/CTRCryptoOutputStream.java
+++ b/src/main/java/org/apache/commons/crypto/stream/CTRCryptoOutputStream.java
@@ -46,342 +46,341 @@ import org.apache.commons.crypto.utils.Utils;
  * (1) calculating counter and (2) padding through stream position.
  * </p>
  * <p>
- * counter = base + pos/(algorithm blocksize);
- * padding = pos%(algorithm blocksize);
+ * counter = base + pos/(algorithm blocksize); padding = pos%(algorithm
+ * blocksize);
  * </p>
  * The underlying stream offset is maintained as state.
  */
 public class CTRCryptoOutputStream extends CryptoOutputStream {
-  /**
-   * Underlying stream offset.
-   */
-  long streamOffset = 0;
+    /**
+     * Underlying stream offset.
+     */
+    long streamOffset = 0;
 
-  /**
-   * The initial IV.
-   */
-  protected final byte[] initIV;
+    /**
+     * The initial IV.
+     */
+    protected final byte[] initIV;
 
-  /**
-   * Initialization vector for the cipher.
-   */
-  protected byte[] iv;
+    /**
+     * Initialization vector for the cipher.
+     */
+    protected byte[] iv;
 
-  /**
-   * Padding = pos%(algorithm blocksize); Padding is put into {@link #inBuffer}
-   * before any other data goes in. The purpose of padding is to put input data
-   * at proper position.
-   */
-  private byte padding;
+    /**
+     * Padding = pos%(algorithm blocksize); Padding is put into
+     * {@link #inBuffer} before any other data goes in. The purpose of padding
+     * is to put input data at proper position.
+     */
+    private byte padding;
 
-  /**
-   * Flag to mark whether the cipher has been reset
-   */
-  private boolean cipherReset = false;
+    /**
+     * Flag to mark whether the cipher has been reset
+     */
+    private boolean cipherReset = false;
 
-  /**
-   * Constructs a {@link CTRCryptoOutputStream}.
-   *
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param out the output stream.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoOutputStream(Properties props, OutputStream out, byte[] key,
-                               byte[] iv)
-      throws IOException {
-    this(props, out, key, iv, 0);
-  }
-
-  /**
-   * Constructs a {@link CTRCryptoOutputStream}.
-   *
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param out the WritableByteChannel instance.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoOutputStream(Properties props, WritableByteChannel out,
-                               byte[] key, byte[] iv)
-      throws IOException {
-    this(props, out, key, iv, 0);
-  }
+    /**
+     * Constructs a {@link CTRCryptoOutputStream}.
+     *
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param out the output stream.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoOutputStream(Properties props, OutputStream out,
+            byte[] key, byte[] iv) throws IOException {
+        this(props, out, key, iv, 0);
+    }
 
-  /**
-   * Constructs a {@link CTRCryptoOutputStream}.
-   *
-   * @param out the output stream.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoOutputStream(OutputStream out, CryptoCipher cipher, int 
bufferSize,
-                               byte[] key, byte[] iv) throws IOException {
-    this(out, cipher, bufferSize, key, iv, 0);
-  }
+    /**
+     * Constructs a {@link CTRCryptoOutputStream}.
+     *
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param out the WritableByteChannel instance.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoOutputStream(Properties props, WritableByteChannel out,
+            byte[] key, byte[] iv) throws IOException {
+        this(props, out, key, iv, 0);
+    }
 
-  /**
-   * Constructs a {@link CTRCryptoOutputStream}.
-   *
-   * @param channel the WritableByteChannel instance.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoOutputStream(WritableByteChannel channel, CryptoCipher 
cipher,
-                               int bufferSize, byte[] key, byte[] iv) throws 
IOException {
-    this(channel, cipher, bufferSize, key, iv, 0);
-  }
+    /**
+     * Constructs a {@link CTRCryptoOutputStream}.
+     *
+     * @param out the output stream.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoOutputStream(OutputStream out, CryptoCipher cipher,
+            int bufferSize, byte[] key, byte[] iv) throws IOException {
+        this(out, cipher, bufferSize, key, iv, 0);
+    }
 
-  /**
-   * Constructs a {@link CTRCryptoOutputStream}.
-   *
-   * @param output the Output instance.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoOutputStream(Output output, CryptoCipher cipher, int 
bufferSize,
-                               byte[] key, byte[] iv)
-      throws IOException {
-    this(output, cipher, bufferSize, key, iv, 0);
-  }
+    /**
+     * Constructs a {@link CTRCryptoOutputStream}.
+     *
+     * @param channel the WritableByteChannel instance.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoOutputStream(WritableByteChannel channel,
+            CryptoCipher cipher, int bufferSize, byte[] key, byte[] iv)
+            throws IOException {
+        this(channel, cipher, bufferSize, key, iv, 0);
+    }
 
-  /**
-   * Constructs a {@link CTRCryptoOutputStream}.
-   *
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param out the output stream.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @param streamOffset the start offset in the data.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoOutputStream(Properties props, OutputStream out, byte[] key,
-                               byte[] iv, long streamOffset)
-      throws IOException {
-    this(out, Utils.getCipherInstance(CipherTransformation.AES_CTR_NOPADDING, 
props),
-        Utils.getBufferSize(props), key, iv, streamOffset);
-  }
+    /**
+     * Constructs a {@link CTRCryptoOutputStream}.
+     *
+     * @param output the Output instance.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoOutputStream(Output output, CryptoCipher cipher,
+            int bufferSize, byte[] key, byte[] iv) throws IOException {
+        this(output, cipher, bufferSize, key, iv, 0);
+    }
 
-  /**
-   * Constructs a {@link CTRCryptoOutputStream}.
-   *
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param out the WritableByteChannel instance.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @param streamOffset the start offset in the data.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoOutputStream(Properties props, WritableByteChannel out,
-                               byte[] key, byte[] iv, long streamOffset)
-      throws IOException {
-    this(out, Utils.getCipherInstance(CipherTransformation.AES_CTR_NOPADDING, 
props),
-        Utils.getBufferSize(props), key, iv, streamOffset);
-  }
+    /**
+     * Constructs a {@link CTRCryptoOutputStream}.
+     *
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param out the output stream.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @param streamOffset the start offset in the data.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoOutputStream(Properties props, OutputStream out,
+            byte[] key, byte[] iv, long streamOffset) throws IOException {
+        this(out, Utils.getCipherInstance(
+                CipherTransformation.AES_CTR_NOPADDING, props), Utils
+                .getBufferSize(props), key, iv, streamOffset);
+    }
 
-  /**
-   * Constructs a {@link CTRCryptoOutputStream}.
-   *
-   * @param out the output stream.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @param streamOffset the start offset in the data.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoOutputStream(OutputStream out, CryptoCipher cipher, int 
bufferSize,
-                               byte[] key, byte[] iv, long streamOffset) 
throws IOException {
-    this(new StreamOutput(out, bufferSize), cipher,
-        bufferSize, key, iv, streamOffset);
-  }
+    /**
+     * Constructs a {@link CTRCryptoOutputStream}.
+     *
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param out the WritableByteChannel instance.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @param streamOffset the start offset in the data.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoOutputStream(Properties props, WritableByteChannel out,
+            byte[] key, byte[] iv, long streamOffset) throws IOException {
+        this(out, Utils.getCipherInstance(
+                CipherTransformation.AES_CTR_NOPADDING, props), Utils
+                .getBufferSize(props), key, iv, streamOffset);
+    }
 
-  /**
-   * Constructs a {@link CTRCryptoOutputStream}.
-   *
-   * @param channel the WritableByteChannel instance.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @param streamOffset the start offset in the data.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoOutputStream(WritableByteChannel channel, CryptoCipher 
cipher,
-                               int bufferSize, byte[] key, byte[] iv,
-                               long streamOffset) throws IOException {
-    this(new ChannelOutput(channel), cipher,
-        bufferSize, key, iv, streamOffset);
-  }
+    /**
+     * Constructs a {@link CTRCryptoOutputStream}.
+     *
+     * @param out the output stream.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @param streamOffset the start offset in the data.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoOutputStream(OutputStream out, CryptoCipher cipher,
+            int bufferSize, byte[] key, byte[] iv, long streamOffset)
+            throws IOException {
+        this(new StreamOutput(out, bufferSize), cipher, bufferSize, key, iv,
+                streamOffset);
+    }
 
-  /**
-   * Constructs a {@link CTRCryptoOutputStream}.
-   *
-   * @param output the output stream.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param iv Initialization vector for the cipher.
-   * @param streamOffset the start offset in the data.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CTRCryptoOutputStream(Output output, CryptoCipher cipher, int 
bufferSize,
-                               byte[] key, byte[] iv, long streamOffset)
-      throws IOException {
-    super(output, cipher, bufferSize, new SecretKeySpec(key, "AES"), new 
IvParameterSpec(iv));
+    /**
+     * Constructs a {@link CTRCryptoOutputStream}.
+     *
+     * @param channel the WritableByteChannel instance.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @param streamOffset the start offset in the data.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoOutputStream(WritableByteChannel channel,
+            CryptoCipher cipher, int bufferSize, byte[] key, byte[] iv,
+            long streamOffset) throws IOException {
+        this(new ChannelOutput(channel), cipher, bufferSize, key, iv,
+                streamOffset);
+    }
 
-    Utils.checkStreamCipher(cipher);
-    this.streamOffset = streamOffset;
-    this.initIV = iv.clone();
-    this.iv = iv.clone();
+    /**
+     * Constructs a {@link CTRCryptoOutputStream}.
+     *
+     * @param output the output stream.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param iv Initialization vector for the cipher.
+     * @param streamOffset the start offset in the data.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CTRCryptoOutputStream(Output output, CryptoCipher cipher,
+            int bufferSize, byte[] key, byte[] iv, long streamOffset)
+            throws IOException {
+        super(output, cipher, bufferSize, new SecretKeySpec(key, "AES"),
+                new IvParameterSpec(iv));
 
-    resetCipher();
-  }
+        Utils.checkStreamCipher(cipher);
+        this.streamOffset = streamOffset;
+        this.initIV = iv.clone();
+        this.iv = iv.clone();
 
-  /**
-   * Does the encryption, input is {@link #inBuffer} and output is
-   * {@link #outBuffer}.
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  protected void encrypt() throws IOException {
-    Utils.checkState(inBuffer.position() >= padding);
-    if (inBuffer.position() == padding) {
-      // There is no real data in the inBuffer.
-      return;
+        resetCipher();
     }
 
-    inBuffer.flip();
-    outBuffer.clear();
-    encryptBuffer(outBuffer);
-    inBuffer.clear();
-    outBuffer.flip();
+    /**
+     * Does the encryption, input is {@link #inBuffer} and output is
+     * {@link #outBuffer}.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    protected void encrypt() throws IOException {
+        Utils.checkState(inBuffer.position() >= padding);
+        if (inBuffer.position() == padding) {
+            // There is no real data in the inBuffer.
+            return;
+        }
 
-    if (padding > 0) {
-      /*
-       * The plain text and cipher text have a 1:1 mapping, they start at the
-       * same position.
-       */
-      outBuffer.position(padding);
-      padding = 0;
-    }
+        inBuffer.flip();
+        outBuffer.clear();
+        encryptBuffer(outBuffer);
+        inBuffer.clear();
+        outBuffer.flip();
+
+        if (padding > 0) {
+            /*
+             * The plain text and cipher text have a 1:1 mapping, they start at
+             * the same position.
+             */
+            outBuffer.position(padding);
+            padding = 0;
+        }
 
-    final int len = output.write(outBuffer);
-    streamOffset += len;
-    if (cipherReset) {
-      /*
-       * This code is generally not executed since the encryptor usually
-       * maintains encryption context (e.g. the counter) internally. However,
-       * some implementations can't maintain context so a re-init is necessary
-       * after each encryption call.
-       */
-      resetCipher();
+        final int len = output.write(outBuffer);
+        streamOffset += len;
+        if (cipherReset) {
+            /*
+             * This code is generally not executed since the encryptor usually
+             * maintains encryption context (e.g. the counter) internally.
+             * However, some implementations can't maintain context so a 
re-init
+             * is necessary after each encryption call.
+             */
+            resetCipher();
+        }
     }
-  }
 
-  /**
-   * Does final encryption of the last data.
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  protected void encryptFinal() throws IOException {
-    // The same as the normal encryption for Counter mode
-    encrypt();
-  }
+    /**
+     * Does final encryption of the last data.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    protected void encryptFinal() throws IOException {
+        // The same as the normal encryption for Counter mode
+        encrypt();
+    }
 
-  /**
-   * Overrides the {@link CryptoOutputStream#initCipher()}.
-   * Initializes the cipher.
-   */
-  @Override
-  protected void initCipher() {
-    // Do nothing for initCipher
-    // Will reset the cipher considering the stream offset
-  }
+    /**
+     * Overrides the {@link CryptoOutputStream#initCipher()}. Initializes the
+     * cipher.
+     */
+    @Override
+    protected void initCipher() {
+        // Do nothing for initCipher
+        // Will reset the cipher considering the stream offset
+    }
 
-  /**
-   * Resets the {@link #cipher}: calculate counter and {@link #padding}.
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  private void resetCipher() throws IOException {
-    final long counter =
-        streamOffset / cipher.getTransformation().getAlgorithmBlockSize();
-    padding =
-        (byte)(streamOffset % 
cipher.getTransformation().getAlgorithmBlockSize());
-    inBuffer.position(padding); // Set proper position for input data.
+    /**
+     * Resets the {@link #cipher}: calculate counter and {@link #padding}.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    private void resetCipher() throws IOException {
+        final long counter = streamOffset
+                / cipher.getTransformation().getAlgorithmBlockSize();
+        padding = (byte) (streamOffset % cipher.getTransformation()
+                .getAlgorithmBlockSize());
+        inBuffer.position(padding); // Set proper position for input data.
 
-    Utils.calculateIV(initIV, counter, iv);
-    try {
-      cipher.init(CryptoCipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
-    } catch (InvalidKeyException e) {
-      throw new IOException(e);
-    }catch (InvalidAlgorithmParameterException e) {
-      throw new IOException(e);
+        Utils.calculateIV(initIV, counter, iv);
+        try {
+            cipher.init(CryptoCipher.ENCRYPT_MODE, key, new 
IvParameterSpec(iv));
+        } catch (InvalidKeyException e) {
+            throw new IOException(e);
+        } catch (InvalidAlgorithmParameterException e) {
+            throw new IOException(e);
+        }
+        cipherReset = false;
     }
-    cipherReset = false;
-  }
 
-  /**
-   * Does the encryption if the ByteBuffer data.
-   *
-   * @param out the output ByteBuffer.
-   * @throws IOException if an I/O error occurs.
-   */
-  private void encryptBuffer(ByteBuffer out)
-      throws IOException {
-    int inputSize = inBuffer.remaining();
-    try {
-      int n = cipher.update(inBuffer, out);
-      if (n < inputSize) {
-        /**
-         * Typically code will not get here. CryptoCipher#update will consume 
all
-         * input data and put result in outBuffer.
-         * CryptoCipher#doFinal will reset the cipher context.
-         */
-        cipher.doFinal(inBuffer, out);
-        cipherReset = true;
-      }
-    } catch (ShortBufferException e) {
-      throw new IOException(e);
-    } catch (BadPaddingException e) {
-      throw new IOException(e);
-    } catch (IllegalBlockSizeException e) {
-      throw new IOException(e);
+    /**
+     * Does the encryption if the ByteBuffer data.
+     *
+     * @param out the output ByteBuffer.
+     * @throws IOException if an I/O error occurs.
+     */
+    private void encryptBuffer(ByteBuffer out) throws IOException {
+        int inputSize = inBuffer.remaining();
+        try {
+            int n = cipher.update(inBuffer, out);
+            if (n < inputSize) {
+                /**
+                 * Typically code will not get here. CryptoCipher#update will
+                 * consume all input data and put result in outBuffer.
+                 * CryptoCipher#doFinal will reset the cipher context.
+                 */
+                cipher.doFinal(inBuffer, out);
+                cipherReset = true;
+            }
+        } catch (ShortBufferException e) {
+            throw new IOException(e);
+        } catch (BadPaddingException e) {
+            throw new IOException(e);
+        } catch (IllegalBlockSizeException e) {
+            throw new IOException(e);
+        }
     }
-  }
 
-  /**
-   * Get the underlying stream offset
-   *
-   * @return the underlying stream offset
-   */
-  protected long getStreamOffset() {
-    return streamOffset;
-  }
+    /**
+     * Get the underlying stream offset
+     *
+     * @return the underlying stream offset
+     */
+    protected long getStreamOffset() {
+        return streamOffset;
+    }
 
-  /**
-   * Set the underlying stream offset
-   *
-   * @param streamOffset the underlying stream offset
-   */
-  protected void setStreamOffset(long streamOffset) {
-    this.streamOffset = streamOffset;
-  }
+    /**
+     * Set the underlying stream offset
+     *
+     * @param streamOffset the underlying stream offset
+     */
+    protected void setStreamOffset(long streamOffset) {
+        this.streamOffset = streamOffset;
+    }
 }

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/stream/CryptoInputStream.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/crypto/stream/CryptoInputStream.java 
b/src/main/java/org/apache/commons/crypto/stream/CryptoInputStream.java
index 7b4313b..edf3e7f 100644
--- a/src/main/java/org/apache/commons/crypto/stream/CryptoInputStream.java
+++ b/src/main/java/org/apache/commons/crypto/stream/CryptoInputStream.java
@@ -40,521 +40,526 @@ import org.apache.commons.crypto.stream.input.StreamInput;
 import org.apache.commons.crypto.utils.Utils;
 
 /**
- * CryptoInputStream reads input data and decrypts data in stream manner. It 
supports
- * any mode of operations such as AES CBC/CTR/GCM mode in concept.It is not 
thread-safe.
+ * CryptoInputStream reads input data and decrypts data in stream manner. It
+ * supports any mode of operations such as AES CBC/CTR/GCM mode in concept.It 
is
+ * not thread-safe.
  *
  */
 
 public class CryptoInputStream extends InputStream implements
-    ReadableByteChannel {
-  private final byte[] oneByteBuf = new byte[1];
-
-  /**The CryptoCipher instance.*/
-  final CryptoCipher cipher;
-
-  /**The buffer size.*/
-  final int bufferSize;
-
-  /**Crypto key for the cipher.*/
-  final Key key;
-
-  /** the algorithm parameters */
-  final AlgorithmParameterSpec params;
-
-  /** Flag to mark whether the input stream is closed.*/
-  private boolean closed;
-
-  /** Flag to mark whether do final of the cipher to end the decrypting 
stream.*/
-  private boolean finalDone = false;
-
-  /**The input data.*/
-  Input input;
-
-  /**
-   * Input data buffer. The data starts at inBuffer.position() and ends at
-   * to inBuffer.limit().
-   */
-  protected ByteBuffer inBuffer;
-
-  /**
-   * The decrypted data buffer. The data starts at outBuffer.position() and
-   * ends at outBuffer.limit().
-   */
-  protected ByteBuffer outBuffer;
-
-  /**
-   * Constructs a {@link CryptoInputStream}.
-   *
-   * @param transformation the CipherTransformation instance.
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param in the input stream.
-   * @param key crypto key for the cipher.
-   * @param params the algorithm parameters.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CryptoInputStream(CipherTransformation transformation,
-                           Properties props, InputStream in, Key key, 
AlgorithmParameterSpec params)
-      throws IOException {
-    this(in, Utils.getCipherInstance(transformation, props), 
Utils.getBufferSize(props), key,
-      params);
-  }
-
-  /**
-   * Constructs a {@link CryptoInputStream}.
-   *
-   * @param transformation the CipherTransformation instance.
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param in the ReadableByteChannel object.
-   * @param key crypto key for the cipher.
-   * @param params the algorithm parameters.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CryptoInputStream(CipherTransformation transformation,
-                           Properties props, ReadableByteChannel in, Key key, 
AlgorithmParameterSpec params)
-      throws IOException {
-    this(in, Utils.getCipherInstance(transformation, props),
-        Utils.getBufferSize(props), key, params);
-  }
-
-  /**
-   * Constructs a {@link CryptoInputStream}.
-   *
-   * @param cipher the cipher instance.
-   * @param in the input stream.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param params the algorithm parameters.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CryptoInputStream(InputStream in, CryptoCipher cipher, int bufferSize,
-                           Key key, AlgorithmParameterSpec params) throws 
IOException {
-    this(new StreamInput(in, bufferSize), cipher, bufferSize, key, params);
-  }
-
-  /**
-   * Constructs a {@link CryptoInputStream}.
-   *
-   * @param in the ReadableByteChannel instance.
-   * @param cipher the cipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param params the algorithm parameters.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CryptoInputStream(ReadableByteChannel in, CryptoCipher cipher,
-                           int bufferSize, Key key, AlgorithmParameterSpec 
params) throws IOException {
-    this(new ChannelInput(in), cipher, bufferSize, key, params);
-  }
-
-  /**
-   * Constructs a {@link CryptoInputStream}.
-   *
-   * @param input the input data.
-   * @param cipher the cipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param params the algorithm parameters.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CryptoInputStream(Input input, CryptoCipher cipher, int bufferSize,
-                           Key key, AlgorithmParameterSpec params) throws 
IOException {
-    this.input = input;
-    this.cipher = cipher;
-    this.bufferSize = Utils.checkBufferSize(cipher, bufferSize);
-
-    this.key = key;
-    this.params = params;
-    if (!(params instanceof IvParameterSpec)) {
-      //other AlgorithmParameterSpec such as GCMParameterSpec is not supported 
now.
-      throw new IOException("Illegal parameters");
+        ReadableByteChannel {
+    private final byte[] oneByteBuf = new byte[1];
+
+    /** The CryptoCipher instance. */
+    final CryptoCipher cipher;
+
+    /** The buffer size. */
+    final int bufferSize;
+
+    /** Crypto key for the cipher. */
+    final Key key;
+
+    /** the algorithm parameters */
+    final AlgorithmParameterSpec params;
+
+    /** Flag to mark whether the input stream is closed. */
+    private boolean closed;
+
+    /**
+     * Flag to mark whether do final of the cipher to end the decrypting 
stream.
+     */
+    private boolean finalDone = false;
+
+    /** The input data. */
+    Input input;
+
+    /**
+     * Input data buffer. The data starts at inBuffer.position() and ends at to
+     * inBuffer.limit().
+     */
+    protected ByteBuffer inBuffer;
+
+    /**
+     * The decrypted data buffer. The data starts at outBuffer.position() and
+     * ends at outBuffer.limit().
+     */
+    protected ByteBuffer outBuffer;
+
+    /**
+     * Constructs a {@link CryptoInputStream}.
+     *
+     * @param transformation the CipherTransformation instance.
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param in the input stream.
+     * @param key crypto key for the cipher.
+     * @param params the algorithm parameters.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CryptoInputStream(CipherTransformation transformation,
+            Properties props, InputStream in, Key key,
+            AlgorithmParameterSpec params) throws IOException {
+        this(in, Utils.getCipherInstance(transformation, props), Utils
+                .getBufferSize(props), key, params);
     }
 
-    inBuffer = ByteBuffer.allocateDirect(this.bufferSize);
-    outBuffer = ByteBuffer.allocateDirect(this.bufferSize +
-        cipher.getTransformation().getAlgorithmBlockSize());
-    outBuffer.limit(0);
-
-    initCipher();
-  }
-
-  /**
-   * Overrides the {@link java.io.InputStream#read()}.
-   * Reads the next byte of data from the input stream.
-   *
-   * @return the next byte of data, or <code>-1</code> if the end of the
-   *         stream is reached.
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public int read() throws IOException {
-    int n;
-    while ((n = read(oneByteBuf, 0, 1)) == 0) ;
-    return (n == -1) ? -1 : oneByteBuf[0] & 0xff;
-  }
-
-  /**
-   * Overrides the {@link java.io.InputStream#read(byte[], int, int)}.
-   * Decryption is buffer based.
-   * If there is data in {@link #outBuffer}, then read it out of this buffer.
-   * If there is no data in {@link #outBuffer}, then read more from the
-   * underlying stream and do the decryption.
-   *
-   * @param b the buffer into which the decrypted data is read.
-   * @param off the buffer offset.
-   * @param len the maximum number of decrypted data bytes to read.
-   * @return int the total number of decrypted data bytes read into the buffer.
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public int read(byte[] b, int off, int len) throws IOException {
-    checkStream();
-    if (b == null) {
-      throw new NullPointerException();
-    } else if (off < 0 || len < 0 || len > b.length - off) {
-      throw new IndexOutOfBoundsException();
-    } else if (len == 0) {
-      return 0;
+    /**
+     * Constructs a {@link CryptoInputStream}.
+     *
+     * @param transformation the CipherTransformation instance.
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param in the ReadableByteChannel object.
+     * @param key crypto key for the cipher.
+     * @param params the algorithm parameters.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CryptoInputStream(CipherTransformation transformation,
+            Properties props, ReadableByteChannel in, Key key,
+            AlgorithmParameterSpec params) throws IOException {
+        this(in, Utils.getCipherInstance(transformation, props), Utils
+                .getBufferSize(props), key, params);
     }
 
-    int remaining = outBuffer.remaining();
-    if (remaining > 0) {
-      // Satisfy the read with the existing data
-      int n = Math.min(len, remaining);
-      outBuffer.get(b, off, n);
-      return n;
-    } else {
-      // No data in the out buffer, try read new data and decrypt it
-      int nd = decryptMore();
-      if(nd <= 0)
-        return nd;
-
-      int n = Math.min(len, outBuffer.remaining());
-      outBuffer.get(b, off, n);
-      return n;
+    /**
+     * Constructs a {@link CryptoInputStream}.
+     *
+     * @param cipher the cipher instance.
+     * @param in the input stream.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param params the algorithm parameters.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CryptoInputStream(InputStream in, CryptoCipher cipher,
+            int bufferSize, Key key, AlgorithmParameterSpec params)
+            throws IOException {
+        this(new StreamInput(in, bufferSize), cipher, bufferSize, key, params);
     }
-  }
-
-  /**
-   * Overrides the {@link java.io.InputStream#skip(long)}.
-   * Skips over and discards <code>n</code> bytes of data from this input
-   * stream.
-   *
-   * @param n the number of bytes to be skipped.
-   * @return the actual number of bytes skipped.
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public long skip(long n) throws IOException {
-    Utils.checkArgument(n >= 0, "Negative skip length.");
-    checkStream();
-
-    if (n == 0) {
-      return 0;
+
+    /**
+     * Constructs a {@link CryptoInputStream}.
+     *
+     * @param in the ReadableByteChannel instance.
+     * @param cipher the cipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param params the algorithm parameters.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CryptoInputStream(ReadableByteChannel in, CryptoCipher cipher,
+            int bufferSize, Key key, AlgorithmParameterSpec params)
+            throws IOException {
+        this(new ChannelInput(in), cipher, bufferSize, key, params);
     }
 
-    long remaining = n;
-    int nd;
+    /**
+     * Constructs a {@link CryptoInputStream}.
+     *
+     * @param input the input data.
+     * @param cipher the cipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param params the algorithm parameters.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CryptoInputStream(Input input, CryptoCipher cipher, int bufferSize,
+            Key key, AlgorithmParameterSpec params) throws IOException {
+        this.input = input;
+        this.cipher = cipher;
+        this.bufferSize = Utils.checkBufferSize(cipher, bufferSize);
+
+        this.key = key;
+        this.params = params;
+        if (!(params instanceof IvParameterSpec)) {
+            // other AlgorithmParameterSpec such as GCMParameterSpec is not
+            // supported now.
+            throw new IOException("Illegal parameters");
+        }
+
+        inBuffer = ByteBuffer.allocateDirect(this.bufferSize);
+        outBuffer = ByteBuffer.allocateDirect(this.bufferSize
+                + cipher.getTransformation().getAlgorithmBlockSize());
+        outBuffer.limit(0);
+
+        initCipher();
+    }
 
-    while (remaining > 0) {
-      if(remaining <= outBuffer.remaining()) {
-        // Skip in the remaining buffer
-        int pos = outBuffer.position() + (int) remaining;
-        outBuffer.position(pos);
+    /**
+     * Overrides the {@link java.io.InputStream#read()}. Reads the next byte of
+     * data from the input stream.
+     *
+     * @return the next byte of data, or <code>-1</code> if the end of the
+     *         stream is reached.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public int read() throws IOException {
+        int n;
+        while ((n = read(oneByteBuf, 0, 1)) == 0)
+            ;
+        return (n == -1) ? -1 : oneByteBuf[0] & 0xff;
+    }
 
-        remaining = 0;
-        break;
-      } else {
-        remaining -= outBuffer.remaining();
-        outBuffer.clear();
-      }
+    /**
+     * Overrides the {@link java.io.InputStream#read(byte[], int, int)}.
+     * Decryption is buffer based. If there is data in {@link #outBuffer}, then
+     * read it out of this buffer. If there is no data in {@link #outBuffer},
+     * then read more from the underlying stream and do the decryption.
+     *
+     * @param b the buffer into which the decrypted data is read.
+     * @param off the buffer offset.
+     * @param len the maximum number of decrypted data bytes to read.
+     * @return int the total number of decrypted data bytes read into the
+     *         buffer.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        checkStream();
+        if (b == null) {
+            throw new NullPointerException();
+        } else if (off < 0 || len < 0 || len > b.length - off) {
+            throw new IndexOutOfBoundsException();
+        } else if (len == 0) {
+            return 0;
+        }
+
+        int remaining = outBuffer.remaining();
+        if (remaining > 0) {
+            // Satisfy the read with the existing data
+            int n = Math.min(len, remaining);
+            outBuffer.get(b, off, n);
+            return n;
+        } else {
+            // No data in the out buffer, try read new data and decrypt it
+            int nd = decryptMore();
+            if (nd <= 0)
+                return nd;
+
+            int n = Math.min(len, outBuffer.remaining());
+            outBuffer.get(b, off, n);
+            return n;
+        }
+    }
+
+    /**
+     * Overrides the {@link java.io.InputStream#skip(long)}. Skips over and
+     * discards <code>n</code> bytes of data from this input stream.
+     *
+     * @param n the number of bytes to be skipped.
+     * @return the actual number of bytes skipped.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public long skip(long n) throws IOException {
+        Utils.checkArgument(n >= 0, "Negative skip length.");
+        checkStream();
+
+        if (n == 0) {
+            return 0;
+        }
+
+        long remaining = n;
+        int nd;
+
+        while (remaining > 0) {
+            if (remaining <= outBuffer.remaining()) {
+                // Skip in the remaining buffer
+                int pos = outBuffer.position() + (int) remaining;
+                outBuffer.position(pos);
+
+                remaining = 0;
+                break;
+            } else {
+                remaining -= outBuffer.remaining();
+                outBuffer.clear();
+            }
+
+            nd = decryptMore();
+            if (nd < 0) {
+                break;
+            }
+        }
+
+        return n - remaining;
+    }
+
+    /**
+     * Overrides the {@link InputStream#available()}. Returns an estimate of 
the
+     * number of bytes that can be read (or skipped over) from this input 
stream
+     * without blocking by the next invocation of a method for this input
+     * stream.
+     *
+     * @return an estimate of the number of bytes that can be read (or skipped
+     *         over) from this input stream without blocking or {@code 0} when
+     *         it reaches the end of the input stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public int available() throws IOException {
+        checkStream();
+
+        return input.available() + outBuffer.remaining();
+    }
+
+    /**
+     * Overrides the {@link InputStream#close()}. Closes this input stream and
+     * releases any system resources associated with the stream.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public void close() throws IOException {
+        if (closed) {
+            return;
+        }
+
+        input.close();
+        freeBuffers();
+        cipher.close();
+        super.close();
+        closed = true;
+    }
+
+    /**
+     * Overrides the {@link java.io.InputStream#mark(int)}. For
+     * {@link CryptoInputStream},we don't support the mark method.
+     *
+     * @param readlimit the maximum limit of bytes that can be read before the
+     *        mark position becomes invalid.
+     */
+    @Override
+    public void mark(int readlimit) {
+    }
+
+    /**
+     * Overrides the {@link InputStream#reset()}. For {@link CryptoInputStream}
+     * ,we don't support the reset method.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public void reset() throws IOException {
+        throw new IOException("Mark/reset not supported");
+    }
 
-      nd = decryptMore();
-      if (nd < 0) {
-        break;
-      }
+    /**
+     * Overrides the {@link InputStream#markSupported()}.
+     *
+     * @return false,the {@link CTRCryptoInputStream} don't support the mark
+     *         method.
+     */
+    @Override
+    public boolean markSupported() {
+        return false;
     }
 
-    return n - remaining;
-  }
-
-  /**
-   * Overrides the {@link InputStream#available()}.
-   * Returns an estimate of the number of bytes that can be read (or
-   * skipped over) from this input stream without blocking by the next
-   * invocation of a method for this input stream.
-   *
-   * @return an estimate of the number of bytes that can be read (or skipped
-   *         over) from this input stream without blocking or {@code 0} when
-   *          it reaches the end of the input stream.
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public int available() throws IOException {
-    checkStream();
-
-    return input.available() + outBuffer.remaining();
-  }
-
-  /**
-   * Overrides the {@link InputStream#close()}.
-   * Closes this input stream and releases any system resources associated
-   * with the stream.
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public void close() throws IOException {
-    if (closed) {
-      return;
+    /**
+     * Overrides the {@link Channel#isOpen()}.
+     *
+     * @return <tt>true</tt> if, and only if, this channel is open.
+     */
+    @Override
+    public boolean isOpen() {
+        return !closed;
     }
 
-    input.close();
-    freeBuffers();
-    cipher.close();
-    super.close();
-    closed = true;
-  }
-
-  /**
-   * Overrides the {@link java.io.InputStream#mark(int)}.
-   * For {@link CryptoInputStream},we don't support the mark method.
-   *
-   * @param readlimit the maximum limit of bytes that can be read before
-   *                  the mark position becomes invalid.
-   */
-  @Override
-  public void mark(int readlimit) {
-  }
-
-  /**
-   * Overrides the {@link InputStream#reset()}.
-   * For {@link CryptoInputStream},we don't support the reset method.
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public void reset() throws IOException {
-    throw new IOException("Mark/reset not supported");
-  }
-
-  /**
-   * Overrides the {@link InputStream#markSupported()}.
-   *
-   * @return false,the {@link CTRCryptoInputStream} don't support the mark 
method.
-   */
-  @Override
-  public boolean markSupported() {
-    return false;
-  }
-
-  /**
-   * Overrides the {@link Channel#isOpen()}.
-   *
-   * @return <tt>true</tt> if, and only if, this channel is open.
-   */
-  @Override
-  public boolean isOpen() {
-    return !closed;
-  }
-
-  /**
-   * Overrides the {@link 
java.nio.channels.ReadableByteChannel#read(ByteBuffer)}.
-   * Reads a sequence of bytes from this channel into the given buffer.
-   *
-   * @param dst The buffer into which bytes are to be transferred.
-   * @return The number of bytes read, possibly zero, or <tt>-1</tt> if the
-   *         channel has reached end-of-stream.
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public int read(ByteBuffer dst) throws IOException {
-    checkStream();
-    int remaining = outBuffer.remaining();
-    if (remaining <= 0) {
-      // Decrypt more data
-      int nd = decryptMore();
-      if(nd < 0) {
-        return -1;
-      }
+    /**
+     * Overrides the
+     * {@link java.nio.channels.ReadableByteChannel#read(ByteBuffer)}. Reads a
+     * sequence of bytes from this channel into the given buffer.
+     *
+     * @param dst The buffer into which bytes are to be transferred.
+     * @return The number of bytes read, possibly zero, or <tt>-1</tt> if the
+     *         channel has reached end-of-stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public int read(ByteBuffer dst) throws IOException {
+        checkStream();
+        int remaining = outBuffer.remaining();
+        if (remaining <= 0) {
+            // Decrypt more data
+            int nd = decryptMore();
+            if (nd < 0) {
+                return -1;
+            }
+        }
+
+        // Copy decrypted data from outBuffer to dst
+        remaining = outBuffer.remaining();
+        final int toRead = dst.remaining();
+        if (toRead <= remaining) {
+            final int limit = outBuffer.limit();
+            outBuffer.limit(outBuffer.position() + toRead);
+            dst.put(outBuffer);
+            outBuffer.limit(limit);
+            return toRead;
+        } else {
+            dst.put(outBuffer);
+            return remaining;
+        }
     }
 
-    // Copy decrypted data from outBuffer to dst
-    remaining = outBuffer.remaining();
-    final int toRead = dst.remaining();
-    if (toRead <= remaining) {
-      final int limit = outBuffer.limit();
-      outBuffer.limit(outBuffer.position() + toRead);
-      dst.put(outBuffer);
-      outBuffer.limit(limit);
-      return toRead;
-    } else {
-      dst.put(outBuffer);
-      return remaining;
+    /**
+     * Gets the buffer size.
+     *
+     * @return the bufferSize.
+     */
+    protected int getBufferSize() {
+        return bufferSize;
     }
-  }
-
-  /**
-   * Gets the buffer size.
-   *
-   * @return the bufferSize.
-   */
-  protected int getBufferSize() {
-    return bufferSize;
-  }
-
-  /**
-   * Gets the key.
-   *
-   * @return the key.
-   */
-  protected Key getKey() {
-    return key;
-  }
-
-
-  /**
-   * Gets the internal CryptoCipher.
-   *
-   * @return the cipher instance.
-   */
-  protected CryptoCipher getCipher() {
-    return cipher;
-  }
-
-  /**
-   * Gets the specification of cryptographic parameters.
-   *
-   * @return the params.
-   */
-  protected AlgorithmParameterSpec getParams() {
-    return params;
-  }
-
-  /**
-   * Gets the input.
-   *
-   * @return the input.
-   */
-  protected Input getInput() {
-    return input;
-  }
-
-  /**
-   * Initializes the cipher.
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  protected void initCipher()
-      throws IOException {
-    try {
-      cipher.init(CryptoCipher.DECRYPT_MODE, key, params);
-    } catch (InvalidKeyException e) {
-      throw new IOException(e);
-    } catch(InvalidAlgorithmParameterException e) {
-      throw new IOException(e);
+
+    /**
+     * Gets the key.
+     *
+     * @return the key.
+     */
+    protected Key getKey() {
+        return key;
+    }
+
+    /**
+     * Gets the internal CryptoCipher.
+     *
+     * @return the cipher instance.
+     */
+    protected CryptoCipher getCipher() {
+        return cipher;
     }
-  }
-
-  /**
-   * Decrypts more data by reading the under layer stream. The decrypted data 
will
-   * be put in the output buffer. If the end of the under stream reached, we 
will
-   * do final of the cipher to finish all the decrypting of data.
-   *
-   * @return The number of decrypted data. -1 if end of the decrypted stream.
-   * @throws IOException if an I/O error occurs.
-   */
-  protected int decryptMore() throws IOException {
-    if(finalDone) {
-      return -1;
+
+    /**
+     * Gets the specification of cryptographic parameters.
+     *
+     * @return the params.
+     */
+    protected AlgorithmParameterSpec getParams() {
+        return params;
     }
 
-    int n = input.read(inBuffer);
-    if (n < 0) {
-      // The stream is end, finalize the cipher stream
-      decryptFinal();
-
-      // Satisfy the read with the remaining
-      int remaining = outBuffer.remaining();
-      if (remaining > 0) {
-        return remaining;
-      }
-
-      // End of the stream
-      return -1;
-    } else if(n == 0) {
-      // No data is read, but the stream is not end yet
-      return 0;
-    } else {
-      decrypt();
-      return outBuffer.remaining();
+    /**
+     * Gets the input.
+     *
+     * @return the input.
+     */
+    protected Input getInput() {
+        return input;
     }
-  }
-
-  /**
-   * Does the decryption using inBuffer as input and outBuffer as output.
-   * Upon return, inBuffer is cleared; the decrypted data starts at
-   * outBuffer.position() and ends at outBuffer.limit().
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  protected void decrypt() throws IOException {
-    // Prepare the input buffer and clear the out buffer
-    inBuffer.flip();
-    outBuffer.clear();
-
-    try {
-      cipher.update(inBuffer, outBuffer);
-    } catch (ShortBufferException e) {
-      throw new IOException(e);
+
+    /**
+     * Initializes the cipher.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void initCipher() throws IOException {
+        try {
+            cipher.init(CryptoCipher.DECRYPT_MODE, key, params);
+        } catch (InvalidKeyException e) {
+            throw new IOException(e);
+        } catch (InvalidAlgorithmParameterException e) {
+            throw new IOException(e);
+        }
     }
 
-    // Clear the input buffer and prepare out buffer
-    inBuffer.clear();
-    outBuffer.flip();
-  }
-
-  /**
-   * Does final of the cipher to end the decrypting stream.
-   *
-   *@throws IOException if an I/O error occurs.
-   */
-  protected void decryptFinal() throws IOException {
-    // Prepare the input buffer and clear the out buffer
-    inBuffer.flip();
-    outBuffer.clear();
-
-    try {
-      cipher.doFinal(inBuffer, outBuffer);
-      finalDone = true;
-    } catch (ShortBufferException e) {
-      throw new IOException(e);
-    } catch (IllegalBlockSizeException e) {
-      throw new IOException(e);
-    } catch( BadPaddingException e) {
-      throw new IOException(e);
+    /**
+     * Decrypts more data by reading the under layer stream. The decrypted data
+     * will be put in the output buffer. If the end of the under stream 
reached,
+     * we will do final of the cipher to finish all the decrypting of data.
+     *
+     * @return The number of decrypted data. -1 if end of the decrypted stream.
+     * @throws IOException if an I/O error occurs.
+     */
+    protected int decryptMore() throws IOException {
+        if (finalDone) {
+            return -1;
+        }
+
+        int n = input.read(inBuffer);
+        if (n < 0) {
+            // The stream is end, finalize the cipher stream
+            decryptFinal();
+
+            // Satisfy the read with the remaining
+            int remaining = outBuffer.remaining();
+            if (remaining > 0) {
+                return remaining;
+            }
+
+            // End of the stream
+            return -1;
+        } else if (n == 0) {
+            // No data is read, but the stream is not end yet
+            return 0;
+        } else {
+            decrypt();
+            return outBuffer.remaining();
+        }
     }
 
-    // Clear the input buffer and prepare out buffer
-    inBuffer.clear();
-    outBuffer.flip();
-  }
-
-  /**
-   * Checks whether the stream is closed.
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  protected void checkStream() throws IOException {
-    if (closed) {
-      throw new IOException("Stream closed");
+    /**
+     * Does the decryption using inBuffer as input and outBuffer as output. 
Upon
+     * return, inBuffer is cleared; the decrypted data starts at
+     * outBuffer.position() and ends at outBuffer.limit().
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void decrypt() throws IOException {
+        // Prepare the input buffer and clear the out buffer
+        inBuffer.flip();
+        outBuffer.clear();
+
+        try {
+            cipher.update(inBuffer, outBuffer);
+        } catch (ShortBufferException e) {
+            throw new IOException(e);
+        }
+
+        // Clear the input buffer and prepare out buffer
+        inBuffer.clear();
+        outBuffer.flip();
     }
-  }
 
-  /** Forcibly free the direct buffers. */
-  protected void freeBuffers() {
-    Utils.freeDirectBuffer(inBuffer);
-    Utils.freeDirectBuffer(outBuffer);
-  }
+    /**
+     * Does final of the cipher to end the decrypting stream.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void decryptFinal() throws IOException {
+        // Prepare the input buffer and clear the out buffer
+        inBuffer.flip();
+        outBuffer.clear();
+
+        try {
+            cipher.doFinal(inBuffer, outBuffer);
+            finalDone = true;
+        } catch (ShortBufferException e) {
+            throw new IOException(e);
+        } catch (IllegalBlockSizeException e) {
+            throw new IOException(e);
+        } catch (BadPaddingException e) {
+            throw new IOException(e);
+        }
+
+        // Clear the input buffer and prepare out buffer
+        inBuffer.clear();
+        outBuffer.flip();
+    }
+
+    /**
+     * Checks whether the stream is closed.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void checkStream() throws IOException {
+        if (closed) {
+            throw new IOException("Stream closed");
+        }
+    }
+
+    /** Forcibly free the direct buffers. */
+    protected void freeBuffers() {
+        Utils.freeDirectBuffer(inBuffer);
+        Utils.freeDirectBuffer(outBuffer);
+    }
 }

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/95a8d486/src/main/java/org/apache/commons/crypto/stream/CryptoOutputStream.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/crypto/stream/CryptoOutputStream.java 
b/src/main/java/org/apache/commons/crypto/stream/CryptoOutputStream.java
index ef91beb..2fd00d2 100644
--- a/src/main/java/org/apache/commons/crypto/stream/CryptoOutputStream.java
+++ b/src/main/java/org/apache/commons/crypto/stream/CryptoOutputStream.java
@@ -43,399 +43,393 @@ import org.apache.commons.crypto.utils.Utils;
 
 /**
  * {@link CryptoOutputStream} encrypts data and writes to the under layer
- * output. It supports any mode of operations such as AES CBC/CTR/GCM mode
- * in concept. It is not thread-safe.
+ * output. It supports any mode of operations such as AES CBC/CTR/GCM mode in
+ * concept. It is not thread-safe.
  */
 
 public class CryptoOutputStream extends OutputStream implements
-    WritableByteChannel {
-  private final byte[] oneByteBuf = new byte[1];
-
-  /** The output.*/
-  Output output;
-
-  /**the CryptoCipher instance*/
-  final CryptoCipher cipher;
-
-  /**The buffer size.*/
-  final int bufferSize;
-
-  /**Crypto key for the cipher.*/
-  final Key key;
-
-  /** the algorithm parameters */
-  final AlgorithmParameterSpec params;
-
-  /** Flag to mark whether the output stream is closed.*/
-  private boolean closed;
-
-  /**
-   * Input data buffer. The data starts at inBuffer.position() and ends at
-   * inBuffer.limit().
-   */
-  ByteBuffer inBuffer;
-
-  /**
-   * Encrypted data buffer. The data starts at outBuffer.position() and ends at
-   * outBuffer.limit().
-   */
-  ByteBuffer outBuffer;
-
-  /**
-   * Constructs a {@link CryptoOutputStream}.
-   *
-   * @param transformation the CipherTransformation instance.
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param out the output stream.
-   * @param key crypto key for the cipher.
-   * @param params the algorithm parameters.
-   * @throws IOException if an I/O error occurs.
-   */
-
-
-  public CryptoOutputStream(
-    CipherTransformation transformation,
-    Properties props,
-    OutputStream out,
-    Key key,
-    AlgorithmParameterSpec params) throws IOException {
-    this(out, Utils.getCipherInstance(transformation, props), 
Utils.getBufferSize(props), key, params);
-
-  }
-
-  /**
-   * Constructs a {@link CryptoOutputStream}.
-   *
-   * @param transformation the CipherTransformation instance.
-   * @param props The <code>Properties</code> class represents a set of
-   *              properties.
-   * @param out the WritableByteChannel instance.
-   * @param key crypto key for the cipher.
-   * @param params the algorithm parameters.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CryptoOutputStream(
-    CipherTransformation transformation,
-    Properties props,
-    WritableByteChannel out,
-    Key key,
-    AlgorithmParameterSpec params) throws IOException {
-    this(out, Utils.getCipherInstance(transformation, props),
-        Utils.getBufferSize(props), key, params);
-
-  }
-
-  /**
-   * Constructs a {@link CryptoOutputStream}.
-   *
-   * @param out the output stream.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param params the algorithm parameters.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CryptoOutputStream(OutputStream out, CryptoCipher cipher, int 
bufferSize,
-                            Key key, AlgorithmParameterSpec params) throws 
IOException {
-    this(new StreamOutput(out, bufferSize), cipher, bufferSize, key, params);
-  }
-
-  /**
-   * Constructs a {@link CryptoOutputStream}.
-   *
-   * @param channel the WritableByteChannel instance.
-   * @param cipher the cipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param params the algorithm parameters.
-   * @throws IOException if an I/O error occurs.
-   */
-  public CryptoOutputStream(WritableByteChannel channel, CryptoCipher cipher,
-                            int bufferSize, Key key, AlgorithmParameterSpec 
params) throws IOException {
-    this(new ChannelOutput(channel), cipher, bufferSize, key, params);
-  }
-
-  /**
-   * Constructs a {@link CryptoOutputStream}.
-   *
-   * @param output the output stream.
-   * @param cipher the CryptoCipher instance.
-   * @param bufferSize the bufferSize.
-   * @param key crypto key for the cipher.
-   * @param params the algorithm parameters.
-   * @throws IOException if an I/O error occurs.
-   */
-  protected CryptoOutputStream(Output output, CryptoCipher cipher, int 
bufferSize,
-                               Key key, AlgorithmParameterSpec params)
-      throws IOException {
-
-    this.output = output;
-    this.bufferSize = Utils.checkBufferSize(cipher, bufferSize);
-    this.cipher = cipher;
-
-    this.key = key;
-    this.params = params;
-
-    if (!(params instanceof IvParameterSpec)) {
-      //other AlgorithmParameterSpec such as GCMParameterSpec is not supported 
now.
-      throw new IOException("Illegal parameters");
+        WritableByteChannel {
+    private final byte[] oneByteBuf = new byte[1];
+
+    /** The output. */
+    Output output;
+
+    /** the CryptoCipher instance */
+    final CryptoCipher cipher;
+
+    /** The buffer size. */
+    final int bufferSize;
+
+    /** Crypto key for the cipher. */
+    final Key key;
+
+    /** the algorithm parameters */
+    final AlgorithmParameterSpec params;
+
+    /** Flag to mark whether the output stream is closed. */
+    private boolean closed;
+
+    /**
+     * Input data buffer. The data starts at inBuffer.position() and ends at
+     * inBuffer.limit().
+     */
+    ByteBuffer inBuffer;
+
+    /**
+     * Encrypted data buffer. The data starts at outBuffer.position() and ends
+     * at outBuffer.limit().
+     */
+    ByteBuffer outBuffer;
+
+    /**
+     * Constructs a {@link CryptoOutputStream}.
+     *
+     * @param transformation the CipherTransformation instance.
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param out the output stream.
+     * @param key crypto key for the cipher.
+     * @param params the algorithm parameters.
+     * @throws IOException if an I/O error occurs.
+     */
+
+    public CryptoOutputStream(CipherTransformation transformation,
+            Properties props, OutputStream out, Key key,
+            AlgorithmParameterSpec params) throws IOException {
+        this(out, Utils.getCipherInstance(transformation, props), Utils
+                .getBufferSize(props), key, params);
+
     }
 
-    inBuffer = ByteBuffer.allocateDirect(this.bufferSize);
-    outBuffer = ByteBuffer.allocateDirect(this.bufferSize +
-        cipher.getTransformation().getAlgorithmBlockSize());
-
-    initCipher();
-  }
-
-  /**
-   * Overrides the {@link java.io.OutputStream#write(byte[])}.
-   * Writes the specified byte to this output stream.
-   *
-   * @param b the data.
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public void write(int b) throws IOException {
-    oneByteBuf[0] = (byte) (b & 0xff);
-    write(oneByteBuf, 0, oneByteBuf.length);
-  }
-
-  /**
-   * Overrides the {@link java.io.OutputStream#write(byte[], int, int)}.
-   * Encryption is buffer based.
-   * If there is enough room in {@link #inBuffer}, then write to this buffer.
-   * If {@link #inBuffer} is full, then do encryption and write data to the
-   * underlying stream.
-   *
-   * @param b the data.
-   * @param off the start offset in the data.
-   * @param len the number of bytes to write.
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public void write(byte[] b, int off, int len) throws IOException {
-    checkStream();
-    if (b == null) {
-      throw new NullPointerException();
-    } else if (off < 0 || len < 0 || off > b.length ||
-        len > b.length - off) {
-      throw new IndexOutOfBoundsException();
+    /**
+     * Constructs a {@link CryptoOutputStream}.
+     *
+     * @param transformation the CipherTransformation instance.
+     * @param props The <code>Properties</code> class represents a set of
+     *        properties.
+     * @param out the WritableByteChannel instance.
+     * @param key crypto key for the cipher.
+     * @param params the algorithm parameters.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CryptoOutputStream(CipherTransformation transformation,
+            Properties props, WritableByteChannel out, Key key,
+            AlgorithmParameterSpec params) throws IOException {
+        this(out, Utils.getCipherInstance(transformation, props), Utils
+                .getBufferSize(props), key, params);
+
     }
 
-    while (len > 0) {
-      final int remaining = inBuffer.remaining();
-      if (len < remaining) {
-        inBuffer.put(b, off, len);
-        len = 0;
-      } else {
-        inBuffer.put(b, off, remaining);
-        off += remaining;
-        len -= remaining;
-        encrypt();
-      }
+    /**
+     * Constructs a {@link CryptoOutputStream}.
+     *
+     * @param out the output stream.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param params the algorithm parameters.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CryptoOutputStream(OutputStream out, CryptoCipher cipher,
+            int bufferSize, Key key, AlgorithmParameterSpec params)
+            throws IOException {
+        this(new StreamOutput(out, bufferSize), cipher, bufferSize, key, 
params);
+    }
+
+    /**
+     * Constructs a {@link CryptoOutputStream}.
+     *
+     * @param channel the WritableByteChannel instance.
+     * @param cipher the cipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param params the algorithm parameters.
+     * @throws IOException if an I/O error occurs.
+     */
+    public CryptoOutputStream(WritableByteChannel channel, CryptoCipher cipher,
+            int bufferSize, Key key, AlgorithmParameterSpec params)
+            throws IOException {
+        this(new ChannelOutput(channel), cipher, bufferSize, key, params);
+    }
+
+    /**
+     * Constructs a {@link CryptoOutputStream}.
+     *
+     * @param output the output stream.
+     * @param cipher the CryptoCipher instance.
+     * @param bufferSize the bufferSize.
+     * @param key crypto key for the cipher.
+     * @param params the algorithm parameters.
+     * @throws IOException if an I/O error occurs.
+     */
+    protected CryptoOutputStream(Output output, CryptoCipher cipher,
+            int bufferSize, Key key, AlgorithmParameterSpec params)
+            throws IOException {
+
+        this.output = output;
+        this.bufferSize = Utils.checkBufferSize(cipher, bufferSize);
+        this.cipher = cipher;
+
+        this.key = key;
+        this.params = params;
+
+        if (!(params instanceof IvParameterSpec)) {
+            // other AlgorithmParameterSpec such as GCMParameterSpec is not
+            // supported now.
+            throw new IOException("Illegal parameters");
+        }
+
+        inBuffer = ByteBuffer.allocateDirect(this.bufferSize);
+        outBuffer = ByteBuffer.allocateDirect(this.bufferSize
+                + cipher.getTransformation().getAlgorithmBlockSize());
+
+        initCipher();
     }
-  }
-
-  /**
-   * Overrides the {@link OutputStream#flush()}.
-   * To flush, we need to encrypt the data in the buffer and write to the
-   * underlying stream, then do the flush.
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public void flush() throws IOException {
-    checkStream();
-    encrypt();
-    output.flush();
-    super.flush();
-  }
-
-  /**
-   * Overrides the {@link OutputStream#close()}.
-   * Closes this output stream and releases any system resources
-   * associated with this stream.
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public void close() throws IOException {
-    if (closed) {
-      return;
+
+    /**
+     * Overrides the {@link java.io.OutputStream#write(byte[])}. Writes the
+     * specified byte to this output stream.
+     *
+     * @param b the data.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public void write(int b) throws IOException {
+        oneByteBuf[0] = (byte) (b & 0xff);
+        write(oneByteBuf, 0, oneByteBuf.length);
     }
 
-    try {
-      encryptFinal();
-      output.close();
-      freeBuffers();
-      cipher.close();
-      super.close();
-    } finally {
-      closed = true;
+    /**
+     * Overrides the {@link java.io.OutputStream#write(byte[], int, int)}.
+     * Encryption is buffer based. If there is enough room in {@link 
#inBuffer},
+     * then write to this buffer. If {@link #inBuffer} is full, then do
+     * encryption and write data to the underlying stream.
+     *
+     * @param b the data.
+     * @param off the start offset in the data.
+     * @param len the number of bytes to write.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public void write(byte[] b, int off, int len) throws IOException {
+        checkStream();
+        if (b == null) {
+            throw new NullPointerException();
+        } else if (off < 0 || len < 0 || off > b.length || len > b.length - 
off) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        while (len > 0) {
+            final int remaining = inBuffer.remaining();
+            if (len < remaining) {
+                inBuffer.put(b, off, len);
+                len = 0;
+            } else {
+                inBuffer.put(b, off, remaining);
+                off += remaining;
+                len -= remaining;
+                encrypt();
+            }
+        }
     }
-  }
-
-  /**
-   * Overrides the {@link Channel#isOpen()}.
-   * Tells whether or not this channel is open.
-   *
-   * @return <tt>true</tt> if, and only if, this channel is open
-   */
-  @Override
-  public boolean isOpen() {
-    return !closed;
-  }
-
-  /**
-   * Overrides the {@link 
java.nio.channels.WritableByteChannel#write(ByteBuffer)}.
-   * Writes a sequence of bytes to this channel from the given buffer.
-   *
-   * @param src The buffer from which bytes are to be retrieved.
-   * @return The number of bytes written, possibly zero.
-   * @throws IOException if an I/O error occurs.
-   */
-  @Override
-  public int write(ByteBuffer src) throws IOException {
-    checkStream();
-    final int len = src.remaining();
-    int remaining = len;
-    while (remaining > 0) {
-      final int space = inBuffer.remaining();
-      if (remaining < space) {
-        inBuffer.put(src);
-        remaining = 0;
-      } else {
-        // to void copy twice, we set the limit to copy directly
-        final int oldLimit = src.limit();
-        final int newLimit = src.position() + space;
-        src.limit(newLimit);
-
-        inBuffer.put(src);
-
-        // restore the old limit
-        src.limit(oldLimit);
-
-        remaining -= space;
+
+    /**
+     * Overrides the {@link OutputStream#flush()}. To flush, we need to encrypt
+     * the data in the buffer and write to the underlying stream, then do the
+     * flush.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public void flush() throws IOException {
+        checkStream();
         encrypt();
-      }
+        output.flush();
+        super.flush();
+    }
+
+    /**
+     * Overrides the {@link OutputStream#close()}. Closes this output stream 
and
+     * releases any system resources associated with this stream.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public void close() throws IOException {
+        if (closed) {
+            return;
+        }
+
+        try {
+            encryptFinal();
+            output.close();
+            freeBuffers();
+            cipher.close();
+            super.close();
+        } finally {
+            closed = true;
+        }
+    }
+
+    /**
+     * Overrides the {@link Channel#isOpen()}. Tells whether or not this 
channel
+     * is open.
+     *
+     * @return <tt>true</tt> if, and only if, this channel is open
+     */
+    @Override
+    public boolean isOpen() {
+        return !closed;
+    }
+
+    /**
+     * Overrides the
+     * {@link java.nio.channels.WritableByteChannel#write(ByteBuffer)}. Writes 
a
+     * sequence of bytes to this channel from the given buffer.
+     *
+     * @param src The buffer from which bytes are to be retrieved.
+     * @return The number of bytes written, possibly zero.
+     * @throws IOException if an I/O error occurs.
+     */
+    @Override
+    public int write(ByteBuffer src) throws IOException {
+        checkStream();
+        final int len = src.remaining();
+        int remaining = len;
+        while (remaining > 0) {
+            final int space = inBuffer.remaining();
+            if (remaining < space) {
+                inBuffer.put(src);
+                remaining = 0;
+            } else {
+                // to void copy twice, we set the limit to copy directly
+                final int oldLimit = src.limit();
+                final int newLimit = src.position() + space;
+                src.limit(newLimit);
+
+                inBuffer.put(src);
+
+                // restore the old limit
+                src.limit(oldLimit);
+
+                remaining -= space;
+                encrypt();
+            }
+        }
+
+        return len;
+    }
+
+    /**
+     * Initializes the cipher.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void initCipher() throws IOException {
+        try {
+            cipher.init(CryptoCipher.ENCRYPT_MODE, key, params);
+        } catch (InvalidKeyException e) {
+            throw new IOException(e);
+        } catch (InvalidAlgorithmParameterException e) {
+            throw new IOException(e);
+        }
+    }
+
+    /**
+     * Does the encryption, input is {@link #inBuffer} and output is
+     * {@link #outBuffer}.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void encrypt() throws IOException {
+
+        inBuffer.flip();
+        outBuffer.clear();
+
+        try {
+            cipher.update(inBuffer, outBuffer);
+        } catch (ShortBufferException e) {
+            throw new IOException(e);
+        }
+
+        inBuffer.clear();
+        outBuffer.flip();
+
+        // write to output
+        output.write(outBuffer);
     }
 
-    return len;
-  }
-
-  /**
-   * Initializes the cipher.
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  protected void initCipher()
-      throws IOException {
-    try {
-      cipher.init(CryptoCipher.ENCRYPT_MODE, key, params);
-    } catch (InvalidKeyException e) {
-      throw new IOException(e);
-    } catch(InvalidAlgorithmParameterException e) {
-      throw new IOException(e);
+    /**
+     * Does final encryption of the last data.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    protected void encryptFinal() throws IOException {
+        inBuffer.flip();
+        outBuffer.clear();
+
+        try {
+            cipher.doFinal(inBuffer, outBuffer);
+        } catch (ShortBufferException e) {
+            throw new IOException(e);
+        } catch (IllegalBlockSizeException e) {
+            throw new IOException(e);
+        } catch (BadPaddingException e) {
+            throw new IOException(e);
+        }
+
+        inBuffer.clear();
+        outBuffer.flip();
+
+        // write to output
+        output.write(outBuffer);
     }
-  }
-
-  /**
-   * Does the encryption, input is {@link #inBuffer} and output is
-   * {@link #outBuffer}.
-   *
-   *@throws IOException if an I/O error occurs.
-   */
-  protected void encrypt() throws IOException {
-
-    inBuffer.flip();
-    outBuffer.clear();
-
-    try {
-      cipher.update(inBuffer, outBuffer);
-    } catch (ShortBufferException e) {
-      throw new IOException(e);
+
+    protected void checkStream() throws IOException {
+        if (closed) {
+            throw new IOException("Stream closed");
+        }
     }
 
-    inBuffer.clear();
-    outBuffer.flip();
-
-    // write to output
-    output.write(outBuffer);
-  }
-
-  /**
-   * Does final encryption of the last data.
-   *
-   * @throws IOException if an I/O error occurs.
-   */
-  protected void encryptFinal() throws IOException {
-    inBuffer.flip();
-    outBuffer.clear();
-
-    try {
-      cipher.doFinal(inBuffer, outBuffer);
-    } catch (ShortBufferException e) {
-      throw new IOException(e);
-    } catch (IllegalBlockSizeException e) {
-      throw new IOException(e);
-    } catch( BadPaddingException e) {
-      throw new IOException(e);
+    /** Forcibly free the direct buffers. */
+    protected void freeBuffers() {
+        Utils.freeDirectBuffer(inBuffer);
+        Utils.freeDirectBuffer(outBuffer);
     }
 
-    inBuffer.clear();
-    outBuffer.flip();
+    /**
+     * Gets the outBuffer.
+     *
+     * @return the outBuffer.
+     */
+    protected ByteBuffer getOutBuffer() {
+        return outBuffer;
+    }
 
-    // write to output
-    output.write(outBuffer);
-  }
+    /**
+     * Gets the internal Cipher.
+     *
+     * @return the cipher instance.
+     */
+    protected CryptoCipher getCipher() {
+        return cipher;
+    }
+
+    /**
+     * Gets the buffer size.
+     *
+     * @return the buffer size.
+     */
+    protected int getBufferSize() {
+        return bufferSize;
+    }
 
-  protected void checkStream() throws IOException {
-    if (closed) {
-      throw new IOException("Stream closed");
+    /**
+     * Gets the inBuffer.
+     *
+     * @return the inBuffer.
+     */
+    protected ByteBuffer getInBuffer() {
+        return inBuffer;
     }
-  }
-
-  /** Forcibly free the direct buffers. */
-  protected void freeBuffers() {
-    Utils.freeDirectBuffer(inBuffer);
-    Utils.freeDirectBuffer(outBuffer);
-  }
-
-  /**
-   * Gets the outBuffer.
-   *
-   * @return the outBuffer.
-   */
-  protected ByteBuffer getOutBuffer() {
-    return outBuffer;
-  }
-
-  /**
-   * Gets the internal Cipher.
-   *
-   * @return the cipher instance.
-   */
-  protected CryptoCipher getCipher() {
-    return cipher;
-  }
-
-  /**
-   * Gets the buffer size.
-   *
-   * @return the buffer size.
-   */
-  protected int getBufferSize() {
-    return bufferSize;
-  }
-
-  /**
-   * Gets the inBuffer.
-   *
-   * @return the inBuffer.
-   */
-  protected ByteBuffer getInBuffer() {
-    return inBuffer;
-  }
 }

Reply via email to