Author: tchemit Date: 2010-03-10 11:31:32 +0100 (Wed, 10 Mar 2010) New Revision: 1794 Log: - Evolution #246: Remove fast-md5 api and use our implementation based on provided MD5 messageDigester - use the new MD5 api - reformat code (80 car max per line) - close opened stream... Added: trunk/src/test/java/org/nuiton/util/MD5InputStreamTest.java Removed: trunk/src/main/java/org/nuiton/util/MD5.java trunk/src/main/java/org/nuiton/util/MD5State.java Modified: trunk/pom.xml trunk/src/main/java/org/nuiton/util/H2TypeEnum.java trunk/src/main/java/org/nuiton/util/MD5InputStream.java trunk/src/main/java/org/nuiton/util/MD5OutputStream.java trunk/src/main/java/org/nuiton/util/MonthEnum.java trunk/src/main/java/org/nuiton/util/ResourceResolver.java trunk/src/main/java/org/nuiton/util/ReverseFileReader.java trunk/src/main/java/org/nuiton/util/SortedProperties.java trunk/src/main/java/org/nuiton/util/StreamKeywordTokenizer.java trunk/src/main/java/org/nuiton/util/StringUtil.java trunk/src/main/java/org/nuiton/util/TransformedList.java trunk/src/main/java/org/nuiton/util/TransparenteSoftReference.java trunk/src/main/java/org/nuiton/util/TransparenteWeakReference.java trunk/src/main/java/org/nuiton/util/URIConverter.java trunk/src/main/java/org/nuiton/util/URLConverter.java trunk/src/main/java/org/nuiton/util/Version.java trunk/src/main/java/org/nuiton/util/VersionConverter.java trunk/src/main/java/org/nuiton/util/VersionUtil.java trunk/src/main/java/org/nuiton/util/ZipStreamEncoder.java trunk/src/main/java/org/nuiton/util/ZipUtil.java Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/pom.xml 2010-03-10 10:31:32 UTC (rev 1794) @@ -118,6 +118,9 @@ <groupId>org.nuiton.i18n</groupId> <artifactId>maven-i18n-plugin</artifactId> <version>${i18n.version}</version> + <configuration> + <silent>true</silent> + </configuration> <executions> <execution> <goals> Modified: trunk/src/main/java/org/nuiton/util/H2TypeEnum.java =================================================================== --- trunk/src/main/java/org/nuiton/util/H2TypeEnum.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/H2TypeEnum.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -21,7 +21,9 @@ * Une énumération pour représenter les différentes types d'implantation dans H2 * * @author chemit + * @deprecated since 1.2, will be removed soon and not replace. */ +@Deprecated public enum H2TypeEnum { derby, h2, Deleted: trunk/src/main/java/org/nuiton/util/MD5.java =================================================================== --- trunk/src/main/java/org/nuiton/util/MD5.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/MD5.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -1,846 +0,0 @@ -/** - * *##% Nuiton utilities library - * Copyright (C) 2004 - 2009 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%* - */ -package org.nuiton.util; - -import java.io.*; - -/** - * Fast implementation of RSA's MD5 hash generator in Java JDK Beta-2 or higher. - * <p> - * Originally written by Santeri Paavolainen, Helsinki Finland 1996.<br> - * (c) Santeri Paavolainen, Helsinki Finland 1996<br> - * Many changes Copyright (c) 2002 - 2008 Timothy W Macinta<br> - * <p> - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * <p> - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * <p> - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * <p> - * See http://www.twmacinta.com/myjava/fast_md5.php for more information - * on this file and the related files. - * <p> - * This was originally a rather straight re-implementation of the - * reference implementation given in RFC1321 by RSA. It passes the MD5 - * test suite as defined in RFC1321. - * <p> - * Many optimizations made by Timothy W Macinta. Reduced time to checksum a - * test file in Java alone to roughly half the time taken compared with - * java.security.MessageDigest (within an intepretter). Also added an - * optional native method to reduce the time even further. - * See http://www.twmacinta.com/myjava/fast_md5.php for further information - * on the time improvements achieved. - * <p> - * Some bug fixes also made by Timothy W Macinta. - * <p> - * Please note: I (Timothy Macinta) have put this code in the - * com.twmacinta.util package only because it came without a package. I - * was not the the original author of the code, although I did - * optimize it (substantially) and fix some bugs. - * <p> - * This Java class has been derived from the RSA Data Security, Inc. MD5 - * Message-Digest Algorithm and its reference implementation. - * <p> - * This class will attempt to use a native method to quickly compute - * checksums when the appropriate native library is available. On Linux, - * this library should be named "MD5.so" and on Windows it should be - * named "MD5.dll". The code will attempt to locate the library in the - * following locations in the order given: - * - * <ol> - * <li>The path specified by the system property - * "com.twmacinta.util.MD5.NATIVE_LIB_FILE" - * (be sure to include "MD5.so" or "MD5.dll" - * as appropriate at the end of the path). - * <li>A platform specific directory beneath the "lib/arch/" directory. - * On Linux for x86, this is "lib/arch/linux_x86/". On Windows for - * x86, this is "lib/arch/win32_x86/". - * <li>Within the "lib/" directory. - * <li>Within the current directory. - * </ol> - * - * <p> - * If the library is not found, the code will fall back to the default - * (slower) Java code. - * <p> - * As a side effect of having the code search for the native library, - * SecurityExceptions might be thrown on JVMs that have a restrictive - * SecurityManager. The initialization code attempts to silently discard - * these exceptions and continue, but many SecurityManagers will - * attempt to notify the user directly of all SecurityExceptions thrown. - * Consequently, the code has provisions for skipping the search for - * the native library. Any of these provisions may be used to skip the - * search as long as they are performed <i>before</i> the first - * instance of a com.twmacinta.util.MD5 object is constructed (note that - * the convenience stream objects will implicitly create an MD5 object). - * <p> - * The first option is to set the system property - * "com.twmacinta.util.MD5.NO_NATIVE_LIB" to "true" or "1". - * Unfortunately, SecurityManagers may also choose to disallow system - * property setting, so this won't be of use in all cases. - * <p> - * The second option is to call - * com.twmacinta.util.MD5.initNativeLibrary(true) before any MD5 objects - * are constructed. - * - * @author Santeri Paavolainen <sjpaavol@cc.helsinki.fi> - * @author Timothy W Macinta (twm@alum.mit.edu) (optimizations and bug fixes) - * @deprecated since 1.1.4 (prefer use jdk implentation instead), will be removed in version 1.2 - */ - -@Deprecated -public class MD5 { - - /** - * MD5 state - **/ - MD5State state; - - /** - * If Final() has been called, finals is set to the current finals - * state. Any Update() causes this to be set to null. - **/ - MD5State finals; - - /** - * Padding for Final() - **/ - static byte padding[] = { - (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - - private static boolean native_lib_loaded = false; - private static boolean native_lib_init_pending = true; - - /** - * Initialize MD5 internal state (object can be reused just by - * calling Init() after every Final() - **/ - public synchronized void Init () { - state = new MD5State(); - finals = null; - } - - /** - * Class constructor - **/ - public MD5 () { - if (native_lib_init_pending) _initNativeLibrary(); - this.Init(); - } - - /** - * Initialize class, and update hash with ob.toString() - * - * @param ob Object, ob.toString() is used to update hash - * after initialization - **/ - public MD5 (Object ob) { - this(); - Update(ob.toString()); - } - - private void Decode (byte buffer[], int shift, int[] out) { - /*len += shift; - for (int i = 0; shift < len; i++, shift += 4) { - out[i] = ((int) (buffer[shift] & 0xff)) | - (((int) (buffer[shift + 1] & 0xff)) << 8) | - (((int) (buffer[shift + 2] & 0xff)) << 16) | - (((int) buffer[shift + 3]) << 24); - }*/ - - // unrolled loop (original loop shown above) - - out[0] = ((int) (buffer[shift] & 0xff)) | - (((int) (buffer[shift + 1] & 0xff)) << 8) | - (((int) (buffer[shift + 2] & 0xff)) << 16) | - (((int) buffer[shift + 3]) << 24); - out[1] = ((int) (buffer[shift + 4] & 0xff)) | - (((int) (buffer[shift + 5] & 0xff)) << 8) | - (((int) (buffer[shift + 6] & 0xff)) << 16) | - (((int) buffer[shift + 7]) << 24); - out[2] = ((int) (buffer[shift + 8] & 0xff)) | - (((int) (buffer[shift + 9] & 0xff)) << 8) | - (((int) (buffer[shift + 10] & 0xff)) << 16) | - (((int) buffer[shift + 11]) << 24); - out[3] = ((int) (buffer[shift + 12] & 0xff)) | - (((int) (buffer[shift + 13] & 0xff)) << 8) | - (((int) (buffer[shift + 14] & 0xff)) << 16) | - (((int) buffer[shift + 15]) << 24); - out[4] = ((int) (buffer[shift + 16] & 0xff)) | - (((int) (buffer[shift + 17] & 0xff)) << 8) | - (((int) (buffer[shift + 18] & 0xff)) << 16) | - (((int) buffer[shift + 19]) << 24); - out[5] = ((int) (buffer[shift + 20] & 0xff)) | - (((int) (buffer[shift + 21] & 0xff)) << 8) | - (((int) (buffer[shift + 22] & 0xff)) << 16) | - (((int) buffer[shift + 23]) << 24); - out[6] = ((int) (buffer[shift + 24] & 0xff)) | - (((int) (buffer[shift + 25] & 0xff)) << 8) | - (((int) (buffer[shift + 26] & 0xff)) << 16) | - (((int) buffer[shift + 27]) << 24); - out[7] = ((int) (buffer[shift + 28] & 0xff)) | - (((int) (buffer[shift + 29] & 0xff)) << 8) | - (((int) (buffer[shift + 30] & 0xff)) << 16) | - (((int) buffer[shift + 31]) << 24); - out[8] = ((int) (buffer[shift + 32] & 0xff)) | - (((int) (buffer[shift + 33] & 0xff)) << 8) | - (((int) (buffer[shift + 34] & 0xff)) << 16) | - (((int) buffer[shift + 35]) << 24); - out[9] = ((int) (buffer[shift + 36] & 0xff)) | - (((int) (buffer[shift + 37] & 0xff)) << 8) | - (((int) (buffer[shift + 38] & 0xff)) << 16) | - (((int) buffer[shift + 39]) << 24); - out[10] = ((int) (buffer[shift + 40] & 0xff)) | - (((int) (buffer[shift + 41] & 0xff)) << 8) | - (((int) (buffer[shift + 42] & 0xff)) << 16) | - (((int) buffer[shift + 43]) << 24); - out[11] = ((int) (buffer[shift + 44] & 0xff)) | - (((int) (buffer[shift + 45] & 0xff)) << 8) | - (((int) (buffer[shift + 46] & 0xff)) << 16) | - (((int) buffer[shift + 47]) << 24); - out[12] = ((int) (buffer[shift + 48] & 0xff)) | - (((int) (buffer[shift + 49] & 0xff)) << 8) | - (((int) (buffer[shift + 50] & 0xff)) << 16) | - (((int) buffer[shift + 51]) << 24); - out[13] = ((int) (buffer[shift + 52] & 0xff)) | - (((int) (buffer[shift + 53] & 0xff)) << 8) | - (((int) (buffer[shift + 54] & 0xff)) << 16) | - (((int) buffer[shift + 55]) << 24); - out[14] = ((int) (buffer[shift + 56] & 0xff)) | - (((int) (buffer[shift + 57] & 0xff)) << 8) | - (((int) (buffer[shift + 58] & 0xff)) << 16) | - (((int) buffer[shift + 59]) << 24); - out[15] = ((int) (buffer[shift + 60] & 0xff)) | - (((int) (buffer[shift + 61] & 0xff)) << 8) | - (((int) (buffer[shift + 62] & 0xff)) << 16) | - (((int) buffer[shift + 63]) << 24); - } - - private native void Transform_native (int[] state, byte buffer[], int shift, int length); - - private void Transform (MD5State state, byte buffer[], int shift, int[] decode_buf) { - int - a = state.state[0], - b = state.state[1], - c = state.state[2], - d = state.state[3], - x[] = decode_buf; - - Decode(buffer, shift, decode_buf); - - /* Round 1 */ - a += ((b & c) | (~b & d)) + x[ 0] + 0xd76aa478; /* 1 */ - a = ((a << 7) | (a >>> 25)) + b; - d += ((a & b) | (~a & c)) + x[ 1] + 0xe8c7b756; /* 2 */ - d = ((d << 12) | (d >>> 20)) + a; - c += ((d & a) | (~d & b)) + x[ 2] + 0x242070db; /* 3 */ - c = ((c << 17) | (c >>> 15)) + d; - b += ((c & d) | (~c & a)) + x[ 3] + 0xc1bdceee; /* 4 */ - b = ((b << 22) | (b >>> 10)) + c; - - a += ((b & c) | (~b & d)) + x[ 4] + 0xf57c0faf; /* 5 */ - a = ((a << 7) | (a >>> 25)) + b; - d += ((a & b) | (~a & c)) + x[ 5] + 0x4787c62a; /* 6 */ - d = ((d << 12) | (d >>> 20)) + a; - c += ((d & a) | (~d & b)) + x[ 6] + 0xa8304613; /* 7 */ - c = ((c << 17) | (c >>> 15)) + d; - b += ((c & d) | (~c & a)) + x[ 7] + 0xfd469501; /* 8 */ - b = ((b << 22) | (b >>> 10)) + c; - - a += ((b & c) | (~b & d)) + x[ 8] + 0x698098d8; /* 9 */ - a = ((a << 7) | (a >>> 25)) + b; - d += ((a & b) | (~a & c)) + x[ 9] + 0x8b44f7af; /* 10 */ - d = ((d << 12) | (d >>> 20)) + a; - c += ((d & a) | (~d & b)) + x[10] + 0xffff5bb1; /* 11 */ - c = ((c << 17) | (c >>> 15)) + d; - b += ((c & d) | (~c & a)) + x[11] + 0x895cd7be; /* 12 */ - b = ((b << 22) | (b >>> 10)) + c; - - a += ((b & c) | (~b & d)) + x[12] + 0x6b901122; /* 13 */ - a = ((a << 7) | (a >>> 25)) + b; - d += ((a & b) | (~a & c)) + x[13] + 0xfd987193; /* 14 */ - d = ((d << 12) | (d >>> 20)) + a; - c += ((d & a) | (~d & b)) + x[14] + 0xa679438e; /* 15 */ - c = ((c << 17) | (c >>> 15)) + d; - b += ((c & d) | (~c & a)) + x[15] + 0x49b40821; /* 16 */ - b = ((b << 22) | (b >>> 10)) + c; - - - /* Round 2 */ - a += ((b & d) | (c & ~d)) + x[ 1] + 0xf61e2562; /* 17 */ - a = ((a << 5) | (a >>> 27)) + b; - d += ((a & c) | (b & ~c)) + x[ 6] + 0xc040b340; /* 18 */ - d = ((d << 9) | (d >>> 23)) + a; - c += ((d & b) | (a & ~b)) + x[11] + 0x265e5a51; /* 19 */ - c = ((c << 14) | (c >>> 18)) + d; - b += ((c & a) | (d & ~a)) + x[ 0] + 0xe9b6c7aa; /* 20 */ - b = ((b << 20) | (b >>> 12)) + c; - - a += ((b & d) | (c & ~d)) + x[ 5] + 0xd62f105d; /* 21 */ - a = ((a << 5) | (a >>> 27)) + b; - d += ((a & c) | (b & ~c)) + x[10] + 0x02441453; /* 22 */ - d = ((d << 9) | (d >>> 23)) + a; - c += ((d & b) | (a & ~b)) + x[15] + 0xd8a1e681; /* 23 */ - c = ((c << 14) | (c >>> 18)) + d; - b += ((c & a) | (d & ~a)) + x[ 4] + 0xe7d3fbc8; /* 24 */ - b = ((b << 20) | (b >>> 12)) + c; - - a += ((b & d) | (c & ~d)) + x[ 9] + 0x21e1cde6; /* 25 */ - a = ((a << 5) | (a >>> 27)) + b; - d += ((a & c) | (b & ~c)) + x[14] + 0xc33707d6; /* 26 */ - d = ((d << 9) | (d >>> 23)) + a; - c += ((d & b) | (a & ~b)) + x[ 3] + 0xf4d50d87; /* 27 */ - c = ((c << 14) | (c >>> 18)) + d; - b += ((c & a) | (d & ~a)) + x[ 8] + 0x455a14ed; /* 28 */ - b = ((b << 20) | (b >>> 12)) + c; - - a += ((b & d) | (c & ~d)) + x[13] + 0xa9e3e905; /* 29 */ - a = ((a << 5) | (a >>> 27)) + b; - d += ((a & c) | (b & ~c)) + x[ 2] + 0xfcefa3f8; /* 30 */ - d = ((d << 9) | (d >>> 23)) + a; - c += ((d & b) | (a & ~b)) + x[ 7] + 0x676f02d9; /* 31 */ - c = ((c << 14) | (c >>> 18)) + d; - b += ((c & a) | (d & ~a)) + x[12] + 0x8d2a4c8a; /* 32 */ - b = ((b << 20) | (b >>> 12)) + c; - - - /* Round 3 */ - a += (b ^ c ^ d) + x[ 5] + 0xfffa3942; /* 33 */ - a = ((a << 4) | (a >>> 28)) + b; - d += (a ^ b ^ c) + x[ 8] + 0x8771f681; /* 34 */ - d = ((d << 11) | (d >>> 21)) + a; - c += (d ^ a ^ b) + x[11] + 0x6d9d6122; /* 35 */ - c = ((c << 16) | (c >>> 16)) + d; - b += (c ^ d ^ a) + x[14] + 0xfde5380c; /* 36 */ - b = ((b << 23) | (b >>> 9)) + c; - - a += (b ^ c ^ d) + x[ 1] + 0xa4beea44; /* 37 */ - a = ((a << 4) | (a >>> 28)) + b; - d += (a ^ b ^ c) + x[ 4] + 0x4bdecfa9; /* 38 */ - d = ((d << 11) | (d >>> 21)) + a; - c += (d ^ a ^ b) + x[ 7] + 0xf6bb4b60; /* 39 */ - c = ((c << 16) | (c >>> 16)) + d; - b += (c ^ d ^ a) + x[10] + 0xbebfbc70; /* 40 */ - b = ((b << 23) | (b >>> 9)) + c; - - a += (b ^ c ^ d) + x[13] + 0x289b7ec6; /* 41 */ - a = ((a << 4) | (a >>> 28)) + b; - d += (a ^ b ^ c) + x[ 0] + 0xeaa127fa; /* 42 */ - d = ((d << 11) | (d >>> 21)) + a; - c += (d ^ a ^ b) + x[ 3] + 0xd4ef3085; /* 43 */ - c = ((c << 16) | (c >>> 16)) + d; - b += (c ^ d ^ a) + x[ 6] + 0x04881d05; /* 44 */ - b = ((b << 23) | (b >>> 9)) + c; - - a += (b ^ c ^ d) + x[ 9] + 0xd9d4d039; /* 33 */ - a = ((a << 4) | (a >>> 28)) + b; - d += (a ^ b ^ c) + x[12] + 0xe6db99e5; /* 34 */ - d = ((d << 11) | (d >>> 21)) + a; - c += (d ^ a ^ b) + x[15] + 0x1fa27cf8; /* 35 */ - c = ((c << 16) | (c >>> 16)) + d; - b += (c ^ d ^ a) + x[ 2] + 0xc4ac5665; /* 36 */ - b = ((b << 23) | (b >>> 9)) + c; - - - /* Round 4 */ - a += (c ^ (b | ~d)) + x[ 0] + 0xf4292244; /* 49 */ - a = ((a << 6) | (a >>> 26)) + b; - d += (b ^ (a | ~c)) + x[ 7] + 0x432aff97; /* 50 */ - d = ((d << 10) | (d >>> 22)) + a; - c += (a ^ (d | ~b)) + x[14] + 0xab9423a7; /* 51 */ - c = ((c << 15) | (c >>> 17)) + d; - b += (d ^ (c | ~a)) + x[ 5] + 0xfc93a039; /* 52 */ - b = ((b << 21) | (b >>> 11)) + c; - - a += (c ^ (b | ~d)) + x[12] + 0x655b59c3; /* 53 */ - a = ((a << 6) | (a >>> 26)) + b; - d += (b ^ (a | ~c)) + x[ 3] + 0x8f0ccc92; /* 54 */ - d = ((d << 10) | (d >>> 22)) + a; - c += (a ^ (d | ~b)) + x[10] + 0xffeff47d; /* 55 */ - c = ((c << 15) | (c >>> 17)) + d; - b += (d ^ (c | ~a)) + x[ 1] + 0x85845dd1; /* 56 */ - b = ((b << 21) | (b >>> 11)) + c; - - a += (c ^ (b | ~d)) + x[ 8] + 0x6fa87e4f; /* 57 */ - a = ((a << 6) | (a >>> 26)) + b; - d += (b ^ (a | ~c)) + x[15] + 0xfe2ce6e0; /* 58 */ - d = ((d << 10) | (d >>> 22)) + a; - c += (a ^ (d | ~b)) + x[ 6] + 0xa3014314; /* 59 */ - c = ((c << 15) | (c >>> 17)) + d; - b += (d ^ (c | ~a)) + x[13] + 0x4e0811a1; /* 60 */ - b = ((b << 21) | (b >>> 11)) + c; - - a += (c ^ (b | ~d)) + x[ 4] + 0xf7537e82; /* 61 */ - a = ((a << 6) | (a >>> 26)) + b; - d += (b ^ (a | ~c)) + x[11] + 0xbd3af235; /* 62 */ - d = ((d << 10) | (d >>> 22)) + a; - c += (a ^ (d | ~b)) + x[ 2] + 0x2ad7d2bb; /* 63 */ - c = ((c << 15) | (c >>> 17)) + d; - b += (d ^ (c | ~a)) + x[ 9] + 0xeb86d391; /* 64 */ - b = ((b << 21) | (b >>> 11)) + c; - - state.state[0] += a; - state.state[1] += b; - state.state[2] += c; - state.state[3] += d; - } - - /** - * Updates hash with the bytebuffer given (using at maximum length bytes from - * that buffer) - * - * @param stat Which state is updated - * @param buffer Array of bytes to be hashed - * @param offset Offset to buffer array - * @param length Use at maximum `length' bytes (absolute - * maximum is buffer.length) - */ - public void Update (MD5State stat, byte buffer[], int offset, int length) { - int index, partlen, i, start; - finals = null; - - /* Length can be told to be shorter, but not inter */ - if ((length - offset)> buffer.length) - length = buffer.length - offset; - - /* compute number of bytes mod 64 */ - - index = (int) (stat.count & 0x3f); - stat.count += length; - - partlen = 64 - index; - - if (length >= partlen) { - - // update state (using native method) to reflect input - - if (native_lib_loaded) { - if (partlen == 64) { - partlen = 0; - } else { - for (i = 0; i < partlen; i++) - stat.buffer[i + index] = buffer[i + offset]; - Transform_native(stat.state, stat.buffer, 0, 64); - } - i = partlen + ((length - partlen) / 64) * 64; - - // break into chunks to guard against stack overflow in JNI - - int transformLength = length - partlen; - int transformOffset = partlen + offset; - final int MAX_LENGTH = 65536; // prevent stack overflow in JNI - while (true) { - if (transformLength > MAX_LENGTH) { - Transform_native(stat.state, buffer, transformOffset, MAX_LENGTH); - transformLength -= MAX_LENGTH; - transformOffset += MAX_LENGTH; - } else { - Transform_native(stat.state, buffer, transformOffset, transformLength); - break; - } - } - } - - // update state (using only Java) to reflect input - - else { - int[] decode_buf = new int[16]; - if (partlen == 64) { - partlen = 0; - } else { - for (i = 0; i < partlen; i++) - stat.buffer[i + index] = buffer[i + offset]; - Transform(stat, stat.buffer, 0, decode_buf); - } - for (i = partlen; (i + 63) < length; i+= 64) { - Transform(stat, buffer, i + offset, decode_buf); - } - } - index = 0; - } else { - i = 0; - } - - /* buffer remaining input */ - if (i < length) { - start = i; - for (; i < length; i++) { - stat.buffer[index + i - start] = buffer[i + offset]; - } - } - } - - /* - * Update()s for other datatypes than byte[] also. Update(byte[], int) - * is only the main driver. - */ - - /** - * Plain update, updates this object - **/ - public void Update (byte buffer[], int offset, int length) { - Update(this.state, buffer, offset, length); - } - - public void Update (byte buffer[], int length) { - Update(this.state, buffer, 0, length); - } - - /** - * Updates hash with given array of bytes - * - * @param buffer Array of bytes to use for updating the hash - **/ - public void Update (byte buffer[]) { - Update(buffer, 0, buffer.length); - } - - /** - * Updates hash with a single byte - * - * @param b Single byte to update the hash - **/ - public void Update (byte b) { - byte buffer[] = new byte[1]; - buffer[0] = b; - - Update(buffer, 1); - } - - /** - * Update buffer with given string. Note that because the version of - * the s.getBytes() method without parameters is used to convert the - * string to a byte array, the results of this method may be different - * on different platforms. The s.getBytes() method converts the string - * into a byte array using the current platform's default character set - * and may therefore have different results on platforms with different - * default character sets. If a version that works consistently - * across platforms with different default character sets is desired, - * use the overloaded version of the Update() method which takes a - * string and a character encoding. - * - * @param s String to be update to hash (is used as s.getBytes()) - **/ - public void Update (String s) { - byte chars[] = s.getBytes(); - Update(chars, chars.length); - } - - /** - * Update buffer with given string using the given encoding. If the - * given encoding is null, the encoding "ISO8859_1" is used. - * - * @param s String to be update to hash (is used as - * s.getBytes(charset_name)) - * @param charset_name The character set to use to convert s to a - * byte array, or null if the "ISO8859_1" - * character set is desired. - * @exception java.io.UnsupportedEncodingException If the named - * charset is not supported. - **/ - public void Update (String s, String charset_name) throws java.io.UnsupportedEncodingException { - if (charset_name == null) charset_name = "ISO8859_1"; - byte chars[] = s.getBytes(charset_name); - Update(chars, chars.length); - } - - /** - * Update buffer with a single integer (only & 0xff part is used, - * as a byte) - * - * @param i Integer value, which is then converted to byte as i & 0xff - **/ - public void Update (int i) { - Update((byte) (i & 0xff)); - } - - private byte[] Encode (int input[], int len) { - int i, j; - byte out[]; - - out = new byte[len]; - - for (i = j = 0; j < len; i++, j += 4) { - out[j] = (byte) (input[i] & 0xff); - out[j + 1] = (byte) ((input[i] >>> 8) & 0xff); - out[j + 2] = (byte) ((input[i] >>> 16) & 0xff); - out[j + 3] = (byte) ((input[i] >>> 24) & 0xff); - } - - return out; - } - - /** - * Returns array of bytes (16 bytes) representing hash as of the - * current state of this object. Note: getting a hash does not - * invalidate the hash object, it only creates a copy of the real - * state which is finalized. - * - * @return Array of 16 bytes, the hash of all updated bytes - **/ - public synchronized byte[] Final () { - byte bits[]; - int index, padlen; - MD5State fin; - - if (finals == null) { - fin = new MD5State(state); - - int[] count_ints = {(int) (fin.count << 3), (int) (fin.count >> 29)}; - bits = Encode(count_ints, 8); - - index = (int) (fin.count & 0x3f); - padlen = (index < 56) ? (56 - index) : (120 - index); - - Update(fin, padding, 0, padlen); - Update(fin, bits, 0, 8); - - /* Update() sets finals to null */ - finals = fin; - } - - return Encode(finals.state, 16); - } - - private static final char[] HEX_CHARS = {'0', '1', '2', '3', - '4', '5', '6', '7', - '8', '9', 'a', 'b', - 'c', 'd', 'e', 'f',}; - - /** - * Turns array of bytes into string representing each byte as - * unsigned hex number. - * - * @param hash Array of bytes to convert to hex-string - * @return Generated hex string - */ - public static String asHex (byte hash[]) { - char buf[] = new char[hash.length * 2]; - for (int i = 0, x = 0; i < hash.length; i++) { - buf[x++] = HEX_CHARS[(hash[i] >>> 4) & 0xf]; - buf[x++] = HEX_CHARS[hash[i] & 0xf]; - } - return new String(buf); - } - - /** - * Returns 32-character hex representation of this objects hash - * - * @return String of this object's hash - */ - public String asHex () { - return asHex(this.Final()); - } - - public static synchronized final void initNativeLibrary (boolean disallow_lib_loading) { - if (disallow_lib_loading) { - native_lib_init_pending = false; - } else { - _initNativeLibrary(); - } - } - - private static synchronized final void _initNativeLibrary () { - if (!native_lib_init_pending) return; - native_lib_loaded = _loadNativeLibrary(); - native_lib_init_pending = false; - } - - private static synchronized final boolean _loadNativeLibrary () { - try { - - // don't try to load if the right property is set - - String prop = System.getProperty("com.twmacinta.util.MD5.NO_NATIVE_LIB"); - if (prop != null) { - prop = prop.trim(); - if (prop.equalsIgnoreCase("true") || prop.equals("1")) return false; - } - - // the library to load can be specified as a property - - File f; - prop = System.getProperty("com.twmacinta.util.MD5.NATIVE_LIB_FILE"); - if (prop != null) { - f = new File(prop); - if (f.canRead()) { - System.load(f.getAbsolutePath()); - return true; - } - } - - // determine the operating system and architecture - - String os_name = System.getProperty("os.name"); - String os_arch = System.getProperty("os.arch"); - if (os_name == null || os_arch == null) return false; - os_name = os_name.toLowerCase(); - os_arch = os_arch.toLowerCase(); - - // define settings which are OS arch architecture independent - - File arch_lib_path = null; - String arch_libfile_suffix = null; - - // fill in settings for Linux on x86 - - if (os_name.equals("linux") && - (os_arch.equals("x86") || - os_arch.equals("i386") || - os_arch.equals("i486") || - os_arch.equals("i586") || - os_arch.equals("i686"))) { - arch_lib_path = new File(new File(new File("lib"), "arch"), "linux_x86"); - arch_libfile_suffix = ".so"; - } - - // fill in settings for Windows on x86 - - else if (os_name.startsWith("windows ") && - (os_arch.equals("x86") || - os_arch.equals("i386") || - os_arch.equals("i486") || - os_arch.equals("i586") || - os_arch.equals("i686"))) { - arch_lib_path = new File(new File(new File("lib"), "arch"), "win32_x86"); - arch_libfile_suffix = ".dll"; - } - - // fill in settings for Mac OS X on PPC - - else if (os_name.startsWith("mac os x") && - (os_arch.equals("ppc"))) { - arch_lib_path = new File(new File(new File("lib"), "arch"), "darwin_ppc"); - arch_libfile_suffix = ".jnilib"; - } - - // fill in settings for Mac OS X on x86 - - else if (os_name.startsWith("mac os x") && - (os_arch.equals("x86") || - os_arch.equals("i386") || - os_arch.equals("i486") || - os_arch.equals("i586") || - os_arch.equals("i686"))) { - arch_lib_path = new File(new File(new File("lib"), "arch"), "darwin_x86"); - arch_libfile_suffix = ".jnilib"; - } - - // default to .so files with no architecture specific subdirectory - - else { - arch_libfile_suffix = ".so"; - } - - // build the required filename - - String fname = "MD5" + arch_libfile_suffix; - - // try the architecture specific directory - - if (arch_lib_path != null) { - f = new File(arch_lib_path, fname); - if (f.canRead()) { - System.load(f.getAbsolutePath()); - return true; - } - } - - // try the "lib" subdirectory - - f = new File(new File("lib"), fname); - if (f.canRead()) { - System.load(f.getAbsolutePath()); - return true; - } - - // try the working directory - - f = new File(fname); - if (f.canRead()) { - System.load(f.getAbsolutePath()); - return true; - } - } - - // discard SecurityExceptions - - catch (SecurityException e) {} - - // unable to load - - return false; - } - - /** - * Calculates and returns the hash of the contents of the given file. - **/ - public static byte[] getHash (File f) throws IOException { - if (!f.exists()) throw new FileNotFoundException(f.toString()); - InputStream close_me = null; - try { - long buf_size = f.length(); - if (buf_size < 512) buf_size = 512; - if (buf_size > 65536) buf_size = 65536; - byte[] buf = new byte[(int) buf_size]; - MD5InputStream in = new MD5InputStream(new FileInputStream(f)); - close_me = in; - while (in.read(buf) != -1); - in.close(); - return in.hash(); - } catch (IOException e) { - if (close_me != null) try { close_me.close(); } catch (Exception e2) {} - throw e; - } - } - - /** - * @return true iff the first 16 bytes of both hash1 and hash2 are - * equal; both hash1 and hash2 are null; or either hash - * array is less than 16 bytes in length and their lengths and - * all of their bytes are equal. - **/ - public static boolean hashesEqual (byte[] hash1, byte[] hash2) { - if (hash1 == null) return hash2 == null; - if (hash2 == null) return false; - int targ = 16; - if (hash1.length < 16) { - if (hash2.length != hash1.length) return false; - targ = hash1.length; - } else if (hash2.length < 16) { - return false; - } - for (int i = 0; i < targ; i++) { - if (hash1[i] != hash2[i]) return false; - } - return true; - } - -} Modified: trunk/src/main/java/org/nuiton/util/MD5InputStream.java =================================================================== --- trunk/src/main/java/org/nuiton/util/MD5InputStream.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/MD5InputStream.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -18,75 +18,96 @@ */ package org.nuiton.util; -import java.io.*; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; -/** +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** * MD5InputStream, a subclass of FilterInputStream implementing MD5 * functionality on a stream. - * <p> - * Originally written by Santeri Paavolainen, Helsinki Finland 1996 <br> - * (c) Santeri Paavolainen, Helsinki Finland 1996 <br> - * Some changes Copyright (c) 2002 Timothy W Macinta <br> - * <p> - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * <p> - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * <p> - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * <p> - * See http://www.twmacinta.com/myjava/fast_md5.php for more information - * on this file. - * <p> - * Please note: I (Timothy Macinta) have put this code in the - * com.twmacinta.util package only because it came without a package. I - * was not the the original author of the code, although I did - * optimize it (substantially) and fix some bugs. * - * @author Santeri Paavolainen <santtu@cs.hut.fi> - * @author Timothy W Macinta (twm@alum.mit.edu) (added main() method) - **/ -public class MD5InputStream extends FilterInputStream { + * @author tchemit <chemit@codelutin.com> + */ +public class MD5InputStream extends DigestInputStream { + /** Class logger. */ - private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(MD5InputStream.class); + private static Log log = LogFactory.getLog(MD5InputStream.class); + + protected static MessageDigest getMD5Digest() { + try { + MessageDigest digest = MessageDigest.getInstance("MD5"); + return digest; + } catch (NoSuchAlgorithmException e) { + if (log.isErrorEnabled()) { + log.error("Could not find algorithm MD5...", e); + } + throw new IllegalStateException(e); + } + } + /** - * MD5 context + * Compute the MD5 for the given {@code input}. + * + * <b>Note:</b> The the stream will be closed after calling the method + * even if something was wrong. + * + * @param input the stream to parse + * @return the MD5 hash for the given input stream + * @throws IOException if any pb while reading in stream or digest */ - protected MD5 md5; + public static byte[] hash(InputStream input) throws IOException { + MD5InputStream in = new MD5InputStream(input); + try { + while (in.read()!=-1) { + // read a caracter on stream + } + + byte[] result = in.hash(); + return result; + } finally { + in.close(); + } + } + + + /** + * Compute the MD5 for the given {@code input} sring. + * + * @param input the stream to parse + * @return the MD5 hash for the given input String + * @throws IOException if any pb while reading in stream or digest + */ + public static byte[] hash(String input) throws IOException { + byte[] result = hash(new ByteArrayInputStream(input.getBytes())); + return result; + } + + /** length of readed stream */ protected long streamLength; /** * Creates a MD5InputStream - * @param in The input stream + * + * @param in The input stream */ public MD5InputStream(InputStream in) { - super(in); - - md5 = new MD5(); + super(in, getMD5Digest()); } @Override public int read() throws IOException { - int c = in.read(); + int c = super.read(); if (c == -1) { return -1; } - - if ((c & ~0xff) != 0) { - log.warn("MD5InputStream.read() got character with (c & ~0xff) != 0)!"); - } else { - streamLength++; - md5.Update(c); - } - + streamLength++; return c; } @@ -94,99 +115,26 @@ public int read(byte bytes[], int offset, int length) throws IOException { int r; - if ((r = in.read(bytes, offset, length)) == -1) { + if ((r = super.read(bytes, offset, length)) == -1) { return r; } streamLength += r; - - md5.Update(bytes, offset, r); - return r; } /** - * Returns array of bytes representing hash of the stream as - * finalized for the current state. + * Returns array of bytes representing hash of the stream as finalized for + * the current state. + * * @return hash - * @see MD5#Final + * @see MessageDigest#digest() */ public byte[] hash() { - return md5.Final(); + return getMessageDigest().digest(); } - public MD5 getMD5() { - return md5; - } - public long getStreamLength() { return streamLength; } - - //TODO TC-20090711 : do a unit test instead of this main ! -// /** -// * This method is here for testing purposes only - do not rely -// * on it being here. -// * -// * @param arg -// */ -// public static void main(String[] arg) { -// try { -// -// //////////////////////////////////////////////////////////////// -// // -// // usage: java com.twmacinta.util.MD5InputStream [--use-default-md5] [--no-native-lib] filename -// // -// ///////// -// -// // determine the filename to use and the MD5 impelementation to use -// -// String filename = arg[arg.length - 1]; -// boolean use_default_md5 = false; -// boolean use_native_lib = true; -// for (int i = 0; i < arg.length - 1; i++) { -// if (arg[i].equals("--use-default-md5")) { -// use_default_md5 = true; -// } else if (arg[i].equals("--no-native-lib")) { -// use_native_lib = false; -// } -// } -// -// // initialize common variables -// -// byte[] buf = new byte[65536]; -// int num_read; -// -// // Use the default MD5 implementation that comes with Java -// -// if (use_default_md5) { -// InputStream in = new BufferedInputStream(new FileInputStream(filename)); -// java.security.MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); -// while ((num_read = in.read(buf)) != -1) { -// digest.update(buf, 0, num_read); -// } -// System.out.println(MD5.asHex(digest.digest()) + " " + filename); -// in.close(); -// -// // Use the optimized MD5 implementation -// -// } else { -// -// // disable the native library search, if requested -// -// if (!use_native_lib) { -// MD5.initNativeLibrary(true); -// } -// -// // calculate the checksum -// -// MD5InputStream in = new MD5InputStream(new BufferedInputStream(new FileInputStream(filename))); -// while ((num_read = in.read(buf)) != -1); -// System.out.println(MD5.asHex(in.hash()) + " " + filename); -// in.close(); -// } -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } } Modified: trunk/src/main/java/org/nuiton/util/MD5OutputStream.java =================================================================== --- trunk/src/main/java/org/nuiton/util/MD5OutputStream.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/MD5OutputStream.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -18,118 +18,36 @@ */ package org.nuiton.util; -import java.io.*; +import java.io.OutputStream; +import java.security.DigestOutputStream; +import java.security.MessageDigest; -/** - * MD5OutputStream is a subclass of FilterOutputStream adding MD5 - * hashing of the output. - * <p> - * Originally written by Santeri Paavolainen, Helsinki Finland 1996 <br> - * (c) Santeri Paavolainen, Helsinki Finland 1996 <br> - * Some changes Copyright (c) 2002 Timothy W Macinta <br> - * <p> - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * <p> - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * <p> - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * <p> - * See http://www.twmacinta.com/myjava/fast_md5.php for more information - * on this file. - * <p> - * Please note: I (Timothy Macinta) have put this code in the - * com.twmacinta.util package only because it came without a package. I - * was not the the original author of the code, although I did - * optimize it (substantially) and fix some bugs. +/** * - * @author Santeri Paavolainen <santtu@cs.hut.fi> - * @author Timothy W Macinta (twm@alum.mit.edu) (added main() method) - **/ + * + */ -public class MD5OutputStream extends FilterOutputStream { - /** - * MD5 context - */ - private MD5 md5; +public class MD5OutputStream extends DigestOutputStream { /** * Creates MD5OutputStream - * @param out The output stream - */ - - public MD5OutputStream (OutputStream out) { - super(out); - - md5 = new MD5(); - } - - /** - * Writes a byte. * - * @see java.io.FilterOutputStream + * @param out The output stream */ - public void write (int b) throws IOException { - out.write(b); - md5.Update((byte) b); + public MD5OutputStream(OutputStream out) { + super(out, MD5InputStream.getMD5Digest()); } /** - * Writes a sub array of bytes. - * - * @see java.io.FilterOutputStream + * @return array of bytes representing hash of the stream as finalized for + * the current state. + * @see MessageDigest#digest() */ - public void write (byte b[], int off, int len) throws IOException { - out.write(b, off, len); - md5.Update(b, off, len); + public byte[] hash() { + return getMessageDigest().digest(); } - /** - * Returns array of bytes representing hash of the stream as finalized - * for the current state. - * @see MD5#Final - */ - - public byte[] hash () { - return md5.Final(); - } - - public MD5 getMD5() { - return md5; - } - - /* - * This method is here for testing purposes only - do not rely - * on it being here. - * - public static void main(String[] arg) { - try { - MD5OutputStream out = new MD5OutputStream(new com.twmacinta.io.NullOutputStream()); - InputStream in = new BufferedInputStream(new FileInputStream(arg[0])); - byte[] buf = new byte[65536]; - int num_read; - long total_read = 0; - while ((num_read = in.read(buf)) != -1) { - total_read += num_read; - out.write(buf, 0, num_read); - } - System.out.println(MD5.asHex(out.hash())+" "+arg[0]); - in.close(); - out.close(); - } catch (Exception e) { - e.printStackTrace(); - } - }*/ - - } Deleted: trunk/src/main/java/org/nuiton/util/MD5State.java =================================================================== --- trunk/src/main/java/org/nuiton/util/MD5State.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/MD5State.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -1,99 +0,0 @@ -/** - * *##% Nuiton utilities library - * Copyright (C) 2004 - 2009 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%* - */ -package org.nuiton.util; - -/** - * Fast implementation of RSA's MD5 hash generator in Java JDK Beta-2 or higher<br> - * Originally written by Santeri Paavolainen, Helsinki Finland 1996 <br> - * (c) Santeri Paavolainen, Helsinki Finland 1996 <br> - * Some changes Copyright (c) 2002 Timothy W Macinta <br> - * <p> - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * <p> - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * <p> - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * <p> - * See http://www.twmacinta.com/myjava/fast_md5.php for more information - * on this file. - * <p> - * Contains internal state of the MD5 class - * <p> - * Please note: I (Timothy Macinta) have put this code in the - * com.twmacinta.util package only because it came without a package. I - * was not the the original author of the code, although I did - * optimize it (substantially) and fix some bugs. - * - * @author Santeri Paavolainen <sjpaavol@cc.helsinki.fi> - * @author Timothy W Macinta (twm@alum.mit.edu) (optimizations and bug fixes) - @deprecated since 1.1.4 (prefer use jdk implentation instead), will be removed in version 1.2 - */ - -@Deprecated -class MD5State { - /** - * 128-bit state - */ - int state[]; - - /** - * 64-bit character count - */ - long count; - - /** - * 64-byte buffer (512 bits) for storing to-be-hashed characters - */ - byte buffer[]; - - public MD5State() { - buffer = new byte[64]; - count = 0; - state = new int[4]; - - state[0] = 0x67452301; - state[1] = 0xefcdab89; - state[2] = 0x98badcfe; - state[3] = 0x10325476; - - } - - /** Create this State as a copy of another state */ - public MD5State (MD5State from) { - this(); - - int i; - - for (i = 0; i < buffer.length; i++) - this.buffer[i] = from.buffer[i]; - - for (i = 0; i < state.length; i++) - this.state[i] = from.state[i]; - - this.count = from.count; - } -}; Modified: trunk/src/main/java/org/nuiton/util/MonthEnum.java =================================================================== --- trunk/src/main/java/org/nuiton/util/MonthEnum.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/MonthEnum.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -17,6 +17,9 @@ * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%* */ package org.nuiton.util; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import static org.nuiton.i18n.I18n._; /** @@ -26,6 +29,7 @@ */ public enum MonthEnum { + JANUARY(_("nuitonutil.month.january")), FEBRUARY(_("nuitonutil.month.february")), MARCH(_("nuitonutil.month.march")), @@ -39,6 +43,9 @@ NOVEMBER(_("nuitonutil.month.november")), DECEMBER(_("nuitonutil.month.december")); + /** Logger */ + private static final Log log = LogFactory.getLog(MonthEnum.class); + private final String libelle; MonthEnum(String libelle) { @@ -52,12 +59,12 @@ public static MonthEnum valueOf(String month, MonthEnum defaultValue) { MonthEnum monthEnum = null; try { - monthEnum = MonthEnum.valueOf(month.toUpperCase()); - } catch (IllegalArgumentException e) { - System.err.println(_("nuitonutil.error.unfound.month", month, defaultValue)); - } catch (NullPointerException e) { - System.err.println(_("nuitonutil.error.unfound.month", month, defaultValue)); - } + monthEnum = valueOf(month.toUpperCase()); + } catch (Exception e) { + log.error( + _("nuitonutil.error.unfound.month", month, defaultValue), + e); + } return monthEnum == null ? defaultValue : monthEnum; } Modified: trunk/src/main/java/org/nuiton/util/ResourceResolver.java =================================================================== --- trunk/src/main/java/org/nuiton/util/ResourceResolver.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/ResourceResolver.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -27,6 +27,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; import javax.xml.transform.URIResolver; import javax.xml.transform.stream.StreamSource; @@ -50,8 +52,8 @@ * eg: <code>xmi/default-uml14.xmi</code> * <p> * You should assign this ResourceResolver on - * {@link javax.xml.transform.Transformer} but not on - * {@link javax.xml.transform.TransformerFactory}. <br/> + * {@link Transformer} but not on + * {@link TransformerFactory}. <br/> * * @author chorlet * @version $Revision$ @@ -66,7 +68,8 @@ /** * Shared Cache to not search in full classpath at each request. */ - protected static final SortedMap<String, Source> sourceCache = new TreeMap<String, Source>(); + protected static final SortedMap<String, Source> sourceCache = + new TreeMap<String, Source>(); /** * Shared Cache of not local resources */ @@ -74,7 +77,8 @@ /** * le pattern de detection d'une uri */ - public static final Pattern HREF_PATTERN = Pattern.compile("([a-zA-Z]+)\\:\\/\\/(.+)"); + public static final Pattern HREF_PATTERN = + Pattern.compile("([a-zA-Z]+)\\:\\/\\/(.+)"); /** * Pour vider le cache partage. @@ -225,7 +229,7 @@ List<URL> urls = null; URLClassLoader ucl = null; if (cl == null) { - ClassLoader cl2 = this.getClass().getClassLoader(); + ClassLoader cl2 = getClass().getClassLoader(); if (cl2 instanceof URLClassLoader) { ucl = (URLClassLoader) cl2; } @@ -253,7 +257,8 @@ source = new StreamSource(url.toString()); } if (verbose) { - log.info("resolved in " + StringUtil.convertTime(System.nanoTime() - t0)); + String time = StringUtil.convertTime(System.nanoTime() - t0); + log.info("resolved in " + time); } return source; } @@ -281,11 +286,8 @@ log.info("will discover " + resource); } - URL url = null; + URL url = Resource.getURLOrNull(resource); - url = Resource.getURLOrNull(resource); - - Source source = null; if (url != null) { @@ -295,7 +297,8 @@ source = new StreamSource(url.toString()); } if (verbose) { - log.info("resolved in " + StringUtil.convertTime(System.nanoTime() - t0)); + String time = StringUtil.convertTime(System.nanoTime() - t0); + log.info("resolved in " + time); } return source; } Modified: trunk/src/main/java/org/nuiton/util/ReverseFileReader.java =================================================================== --- trunk/src/main/java/org/nuiton/util/ReverseFileReader.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/ReverseFileReader.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -42,19 +42,19 @@ public ReverseFileReader(File file) throws IOException { // Open up a random access file - this.randomfile = new RandomAccessFile(file, "r"); + randomfile = new RandomAccessFile(file, "r"); // Set our seek position to the end of the file - this.position = this.randomfile.length(); + position = randomfile.length(); // Seek to the end of the file - this.randomfile.seek(this.position); + randomfile.seek(position); //Move our pointer to the first valid position at the end of the file. - String thisLine = this.randomfile.readLine(); + String thisLine = randomfile.readLine(); while (thisLine == null) { - this.position--; - this.randomfile.seek(this.position); - thisLine = this.randomfile.readLine(); - this.randomfile.seek(this.position); + position--; + randomfile.seek(position); + thisLine = randomfile.readLine(); + randomfile.seek(position); } } @@ -65,8 +65,9 @@ /** * Read one line from the current position towards the beginning. * - * @return the next line of text from this file, or null if end of file is encountered before even one byte is read. - * @throws IOException + * @return the next line of text from this file, or null if end of file is + * encountered before even one byte is read. + * @throws IOException if any pb while reading line */ public String readLine() throws IOException { int thisCode; @@ -75,42 +76,42 @@ // If our position is less than zero already, we are at the beginning // with nothing to return. - if (this.position < 0) { + if (position < 0) { return null; } for (;;) { // we've reached the beginning of the file - if (this.position < 0) { + if (position < 0) { break; } // Seek to the current position - this.randomfile.seek(this.position); + randomfile.seek(position); // Read the data at this position - thisCode = this.randomfile.readByte(); + thisCode = randomfile.readByte(); thisChar = (char) thisCode; // If this is a line break or carrige return, stop looking if (thisCode == 13 || thisCode == 10) { // See if the previous character is also a line break character. // this accounts for crlf combinations - this.randomfile.seek(this.position - 1); - int nextCode = this.randomfile.readByte(); - if ((thisCode == 10 && nextCode == 13) - || (thisCode == 13 && nextCode == 10)) { + randomfile.seek(position - 1); + int nextCode = randomfile.readByte(); + if (thisCode == 10 && nextCode == 13 + || thisCode == 13 && nextCode == 10) { // If we found another linebreak character, ignore it - this.position = this.position - 1; + position = position - 1; } // Move the pointer for the next readline - this.position--; + position--; break; } else { // This is a valid character append to the string finalLine = thisChar + finalLine; } // Move to the next char - this.position--; + position--; } // return the line return finalLine; @@ -134,4 +135,4 @@ close(); super.finalize(); } -} \ No newline at end of file +} Modified: trunk/src/main/java/org/nuiton/util/SortedProperties.java =================================================================== --- trunk/src/main/java/org/nuiton/util/SortedProperties.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/SortedProperties.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -47,7 +47,8 @@ Vector<Object> result; try { // Attention, si les clef ne sont pas des string, ca ne marchera pas - List<String> list = CollectionUtil.toGenericList(objects, String.class); + List<String> list = CollectionUtil.toGenericList(objects, + String.class); Collections.sort(list); result = new Vector<Object>(list); } catch (IllegalArgumentException e) { Modified: trunk/src/main/java/org/nuiton/util/StreamKeywordTokenizer.java =================================================================== --- trunk/src/main/java/org/nuiton/util/StreamKeywordTokenizer.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/StreamKeywordTokenizer.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -35,6 +35,9 @@ import java.io.IOException; import java.io.Reader; +/** + * TODO What is it for ? + */ public class StreamKeywordTokenizer extends StreamTokenizer { // StreamKeywordTokenizer public static final int TT_KEYWORD = -101; @@ -74,14 +77,15 @@ /** * This method must be call before addKeyword. - */ + * @param fl + */ public void lowerCaseKeyword(boolean fl){ lowerCaseKeyword = fl; } public void quoteCharVariable(int c){ quoteChar(c); - this.quoteCharVariable = c; + quoteCharVariable = c; } } // StreamKeywordTokenizer Modified: trunk/src/main/java/org/nuiton/util/StringUtil.java =================================================================== --- trunk/src/main/java/org/nuiton/util/StringUtil.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/StringUtil.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -30,7 +30,6 @@ import java.awt.Color; import java.lang.reflect.Field; -import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.DateFormat; import java.text.MessageFormat; @@ -39,6 +38,7 @@ import java.util.Arrays; import java.util.Date; import java.util.List; +import java.util.Locale; /** * Classe contenant un ensemle de methode static utiles pour la manipulation des @@ -131,6 +131,7 @@ * @deprecated you must use * org.apache.commons.lang.StringUtils.capitalise(String) */ + @Deprecated public static String capitalize(String word) { return word.substring(0, 1).toUpperCase() + word.substring(1); } @@ -143,6 +144,7 @@ * @deprecated you must use * org.apache.commons.lang.StringUtils.uncapitalise(String) */ + @Deprecated public static String uncapitalize(String word) { return word.substring(0, 1).toLowerCase() + word.substring(1); } @@ -156,6 +158,7 @@ * ou vide, la chaine resultante est une chaine vide. * @deprecated you must use org.apache.commons.lang.StringUtils.join */ + @Deprecated public static String unsplit(String[] s, String sep) { if (s == null || s.length <= 0) { return ""; @@ -203,8 +206,8 @@ * Split string use 'separator' as separator. If String contains "' * and <code>openingChar</code> <code>closingChars</code> * <p/> - * this method count the number of open char end close char to split correctly - * argument + * this method count the number of open char end close char to split + * correctly argument * * @param openingChars list of opening caracteres * @param closingChars list of closing caracteres @@ -244,7 +247,8 @@ // open string " or ' last = c; } else if (op.length() == 0 && - args.regionMatches(i, separator, 0, separator.length())) { + args.regionMatches(i, separator, 0, + separator.length())) { // end of one arguement end = i; // pass separator @@ -367,7 +371,27 @@ return result; } + private static final char[] HEX_CHARS = {'0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f',}; /** + * Turns array of bytes into string representing each byte as + * unsigned hex number. + * + * @param hash Array of bytes to convert to hex-string + * @return Generated hex string + */ + public static String asHex (byte hash[]) { + char buf[] = new char[hash.length * 2]; + for (int i = 0, x = 0; i < hash.length; i++) { + buf[x++] = HEX_CHARS[hash[i] >>> 4 & 0xf]; + buf[x++] = HEX_CHARS[hash[i] & 0xf]; + } + return new String(buf); + } + + /** * Essai de convertir une chaine de caractere en une couleur si possible si * ce n'est pas possible retourne null. * @@ -465,8 +489,9 @@ } /** - * Note: this method use the current locale (the {@link java.util.Locale#getDefault()}) in - * the method {@link MessageFormat#MessageFormat(String)}. + * Note: this method use the current locale + * (the {@link Locale#getDefault()}) in the method + * {@link MessageFormat#MessageFormat(String)}. * * @param value * @param factors @@ -502,7 +527,7 @@ * @param closer le caractère fermant * @return <code>true</code> is la chaine est valide */ - public static boolean checkEnclosure(String txt, final char opener, char closer) { + public static boolean checkEnclosure(String txt, char opener, char closer) { if (txt.indexOf(opener) == -1 && txt.indexOf(closer) == -1) { // ok pas de block détectés return true; @@ -580,18 +605,19 @@ * * @param toEncode string concerned * @return md5 corresponding + * @throws NoSuchAlgorithmException if could not found algorithm MD5 */ public static String encodeMD5(String toEncode) throws NoSuchAlgorithmException { byte[] uniqueKey = toEncode.getBytes(); - byte[] hash = null; - + byte[] hash; // on récupère un objet qui permettra de crypter la chaine - hash = MessageDigest.getInstance("MD5").digest(uniqueKey); + hash = MD5InputStream.getMD5Digest().digest(uniqueKey); +// hash = MessageDigest.getInstance("MD5").digest(uniqueKey); StringBuffer hashString = new StringBuffer(); - for (int i = 0; i < hash.length; ++i) { - String hex = Integer.toHexString(hash[i]); + for (byte aHash : hash) { + String hex = Integer.toHexString(aHash); if (hex.length() == 1) { hashString.append("0"); hashString.append(hex.charAt(hex.length() - 1)); Modified: trunk/src/main/java/org/nuiton/util/TransformedList.java =================================================================== --- trunk/src/main/java/org/nuiton/util/TransformedList.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/TransformedList.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -37,6 +37,10 @@ import java.util.Collection; import java.util.List; +/** + * TODO Wthat is it for ? + * @param <E> + */ public class TransformedList<E> extends AbstractList<E> implements Serializable { // TransformedList private static final long serialVersionUID = 2354881761407900789L; @@ -49,10 +53,11 @@ } this.transformer = transformer; - this.inner = new ArrayList<Object>(); + inner = new ArrayList<Object>(); } - public TransformedList(Transformer<E, ? super Object> transformer, Collection<? extends E> c) { + public TransformedList(Transformer<E, ? super Object> transformer, + Collection<? extends E> c) { this(transformer); addAll(c); } @@ -97,7 +102,8 @@ } @SuppressWarnings("unchecked") - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + private void readObject(ObjectInputStream in) throws IOException, + ClassNotFoundException { in.defaultReadObject(); transformer = (Transformer<E, Object>) in.readObject(); inner = (List<Object>) in.readObject(); Modified: trunk/src/main/java/org/nuiton/util/TransparenteSoftReference.java =================================================================== --- trunk/src/main/java/org/nuiton/util/TransparenteSoftReference.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/TransparenteSoftReference.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -39,8 +39,8 @@ */ public class TransparenteSoftReference<T> extends SoftReference<T> { - protected int hash = 0; - protected String toString = null; + protected int hash; + protected String toString; /** * DOCUMENTME Constructor for the TransparenteSoftReference object @@ -60,7 +60,9 @@ init(o, objectToStringUsed); } - public TransparenteSoftReference(T o, ReferenceQueue<? super T> queue, boolean objectToStringUsed) { + public TransparenteSoftReference(T o, + ReferenceQueue<? super T> queue, + boolean objectToStringUsed) { super(o, queue); init(o, objectToStringUsed); } @@ -68,6 +70,8 @@ /** * On conserve le hash pour que la Reference puisse encore se faire * passer pour l'objet alors que celui-ci a disparu de la memoire + * @param o TODO + * @param objectToStringUsed TODO */ protected void init(T o, boolean objectToStringUsed) { if (o == null) { @@ -78,7 +82,8 @@ toString = o.toString(); } if (toString == null) { - toString = o.getClass().getName() + '@' + Integer.toHexString(hash); + toString = o.getClass().getName() + '@' + + Integer.toHexString(hash); } if (toString.length() > 100) { toString = toString.substring(0, 100) + "..."; @@ -100,12 +105,12 @@ // synchroniser la méthode Object local = get(); if (o instanceof Reference) { - o = ((Reference) o).get(); + o = ((Reference<?>) o).get(); } boolean result = - (o == null && local == null) - || (o != null && o.equals(local)); + o == null && local == null + || o != null && o.equals(local); return result; } Modified: trunk/src/main/java/org/nuiton/util/TransparenteWeakReference.java =================================================================== --- trunk/src/main/java/org/nuiton/util/TransparenteWeakReference.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/TransparenteWeakReference.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -40,8 +40,8 @@ */ public class TransparenteWeakReference<T> extends WeakReference<T> { - protected int hash = 0; - protected String toString = null; + protected int hash; + protected String toString; protected boolean objectToStringUsed = true; public TransparenteWeakReference(T o) { @@ -62,7 +62,9 @@ init(o, objectToStringUsed); } - public TransparenteWeakReference(T o, ReferenceQueue<? super T> queue, boolean objectToStringUsed) { + public TransparenteWeakReference(T o, + ReferenceQueue<? super T> queue, + boolean objectToStringUsed) { super(o, queue); init(o, objectToStringUsed); } @@ -82,7 +84,8 @@ toString = o.toString(); } if (toString == null) { - toString = o.getClass().getName() + '@' + Integer.toHexString(hash); + toString = o.getClass().getName() + '@' + + Integer.toHexString(hash); } if (toString.length() > 100) { toString = toString.substring(0, 100) + "..."; @@ -92,7 +95,8 @@ /** * @param o l'objet a comparer - * @return <code>true</code> si meme reference memoire on les objets references sont egaux + * @return <code>true</code> si meme reference memoire on les objets + * references sont egaux */ @Override public boolean equals(Object o) { @@ -112,8 +116,8 @@ } } - return (other == null && local == null) || - (other != null && other.equals(local)); + return other == null && local == null || + other != null && other.equals(local); } @Override Modified: trunk/src/main/java/org/nuiton/util/URIConverter.java =================================================================== --- trunk/src/main/java/org/nuiton/util/URIConverter.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/URIConverter.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -23,6 +23,7 @@ import java.net.URI; import java.net.URISyntaxException; import org.apache.commons.beanutils.Converter; +import org.apache.commons.logging.Log; /** * classe pour convertir une chaine en un objet URI. @@ -32,12 +33,13 @@ public class URIConverter implements Converter { /** to use log facility, just put in your code: log.info(\"...\"); */ - static org.apache.commons.logging.Log log = getLog(URIConverter.class); + static Log log = getLog(URIConverter.class); @Override public Object convert(Class aClass, Object value) { if (value == null) { - throw new ConversionException(_("nuitonutil.error.convertor.noValue", this)); + throw new ConversionException( + _("nuitonutil.error.convertor.noValue", this)); } if (isEnabled(aClass)) { Object result; @@ -50,7 +52,8 @@ return result; } } - throw new ConversionException(_("nuitonutil.error.no.convertor", aClass.getName(), value)); + throw new ConversionException( + _("nuitonutil.error.no.convertor", aClass.getName(), value)); } protected URI valueOf(String value) { @@ -59,7 +62,8 @@ result = new URI(value); return result; } catch (URISyntaxException e) { - throw new ConversionException(_("nuitonutil.error.url.convertor", value, this, e.getMessage())); + throw new ConversionException( + _("nuitonutil.error.url.convertor", value, this, e.getMessage())); } } @@ -70,7 +74,7 @@ } protected boolean isEnabled(Class<?> aClass) { - return aClass == URI.class; + return URI.class.equals(aClass); } public Class<?> getType() { Modified: trunk/src/main/java/org/nuiton/util/URLConverter.java =================================================================== --- trunk/src/main/java/org/nuiton/util/URLConverter.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/URLConverter.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -24,6 +24,7 @@ import java.net.MalformedURLException; import java.net.URL; import org.apache.commons.beanutils.Converter; +import org.apache.commons.logging.Log; /** * classe pour convertir une chaine en un objet URL. @@ -33,12 +34,13 @@ public class URLConverter implements Converter { /** to use log facility, just put in your code: log.info(\"...\"); */ - static org.apache.commons.logging.Log log = getLog(URLConverter.class); + static Log log = getLog(URLConverter.class); @Override public Object convert(Class aClass, Object value) { if (value == null) { - throw new ConversionException(_("nuitonutil.error.convertor.noValue", this)); + throw new ConversionException( + _("nuitonutil.error.convertor.noValue", this)); } if (isEnabled(aClass)) { Object result; @@ -51,7 +53,8 @@ return result; } } - throw new ConversionException(_("nuitonutil.error.no.convertor", aClass.getName(), value)); + throw new ConversionException( + _("nuitonutil.error.no.convertor", aClass.getName(), value)); } protected URL valueOf(String value) { @@ -60,7 +63,8 @@ result = new URL(value); return result; } catch (MalformedURLException e) { - throw new ConversionException(_("nuitonutil.error.url.convertor", value, this, e.getMessage())); + throw new ConversionException( + _("nuitonutil.error.url.convertor", value, this, e.getMessage())); } } @@ -69,7 +73,7 @@ } protected boolean isEnabled(Class<?> aClass) { - return aClass == URL.class; + return URL.class.equals(aClass); } public Class<?> getType() { Modified: trunk/src/main/java/org/nuiton/util/Version.java =================================================================== --- trunk/src/main/java/org/nuiton/util/Version.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/Version.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -47,10 +47,12 @@ * * - the class is comparable, using the natural version order : * - * <pre>0 < 0.1 < 1 < 1.0 < 1.1-alpha-0 < 1.1-alpha-1 < 1.1-beta-0 < 1.1-rc-1 < 1.1 </pre> + * <pre>0 < 0.1 < 1 < 1.0 < 1.1-alpha-0 < 1.1-alpha-1 < 1.1-beta-0 < + * 1.1-rc-1 < 1.1 </pre> * * - the class is immutable, you should not instanciate directly a Version, - * but prefer use the factory static methods <code>VersionUtil.valueOf(...)</code> instead. + * but prefer use the factory static methods + * <code>VersionUtil.valueOf(...)</code> instead. * * @author chemit * @since 1.1.0 @@ -75,7 +77,8 @@ */ protected final int[] numbers; /** - * representation textuelle de la version (celle utilisee dans le {@link #toString()}. + * representation textuelle de la version (celle utilisee dans le + * {@link #toString()}. */ protected transient String version; @@ -99,14 +102,16 @@ * Constructeur d'une version (simple ou avec classifier) * * @param classifier le classifier (peut-être null) - * @param classiferNumber la version du classifier (doit etre null si le classifier est null) + * @param classiferNumber la version du classifier (doit etre null si le + * classifier est null) * @param numbers les nombres de la version */ public Version(String classifier, Integer classiferNumber, int... numbers) { this.numbers = numbers.length == 0 ? new int[]{0} : numbers; // always keep a lower case classifier - this.classifier = classifier == null ? null : classifier.trim().toLowerCase(); - this.classifierNumber = classiferNumber; + this.classifier = classifier == null ? null : + classifier.trim().toLowerCase(); + classifierNumber = classiferNumber; } /** @@ -125,7 +130,8 @@ if (!matcher.matches()) { // not a known pattern - throw new IllegalArgumentException(_("nuitonutil.error.version.pattern", version)); + throw new IllegalArgumentException( + _("nuitonutil.error.version.pattern", version)); } // get numbers as string @@ -143,7 +149,7 @@ } // numbers - this.numbers = new int[strNumbers.length]; + numbers = new int[strNumbers.length]; for (int i = 0, j = strNumbers.length; i < j; i++) { String number = strNumbers[i].trim(); @@ -151,10 +157,10 @@ } // classifier - this.classifier = strClassifier; + classifier = strClassifier; // classifier number - this.classifierNumber = intClassifierNumber; + classifierNumber = intClassifierNumber; } public int[] getNumbers() { @@ -179,7 +185,9 @@ public int getNumber(int level) { if (level < 0 || level >= numbers.length) { - throw new IllegalArgumentException("not a valid level " + level + " for the VersionNumber " + this); + throw new IllegalArgumentException( + "not a valid level " + level + " for the VersionNumber " + + this); } return numbers[level]; } @@ -191,7 +199,10 @@ sb.append('.').append(number); } if (hasClassifier()) { - sb.append('-').append(classifier).append('-').append(classifierNumber); + sb.append('-'); + sb.append(classifier); + sb.append('-'); + sb.append(classifierNumber); } version = sb.substring(1); } @@ -257,7 +268,8 @@ @Override public boolean equals(Object obj) { - return obj != null && (obj instanceof Version) && getVersion().equals(((Version) obj).getVersion()); + return obj != null && obj instanceof Version && + getVersion().equals(((Version) obj).getVersion()); } @Override Modified: trunk/src/main/java/org/nuiton/util/VersionConverter.java =================================================================== --- trunk/src/main/java/org/nuiton/util/VersionConverter.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/VersionConverter.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -19,6 +19,7 @@ import org.apache.commons.beanutils.ConversionException; import org.apache.commons.beanutils.Converter; +import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import static org.nuiton.i18n.I18n._; @@ -31,7 +32,7 @@ public class VersionConverter implements Converter { /** to use log facility, just put in your code: log.info(\"...\"); */ - private static final org.apache.commons.logging.Log log = LogFactory.getLog(VersionConverter.class); + private static final Log log = LogFactory.getLog(VersionConverter.class); public VersionConverter() { if (log.isDebugEnabled()) { @@ -42,7 +43,8 @@ @Override public Object convert(Class aClass, Object value) { if (value == null) { - throw new ConversionException(_("nuitonutil.error.convertor.noValue", this)); + throw new ConversionException( + _("nuitonutil.error.convertor.noValue", this)); } if (isEnabled(aClass)) { Object result; @@ -55,15 +57,17 @@ result = VersionUtil.valueOf((String) value); return result; } catch (IllegalArgumentException e) { - throw new ConversionException(_("nuitonutil.error.version.convertor", value, this, e.getMessage()), e); + throw new ConversionException( + _("nuitonutil.error.version.convertor", value, this, e.getMessage()), e); } } } - throw new ConversionException(_("nuitonutil.error.no.convertor", aClass.getName(), value)); + throw new ConversionException( + _("nuitonutil.error.no.convertor", aClass.getName(), value)); } protected boolean isEnabled(Class<?> aClass) { - return aClass == Version.class; + return Version.class.equals(aClass); } public Class<?> getType() { Modified: trunk/src/main/java/org/nuiton/util/VersionUtil.java =================================================================== --- trunk/src/main/java/org/nuiton/util/VersionUtil.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/VersionUtil.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -52,13 +52,15 @@ * * Dans le cas d'une version simple (sans classifier), le groupe 2 et 3 sont null. */ - public static final Pattern VERSION_PATTERN = Pattern.compile("^(\\d+(?:\\.(?:\\d+))*)(?:-(\\w+?)-(\\d+?)){0,1}$"); + public static final Pattern VERSION_PATTERN = + Pattern.compile("^(\\d+(?:\\.(?:\\d+))*)(?:-(\\w+?)-(\\d+?)){0,1}$"); /** * Shared instance of default version comparator. * * @see VersionComparator */ - public static final VersionComparator DEFAULT_VERSION_COMPARATOR = new VersionComparator(); + public static final VersionComparator DEFAULT_VERSION_COMPARATOR = + new VersionComparator(); /** * The snapshot suffix. */ @@ -83,7 +85,8 @@ * @param numbers les nombres de la version * @return l'instance de la version requise */ - public static Version valueOf(String classifier, Integer classifierNumber, int... numbers) { + public static Version valueOf(String classifier, + Integer classifierNumber, int... numbers) { Version v = new Version(classifier, classifierNumber, numbers); return v; } @@ -110,7 +113,10 @@ * @throws NullPointerException si le classifier ou le classifierNumber est null. * @throws IllegalArgumentException si la version donnee contient deja un classifier. */ - public static Version addClassifier(Version version, String classifier, Integer classifierNumber) throws NullPointerException, IllegalArgumentException { + public static Version addClassifier(Version version, + String classifier, + Integer classifierNumber) + throws NullPointerException, IllegalArgumentException { Version result; if (classifier == null) { throw new NullPointerException("classifier can not be null"); @@ -119,7 +125,8 @@ throw new NullPointerException("classifierNumber can not be null"); } if (version.hasClassifier()) { - throw new IllegalArgumentException("version " + version + "contains already a classifier "); + throw new IllegalArgumentException( + "version " + version + "contains already a classifier "); } result = valueOf(classifier, classifierNumber, version.getNumbers()); @@ -132,12 +139,15 @@ * * @param version la version de base (avec classifier) * @return l'instance de la version requise - * @throws IllegalArgumentException si la version donnee contient deja un classifier. + * @throws IllegalArgumentException si la version donnee contient deja + * un classifier. */ - public static Version removeClassifier(Version version) throws IllegalArgumentException { + public static Version removeClassifier(Version version) + throws IllegalArgumentException { Version result; if (!version.hasClassifier()) { - throw new IllegalArgumentException("version " + version + "does no contain a classifier "); + throw new IllegalArgumentException( + "version " + version + "does no contain a classifier "); } result = valueOf(version.getNumbers()); return result; @@ -165,7 +175,8 @@ newNumbers[nbComponents - 1] = newNumbers[nbComponents - 1] + 1; } - Version result = valueOf(newClassifier, newClassifierNumber, newNumbers); + Version result = valueOf(newClassifier, newClassifierNumber, + newNumbers); return result; } @@ -178,7 +189,8 @@ * without the <code>-SNAPSHOT</code> suffix (if any). * @throws NullPointerException if version is null */ - public static String removeSnapshot(String version) throws NullPointerException { + public static String removeSnapshot(String version) + throws NullPointerException { if (version == null) { throw new NullPointerException("version parameter can not be null"); } @@ -199,14 +211,18 @@ * @param includeMax flag to include max version * @return versions between min and max */ - public static List<Version> filterVersions(Set<Version> versions, Version min, Version max, boolean includeMin, boolean includeMax) { + public static List<Version> filterVersions(Set<Version> versions, + Version min, + Version max, + boolean includeMin, + boolean includeMax) { List<Version> toApply = new ArrayList<Version>(); for (Version v : versions) { int t; if (min != null) { t = v.compareTo(min); // if (v.compareTo(min) <= 0) { - if (t < 0 || (t == 0 && !includeMin)) { + if (t < 0 || t == 0 && !includeMin) { // version trop ancienne continue; } @@ -214,7 +230,7 @@ if (max != null) { t = v.compareTo(max); // if (v.compareTo(max) > 0) { - if (t > 0 || (t == 0 && !includeMax)) { + if (t > 0 || t == 0 && !includeMax) { // version trop recente continue; } @@ -232,15 +248,15 @@ * * 1) Si versions égales, on quitte. * - * 2) On teste l'ordre des nombres {@link #compareNumbers(org.nuiton.util.Version, org.nuiton.util.Version)} + * 2) On teste l'ordre des nombres {@link #compareNumbers(Version, Version)} * * Si différent, alors versions différentes, on quitte * - * 3) On teste l'ordre des classifiers {@link #compareClassifier(org.nuiton.util.Version, org.nuiton.util.Version)} + * 3) On teste l'ordre des classifiers {@link #compareClassifier(Version, Version)} * * Si différent, alors versions différentes, on quitte * - * 4) On teste l'ordre des versions de classifiers {@link #compareClassifierNumber(org.nuiton.util.Version, org.nuiton.util.Version)}. + * 4) On teste l'ordre des versions de classifiers {@link #compareClassifierNumber(Version, Version)}. * */ public static class VersionComparator implements Comparator<Version> { @@ -337,16 +353,15 @@ * @param args les versions */ public static void main(String... args) { - //System.err.println(VersionUtil.class.getName() + "#main(" + Arrays.asList(args) + ")"); - //I18n.init(); List<Version> list = new ArrayList<Version>(); List<Version> snapshots = new ArrayList<Version>(); for (String a : args) { //System.err.println("convert value : " + a); if (a.endsWith("-SNAPSHOT")) { - snapshots.add(valueOf(a.substring(0, a.length() - "-SNAPSHOT".length()))); + snapshots.add(valueOf( + a.substring(0, a.length() - "-SNAPSHOT".length()))); continue; } Version v = valueOf(a); Modified: trunk/src/main/java/org/nuiton/util/ZipStreamEncoder.java =================================================================== --- trunk/src/main/java/org/nuiton/util/ZipStreamEncoder.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/ZipStreamEncoder.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -25,6 +25,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** @@ -33,7 +34,7 @@ public class ZipStreamEncoder extends Thread { /** to use log facility, just put in your code: log.info(\"...\"); */ - static private org.apache.commons.logging.Log log = LogFactory.getLog(ZipStreamEncoder.class); + static private Log log = LogFactory.getLog(ZipStreamEncoder.class); /** The Constant BUFFER. */ static final int BUFFER = 2048; @@ -53,7 +54,6 @@ * the os */ public ZipStreamEncoder(Map<String, InputStream> files, OutputStream os) { - super(); this.files = files; zos = new ZipOutputStream(os); Modified: trunk/src/main/java/org/nuiton/util/ZipUtil.java =================================================================== --- trunk/src/main/java/org/nuiton/util/ZipUtil.java 2010-03-10 10:09:23 UTC (rev 1793) +++ trunk/src/main/java/org/nuiton/util/ZipUtil.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -17,6 +17,7 @@ package org.nuiton.util; +import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.BufferedInputStream; @@ -51,7 +52,7 @@ public class ZipUtil { /** Class logger. */ - private static org.apache.commons.logging.Log log = LogFactory.getLog(ZipUtil.class); + private static Log log = LogFactory.getLog(ZipUtil.class); /** Taille du buffer pour les lectures/écritures. */ private static final int BUFFER_SIZE = 8 * 1024; @@ -103,7 +104,10 @@ * @return return last entry name * @throws IOException if any problem while uncompressing */ - public static String uncompressAndRename(File file, File targetDir, String renameFrom, String renameTo) throws IOException { + public static String uncompressAndRename(File file, + File targetDir, + String renameFrom, + String renameTo) throws IOException { String result = ""; ZipInputStream in = new ZipInputStream(new FileInputStream(file)); ZipEntry entry; @@ -122,12 +126,15 @@ } else { target.getParentFile().mkdirs(); OutputStream out = new BufferedOutputStream(new FileOutputStream(target)); - byte[] buffer = new byte[BUFFER_SIZE]; - int len; - while ((len = in.read(buffer, 0, BUFFER_SIZE)) != -1) { - out.write(buffer, 0, len); + try { + byte[] buffer = new byte[BUFFER_SIZE]; + int len; + while ((len = in.read(buffer, 0, BUFFER_SIZE)) != -1) { + out.write(buffer, 0, len); + } + } finally { + out.close(); } - out.close(); } } in.close(); @@ -142,9 +149,12 @@ * @param root for all file in includes that is in this directory, then we * remove this directory in zip entry name (aka -C for tar), can be null; * @param includes the files to include in zip - * @throws java.io.IOException if any problem while compressing + * @throws IOException if any problem while compressing */ - public static void compressFiles(File zipFile, File root, Collection<File> includes) throws IOException { + public static void compressFiles(File zipFile, + File root, + Collection<File> includes) throws + IOException { compressFiles(zipFile, root, includes, false); } @@ -159,7 +169,10 @@ * @param createMD5 also create a MD5 file (zip name + .md5). MD5 file is created after zip. * @throws IOException if any problem while compressing */ - public static void compressFiles(File zipFile, File root, Collection<File> includes, boolean createMD5) throws IOException { + public static void compressFiles(File zipFile, + File root, + Collection<File> includes, + boolean createMD5) throws IOException { OutputStream oStream = new FileOutputStream(zipFile); // if md5 creation flag @@ -182,10 +195,14 @@ int bytesIn; BufferedInputStream bis = new BufferedInputStream( new FileInputStream(file), BUFFER_SIZE); - while ((bytesIn = bis.read(readBuffer, 0, BUFFER_SIZE)) != -1) { - zipOStream.write(readBuffer, 0, bytesIn); + try { + while ((bytesIn = + bis.read(readBuffer, 0, BUFFER_SIZE)) != -1) { + zipOStream.write(readBuffer, 0, bytesIn); + } + } finally { + bis.close(); } - bis.close(); } zipOStream.closeEntry(); } @@ -193,7 +210,7 @@ // if md5 creation flag if (createMD5) { - String md5hash = MD5.asHex(((MD5OutputStream)oStream).hash()); + String md5hash = StringUtil.asHex(((MD5OutputStream)oStream).hash()); File md5File = new File(zipFile.getAbsoluteFile() + ".md5"); FileUtil.writeString(md5File, md5hash); } @@ -213,7 +230,8 @@ * @param fileOrDirectory the file or directory to compress * @throws IOException if any problem while compressing */ - public static void compress(File zipFile, File fileOrDirectory) throws IOException { + public static void compress(File zipFile, + File fileOrDirectory) throws IOException { compress(zipFile, fileOrDirectory, null, false); } @@ -229,7 +247,9 @@ * @param filter used to accept file, if null, all file is accepted * @throws IOException if any problem while compressing */ - public static void compress(File zipFile, File fileOrDirectory, FileFilter filter) throws IOException { + public static void compress(File zipFile, + File fileOrDirectory, + FileFilter filter) throws IOException { compress(zipFile, fileOrDirectory, filter, false); } @@ -246,7 +266,10 @@ * @param createMD5 also create a MD5 file (zip name + .md5). MD5 file is created after zip. * @throws IOException if any problem while compressing */ - public static void compress(File zipFile, File fileOrDirectory, FileFilter filter, boolean createMD5) throws IOException { + public static void compress(File zipFile, + File fileOrDirectory, + FileFilter filter, + boolean createMD5) throws IOException { if (filter == null) { filter = ALL_FILE_FILTER; } @@ -257,7 +280,8 @@ files.add(fileOrDirectory); } - compressFiles(zipFile, fileOrDirectory.getParentFile(), files, createMD5); + compressFiles(zipFile, fileOrDirectory.getParentFile(), files, + createMD5); } /** @@ -312,13 +336,17 @@ * (only use if <code>targetDir</code> is not * <code>null</code>) * @param excludeFilter used to exclude some files - * @param renameFrom {@link #uncompressAndRename(java.io.File, java.io.File, String, String)} - * @param renameTo {@link #uncompressAndRename(java.io.File, java.io.File, String, String)} + * @param renameFrom {@link #uncompressAndRename(File, File, String, String)} + * @param renameTo {@link #uncompressAndRename(File, File, String, String)} * @throws IOException if any exception while dealing with zipfile */ - public static void scan(File zipFile, File targetDir, List<String> newFiles, - List<String> existingFiles, FileFilter excludeFilter, String renameFrom, String renameTo) - throws IOException { + public static void scan(File zipFile, + File targetDir, + List<String> newFiles, + List<String> existingFiles, + FileFilter excludeFilter, + String renameFrom, + String renameTo) throws IOException { ZipFile zip = null; try { zip = new ZipFile(zipFile); @@ -350,13 +378,17 @@ } @SuppressWarnings({"unchecked"}) - public static List<String>[] scanAndExplodeZip(File source, File root, FileFilter excludeFilter) throws IOException { + public static List<String>[] scanAndExplodeZip(File source, + File root, + FileFilter excludeFilter) + throws IOException { List<String> overwrittenFiles = new ArrayList<String>(); List<String> newFiles = new ArrayList<String>(); // obtain list of relative paths (to add or overwrite) - scan(source, root, newFiles, overwrittenFiles, excludeFilter, null, null); + scan(source, root, newFiles, overwrittenFiles, excludeFilter, null, + null); return new List[]{newFiles, overwrittenFiles}; } @@ -377,50 +409,61 @@ * @return return last entry name * @throws IOException if nay exception while operation */ - public static String uncompress(File file, File targetDir, List<String> toTreate, String renameFrom, String renameTo) throws IOException { - String result = ""; - ZipInputStream in = new ZipInputStream(new FileInputStream(file)); - ZipEntry entry; + public static String uncompress(File file, + File targetDir, + List<String> toTreate, + String renameFrom, + String renameTo) throws IOException { if (toTreate == null || toTreate.isEmpty()) { - return ZipUtil.uncompressAndRename(file, targetDir, renameFrom, renameTo); + return uncompressAndRename(file, targetDir, renameFrom, renameTo); } boolean rename = renameFrom != null && renameTo != null; - while ((entry = in.getNextEntry()) != null) { - String name = entry.getName(); - if (rename) { - result = convertToLocalEntryName(name.replaceAll(renameFrom, renameTo)); - } else { - result = convertToLocalEntryName(name); - } + String result = ""; + ZipEntry entry; + ZipInputStream in = new ZipInputStream(new FileInputStream(file)); + try { + while ((entry = in.getNextEntry()) != null) { + String name = entry.getName(); + if (rename) { + result = convertToLocalEntryName(name.replaceAll(renameFrom, + renameTo)); + } else { + result = convertToLocalEntryName(name); + } - if (log.isDebugEnabled()) { - log.debug("open [" + name + "] : " + result); - } - if (!toTreate.contains(result)) { - continue; - } + if (log.isDebugEnabled()) { + log.debug("open [" + name + "] : " + result); + } + if (!toTreate.contains(result)) { + continue; + } - if (log.isDebugEnabled()) { - log.debug("copy [" + name + "] : " + result); - } - File target = new File(targetDir, result); - if (entry.isDirectory()) { - target.mkdirs(); - } else { - target.getParentFile().mkdirs(); - OutputStream out = - new BufferedOutputStream(new FileOutputStream(target)); - byte[] buffer = new byte[BUFFER_SIZE]; - int len; - while ((len = in.read(buffer, 0, BUFFER_SIZE)) != -1) { - out.write(buffer, 0, len); + if (log.isDebugEnabled()) { + log.debug("copy [" + name + "] : " + result); } - out.close(); + File target = new File(targetDir, result); + if (entry.isDirectory()) { + target.mkdirs(); + } else { + target.getParentFile().mkdirs(); + OutputStream out =new BufferedOutputStream( + new FileOutputStream(target)); + try { + byte[] buffer = new byte[BUFFER_SIZE]; + int len; + while ((len = in.read(buffer, 0, BUFFER_SIZE)) != -1) { + out.write(buffer, 0, len); + } + } finally { + out.close(); + } + } } + } finally { + in.close(); } - in.close(); return result; } @@ -432,7 +475,9 @@ * @param excludes excludes pattern (pattern must match complete entry name including root folder) * @throws IOException */ - public static void uncompressFiltred(File file, File targetDir, String... excludes) throws IOException { + public static void uncompressFiltred(File file, + File targetDir, + String... excludes) throws IOException { ZipFile zipFile = new ZipFile(file); @@ -458,17 +503,24 @@ target.mkdirs(); } else { // get inputstream only here + target.getParentFile().mkdirs(); InputStream in = zipFile.getInputStream(entry); - target.getParentFile().mkdirs(); - OutputStream out = new BufferedOutputStream(new FileOutputStream(target)); - byte[] buffer = new byte[8 * 1024]; - int len; - - while ((len = in.read(buffer, 0, 8 * 1024)) != -1) { - out.write(buffer, 0, len); + try { + OutputStream out = new BufferedOutputStream( + new FileOutputStream(target)); + try { + byte[] buffer = new byte[8 * 1024]; + int len; + + while ((len = in.read(buffer, 0, 8 * 1024)) != -1) { + out.write(buffer, 0, len); + } + } finally { + out.close(); + } + } finally { + in.close(); } - out.close(); - in.close(); } } } Added: trunk/src/test/java/org/nuiton/util/MD5InputStreamTest.java =================================================================== --- trunk/src/test/java/org/nuiton/util/MD5InputStreamTest.java (rev 0) +++ trunk/src/test/java/org/nuiton/util/MD5InputStreamTest.java 2010-03-10 10:31:32 UTC (rev 1794) @@ -0,0 +1,986 @@ +package org.nuiton.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Test; + +import java.io.*; +import java.net.URL; + +/** + * @author tchemit <chemit@codelutin.com> + * @since 1.2 + */ +public class MD5InputStreamTest { + + /** Logger */ + private static final Log log = LogFactory.getLog(MD5InputStreamTest.class); + + public static class MD5InputStreamOld extends FilterInputStream { + + /** MD5 context */ + protected MD5 md5; + + protected long streamLength; + + /** + * Creates a MD5InputStream + * + * @param in The input stream + */ + public MD5InputStreamOld(InputStream in) { + super(in); + + md5 = new MD5(); + } + + @Override + public int read() throws IOException { + int c = in.read(); + + if (c == -1) { + return -1; + } + + if ((c & ~0xff) != 0) { + log.warn("MD5InputStream.read() got character with (c & ~0xff) != 0)!"); + } else { + streamLength++; + md5.Update(c); + } + + return c; + } + + @Override + public int read(byte bytes[], int offset, int length) throws IOException { + int r; + + if ((r = in.read(bytes, offset, length)) == -1) { + return r; + } + streamLength += r; + + md5.Update(bytes, offset, r); + + return r; + } + + /** + * Returns array of bytes representing hash of the stream as finalized + * for the current state. + * + * @return hash + * @see MD5#Final + */ + public byte[] hash() { + return md5.Final(); + } + + public MD5 getMD5() { + return md5; + } + + public long getStreamLength() { + return streamLength; + } + } + + byte[] oldBytes; + + long oldLength; + + byte[] newBytes; + + long newLength; + + @Test + public void testRead() throws Exception { + + String txt = "jfdjskfjsdkljfdjfklsdjlfsdjlfjsdlfjlsdjlfsdjljklfsd"; + + buildMD5_old(new ByteArrayInputStream(txt.getBytes())); + + buildMD5_new(new ByteArrayInputStream(txt.getBytes())); + + assertMD5(); + + URL resource = getClass().getResource("/zip/test-uncompress.zip"); + + Assert.assertNotNull(resource); + + if (log.isInfoEnabled()) { + log.info(resource + " to test"); + } + + if (log.isInfoEnabled()) { + log.info("compute 10 times (new then old)"); + } + for (int i=0;i<10;i++) { + buildMD5_new(resource.openStream()); + buildMD5_old(resource.openStream()); + + assertMD5(); + } + if (log.isInfoEnabled()) { + log.info("compute 10 times (old then new)"); + } + for (int i=0;i<10;i++) { + buildMD5_old(resource.openStream()); + buildMD5_new(resource.openStream()); + + assertMD5(); + } + } + + protected void assertMD5() { + + Assert.assertNotNull(oldBytes); + Assert.assertNotNull(newBytes); + + Assert.assertEquals(oldLength, newLength); + + Assert.assertEquals(oldBytes.length, newBytes.length); + for (int i = 0, j = oldBytes.length; i < j; i++) { + byte oldB = oldBytes[i]; + byte newB = newBytes[i]; + Assert.assertEquals(oldB, newB); + } + } + + protected static final String logFormat = "computed for length %1$5d : %2$s"; + + protected void buildMD5_old(InputStream in) throws IOException { + + oldLength = -1; + oldBytes = null; + long t0 = System.nanoTime(); + MD5InputStreamOld md5Stream = new MD5InputStreamOld(in); + try { + while (md5Stream.read() != -1) { + // read me + } + + oldLength = md5Stream.getStreamLength(); + oldBytes = md5Stream.hash(); + } catch (IOException e) { + if (log.isDebugEnabled()) { + log.debug(e); + } + throw e; + } finally { + if (log.isInfoEnabled()) { + String message = String.format( + logFormat, + oldLength, + StringUtil.convertTime(System.nanoTime() - t0)); + log.info(message); + } + md5Stream.close(); + } + } + + protected void buildMD5_new(InputStream in) throws IOException { + newLength = -1; + newBytes = null; + long t0 = System.nanoTime(); + MD5InputStream md5Stream = new MD5InputStream(in); + try { + while (md5Stream.read() != -1) { + // read me + } + + newLength = md5Stream.getStreamLength(); + newBytes = md5Stream.hash(); + } catch (IOException e) { + if (log.isDebugEnabled()) { + log.debug(e); + } + throw e; + } finally { + if (log.isInfoEnabled()) { + String message = String.format( + logFormat, + newLength, + StringUtil.convertTime(System.nanoTime() - t0)); + log.info(message); + } + md5Stream.close(); + } + } + + + static class MD5State { + /** 128-bit state */ + int state[]; + + /** 64-bit character count */ + long count; + + /** 64-byte buffer (512 bits) for storing to-be-hashed characters */ + byte buffer[]; + + public MD5State() { + buffer = new byte[64]; + count = 0; + state = new int[4]; + + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; + + } + + /** Create this State as a copy of another state */ + public MD5State(MD5State from) { + this(); + + int i; + + for (i = 0; i < buffer.length; i++) { + this.buffer[i] = from.buffer[i]; + } + + for (i = 0; i < state.length; i++) { + this.state[i] = from.state[i]; + } + + this.count = from.count; + } + } + + + public static class MD5 { + + /** + * MD5 state + **/ + MD5State state; + + /** + * If Final() has been called, finals is set to the current finals + * state. Any Update() causes this to be set to null. + **/ + MD5State finals; + + /** + * Padding for Final() + **/ + static byte padding[] = { + (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + private static boolean native_lib_loaded = false; + private static boolean native_lib_init_pending = true; + + /** + * Initialize MD5 internal state (object can be reused just by + * calling Init() after every Final() + **/ + public synchronized void Init () { + state = new MD5State(); + finals = null; + } + + /** + * Class constructor + **/ + public MD5 () { + if (native_lib_init_pending) _initNativeLibrary(); + this.Init(); + } + + /** + * Initialize class, and update hash with ob.toString() + * + * @param ob Object, ob.toString() is used to update hash + * after initialization + **/ + public MD5 (Object ob) { + this(); + Update(ob.toString()); + } + + private void Decode (byte buffer[], int shift, int[] out) { + /*len += shift; + for (int i = 0; shift < len; i++, shift += 4) { + out[i] = ((int) (buffer[shift] & 0xff)) | + (((int) (buffer[shift + 1] & 0xff)) << 8) | + (((int) (buffer[shift + 2] & 0xff)) << 16) | + (((int) buffer[shift + 3]) << 24); + }*/ + + // unrolled loop (original loop shown above) + + out[0] = ((int) (buffer[shift] & 0xff)) | + (((int) (buffer[shift + 1] & 0xff)) << 8) | + (((int) (buffer[shift + 2] & 0xff)) << 16) | + (((int) buffer[shift + 3]) << 24); + out[1] = ((int) (buffer[shift + 4] & 0xff)) | + (((int) (buffer[shift + 5] & 0xff)) << 8) | + (((int) (buffer[shift + 6] & 0xff)) << 16) | + (((int) buffer[shift + 7]) << 24); + out[2] = ((int) (buffer[shift + 8] & 0xff)) | + (((int) (buffer[shift + 9] & 0xff)) << 8) | + (((int) (buffer[shift + 10] & 0xff)) << 16) | + (((int) buffer[shift + 11]) << 24); + out[3] = ((int) (buffer[shift + 12] & 0xff)) | + (((int) (buffer[shift + 13] & 0xff)) << 8) | + (((int) (buffer[shift + 14] & 0xff)) << 16) | + (((int) buffer[shift + 15]) << 24); + out[4] = ((int) (buffer[shift + 16] & 0xff)) | + (((int) (buffer[shift + 17] & 0xff)) << 8) | + (((int) (buffer[shift + 18] & 0xff)) << 16) | + (((int) buffer[shift + 19]) << 24); + out[5] = ((int) (buffer[shift + 20] & 0xff)) | + (((int) (buffer[shift + 21] & 0xff)) << 8) | + (((int) (buffer[shift + 22] & 0xff)) << 16) | + (((int) buffer[shift + 23]) << 24); + out[6] = ((int) (buffer[shift + 24] & 0xff)) | + (((int) (buffer[shift + 25] & 0xff)) << 8) | + (((int) (buffer[shift + 26] & 0xff)) << 16) | + (((int) buffer[shift + 27]) << 24); + out[7] = ((int) (buffer[shift + 28] & 0xff)) | + (((int) (buffer[shift + 29] & 0xff)) << 8) | + (((int) (buffer[shift + 30] & 0xff)) << 16) | + (((int) buffer[shift + 31]) << 24); + out[8] = ((int) (buffer[shift + 32] & 0xff)) | + (((int) (buffer[shift + 33] & 0xff)) << 8) | + (((int) (buffer[shift + 34] & 0xff)) << 16) | + (((int) buffer[shift + 35]) << 24); + out[9] = ((int) (buffer[shift + 36] & 0xff)) | + (((int) (buffer[shift + 37] & 0xff)) << 8) | + (((int) (buffer[shift + 38] & 0xff)) << 16) | + (((int) buffer[shift + 39]) << 24); + out[10] = ((int) (buffer[shift + 40] & 0xff)) | + (((int) (buffer[shift + 41] & 0xff)) << 8) | + (((int) (buffer[shift + 42] & 0xff)) << 16) | + (((int) buffer[shift + 43]) << 24); + out[11] = ((int) (buffer[shift + 44] & 0xff)) | + (((int) (buffer[shift + 45] & 0xff)) << 8) | + (((int) (buffer[shift + 46] & 0xff)) << 16) | + (((int) buffer[shift + 47]) << 24); + out[12] = ((int) (buffer[shift + 48] & 0xff)) | + (((int) (buffer[shift + 49] & 0xff)) << 8) | + (((int) (buffer[shift + 50] & 0xff)) << 16) | + (((int) buffer[shift + 51]) << 24); + out[13] = ((int) (buffer[shift + 52] & 0xff)) | + (((int) (buffer[shift + 53] & 0xff)) << 8) | + (((int) (buffer[shift + 54] & 0xff)) << 16) | + (((int) buffer[shift + 55]) << 24); + out[14] = ((int) (buffer[shift + 56] & 0xff)) | + (((int) (buffer[shift + 57] & 0xff)) << 8) | + (((int) (buffer[shift + 58] & 0xff)) << 16) | + (((int) buffer[shift + 59]) << 24); + out[15] = ((int) (buffer[shift + 60] & 0xff)) | + (((int) (buffer[shift + 61] & 0xff)) << 8) | + (((int) (buffer[shift + 62] & 0xff)) << 16) | + (((int) buffer[shift + 63]) << 24); + } + + private native void Transform_native (int[] state, byte buffer[], int shift, int length); + + private void Transform (MD5State state, byte buffer[], int shift, int[] decode_buf) { + int + a = state.state[0], + b = state.state[1], + c = state.state[2], + d = state.state[3], + x[] = decode_buf; + + Decode(buffer, shift, decode_buf); + + /* Round 1 */ + a += ((b & c) | (~b & d)) + x[ 0] + 0xd76aa478; /* 1 */ + a = ((a << 7) | (a >>> 25)) + b; + d += ((a & b) | (~a & c)) + x[ 1] + 0xe8c7b756; /* 2 */ + d = ((d << 12) | (d >>> 20)) + a; + c += ((d & a) | (~d & b)) + x[ 2] + 0x242070db; /* 3 */ + c = ((c << 17) | (c >>> 15)) + d; + b += ((c & d) | (~c & a)) + x[ 3] + 0xc1bdceee; /* 4 */ + b = ((b << 22) | (b >>> 10)) + c; + + a += ((b & c) | (~b & d)) + x[ 4] + 0xf57c0faf; /* 5 */ + a = ((a << 7) | (a >>> 25)) + b; + d += ((a & b) | (~a & c)) + x[ 5] + 0x4787c62a; /* 6 */ + d = ((d << 12) | (d >>> 20)) + a; + c += ((d & a) | (~d & b)) + x[ 6] + 0xa8304613; /* 7 */ + c = ((c << 17) | (c >>> 15)) + d; + b += ((c & d) | (~c & a)) + x[ 7] + 0xfd469501; /* 8 */ + b = ((b << 22) | (b >>> 10)) + c; + + a += ((b & c) | (~b & d)) + x[ 8] + 0x698098d8; /* 9 */ + a = ((a << 7) | (a >>> 25)) + b; + d += ((a & b) | (~a & c)) + x[ 9] + 0x8b44f7af; /* 10 */ + d = ((d << 12) | (d >>> 20)) + a; + c += ((d & a) | (~d & b)) + x[10] + 0xffff5bb1; /* 11 */ + c = ((c << 17) | (c >>> 15)) + d; + b += ((c & d) | (~c & a)) + x[11] + 0x895cd7be; /* 12 */ + b = ((b << 22) | (b >>> 10)) + c; + + a += ((b & c) | (~b & d)) + x[12] + 0x6b901122; /* 13 */ + a = ((a << 7) | (a >>> 25)) + b; + d += ((a & b) | (~a & c)) + x[13] + 0xfd987193; /* 14 */ + d = ((d << 12) | (d >>> 20)) + a; + c += ((d & a) | (~d & b)) + x[14] + 0xa679438e; /* 15 */ + c = ((c << 17) | (c >>> 15)) + d; + b += ((c & d) | (~c & a)) + x[15] + 0x49b40821; /* 16 */ + b = ((b << 22) | (b >>> 10)) + c; + + + /* Round 2 */ + a += ((b & d) | (c & ~d)) + x[ 1] + 0xf61e2562; /* 17 */ + a = ((a << 5) | (a >>> 27)) + b; + d += ((a & c) | (b & ~c)) + x[ 6] + 0xc040b340; /* 18 */ + d = ((d << 9) | (d >>> 23)) + a; + c += ((d & b) | (a & ~b)) + x[11] + 0x265e5a51; /* 19 */ + c = ((c << 14) | (c >>> 18)) + d; + b += ((c & a) | (d & ~a)) + x[ 0] + 0xe9b6c7aa; /* 20 */ + b = ((b << 20) | (b >>> 12)) + c; + + a += ((b & d) | (c & ~d)) + x[ 5] + 0xd62f105d; /* 21 */ + a = ((a << 5) | (a >>> 27)) + b; + d += ((a & c) | (b & ~c)) + x[10] + 0x02441453; /* 22 */ + d = ((d << 9) | (d >>> 23)) + a; + c += ((d & b) | (a & ~b)) + x[15] + 0xd8a1e681; /* 23 */ + c = ((c << 14) | (c >>> 18)) + d; + b += ((c & a) | (d & ~a)) + x[ 4] + 0xe7d3fbc8; /* 24 */ + b = ((b << 20) | (b >>> 12)) + c; + + a += ((b & d) | (c & ~d)) + x[ 9] + 0x21e1cde6; /* 25 */ + a = ((a << 5) | (a >>> 27)) + b; + d += ((a & c) | (b & ~c)) + x[14] + 0xc33707d6; /* 26 */ + d = ((d << 9) | (d >>> 23)) + a; + c += ((d & b) | (a & ~b)) + x[ 3] + 0xf4d50d87; /* 27 */ + c = ((c << 14) | (c >>> 18)) + d; + b += ((c & a) | (d & ~a)) + x[ 8] + 0x455a14ed; /* 28 */ + b = ((b << 20) | (b >>> 12)) + c; + + a += ((b & d) | (c & ~d)) + x[13] + 0xa9e3e905; /* 29 */ + a = ((a << 5) | (a >>> 27)) + b; + d += ((a & c) | (b & ~c)) + x[ 2] + 0xfcefa3f8; /* 30 */ + d = ((d << 9) | (d >>> 23)) + a; + c += ((d & b) | (a & ~b)) + x[ 7] + 0x676f02d9; /* 31 */ + c = ((c << 14) | (c >>> 18)) + d; + b += ((c & a) | (d & ~a)) + x[12] + 0x8d2a4c8a; /* 32 */ + b = ((b << 20) | (b >>> 12)) + c; + + + /* Round 3 */ + a += (b ^ c ^ d) + x[ 5] + 0xfffa3942; /* 33 */ + a = ((a << 4) | (a >>> 28)) + b; + d += (a ^ b ^ c) + x[ 8] + 0x8771f681; /* 34 */ + d = ((d << 11) | (d >>> 21)) + a; + c += (d ^ a ^ b) + x[11] + 0x6d9d6122; /* 35 */ + c = ((c << 16) | (c >>> 16)) + d; + b += (c ^ d ^ a) + x[14] + 0xfde5380c; /* 36 */ + b = ((b << 23) | (b >>> 9)) + c; + + a += (b ^ c ^ d) + x[ 1] + 0xa4beea44; /* 37 */ + a = ((a << 4) | (a >>> 28)) + b; + d += (a ^ b ^ c) + x[ 4] + 0x4bdecfa9; /* 38 */ + d = ((d << 11) | (d >>> 21)) + a; + c += (d ^ a ^ b) + x[ 7] + 0xf6bb4b60; /* 39 */ + c = ((c << 16) | (c >>> 16)) + d; + b += (c ^ d ^ a) + x[10] + 0xbebfbc70; /* 40 */ + b = ((b << 23) | (b >>> 9)) + c; + + a += (b ^ c ^ d) + x[13] + 0x289b7ec6; /* 41 */ + a = ((a << 4) | (a >>> 28)) + b; + d += (a ^ b ^ c) + x[ 0] + 0xeaa127fa; /* 42 */ + d = ((d << 11) | (d >>> 21)) + a; + c += (d ^ a ^ b) + x[ 3] + 0xd4ef3085; /* 43 */ + c = ((c << 16) | (c >>> 16)) + d; + b += (c ^ d ^ a) + x[ 6] + 0x04881d05; /* 44 */ + b = ((b << 23) | (b >>> 9)) + c; + + a += (b ^ c ^ d) + x[ 9] + 0xd9d4d039; /* 33 */ + a = ((a << 4) | (a >>> 28)) + b; + d += (a ^ b ^ c) + x[12] + 0xe6db99e5; /* 34 */ + d = ((d << 11) | (d >>> 21)) + a; + c += (d ^ a ^ b) + x[15] + 0x1fa27cf8; /* 35 */ + c = ((c << 16) | (c >>> 16)) + d; + b += (c ^ d ^ a) + x[ 2] + 0xc4ac5665; /* 36 */ + b = ((b << 23) | (b >>> 9)) + c; + + + /* Round 4 */ + a += (c ^ (b | ~d)) + x[ 0] + 0xf4292244; /* 49 */ + a = ((a << 6) | (a >>> 26)) + b; + d += (b ^ (a | ~c)) + x[ 7] + 0x432aff97; /* 50 */ + d = ((d << 10) | (d >>> 22)) + a; + c += (a ^ (d | ~b)) + x[14] + 0xab9423a7; /* 51 */ + c = ((c << 15) | (c >>> 17)) + d; + b += (d ^ (c | ~a)) + x[ 5] + 0xfc93a039; /* 52 */ + b = ((b << 21) | (b >>> 11)) + c; + + a += (c ^ (b | ~d)) + x[12] + 0x655b59c3; /* 53 */ + a = ((a << 6) | (a >>> 26)) + b; + d += (b ^ (a | ~c)) + x[ 3] + 0x8f0ccc92; /* 54 */ + d = ((d << 10) | (d >>> 22)) + a; + c += (a ^ (d | ~b)) + x[10] + 0xffeff47d; /* 55 */ + c = ((c << 15) | (c >>> 17)) + d; + b += (d ^ (c | ~a)) + x[ 1] + 0x85845dd1; /* 56 */ + b = ((b << 21) | (b >>> 11)) + c; + + a += (c ^ (b | ~d)) + x[ 8] + 0x6fa87e4f; /* 57 */ + a = ((a << 6) | (a >>> 26)) + b; + d += (b ^ (a | ~c)) + x[15] + 0xfe2ce6e0; /* 58 */ + d = ((d << 10) | (d >>> 22)) + a; + c += (a ^ (d | ~b)) + x[ 6] + 0xa3014314; /* 59 */ + c = ((c << 15) | (c >>> 17)) + d; + b += (d ^ (c | ~a)) + x[13] + 0x4e0811a1; /* 60 */ + b = ((b << 21) | (b >>> 11)) + c; + + a += (c ^ (b | ~d)) + x[ 4] + 0xf7537e82; /* 61 */ + a = ((a << 6) | (a >>> 26)) + b; + d += (b ^ (a | ~c)) + x[11] + 0xbd3af235; /* 62 */ + d = ((d << 10) | (d >>> 22)) + a; + c += (a ^ (d | ~b)) + x[ 2] + 0x2ad7d2bb; /* 63 */ + c = ((c << 15) | (c >>> 17)) + d; + b += (d ^ (c | ~a)) + x[ 9] + 0xeb86d391; /* 64 */ + b = ((b << 21) | (b >>> 11)) + c; + + state.state[0] += a; + state.state[1] += b; + state.state[2] += c; + state.state[3] += d; + } + + /** + * Updates hash with the bytebuffer given (using at maximum length bytes from + * that buffer) + * + * @param stat Which state is updated + * @param buffer Array of bytes to be hashed + * @param offset Offset to buffer array + * @param length Use at maximum `length' bytes (absolute + * maximum is buffer.length) + */ + public void Update (MD5State stat, byte buffer[], int offset, int length) { + int index, partlen, i, start; + finals = null; + + /* Length can be told to be shorter, but not inter */ + if ((length - offset)> buffer.length) + length = buffer.length - offset; + + /* compute number of bytes mod 64 */ + + index = (int) (stat.count & 0x3f); + stat.count += length; + + partlen = 64 - index; + + if (length >= partlen) { + + // update state (using native method) to reflect input + + if (native_lib_loaded) { + if (partlen == 64) { + partlen = 0; + } else { + for (i = 0; i < partlen; i++) + stat.buffer[i + index] = buffer[i + offset]; + Transform_native(stat.state, stat.buffer, 0, 64); + } + i = partlen + ((length - partlen) / 64) * 64; + + // break into chunks to guard against stack overflow in JNI + + int transformLength = length - partlen; + int transformOffset = partlen + offset; + final int MAX_LENGTH = 65536; // prevent stack overflow in JNI + while (true) { + if (transformLength > MAX_LENGTH) { + Transform_native(stat.state, buffer, transformOffset, MAX_LENGTH); + transformLength -= MAX_LENGTH; + transformOffset += MAX_LENGTH; + } else { + Transform_native(stat.state, buffer, transformOffset, transformLength); + break; + } + } + } + + // update state (using only Java) to reflect input + + else { + int[] decode_buf = new int[16]; + if (partlen == 64) { + partlen = 0; + } else { + for (i = 0; i < partlen; i++) + stat.buffer[i + index] = buffer[i + offset]; + Transform(stat, stat.buffer, 0, decode_buf); + } + for (i = partlen; (i + 63) < length; i+= 64) { + Transform(stat, buffer, i + offset, decode_buf); + } + } + index = 0; + } else { + i = 0; + } + + /* buffer remaining input */ + if (i < length) { + start = i; + for (; i < length; i++) { + stat.buffer[index + i - start] = buffer[i + offset]; + } + } + } + + /* + * Update()s for other datatypes than byte[] also. Update(byte[], int) + * is only the main driver. + */ + + /** + * Plain update, updates this object + **/ + public void Update (byte buffer[], int offset, int length) { + Update(this.state, buffer, offset, length); + } + + public void Update (byte buffer[], int length) { + Update(this.state, buffer, 0, length); + } + + /** + * Updates hash with given array of bytes + * + * @param buffer Array of bytes to use for updating the hash + **/ + public void Update (byte buffer[]) { + Update(buffer, 0, buffer.length); + } + + /** + * Updates hash with a single byte + * + * @param b Single byte to update the hash + **/ + public void Update (byte b) { + byte buffer[] = new byte[1]; + buffer[0] = b; + + Update(buffer, 1); + } + + /** + * Update buffer with given string. Note that because the version of + * the s.getBytes() method without parameters is used to convert the + * string to a byte array, the results of this method may be different + * on different platforms. The s.getBytes() method converts the string + * into a byte array using the current platform's default character set + * and may therefore have different results on platforms with different + * default character sets. If a version that works consistently + * across platforms with different default character sets is desired, + * use the overloaded version of the Update() method which takes a + * string and a character encoding. + * + * @param s String to be update to hash (is used as s.getBytes()) + **/ + public void Update (String s) { + byte chars[] = s.getBytes(); + Update(chars, chars.length); + } + + /** + * Update buffer with given string using the given encoding. If the + * given encoding is null, the encoding "ISO8859_1" is used. + * + * @param s String to be update to hash (is used as + * s.getBytes(charset_name)) + * @param charset_name The character set to use to convert s to a + * byte array, or null if the "ISO8859_1" + * character set is desired. + * @exception java.io.UnsupportedEncodingException If the named + * charset is not supported. + **/ + public void Update (String s, String charset_name) throws java.io.UnsupportedEncodingException { + if (charset_name == null) charset_name = "ISO8859_1"; + byte chars[] = s.getBytes(charset_name); + Update(chars, chars.length); + } + + /** + * Update buffer with a single integer (only & 0xff part is used, + * as a byte) + * + * @param i Integer value, which is then converted to byte as i & 0xff + **/ + public void Update (int i) { + Update((byte) (i & 0xff)); + } + + private byte[] Encode (int input[], int len) { + int i, j; + byte out[]; + + out = new byte[len]; + + for (i = j = 0; j < len; i++, j += 4) { + out[j] = (byte) (input[i] & 0xff); + out[j + 1] = (byte) ((input[i] >>> 8) & 0xff); + out[j + 2] = (byte) ((input[i] >>> 16) & 0xff); + out[j + 3] = (byte) ((input[i] >>> 24) & 0xff); + } + + return out; + } + + /** + * Returns array of bytes (16 bytes) representing hash as of the + * current state of this object. Note: getting a hash does not + * invalidate the hash object, it only creates a copy of the real + * state which is finalized. + * + * @return Array of 16 bytes, the hash of all updated bytes + **/ + public synchronized byte[] Final () { + byte bits[]; + int index, padlen; + MD5State fin; + + if (finals == null) { + fin = new MD5State(state); + + int[] count_ints = {(int) (fin.count << 3), (int) (fin.count >> 29)}; + bits = Encode(count_ints, 8); + + index = (int) (fin.count & 0x3f); + padlen = (index < 56) ? (56 - index) : (120 - index); + + Update(fin, padding, 0, padlen); + Update(fin, bits, 0, 8); + + /* Update() sets finals to null */ + finals = fin; + } + + return Encode(finals.state, 16); + } + + private static final char[] HEX_CHARS = {'0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f',}; + + /** + * Turns array of bytes into string representing each byte as + * unsigned hex number. + * + * @param hash Array of bytes to convert to hex-string + * @return Generated hex string + */ + public static String asHex (byte hash[]) { + char buf[] = new char[hash.length * 2]; + for (int i = 0, x = 0; i < hash.length; i++) { + buf[x++] = HEX_CHARS[(hash[i] >>> 4) & 0xf]; + buf[x++] = HEX_CHARS[hash[i] & 0xf]; + } + return new String(buf); + } + + /** + * Returns 32-character hex representation of this objects hash + * + * @return String of this object's hash + */ + public String asHex () { + return asHex(this.Final()); + } + + public static synchronized final void initNativeLibrary (boolean disallow_lib_loading) { + if (disallow_lib_loading) { + native_lib_init_pending = false; + } else { + _initNativeLibrary(); + } + } + + private static synchronized final void _initNativeLibrary () { + if (!native_lib_init_pending) return; + native_lib_loaded = _loadNativeLibrary(); + native_lib_init_pending = false; + } + + private static synchronized final boolean _loadNativeLibrary () { + try { + + // don't try to load if the right property is set + + String prop = System.getProperty("com.twmacinta.util.MD5.NO_NATIVE_LIB"); + if (prop != null) { + prop = prop.trim(); + if (prop.equalsIgnoreCase("true") || prop.equals("1")) return false; + } + + // the library to load can be specified as a property + + File f; + prop = System.getProperty("com.twmacinta.util.MD5.NATIVE_LIB_FILE"); + if (prop != null) { + f = new File(prop); + if (f.canRead()) { + System.load(f.getAbsolutePath()); + return true; + } + } + + // determine the operating system and architecture + + String os_name = System.getProperty("os.name"); + String os_arch = System.getProperty("os.arch"); + if (os_name == null || os_arch == null) return false; + os_name = os_name.toLowerCase(); + os_arch = os_arch.toLowerCase(); + + // define settings which are OS arch architecture independent + + File arch_lib_path = null; + String arch_libfile_suffix = null; + + // fill in settings for Linux on x86 + + if (os_name.equals("linux") && + (os_arch.equals("x86") || + os_arch.equals("i386") || + os_arch.equals("i486") || + os_arch.equals("i586") || + os_arch.equals("i686"))) { + arch_lib_path = new File(new File(new File("lib"), "arch"), "linux_x86"); + arch_libfile_suffix = ".so"; + } + + // fill in settings for Windows on x86 + + else if (os_name.startsWith("windows ") && + (os_arch.equals("x86") || + os_arch.equals("i386") || + os_arch.equals("i486") || + os_arch.equals("i586") || + os_arch.equals("i686"))) { + arch_lib_path = new File(new File(new File("lib"), "arch"), "win32_x86"); + arch_libfile_suffix = ".dll"; + } + + // fill in settings for Mac OS X on PPC + + else if (os_name.startsWith("mac os x") && + (os_arch.equals("ppc"))) { + arch_lib_path = new File(new File(new File("lib"), "arch"), "darwin_ppc"); + arch_libfile_suffix = ".jnilib"; + } + + // fill in settings for Mac OS X on x86 + + else if (os_name.startsWith("mac os x") && + (os_arch.equals("x86") || + os_arch.equals("i386") || + os_arch.equals("i486") || + os_arch.equals("i586") || + os_arch.equals("i686"))) { + arch_lib_path = new File(new File(new File("lib"), "arch"), "darwin_x86"); + arch_libfile_suffix = ".jnilib"; + } + + // default to .so files with no architecture specific subdirectory + + else { + arch_libfile_suffix = ".so"; + } + + // build the required filename + + String fname = "MD5" + arch_libfile_suffix; + + // try the architecture specific directory + + if (arch_lib_path != null) { + f = new File(arch_lib_path, fname); + if (f.canRead()) { + System.load(f.getAbsolutePath()); + return true; + } + } + + // try the "lib" subdirectory + + f = new File(new File("lib"), fname); + if (f.canRead()) { + System.load(f.getAbsolutePath()); + return true; + } + + // try the working directory + + f = new File(fname); + if (f.canRead()) { + System.load(f.getAbsolutePath()); + return true; + } + } + + // discard SecurityExceptions + + catch (SecurityException e) {} + + // unable to load + + return false; + } + + /** + * Calculates and returns the hash of the contents of the given file. + **/ + public static byte[] getHash (File f) throws IOException { + if (!f.exists()) throw new FileNotFoundException(f.toString()); + InputStream close_me = null; + try { + long buf_size = f.length(); + if (buf_size < 512) buf_size = 512; + if (buf_size > 65536) buf_size = 65536; + byte[] buf = new byte[(int) buf_size]; + MD5InputStream in = new MD5InputStream(new FileInputStream(f)); + close_me = in; + while (in.read(buf) != -1); + in.close(); + return in.hash(); + } catch (IOException e) { + if (close_me != null) try { close_me.close(); } catch (Exception e2) {} + throw e; + } + } + + /** + * @return true iff the first 16 bytes of both hash1 and hash2 are + * equal; both hash1 and hash2 are null; or either hash + * array is less than 16 bytes in length and their lengths and + * all of their bytes are equal. + **/ + public static boolean hashesEqual (byte[] hash1, byte[] hash2) { + if (hash1 == null) return hash2 == null; + if (hash2 == null) return false; + int targ = 16; + if (hash1.length < 16) { + if (hash2.length != hash1.length) return false; + targ = hash1.length; + } else if (hash2.length < 16) { + return false; + } + for (int i = 0; i < targ; i++) { + if (hash1[i] != hash2[i]) return false; + } + return true; + } + +} +} Property changes on: trunk/src/test/java/org/nuiton/util/MD5InputStreamTest.java ___________________________________________________________________ Added: svn:keywords + "Author Date Id Revision HeadURL