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> <tt><=</tt> <i>n</i> <tt><=</tt> <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> <tt>+</tt> <i>n</i> <tt>-</tt> <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> <tt>+</tt> <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> <tt><=</tt> <i>n</i> <tt><=</tt> <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> <tt>+</tt> <i>n</i> <tt>-</tt> <tt>1</tt>.
+ * Upon return the buffer's position will be equal to
+ * <i>p</i> <tt>+</tt> <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;