User: starksm 
  Date: 02/02/26 21:40:18

  Modified:    src/main/org/jboss/invocation MarshalledInvocation.java
  Added:       src/main/org/jboss/invocation MarshalledValue.java
                        MarshalledValueInputStream.java
                        MarshalledValueOutputStream.java
  Log:
  Replace MarshalledObject with MarshalledValue in MarshalledInvocation so
  that class and proxy resolution are done with the thread context class
  loader.
  
  Revision  Changes    Path
  1.4       +68 -78    jboss/src/main/org/jboss/invocation/MarshalledInvocation.java
  
  Index: MarshalledInvocation.java
  ===================================================================
  RCS file: 
/cvsroot/jboss/jboss/src/main/org/jboss/invocation/MarshalledInvocation.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- MarshalledInvocation.java 13 Jan 2002 16:28:55 -0000      1.3
  +++ MarshalledInvocation.java 27 Feb 2002 05:40:18 -0000      1.4
  @@ -6,49 +6,25 @@
   */
   package org.jboss.invocation;
   
  -import java.util.Map;
  -import java.util.Iterator;
  -import java.util.HashMap;
  -import java.util.WeakHashMap;
  -import java.lang.reflect.Method;
   import java.io.DataOutputStream;
   import java.io.ByteArrayInputStream;
   import java.io.ByteArrayOutputStream;
   import java.io.IOException;
  -import java.rmi.MarshalledObject;
  -
  -
  -import java.security.Principal;
  -import java.security.MessageDigest;
  -import java.security.DigestOutputStream;
  -
  -import javax.transaction.Transaction;
  -
  -import org.jboss.invocation.Invocation;
  -
  -/*
  -import java.io.ByteArrayInputStream;
  -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.security.DigestOutputStream;
  +import java.security.MessageDigest;
  +import java.security.Principal;
   import java.util.Map;
  -import java.util.WeakHashMap;
  +import java.util.Iterator;
   import java.util.HashMap;
  -
  -import java.security.Principal;
  -import java.security.MessageDigest;
  -import java.security.DigestOutputStream;
  -
  +import java.util.WeakHashMap;
   import javax.transaction.Transaction;
  -*/
  +
  +import org.jboss.invocation.Invocation;
   
   /**
  -*
  -* The MarshalledInvocation is an invocation that travels.  As such it serializes 
its payload because of lack of ClassLoader visibility.
  +* The MarshalledInvocation is an invocation that travels.  As such it serializes
  +* its payload because of lack of ClassLoader visibility.
   * As such it contains Marshalled data representing the byte[] of the Invocation 
object it extends
   * Besides handling the specifics of "marshalling" the payload, which could be done 
at the Invocation level
   * the Marshalled Invocation can hold optimization and needed code for distribution 
for example the 
  @@ -58,7 +34,7 @@
   *
   *   @see <related>
   *   @author  <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
  -*   @version $Revision: 1.3 $
  +*   @version $Revision: 1.4 $
   *   Revisions:
   *
   *   <p><b>Revisions:</b>
  @@ -77,25 +53,23 @@
   *   </ul>
   */
   public class MarshalledInvocation
  -extends Invocation
  -implements java.io.Externalizable
  +   extends Invocation
  +   implements java.io.Externalizable
   {
      // Constants -----------------------------------------------------
      
      /** Serial Version Identifier. */
  -   // FIXME TODO 
  -   
  +   static final long serialVersionUID = -718723094688127810L;
  +
      // The Transaction Propagation Context for distribution
      Object tpc;
      
      // The Map of methods used by this Invocation
      transient Map methodMap;
      
  -   
      // Static --------------------------------------------------------
      static Map hashMap = new WeakHashMap();
  -   
  -   
  +
      /**
      * Calculate method hashes. This algo is taken from RMI.
      *
  @@ -134,7 +108,8 @@
               else 
                  map.put(new Long(hash), method);
                  
  -         } catch (Exception e)
  +         }
  +         catch (Exception e)
            {
               e.printStackTrace();
            }
  @@ -142,7 +117,7 @@
         
         return map;
      }
  -   
  +
      static String getTypeString(Class cl)
      {
         if (cl == Byte.TYPE)
  @@ -180,7 +155,7 @@
            return "L"+cl.getName().replace('.','/')+";";
         }
      }
  -   
  +
      /*
      * The use of hashCode is not enough to differenciate methods
      * we override the hashCode
  @@ -234,10 +209,10 @@
      {
         Object value = getValue(METHOD);
         
  -      if (value instanceof Method) return (Method) value;
  -         
  -      else {
  -         
  +      if (value instanceof Method)
  +         return (Method) value;  
  +      else
  +      {   
            // Try the hash, the methodMap should be set
            Method m = (Method)methodMap.get(value);
            
  @@ -248,48 +223,62 @@
               
               return m;
            }
  -         
            // This is a bug barf
            else 
            {
               throw new NullPointerException("METHOD IS NOT FOUND: "+value);
            }
  -      
         }
      }
      
      
  -   public void setMethodMap(Map methods) { methodMap = methods; }
  -   
  -   
  +   public void setMethodMap(Map methods)
  +   {
  +      methodMap = methods;
  +   }
  +
      // The transaction propagation context for the Invocation that travels 
(distributed tx only)
  -   public void setTransactionPropagationContext(Object tpc) { this.tpc = tpc; }
  -   public Object getTransactionPropagationContext() { return tpc; }
  -   
  +   public void setTransactionPropagationContext(Object tpc)
  +   {
  +      this.tpc = tpc;
  +   }
  +   public Object getTransactionPropagationContext()
  +   {
  +      return tpc;
  +   }
  +
      // Invocation overwrite -----------------------------------------
  -   
  -   // A Marshalled invocation has serialized data in the form of 
java.rmi.Marshalled 
  -   // We overwrite the "getValue" to deserialize the data, this assume that the 
thread context
  -   // class loader has visibility on the classes.
  +
  +   /** A Marshalled invocation has serialized data in the form of
  +    MarshalledValue objects. We overwrite the "getValue" to deserialize the
  +    data, this assume that the thread context class loader has visibility
  +    on the classes.
  +    */
      public Object getValue(Object key) 
      { 
         Object value = payload.get(key);
         
         // The map may contain serialized values of the fields
  -      if (value instanceof java.rmi.MarshalledObject) { 
  -         
  -         try { return ((MarshalledObject) value).get(); }
  -            
  +      if (value instanceof MarshalledValue)
  +      {
  +         try
  +         {
  +            MarshalledValue mv = (MarshalledValue) value;
  +            value = mv.get();
  +         }   
            // Barf and return null
  -         catch (Exception e) { e.printStackTrace();return null; }
  +         catch (Exception e)
  +         {
  +            e.printStackTrace();
  +            value = null;
  +         }
         }
  -      
  -      else return value;
  +      return value;
      }
  -   
  +
      // Externalizable implementation ---------------------------------
      public void writeExternal(java.io.ObjectOutput out)
  -   throws IOException
  +      throws IOException
      {
         
         // Write the TPC, not the local transaction
  @@ -297,10 +286,10 @@
         
         HashMap sentData = new HashMap ();
         
  -      // Everything else is possibly tied to classloaders that exist inside the 
server but not in 
  -      // the generic JMX land. 
  -      // they will travel in the  payload as Marshalled Object, see the Invocation 
getter logic
  -      
  +      /* Everything else is possibly tied to classloaders that exist inside the
  +      server but not in the generic JMX land. they will travel in the  payload
  +      as MarshalledValue objects, see the Invocation getter logic
  +      */
         // FIXME MARCF: we can put some optimizations in what we serialize and not, 
for example
         // classes that come from the JDK will be present at deserialization on the 
server side. 
         // So there is no need to marshal a "Principal" for example. 
  @@ -308,9 +297,10 @@
         // think about time, test these string manipulation to see if it is good 
(test method arguments
         // with native object and with extensions... compare)
         Iterator keys = payload.keySet().iterator();
  -      while (keys.hasNext()) {
  +      while (keys.hasNext())
  +      {
            Object currentKey = keys.next();
  -         
  +   
            // This code could be if (object.getClass().getName().startsWith("java")) 
then don't serialize. 
            // Bench the above for speed.
            
  @@ -321,16 +311,16 @@
                  // We write the hash instead of the method
                  sentData.put(METHOD, new Long(calculateHash((Method) 
payload.get(METHOD))));
               else
  -               sentData.put (currentKey, new 
MarshalledObject(payload.get(currentKey)));
  +               sentData.put (currentKey, new 
MarshalledValue(payload.get(currentKey)));
            }
         }
         
         // The map contains only serialized representations of every other object
         out.writeObject(sentData);
      }
  -   
  +
      public void readExternal(java.io.ObjectInput in)
  -   throws IOException, ClassNotFoundException
  +      throws IOException, ClassNotFoundException
      {
         // Read TPC
         tpc = in.readObject();
  
  
  
  1.1                  jboss/src/main/org/jboss/invocation/MarshalledValue.java
  
  Index: MarshalledValue.java
  ===================================================================
  /*
  * JBoss, the OpenSource J2EE webOS
  *
  * Distributable under LGPL license.
  * See terms of license at gnu.org.
  */
  package org.jboss.invocation;
  
  import java.io.DataOutputStream;
  import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.ObjectInput;
  import java.io.ObjectOutput;
  import java.util.Arrays;
  
  /** A simple replacement for the RMI MarshalledObject that uses the thread
   context class loader for resolving classes and proxies. This currently does
   not support class annotations and dynamic class loading.
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
  */
  public class MarshalledValue implements java.io.Externalizable
  {
     // Constants -----------------------------------------------------
     
     /** Serial Version Identifier. */
     static final long serialVersionUID = -1527598981234110311L;
  
     /** The serialized form of the value. If <code>serializedForm</code> is
     * <code>null</code> then the object marshalled was a <code>null</code>
     * reference.
     */
     private byte[] serializedForm = null;
     /** The RMI MarshalledObject hash of the serializedForm array
      */
     private int hashCode;
  
     public MarshalledValue()
     {
     }
  
     public MarshalledValue(Object obj) throws IOException
     {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        MarshalledValueOutputStream mvos = new MarshalledValueOutputStream(baos);
        mvos.writeObject(obj);
        mvos.flush();
        serializedForm = baos.toByteArray();
  
        // Use the java.rmi.MarshalledObject hash code calculation
        int hash = 0;
        for (int i = 0; i < serializedForm.length; i++)
        {
            hash = 31 * hash + serializedForm[i];
        }
        hashCode = hash;
     }
  
     public Object get() throws IOException, ClassNotFoundException
     {
        if( serializedForm == null )
           return null;
  
        ByteArrayInputStream bais = new ByteArrayInputStream(serializedForm);
        MarshalledValueInputStream mvis = new MarshalledValueInputStream(bais);
        return mvis.readObject();
     }
  
     /** Return a hash code for the serialized form of the value.
     *
     * @return the serialized form value hash.
     */
     public int hashCode()
     {
        return hashCode;
     }
  
     public boolean equals(Object obj)
     {
        if( this == obj )
           return true;
  
        boolean equals = false;
        if( obj instanceof MarshalledValue )
        {
           MarshalledValue mv = (MarshalledValue) obj;
           if( serializedForm == mv.serializedForm )
           {
              equals = true;
           }
           else
           {
              equals = Arrays.equals(serializedForm, mv.serializedForm);
           }
        }
        return equals;
     }
     
     /**
      * The object implements the readExternal method to restore its
      * contents by calling the methods of DataInput for primitive
      * types and readObject for objects, strings and arrays.  The
      * readExternal method must read the values in the same sequence
      * and with the same types as were written by writeExternal.
      *
      * @param in the stream to read data from in order to restore the object
      * @exception IOException if I/O errors occur
      * @exception ClassNotFoundException If the class for an object being
      *             restored cannot be found.
      */
     public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException
     {
        int length = in.readInt();
        serializedForm = null;
        if( length > 0 )
        {
           serializedForm = new byte[length];
           in.readFully(serializedForm);
        }
        hashCode = in.readInt();
     }
  
     /**
      * The object implements the writeExternal method to save its contents
      * by calling the methods of DataOutput for its primitive values or
      * calling the writeObject method of ObjectOutput for objects, strings,
      * and arrays.
      *
      * @serialData Overriding methods should use this tag to describe
      *            the data layout of this Externalizable object.
      *            List the sequence of element types and, if possible,
      *            relate the element to a public/protected field and/or
      *            method of this Externalizable class.
      *
      * @param out the stream to write the object to
      * @exception IOException Includes any I/O exceptions that may occur
      */
     public void writeExternal(ObjectOutput out) throws IOException
     {
        int length = serializedForm != null ? serializedForm.length : 0;
        out.writeInt(length);
        if( length > 0 )
        {
           out.write(serializedForm);
        }
        out.writeInt(hashCode);
     }
  
  }
  
  
  
  1.1                  
jboss/src/main/org/jboss/invocation/MarshalledValueInputStream.java
  
  Index: MarshalledValueInputStream.java
  ===================================================================
  /*
  * JBoss, the OpenSource J2EE webOS
  *
  * Distributable under LGPL license.
  * See terms of license at gnu.org.
  */
  package org.jboss.invocation;
  
  import java.io.InputStream;
  import java.io.IOException;
  import java.io.ObjectInputStream;
  import java.io.ObjectStreamClass;
  
  import org.jboss.logging.Logger;
  
  /** An ObjectInputStream subclass used by the MarshalledValue class to
   ensure the classes and proxies are loaded using the thread context
   class loader.
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
   */
  public class MarshalledValueInputStream extends ObjectInputStream
  {
     private static Logger log = Logger.getLogger(MarshalledValueInputStream.class);
  
     /** Creates a new instance of MarshalledValueOutputStream */
     public MarshalledValueInputStream(InputStream is) throws IOException
     {
        super(is);
     }
  
     /** Use the thread context class loader to resolve the class
      * @exception IOException Any exception thrown by the underlying OutputStream.
      */
     protected Class resolveClass(ObjectStreamClass v) throws IOException,
        ClassNotFoundException
     {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        String className = v.getName();
        return loader.loadClass(className);
     }
  
     protected Class resolveProxyClass(String[] interfaces) throws IOException,
        ClassNotFoundException
     {
        if( log.isDebugEnabled() )
        {
           StringBuffer tmp = new StringBuffer("[");
           for(int i = 0; i < interfaces.length; i ++)
           {
              if( i > 0 )
                 tmp.append(',');
              tmp.append(interfaces[i]);
           }
           tmp.append(']');
           log.debug("resolveProxyClass called, ifaces="+tmp.toString());
        }
        // Load the interfaces from the thread context class loader
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        Class[] ifaceClasses = new Class[interfaces.length];
        for (int i = 0; i < interfaces.length; i++)
        {
            ifaceClasses[i] = loader.loadClass(interfaces[i]);
        }
        return java.lang.reflect.Proxy.getProxyClass(loader, ifaceClasses);
     }
  }
  
  
  
  1.1                  
jboss/src/main/org/jboss/invocation/MarshalledValueOutputStream.java
  
  Index: MarshalledValueOutputStream.java
  ===================================================================
  /*
  * JBoss, the OpenSource J2EE webOS
  *
  * Distributable under LGPL license.
  * See terms of license at gnu.org.
  */
  package org.jboss.invocation;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.ObjectOutputStream;
  
  import org.jboss.logging.Logger;
  
  /** An ObjectOutputStream subclass used by the MarshalledValue class to
   ensure the classes and proxies are loaded using the thread context
   class loader. Currently this does not do anything as neither class or
   proxy annotations are used.
  
  @author [EMAIL PROTECTED]
  @version $Revision: 1.1 $
   */
  public class MarshalledValueOutputStream extends ObjectOutputStream
  {
     private static Logger log = Logger.getLogger(MarshalledValueInputStream.class);
  
     /** Creates a new instance of MarshalledValueOutputStream */
     public MarshalledValueOutputStream(OutputStream os) throws IOException
     {
        super(os);
     }
  
     /**
      * @exception IOException Any exception thrown by the underlying OutputStream.
      */
     protected void annotateClass(Class cl) throws IOException
     {
        super.annotateClass(cl);
     }
     
     /**
      * @exception IOException Any exception thrown by the underlying OutputStream.
      */
     protected void annotateProxyClass(Class cl) throws IOException
     {
        super.annotateProxyClass(cl);
     }
  
  }
  
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to