You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by xu...@apache.org on 2016/04/22 07:18:32 UTC

[4/8] commons-crypto git commit: CRYPTO-7: Rename source code in Chimera to Apache name space

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/stream/input/ChannelInput.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/stream/input/ChannelInput.java b/src/main/java/org/apache/commons/crypto/stream/input/ChannelInput.java
new file mode 100644
index 0000000..ee24a0c
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/stream/input/ChannelInput.java
@@ -0,0 +1,165 @@
+/**
+ * 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.commons.crypto.stream.input;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+
+/**
+ * The ChannelInput class takes a <code>ReadableByteChannel</code> object and
+ * wraps it as <code>Input</code> object acceptable by <code>CryptoInputStream</code>.
+ */
+public class ChannelInput implements Input {
+  private static final int SKIP_BUFFER_SIZE = 2048;
+
+  private ByteBuffer buf;
+  private ReadableByteChannel channel;
+
+  /**
+   * Constructs the {@link org.apache.commons.crypto.stream.input.ChannelInput}.
+   *
+   * @param channel the ReadableByteChannel object.
+   */
+  public ChannelInput(
+      ReadableByteChannel channel) {
+    this.channel = channel;
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.input.Input#read(ByteBuffer)}.
+   * Reads a sequence of bytes from input into the given buffer.
+   *
+   * @param  dst The buffer into which bytes are to be transferred.
+   * @return the total number of bytes read into the buffer, or
+   *          <code>-1</code> if there is no more data because the end of
+   *          the stream has been reached.
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public int read(ByteBuffer dst) throws IOException {
+    return channel.read(dst);
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.input.Input#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 {
+    long remaining = n;
+    int nr;
+
+    if (n <= 0) {
+      return 0;
+    }
+
+    int size = (int)Math.min(SKIP_BUFFER_SIZE, remaining);
+    ByteBuffer skipBuffer = getSkipBuf();
+    while (remaining > 0) {
+      skipBuffer.clear();
+      skipBuffer.limit((int)Math.min(size, remaining));
+      nr = read(skipBuffer);
+      if (nr < 0) {
+        break;
+      }
+      remaining -= nr;
+    }
+
+    return n - remaining;
+  }
+
+  /**
+   * Overrides the {@link Input#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. The next invocation
+   * might be the same thread or another thread.  A single read or skip of this
+   * many bytes will not block, but may read or skip fewer bytes.
+   *
+   * @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 {
+    return 0;
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.input.Input#read(long, byte[], int, int)}.
+   * Reads up to <code>len</code> bytes of data from the input stream into
+   * an array of bytes.  An attempt is made to read as many as
+   * <code>len</code> bytes, but a smaller number may be read.
+   * The number of bytes actually read is returned as an integer.
+   *
+   * @param position the given position within a stream.
+   * @param buffer the buffer into which the data is read.
+   * @param offset the start offset in array buffer.
+   * @param length the maximum number of bytes to read.
+   * @return the total number of bytes read into the buffer, or
+   *          <code>-1</code> if there is no more data because the end of
+   *          the stream has been reached.
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public int read(long position, byte[] buffer, int offset, int length)
+      throws IOException {
+    throw new UnsupportedOperationException(
+        "Positioned read is not supported by this implementation");
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.input.Input#seek(long)}.
+   * Seeks to the given offset from the start of the stream.
+   * The next read() will be from that location.
+   *
+   * @param position the offset from the start of the stream.
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public void seek(long position) throws IOException {
+    throw new UnsupportedOperationException(
+        "Seek is not supported by this implementation");
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.input.Input#seek(long)}.
+   * Closes this input and releases any system resources associated
+   * with the under layer input.
+   *
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public void close() throws IOException {
+    channel.close();
+  }
+
+  private ByteBuffer getSkipBuf() {
+    if (buf == null) {
+      buf = ByteBuffer.allocate(SKIP_BUFFER_SIZE);
+    }
+    return buf;
+  }
+}

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/stream/input/Input.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/stream/input/Input.java b/src/main/java/org/apache/commons/crypto/stream/input/Input.java
new file mode 100644
index 0000000..a63c6ca
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/stream/input/Input.java
@@ -0,0 +1,133 @@
+/**
+ * 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.commons.crypto.stream.input;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * The Input interface abstract the input source of <code>CryptoInputStream</code> so that
+ * different implementation of input can be used. The implementation Input interface will usually
+ * wraps an input mechanism such as <code>InputStream</code> or <code>ReadableByteChannel</code>.
+ */
+public interface Input {
+  /**
+   * Reads a sequence of bytes from input into the given buffer.
+   *
+   * <p> An attempt is made to read up to <i>r</i> bytes from the input,
+   * where <i>r</i> is the number of bytes remaining in the buffer, that is,
+   * <tt>dst.remaining()</tt>, at the moment this method is invoked.
+   *
+   * <p> Suppose that a byte sequence of length <i>n</i> is read, where
+   * <tt>0</tt>&nbsp;<tt>&lt;=</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+   * This byte sequence will be transferred into the buffer so that the first
+   * byte in the sequence is at index <i>p</i> and the last byte is at index
+   * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>&nbsp;<tt>-</tt>&nbsp;<tt>1</tt>,
+   * where <i>p</i> is the buffer's position at the moment this method is
+   * invoked.  Upon return the buffer's position will be equal to
+   * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
+   *
+   * @param  dst
+   *         The buffer into which bytes are to be transferred.
+   * @return the total number of bytes read into the buffer, or
+   *         <code>-1</code> if there is no more data because the end of
+   *         the stream has been reached.
+   * @throws  IOException
+   *          If some other I/O error occurs.
+   */
+  int read(ByteBuffer dst) throws IOException;
+
+  /**
+   * Skips over and discards <code>n</code> bytes of data from this input
+   * The <code>skip</code> method may, for a variety of reasons, end
+   * up skipping over some smaller number of bytes, possibly <code>0</code>.
+   * This may result from any of a number of conditions; reaching end of file
+   * before <code>n</code> bytes have been skipped is only one possibility.
+   * The actual number of bytes skipped is returned.  If <code>n</code> is
+   * negative, no bytes are skipped.
+   *
+   * <p> The <code>skip</code> method of this class creates a
+   * byte array and then repeatedly reads into it until <code>n</code> bytes
+   * have been read or the end of the stream has been reached. Subclasses are
+   * encouraged to provide a more efficient implementation of this method.
+   * For instance, the implementation may depend on the ability to seek.
+   *
+   * @param      n the number of bytes to be skipped.
+   * @return     the actual number of bytes skipped.
+   * @exception  IOException  if the stream does not support seek,
+   *                          or if some other I/O error occurs.
+   */
+  long skip(long n) throws IOException;
+
+  /**
+   * Returns an estimate of the number of bytes that can be read (or
+   * skipped over) from this input without blocking by the next
+   * invocation of a method for this input stream. The next invocation
+   * might be the same thread or another thread.  A single read or skip of this
+   * many bytes will not block, but may read or skip fewer bytes.
+   *
+   * <p> It is never correct to use the return value of this method to allocate
+   * a buffer intended to hold all data in this 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.
+   * @exception  IOException if an I/O error occurs.
+   */
+  int available() throws IOException;
+
+  /**
+   * Reads up to the specified number of bytes from a given position within a
+   * stream and return the number of bytes read.
+   * This does not change the current offset of the stream and is thread-safe.
+   * 
+   * An implementation may not support positioned read. If the implementation
+   * doesn't support positioned read, it throws UnsupportedOperationException.
+   *
+   * @param position the given position within a stream.
+   * @param buffer the buffer into which the data is read.
+   * @param offset the start offset in array buffer.
+   * @param length the maximum number of bytes to read.
+   * @return the total number of bytes read into the buffer, or
+   *         <code>-1</code> if there is no more data because the end of
+   *         the stream has been reached.
+   * @throws IOException if an I/O error occurs.
+   */
+  int read(long position, byte[] buffer, int offset, int length)
+      throws IOException;
+
+  /**
+   * Seeks to the given offset from the start of the stream.
+   * The next read() will be from that location.
+   * 
+   * An implementation may not support seek. If the implementation 
+   * doesn't support seek, it throws UnsupportedOperationException.
+   *
+   * @param position the offset from the start of the stream.
+   * @throws IOException if an I/O error occurs.
+   */
+  void seek(long position) throws IOException;
+
+  /**
+   * Closes this input and releases any system resources associated
+   * with the under layer input.
+   *
+   * @exception  IOException  if an I/O error occurs.
+   */
+  void close() throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/stream/input/StreamInput.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/stream/input/StreamInput.java b/src/main/java/org/apache/commons/crypto/stream/input/StreamInput.java
new file mode 100644
index 0000000..ac3739b
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/stream/input/StreamInput.java
@@ -0,0 +1,164 @@
+/**
+ * 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.commons.crypto.stream.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * The StreamInput class takes a <code>InputStream</code> object and
+ * wraps it as <code>Input</code> object acceptable by <code>CryptoInputStream</code>.
+ */
+public class StreamInput implements Input {
+  private byte[] buf;
+  private int bufferSize;
+  InputStream in;
+
+  /**
+   * Constructs a {@link org.apache.commons.crypto.stream.input.StreamInput}.
+   *
+   * @param inputStream the inputstream object.
+   * @param bufferSize the buffersize.
+   */
+  public StreamInput(InputStream inputStream, int bufferSize) {
+    this.in = inputStream;
+    this.bufferSize = bufferSize;
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.input.Input#read(ByteBuffer)}.
+   * Reads a sequence of bytes from input into the given buffer.
+   *
+   * @param  dst
+   *         The buffer into which bytes are to be transferred.
+   *
+   * @return the total number of bytes read into the buffer, or
+   *          <code>-1</code> if there is no more data because the end of
+   *          the stream has been reached.
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public int read(ByteBuffer dst) throws IOException {
+    int remaining = dst.remaining();
+    final byte[] tmp = getBuf();
+    int read = 0;
+    while (remaining > 0) {
+      final int n = in.read(tmp, 0, Math.min(remaining, bufferSize));
+      if (n == -1) {
+        if (read == 0) {
+          read = -1;
+        }
+        break;
+      } else if (n > 0) {
+        dst.put(tmp, 0, n);
+        read += n;
+        remaining -= n;
+      }
+    }
+    return read;
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.input.Input#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 {
+    return in.skip(n);
+  }
+
+  /**
+   * Overrides the {@link Input#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. The next invocation
+   * might be the same thread or another thread.  A single read or skip of this
+   * many bytes will not block, but may read or skip fewer bytes.
+   *
+   * @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 {
+    return in.available();
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.input.Input#read(long, byte[], int, int)}.
+   * Reads up to <code>len</code> bytes of data from the input stream into
+   * an array of bytes.  An attempt is made to read as many as
+   * <code>len</code> bytes, but a smaller number may be read.
+   * The number of bytes actually read is returned as an integer.
+   *
+   * @param position the given position within a stream.
+   * @param buffer the buffer into which the data is read.
+   * @param offset the start offset in array buffer.
+   * @param length the maximum number of bytes to read.
+   * @return the total number of bytes read into the buffer, or
+   *          <code>-1</code> if there is no more data because the end of
+   *          the stream has been reached.
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public int read(long position, byte[] buffer, int offset, int length)
+      throws IOException {
+    throw new UnsupportedOperationException(
+        "Positioned read is not supported by this implementation");
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.input.Input#seek(long)}.
+   * Seeks to the given offset from the start of the stream.
+   * The next read() will be from that location.
+   *
+   * @param position the offset from the start of the stream.
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public void seek(long position) throws IOException {
+    throw new UnsupportedOperationException(
+        "Seek is not supported by this implementation");
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.input.Input#seek(long)}.
+   * Closes this input and releases any system resources associated
+   * with the under layer input.
+   *
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public void close() throws IOException {
+    in.close();
+  }
+
+  private byte[] getBuf() {
+    if (buf == null) {
+      buf = new byte[bufferSize];
+    }
+    return buf;
+  }
+}

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/stream/output/ChannelOutput.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/stream/output/ChannelOutput.java b/src/main/java/org/apache/commons/crypto/stream/output/ChannelOutput.java
new file mode 100644
index 0000000..bae82a8
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/stream/output/ChannelOutput.java
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.crypto.stream.output;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+
+/**
+ * The ChannelOutput class takes a <code>WritableByteChannel</code> object and wraps it as 
+ * <code>Output</code> object acceptable by <code>CryptoOutputStream</code> as the output target.
+ */
+public class ChannelOutput implements Output {
+
+  private WritableByteChannel channel;
+
+  /**
+   * Constructs a {@link org.apache.commons.crypto.stream.output.ChannelOutput}.
+   *
+   * @param channel the WritableByteChannel object.
+   */
+  public ChannelOutput(WritableByteChannel channel) {
+    this.channel = channel;
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.output.Output#write(ByteBuffer)}.
+   * Writes a sequence of bytes to this output 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 {
+    return channel.write(src);
+  }
+
+  /**
+   * Overrides the {@link Output#flush()}.
+   * Flushes this output and forces any buffered output bytes
+   * to be written out if the under layer output method support.
+   *
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public void flush() throws IOException {
+  }
+
+  /**
+   * Overrides the {@link Output#close()}.
+   * Closes this output and releases any system resources associated
+   * with the under layer output.
+   *
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public void close() throws IOException {
+    channel.close();
+  }
+}

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/stream/output/Output.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/stream/output/Output.java b/src/main/java/org/apache/commons/crypto/stream/output/Output.java
new file mode 100644
index 0000000..903fcea
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/stream/output/Output.java
@@ -0,0 +1,76 @@
+/**
+ * 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.commons.crypto.stream.output;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * The Output interface abstract the output target of <code>CryptoOutputStream</code> so that
+ * different implementation of output can be used. The implementation Output interface will usually
+ * wraps an output mechanism such as <code>OutputStream</code> or <code>WritableByteChannel</code>.
+ */
+public interface Output {
+
+  /**
+   * Writes a sequence of bytes to this output from the given buffer.
+   *
+   * <p> An attempt is made to write up to <i>r</i> bytes to the channel,
+   * where <i>r</i> is the number of bytes remaining in the buffer, that is,
+   * <tt>src.remaining()</tt>, at the moment this method is invoked.
+   *
+   * <p> Suppose that a byte sequence of length <i>n</i> is written, where
+   * <tt>0</tt>&nbsp;<tt>&lt;=</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
+   * This byte sequence will be transferred from the buffer starting at index
+   * <i>p</i>, where <i>p</i> is the buffer's position at the moment this
+   * method is invoked; the index of the last byte written will be
+   * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>&nbsp;<tt>-</tt>&nbsp;<tt>1</tt>.
+   * Upon return the buffer's position will be equal to
+   * <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
+   *
+   * @param  src
+   *         The buffer from which bytes are to be retrieved.
+   *
+   * @return The number of bytes written, possibly zero.
+   *
+   * @throws  IOException
+   *          If some other I/O error occurs.
+   */
+  int write(ByteBuffer src) throws IOException;
+  
+  /**
+   * Flushes this output and forces any buffered output bytes
+   * to be written out if the under layer output method support.
+   * The general contract of <code>flush</code> is
+   * that calling it is an indication that, if any bytes previously
+   * written have been buffered by the implementation of the output
+   * stream, such bytes should immediately be written to their
+   * intended destination.
+   *
+   * @throws IOException  if an I/O error occurs.
+   */
+  void flush() throws IOException;
+  
+  /**
+   * Closes this output and releases any system resources associated
+   * with the under layer output.
+   *
+   * @throws IOException  if an I/O error occurs.
+   */
+  void close() throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/stream/output/StreamOutput.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/stream/output/StreamOutput.java b/src/main/java/org/apache/commons/crypto/stream/output/StreamOutput.java
new file mode 100644
index 0000000..beead7f
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/stream/output/StreamOutput.java
@@ -0,0 +1,101 @@
+/**
+ * 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.commons.crypto.stream.output;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * The StreamOutput class takes a <code>OutputStream</code> object and wraps it as 
+ * <code>Output</code> object acceptable by <code>CryptoOutputStream</code> as the output target.
+ */
+public class StreamOutput implements Output {
+  private byte[] buf;
+  private int bufferSize;
+  protected OutputStream out;
+
+  /**
+   * Constructs a {@link org.apache.commons.crypto.stream.output.StreamOutput}.
+   *
+   * @param out the OutputStream object.
+   * @param bufferSize the buffersize.
+   */
+  public StreamOutput(OutputStream out, int bufferSize) {
+    this.out = out;
+    this.bufferSize = bufferSize;
+  }
+
+  /**
+   * Overrides the {@link org.apache.commons.crypto.stream.output.Output#write(ByteBuffer)}.
+   * Writes a sequence of bytes to this output 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 {
+    final int len = src.remaining();
+    final byte[] buf = getBuf();
+    
+    int remaining = len;
+    while(remaining > 0) {
+      final int n = Math.min(remaining, bufferSize);
+      src.get(buf, 0, n);
+      out.write(buf, 0, n);
+      remaining = src.remaining();
+    }
+    
+    return len;
+  }
+
+  /**
+   * Overrides the {@link Output#flush()}.
+   * Flushes this output and forces any buffered output bytes
+   * to be written out if the under layer output method support.
+   *
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public void flush() throws IOException {
+    out.flush();
+  }
+
+  /**
+   * Overrides the {@link Output#close()}.
+   * Closes this output and releases any system resources associated
+   * with the under layer output.
+   *
+   * @throws IOException if an I/O error occurs.
+   */
+  @Override
+  public void close() throws IOException {
+    out.close();
+  }
+  
+  private byte[] getBuf() {
+    if (buf == null) {
+      buf = new byte[bufferSize];
+    }
+    return buf;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/utils/IOUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/utils/IOUtils.java b/src/main/java/org/apache/commons/crypto/utils/IOUtils.java
new file mode 100644
index 0000000..58a20a5
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/utils/IOUtils.java
@@ -0,0 +1,96 @@
+/**
+ * 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.commons.crypto.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.crypto.stream.input.Input;
+import org.apache.commons.logging.Log;
+
+/**
+ * General utility methods for working with IO.
+ */
+public class IOUtils {
+
+  /**
+   * Does the readFully based on the Input read.
+   *
+   * @param in the input stream of bytes.
+   * @param buf the buffer to be read.
+   * @param off the start offset in array buffer.
+   * @param len the maximum number of bytes to read.
+   * @throws IOException if an I/O error occurs.
+   */
+  public static void readFully(InputStream in, byte buf[],
+      int off, int len) throws IOException {
+    int toRead = len;
+    while (toRead > 0) {
+      int ret = in.read(buf, off, toRead);
+      if (ret < 0) {
+        throw new IOException( "Premature EOF from inputStream");
+      }
+      toRead -= ret;
+      off += ret;
+    }
+  }
+
+  /**
+   * Does the readFully based on Input's positioned read.
+   * This does not change the current offset of the stream and is thread-safe.
+   *
+   * @param in the input source.
+   * @param position the given position.
+   * @param buffer the buffer to be read.
+   * @param length the maximum number of bytes to read.
+   * @param offset the start offset in array buffer.
+   * @throws IOException if an I/O error occurs.
+   */
+  public static void readFully(Input in, long position,
+      byte[] buffer, int offset, int length) throws IOException {
+    int nread = 0;
+    while (nread < length) {
+      int nbytes = in.read(position+nread, buffer, offset+nread, length-nread);
+      if (nbytes < 0) {
+        throw new IOException("End of stream reached before reading fully.");
+      }
+      nread += nbytes;
+    }
+  }
+
+  /**
+   * Closes the Closeable objects and <b>ignore</b> any {@link IOException} or
+   * null pointers. Must only be used for cleanup in exception handlers.
+   *
+   * @param log the log to record problems to at debug level. Can be null.
+   * @param closeables the objects to close.
+   */
+  public static void cleanup(Log log, java.io.Closeable... closeables) {
+    for (java.io.Closeable c : closeables) {
+      if (c != null) {
+        try {
+          c.close();
+        } catch(Throwable e) {
+          if (log != null && log.isDebugEnabled()) {
+            log.debug("Exception in closing " + c, e);
+          }
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/utils/NativeCodeLoader.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/utils/NativeCodeLoader.java b/src/main/java/org/apache/commons/crypto/utils/NativeCodeLoader.java
new file mode 100644
index 0000000..475fdda
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/utils/NativeCodeLoader.java
@@ -0,0 +1,279 @@
+/**
+ * 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.commons.crypto.utils;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+/**
+ * A helper to load the native code i.e. libchimera.so.
+ * This handles the fallback to either the bundled libchimera-Linux-i386-32.so
+ * or the default java implementations where appropriate.
+ */
+public class NativeCodeLoader {
+
+  private static final Log LOG =
+    LogFactory.getLog(NativeCodeLoader.class);
+  
+  private static boolean nativeCodeLoaded = false;
+  
+  static {
+    // Try to load native library and set fallback flag appropriately
+    if(LOG.isDebugEnabled()) {
+      LOG.debug("Trying to load the custom-built native-chimera library...");
+    }
+
+    try {
+      File nativeLibFile = findNativeLibrary();
+      if (nativeLibFile != null) {
+        // Load extracted or specified native library.
+        System.load(nativeLibFile.getAbsolutePath());
+      } else {
+        // Load preinstalled library (in the path -Djava.library.path)
+        System.loadLibrary("chimera");
+      }
+      LOG.debug("Loaded the native library");
+      nativeCodeLoaded = true;
+    } catch (Throwable t) {
+      // Ignore failure to load
+      if(LOG.isDebugEnabled()) {
+        LOG.debug("Failed to load native library with error: " + t);
+        LOG.debug("java.library.path=" +
+            System.getProperty("java.library.path"));
+      }
+    }
+
+    if (!nativeCodeLoaded) {
+      LOG.warn("Unable to load native library for the platform... " +
+               "using builtin-java classes where applicable");
+    }
+  }
+
+  static File findNativeLibrary() {
+    // Try to load the library in chimera.lib.path */
+    String nativeLibraryPath = Utils
+        .getLibPath();
+    String nativeLibraryName = Utils
+        .getLibName();
+
+    // Resolve the library file name with a suffix (e.g., dll, .so, etc.)
+    if (nativeLibraryName == null)
+      nativeLibraryName = System.mapLibraryName("chimera");
+
+    if (nativeLibraryPath != null) {
+      File nativeLib = new File(nativeLibraryPath,
+          nativeLibraryName);
+      if (nativeLib.exists())
+        return nativeLib;
+    }
+
+    // Load an OS-dependent native library inside a jar file
+    nativeLibraryPath = "/org/apache/commons/crypto/native/"
+        + OSInfo.getNativeLibFolderPathForCurrentOS();
+    boolean hasNativeLib = hasResource(nativeLibraryPath + "/"
+        + nativeLibraryName);
+    if(!hasNativeLib) {
+      if (OSInfo.getOSName().equals("Mac")) {
+        // Fix for openjdk7 for Mac
+        String altName = "libchimera.jnilib";
+        if (hasResource(nativeLibraryPath + "/" + altName)) {
+          nativeLibraryName = altName;
+          hasNativeLib = true;
+        }
+      }
+    }
+
+    if (!hasNativeLib) {
+      String errorMessage = String.format(
+          "no native library is found for os.name=%s and os.arch=%s",
+          OSInfo.getOSName(), OSInfo.getArchName());
+      throw new RuntimeException(errorMessage);
+    }
+
+    // Temporary folder for the native lib. Use the value of
+    // chimera.tempdir or java.io.tmpdir
+    String tempFolder = new File(Utils.getTmpDir())
+        .getAbsolutePath();
+
+    // Extract and load a native library inside the jar file
+    return extractLibraryFile(nativeLibraryPath,
+        nativeLibraryName, tempFolder);
+  }
+
+  /**
+   * Extracts the specified library file to the target folder.
+   * 
+   * @param libFolderForCurrentOS the library in chimera.lib.path.
+   * @param libraryFileName the library name.
+   * @param targetFolder Target folder for the native lib. Use the value of
+   *                     chimera.tempdir or java.io.tmpdir.
+   * @return the library file.
+   */
+  private static File extractLibraryFile(String libFolderForCurrentOS,
+      String libraryFileName, String targetFolder) {
+    String nativeLibraryFilePath = libFolderForCurrentOS + "/"
+        + libraryFileName;
+
+    // Attach UUID to the native library file to ensure multiple class loaders
+    // can read the libchimera multiple times.
+    String uuid = UUID.randomUUID().toString();
+    String extractedLibFileName = String.format("chimera-%s-%s-%s", getVersion(), uuid,
+        libraryFileName);
+    File extractedLibFile = new File(targetFolder, extractedLibFileName);
+
+    InputStream reader = null;
+    try {
+      // Extract a native library file into the target directory
+      reader = NativeCodeLoader.class.getResourceAsStream(nativeLibraryFilePath);
+      FileOutputStream writer = new FileOutputStream(extractedLibFile);
+      try {
+        byte[] buffer = new byte[8192];
+        int bytesRead;
+        while ((bytesRead = reader.read(buffer)) != -1) {
+          writer.write(buffer, 0, bytesRead);
+        }
+      } finally {
+        // Delete the extracted lib file on JVM exit.
+        extractedLibFile.deleteOnExit();
+
+        if (writer != null){
+          writer.close();
+        }
+
+        if (reader != null) {
+          reader.close();
+          reader = null;
+        }
+      }
+
+      // Set executable (x) flag to enable Java to load the native library
+      if (!extractedLibFile.setReadable(true) || !extractedLibFile.setExecutable(true)
+          || !extractedLibFile.setWritable(true, true)) {
+        throw new RuntimeException("Invalid path for library path");
+      }
+
+      // Check whether the contents are properly copied from the resource folder
+      {
+        InputStream nativeIn = null;
+        InputStream extractedLibIn = null;
+        try {
+          nativeIn =
+              NativeCodeLoader.class.getResourceAsStream(nativeLibraryFilePath);
+          extractedLibIn = new FileInputStream(extractedLibFile);
+          if (!contentsEquals(nativeIn, extractedLibIn))
+            throw new RuntimeException(String.format(
+                    "Failed to write a native library file at %s",
+                    extractedLibFile));
+        } finally {
+          if (nativeIn != null)
+            nativeIn.close();
+          if (extractedLibIn != null)
+            extractedLibIn.close();
+        }
+      }
+
+      return new File(targetFolder, extractedLibFileName);
+    } catch (IOException e) {
+      e.printStackTrace(System.err);
+      return null;
+    } finally{
+      if(reader != null){
+        try {
+          reader.close();
+        } catch (IOException e) {
+          e.printStackTrace();
+        }
+      }
+    }
+  }
+
+  /**
+   * Gets the version by reading pom.properties embedded in jar.
+   * This version data is used as a suffix of a dll file extracted from the
+   * jar.
+   * 
+   * @return the version string
+   */
+  public static String getVersion() {
+    URL versionFile = NativeCodeLoader.class
+        .getResource("/META-INF/maven/org.apache.commons.crypto/chimera/pom.properties");
+    if (versionFile == null)
+      versionFile = NativeCodeLoader.class
+          .getResource("/org/apache/commons/crypto/VERSION");
+
+    String version = "unknown";
+    try {
+      if (versionFile != null) {
+        Properties versionData = new Properties();
+        versionData.load(versionFile.openStream());
+        version = versionData.getProperty("version", version);
+        if (version.equals("unknown"))
+          version = versionData.getProperty("VERSION", version);
+        version = version.trim().replaceAll("[^0-9M\\.]", "");
+      }
+    } catch (IOException e) {
+      System.err.println(e);
+    }
+    return version;
+  }
+
+  private static boolean contentsEquals(InputStream in1, InputStream in2)
+      throws IOException {
+    if (!(in1 instanceof BufferedInputStream)) {
+      in1 = new BufferedInputStream(in1);
+    }
+    if (!(in2 instanceof BufferedInputStream)) {
+      in2 = new BufferedInputStream(in2);
+    }
+
+    int ch = in1.read();
+    while (ch != -1) {
+      int ch2 = in2.read();
+      if (ch != ch2)
+        return false;
+      ch = in1.read();
+    }
+    int ch2 = in2.read();
+    return ch2 == -1;
+  }
+
+  private static boolean hasResource(String path) {
+    return NativeCodeLoader.class.getResource(path) != null;
+  }
+
+  /**
+   * Checks whether native code is loaded for this platform.
+   * 
+   * @return <code>true</code> if native is loaded, 
+   *         else <code>false</code>.
+   */
+  public static boolean isNativeCodeLoaded() {
+    return nativeCodeLoaded;
+  }
+}

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/utils/OSInfo.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/utils/OSInfo.java b/src/main/java/org/apache/commons/crypto/utils/OSInfo.java
new file mode 100644
index 0000000..67f7d56
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/utils/OSInfo.java
@@ -0,0 +1,190 @@
+/**
+ * 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.commons.crypto.utils;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Locale;
+
+/**
+ * Provides OS name and architecture name.
+ */
+public class OSInfo {
+  private static HashMap<String, String> archMapping = new HashMap<String, String>();
+
+  /**
+   * The constant string represents for X86 architecture, the value is: {@value #X86}.*/
+  public static final String X86 = "x86";
+
+  /**
+   * The constant string represents for X86_64 architecture, the value is:{@value #X86_64}.*/
+  public static final String X86_64 = "x86_64";
+
+  /**
+   * The constant string represents for IA64_32 architecture, the value is:{@value #IA64_32}.*/
+  public static final String IA64_32 = "ia64_32";
+
+  /**
+   * The constant string represents for IA64 architecture, the value is:{@value #IA64}.*/
+  public static final String IA64 = "ia64";
+
+  /**
+   * The constant string represents for PPC architecture, the value is:{@value #PPC}.*/
+  public static final String PPC = "ppc";
+
+  /**
+   * The constant string represents for PPC64 architecture, the value is:{@value #PPC64}.*/
+  public static final String PPC64 = "ppc64";
+
+  static {
+    // x86 mappings
+    archMapping.put(X86, X86);
+    archMapping.put("i386", X86);
+    archMapping.put("i486", X86);
+    archMapping.put("i586", X86);
+    archMapping.put("i686", X86);
+    archMapping.put("pentium", X86);
+
+    // x86_64 mappings
+    archMapping.put(X86_64, X86_64);
+    archMapping.put("amd64", X86_64);
+    archMapping.put("em64t", X86_64);
+    archMapping.put("universal", X86_64); // Needed for openjdk7 in Mac
+
+    // Itenium 64-bit mappings
+    archMapping.put(IA64, IA64);
+    archMapping.put("ia64w", IA64);
+
+    // Itenium 32-bit mappings, usually an HP-UX construct
+    archMapping.put(IA64_32, IA64_32);
+    archMapping.put("ia64n", IA64_32);
+
+    // PowerPC mappings
+    archMapping.put(PPC, PPC);
+    archMapping.put("power", PPC);
+    archMapping.put("powerpc", PPC);
+    archMapping.put("power_pc", PPC);
+    archMapping.put("power_rs", PPC);
+
+    // TODO: PowerPC 64bit mappings
+    archMapping.put(PPC64, PPC64);
+    archMapping.put("power64", PPC64);
+    archMapping.put("powerpc64", PPC64);
+    archMapping.put("power_pc64", PPC64);
+    archMapping.put("power_rs64", PPC64);
+  }
+
+  public static void main(String[] args) {
+    if (args.length >= 1) {
+      if ("--os".equals(args[0])) {
+        System.out.print(getOSName());
+        return;
+      } else if ("--arch".equals(args[0])) {
+        System.out.print(getArchName());
+        return;
+      }
+    }
+
+    System.out.print(getNativeLibFolderPathForCurrentOS());
+  }
+
+  /**
+   * Gets the native lib folder.
+   *
+   * @return the current OS's native lib folder.
+   */
+  public static String getNativeLibFolderPathForCurrentOS() {
+    return getOSName() + "/" + getArchName();
+  }
+
+  /**
+   * Gets the OS name.
+   *
+   * @return the OS name.
+   */
+  public static String getOSName() {
+    return translateOSNameToFolderName(System.getProperty("os.name"));
+  }
+
+  /**
+   * Gets the architecture name.
+   *
+   * @return the architecture name.
+   */
+  public static String getArchName() {
+    // if running Linux on ARM, need to determine ABI of JVM
+    String osArch = System.getProperty("os.arch");
+    if (osArch.startsWith("arm")
+        && System.getProperty("os.name").contains("Linux")) {
+      String javaHome = System.getProperty("java.home");
+      try {
+        // determine if first JVM found uses ARM hard-float ABI
+        String[] cmdarray = {
+            "/bin/sh",
+            "-c",
+            "find '" + javaHome
+                + "' -name 'libjvm.so' | head -1 | xargs readelf -A | "
+                + "grep 'Tag_ABI_VFP_args: VFP registers'" };
+        int exitCode = Runtime.getRuntime().exec(cmdarray).waitFor();
+        if (exitCode == 0)
+          return "armhf";
+      } catch (IOException e) {
+        // ignored: fall back to "arm" arch (soft-float ABI)
+      } catch (InterruptedException e) {
+        // ignored: fall back to "arm" arch (soft-float ABI)
+      }
+    } else {
+      String lc = osArch.toLowerCase(Locale.US);
+      if (archMapping.containsKey(lc))
+        return archMapping.get(lc);
+    }
+    return translateArchNameToFolderName(osArch);
+  }
+
+  /**
+   * Translates the OS name to folder name.
+   *
+   * @param osName the OS name.
+   * @return the folder name.
+   */
+  static String translateOSNameToFolderName(String osName) {
+    if (osName.contains("Windows")) {
+      return "Windows";
+    } else if (osName.contains("Mac")) {
+      return "Mac";
+    } else if (osName.contains("Linux")) {
+      return "Linux";
+    } else if (osName.contains("AIX")) {
+      return "AIX";
+    }
+
+    else {
+      return osName.replaceAll("\\W", "");
+    }
+  }
+
+  /**
+   * Translates the architecture name to folder name.
+   *
+   * @param archName the architecture name.
+   * @return the folder name.
+   */
+  static String translateArchNameToFolderName(String archName) {
+    return archName.replaceAll("\\W", "");
+  }
+}

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/utils/ReflectionUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/utils/ReflectionUtils.java b/src/main/java/org/apache/commons/crypto/utils/ReflectionUtils.java
new file mode 100644
index 0000000..9ffd7e8
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/utils/ReflectionUtils.java
@@ -0,0 +1,204 @@
+/**
+ * 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.commons.crypto.utils;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.apache.commons.crypto.cipher.Cipher;
+
+/**
+ * General utility methods for working with reflection.
+ */
+public class ReflectionUtils {
+
+  private static final Map<ClassLoader, Map<String, WeakReference<Class<?>>>>
+    CACHE_CLASSES = new WeakHashMap<ClassLoader, Map<String, WeakReference<Class<?>>>>();
+
+  private static ClassLoader classLoader;
+  static {
+    classLoader = Thread.currentThread().getContextClassLoader();
+    if (classLoader == null) {
+      classLoader = Cipher.class.getClassLoader();
+    }
+  }
+
+  /**
+   * Sentinel value to store negative cache results in {@link #CACHE_CLASSES}.
+   */
+  private static final Class<?> NEGATIVE_CACHE_SENTINEL =
+    NegativeCacheSentinel.class;
+
+  /**
+   * A unique class which is used as a sentinel value in the caching
+   * for getClassByName. {@link Cipher#getClassByNameOrNull(String)}.
+   */
+  private static abstract class NegativeCacheSentinel {}
+
+  /**
+   * Uses the constructor represented by this {@code Constructor} object to
+   * create and initialize a new instance of the constructor's
+   * declaring class, with the specified initialization parameters.
+   *
+   * @param klass the Class object.
+   * @param args array of objects to be passed as arguments to
+   *             the constructor call.
+   * @return a new object created by calling the constructor
+   *            this object represents.
+   */
+  @SuppressWarnings("rawtypes")
+  public static <T> T newInstance(Class<T> klass, Object ... args) {
+    try {
+      Constructor<T> ctor = null;
+
+      if (args.length == 0) {
+        ctor = klass.getDeclaredConstructor(new Class[] {});
+      } else {
+        Class[] argClses = new Class[args.length];
+        for (int i = 0; i < args.length; i++) {
+          argClses[i] = args[i].getClass();
+        }
+        ctor = klass.getDeclaredConstructor(argClses);
+      }
+      ctor.setAccessible(true);
+      return ctor.newInstance(args);
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /** 
+   * Gets the value of the <code>name</code> property as a <code>Class</code>
+   * implementing the interface specified by <code>xface</code>.
+   * If no such property is specified, then <code>defaultValue</code> is 
+   * returned.An exception is thrown if the returned class does not
+   * implement the named interface.
+   * 
+   * @param name the class name of default implementation.
+   * @param defaultValue default value.
+   * @param xface the interface implemented by the named class.
+   * @return property value as a <code>Class</code>, 
+   *         or <code>defaultValue</code>.
+   */
+  public static <U> Class<? extends U> getClass(String name, 
+                                         Class<? extends U> defaultValue, 
+                                         Class<U> xface) {
+    try {
+      Class<?> theClass = null;
+      if (name != null && !name.isEmpty()) {
+        theClass = getClassByName(name);
+      }
+      if (theClass == null) {
+        theClass = defaultValue;
+      }
+      if (theClass != null && !xface.isAssignableFrom(theClass))
+        throw new RuntimeException(theClass+" not "+xface.getName());
+      else if (theClass != null)
+        return theClass.asSubclass(xface);
+      else
+        return null;
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /** 
+   * Gets the value of the <code>name</code> property as a <code>Class</code>.
+   * If no such property is specified, then <code>defaultValue</code> is 
+   * returned.
+   * 
+   * @param name the class name.
+   * @param defaultValue default value.
+   * @return property value as a <code>Class</code>, 
+   *         or <code>defaultValue</code>. 
+   */
+  public static Class<?> getClass(String name, Class<?> defaultValue) {
+    String valueString = System.getProperty(name);
+    if (valueString == null)
+      return defaultValue;
+    try {
+      return getClassByName(valueString);
+    } catch (ClassNotFoundException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Loads a class by name.
+   * 
+   * @param name the class name.
+   * @return the class object.
+   * @throws ClassNotFoundException if the class is not found.
+   */
+  public static Class<?> getClassByName(String name)
+      throws ClassNotFoundException {
+    Class<?> ret = getClassByNameOrNull(name);
+    if (ret == null) {
+      throw new ClassNotFoundException("Class " + name + " not found");
+    }
+    return ret;
+  }
+  
+  /**
+   * Loads a class by name, returning null rather than throwing an exception
+   * if it couldn't be loaded. This is to avoid the overhead of creating
+   * an exception.
+   * 
+   * @param name the class name.
+   * @return the class object, or null if it could not be found.
+   */
+  private static Class<?> getClassByNameOrNull(String name) {
+    Map<String, WeakReference<Class<?>>> map;
+
+    synchronized (CACHE_CLASSES) {
+      map = CACHE_CLASSES.get(classLoader);
+      if (map == null) {
+        map = Collections.synchronizedMap(
+          new WeakHashMap<String, WeakReference<Class<?>>>());
+        CACHE_CLASSES.put(classLoader, map);
+      }
+    }
+
+    Class<?> clazz = null;
+    WeakReference<Class<?>> ref = map.get(name); 
+    if (ref != null) {
+       clazz = ref.get();
+    }
+     
+    if (clazz == null) {
+      try {
+        clazz = Class.forName(name, true, classLoader);
+      } catch (ClassNotFoundException e) {
+        // Leave a marker that the class isn't found
+        map.put(name, new WeakReference<Class<?>>(NEGATIVE_CACHE_SENTINEL));
+        return null;
+      }
+      // two putters can race here, but they'll put the same class
+      map.put(name, new WeakReference<Class<?>>(clazz));
+      return clazz;
+    } else if (clazz == NEGATIVE_CACHE_SENTINEL) {
+      return null; // not found
+    } else {
+      // cache hit
+      return clazz;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/utils/Utils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/utils/Utils.java b/src/main/java/org/apache/commons/crypto/utils/Utils.java
new file mode 100644
index 0000000..3658adf
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/utils/Utils.java
@@ -0,0 +1,362 @@
+/**
+ * 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.commons.crypto.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.crypto.cipher.Cipher;
+import org.apache.commons.crypto.cipher.CipherFactory;
+import org.apache.commons.crypto.cipher.CipherTransformation;
+
+import static org.apache.commons.crypto.conf.ConfigurationKeys.CHIMERA_CRYPTO_STREAM_BUFFER_SIZE_DEFAULT;
+import static org.apache.commons.crypto.conf.ConfigurationKeys.CHIMERA_CRYPTO_STREAM_BUFFER_SIZE_KEY;
+import static org.apache.commons.crypto.conf.ConfigurationKeys.CHIMERA_CRYPTO_CIPHER_CLASSES_DEFAULT;
+import static org.apache.commons.crypto.conf.ConfigurationKeys.CHIMERA_CRYPTO_CIPHER_CLASSES_KEY;
+import static org.apache.commons.crypto.conf.ConfigurationKeys.CHIMERA_CRYPTO_CIPHER_JCE_PROVIDER_KEY;
+import static org.apache.commons.crypto.conf.ConfigurationKeys.CHIMERA_CRYPTO_LIB_NAME_KEY;
+import static org.apache.commons.crypto.conf.ConfigurationKeys.CHIMERA_CRYPTO_LIB_PATH_KEY;
+import static org.apache.commons.crypto.conf.ConfigurationKeys.CHIMERA_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_DEFAULT;
+import static org.apache.commons.crypto.conf.ConfigurationKeys.CHIMERA_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_KEY;
+import static org.apache.commons.crypto.conf.ConfigurationKeys.CHIMERA_SYSTEM_PROPERTIES_FILE;
+import static org.apache.commons.crypto.conf.ConfigurationKeys.CHIMERA_CRYPTO_LIB_TEMPDIR_KEY;
+
+/**
+ * General utility methods.
+ */
+public class Utils {
+  private static final int MIN_BUFFER_SIZE = 512;
+
+  protected static final CipherTransformation AES_CTR_NOPADDING = CipherTransformation.AES_CTR_NOPADDING;
+
+  /**
+   * For AES, the algorithm block is fixed size of 128 bits.
+   * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+   */
+  private static final int AES_BLOCK_SIZE = AES_CTR_NOPADDING.getAlgorithmBlockSize();
+
+  static {
+    loadChimeraSystemProperties();
+  }
+
+  /**
+   * loads system properties when configuration file of the name
+   * {@link #CHIMERA_SYSTEM_PROPERTIES_FILE} is found.
+   */
+  private static void loadChimeraSystemProperties() {
+    try {
+      InputStream is = Thread.currentThread().getContextClassLoader()
+          .getResourceAsStream(CHIMERA_SYSTEM_PROPERTIES_FILE);
+
+      if (is == null)
+        return; // no configuration file is found
+
+      // Load property file
+      Properties props = new Properties();
+      props.load(is);
+      is.close();
+      Enumeration<?> names = props.propertyNames();
+      while (names.hasMoreElements()) {
+        String name = (String) names.nextElement();
+        if (name.startsWith("chimera.")) {
+          if (System.getProperty(name) == null) {
+            System.setProperty(name, props.getProperty(name));
+          }
+        }
+      }
+    } catch (Throwable ex) {
+      System.err.println("Could not load '"
+          + CHIMERA_SYSTEM_PROPERTIES_FILE + "' from classpath: "
+          + ex.toString());
+    }
+  }
+
+  /**
+   * Forcibly free the direct buffer.
+   *
+   * @param buffer the bytebuffer to be freed.
+   */
+  public static void freeDirectBuffer(ByteBuffer buffer) {
+    if (buffer instanceof sun.nio.ch.DirectBuffer) {
+      final sun.misc.Cleaner bufferCleaner =
+          ((sun.nio.ch.DirectBuffer) buffer).cleaner();
+      bufferCleaner.clean();
+    }
+  }
+
+  /**
+   * Reads crypto buffer size.
+   *
+   * @param props The <code>Properties</code> class represents a set of
+   *              properties.
+   * @return the buffer size.
+   * */
+  public static int getBufferSize(Properties props) {
+    String bufferSizeStr = props.getProperty(
+        CHIMERA_CRYPTO_STREAM_BUFFER_SIZE_KEY);
+    if (bufferSizeStr == null || bufferSizeStr.isEmpty()) {
+      bufferSizeStr = System
+        .getProperty(CHIMERA_CRYPTO_STREAM_BUFFER_SIZE_KEY);
+    }
+    if (bufferSizeStr == null || bufferSizeStr.isEmpty()) {
+      return CHIMERA_CRYPTO_STREAM_BUFFER_SIZE_DEFAULT;
+    } else {
+      return Integer.parseInt(bufferSizeStr);
+    }
+  }
+
+  /**
+   * Gets the cipher class.
+   *
+   * @param props The <code>Properties</code> class represents a set of
+   *              properties.
+   * @return the cipher class based on the props.
+   */
+  public static String getCipherClassString(Properties props) {
+    final String configName = CHIMERA_CRYPTO_CIPHER_CLASSES_KEY;
+    return props.getProperty(configName) != null ? props.getProperty(configName) : System
+        .getProperty(configName, CHIMERA_CRYPTO_CIPHER_CLASSES_DEFAULT);
+  }
+
+  /**
+   * Gets the Jce provider.
+   *
+   * @param props The <code>Properties</code> class represents a set of
+   *              properties.
+   * @return the jce provider based on the props.
+   */
+  public static String getJCEProvider(Properties props) {
+    return props.getProperty(CHIMERA_CRYPTO_CIPHER_JCE_PROVIDER_KEY) != null ?
+        props.getProperty(CHIMERA_CRYPTO_CIPHER_JCE_PROVIDER_KEY) :
+        System.getProperty(CHIMERA_CRYPTO_CIPHER_JCE_PROVIDER_KEY);
+  }
+
+  /**
+   * Gets the random device path.
+   *
+   * @param props The <code>Properties</code> class represents a set of
+   *              properties.
+   * @return the random device path based on the props.
+   */
+  public static String getRandomDevPath(Properties props) {
+    String devPath = props.getProperty(
+        CHIMERA_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_KEY);
+    if (devPath == null) {
+      devPath = System.getProperty(
+          CHIMERA_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_KEY,
+          CHIMERA_CRYPTO_SECURE_RANDOM_DEVICE_FILE_PATH_DEFAULT);
+    }
+    return devPath;
+  }
+
+  /**
+   * Gets path of native library.
+   *
+   * @return the path of native library.
+   */
+  public static String getLibPath() {
+    return System.getProperty(CHIMERA_CRYPTO_LIB_PATH_KEY);
+  }
+
+  /**
+   * Gets the file name of native library.
+   *
+   * @return the file name of native library.
+   */
+  public static String getLibName() {
+    return System.getProperty(CHIMERA_CRYPTO_LIB_NAME_KEY);
+  }
+
+  /**
+   * Gets the temp directory for extracting crypto library.
+   *
+   * @return the temp directory.
+   */
+  public static String getTmpDir() {
+    return System.getProperty(CHIMERA_CRYPTO_LIB_TEMPDIR_KEY,
+        System.getProperty("java.io.tmpdir"));
+  }
+
+  /**
+   * Checks whether the cipher is supported streaming.
+   *
+   * @param cipher the {@link org.apache.commons.crypto.cipher.Cipher} instance.
+   * @throws IOException if an I/O error occurs.
+   */
+  public static void checkStreamCipher(Cipher cipher) throws IOException {
+    if (cipher.getTransformation() != CipherTransformation.AES_CTR_NOPADDING) {
+      throw new IOException("AES/CTR/NoPadding is required");
+    }
+  }
+
+  /**
+   * Checks and floors buffer size.
+   *
+   * @param cipher the {@link org.apache.commons.crypto.cipher.Cipher} instance.
+   * @param bufferSize the buffer size.
+   * @return the remaining buffer size.
+   */
+  public static int checkBufferSize(Cipher cipher, int bufferSize) {
+    checkArgument(bufferSize >= MIN_BUFFER_SIZE,
+        "Minimum value of buffer size is " + MIN_BUFFER_SIZE + ".");
+    return bufferSize - bufferSize % cipher.getTransformation()
+        .getAlgorithmBlockSize();
+  }
+
+  /**
+   * This method is only for Counter (CTR) mode. Generally the Cipher calculates the
+   * IV and maintain encryption context internally.For example a
+   * {@link javax.crypto.Cipher} will maintain its encryption context internally
+   * when we do encryption/decryption using the Cipher#update interface.
+   * <p/>
+   * Encryption/Decryption is not always on the entire file. For example,
+   * in Hadoop, a node may only decrypt a portion of a file (i.e. a split).
+   * In these situations, the counter is derived from the file position.
+   * <p/>
+   * The IV can be calculated by combining the initial IV and the counter with
+   * a lossless operation (concatenation, addition, or XOR).
+   * @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29
+   *
+   * @param initIV initial IV
+   * @param counter counter for input stream position
+   * @param IV the IV for input stream position
+   */
+  public static void calculateIV(byte[] initIV, long counter, byte[] IV) {
+    checkArgument(initIV.length == AES_BLOCK_SIZE);
+    checkArgument(IV.length == AES_BLOCK_SIZE);
+
+    int i = IV.length; // IV length
+    int j = 0; // counter bytes index
+    int sum = 0;
+    while (i-- > 0) {
+      // (sum >>> Byte.SIZE) is the carry for addition
+      sum = (initIV[i] & 0xff) + (sum >>> Byte.SIZE);
+      if (j++ < 8) { // Big-endian, and long is 8 bytes length
+        sum += (byte) counter & 0xff;
+        counter >>>= 8;
+      }
+      IV[i] = (byte) sum;
+    }
+  }
+
+  /**
+   * Helper method to create a Cipher instance and throws only IOException.
+   *
+   * @param props The <code>Properties</code> class represents a set of
+   *              properties.
+   * @param transformation the CipherTransformation instance.
+   * @return the Cipher instance.
+   * @throws IOException if an I/O error occurs.
+   */
+  public static Cipher getCipherInstance(CipherTransformation transformation,
+      Properties props) throws IOException {
+    try {
+      return CipherFactory.getInstance(transformation, props);
+    } catch (GeneralSecurityException e) {
+      throw new IOException(e);
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving one or more parameters to
+   * the calling method.
+   *
+   * @param expression a boolean expression.
+   * @throws IllegalArgumentException if expression is false.
+   */
+  public static void checkArgument(boolean expression) {
+    if(!expression) {
+      throw new IllegalArgumentException();
+    }
+  }
+
+  /**
+   * Checks the truth of an expression.
+   *
+   * @param expression   a boolean expression.
+   * @param errorMessage the exception message to use if the check fails;
+   *                     will be converted to a string using <code>String
+   *                     .valueOf(Object)</code>.
+   * @throws IllegalArgumentException if expression is false.
+   */
+  public static void checkArgument(boolean expression, Object errorMessage) {
+    if (!expression) {
+      throw new IllegalArgumentException(String.valueOf(errorMessage));
+    }
+  }
+
+  /**
+   * Ensures that an object reference passed as a parameter to the calling
+   * method is not null.
+   *
+   * @param reference an object reference.
+   * @return the non-null reference that was validated.
+   * @throws NullPointerException if reference is null.
+   */
+  public static <T> T checkNotNull(T reference) {
+    if(reference == null) {
+      throw new NullPointerException();
+    } else {
+      return reference;
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving the state of the calling
+   * instance, but not involving any parameters to the calling method.
+   *
+   * @param expression a boolean expression.
+   * @throws IllegalStateException if expression is false.
+   */
+  public static void checkState(boolean expression) {
+    if(!expression) {
+      throw new IllegalStateException();
+    }
+  }
+
+  /**
+   * Splits class names sequence into substrings, Trim each substring into an
+   * entry,and returns an list of the entries.
+   *
+   * @param clazzNames a string consist of a list of the entries joined by a
+   *                   delimiter.
+   * @param separator  a delimiter for the input string.
+   * @return a list of class entries.
+   */
+  public static List<String> splitClassNames(String clazzNames,
+      String separator) {
+    List<String> res = new ArrayList<String>();
+    if (clazzNames == null || clazzNames.isEmpty()) {
+      return res;
+    }
+
+    for (String clazzName : clazzNames.split(separator)) {
+      clazzName = clazzName.trim();
+      if (!clazzName.isEmpty()) {
+        res.add(clazzName);
+      }
+    }
+    return res;
+  }
+}

http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/4920d272/src/main/java/org/apache/commons/crypto/utils/package-info.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/crypto/utils/package-info.java b/src/main/java/org/apache/commons/crypto/utils/package-info.java
new file mode 100644
index 0000000..7a3c334
--- /dev/null
+++ b/src/main/java/org/apache/commons/crypto/utils/package-info.java
@@ -0,0 +1,21 @@
+/**
+ * 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.
+ */
+/**
+ * Utils classes
+ */
+package org.apache.commons.crypto.utils;