/* JFox, the OpenSource J2EE Application Server
 *
 * Copyright (C) 2002 huihoo.com
 * Distributable under GNU LGPL license
 * See the GNU Lesser General Public License for more details.
 */

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) {

  }
}