User: oberg   
  Date: 01/02/21 01:55:27

  Modified:    src/main/org/jboss/ejb/plugins/jrmp/interfaces
                        RemoteMethodInvocation.java
  Log:
  Removed className (wasn't used)
  Changed hash calc algo to that of RMI
  Now caches hash calcs.
  
  Revision  Changes    Path
  1.12      +120 -39   
jboss/src/main/org/jboss/ejb/plugins/jrmp/interfaces/RemoteMethodInvocation.java
  
  Index: RemoteMethodInvocation.java
  ===================================================================
  RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/jrmp/interfaces/RemoteMethodInvocation.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- RemoteMethodInvocation.java       2001/02/09 18:56:15     1.11
  +++ RemoteMethodInvocation.java       2001/02/21 09:55:27     1.12
  @@ -10,11 +10,17 @@
   import java.io.ByteArrayOutputStream;
   import java.io.ObjectInputStream;
   import java.io.ObjectOutputStream;
  +import java.io.DataOutputStream;
   import java.io.IOException;
   import java.lang.reflect.Method;
  +import java.util.Collections;
   import java.util.Map;
  +import java.util.WeakHashMap;
  +import java.util.HashMap;
   
   import java.security.Principal;
  +import java.security.MessageDigest;
  +import java.security.DigestOutputStream;
   
   import javax.transaction.Transaction;
   
  @@ -28,7 +34,7 @@
    *  @author <a href="mailto:[EMAIL PROTECTED]">Richard 
Monson-Haefel</a>.
    *  @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>.
    *  @author <a href="mailto:[EMAIL PROTECTED]">Daniel O'Connor</a>.
  - *  @version $Revision: 1.11 $
  + *  @version $Revision: 1.12 $
    */
   public final class RemoteMethodInvocation
      implements java.io.Externalizable
  @@ -37,8 +43,8 @@
   
      // Attributes ----------------------------------------------------
      Object id;
  -   String className;
  -   int hash;
  +//   String className;
  +   long hash;
        
      Object[] args;
   
  @@ -47,37 +53,115 @@
      private Object credential;
        
      transient Map methodMap;
  -
  +   
      // Static --------------------------------------------------------
  +   static Map hashMap = new WeakHashMap();
  +
   
  +     /**
  +      * Calculate method hashes. This algo is taken from RMI.
  +      *
  +      * @param   intf  
  +      * @return     
  +      */
  +   public static Map getInterfaceHashes(Class intf)
  +   {
  +      // Create method hashes
  +      Method[] methods = intf.getDeclaredMethods();
  +      HashMap map = new HashMap();
  +      for (int i = 0; i < methods.length; i++)
  +      {
  +         Method method = methods[i];
  +         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
  +         {
  +            long hash = 0;
  +            ByteArrayOutputStream bytearrayoutputstream = new 
ByteArrayOutputStream(512);
  +            MessageDigest messagedigest = MessageDigest.getInstance("SHA");
  +            DataOutputStream dataoutputstream = new DataOutputStream(new 
DigestOutputStream(bytearrayoutputstream, messagedigest));
  +            dataoutputstream.writeUTF(methodDesc);
  +            dataoutputstream.flush();
  +            byte abyte0[] = messagedigest.digest();
  +            for(int j = 0; j < Math.min(8, abyte0.length); j++)
  +              hash += (long)(abyte0[j] & 0xff) << j * 8;
  +            map.put(method, new Long(hash));
  +         } catch (Exception e)
  +         {
  +            e.printStackTrace();
  +         }
  +      }
  +      
  +      return map;
  +   }
  +
  +   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('.','/')+";";
  +      }
  +   }
  +   
      /*
      * The use of hashCode is not enough to differenciate methods
      * we override the hashCode
  -   *
  -   * This is taken from the RMH code in EJBoss 0.9
      *
  +   * The hashes are cached in a static for efficiency
  +   * RO: WeakHashMap needed to support undeploy
      */
  -   public static int calculateHash(Method method)
  +   public static long calculateHash(Method method)
      {
  -      int hash =
  -          // We use the declaring class
  -          method.getDeclaringClass().getName().hashCode() ^ //name of class
  -          // We use the name of the method
  -          method.getName().hashCode(); //name of method
  -
  -      Class[] clazz = method.getParameterTypes();
  -
  -      for (int i = 0; i < clazz.length; i++) {
  -         // XOR
  -         // We use the constant because
  -         // a^b^b = a (thank you norbert)
  -         // so that methodA() hashes to methodA(String, String)
  -
  -         hash = (hash +20000) ^ clazz[i].getName().hashCode();
  +      Map methodHashes = (Map)hashMap.get(method.getDeclaringClass());
  +      
  +      if (methodHashes == null)
  +      {
  +         methodHashes = getInterfaceHashes(method.getDeclaringClass());
  +         
  +         // Copy and add
  +         WeakHashMap newHashMap = new WeakHashMap();
  +         newHashMap.putAll(hashMap);
  +         newHashMap.put(method.getDeclaringClass(), methodHashes);
  +         hashMap = newHashMap;
         }
  -
  -      //DEBUGSystem.out.println(method+"="+hash);
  -      return hash;
  +   
  +      return ((Long)methodHashes.get(method)).longValue();
      }
        
      // Constructors --------------------------------------------------
  @@ -96,7 +180,7 @@
         this.id = id;
         this.args = args;
         this.hash = calculateHash(m);
  -      this.className = m.getDeclaringClass().getName();
  +//      this.className = m.getDeclaringClass().getName();
      }
        
      // Public --------------------------------------------------------
  @@ -106,7 +190,12 @@
   
      public Method getMethod()
      {
  -      return (Method)methodMap.get(new Integer(hash));
  +      Method m = (Method)methodMap.get(new Long(hash));
  +      
  +      if (m == null)
  +         throw new NullPointerException("METHOD IS NOT FOUND:"+hash+" "+methodMap);
  +      
  +      return (Method)methodMap.get(new Long(hash));
      }
   
      public Object[] getArguments()
  @@ -148,16 +237,13 @@
      {
         this.credential = credential;
      }
  -      
  -   // Package protected ---------------------------------------------
  -
  -   // Protected -----------------------------------------------------
  +     
  +   // Externalizable implementation ---------------------------------
      public void writeExternal(java.io.ObjectOutput out)
         throws IOException
      {
         out.writeObject(id);
  -      out.writeUTF(className);
  -      out.writeInt(hash);
  +      out.writeLong(hash);
         out.writeObject(args);
   
         out.writeObject(tpc);
  @@ -169,17 +255,12 @@
         throws IOException, ClassNotFoundException
      {
         id = in.readObject();
  -      className = in.readUTF();
  -      hash = in.readInt();
  +      hash = in.readLong();
         args = (Object[])in.readObject();
   
         tpc = in.readObject();
         identity = (Principal)in.readObject();
         credential = in.readObject();
      }
  -
  -   // Private -------------------------------------------------------
  -     
  -   // Inner classes -------------------------------------------------
   }
   
  
  
  

Reply via email to