Java/Development Class/Hash Code

Материал из Java эксперт
Перейти к: навигация, поиск

A hash-code generator and a collection of static hash-code generation methods.

      
 
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This 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 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
import java.io.Serializable;
/**
 * A hash-code generator and a collection of static hash-code generation
 * methods.
 * 
 * @version <tt>$Revision: 2800 $</tt>
 * @author 
 */
@SuppressWarnings("unchecked")
public final class HashCode implements Serializable, Cloneable, Comparable {
  /** The serialVersionUID */
  private static final long serialVersionUID = 2391396931740264021L;
  /** Hashcode for a "null" value. */
  private static final int NULL_HASHCODE = 0;
  /** Hashcode for a "true" boolean */
  private static final int TRUE_HASHCODE = 1231; // completely arbitrary
  /** Hashcode for a "false" boolean */
  private static final int FALSE_HASHCODE = 1237; // completely arbitrary
  /** The hash-code value. */
  private int value;
  /**
   * Construct a new <tt>HashCode</tt> using the given <tt>int</tt> as the
   * base value.
   * 
   * @param value
   *          <tt>int</tt> to use as the base value.
   */
  public HashCode(final int value) {
    this.value = value;
  }
  /**
   * Construct a new <tt>HashCode</tt>.
   */
  public HashCode() {
    this(0);
  }
  /**
   * Add the hash-code of the given value.
   * 
   * @param b
   *          Value to get hash-code from.
   * @return <i>This</i> <tt>HashCode</tt>.
   */
  public HashCode add(final boolean b) {
    value ^= generate(b);
    return this;
  }
  /**
   * Add the hash-code of the given value.
   * 
   * @param n
   *          Value to get hash-code from.
   * @return <i>This</i> <tt>HashCode</tt>.
   */
  public HashCode add(final byte n) {
    value ^= n;
    return this;
  }
  /**
   * Add the hash-code of the given value.
   * 
   * @param n
   *          Value to get hash-code from.
   * @return <i>This</i> <tt>HashCode</tt>.
   */
  public HashCode add(final char n) {
    value ^= n;
    return this;
  }
  /**
   * Add the hash-code of the given value.
   * 
   * @param n
   *          Value to get hash-code from.
   * @return <i>This</i> <tt>HashCode</tt>.
   */
  public HashCode add(final short n) {
    value ^= n;
    return this;
  }
  /**
   * Add the hash-code of the given value.
   * 
   * @param n
   *          Value to get hash-code from.
   * @return <i>This</i> <tt>HashCode</tt>.
   */
  public HashCode add(final int n) {
    value ^= n;
    return this;
  }
  /**
   * Add the hash-code of the given value.
   * 
   * @param n
   *          Value to get hash-code from.
   * @return <i>This</i> <tt>HashCode</tt>.
   */
  public HashCode add(final long n) {
    value ^= generate(n);
    return this;
  }
  /**
   * Add the hash-code of the given value.
   * 
   * @param f
   *          Value to get hash-code from.
   * @return <i>This</i> <tt>HashCode</tt>.
   */
  public HashCode add(final float f) {
    value ^= generate(f);
    return this;
  }
  /**
   * Add the hash-code of the given value.
   * 
   * @param f
   *          Value to get hash-code from.
   * @return <i>This</i> <tt>HashCode</tt>.
   */
  public HashCode add(final double f) {
    value ^= generate(f);
    return this;
  }
  /**
   * Add the hash-code of the given object.
   * 
   * @param obj
   *          Value to get hash-code from.
   * @return <i>This</i> <tt>HashCode</tt>.
   */
  public HashCode add(final Object obj) {
    value ^= generate(obj);
    return this;
  }
  /**
   * Get the hash-code.
   * 
   * @return Hash-code.
   */
  public int hashCode() {
    return value;
  }
  /**
   * Compares this object with the specified <tt>int</tt> for order.
   * 
   * @param other
   *          Value to compare with.
   * @return A negative integer, zero, or a positive integer as this object is
   *         less than, equal to, or greater than the specified object.
   */
  public int compareTo(final int other) {
    return (value < other) ? -1 : (value == other) ? 0 : 1;
  }
  /**
   * Compares this object with the specified object for order.
   * 
   * @param obj
   *          Value to compare with.
   * @return A negative integer, zero, or a positive integer as this object is
   *         less than, equal to, or greater than the specified object.
   * 
   * @throws ClassCastException
   *           Object is not a <tt>HashCode</tt>.
   */
  public int compareTo(final Object obj) throws ClassCastException {
    HashCode hashCode = (HashCode) obj;
    return compareTo(hashCode.value);
  }
  /**
   * Test the equality of this <tt>HashCode</tt> and another object.
   * 
   * @param obj
   *          Object to test equality with.
   * @return True if object is equal.
   */
  public boolean equals(final Object obj) {
    if (obj == this)
      return true;
    if (obj != null && obj.getClass() == getClass()) {
      return value == ((HashCode) obj).value;
    }
    return false;
  }
  /**
   * Return a string representation of this <tt>HashCode</tt>.
   * 
   * @return A string representation of this <tt>HashCode</tt>.
   */
  public String toString() {
    return String.valueOf(value);
  }
  /**
   * Return a cloned copy of this <tt>HashCode</tt>.
   * 
   * @return Cloned <tt>HashCode</tt>.
   */
  public Object clone() {
    try {
      return super.clone();
    } catch (CloneNotSupportedException e) {
      throw new InternalError();
    }
  }
  // ///////////////////////////////////////////////////////////////////////
  // Generation Methods //
  // ///////////////////////////////////////////////////////////////////////
  /**
   * Generate a hash code for a boolean value.
   * 
   * @param value
   *          Boolean value to generate hash code from.
   * @return Hash code.
   */
  public static int generate(final boolean value) {
    return value ? TRUE_HASHCODE : FALSE_HASHCODE;
  }
  /**
   * Generate a hash code for a long value.
   * 
   * @param value
   *          Long value to generate hash code from.
   * @return Hash code.
   */
  public static int generate(final long value) {
    return (int) (value ^ (value >> 32));
  }
  /**
   * Generate a hash code for a double value.
   * 
   * @param value
   *          Double value to generate hash code from.
   * @return Hash code.
   */
  public static int generate(final double value) {
    return generate(Double.doubleToLongBits(value));
  }
  /**
   * Generate a hash code for a float value.
   * 
   * @param value
   *          Float value to generate hash code from.
   * @return Hash code.
   */
  public static int generate(final float value) {
    return Float.floatToIntBits(value);
  }
  /**
   * Generate a hash code for a byte array.
   * 
   * @param bytes
   *          An array of bytes to generate a hash code from.
   * @return Hash code.
   */
  public static int generate(final byte[] bytes) {
    int hashcode = 0;
    for (int i = 0; i < bytes.length; i++) {
      hashcode <<= 1;
      hashcode ^= bytes[i];
    }
    return hashcode;
  }
  /**
   * Generate a hash code for an object array.
   * 
   * <p>
   * Does not handle nested primitive array elements.
   * 
   * @param array
   *          Array to generate hashcode for.
   * @param deep
   *          True to traverse elements which are arrays to determine the
   *          elements hash code.
   * @return Hash code.
   */
  public static int generate(final Object array[], final boolean deep) {
    int hashcode = 0;
    for (int i = 0; i < array.length; i++) {
      if (deep && (array[i] instanceof Object[])) {
        hashcode ^= generate((Object[]) array[i], true);
      } else {
        hashcode ^= array[i].hashCode();
      }
    }
    return hashcode;
  }
  /**
   * Generate a shallow hash code for an object array.
   * 
   * @param array
   *          Array to generate hashcode for.
   * @return Hash code.
   */
  public static int generate(final Object array[]) {
    return generate(array, false);
  }
  /**
   * Generate a hash code for an object.
   * 
   * @param obj
   *          Object to generate hashcode for.
   * @return Hash code.
   */
  public static int generate(final Object obj) {
    if (obj != null) {
      return obj.hashCode();
    }
    return NULL_HASHCODE;
  }
}





An implementation of the HMACT64 keyed hashing algorithm

     
/* HMACT64 keyed hashing algorithm
 * Copyright (C) 2003 "Eric Glass" <jcifs at samba dot org>
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

import java.security.MessageDigest;
/**
 * This is an implementation of the HMACT64 keyed hashing algorithm.
 * HMACT64 is defined by Luke Leighton as a modified HMAC-MD5 (RFC 2104)
 * in which the key is truncated at 64 bytes (rather than being hashed
 * via MD5).
 */ 
public class HMACT64 extends MessageDigest implements Cloneable {
    private static final int BLOCK_LENGTH = 64;
    private static final byte IPAD = (byte) 0x36;
    private static final byte OPAD = (byte) 0x5c;
    private MessageDigest md5;
    private byte[] ipad = new byte[BLOCK_LENGTH];
    private byte[] opad = new byte[BLOCK_LENGTH];
    /**
     * Creates an HMACT64 instance which uses the given secret key material.
     *
     * @param key The key material to use in hashing.
     */
    public HMACT64(byte[] key) {
        super("HMACT64");
        int length = Math.min(key.length, BLOCK_LENGTH);
        for (int i = 0; i < length; i++) {
            ipad[i] = (byte) (key[i] ^ IPAD);
            opad[i] = (byte) (key[i] ^ OPAD);
        }
        for (int i = length; i < BLOCK_LENGTH; i++) {
            ipad[i] = IPAD;
            opad[i] = OPAD;
        }
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception ex) {
            throw new IllegalStateException(ex.getMessage());
        }
        engineReset();
    }
    private HMACT64(HMACT64 hmac) throws CloneNotSupportedException {
        super("HMACT64");
        this.ipad = hmac.ipad;
        this.opad = hmac.opad;
        this.md5 = (MessageDigest) hmac.md5.clone();
    }
    public Object clone() {
        try {
            return new HMACT64(this);
        } catch (CloneNotSupportedException ex) {
            throw new IllegalStateException(ex.getMessage());
        }
    }
    protected byte[] engineDigest() {
        byte[] digest = md5.digest();
        md5.update(opad);
        return md5.digest(digest);
    }
    protected int engineDigest(byte[] buf, int offset, int len) {
        byte[] digest = md5.digest();
        md5.update(opad);
        md5.update(digest);
        try {
            return md5.digest(buf, offset, len);
        } catch (Exception ex) {
            throw new IllegalStateException();
        }
    }
    protected int engineGetDigestLength() {
        return md5.getDigestLength();
    }
    protected void engineReset() {
        md5.reset();
        md5.update(ipad);
    }
    protected void engineUpdate(byte b) {
        md5.update(b);
    }
    protected void engineUpdate(byte[] input, int offset, int len) {
        md5.update(input, offset, len);
    }
}





A very efficient java hash algorithm, based on the BuzHash algoritm

      
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * A very efficient java hash algorithm, based on the BuzHash algoritm by Robert
 * Uzgalis (see http://www.serve.net/buz/hash.adt/java.000.html for more
 * information). BuzHash is Copyright (c)1996 Robert Uzgalis, All Rights
 * Reserved. Used with kind permission of the author
 * 
 * @version $Id: HashUtil.java 587751 2007-10-24 02:41:36Z vgritsenko $
 */
public final class HashUtil {
  private static long initial_hash = 0xe12398c6d9ae3b8aL; // initial values
  private static long mix_master[/* 0:255 */] = {
  /* 000 */0x4476081a7043a46fL, 0x45768b8a6e7eac19L, 0xebd556c1cf055952L,
  /* */0x72ed2da1bf010101L, 0x3ff2030b128e8a64L,
  /* 005 */0xcbc330238adcfef2L, 0x737807fe42e20c6cL, 0x74dabaedb1095c58L,
  /* */0x968f065c65361d67L, 0xd3f4018ac7a4b199L,
  /* 010 */0x954b389b52f24df2L, 0x2f97a9d8d0549327L, 0xb9bea2b49a3b180fL,
  /* */0xaf2f42536b21f2ebL, 0x85d991663cff1325L,
  /* 015 */0xb9e1260207b575b9L, 0xf3ea88398a23b7e2L, 0xfaf8c83ffbd9091dL,
  /* */0x4274fe90834dbdf9L, 0x3f20b157b68d6313L,
  /* 020 */0x68b48972b6d06b93L, 0x694837b6eba548afL, 0xeecb51d1acc917c9L,
  /* */0xf1c633f02dffbcfaL, 0xa6549ec9d301f3b5L,
  /* 025 */0x451dc944f1663592L, 0x446d6acef6ce9e4fL, 0x1c8a5b3013206f02L,
  /* */0x5908ca36f2dc50f7L, 0x4fd55d3f3e880a87L,
  /* 030 */0xa03a8dbeabbf065dL, 0x3ccbbe078fabcb6dL, 0x1da53a259116f2d0L,
  /* */0xfb27a96fcb9af152L, 0x50aba242e85aec09L,
  /* 035 */0x24d4e414fc4fc987L, 0x83971844a9ce535eL, 0xc26a3fdeb849398eL,
  /* */0xc2380d044d2e70d8L, 0xab418aa8ae19b18fL,
  /* 040 */0xd95b6b9247d5ebeaL, 0x8b3b2171fdc60511L, 0xe15cd0ae3fcc44afL,
  /* */0x5a4e27f914a68f17L, 0x377bd28ca09aafdcL,
  /* 045 */0xbbeb9828594a3294L, 0x7c8df263ae1de1b9L, 0xba0a48a5fd1c1dd0L,
  /* */0x57cc1b8818b98ee6L, 0x8c570975d357dabcL,
  /* 050 */0x76bdcd6f2e8826aaL, 0x529b15b6ec4055f1L, 0x9147c7a54c34f8a9L,
  /* */0x2f96a7728170e402L, 0xe46602f455eca72eL,
  /* 055 */0x22834c4dd1bde03fL, 0x2644cf5a25e368ffL, 0x907c6de90b120f4aL,
  /* */0xadfe8ba99028f728L, 0xa85199ae14df0433L,
  /* 060 */0x2d749b946dd3601eL, 0x76e35457aa052772L, 0x90410bf6e427f736L,
  /* */0x536ad04d13e35041L, 0x8cc0d76769b76914L,
  /* 065 */0xae0249f6e3b3c01cL, 0x1bdfd075307d6fafL, 0xd8e04f70c221deccL,
  /* */0x4ab23622a4281a5dL, 0x37a5613da2fcaba7L,
  /* 070 */0x19a56203666d4a9fL, 0x158ffab502c4be93L, 0x0bee714e332ecb2fL,
  /* */0x69b71a59f6f74ab0L, 0x0fc7fc622f1dfe8fL,
  /* 075 */0x513966de7152a6f9L, 0xc16fae9cc2ea9be7L, 0xb66f0ac586c1899eL,
  /* */0x11e124aee3bdefd7L, 0x86cf5a577512901bL,
  /* 080 */0x33f33ba6994a1fbdL, 0xde6c4d1d3d47ff0dL, 0x6a99220dc6f78e66L,
  /* */0x2dc06ca93e2d25d2L, 0x96413b520134d573L,
  /* 085 */0xb4715ce8e1023afaL, 0xe6a75900c8c66c0aL, 0x6448f13ad54c12edL,
  /* */0xb9057c28cf6689f0L, 0xf4023daf67f7677aL,
  /* 090 */0x877c2650767b9867L, 0xb7ea587dcd5b2341L, 0xc048cf111733f9bcL,
  /* */0x112012c15bc867bfL, 0xc95f52b1d9418811L,
  /* 095 */0xa47e624ee7499083L, 0x26928606df9b12e8L, 0x5d020462ec3e0928L,
  /* */0x8bbde651f6d08914L, 0xd5db83db758e524aL,
  /* 100 */0x3105e355c000f455L, 0xdd7fe1b81a786c79L, 0x1f3a818c8e012db1L,
  /* */0xd902de819d7b42faL, 0x4200e63325cda5f0L,
  /* 105 */0x0e919cdc5fba9220L, 0x5360dd54605a11e1L, 0xa3182d0e6cb23e6cL,
  /* */0x13ee462c1b483b87L, 0x1b1b6087b997ee22L,
  /* 110 */0x81c36d0b877f7362L, 0xc24879932c1768d4L, 0x1faa756e1673f9adL,
  /* */0x61651b24d11fe93dL, 0x30fe3d9304e1cde4L,
  /* 115 */0x7be867c750747250L, 0x973e52c7005b5db6L, 0x75d6b699bbaf4817L,
  /* */0x25d2a9e97379e196L, 0xe65fb599aca98701L,
  /* 120 */0x6ac27960d24bde84L, 0xdfacc04c9fabbcb6L, 0xa46cd07f4a97882bL,
  /* */0x652031d8e59a1fd8L, 0x1185bd967ec7ce10L,
  /* 125 */0xfc9bd84c6780f244L, 0x0a0c59872f61b3ffL, 0x63885727a1c71c95L,
  /* */0x5e88b4390b2d765cL, 0xf0005ccaf988514dL,
  /* 130 */0x474e44280a98e840L, 0x32de151c1411bc42L, 0x2c4b86d5aa4482c2L,
  /* */0xccd93deb2d9d47daL, 0x3743236ff128a622L,
  /* 135 */0x42ed2f2635ba5647L, 0x99c74afd18962dbdL, 0x2d663bb870f6d242L,
  /* */0x7912033bc7635d81L, 0xb442862f43753680L,
  /* 140 */0x94b1a5400aeaab4cL, 0x5ce285fe810f2220L, 0xe8a7dbe565d9c0b1L,
  /* */0x219131af78356c94L, 0x7b3a80d130f27e2fL,
  /* 145 */0xbaa5d2859d16b440L, 0x821cfb6935771070L, 0xf68cfb6ee9bc2336L,
  /* */0x18244132e935d2fdL, 0x2ed0bda1f4720cffL,
  /* 150 */0x4ed48cdf6975173cL, 0xfd37a7a2520e2405L, 0x82c102b2a9e73ce2L,
  /* */0xadac6517062623a7L, 0x5a1294d318e26104L,
  /* 155 */0xea84fe65c0e4f061L, 0x4f96f8a9464cfee9L, 0x9831dff8ccdc534aL,
  /* */0x4ca927cd0f192a14L, 0x030900b294b71649L,
  /* 160 */0x644b263b9aeb0675L, 0xa601d4e34647e040L, 0x34d897eb397f1004L,
  /* */0xa6101c37f4ec8dfcL, 0xc29d2a8bbfd0006bL,
  /* 165 */0xc6b07df8c5b4ed0fL, 0xce1b7d92ba6bccbeL, 0xfa2f99442e03fe1bL,
  /* */0xd8863e4c16f0b363L, 0x033b2cccc3392942L,
  /* 170 */0x757dc33522d6cf9cL, 0xf07b1ff6ce55fec5L, 0x1569e75f09b40463L,
  /* */0xfa33fa08f14a310bL, 0x6eb79aa27bbcf76bL,
  /* 175 */0x157061207c249602L, 0x25e5a71fc4e99555L, 0x5df1fe93de625355L,
  /* */0x235b56090c1aa55dL, 0xe51068613eaced91L,
  /* 180 */0x45bd47b893b9ff1eL, 0x6595e1798d381f2dL, 0xc9b5848cbcdb5ba8L,
  /* */0x65985146ff7792bcL, 0x4ab4a17bf05a19a0L,
  /* 185 */0xfd94f4ca560ffb0cL, 0xcf9bad581a68fa68L, 0x92b4f0b502b1ce1aL,
  /* */0xbcbec0769a610474L, 0x8dbd31ded1a0fecbL,
  /* 190 */0xdd1f5ed9f90e8533L, 0x61c1e6a523f84d95L, 0xf24475f383c110c4L,
  /* */0xdb2dffa66f90588dL, 0xac06d88e9ee04455L,
  /* 195 */0xa215fc47c40504baL, 0x86d7caebfee93369L, 0x9eaec31985804099L,
  /* */0x0fba2214abe5d01bL, 0x5a32975a4b3865d6L,
  /* 200 */0x8cceebc98a5c108fL, 0x7e12c4589654f2dcL, 0xa49ad49fb0d19772L,
  /* */0x3d142dd9c406152bL, 0x9f13589e7be2b8a5L,
  /* 205 */0x5e8dbac1892967adL, 0xcc23b93a6308e597L, 0x1ef35f5fe874e16aL,
  /* */0x63ae9cc08d2e274fL, 0x5bbabee56007fc05L,
  /* 210 */0xabfd72994230fc39L, 0x9d71a13a99144de1L, 0xd9daf5aa8dcc89b3L,
  /* */0xe145ec0514161bfdL, 0x143befc2498cd270L,
  /* 215 */0xa8e192557dbbd9f8L, 0xcbeda2445628d7d0L, 0x997f0a93205d9ea4L,
  /* */0x01014a97f214ebfaL, 0x70c026ffd1ebedafL,
  /* 220 */0xf8737b1b3237002fL, 0x8afcbef3147e6e5eL, 0x0e1bb0684483ebd3L,
  /* */0x4cbad70ae9b05aa6L, 0xd4a31f523517c363L,
  /* 225 */0xdb0f057ae8e9e8a2L, 0x400894a919d89df6L, 0x6a626a9b62defab3L,
  /* */0xf907fd7e14f4e201L, 0xe10e4a5657c48f3fL,
  /* 230 */0xb17f9f54b8e6e5dcL, 0x6b9e69045fa6d27aL, 0x8b74b6a41dc3078eL,
  /* */0x027954d45ca367f9L, 0xd07207b8fdcbb7ccL,
  /* 235 */0xf397c47d2f36414bL, 0x05e4e8b11d3a034fL, 0x36adb3f7122d654fL,
  /* */0x607d9540eb336078L, 0xb639118e3a8b9600L,
  /* 240 */0xd0a406770b5f1484L, 0x3cbee8213ccfb7c6L, 0x467967bb2ff89cf1L,
  /* */0xb115fe29609919a6L, 0xba740e6ffa83287eL,
  /* 245 */0xb4e51be9b694b7cdL, 0xc9a081c677df5aeaL, 0x2e1fbcd8944508ccL,
  /* */0xf626e7895581fbb8L, 0x3ce6e9b5728a05cbL,
  /* 250 */0x46e87f2664a31712L, 0x8c1dc526c2f6acfaL, 0x7b4826726e560b10L,
  /* */0x2966e0099d8d7ce1L, 0xbb0dd5240d2b2adeL, 0x0d527cc60bbaa936L };
  /**
   * This is buzhash the hash function on which most other Hash methods are
   * built.
   */
  private static long buzhash(StringBuffer arg) {
    /* Hash StringBuffer */
    long h = initial_hash;
    for (int i = 0; i < arg.length(); ++i)
      h = (h << 1) ^ (h >>> 63) ^ mix_master[(arg.charAt(i) ^ (arg.charAt(i) >>> 8)) & 0xff];
    return h;
  }
  /**
   * This is buzhash the hash function on which most other Hash methods are
   * built.
   */
  private static long buzhash(String arg) {
    /* Hash StringBuffer */
    long h = initial_hash;
    for (int i = 0; i < arg.length(); ++i)
      h = (h << 1) ^ (h >>> 63) ^ mix_master[(arg.charAt(i) ^ (arg.charAt(i) >>> 8)) & 0xff];
    return h;
  }
  /**
   * Hash a String.
   * 
   * @param arg
   *          The String to be hashed
   * @return The hash for the input.
   */
  public static long hash(String arg) {
    // Make Hash from String
    return buzhash(arg);
  }
  /**
   * Hash a String.
   * 
   * @param arg
   *          The String represented by the StringBuffer to be hashed
   * @return The hash for the input.
   */
  public static long hash(StringBuffer arg) {
    // Make Hash from StringBuffer
    return buzhash(arg);
  }
}





Computing hash codes

      
/*
 * JBoss DNA (http://www.jboss.org/dna)
 * See the COPYRIGHT.txt file distributed with this work for information
 * regarding copyright ownership.  Some portions may be licensed
 * to Red Hat, Inc. under one or more contributor license agreements.
 * See the AUTHORS.txt file in the distribution for a full listing of 
 * individual contributors. 
 *
 * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
 * is licensed to you under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * JBoss DNA 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
import java.util.Arrays;
/**
 * Utilities for easily computing hash codes. The algorithm should generally produce good distributions for use in hash-based
 * containers or collections, but as expected does always result in repeatable hash codes given the inputs.
 * @author Randall Hauch
 */
public class HashCode {
    // Prime number used in improving distribution: 1,000,003
    private static final int PRIME = 103;
    /**
     * Compute a combined hash code from the supplied objects. This method always returns 0 if no objects are supplied.
     * @param objects the objects that should be used to compute the hash code
     * @return the hash code
     */
    public static int compute( Object... objects ) {
        return compute(0, objects);
    }
    /**
     * Compute a combined hash code from the supplied objects using the supplied seed.
     * @param seed a value upon which the hash code will be based; may be 0
     * @param objects the objects that should be used to compute the hash code
     * @return the hash code
     */
    protected static int compute( int seed, Object... objects ) {
        if (objects == null || objects.length == 0) {
            return seed * HashCode.PRIME;
        }
        // Compute the hash code for all of the objects ...
        int hc = seed;
        for (Object object : objects) {
            hc = HashCode.PRIME * hc;
            if (object instanceof byte[]) {
                hc += Arrays.hashCode((byte[])object);
            } else if (object instanceof boolean[]) {
                hc += Arrays.hashCode((boolean[])object);
            } else if (object instanceof short[]) {
                hc += Arrays.hashCode((short[])object);
            } else if (object instanceof int[]) {
                hc += Arrays.hashCode((int[])object);
            } else if (object instanceof long[]) {
                hc += Arrays.hashCode((long[])object);
            } else if (object instanceof float[]) {
                hc += Arrays.hashCode((float[])object);
            } else if (object instanceof double[]) {
                hc += Arrays.hashCode((double[])object);
            } else if (object instanceof char[]) {
                hc += Arrays.hashCode((char[])object);
            } else if (object instanceof Object[]) {
                hc += Arrays.hashCode((Object[])object);
            } else if (object != null) {
                hc += object.hashCode();
            }
        }
        return hc;
    }
}





Easy implementation of hashCode

     
// Copyright (c) 2003-2009, Jodd Team (jodd.org). All Rights Reserved.

/**
 * Collected methods which allow easy implementation of <code>hashCode()</code>.
 * Based on items #7 and #8 from "Effective Java" book.
 * <p>
 * Usage scenario:<br>
 * <pre>
 * int result = HashCodeUtil.SEED;
 * result = HashCodeUtil.hash(result, fIsDecrepit);
 * ...
 * return result;
 * </pre>
 */
public class HashCode {
  /**
   * An initial hash code value to which is added contributions from fields.
   * Using a non-zero value decreases collisions of hash code values.
   */
  public static final int SEED = 173;
  public static final int PRIME = 37;
  // ---------------------------------------------------------------- boolean
  /**
   * Calculates hash code for booleans.
   */
  public static int hash(int seed, boolean aBoolean) {
    return (PRIME * seed) + (aBoolean ? 1231 : 1237);
  }
  /**
   * Calculates hash code for boolean array.
   */
  public static int hash(int seed, boolean[] booleanArray) {
    if (booleanArray == null) {
      return 0;
    }
    for (boolean aBoolean : booleanArray) {
      seed = hash(seed, aBoolean);
    }
    return seed;
  }
  /**
   * Calculates hash code for boolean array.
   */
  public static int hashBooleanArray(int seed, boolean... booleanArray) {
    return hash(seed, booleanArray);
  }
  // ---------------------------------------------------------------- char
  /**
   * Calculates hash code for chars.
   */
  public static int hash(int seed, char aChar) {
    return (PRIME * seed) + (int) aChar;
  }
  /**
   * Calculates hash code for char array.
   */
  public static int hash(int seed, char[] charArray) {
    if (charArray == null) {
      return 0;
    }
    for (char aChar : charArray) {
      seed = hash(seed, aChar);
    }
    return seed;
  }
  /**
   * Calculates hash code for char array.
   */
  public static int hashCharArray(int seed, char... charArray) {
    return hash(seed, charArray);
  }
  // ---------------------------------------------------------------- ints
  /**
   * Calculates hash code for ints.
   */
  public static int hash(int seed, int anInt) {
    return (PRIME * seed) + anInt;
  }
  /**
   * Calculates hash code for int array.
   */
  public static int hash(int seed, int[] intArray) {
    if (intArray == null) {
      return 0;
    }
    for (int anInt : intArray) {
      seed = hash(seed, anInt);
    }
    return seed;
  }
  /**
   * Calculates hash code for int array.
   */
  public static int hashIntArray(int seed, int... intArray) {
      return hash(seed, intArray);
  }

  /**
   * Calculates hash code for short array.
   */
  public static int hash(int seed, short[] shortArray) {
    if (shortArray == null) {
      return 0;
    }
    for (short aShort : shortArray) {
      seed = hash(seed, aShort);
    }
    return seed;
  }
  /**
   * Calculates hash code for short array.
   */
  public static int hashShortArray(int seed, short... shortArray) {
    return hash(seed, shortArray);
  }
  /**
   * Calculates hash code for byte array.
   */
  public static int hash(int seed, byte[] byteArray) {
    if (byteArray == null) {
      return 0;
    }
    for (byte aByte : byteArray) {
      seed = hash(seed, aByte);
    }
    return seed;
  }
  /**
   * Calculates hash code for byte array.
   */
  public static int hashByteArray(int seed, byte... byteArray) {
    return hash(seed, byteArray);
  }

  // ---------------------------------------------------------------- long
  /**
   * Calculates hash code for longs.
   */
  public static int hash(int seed, long aLong) {
    return (PRIME * seed) + (int) (aLong ^ (aLong >>> 32));
  }
  /**
   * Calculates hash code for long array.
   */
  public static int hash(int seed, long[] longArray) {
    if (longArray == null) {
      return 0;
    }
    for (long aLong : longArray) {
      seed = hash(seed, aLong);
    }
    return seed;
  }
  /**
   * Calculates hash code for long array.
   */
  public static int hashLongArray(int seed, long... longArray) {
    return hash(seed, longArray);
  }
  // ---------------------------------------------------------------- float
  /**
   * Calculates hash code for floats.
   */
  public static int hash(int seed, float aFloat) {
    return hash(seed, Float.floatToIntBits(aFloat));
  }
  /**
   * Calculates hash code for float array.
   */
  public static int hash(int seed, float[] floatArray) {
    if (floatArray == null) {
      return 0;
    }
    for (float aFloat : floatArray) {
      seed = hash(seed, aFloat);
    }
    return seed;
  }

  /**
   * Calculates hash code for float array.
   */
  public static int hashFloatArray(int seed, float... floatArray) {
    return hash(seed, floatArray);
  }
  // ---------------------------------------------------------------- double
  /**
   * Calculates hash code for doubles.
   */
  public static int hash(int seed, double aDouble) {
    return hash(seed, Double.doubleToLongBits(aDouble));
  }
  /**
   * Calculates hash code for double array.
   */
  public static int hash(int seed, double[] doubleArray) {
    if (doubleArray == null) {
      return 0;
    }
    for (double aDouble : doubleArray) {
      seed = hash(seed, aDouble);
    }
    return seed;
  }
  /**
   * Calculates hash code for double array.
   */
  public static int hashDoubleArray(int seed, double... doubleArray) {
      return hash(seed, doubleArray);
  }
  // ---------------------------------------------------------------- object
  /**
   * Calculates hash code for Objects. Object is a possibly-null object field, and possibly an array.
   * <p>
   * If <code>aObject</code> is an array, then each element may be a primitive
   * or a possibly-null object.
   */
  public static int hash(int seed, Object aObject) {
    int result = seed;
    if (aObject == null) {
      result = hash(result, 0);
    } else if (aObject.getClass().isArray() == false) {
      result = hash(result, aObject.hashCode());
    } else {
      Object[] objects = (Object[]) aObject;
      int length = objects.length;
      for (int idx = 0; idx < length; ++idx) {
        result = hash(result, objects[idx]);
      }
    }
    return result;
  }
}





Get hash code for primitive data types

    
import java.lang.reflect.Array;
import java.util.Arrays;
/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
//Revised from springframework
/**
 * Miscellaneous object utility methods. Mainly for internal use within the
 * framework; consider Jakarta"s Commons Lang for a more comprehensive suite
 * of object utilities.
 *
 * @author Juergen Hoeller
 * @author Keith Donald
 * @author Rod Johnson
 * @author Rob Harrop
 * @author Alex Ruiz
 * @since 19.03.2004
 * @see org.apache.rumons.lang.ObjectUtils
 */
abstract class ObjectUtils {
  private static final int INITIAL_HASH = 7;
  private static final int MULTIPLIER = 31;
  private static final String EMPTY_STRING = "";
  private static final String NULL_STRING = "null";
  private static final String ARRAY_START = "{";
  private static final String ARRAY_END = "}";
  private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END;
  private static final String ARRAY_ELEMENT_SEPARATOR = ", ";

  /**
   * Return the same value as <code>{@link Boolean#hashCode()}</code>.
   * @see Boolean#hashCode()
   */
  public static int hashCode(boolean bool) {
    return bool ? 1231 : 1237;
  }
  /**
   * Return the same value as <code>{@link Double#hashCode()}</code>.
   * @see Double#hashCode()
   */
  public static int hashCode(double dbl) {
    long bits = Double.doubleToLongBits(dbl);
    return hashCode(bits);
  }
  /**
   * Return the same value as <code>{@link Float#hashCode()}</code>.
   * @see Float#hashCode()
   */
  public static int hashCode(float flt) {
    return Float.floatToIntBits(flt);
  }
  /**
   * Return the same value as <code>{@link Long#hashCode()}</code>.
   * @see Long#hashCode()
   */
  public static int hashCode(long lng) {
    return (int) (lng ^ (lng >>> 32));
  }
}





Gets the hash code of an object returning zero when the object is null

   
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.io.Serializable;
/**
 * <p>Operations on <code>Object</code>.</p>
 * 
 * <p>This class tries to handle <code>null</code> input gracefully.
 * An exception will generally not be thrown for a <code>null</code> input.
 * Each method documents its behaviour in more detail.</p>
 *
 * @author 
 * @since 1.0
 * @version $Id: ObjectUtils.java 594336 2007-11-12 22:54:02Z bayard $
 */
public class ObjectUtils {
    /**
     * <p>Singleton used as a <code>null</code> placeholder where
     * <code>null</code> has another meaning.</p>
     *
     * <p>For example, in a <code>HashMap</code> the
     * {@link java.util.HashMap#get(java.lang.Object)} method returns
     * <code>null</code> if the <code>Map</code> contains
     * <code>null</code> or if there is no matching key. The
     * <code>Null</code> placeholder can be used to distinguish between
     * these two cases.</p>
     *
     * <p>Another example is <code>Hashtable</code>, where <code>null</code>
     * cannot be stored.</p>
     *
     * <p>This instance is Serializable.</p>
     */
    public static final Null NULL = new Null();
    
    /**
     * <p><code>ObjectUtils</code> instances should NOT be constructed in
     * standard programming. Instead, the class should be used as
     * <code>ObjectUtils.defaultIfNull("a","b");</code>.</p>
     *
     * <p>This constructor is public to permit tools that require a JavaBean instance
     * to operate.</p>
     */
    public ObjectUtils() {
        super();
    }
    // Defaulting
    //-----------------------------------------------------------------------
    /**
     * <p>Returns a default value if the object passed is
     * <code>null</code>.</p>
     * 
     * <pre>
     * ObjectUtils.defaultIfNull(null, null)      = null
     * ObjectUtils.defaultIfNull(null, "")        = ""
     * ObjectUtils.defaultIfNull(null, "zz")      = "zz"
     * ObjectUtils.defaultIfNull("abc", *)        = "abc"
     * ObjectUtils.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
     * </pre>
     *
     * @param object  the <code>Object</code> to test, may be <code>null</code>
     * @param defaultValue  the default value to return, may be <code>null</code>
     * @return <code>object</code> if it is not <code>null</code>, defaultValue otherwise
     */
    public static Object defaultIfNull(Object object, Object defaultValue) {
        return object != null ? object : defaultValue;
    }
    /**
     * <p>Compares two objects for equality, where either one or both
     * objects may be <code>null</code>.</p>
     *
     * <pre>
     * ObjectUtils.equals(null, null)                  = true
     * ObjectUtils.equals(null, "")                    = false
     * ObjectUtils.equals("", null)                    = false
     * ObjectUtils.equals("", "")                      = true
     * ObjectUtils.equals(Boolean.TRUE, null)          = false
     * ObjectUtils.equals(Boolean.TRUE, "true")        = false
     * ObjectUtils.equals(Boolean.TRUE, Boolean.TRUE)  = true
     * ObjectUtils.equals(Boolean.TRUE, Boolean.FALSE) = false
     * </pre>
     *
     * @param object1  the first object, may be <code>null</code>
     * @param object2  the second object, may be <code>null</code>
     * @return <code>true</code> if the values of both objects are the same
     */
    public static boolean equals(Object object1, Object object2) {
        if (object1 == object2) {
            return true;
        }
        if ((object1 == null) || (object2 == null)) {
            return false;
        }
        return object1.equals(object2);
    }
    /**
     * <p>Gets the hash code of an object returning zero when the
     * object is <code>null</code>.</p>
     *
     * <pre>
     * ObjectUtils.hashCode(null)   = 0
     * ObjectUtils.hashCode(obj)    = obj.hashCode()
     * </pre>
     *
     * @param obj  the object to obtain the hash code of, may be <code>null</code>
     * @return the hash code of the object, or zero if null
     * @since 2.1
     */
    public static int hashCode(Object obj) {
        return (obj == null) ? 0 : obj.hashCode();
    }
    // Identity ToString
    //-----------------------------------------------------------------------
    /**
     * <p>Gets the toString that would be produced by <code>Object</code>
     * if a class did not override toString itself. <code>null</code>
     * will return <code>null</code>.</p>
     *
     * <pre>
     * ObjectUtils.identityToString(null)         = null
     * ObjectUtils.identityToString("")           = "java.lang.String@1e23"
     * ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
     * </pre>
     *
     * @param object  the object to create a toString for, may be
     *  <code>null</code>
     * @return the default toString text, or <code>null</code> if
     *  <code>null</code> passed in
     */
    public static String identityToString(Object object) {
        if (object == null) {
            return null;
        }
        StringBuffer buffer = new StringBuffer();
        identityToString(buffer, object);
        return buffer.toString();
    }
    /**
     * <p>Appends the toString that would be produced by <code>Object</code>
     * if a class did not override toString itself. <code>null</code>
     * will throw a NullPointerException for either of the two parameters. </p>
     *
     * <pre>
     * ObjectUtils.identityToString(buf, "")            = buf.append("java.lang.String@1e23"
     * ObjectUtils.identityToString(buf, Boolean.TRUE)  = buf.append("java.lang.Boolean@7fa"
     * ObjectUtils.identityToString(buf, Boolean.TRUE)  = buf.append("java.lang.Boolean@7fa")
     * </pre>
     *
     * @param buffer  the buffer to append to
     * @param object  the object to create a toString for
     * @since 2.4
     */
    public static void identityToString(StringBuffer buffer, Object object) {
        if (object == null) {
            throw new NullPointerException("Cannot get the toString of a null identity");
        }
        buffer.append(object.getClass().getName())
              .append("@")
              .append(Integer.toHexString(System.identityHashCode(object)));
    }

    // ToString
    //-----------------------------------------------------------------------
    /**
     * <p>Gets the <code>toString</code> of an <code>Object</code> returning
     * an empty string ("") if <code>null</code> input.</p>
     * 
     * <pre>
     * ObjectUtils.toString(null)         = ""
     * ObjectUtils.toString("")           = ""
     * ObjectUtils.toString("bat")        = "bat"
     * ObjectUtils.toString(Boolean.TRUE) = "true"
     * </pre>
     * 
     * @see StringUtils#defaultString(String)
     * @see String#valueOf(Object)
     * @param obj  the Object to <code>toString</code>, may be null
     * @return the passed in Object"s toString, or nullStr if <code>null</code> input
     * @since 2.0
     */
    public static String toString(Object obj) {
        return obj == null ? "" : obj.toString();
    }
    /**
     * <p>Gets the <code>toString</code> of an <code>Object</code> returning
     * a specified text if <code>null</code> input.</p>
     * 
     * <pre>
     * ObjectUtils.toString(null, null)           = null
     * ObjectUtils.toString(null, "null")         = "null"
     * ObjectUtils.toString("", "null")           = ""
     * ObjectUtils.toString("bat", "null")        = "bat"
     * ObjectUtils.toString(Boolean.TRUE, "null") = "true"
     * </pre>
     * 
     * @see StringUtils#defaultString(String,String)
     * @see String#valueOf(Object)
     * @param obj  the Object to <code>toString</code>, may be null
     * @param nullStr  the String to return if <code>null</code> input, may be null
     * @return the passed in Object"s toString, or nullStr if <code>null</code> input
     * @since 2.0
     */
    public static String toString(Object obj, String nullStr) {
        return obj == null ? nullStr : obj.toString();
    }

    // Null
    //-----------------------------------------------------------------------
    /**
     * <p>Class used as a null placeholder where <code>null</code>
     * has another meaning.</p>
     *
     * <p>For example, in a <code>HashMap</code> the
     * {@link java.util.HashMap#get(java.lang.Object)} method returns
     * <code>null</code> if the <code>Map</code> contains
     * <code>null</code> or if there is no matching key. The
     * <code>Null</code> placeholder can be used to distinguish between
     * these two cases.</p>
     *
     * <p>Another example is <code>Hashtable</code>, where <code>null</code>
     * cannot be stored.</p>
     */
    public static class Null implements Serializable {
        /**
         * Required for serialization support. Declare serialization compatibility with Commons Lang 1.0
         * 
         * @see java.io.Serializable
         */
        private static final long serialVersionUID = 7092611880189329093L;
        
        /**
         * Restricted constructor - singleton.
         */
        Null() {
            super();
        }
        
        /**
         * <p>Ensure singleton.</p>
         * 
         * @return the singleton value
         */
        private Object readResolve() {
            return ObjectUtils.NULL;
        }
    }
}





Hash 32 String

    
/*
    GNU LESSER GENERAL PUBLIC LICENSE
    Copyright (C) 2006 The Lobo Project
    This library 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 2.1 of the License, or (at your option) any later version.
    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
    Lesser General Public License for more details.
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    Contact info: lobochief@users.sourceforge.net
*/
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
public class Strings
{
  private static final MessageDigest MESSAGE_DIGEST;
  public static final String[] EMPTY_ARRAY = new String[0];
  static {
      MessageDigest md;
      try {
          md = MessageDigest.getInstance("MD5");
      } catch(NoSuchAlgorithmException err) {
        throw new IllegalStateException();
      }
      MESSAGE_DIGEST = md;
  }
  private static final String HEX_CHARS = "0123456789ABCDEF";
  
  public static String getMD5(String source) {    
      byte[] bytes;
      try {
        bytes = source.getBytes("UTF-8");
      } catch(java.io.UnsupportedEncodingException ue) {
        throw new IllegalStateException(ue);
      }
      byte[] result;
      synchronized(MESSAGE_DIGEST) {
          MESSAGE_DIGEST.update(bytes);
          result = MESSAGE_DIGEST.digest();
      }
      char[] resChars = new char[32];
      int len = result.length;
      for(int i = 0; i < len; i++) {
          byte b = result[i];
          int lo4 = b & 0x0F;
          int hi4 = (b & 0xF0) >> 4;
          resChars[i*2] = HEX_CHARS.charAt(hi4);
          resChars[i*2 + 1] = HEX_CHARS.charAt(lo4);
      }
      return new String(resChars);
  }
  
  public static String getHash32(String source) throws UnsupportedEncodingException {
      String md5 = getMD5(source);
      return md5.substring(0, 8);
  }      
  public static String getHash64(String source) throws UnsupportedEncodingException {
      String md5 = getMD5(source);
      return md5.substring(0, 16);
  }   
  
}





Hash 64 String

    
/*
    GNU LESSER GENERAL PUBLIC LICENSE
    Copyright (C) 2006 The Lobo Project
    This library 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 2.1 of the License, or (at your option) any later version.
    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
    Lesser General Public License for more details.
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    Contact info: lobochief@users.sourceforge.net
*/
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
public class Strings
{
  private static final MessageDigest MESSAGE_DIGEST;
  public static final String[] EMPTY_ARRAY = new String[0];
  static {
      MessageDigest md;
      try {
          md = MessageDigest.getInstance("MD5");
      } catch(NoSuchAlgorithmException err) {
        throw new IllegalStateException();
      }
      MESSAGE_DIGEST = md;
  }
  private static final String HEX_CHARS = "0123456789ABCDEF";
  
  public static String getMD5(String source) {    
      byte[] bytes;
      try {
        bytes = source.getBytes("UTF-8");
      } catch(java.io.UnsupportedEncodingException ue) {
        throw new IllegalStateException(ue);
      }
      byte[] result;
      synchronized(MESSAGE_DIGEST) {
          MESSAGE_DIGEST.update(bytes);
          result = MESSAGE_DIGEST.digest();
      }
      char[] resChars = new char[32];
      int len = result.length;
      for(int i = 0; i < len; i++) {
          byte b = result[i];
          int lo4 = b & 0x0F;
          int hi4 = (b & 0xF0) >> 4;
          resChars[i*2] = HEX_CHARS.charAt(hi4);
          resChars[i*2 + 1] = HEX_CHARS.charAt(lo4);
      }
      return new String(resChars);
  }
  
  public static String getHash32(String source) throws UnsupportedEncodingException {
      String md5 = getMD5(source);
      return md5.substring(0, 8);
  }      
  public static String getHash64(String source) throws UnsupportedEncodingException {
      String md5 = getMD5(source);
      return md5.substring(0, 16);
  }   
  
}





Hash Code Builder

    
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
 * <code>HashCode</code> generation routines.
 * <p>
 * This class enables a good hashcode to be built for any class. It follows
 * the rules laid out in the book Effective Java, by Joshua Bloch. Writing a 
 * good hashCode is actually quite difficult. This class aims to simplify the 
 * process.
 * <p>
 * All relevant fields from the object should be included in the hashCode. Derived
 * fields may be excluded. In general, any field used in the equals method must be
 * used in the hashCode method. 
 * <p>
 * To use this class write code as follows:
 * <pre>
 * public class Person {
 *   String name;
 *   int age;
 *   boolean isSmoker;
 *   ...
 * 
 *   public int hashCode() {
 *     // you pick a hard-coded, randomly chosen, non-zero, odd number
 *     // ideally different for each class
 *     return new HashCodeBuilder(17, 37).   
 *       append(name).
 *       append(age).
 *       append(smoker).
 *       toHashCode();
 *   }
 * }
 * </pre>
 * <p>
 * Alternatively, there is a method that uses reflection to determine
 * the fields to test. Because these fields are usually private, the method, 
 * <code>reflectionHashCode</code>, uses <code>Field.setAccessible</code> to
 * change the visibility of the fields. This will fail under a security manager, 
 * unless the appropriate permissions are set. It is also slower than testing 
 * explicitly.
 * <p>
 * A typical invocation for this method would look like:
 * <pre>
 * public boolean hashCode(Object o) {
 *   return HashCodeBuilder.reflectionHashCode(this);
 * }
 * </pre>
 * 
 * @author 
 * @version $Id: HashCodeBuilder.java 517121 2007-03-12 07:45:49Z ate $
 */
public class HashCodeBuilder
{
    /**
     * Constant to use in building the hashCode
     */
    private final int iConstant;
    /**
     * Running total of the hashCode
     */
    private int iTotal = 0;
    /**
     * Constructor for HashCodeBuilder.
     * This constructor uses two hard coded choices for the constants needed
     * to build a hashCode.
     */
    public HashCodeBuilder()
    {
        super();
        iConstant = 37;
        iTotal = 17;
    }
    /**
     * Constructor for HashCodeBuilder.
     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
     * these should be different for each class, however this is not vital.
     * Prime numbers are preferred, especially for the multiplier.
     * 
     * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
     * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
     * @throws IllegalArgumentException if the number is zero or even
     */
    public HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber)
    {
        super();
        if (initialNonZeroOddNumber == 0)
        {
            throw new IllegalArgumentException("HashCodeBuilder requires a non zero initial value");
        }
        if (initialNonZeroOddNumber % 2 == 0)
        {
            throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
        }
        if (multiplierNonZeroOddNumber == 0)
        {
            throw new IllegalArgumentException("HashCodeBuilder requires a non zero multiplier");
        }
        if (multiplierNonZeroOddNumber % 2 == 0)
        {
            throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
        }
        iConstant = multiplierNonZeroOddNumber;
        iTotal = initialNonZeroOddNumber;
    }
    //-------------------------------------------------------------------------
    /**
     * This method uses reflection to build a valid hash code. 
     * <p>
     * It uses Field.setAccessible to gain access to private fields. This means
     * that it will throw a security exception if run under a security manger, if
     * the permissions are not set up.
     * It is also not as efficient as testing explicitly. 
     * Transient members will be not be used, as they are likely derived 
     * fields, and not part of the value of the object. 
     * Static fields will not be tested.
     * This constructor uses two hard coded choices for the constants needed
     * to build a hash code.
     * 
     * @param object  the object to create a hash code for
     * @return int hash code
     * @throws IllegalArgumentException if the object is null
     */
    public static int reflectionHashCode(Object object)
    {
        return reflectionHashCode(object, false);
    }
    /**
     * This method uses reflection to build a valid hash code. 
     * <p>
     * It uses Field.setAccessible to gain access to private fields. This means
     * that it will throw a security exception if run under a security manger, if
     * the permissions are not set up.
     * It is also not as efficient as testing explicitly. 
     * If the TestTransients parameter is set to true, transient members will be
     * tested, otherwise they are ignored, as they are likely derived fields, and
     * not part of the value of the object. 
     * Static fields will not be tested.
     * This constructor uses two hard coded choices for the constants needed
     * to build a hash code.
     * 
     * @param object  the object to create a hash code for
     * @param testTransients  whether to include transient fields
     * @return int hash code
     * @throws IllegalArgumentException if the object is null
     */
    public static int reflectionHashCode(Object object, boolean testTransients)
    {
        return reflectionHashCode(17, 37, object, testTransients);
    }
    /**
     * This method uses reflection to build a valid hash code. 
     * <p>
     * It uses Field.setAccessible to gain access to private fields. This means
     * that it will throw a security exception if run under a security manger, if
     * the permissions are not set up.
     * It is also not as efficient as testing explicitly. 
     * Transient members will be not be used, as they are likely derived 
     * fields, and not part of the value of the object. 
     * Static fields will not be tested.
     * <p>
     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
     * these should be different for each class, however this is not vital.
     * Prime numbers are preferred, especially for the multiplier.
     * 
     * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
     * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
     * @param object  the object to create a hash code for
     * @return int hash code
     * @throws IllegalArgumentException if the object is null
     * @throws IllegalArgumentException if the number is zero or even
     */
    public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object)
    {
        return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false);
    }
    /**
     * This method uses reflection to build a valid hash code. 
     * <p>
     * It uses Field.setAccessible to gain access to private fields. This means
     * that it will throw a security exception if run under a security manger, if
     * the permissions are not set up.
     * It is also not as efficient as testing explicitly. 
     * If the TestTransients parameter is set to true, transient members will be
     * tested, otherwise they are ignored, as they are likely derived fields, and
     * not part of the value of the object. 
     * Static fields will not be tested.
     * <p>
     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
     * these should be different for each class, however this is not vital.
     * Prime numbers are preferred, especially for the multiplier.
     * 
     * @param initialNonZeroOddNumber
     * @param multiplierNonZeroOddNumber
     * @param object  the object to create a hash code for
     * @param testTransients  whether to include transient fields
     * @return int hash code
     * @throws IllegalArgumentException if the object is null
     * @throws IllegalArgumentException if the number is zero or even
     */
    public static int reflectionHashCode(
        int initialNonZeroOddNumber,
        int multiplierNonZeroOddNumber,
        Object object,
        boolean testTransients)
    {
        if (object == null)
        {
            throw new IllegalArgumentException("The object to build a hash code for must not be null");
        }
        HashCodeBuilder hashCodeBuilder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
        Field[] fields = object.getClass().getDeclaredFields();
        Field.setAccessible(fields, true);
        for (int i = 0; i < fields.length; ++i)
        {
            Field f = fields[i];
            if (testTransients || !Modifier.isTransient(f.getModifiers()))
            {
                if (!Modifier.isStatic(f.getModifiers()))
                {
                    try
                    {
                        hashCodeBuilder.append(f.get(object));
                    }
                    catch (IllegalAccessException e)
                    {
                        //this can"t happen. Would get a Security exception instead
                        //throw a runtime exception in case the impossible happens.
                        throw new InternalError("Unexpected IllegalAccessException");
                    }
                }
            }
        }
        return hashCodeBuilder.toHashCode();
    }
    //-------------------------------------------------------------------------
    /**
     * Append a hashCode for an Object.
     *
     * @param object  the object to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(Object object)
    {
        if (object == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            if (object.getClass().isArray() == false)
            {
                //the simple case, not an array, just the element 
                iTotal = iTotal * iConstant + object.hashCode();
            }
            else
            {
                //"Switch" on type of array, to dispatch to the correct handler
                // This handles multi dimensional arrays
                if (object instanceof long[])
                {
                    append((long[]) object);
                }
                else if (object instanceof int[])
                {
                    append((int[]) object);
                }
                else if (object instanceof short[])
                {
                    append((short[]) object);
                }
                else if (object instanceof char[])
                {
                    append((char[]) object);
                }
                else if (object instanceof byte[])
                {
                    append((byte[]) object);
                }
                else if (object instanceof double[])
                {
                    append((double[]) object);
                }
                else if (object instanceof float[])
                {
                    append((float[]) object);
                }
                else if (object instanceof boolean[])
                {
                    append((boolean[]) object);
                }
                else
                {
                    // Not an array of primitives
                    append((Object[]) object);
                }
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a long.
     *
     * @param value  the long to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(long value)
    {
        iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
        return this;
    }
    /**
     * Append a hashCode for an int.
     *
     * @param value  the int to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(int value)
    {
        iTotal = iTotal * iConstant + value;
        return this;
    }
    /**
     * Append a hashCode for a short.
     *
     * @param value  the short to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(short value)
    {
        iTotal = iTotal * iConstant + value;
        return this;
    }
    /**
     * Append a hashCode for a char.
     *
     * @param value  the char to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(char value)
    {
        iTotal = iTotal * iConstant + value;
        return this;
    }
    /**
     * Append a hashCode for a byte.
     *
     * @param value  the byte to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(byte value)
    {
        iTotal = iTotal * iConstant + value;
        return this;
    }
    /**
     * Append a hashCode for a double.
     *
     * @param value  the double to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(double value)
    {
        return append(Double.doubleToLongBits(value));
    }
    /**
     * Append a hashCode for a float.
     *
     * @param value  the float to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(float value)
    {
        iTotal = iTotal * iConstant + Float.floatToIntBits(value);
        return this;
    }
    /**
     * Append a hashCode for a long.
     *
     * @param value  the long to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(boolean value)
    {
        iTotal = iTotal * iConstant + (value ? 0 : 1);
        return this;
    }
    /**
     * Append a hashCode for an Object array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(Object[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a long array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(long[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for an int array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(int[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a short array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(short[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a char array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(char[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a byte array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(byte[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a double array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(double[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a float array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(float[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a boolean array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(boolean[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Return the computed hashCode
     * 
     * @return int hashCode based on the fields appended
     */
    public int toHashCode()
    {
        return iTotal;
    }
}





HashCode generation

    
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
 * <code>HashCode</code> generation routines.
 * <p>
 * This class enables a good hashcode to be built for any class. It follows
 * the rules laid out in the book Effective Java, by Joshua Bloch. Writing a 
 * good hashCode is actually quite difficult. This class aims to simplify the 
 * process.
 * <p>
 * All relevant fields from the object should be included in the hashCode. Derived
 * fields may be excluded. In general, any field used in the equals method must be
 * used in the hashCode method. 
 * <p>
 * To use this class write code as follows:
 * <pre>
 * public class Person {
 *   String name;
 *   int age;
 *   boolean isSmoker;
 *   ...
 * 
 *   public int hashCode() {
 *     // you pick a hard-coded, randomly chosen, non-zero, odd number
 *     // ideally different for each class
 *     return new HashCodeBuilder(17, 37).   
 *       append(name).
 *       append(age).
 *       append(smoker).
 *       toHashCode();
 *   }
 * }
 * </pre>
 * <p>
 * Alternatively, there is a method that uses reflection to determine
 * the fields to test. Because these fields are usually private, the method, 
 * <code>reflectionHashCode</code>, uses <code>Field.setAccessible</code> to
 * change the visibility of the fields. This will fail under a security manager, 
 * unless the appropriate permissions are set. It is also slower than testing 
 * explicitly.
 * <p>
 * A typical invocation for this method would look like:
 * <pre>
 * public boolean hashCode(Object o) {
 *   return HashCodeBuilder.reflectionHashCode(this);
 * }
 * </pre>
 * 
 * @author 
 * @version $Id: HashCodeBuilder.java 517121 2007-03-12 07:45:49Z ate $
 */
public class HashCodeBuilder
{
    /**
     * Constant to use in building the hashCode
     */
    private final int iConstant;
    /**
     * Running total of the hashCode
     */
    private int iTotal = 0;
    /**
     * Constructor for HashCodeBuilder.
     * This constructor uses two hard coded choices for the constants needed
     * to build a hashCode.
     */
    public HashCodeBuilder()
    {
        super();
        iConstant = 37;
        iTotal = 17;
    }
    /**
     * Constructor for HashCodeBuilder.
     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
     * these should be different for each class, however this is not vital.
     * Prime numbers are preferred, especially for the multiplier.
     * 
     * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
     * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
     * @throws IllegalArgumentException if the number is zero or even
     */
    public HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber)
    {
        super();
        if (initialNonZeroOddNumber == 0)
        {
            throw new IllegalArgumentException("HashCodeBuilder requires a non zero initial value");
        }
        if (initialNonZeroOddNumber % 2 == 0)
        {
            throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
        }
        if (multiplierNonZeroOddNumber == 0)
        {
            throw new IllegalArgumentException("HashCodeBuilder requires a non zero multiplier");
        }
        if (multiplierNonZeroOddNumber % 2 == 0)
        {
            throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
        }
        iConstant = multiplierNonZeroOddNumber;
        iTotal = initialNonZeroOddNumber;
    }
    //-------------------------------------------------------------------------
    /**
     * This method uses reflection to build a valid hash code. 
     * <p>
     * It uses Field.setAccessible to gain access to private fields. This means
     * that it will throw a security exception if run under a security manger, if
     * the permissions are not set up.
     * It is also not as efficient as testing explicitly. 
     * Transient members will be not be used, as they are likely derived 
     * fields, and not part of the value of the object. 
     * Static fields will not be tested.
     * This constructor uses two hard coded choices for the constants needed
     * to build a hash code.
     * 
     * @param object  the object to create a hash code for
     * @return int hash code
     * @throws IllegalArgumentException if the object is null
     */
    public static int reflectionHashCode(Object object)
    {
        return reflectionHashCode(object, false);
    }
    /**
     * This method uses reflection to build a valid hash code. 
     * <p>
     * It uses Field.setAccessible to gain access to private fields. This means
     * that it will throw a security exception if run under a security manger, if
     * the permissions are not set up.
     * It is also not as efficient as testing explicitly. 
     * If the TestTransients parameter is set to true, transient members will be
     * tested, otherwise they are ignored, as they are likely derived fields, and
     * not part of the value of the object. 
     * Static fields will not be tested.
     * This constructor uses two hard coded choices for the constants needed
     * to build a hash code.
     * 
     * @param object  the object to create a hash code for
     * @param testTransients  whether to include transient fields
     * @return int hash code
     * @throws IllegalArgumentException if the object is null
     */
    public static int reflectionHashCode(Object object, boolean testTransients)
    {
        return reflectionHashCode(17, 37, object, testTransients);
    }
    /**
     * This method uses reflection to build a valid hash code. 
     * <p>
     * It uses Field.setAccessible to gain access to private fields. This means
     * that it will throw a security exception if run under a security manger, if
     * the permissions are not set up.
     * It is also not as efficient as testing explicitly. 
     * Transient members will be not be used, as they are likely derived 
     * fields, and not part of the value of the object. 
     * Static fields will not be tested.
     * <p>
     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
     * these should be different for each class, however this is not vital.
     * Prime numbers are preferred, especially for the multiplier.
     * 
     * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
     * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
     * @param object  the object to create a hash code for
     * @return int hash code
     * @throws IllegalArgumentException if the object is null
     * @throws IllegalArgumentException if the number is zero or even
     */
    public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object)
    {
        return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false);
    }
    /**
     * This method uses reflection to build a valid hash code. 
     * <p>
     * It uses Field.setAccessible to gain access to private fields. This means
     * that it will throw a security exception if run under a security manger, if
     * the permissions are not set up.
     * It is also not as efficient as testing explicitly. 
     * If the TestTransients parameter is set to true, transient members will be
     * tested, otherwise they are ignored, as they are likely derived fields, and
     * not part of the value of the object. 
     * Static fields will not be tested.
     * <p>
     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
     * these should be different for each class, however this is not vital.
     * Prime numbers are preferred, especially for the multiplier.
     * 
     * @param initialNonZeroOddNumber
     * @param multiplierNonZeroOddNumber
     * @param object  the object to create a hash code for
     * @param testTransients  whether to include transient fields
     * @return int hash code
     * @throws IllegalArgumentException if the object is null
     * @throws IllegalArgumentException if the number is zero or even
     */
    public static int reflectionHashCode(
        int initialNonZeroOddNumber,
        int multiplierNonZeroOddNumber,
        Object object,
        boolean testTransients)
    {
        if (object == null)
        {
            throw new IllegalArgumentException("The object to build a hash code for must not be null");
        }
        HashCodeBuilder hashCodeBuilder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
        Field[] fields = object.getClass().getDeclaredFields();
        Field.setAccessible(fields, true);
        for (int i = 0; i < fields.length; ++i)
        {
            Field f = fields[i];
            if (testTransients || !Modifier.isTransient(f.getModifiers()))
            {
                if (!Modifier.isStatic(f.getModifiers()))
                {
                    try
                    {
                        hashCodeBuilder.append(f.get(object));
                    }
                    catch (IllegalAccessException e)
                    {
                        //this can"t happen. Would get a Security exception instead
                        //throw a runtime exception in case the impossible happens.
                        throw new InternalError("Unexpected IllegalAccessException");
                    }
                }
            }
        }
        return hashCodeBuilder.toHashCode();
    }
    //-------------------------------------------------------------------------
    /**
     * Append a hashCode for an Object.
     *
     * @param object  the object to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(Object object)
    {
        if (object == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            if (object.getClass().isArray() == false)
            {
                //the simple case, not an array, just the element 
                iTotal = iTotal * iConstant + object.hashCode();
            }
            else
            {
                //"Switch" on type of array, to dispatch to the correct handler
                // This handles multi dimensional arrays
                if (object instanceof long[])
                {
                    append((long[]) object);
                }
                else if (object instanceof int[])
                {
                    append((int[]) object);
                }
                else if (object instanceof short[])
                {
                    append((short[]) object);
                }
                else if (object instanceof char[])
                {
                    append((char[]) object);
                }
                else if (object instanceof byte[])
                {
                    append((byte[]) object);
                }
                else if (object instanceof double[])
                {
                    append((double[]) object);
                }
                else if (object instanceof float[])
                {
                    append((float[]) object);
                }
                else if (object instanceof boolean[])
                {
                    append((boolean[]) object);
                }
                else
                {
                    // Not an array of primitives
                    append((Object[]) object);
                }
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a long.
     *
     * @param value  the long to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(long value)
    {
        iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
        return this;
    }
    /**
     * Append a hashCode for an int.
     *
     * @param value  the int to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(int value)
    {
        iTotal = iTotal * iConstant + value;
        return this;
    }
    /**
     * Append a hashCode for a short.
     *
     * @param value  the short to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(short value)
    {
        iTotal = iTotal * iConstant + value;
        return this;
    }
    /**
     * Append a hashCode for a char.
     *
     * @param value  the char to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(char value)
    {
        iTotal = iTotal * iConstant + value;
        return this;
    }
    /**
     * Append a hashCode for a byte.
     *
     * @param value  the byte to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(byte value)
    {
        iTotal = iTotal * iConstant + value;
        return this;
    }
    /**
     * Append a hashCode for a double.
     *
     * @param value  the double to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(double value)
    {
        return append(Double.doubleToLongBits(value));
    }
    /**
     * Append a hashCode for a float.
     *
     * @param value  the float to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(float value)
    {
        iTotal = iTotal * iConstant + Float.floatToIntBits(value);
        return this;
    }
    /**
     * Append a hashCode for a long.
     *
     * @param value  the long to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(boolean value)
    {
        iTotal = iTotal * iConstant + (value ? 0 : 1);
        return this;
    }
    /**
     * Append a hashCode for an Object array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(Object[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a long array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(long[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for an int array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(int[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a short array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(short[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a char array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(char[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a byte array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(byte[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a double array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(double[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a float array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(float[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Append a hashCode for a boolean array.
     *
     * @param array  the array to add to the hashCode
     * @return this
     */
    public HashCodeBuilder append(boolean[] array)
    {
        if (array == null)
        {
            iTotal = iTotal * iConstant;
        }
        else
        {
            for (int i = 0; i < array.length; i++)
            {
                append(array[i]);
            }
        }
        return this;
    }
    /**
     * Return the computed hashCode
     * 
     * @return int hashCode based on the fields appended
     */
    public int toHashCode()
    {
        return iTotal;
    }
}





MD5 hash generator

    
/*
 * written Santeri Paavolainen, Helsinki Finland 1996
 * (c) Santeri Paavolainen, Helsinki Finland 1996
 * modifications Copyright (C) 2002-2007 Stephen Ostermiller
 * http://ostermiller.org/contact.pl?regarding=Java+Utilities
 * Copyright (C) 2007 Stu Thompson stu.rup -at- mailworks.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 Public License for more details.
 *
 * See COPYING.TXT for details.
 *
 * The original work by Santeri Paavolainen can be found at
 * http://www.helsinki.fi/~sjpaavol/programs/md5/
 *
 * This Java class has been derived from the RSA Data Security, Inc. MD5
 * Message-Digest Algorithm and its reference implementation.
 */
import java.io.*;
/**
 * MD5 hash generator.
 * More information about this class is available from .
 * <p>
 * This class takes as input a message of arbitrary length and produces
 * as output a 128-bit "fingerprint" or "message digest" of the input.
 * It is conjectured that it is computationally infeasible to produce
 * two messages having the same message digest, or to produce any
 * message having a given pre-specified target message digest. The MD5
 * algorithm is intended for digital signature applications, where a
 * large file must be "compressed" in a secure manner before being
 * encrypted with a private (secret) key under a public-key cryptosystem
 * such as RSA.
 * <p>
 * For more information see RFC1321.
 *
 * @see MD5OutputStream
 * @see MD5InputStream
 *
 * @author Santeri Paavolainen http://www.helsinki.fi/~sjpaavol/programs/md5/
 * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
 * @since ostermillerutils 1.00.00
 */
public class MD5 {
  /**
   * Class constructor
   *
   * @since ostermillerutils 1.00.00
   */
  public MD5 () {
    reset();
  }
  /**
   * Command line program that will take files as arguments
   * and output the MD5 sum for each file.
   *
   * @param args command line arguments
   *
   * @since ostermillerutils 1.00.00
   */
  public static void main (String[] args){
    if (args.length == 0){
      System.err.println("Please specify a file.");
    } else {
      for (String element: args) {
        try {
          System.out.println(MD5.getHashString(new File(element)) + " " + element);
        } catch (IOException x){
          System.err.println(x.getMessage());
        }
      }
    }
  }
  /**
   * Gets this hash sum as an array of 16 bytes.
   *
   * @return Array of 16 bytes, the hash of all updated bytes.
   *
   * @since ostermillerutils 1.00.00
   */
  public byte[] getHash() {
    if (!finalState.valid) {
      finalState.copy(workingState);
      long bitCount = finalState.bitCount;
      // Compute the number of left over bits
      int leftOver = (int) (((bitCount >>> 3)) & 0x3f);
      // Compute the amount of padding to add based on number of left over bits.
      int padlen = (leftOver < 56) ? (56 - leftOver) : (120 - leftOver);
      // add the padding
      update(finalState, padding, 0, padlen);
      // add the length (computed before padding was added)
      update(finalState, encode(bitCount), 0, 8);
      finalState.valid = true;
    }
    // make a copy of the hash before returning it.
    return encode(finalState.state, 16);
  }
  /**
   * Returns 32-character hex representation of this hash.
   *
   * @return String representation of this object"s hash.
   *
   * @since ostermillerutils 1.00.00
   */
  public String getHashString(){
    return toHex(this.getHash());
  }
  /**
   * Gets the MD5 hash of the given byte array.
   *
   * @param b byte array for which an MD5 hash is desired.
   * @return Array of 16 bytes, the hash of all updated bytes.
   *
   * @since ostermillerutils 1.00.00
   */
  public static byte[] getHash(byte[] b){
    MD5 md5 = new MD5();
    md5.update(b);
    return md5.getHash();
  }
  /**
   * Gets the MD5 hash of the given byte array.
   *
   * @param b byte array for which an MD5 hash is desired.
   * @return 32-character hex representation the data"s MD5 hash.
   *
   * @since ostermillerutils 1.00.00
   */
  public static String getHashString(byte[] b){
    MD5 md5 = new MD5();
    md5.update(b);
    return md5.getHashString();
  }
  /**
   * Gets the MD5 hash the data on the given InputStream.
   *
   * @param in byte array for which an MD5 hash is desired.
   * @return Array of 16 bytes, the hash of all updated bytes.
   * @throws IOException if an I/O error occurs.
   *
   * @since ostermillerutils 1.00.00
   */
  public static byte[] getHash(InputStream in) throws IOException {
    MD5 md5 = new MD5();
    byte[] buffer = new byte[1024];
    int read;
    while ((read = in.read(buffer)) != -1){
      md5.update(buffer, read);
    }
    return md5.getHash();
  }
  /**
   * Gets the MD5 hash the data on the given InputStream.
   *
   * @param in byte array for which an MD5 hash is desired.
   * @return 32-character hex representation the data"s MD5 hash.
   * @throws IOException if an I/O error occurs.
   *
   * @since ostermillerutils 1.00.00
   */
  public static String getHashString(InputStream in) throws IOException {
    MD5 md5 = new MD5();
    byte[] buffer = new byte[1024];
    int read;
    while ((read = in.read(buffer)) != -1){
      md5.update(buffer, read);
    }
    return md5.getHashString();
  }
  /**
   * Gets the MD5 hash of the given file.
   *
   * @param f file for which an MD5 hash is desired.
   * @return Array of 16 bytes, the hash of all updated bytes.
   * @throws IOException if an I/O error occurs.
   *
   * @since ostermillerutils 1.00.00
   */
  public static byte[] getHash(File f) throws IOException {
    InputStream is = new FileInputStream(f);
    byte[] hash = getHash(is);
    is.close();
    return hash;
  }
  /**
   * Gets the MD5 hash of the given file.
   *
   * @param f file array for which an MD5 hash is desired.
   * @return 32-character hex representation the data"s MD5 hash.
   * @throws IOException if an I/O error occurs.
   *
   * @since ostermillerutils 1.00.00
   */
  public static String getHashString(File f) throws IOException {
    InputStream is = new FileInputStream(f);
    String hash = getHashString(is);
    is.close();
    return hash;
  }
  /**
   * Gets the MD5 hash of the given String.
   * The string is converted to bytes using the current
   * platform"s default character encoding.
   *
   * @param s String for which an MD5 hash is desired.
   * @return Array of 16 bytes, the hash of all updated bytes.
   *
   * @since ostermillerutils 1.00.00
   */
  public static byte[] getHash(String s){
    MD5 md5 = new MD5();
    md5.update(s);
    return md5.getHash();
  }
  /**
   * Gets the MD5 hash of the given String.
   * The string is converted to bytes using the current
   * platform"s default character encoding.
   *
   * @param s String for which an MD5 hash is desired.
   * @return 32-character hex representation the data"s MD5 hash.
   *
   * @since ostermillerutils 1.00.00
   */
  public static String getHashString(String s){
    MD5 md5 = new MD5();
    md5.update(s);
    return md5.getHashString();
  }

  /**
   * Gets the MD5 hash of the given String.
   *
   * @param s String for which an MD5 hash is desired.
   * @param enc The name of a supported character encoding.
   * @return Array of 16 bytes, the hash of all updated bytes.
   * @throws UnsupportedEncodingException If the named encoding is not supported.
   *
   * @since ostermillerutils 1.00.00
   */
  public static byte[] getHash(String s, String enc) throws UnsupportedEncodingException {
    MD5 md5 = new MD5();
    md5.update(s, enc);
    return md5.getHash();
  }
  /**
   * Gets the MD5 hash of the given String.
   *
   * @param s String for which an MD5 hash is desired.
   * @param enc The name of a supported character encoding.
   * @return 32-character hex representation the data"s MD5 hash.
   * @throws UnsupportedEncodingException If the named encoding is not supported.
   *
   * @since ostermillerutils 1.00.00
   */
  public static String getHashString(String s, String enc) throws UnsupportedEncodingException {
    MD5 md5 = new MD5();
    md5.update(s, enc);
    return md5.getHashString();
  }

  /**
   * Reset the MD5 sum to its initial state.
   *
   * @since ostermillerutils 1.00.00
   */
  public void reset() {
    workingState.reset();
    finalState.valid = false;
  }
  /**
   * Returns 32-character hex representation of this hash.
   *
   * @return String representation of this object"s hash.
   *
   * @since ostermillerutils 1.00.00
   */
  @Override public String toString(){
    return getHashString();
  }
  /**
   * Update this hash with the given data.
   * <p>
   * A state may be passed into this method so that we can add padding
   * and finalize a md5 hash without limiting our ability to update
   * more data later.
   * <p>
   * If length bytes are not available to be hashed, as many bytes as
   * possible will be hashed.
   *
   * @param state Which state is updated.
   * @param buffer Array of bytes to be hashed.
   * @param offset Offset to buffer array.
   * @param length number of bytes to hash.
   *
   * @since ostermillerutils 1.00.00
   */
  private void update (MD5State state, byte buffer[], int offset, int length) {
    finalState.valid = false;
    // if length goes beyond the end of the buffer, cut it short.
    if ((length + offset) > buffer.length){
      length = buffer.length - offset;
    }
    // compute number of bytes mod 64
    // this is what we have sitting in a buffer
    // that have not been hashed yet
    int index = (int) (state.bitCount >>> 3) & 0x3f;
    // add the length to the count (translate bytes to bits)
    state.bitCount += length << 3;
    int partlen = 64 - index;
    int i = 0;
    if (length >= partlen) {
      System.arraycopy(buffer, offset, state.buffer, index, partlen);
      transform(state, decode(state.buffer, 64, 0));
      for (i = partlen; (i + 63) < length; i+= 64){
        transform(state, decode(buffer, 64, i));
      }
      index = 0;
    }
    // buffer remaining input
    if (i < length) {
      for (int start = i; i < length; i++) {
        state.buffer[index + i - start] = buffer[i + offset];
      }
    }
  }
  /**
   * Update this hash with the given data.
   * <p>
   * If length bytes are not available to be hashed, as many bytes as
   * possible will be hashed.
   *
   * @param buffer Array of bytes to be hashed.
   * @param offset Offset to buffer array.
   * @param length number of bytes to hash.
   *
   * @since ostermillerutils 1.00.00
   */
  public void update (byte buffer[], int offset, int length) {
    update(workingState, buffer, offset, length);
  }
  /**
   * Update this hash with the given data.
   * <p>
   * If length bytes are not available to be hashed, as many bytes as
   * possible will be hashed.
   *
   * @param buffer Array of bytes to be hashed.
   * @param length number of bytes to hash.
   *
   * @since ostermillerutils 1.00.00
   */
  public void update (byte buffer[], int length) {
    update(buffer, 0, length);
  }
  /**
   * Update this hash with the given data.
   *
   * @param buffer Array of bytes to be hashed.
   *
   * @since ostermillerutils 1.00.00
   */
  public void update (byte buffer[]) {
    update(buffer, 0, buffer.length);
  }
  /**
   * Updates this hash with a single byte.
   *
   * @param b byte to be hashed.
   *
   * @since ostermillerutils 1.00.00
   */
  public void update (byte b) {
    byte buffer[] = new byte[1];
    buffer[0] = b;
    update(buffer, 1);
  }
  /**
   * Update this hash with a String.
   * The string is converted to bytes using the current
   * platform"s default character encoding.
   *
   * @param s String to be hashed.
   *
   * @since ostermillerutils 1.00.00
   */
  public void update (String s) {
    update(s.getBytes());
  }
  /**
   * Update this hash with a String.
   *
   * @param s String to be hashed.
   * @param enc The name of a supported character encoding.
   * @throws UnsupportedEncodingException If the named encoding is not supported.
   *
   * @since ostermillerutils 1.00.00
   */
  public void update (String s, String enc) throws UnsupportedEncodingException {
    update(s.getBytes(enc));
  }
  /**
   * The current state from which the hash sum
   * can be computed or updated.
   *
   * @since ostermillerutils 1.00.00
   */
  private MD5State workingState = new MD5State();
  /**
   * Cached copy of the final MD5 hash sum.  This is created when
   * the hash is requested and it is invalidated when the hash
   * is updated.
   *
   * @since ostermillerutils 1.00.00
   */
  private MD5State finalState = new MD5State();
  /**
   * Temporary buffer cached here for performance reasons.
   *
   * @since ostermillerutils 1.00.00
   */
  private int[] decodeBuffer = new int[16];
  /**
   * 64 bytes of padding that can be added if the length
   * is not divisible by 64.
   *
   * @since ostermillerutils 1.00.00
   */
  private static final 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,
  };
  /**
   * Contains internal state of the MD5 class.
   * Passes MD5 test suite as defined in RFC1321.
   *
   * @since ostermillerutils 1.00.00
   */
  private class MD5State {
    /**
     * True if this state is valid.
     *
     * @since ostermillerutils 1.00.00
     */
    private boolean valid = true;
    /**
     * Reset to initial state.
     *
     * @since ostermillerutils 1.00.00
     */
    private void reset(){
      state[0] = 0x67452301;
      state[1] = 0xefcdab89;
      state[2] = 0x98badcfe;
      state[3] = 0x10325476;
      bitCount = 0;
    }
    /**
     * 128-byte state
     *
     * @since ostermillerutils 1.00.00
     */
    private int state[] = new int[4];
    /**
     * 64-bit count of the number of bits that have been hashed.
     *
     * @since ostermillerutils 1.00.00
     */
    private long bitCount;
    /**
     * 64-byte buffer (512 bits) for storing to-be-hashed characters
     *
     * @since ostermillerutils 1.00.00
     */
    private byte buffer[] = new byte[64];
    private MD5State() {
      reset();
    }
    /**
     * Set this state to be exactly the same as some other.
     *
     * @param from state to copy from.
     *
     * @since ostermillerutils 1.00.00
     */
    private void copy(MD5State from) {
      System.arraycopy(from.buffer, 0, this.buffer, 0, this.buffer.length);
      System.arraycopy(from.state, 0, this.state, 0, this.state.length);
      this.valid = from.valid;
      this.bitCount = from.bitCount;
    }
  }

  /**
   * Turns array of bytes into string representing each byte as
   * a two digit unsigned hex number.
   *
   * @param hash Array of bytes to convert to hex-string
   * @return  Generated hex string
   *
   * @since ostermillerutils 1.00.00
   */
  private static String toHex(byte hash[]){
    StringBuffer buf = new StringBuffer(hash.length * 2);
    for (byte element: hash) {
      int intVal = element & 0xff;
      if (intVal < 0x10){
        // append a zero before a one digit hex
        // number to make it two digits.
        buf.append("0");
      }
      buf.append(Integer.toHexString(intVal));
    }
    return buf.toString();
  }
  private static int FF (int a, int b, int c, int d, int x, int s, int ac) {
    a += ((b & c) | (~b & d));
    a += x;
    a += ac;
    //return rotateLeft(a, s) + b;
    a = (a << s) | (a >>> (32 - s));
    return a + b;
  }
  private static int GG (int a, int b, int c, int d, int x, int s, int ac) {
    a += ((b & d) | (c & ~d));
    a += x;
    a += ac;
    //return rotateLeft(a, s) + b;
    a = (a << s) | (a >>> (32 - s));
    return a + b;
  }
  private static int HH (int a, int b, int c, int d, int x, int s, int ac) {
    a += (b ^ c ^ d);
    a += x;
    a += ac;
    //return rotateLeft(a, s) + b;
    a = (a << s) | (a >>> (32 - s));
    return a + b;
  }
  private static int II (int a, int b, int c, int d, int x, int s, int ac) {
    a += (c ^ (b | ~d));
    a += x;
    a += ac;
    //return rotateLeft(a, s) + b;
    a = (a << s) | (a >>> (32 - s));
    return a + b;
  }
  private static byte[] encode(long l){
    byte[] out = new byte[8];
    out[0] = (byte) (l & 0xff);
    out[1] = (byte) ((l >>> 8) & 0xff);
    out[2] = (byte) ((l >>> 16) & 0xff);
    out[3] = (byte) ((l >>> 24) & 0xff);
    out[4] = (byte) ((l >>> 32) & 0xff);
    out[5] = (byte) ((l >>> 40) & 0xff);
    out[6] = (byte) ((l >>> 48) & 0xff);
    out[7] = (byte) ((l >>> 56) & 0xff);
    return out;
  }
  private static byte[] encode(int input[], int len){
    byte[] out = new byte[len];
    int i, j;
    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;
  }
  private int[] decode(byte buffer[], int len, int offset){
    int i, j;
    for (i = j = 0; j < len; i++, j += 4) {
      decodeBuffer[i] = (
        (buffer[j + offset] & 0xff)) |
        (((buffer[j + 1 + offset] & 0xff)) << 8) |
        (((buffer[j + 2 + offset] & 0xff)) << 16) |
        (((buffer[j + 3 + offset] & 0xff)) << 24
      );
    }
    return decodeBuffer;
  }
  private static void transform(MD5State state, int[] x){
    int a = state.state[0];
    int b = state.state[1];
    int c = state.state[2];
    int d = state.state[3];
    /* Round 1 */
    a = FF (a, b, c, d, x[ 0],   7, 0xd76aa478); /* 1 */
    d = FF (d, a, b, c, x[ 1],  12, 0xe8c7b756); /* 2 */
    c = FF (c, d, a, b, x[ 2],  17, 0x242070db); /* 3 */
    b = FF (b, c, d, a, x[ 3],  22, 0xc1bdceee); /* 4 */
    a = FF (a, b, c, d, x[ 4],   7, 0xf57c0faf); /* 5 */
    d = FF (d, a, b, c, x[ 5],  12, 0x4787c62a); /* 6 */
    c = FF (c, d, a, b, x[ 6],  17, 0xa8304613); /* 7 */
    b = FF (b, c, d, a, x[ 7],  22, 0xfd469501); /* 8 */
    a = FF (a, b, c, d, x[ 8],   7, 0x698098d8); /* 9 */
    d = FF (d, a, b, c, x[ 9],  12, 0x8b44f7af); /* 10 */
    c = FF (c, d, a, b, x[10],  17, 0xffff5bb1); /* 11 */
    b = FF (b, c, d, a, x[11],  22, 0x895cd7be); /* 12 */
    a = FF (a, b, c, d, x[12],   7, 0x6b901122); /* 13 */
    d = FF (d, a, b, c, x[13],  12, 0xfd987193); /* 14 */
    c = FF (c, d, a, b, x[14],  17, 0xa679438e); /* 15 */
    b = FF (b, c, d, a, x[15],  22, 0x49b40821); /* 16 */
    /* Round 2 */
    a = GG (a, b, c, d, x[ 1],   5, 0xf61e2562); /* 17 */
    d = GG (d, a, b, c, x[ 6],   9, 0xc040b340); /* 18 */
    c = GG (c, d, a, b, x[11],  14, 0x265e5a51); /* 19 */
    b = GG (b, c, d, a, x[ 0],  20, 0xe9b6c7aa); /* 20 */
    a = GG (a, b, c, d, x[ 5],   5, 0xd62f105d); /* 21 */
    d = GG (d, a, b, c, x[10],   9, 0x02441453); /* 22 */
    c = GG (c, d, a, b, x[15],  14, 0xd8a1e681); /* 23 */
    b = GG (b, c, d, a, x[ 4],  20, 0xe7d3fbc8); /* 24 */
    a = GG (a, b, c, d, x[ 9],   5, 0x21e1cde6); /* 25 */
    d = GG (d, a, b, c, x[14],   9, 0xc33707d6); /* 26 */
    c = GG (c, d, a, b, x[ 3],  14, 0xf4d50d87); /* 27 */
    b = GG (b, c, d, a, x[ 8],  20, 0x455a14ed); /* 28 */
    a = GG (a, b, c, d, x[13],   5, 0xa9e3e905); /* 29 */
    d = GG (d, a, b, c, x[ 2],   9, 0xfcefa3f8); /* 30 */
    c = GG (c, d, a, b, x[ 7],  14, 0x676f02d9); /* 31 */
    b = GG (b, c, d, a, x[12],  20, 0x8d2a4c8a); /* 32 */
    /* Round 3 */
    a = HH (a, b, c, d, x[ 5],   4, 0xfffa3942); /* 33 */
    d = HH (d, a, b, c, x[ 8],  11, 0x8771f681); /* 34 */
    c = HH (c, d, a, b, x[11],  16, 0x6d9d6122); /* 35 */
    b = HH (b, c, d, a, x[14],  23, 0xfde5380c); /* 36 */
    a = HH (a, b, c, d, x[ 1],   4, 0xa4beea44); /* 37 */
    d = HH (d, a, b, c, x[ 4],  11, 0x4bdecfa9); /* 38 */
    c = HH (c, d, a, b, x[ 7],  16, 0xf6bb4b60); /* 39 */
    b = HH (b, c, d, a, x[10],  23, 0xbebfbc70); /* 40 */
    a = HH (a, b, c, d, x[13],   4, 0x289b7ec6); /* 41 */
    d = HH (d, a, b, c, x[ 0],  11, 0xeaa127fa); /* 42 */
    c = HH (c, d, a, b, x[ 3],  16, 0xd4ef3085); /* 43 */
    b = HH (b, c, d, a, x[ 6],  23, 0x04881d05); /* 44 */
    a = HH (a, b, c, d, x[ 9],   4, 0xd9d4d039); /* 45 */
    d = HH (d, a, b, c, x[12],  11, 0xe6db99e5); /* 46 */
    c = HH (c, d, a, b, x[15],  16, 0x1fa27cf8); /* 47 */
    b = HH (b, c, d, a, x[ 2],  23, 0xc4ac5665); /* 48 */
    /* Round 4 */
    a = II (a, b, c, d, x[ 0],   6, 0xf4292244); /* 49 */
    d = II (d, a, b, c, x[ 7],  10, 0x432aff97); /* 50 */
    c = II (c, d, a, b, x[14],  15, 0xab9423a7); /* 51 */
    b = II (b, c, d, a, x[ 5],  21, 0xfc93a039); /* 52 */
    a = II (a, b, c, d, x[12],   6, 0x655b59c3); /* 53 */
    d = II (d, a, b, c, x[ 3],  10, 0x8f0ccc92); /* 54 */
    c = II (c, d, a, b, x[10],  15, 0xffeff47d); /* 55 */
    b = II (b, c, d, a, x[ 1],  21, 0x85845dd1); /* 56 */
    a = II (a, b, c, d, x[ 8],   6, 0x6fa87e4f); /* 57 */
    d = II (d, a, b, c, x[15],  10, 0xfe2ce6e0); /* 58 */
    c = II (c, d, a, b, x[ 6],  15, 0xa3014314); /* 59 */
    b = II (b, c, d, a, x[13],  21, 0x4e0811a1); /* 60 */
    a = II (a, b, c, d, x[ 4],   6, 0xf7537e82); /* 61 */
    d = II (d, a, b, c, x[11],  10, 0xbd3af235); /* 62 */
    c = II (c, d, a, b, x[ 2],  15, 0x2ad7d2bb); /* 63 */
    b = II (b, c, d, a, x[ 9],  21, 0xeb86d391); /* 64 */
    state.state[0] += a;
    state.state[1] += b;
    state.state[2] += c;
    state.state[3] += d;
  }
}





MD5 hashing: Encodes a string

    
/*
 * Copyright (c) JForum Team
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, 
 * with or without modification, are permitted provided 
 * that the following conditions are met:
 * 
 * 1) Redistributions of source code must retain the above 
 * copyright notice, this list of conditions and the 
 * following  disclaimer.
 * 2)  Redistributions in binary form must reproduce the 
 * above copyright notice, this list of conditions and 
 * the following disclaimer in the documentation and/or 
 * other materials provided with the distribution.
 * 3) Neither the name of "Rafael Steil" nor 
 * the names of its contributors may be used to endorse 
 * or promote products derived from this software without 
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
 * IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
 * 
 * This file creation date: Mar 29, 2003 / 1:15:50 AM
 * The JForum Project
 * http://www.jforum.net
 */
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Encodes a string using MD5 hashing 
 * 
 * @author Rafael Steil
 * @version $Id: MD5.java,v 1.7 2006/08/23 02:13:44 rafaelsteil Exp $
 */
public class MD5 
{
  /**
   * Encodes a string
   * 
   * @param str String to encode
   * @return Encoded String
   * @throws NoSuchAlgorithmException
   */
  public static String crypt(String str)
  {
    if (str == null || str.length() == 0) {
      throw new IllegalArgumentException("String to encript cannot be null or zero length");
    }
    
    StringBuffer hexString = new StringBuffer();
    
    try {
      MessageDigest md = MessageDigest.getInstance("MD5");
      md.update(str.getBytes());
      byte[] hash = md.digest();
      
      for (int i = 0; i < hash.length; i++) {
        if ((0xff & hash[i]) < 0x10) {
          hexString.append("0" + Integer.toHexString((0xFF & hash[i])));
        }       
        else {
          hexString.append(Integer.toHexString(0xFF & hash[i]));
        }       
      }
    }
    catch (NoSuchAlgorithmException e) {
      throw new RuntimeException("" + e);
    }
    
    return hexString.toString();
  }
}





MD5 String

    
/*
    GNU LESSER GENERAL PUBLIC LICENSE
    Copyright (C) 2006 The Lobo Project
    This library 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 2.1 of the License, or (at your option) any later version.
    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
    Lesser General Public License for more details.
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    Contact info: lobochief@users.sourceforge.net
*/
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
public class Strings
{
  private static final MessageDigest MESSAGE_DIGEST;
  public static final String[] EMPTY_ARRAY = new String[0];
  static {
      MessageDigest md;
      try {
          md = MessageDigest.getInstance("MD5");
      } catch(NoSuchAlgorithmException err) {
        throw new IllegalStateException();
      }
      MESSAGE_DIGEST = md;
  }
  private static final String HEX_CHARS = "0123456789ABCDEF";
  
  public static String getMD5(String source) {    
      byte[] bytes;
      try {
        bytes = source.getBytes("UTF-8");
      } catch(java.io.UnsupportedEncodingException ue) {
        throw new IllegalStateException(ue);
      }
      byte[] result;
      synchronized(MESSAGE_DIGEST) {
          MESSAGE_DIGEST.update(bytes);
          result = MESSAGE_DIGEST.digest();
      }
      char[] resChars = new char[32];
      int len = result.length;
      for(int i = 0; i < len; i++) {
          byte b = result[i];
          int lo4 = b & 0x0F;
          int hi4 = (b & 0xF0) >> 4;
          resChars[i*2] = HEX_CHARS.charAt(hi4);
          resChars[i*2 + 1] = HEX_CHARS.charAt(lo4);
      }
      return new String(resChars);
  }
  
  public static String getHash32(String source) throws UnsupportedEncodingException {
      String md5 = getMD5(source);
      return md5.substring(0, 8);
  }      
  public static String getHash64(String source) throws UnsupportedEncodingException {
      String md5 = getMD5(source);
      return md5.substring(0, 16);
  }   
  
}





Null Safe Hash Code

     
import java.lang.reflect.Array;
import java.util.Arrays;
/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
//Revised from springframework
/**
 * Miscellaneous object utility methods. Mainly for internal use within the
 * framework; consider Jakarta"s Commons Lang for a more comprehensive suite
 * of object utilities.
 *
 * @author Juergen Hoeller
 * @author Keith Donald
 * @author Rod Johnson
 * @author Rob Harrop
 * @author Alex Ruiz
 * @since 19.03.2004
 * @see org.apache.rumons.lang.ObjectUtils
 */
abstract class ObjectUtils {
  private static final int INITIAL_HASH = 7;
  private static final int MULTIPLIER = 31;
  private static final String EMPTY_STRING = "";
  private static final String NULL_STRING = "null";
  private static final String ARRAY_START = "{";
  private static final String ARRAY_END = "}";
  private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END;
  private static final String ARRAY_ELEMENT_SEPARATOR = ", ";

  /**
   * Return a hash code based on the contents of the specified array.
   * If <code>array</code> is <code>null</code>, this method returns 0.
   */
  public static int nullSafeHashCode(boolean[] array) {
    if (array == null) {
      return 0;
    }
    int hash = INITIAL_HASH;
    int arraySize = array.length;
    for (int i = 0; i < arraySize; i++) {
      hash = MULTIPLIER * hash + hashCode(array[i]);
    }
    return hash;
  }
  /**
   * Return a hash code based on the contents of the specified array.
   * If <code>array</code> is <code>null</code>, this method returns 0.
   */
  public static int nullSafeHashCode(byte[] array) {
    if (array == null) {
      return 0;
    }
    int hash = INITIAL_HASH;
    int arraySize = array.length;
    for (int i = 0; i < arraySize; i++) {
      hash = MULTIPLIER * hash + array[i];
    }
    return hash;
  }
  /**
   * Return a hash code based on the contents of the specified array.
   * If <code>array</code> is <code>null</code>, this method returns 0.
   */
  public static int nullSafeHashCode(char[] array) {
    if (array == null) {
      return 0;
    }
    int hash = INITIAL_HASH;
    int arraySize = array.length;
    for (int i = 0; i < arraySize; i++) {
      hash = MULTIPLIER * hash + array[i];
    }
    return hash;
  }
  /**
   * Return a hash code based on the contents of the specified array.
   * If <code>array</code> is <code>null</code>, this method returns 0.
   */
  public static int nullSafeHashCode(double[] array) {
    if (array == null) {
      return 0;
    }
    int hash = INITIAL_HASH;
    int arraySize = array.length;
    for (int i = 0; i < arraySize; i++) {
      hash = MULTIPLIER * hash + hashCode(array[i]);
    }
    return hash;
  }
  /**
   * Return a hash code based on the contents of the specified array.
   * If <code>array</code> is <code>null</code>, this method returns 0.
   */
  public static int nullSafeHashCode(float[] array) {
    if (array == null) {
      return 0;
    }
    int hash = INITIAL_HASH;
    int arraySize = array.length;
    for (int i = 0; i < arraySize; i++) {
      hash = MULTIPLIER * hash + hashCode(array[i]);
    }
    return hash;
  }
  /**
   * Return a hash code based on the contents of the specified array.
   * If <code>array</code> is <code>null</code>, this method returns 0.
   */
  public static int nullSafeHashCode(int[] array) {
    if (array == null) {
      return 0;
    }
    int hash = INITIAL_HASH;
    int arraySize = array.length;
    for (int i = 0; i < arraySize; i++) {
      hash = MULTIPLIER * hash + array[i];
    }
    return hash;
  }
  /**
   * Return a hash code based on the contents of the specified array.
   * If <code>array</code> is <code>null</code>, this method returns 0.
   */
  public static int nullSafeHashCode(long[] array) {
    if (array == null) {
      return 0;
    }
    int hash = INITIAL_HASH;
    int arraySize = array.length;
    for (int i = 0; i < arraySize; i++) {
      hash = MULTIPLIER * hash + hashCode(array[i]);
    }
    return hash;
  }
  /**
   * Return a hash code based on the contents of the specified array.
   * If <code>array</code> is <code>null</code>, this method returns 0.
   */
  public static int nullSafeHashCode(short[] array) {
    if (array == null) {
      return 0;
    }
    int hash = INITIAL_HASH;
    int arraySize = array.length;
    for (int i = 0; i < arraySize; i++) {
      hash = MULTIPLIER * hash + array[i];
    }
    return hash;
  }
  /**
   * Return the same value as <code>{@link Boolean#hashCode()}</code>.
   * @see Boolean#hashCode()
   */
  public static int hashCode(boolean bool) {
    return bool ? 1231 : 1237;
  }
  /**
   * Return the same value as <code>{@link Double#hashCode()}</code>.
   * @see Double#hashCode()
   */
  public static int hashCode(double dbl) {
    long bits = Double.doubleToLongBits(dbl);
    return hashCode(bits);
  }
  /**
   * Return the same value as <code>{@link Float#hashCode()}</code>.
   * @see Float#hashCode()
   */
  public static int hashCode(float flt) {
    return Float.floatToIntBits(flt);
  }
  /**
   * Return the same value as <code>{@link Long#hashCode()}</code>.
   * @see Long#hashCode()
   */
  public static int hashCode(long lng) {
    return (int) (lng ^ (lng >>> 32));
  }
}





Return as hash code for the given object

    
import java.lang.reflect.Array;
import java.util.Arrays;
/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
//Revised from springframework
/**
 * Miscellaneous object utility methods. Mainly for internal use within the
 * framework; consider Jakarta"s Commons Lang for a more comprehensive suite
 * of object utilities.
 *
 * @author Juergen Hoeller
 * @author Keith Donald
 * @author Rod Johnson
 * @author Rob Harrop
 * @author Alex Ruiz
 * @since 19.03.2004
 * @see org.apache.rumons.lang.ObjectUtils
 */
abstract class ObjectUtils {
  private static final int INITIAL_HASH = 7;
  private static final int MULTIPLIER = 31;
  private static final String EMPTY_STRING = "";
  private static final String NULL_STRING = "null";
  private static final String ARRAY_START = "{";
  private static final String ARRAY_END = "}";
  private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END;
  private static final String ARRAY_ELEMENT_SEPARATOR = ", ";
  /**
   * Return as hash code for the given object; typically the value of
   * <code>{@link Object#hashCode()}</code>. If the object is an array,
   * this method will delegate to any of the <code>nullSafeHashCode</code>
   * methods for arrays in this class. If the object is <code>null</code>,
   * this method returns 0.
   * @see #nullSafeHashCode(Object[])
   * @see #nullSafeHashCode(boolean[])
   * @see #nullSafeHashCode(byte[])
   * @see #nullSafeHashCode(char[])
   * @see #nullSafeHashCode(double[])
   * @see #nullSafeHashCode(float[])
   * @see #nullSafeHashCode(int[])
   * @see #nullSafeHashCode(long[])
   * @see #nullSafeHashCode(short[])
   */
  public static int nullSafeHashCode(Object obj) {
    if (obj == null) {
      return 0;
    }
    if (obj instanceof Object[]) {
      return nullSafeHashCode((Object[]) obj);
    }
    if (obj instanceof boolean[]) {
      return nullSafeHashCode((boolean[]) obj);
    }
    if (obj instanceof byte[]) {
      return nullSafeHashCode((byte[]) obj);
    }
    if (obj instanceof char[]) {
      return nullSafeHashCode((char[]) obj);
    }
    if (obj instanceof double[]) {
      return nullSafeHashCode((double[]) obj);
    }
    if (obj instanceof float[]) {
      return nullSafeHashCode((float[]) obj);
    }
    if (obj instanceof int[]) {
      return nullSafeHashCode((int[]) obj);
    }
    if (obj instanceof long[]) {
      return nullSafeHashCode((long[]) obj);
    }
    if (obj instanceof short[]) {
      return nullSafeHashCode((short[]) obj);
    }
    return obj.hashCode();
  }
}





Secure Hash

 
/*
 * JBoss DNA (http://www.jboss.org/dna)
 * See the COPYRIGHT.txt file distributed with this work for information
 * regarding copyright ownership.  Some portions may be licensed
 * to Red Hat, Inc. under one or more contributor license agreements.
 * See the AUTHORS.txt file in the distribution for a full listing of 
 * individual contributors. 
 *
 * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
 * is licensed to you under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * JBoss DNA 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
 * @author Randall Hauch
 */
public class SecureHash {
    /**
     * Commonly-used hashing algorithms.
     */
    public enum Algorithm {
        MD2("MD2", "The MD2 message digest algorithm as defined in RFC 1319"),
        MD5("MD5", "The MD5 message digest algorithm as defined in RFC 1321"),
        SHA_1("SHA-1", "The Secure Hash Algorithm, as defined in Secure Hash Standard, NIST FIPS 180-1"),
        SHA_256(
                "SHA-256",
                "New hash algorithms for which the draft Federal Information Processing Standard 180-2, "
                + "Secure Hash Standard (SHS) is now available.  SHA-256 is a 256-bit hash function intended to provide 128 bits of "
                + "security against collision attacks."),
        SHA_384(
                "SHA-384",
                "New hash algorithms for which the draft Federal Information Processing Standard 180-2, "
                + "Secure Hash Standard (SHS) is now available.  A 384-bit hash may be obtained by truncating the SHA-512 output."),
        SHA_512(
                "SHA-512",
                "New hash algorithms for which the draft Federal Information Processing Standard 180-2, "
                + "Secure Hash Standard (SHS) is now available.  SHA-512 is a 512-bit hash function intended to provide 256 bits of security.");
        private String name;
        private String description;
        private Algorithm( String name,
                           String description ) {
            this.name = name;
            this.description = description;
        }
        public String digestName() {
            return this.name;
        }
        public String description() {
            return this.description;
        }
        @Override
        public String toString() {
            return digestName();
        }
    }
    /**
     * Get the hash of the supplied content, using the supplied digest algorithm.
     * 
     * @param algorithm the hashing function algorithm that should be used
     * @param content the content to be hashed; may not be null
     * @return the hash of the contents as a byte array
     * @throws NoSuchAlgorithmException if the supplied algorithm could not be found
     * @throws IllegalArgumentException if the algorithm is null
     */
    public static byte[] getHash( Algorithm algorithm,
                                  byte[] content ) throws NoSuchAlgorithmException {
        return getHash(algorithm.digestName(), content);
    }
    /**
     * Get the hash of the supplied content, using the supplied digest algorithm.
     * 
     * @param algorithm the hashing function algorithm that should be used
     * @param file the file containing the content to be hashed; may not be null
     * @return the hash of the contents as a byte array
     * @throws NoSuchAlgorithmException if the supplied algorithm could not be found
     * @throws IllegalArgumentException if the algorithm is null
     * @throws IOException if there is an error reading the file
     */
    public static byte[] getHash( Algorithm algorithm,
                                  File file ) throws NoSuchAlgorithmException, IOException {
        return getHash(algorithm.digestName(), file);
    }
    /**
     * Get the hash of the supplied content, using the supplied digest algorithm.
     * 
     * @param algorithm the hashing function algorithm that should be used
     * @param stream the stream containing the content to be hashed; may not be null
     * @return the hash of the contents as a byte array
     * @throws NoSuchAlgorithmException if the supplied algorithm could not be found
     * @throws IllegalArgumentException if the algorithm is null
     * @throws IOException if there is an error reading the stream
     */
    public static byte[] getHash( Algorithm algorithm,
                                  InputStream stream ) throws NoSuchAlgorithmException, IOException {
        return getHash(algorithm.digestName(), stream);
    }
    /**
     * Get the hash of the supplied content, using the digest identified by the supplied name.
     * 
     * @param digestName the name of the hashing function (or {@link MessageDigest message digest}) that should be used
     * @param content the content to be hashed; may not be null
     * @return the hash of the contents as a byte array
     * @throws NoSuchAlgorithmException if the supplied algorithm could not be found
     */
    public static byte[] getHash( String digestName,
                                  byte[] content ) throws NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance(digestName);
        assert digest != null;
        return digest.digest(content);
    }
    /**
     * Get the hash of the supplied content, using the digest identified by the supplied name.
     * 
     * @param digestName the name of the hashing function (or {@link MessageDigest message digest}) that should be used
     * @param file the file whose content is to be hashed; may not be null
     * @return the hash of the contents as a byte array
     * @throws NoSuchAlgorithmException if the supplied algorithm could not be found
     * @throws IOException if there is an error reading the file
     */
    public static byte[] getHash( String digestName,
                                  File file ) throws NoSuchAlgorithmException, IOException {
        MessageDigest digest = MessageDigest.getInstance(digestName);
        assert digest != null;
        InputStream in = new BufferedInputStream(new FileInputStream(file));
        boolean error = false;
        try {
            int bufSize = 1024;
            byte[] buffer = new byte[bufSize];
            int n = in.read(buffer, 0, bufSize);
            int count = 0;
            while (n != -1) {
                count += n;
                digest.update(buffer, 0, n);
                n = in.read(buffer, 0, bufSize);
            }
        } catch (IOException e) {
            error = true;
            throw e;
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                if (!error) throw e;
            }
        }
        return digest.digest();
    }
    /**
     * Get the hash of the supplied content, using the digest identified by the supplied name. Note that this method never closes
     * the supplied stream.
     * 
     * @param digestName the name of the hashing function (or {@link MessageDigest message digest}) that should be used
     * @param stream the stream containing the content to be hashed; may not be null
     * @return the hash of the contents as a byte array
     * @throws NoSuchAlgorithmException if the supplied algorithm could not be found
     * @throws IOException if there is an error reading the stream
     */
    public static byte[] getHash( String digestName,
                                  InputStream stream ) throws NoSuchAlgorithmException, IOException {
        MessageDigest digest = MessageDigest.getInstance(digestName);
        assert digest != null;
        int bufSize = 1024;
        byte[] buffer = new byte[bufSize];
        int n = stream.read(buffer, 0, bufSize);
        int count = 0;
        while (n != -1) {
            count += n;
            digest.update(buffer, 0, n);
            n = stream.read(buffer, 0, bufSize);
        }
        return digest.digest();
    }
}





Unify Hash

     
/* UnifyHash Copyright (C) 1999-2002 Jochen Hoenicke.
 *
 * 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 2, 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 Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; see the file COPYING.LESSER.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: UnifyHash.java.in,v 1.3.2.2 2002/05/28 17:34:24 hoenicke Exp $
 */
///#ifdef JDK12
import java.lang.ref.WeakReference;
import java.lang.ref.ReferenceQueue;
///#endif
import java.util.ruparator;
import java.util.AbstractCollection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.ConcurrentModificationException;
import java.lang.UnsupportedOperationException;
public class UnifyHash extends AbstractCollection {
    /** 
     * the default capacity
     */
    private static final int DEFAULT_CAPACITY = 11;
    /** the default load factor of a HashMap */
    private static final float DEFAULT_LOAD_FACTOR = 0.75F;
///#ifdef JDK12
    private ReferenceQueue queue = new ReferenceQueue();
///#endif
    static class Bucket
///#ifdef JDK12
  extends WeakReference
///#endif
    {
///#ifdef JDK12
  public Bucket(Object o, ReferenceQueue q) {
      super(o, q);
  }
///#else
/// public Bucket(Object o) {
///     this.obj = o;
/// }
///
/// Object obj;
///
/// public Object get() {
///     return obj;
/// }
///#endif
  int hash;
  Bucket next;
    }
    private Bucket[] buckets;
    int modCount = 0;
    int size = 0;
    int threshold;
    float loadFactor;
    public UnifyHash(int initialCapacity, float loadFactor) {
  this.loadFactor = loadFactor;
  buckets = new Bucket[initialCapacity];
  threshold = (int) (loadFactor * initialCapacity);
    }
    public UnifyHash(int initialCapacity) {
  this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }
    public UnifyHash() {
  this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
    }
    private void grow() {
  Bucket[] oldBuckets = buckets;
  int newCap = buckets.length * 2 + 1;
  threshold = (int) (loadFactor * newCap);
  buckets = new Bucket[newCap];
  for (int i = 0; i < oldBuckets.length; i++) {
      Bucket nextBucket;
      for (Bucket b = oldBuckets[i]; b != null; b = nextBucket) {
    if (i != Math.abs(b.hash % oldBuckets.length))
        throw new RuntimeException(""+i+", hash: "+b.hash+", oldlength: "+oldBuckets.length);
    int newSlot = Math.abs(b.hash % newCap);
    nextBucket = b.next;
    b.next = buckets[newSlot];
    buckets[newSlot] = b;
      }
  }
    }
///#ifdef JDK12
    public final void cleanUp() {
  Bucket died;
  while ((died = (Bucket)queue.poll()) != null) {
      int diedSlot = Math.abs(died.hash % buckets.length);
      if (buckets[diedSlot] == died)
    buckets[diedSlot] = died.next;
      else {
    Bucket b = buckets[diedSlot];
    while (b.next != died)
        b = b.next;
    b.next = died.next;
      }
      size--;
  }
    }
///#endif

    public int size() {
  return size;
    }
    public Iterator iterator() {
///#ifdef JDK12
  cleanUp();
///#endif
  return new Iterator() {
      private int bucket = 0;
      private int known = modCount;
      private Bucket nextBucket;
      private Object nextVal;
      {
    internalNext();
      }
      private void internalNext() {
    while (true) {
        while (nextBucket == null) {
      if (bucket == buckets.length)
          return;
      nextBucket = buckets[bucket++];
        }
        
        nextVal = nextBucket.get();
        if (nextVal != null)
      return;
        nextBucket = nextBucket.next;
    }
      }
      public boolean hasNext() {
    return nextBucket != null;
      }
      public Object next() {
    if (known != modCount)
        throw new ConcurrentModificationException();
    if (nextBucket == null)
        throw new NoSuchElementException();
    Object result = nextVal;
    nextBucket = nextBucket.next;
    internalNext();
    return result;
      }
      public void remove() {
    throw new UnsupportedOperationException();
      }
  };
    }
    public Iterator iterateHashCode(final int hash) {
///#ifdef JDK12
  cleanUp();
///#endif
  return new Iterator() {
      private int known = modCount;
      private Bucket nextBucket
    = buckets[Math.abs(hash % buckets.length)];
      private Object nextVal;
      {
    internalNext();
      }
      private void internalNext() {
    while (nextBucket != null) {
        if (nextBucket.hash == hash) {
      nextVal = nextBucket.get();
      if (nextVal != null)
          return;
        }
        nextBucket = nextBucket.next;
    }
      }
      public boolean hasNext() {
    return nextBucket != null;
      }
      public Object next() {
    if (known != modCount)
        throw new ConcurrentModificationException();
    if (nextBucket == null)
        throw new NoSuchElementException();
    Object result = nextVal;
    nextBucket = nextBucket.next;
    internalNext();
    return result;
      }
      public void remove() {
    throw new UnsupportedOperationException();
      }
  };
    }
    public void put(int hash, Object o) {
  if (size++ > threshold)
      grow();
  modCount++;
  int slot = Math.abs(hash % buckets.length);
///#ifdef JDK12
  Bucket b = new Bucket(o, queue);
///#else
/// Bucket b = new Bucket(o);
///#endif
  b.hash = hash;
  b.next = buckets[slot];
  buckets[slot] = b;
    }
    public Object unify(Object o, int hash, Comparator comparator) {
///#ifdef JDK12
  cleanUp();
///#endif
  int slot = Math.abs(hash % buckets.length);
  for (Bucket b = buckets[slot]; b != null; b = b.next) {
      Object old = b.get();
      if (old != null && comparator.rupare(o, old) == 0)
    return old;
  }
  put(hash, o);
  return o;
    }
}