mx4j/src/core/mx4j/remote/rmi Marshaller.java,NONE,1.1 RMIMarshaller.java,1.7,1.8

[email protected]
Newsgroups gmane.comp.java.mx4j.cvs
Message-ID <[email protected]>
Update of /cvsroot/mx4j/mx4j/src/core/mx4j/remote/rmi
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27925/src/core/mx4j/remote/rmi

Modified Files:
	RMIMarshaller.java 
Added Files:
	Marshaller.java 
Log Message:
Fixed RMI Marshalling bug

--- NEW FILE: Marshaller.java ---
/*
 * Copyright (C) MX4J.
 * All rights reserved.
 *
 * This software is distributed under the terms of the MX4J License version 1.0.
 * See the terms of the MX4J License in the documentation provided with this software.
 */

package mx4j.remote.rmi;

import java.io.IOException;
import java.rmi.MarshalledObject;

/**
 * IMPORTANT: see {@link RMIMarshaller}
 * @author <a href="mailto:[email protected]">Simone Bordet</a>
 * @version $Revision: 1.1 $
 */
public class Marshaller
{
   public static Object unmarshal(MarshalledObject obj) throws IOException, ClassNotFoundException
   {
      return obj.get();
   }
}

Index: RMIMarshaller.java
===================================================================
RCS file: /cvsroot/mx4j/mx4j/src/core/mx4j/remote/rmi/RMIMarshaller.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** RMIMarshaller.java	1 Mar 2004 18:19:55 -0000	1.7
--- RMIMarshaller.java	10 Mar 2004 18:33:35 -0000	1.8
***************
*** 9,25 ****
  package mx4j.remote.rmi;
  
  import java.io.IOException;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.net.URL;
- import java.net.URLClassLoader;
  import java.rmi.MarshalledObject;
  import java.security.AccessController;
  import java.security.PrivilegedAction;
  import java.security.PrivilegedActionException;
  import java.security.PrivilegedExceptionAction;
  
  /**
!  * Marshaller/Unmarshaller for RMI's MarshalledObjects.
   *
   * @author <a href="mailto:[email protected]">Simone Bordet</a>
--- 9,61 ----
  package mx4j.remote.rmi;
  
+ import java.io.BufferedInputStream;
+ import java.io.BufferedOutputStream;
+ import java.io.ByteArrayOutputStream;
  import java.io.IOException;
+ import java.io.InputStream;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.net.URL;
  import java.rmi.MarshalledObject;
  import java.security.AccessController;
  import java.security.PrivilegedAction;
+ import java.security.SecureClassLoader;
  import java.security.PrivilegedActionException;
  import java.security.PrivilegedExceptionAction;
  
  /**
!  * Marshaller/Unmarshaller for RMI's MarshalledObjects. <br />
!  *
!  * This class implements the JMX Remote Specification, chapter 2. <br />
!  * <strong>
!  * Don't touch unless discussed on [email protected], and unless
!  * you know what you're doing (included who wrote this javadoc).
!  * </strong>
!  * <br />
!  * IMPLEMENTATION NOTES: <br />
!  * MarshalledObject.get() loads the object it contains by using the first user-defined classloader it can find
!  * in the stack frames of the call. <br />
!  * If the class cannot be found with that loader, then the RMI semantic is tried: first the thread context
!  * classloader, then dynamic code download (if there is a security manager). <br />
!  * We need that MarshalledObject.get() unmarshals using the context classloader and not the first user-defined
!  * classloader, since this way we can implement correctly the JMX specification (see
!  * {@link #unmarshal(MarshalledObject, ClassLoader, ClassLoader)}). <br />
!  * Here we load the {@link Marshaller} class using {@link MarshallerClassLoader} that can only load the
!  * {@link Marshaller} class.
!  * It is important that {@link MarshallerClassLoader} cannot load from the classpath (the system classloader)
!  * since that would break the JMX Remote Specification compliance. <br />
!  * This URLClassLoader then becomes the first user-defined classloader in the stack frames, but it will fail
!  * to load anything else, thus allowing MarshalledObject.get() to use the thread context classloader.
!  * The stack trace will be something like:
!  * <pre>
!  * {@link Marshaller#unmarshal} [MarshallerClassLoader]
!  *   ... reflection classes ... [Boot ClassLoader]
!  *     {@link RMIMarshaller#unmarshal(MarshalledObject)} [System ClassLoader (normally)]
!  * </pre>
!  * <br />
!  * Note that the classloader that loaded this class may be something totally different from URLClassLoader:
!  * this is the case for the <a href="http://www.osgi.org">OSGi</a>. <br />
!  * We just rely on the {@link ClassLoader#getResourceAsStream(java.lang.String)} semantic to load the
!  * {@link Marshaller} class' bytes.
   *
   * @author <a href="mailto:[email protected]">Simone Bordet</a>
***************
*** 28,63 ****
  class RMIMarshaller
  {
!    private static Method unmarshal;
  
!    /**
!     * MarshalledObject.get() loads the object it contains by using the first user-defined classloader it can find
!     * in the stack frames of the call.
!     * In a normal usage of JSR 160, this classloader is the one that loaded this class, most probably
!     * the system classloader.
!     * If the class cannot be found with that loader, then the RMI semantic is tried: first the thread context
!     * classloader, then dynamic code download (if there is a security manager).
!     * Here we load the Marshaller class using an URLClassLoader that is only able to load classes from the URL
!     * where it loaded this class, thus it cannot see other classes in the system classloader.
!     * This URLClassLoader then becomes the first user-defined classloader in the stack frames, but it will fail
!     * to load anything else, thus allowing MarshalledObject.get() to use the thread context classloader.
!     */
!    static
     {
        try
        {
!          AccessController.doPrivileged(new PrivilegedExceptionAction()
!          {
!             public Object run() throws Exception
!             {
!                URL url = RMIMarshaller.class.getProtectionDomain().getCodeSource().getLocation();
!                // TODO: is it enough to use the parent, or maybe better use null as parent classloader ?
!                URLClassLoader loader = new URLClassLoader(new URL[] {url}, RMIMarshaller.class.getClassLoader().getParent());
!                Class marshaller = loader.loadClass(Marshaller.class.getName());
!                unmarshal = marshaller.getMethod("unmarshal", new Class[] {MarshalledObject.class});
!                return null;
!             }
!          });
        }
!       catch (PrivilegedActionException x)
        {
           throw new Error(x.toString());
--- 64,104 ----
  class RMIMarshaller
  {
!    private static final Method unmarshal = getUnmarshalMethod();
  
!    private static Method getUnmarshalMethod()
     {
+       String marshallerName = Marshaller.class.getName();
+       InputStream stream = Marshaller.class.getResourceAsStream(marshallerName.substring(marshallerName.lastIndexOf('.') + 1) + ".class");
+       if (stream == null) throw new Error("Could not load implementation class " + marshallerName);
+       BufferedInputStream bis = new BufferedInputStream(stream);
+       ByteArrayOutputStream baos = new ByteArrayOutputStream();
+       BufferedOutputStream bos = new BufferedOutputStream(baos);
        try
        {
!          byte[] buffer = new byte[256];
!          int read = -1;
!          while ((read = bis.read(buffer)) >= 0) bos.write(buffer, 0, read);
!          bis.close();
!          bos.close();
        }
!       catch (IOException x)
!       {
!          throw new Error(x.toString());
!       }
! 
!       byte[] classBytes = baos.toByteArray();
! 
!       MarshallerClassLoader loader = new MarshallerClassLoader(classBytes);
! 
!       try
!       {
!          Class cls = loader.loadClass(marshallerName);
!          return cls.getMethod("unmarshal", new Class[]{MarshalledObject.class});
!       }
!       catch (ClassNotFoundException x)
!       {
!          throw new Error(x.toString());
!       }
!       catch (NoSuchMethodException x)
        {
           throw new Error(x.toString());
***************
*** 87,91 ****
           public Object run()
           {
!             return new MarshallerClassLoader(mbeanLoader, defaultLoader);
           }
        });
--- 128,132 ----
           public Object run()
           {
!             return new ExtendedClassLoader(mbeanLoader, defaultLoader);
           }
        });
***************
*** 149,165 ****
     }
  
!    public static class Marshaller
     {
!       public static Object unmarshal(MarshalledObject obj) throws IOException, ClassNotFoundException
        {
!          return obj.get();
        }
     }
  
!    private static class MarshallerClassLoader extends ClassLoader
     {
        private final ClassLoader defaultLoader;
  
!       private MarshallerClassLoader(ClassLoader mbeanLoader, ClassLoader defaultLoader)
        {
           super(mbeanLoader);
--- 190,249 ----
     }
  
!    private static class MarshallerClassLoader extends SecureClassLoader
     {
!       private byte[] bytes;
! 
!       private MarshallerClassLoader(byte[] classBytes)
        {
!          super(null);
!          this.bytes = classBytes;
!       }
! 
!       /**
!        * This method is overridden to load only classes from the java.* packages and the
!        * {@link Marshaller} class ONLY.
!        * Classes from java.* packages (like java.lang.Object and java.rmi.MarshalledObject) are
!        * referenced by {@link Marshaller} itself.
!        * We don't load classes from javax.management.* packages, since we assume the context classloader
!        * can load those classes by itself or by one of its ancestor classloaders.
!        */
!       public Class loadClass(final String name) throws ClassNotFoundException
!       {
!          if (name.startsWith("java.")) return super.loadClass(name);
!          if (!name.startsWith(Marshaller.class.getName())) throw new ClassNotFoundException(name);
! 
!          try
!          {
!             return (Class)AccessController.doPrivileged(new PrivilegedExceptionAction()
!             {
!                public Object run() throws ClassNotFoundException
!                {
!                   try
!                   {
!                      return defineClass(name, bytes, 0, bytes.length, MarshallerClassLoader.this.getClass().getProtectionDomain());
!                   }
!                   catch (ClassFormatError x)
!                   {
!                      throw new ClassNotFoundException("Class Format Error", x);
!                   }
!                }
!             }, null);
!          }
!          catch (PrivilegedActionException x)
!          {
!             throw (ClassNotFoundException)x.getException();
!          }
        }
     }
  
!    /**
!     * This is an implementation of the extended classloader as defined by the
!     * JMX Remote Specification, chapter 2.
!     */
!    private static class ExtendedClassLoader extends SecureClassLoader
     {
        private final ClassLoader defaultLoader;
  
!       private ExtendedClassLoader(ClassLoader mbeanLoader, ClassLoader defaultLoader)
        {
           super(mbeanLoader);



-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.