/* JFox, the OpenSource J2EE Application Server
 *
 * Distributable under GNU LGPL license by gun.org
 * more details please visit http://www.huihoo.org/jfox
 */

package org.jfox.ejb;

import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public final class MethodHasher {

    private static MessageDigest md5 = null;

    static {
        try {
            md5 = MessageDigest.getInstance("MD5");
        }
        catch(NoSuchAlgorithmException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 得到一个 method 的 hashCode ，可以唯一的标志一个 method
     *
     * @param method
     * @return
     */
    public static long getMethodHash(Method method) {
        long hash = 0;
        Class[] parameterTypes = method.getParameterTypes();
        String methodDesc = method.getName() + "(";
        for(int j = 0; j < parameterTypes.length; j++) {
            methodDesc += getTypeString(parameterTypes[j]);
        }
        methodDesc += ")" + getTypeString(method.getReturnType());

        try {
            byte[] bytes = md5.digest(methodDesc.getBytes("ISO-8859-1"));
            for(int j = 0; j < Math.min(8, bytes.length); j++) {
                hash += (long) (bytes[j] & 0xff) << j * 8;
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }
        return hash;
    }

    private static String getTypeString(Class cl) {
        if(cl == Byte.TYPE) {
            return "B";
        }
        else if(cl == Character.TYPE) {
            return "C";
        }
        else if(cl == Double.TYPE) {
            return "D";
        }
        else if(cl == Float.TYPE) {
            return "F";
        }
        else if(cl == Integer.TYPE) {
            return "I";
        }
        else if(cl == Long.TYPE) {
            return "J";
        }
        else if(cl == Short.TYPE) {
            return "S";
        }
        else if(cl == Boolean.TYPE) {
            return "Z";
        }
        else if(cl == Void.TYPE) {
            return "V";
        }
        else if(cl.isArray()) {
            return "[" + getTypeString(cl.getComponentType());
        }
        else {
            return "L" + cl.getName().replace('.', '/') + ";";
        }
    }

    public static void main(String[] args) {

    }
}
