Below is a patch created via `cvs diff -u . > patchfile` from
'jboss/src/main/org/jboss/ejb/plugins'.  It contains all of the changes to
the existing files to support this change.  (list server didn't seem to like
attachements).

In the process of adding this support I cleaned up the Proxy and Handle
classes.  The following are no longer needed (under
jboss/src/main/org/jboss/ejb/plugins/jrmp/interfaces):

 o StatefulHandleImpl.java (replaced by SessionHandle.java)
 o StatelessSessionProxy.java (replaced by SessionHandle.java)
 o StatefulSessionProxy.java (replaced by SessionProxy.java)
 o StatelessHandleImpl.java (replaced by SessionProxy.java)

The following are new additions:

 o BeanProxy.java (a base class for bean proxys)
 o SessionProxy.java (a proxy for stateless and stateful session beans)
 o AbstractHandle.java (common methods used by all handles)
 o InitialContextState.java (wrapper to save/restore the correct context)
 o SessionHandle.java (a handle for stateless and statful session beans)

About The Patch
---------------

In order to allow handles (home or bean) to retain the correct naming
context I had to modify the proxy classes which created them.  While doing
that I noticed that lots of duplicate code was being performed and thus
BeanProxy was born.  I also noticed that the proxys for stateful and
stateless were very similar, and thus SessionProxy was born.

In the process of making these changes I condensed a lot of the grunt work
being performed in the concrete classes into GenericProxy (such as invoking
the container... local and remote).

I tend to document things as I go, so I added javadocs for most fields and
methods... though I didn't fully finish with GenericProxy.

I changed most fields that were package-private to protected to allow any
extending classes access.  I moved the static method references which were
duplicated in all of the concrete proxys to GenericProxy, BeanProxy and
HomeProxy (where appropriate of course).

To achieve the context fluff that I originally intended to add, I created
InitialContextState, which is created in the non-default GenericProxy
constructor (as it should only be initialized while the container is local).
InitialContextState is a simple class that saves the InitialContext
environment from a default context (ie. new InitialContext()), and has a
method to recreate a InitialContext with that environment.

This was originally added to GenericProxy, but it turns out that some of the
same code was needed in AbstractHandle, so I just turned it into a class.
BeanProxy provides a getEJBHome() method, which uses the InitialContextState
(via GenericProxy.createInitialContext()) to return the correct home
reference.

To get the handles working, I modified the handle classes to take an
InitialContextState object as a construction parameter, then modified the
proxys to construct with their 'contextState' fields.

You will notice that HomeHandleImpl, still has a single argument constructor
(for name), this is for the JRMPContainerInvoker, which constructs
HomeHandle's.  I am not sure exactly what happens with these, but it seems
to work.  I think that some work might be needed to ensure this.
AbstractHandle.createInitialContext() will return a 'new InitialContext()'
when contextState is null, else it returns 'contextState.restore()'.  This
*might* be sufficient.

The changes to JRMPContainerInvoker are only the removal of explicit imports
with a .* import.  If the above listed files are removed, then this fix
needs to be here so it will compile.

To get the correct jrmp version interfaces to work I simply changed them the
extend from the correct class (in the case of session beans).

Currently InitialContextState implement Serializable, and doesn't perform
any special work when writing out the environment Hashtable.  If we can
assume that this will only contain strings, then we could override the
default and just write out the strings.

--

I *think* that is it.  I hope this find all of you well.  Please let me know
if you have any questions, comments or complaints.  I am not sure if cvs
will ignore the first few lines of the patch file (they contain ? ... <new
file> fluff) might want to remove those if you have problems?

PS. Is there a prefered way to attach these files so that the list server
    won't complain about this?

--jason

patchfile.txt ----8<----
? jrmp/interfaces/BeanProxy.java
? jrmp/interfaces/SessionProxy.java
? jrmp/interfaces/AbstractHandle.java
? jrmp/interfaces/InitialContextState.java
? jrmp/interfaces/SessionHandle.java
Index: jrmp/interfaces/EntityHandleImpl.java
===================================================================
RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/jrmp/interfaces/EntityHandleImpl.java,v
retrieving revision 1.6
diff -u -r1.6 EntityHandleImpl.java
--- jrmp/interfaces/EntityHandleImpl.java       2000/12/07 15:44:42     1.6
+++ jrmp/interfaces/EntityHandleImpl.java       2000/12/08 05:51:26
@@ -6,55 +6,67 @@
  */
 package org.jboss.ejb.plugins.jrmp.interfaces;

-import java.rmi.RemoteException;
-import java.rmi.ServerException;
-import javax.ejb.Handle;
-import javax.ejb.EJBObject;
-import javax.naming.InitialContext;
-import java.lang.reflect.Method;
+import java.rmi.*;
+import javax.ejb.*;

-
 /**
- *     <description>
+ *     An EJB entity bean handle.
  *
  *     @see <related>
  *     @author Rickard �berg ([EMAIL PROTECTED])
  *     @version $Revision: 1.6 $
  */
 public class EntityHandleImpl
+   extends AbstractHandle
    implements Handle
 {
    // Constants -----------------------------------------------------

    // Attributes ----------------------------------------------------
-   String name;
-   Object id;
+
+   /** The primary key of the entity bean */
+   protected Object id;

    // Static --------------------------------------------------------

    // Constructors --------------------------------------------------
-   public EntityHandleImpl(String name, Object id)
+
+   /**
+    * Construct a EntityHandleImpl.
+    *
+    * @param contextState  <code>InitialContextState</code> used to restore
+    *                      the correct naming context.
+    * @param name          <code>EJBHome</code> <i>JNDI</i> for the entity.
+    * @param id            Primary key of the entity.
+    */
+   public EntityHandleImpl(InitialContextState contextState, String name,
+                           Object id)
    {
-      this.name = name;
+      super(contextState, name);
       this.id = id;
    }

    // Public --------------------------------------------------------

-   // Handle implementation -----------------------------------------
-   public EJBObject getEJBObject()
-      throws RemoteException
-   {
-      try
-      {
-         Object home = new InitialContext().lookup(name);
-
-         Method finder = home.getClass().getMethod("findByPrimaryKey", new Class[] { 
id.getClass() });
-         return (EJBObject)finder.invoke(home, new Object[] { id });
-      } catch (Exception e)
-      {
+   /**
+    * Handle implementation.
+    *
+    * @return  <code>EJBObject</code> reference.
+    *
+    * @throws RemoteException
+    * @throws ServerException    Could not get EJBObject.
+    */
+   public EJBObject getEJBObject() throws RemoteException {
+      EJBObject ejb;
+
+      try {
+         ejb = getEJBObject("findByPrimaryKey", id);
+      }
+      catch (Exception e) {
          throw new ServerException("Could not get EJBObject", e);
       }
+
+      return ejb;
    }

    // Package protected ---------------------------------------------
Index: jrmp/interfaces/EntityProxy.java
===================================================================
RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/jrmp/interfaces/EntityProxy.java,v
retrieving revision 1.20
diff -u -r1.20 EntityProxy.java
--- jrmp/interfaces/EntityProxy.java    2000/12/07 15:44:42     1.20
+++ jrmp/interfaces/EntityProxy.java    2000/12/08 05:51:26
@@ -1,195 +1,141 @@
 /*
-* JBoss, the OpenSource EJB server
-*
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
-*/
+ * JBoss, the OpenSource EJB server
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
 package org.jboss.ejb.plugins.jrmp.interfaces;

-import java.io.IOException;
-import java.rmi.MarshalledObject;
+import java.io.*;
 import java.lang.reflect.Method;
-import javax.naming.InitialContext;

-import javax.ejb.EJBObject;
-import javax.ejb.EJBHome;
-
-import org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker;
 import org.jboss.ejb.CacheKey;

 /**
-*      <description>
-*
-*   @see <related>
-*   @author Rickard �berg ([EMAIL PROTECTED])
-*      @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
-*   @version $Revision: 1.20 $
-*/
+ * An EJB entity bean proxy class.
+ *
+ * @version $Revision: 1.19 $
+ * @author  Rickard �berg ([EMAIL PROTECTED])
+ *     @author  <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+ * @author  Jason Dillon <a 
+href="mailto:[EMAIL PROTECTED]">&lt;[EMAIL PROTECTED]&gt;</a>
+ */
 public class EntityProxy
-extends GenericProxy
+   extends BeanProxy
 {
-    // Constants -----------------------------------------------------
-
-    // Attributes ----------------------------------------------------
-    protected CacheKey cacheKey;
-
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   /** The primary key of the entity bean. */
+   protected CacheKey cacheKey;

-    // Static --------------------------------------------------------
+   // Static --------------------------------------------------------

-    static Method getPrimaryKey;
-    static Method getHandle;
-       static Method getEJBHome;
-    static Method isIdentical;
-    static Method toStr;
-    static Method eq;
-    static Method hash;
-
-    static
-    {
-       try
-       {
-         // EJB methods
-         getPrimaryKey = EJBObject.class.getMethod("getPrimaryKey", new Class[0]);
-         getHandle = EJBObject.class.getMethod("getHandle", new Class[0]);
-         getEJBHome = EJBObject.class.getMethod("getEJBHome", new Class[0]);
-                isIdentical = EJBObject.class.getMethod("isIdentical", new Class[] { 
EJBObject.class });
-
-         // Object methods
-         toStr = Object.class.getMethod("toString", new Class[0]);
-         eq = Object.class.getMethod("equals", new Class[] { Object.class });
-         hash = Object.class.getMethod("hashCode", new Class[0]);
-       } catch (Exception e)
-       {
-         e.printStackTrace();
-       }
-    }
-
-    // Constructors --------------------------------------------------
-    public EntityProxy()
-    {
-       // For externalization to work
-    }
-
-    public EntityProxy(String name, ContainerRemote container, Object id, boolean 
optimize)
-    {
-       super(name, container, optimize);
+   // Constructors --------------------------------------------------
+
+   /**
+    * Default constructor for externalization.
+    */
+   public EntityProxy() {}
+
+   /**
+    * Construct a new EntityProxy.
+    *
+    * @param name
+    * @param container
+    * @param id
+    * @param optimize
+    */
+   public EntityProxy(String name, ContainerRemote container, Object id,
+                      boolean optimize)
+   {
+      super(name, container, optimize);

-       if (id == null)
+      if (id == null)
          throw new NullPointerException("Id may not be null");

-       if (id instanceof CacheKey) {
-         this.cacheKey = (CacheKey) id;
-       }
-       else
-       {
+      if (id instanceof CacheKey) {
+         this.cacheKey = (CacheKey)id;
+      }
+      else {
          // In case we pass the Object or anything else we encapsulate
          cacheKey = new CacheKey(id);
-       }
-    }
+      }
+   }

-    // Public --------------------------------------------------------
+   // Public --------------------------------------------------------

-    // InvocationHandler implementation ------------------------------
-    public final Object invoke(Object proxy, Method m, Object[] args)
-    throws Throwable
-    {
-       // Normalize args to always be an array
-       // Isn't this a bug in the proxy call??
-       if (args == null)
+       /**
+    * InvocationHandler implementation.
+    *
+    * @param proxy   The proxy object.
+    * @param m       The method being invoked.
+    * @param args    The arguments for the method.
+    *
+    * @throws Throwable    Any exception or error thrown while processing.
+    */
+   public final Object invoke(Object proxy, Method m, Object[] args)
+      throws Throwable
+   {
+      // Normalize args to always be an array
+      // Isn't this a bug in the proxy call??
+      if (args == null)
          args = new Object[0];
-
-       // Implement local methods
-       if (m.equals(toStr))
-       {
-
-         return name+":"+cacheKey.id.toString();

-       }
-       else if (m.equals(eq))
-       {
+      // Implement local methods
+      if (m.equals(toStr)) {
+         return name + ":" + cacheKey.id.toString();
+      }
+      else if (m.equals(eq)) {
          return invoke(proxy, isIdentical, args);
-       }
-
-       else if (m.equals(hash))
-       {
-         return new Integer(cacheKey.id.hashCode());
-       }
-
-       // Implement local EJB calls
-       else if (m.equals(getHandle))
-       {
-         return new EntityHandleImpl(name, cacheKey.id);
-       }
-
-       else if (m.equals(getPrimaryKey))
-       {
+      }
+      else if (m.equals(hash)) {
+         return hashCode(cacheKey.id);
+      }
+      // Implement local EJB calls
+      else if (m.equals(getHandle)) {
+         return new EntityHandleImpl(contextState, name, cacheKey.id);
+      }
+      else if (m.equals(getPrimaryKey)) {
          return cacheKey.id;
-       }
-
-          else if (m.equals(getEJBHome))
-       {
-         return (EJBHome) new InitialContext().lookup(name);
-       }
-
-       else if (m.equals(isIdentical))
-       {
-         return new Boolean(((EJBObject)args[0]).getPrimaryKey().equals(cacheKey.id));
-       }
-
-       // If not taken care of, go on and call the container
-       else
-       {
-         // Delegate to container
-         // Optimize if calling another bean in same EJB-application
-         if (optimize && isLocal())
-         {
-          return container.invoke( // The entity id, method and arguments for the 
invocation
-              cacheKey, m, args,
-              // Transaction attributes
-              tm != null ? tm.getTransaction() : null,
-              // Security attributes
-              getPrincipal(), getCredential());
-         } else
-         {
-          // Create a new MethodInvocation for distribution
-          RemoteMethodInvocation rmi = new RemoteMethodInvocation(cacheKey, m, args);
-
-          // Set the transaction context
-          rmi.setTransaction(tm != null? tm.getTransaction() : null);
-
-          // Set the security stuff
-          // MF fixme this will need to use "thread local" and therefore same 
construct as above
-          // rmi.setPrincipal(sm != null? sm.getPrincipal() : null);
-          // rmi.setCredential(sm != null? sm.getCredential() : null);
-          // is the credential thread local? (don't think so... but...)
-          rmi.setPrincipal( getPrincipal() );
-          rmi.setCredential( getCredential() );
-
-          // Invoke on the remote server, enforce marshalling
-          return container.invoke(new MarshalledObject(rmi)).get();
-         }
-       }
-    }
-
-    // Package protected ---------------------------------------------
-
-    // Protected -----------------------------------------------------
-    public void writeExternal(java.io.ObjectOutput out)
-    throws IOException
-    {
-       super.writeExternal(out);
-       out.writeObject(cacheKey);
-    }
-
-    public void readExternal(java.io.ObjectInput in)
-    throws IOException, ClassNotFoundException
-    {
-       super.readExternal(in);
-       cacheKey = (CacheKey) in.readObject();
-    }
+      }
+          else if (m.equals(getEJBHome)) {
+         return getEJBHome();
+      }
+      else if (m.equals(isIdentical)) {
+         return isIdentical(args[0], cacheKey.id);
+      }
+      // If not taken care of, go on and call the container
+      else {
+         return invokeContainer(cacheKey, m, args);
+      }
+   }

-    // Private -------------------------------------------------------
+   // Package protected ---------------------------------------------

-    // Inner classes -------------------------------------------------
-}
+   // Protected -----------------------------------------------------

+   /**
+    * Externalization support.
+    */
+   public void writeExternal(ObjectOutput out)
+      throws IOException
+   {
+      super.writeExternal(out);
+      out.writeObject(cacheKey);
+   }
+
+   /**
+    * Externalization support.
+    */
+   public void readExternal(ObjectInput in)
+      throws IOException, ClassNotFoundException
+   {
+      super.readExternal(in);
+      cacheKey = (CacheKey)in.readObject();
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+}
Index: jrmp/interfaces/GenericProxy.java
===================================================================
RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/jrmp/interfaces/GenericProxy.java,v
retrieving revision 1.8
diff -u -r1.8 GenericProxy.java
--- jrmp/interfaces/GenericProxy.java   2000/12/07 15:44:42     1.8
+++ jrmp/interfaces/GenericProxy.java   2000/12/08 05:51:26
@@ -6,73 +6,127 @@
  */
 package org.jboss.ejb.plugins.jrmp.interfaces;

-import java.io.IOException;
+import java.io.*;
+import java.rmi.*;
+import java.lang.reflect.*;
 import java.security.Principal;

-import javax.transaction.TransactionManager;
+import javax.transaction.*;
+import javax.ejb.*;
+import javax.naming.*;

 import org.jboss.ejb.MethodInvocation;
 import org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker;
 import org.jboss.tm.TxManager;

-import java.util.HashMap;
+import java.util.*;
 import org.jboss.system.SecurityAssociation;


 /**
- *      <description>
- *
- *      @see <related>
- *      @author Rickard �berg ([EMAIL PROTECTED])
- *      @version $Revision: 1.8 $
+ * An abstract base proxy class from which all other proxys extend from.
+ *
+ * @version $Revision: 1.7 $
+ * @author  Rickard �berg ([EMAIL PROTECTED])
+ * @author  Jason Dillon <a 
+href="mailto:[EMAIL PROTECTED]">&lt;[EMAIL PROTECTED]&gt;</a>
  */
 public abstract class GenericProxy
-   implements java.io.Externalizable
+   implements Externalizable
 {
    // Constants -----------------------------------------------------
-
+
    // Attributes ----------------------------------------------------
-   String name;
-   ContainerRemote container;
-   long containerStartup = ContainerRemote.startup;
-
-   boolean optimize = false;
+
+   protected String name;
+   protected ContainerRemote container;
+   protected long containerStartup = ContainerRemote.startup;
+   protected boolean optimize; // = false;
+
+   /** The current InitialContextState */
+   protected InitialContextState contextState;

    // Static --------------------------------------------------------
-   static TransactionManager tm;
+
+   protected static TransactionManager tm;
+   protected static HashMap invokers = new HashMap(); // Prevent DGC

-   static HashMap invokers = new HashMap(); // Prevent DGC
-   public static ContainerRemote getLocal(String jndiName) { return 
(ContainerRemote)invokers.get(jndiName); }
-   public static void addLocal(String jndiName, ContainerRemote invoker) { 
invokers.put(jndiName, invoker); }
-   public static void removeLocal(String jndiName) { invokers.remove(jndiName); }
-
-       public static void setTransactionManager(TransactionManager txMan)
-       {
-               if (tm == null)
+   protected static Method toStr;
+   protected static Method hash;
+   protected static Method eq;
+
+   /**
+    * Initialize Object method references.
+    */
+   static {
+      try {
+         Class[] empty = {};
+         Class type = Object.class;
+
+         toStr = type.getMethod("toString", empty);
+         hash = type.getMethod("hashCode", empty);
+         eq = type.getMethod("equals", new Class[] { type });
+      }
+      catch (Exception e) {
+         e.printStackTrace();
+      }
+   }
+
+   public static ContainerRemote getLocal(String jndiName) {
+      return (ContainerRemote)invokers.get(jndiName);
+   }
+
+   public static void addLocal(String jndiName, ContainerRemote invoker) {
+      invokers.put(jndiName, invoker);
+   }
+
+   public static void removeLocal(String jndiName) {
+      invokers.remove(jndiName);
+   }
+
+   /**
+    * Set the <code>TransactionManager</code> if there is not already one set.
+    *
+    * @param txMan   <code>TransactionManager</code>.
+    */
+       public static void setTransactionManager(TransactionManager txMan) {
+               if (tm == null) {
                   tm = txMan;
+      }
        }

-  public Principal getPrincipal()
-  {
-    return SecurityAssociation.getPrincipal();
-  }
-
-  public Object getCredential()
-  {
-    return SecurityAssociation.getCredential();
-  }
+   // should this be static ?
+   public Principal getPrincipal() {
+      return SecurityAssociation.getPrincipal();
+   }

-   // Constructors --------------------------------------------------
-   public GenericProxy()
-   {
-      // For externalization to work
+   // should this be static ?
+   public Object getCredential() {
+      return SecurityAssociation.getCredential();
    }
-
-   protected GenericProxy(String name, ContainerRemote container, boolean optimize)
+
+   // Constructors --------------------------------------------------
+
+   /**
+    * Default constructor for externalization.
+    */
+   public GenericProxy() {}
+
+   /**
+    * Initialze a GenericProxy.
+    *
+    * @param name       <i>JNDI</i> name.
+    * @param container  ???
+    * @param optimize   ???
+    */
+   protected GenericProxy(String name, ContainerRemote container,
+                          boolean optimize)
    {
       this.name = name;
       this.container = container;
       this.optimize = optimize;
+
+      // save the current initial context state.
+      contextState = new InitialContextState();
    }

    // Public --------------------------------------------------------
@@ -80,21 +134,151 @@
    // Package protected ---------------------------------------------

    // Protected -----------------------------------------------------
-   protected boolean isLocal()
+
+   /**
+    * Create an <code>InitialContext</code> using the saved environment or
+    * create a vanilla <code>InitialContext</code> when the enviroment
+    * is <i>null</i>.
+    *
+    * @return  <code>InitialContext</code> suitable for the bean that this
+    *          is a proxy for.
+    *
+    * @throws NamingException    Failed to create <code>InitialContext</code>.
+    */
+   protected final InitialContext createInitialContext()
+      throws NamingException
    {
+      return contextState.restore();
+   }
+
+   /**
+    * Check if this is a local invocation.
+    *
+    * @return  True if this is a local invocation.
+    */
+   protected boolean isLocal() {
       return containerStartup == ContainerRemote.startup;
    }

-   public void writeExternal(java.io.ObjectOutput out)
+   /**
+    * Get the hash-code of the given object and wrap it in a
+    * <code>Integer</code>.
+    *
+    * <p>Could cache the generated <code>Integer</code> in a field too.
+    *
+    * @param obj  Object to get the hash-code from.
+    * @return     <code>Integer</code> hash-code.
+    */
+   protected Integer hashCode(Object obj) {
+      // could cache this value here
+      return new Integer(obj.hashCode());
+   }
+
+   /**
+    * Macro to get a <code>Transaction</code> from the
+    * <code>TransactionManager</code> if it is non-null.
+    */
+   protected Transaction getTransaction() throws SystemException {
+      return tm != null ? tm.getTransaction() : null;
+   }
+
+   /**
+    * Invoke the container to handle this method invocation.
+    *
+    * <p>If optimization is enabled and this is a local proxy, then the
+    *    container is invoked directly, else a remote call is made.
+    *
+    * @param id
+    * @param m
+    * @param args
+    *
+    * @throws Throwable
+    */
+   protected Object invokeContainer(Object id, Method m, Object[] args)
+      throws Throwable
+   {
+      Object result;
+
+      // optimize if calling another bean in same EJB-application
+      if (optimize && isLocal()) {
+         result = container.invoke(id, m, args, getTransaction(),
+                                   getPrincipal(), getCredential());
+      }
+      else {
+         result = invokeRemoteContainer(id, m, args);
+      }
+
+      return result;
+   }
+
+   /**
+    * Create and initial a <code>MarshalledObject</code> suitable for
+    * invoking a remote container with.
+    *
+    * @param id
+    * @param m
+    * @param args
+    * @return        <code>MarshalledObject</code> suitable for invoking
+    *                a remote container with.
+    *
+    * @throws SystemException    Failed to get transaction.
+    * @throws IOException        Failed to create <code>MarshalledObject</code>.
+    */
+   protected MarshalledObject createMarshalledObject(Object id, Method m,
+                                                     Object[] args)
+      throws SystemException, IOException
+   {
+      RemoteMethodInvocation rmi = new RemoteMethodInvocation(id, m, args);
+
+      // Set the transaction context
+      rmi.setTransaction(getTransaction());
+
+      // Set the security stuff
+      // MF fixme this will need to use "thread local" and therefore same construct 
+as above
+      // rmi.setPrincipal(sm != null? sm.getPrincipal() : null);
+      // rmi.setCredential(sm != null? sm.getCredential() : null);
+      // is the credential thread local? (don't think so... but...)
+      rmi.setPrincipal(getPrincipal());
+      rmi.setCredential(getCredential());
+
+      return new MarshalledObject(rmi);
+   }
+
+   /**
+    * Invoke the remote container to handle this method invocation.
+    *
+    * @param id
+    * @param m
+    * @param args
+    *
+    * @throws Throwable
+    */
+   protected Object invokeRemoteContainer(Object id, Method m, Object[] args)
+      throws Throwable
+   {
+      MarshalledObject mo = createMarshalledObject(id, m, args);
+
+      // Invoke on the remote server, enforce marshalling
+      return container.invokeHome(mo).get();
+   }
+
+   /**
+    * Externalization support.
+    */
+   public void writeExternal(ObjectOutput out)
       throws IOException
    {
-         out.writeUTF(name);
-         out.writeObject(isLocal() ? container : null);
-        out.writeLong(containerStartup);
-        out.writeBoolean(optimize);
+      out.writeUTF(name);
+      out.writeObject(isLocal() ? container : null);
+      out.writeLong(containerStartup);
+      out.writeBoolean(optimize);
+      out.writeObject(contextState);
    }

-   public void readExternal(java.io.ObjectInput in)
+   /**
+    * Externalization support.
+    */
+   public void readExternal(ObjectInput in)
       throws IOException, ClassNotFoundException
    {
        name = in.readUTF();
@@ -102,11 +286,12 @@
        containerStartup = in.readLong();
        optimize = in.readBoolean();

-      if (isLocal())
-      {
+      if (isLocal()) {
          // VM-local optimization; still follows RMI-semantics though
          container = getLocal(name);
       }
+
+      contextState = (InitialContextState)in.readObject();
    }

    // Private -------------------------------------------------------
Index: jrmp/interfaces/HomeHandleImpl.java
===================================================================
RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/jrmp/interfaces/HomeHandleImpl.java,v
retrieving revision 1.5
diff -u -r1.5 HomeHandleImpl.java
--- jrmp/interfaces/HomeHandleImpl.java 2000/12/07 15:44:42     1.5
+++ jrmp/interfaces/HomeHandleImpl.java 2000/12/08 05:51:26
@@ -6,54 +6,69 @@
  */
 package org.jboss.ejb.plugins.jrmp.interfaces;

-import java.rmi.RemoteException;
-import java.rmi.ServerException;
-import javax.ejb.HomeHandle;
-import javax.ejb.EJBHome;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import java.lang.reflect.Method;
+import java.rmi.*;
+import javax.ejb.*;
+import javax.naming.*;

-
 /**
- *     <description>
+ *     An EJB home handle.
  *
- *     @see <related>
- *     @author Rickard �berg ([EMAIL PROTECTED])
  *     @version $Revision: 1.5 $
+ *     @author  Rickard �berg ([EMAIL PROTECTED])
+ * @author  Jason Dillon <a 
+href="mailto:[EMAIL PROTECTED]">&lt;[EMAIL PROTECTED]&gt;</a>
  */
 public class HomeHandleImpl
+   extends AbstractHandle
    implements HomeHandle
 {
    // Constants -----------------------------------------------------

    // Attributes ----------------------------------------------------
-   String name;

    // Static --------------------------------------------------------

    // Constructors --------------------------------------------------
-   public HomeHandleImpl(String name)
-   {
-      this.name = name;
+
+   /**
+    * Construct a HomeHandleImpl.
+    *
+    * @param contextState  <code>InitialContextState</code> used to restore
+    *                      the correct naming context.
+    * @param name          <code>EJBHome</code> <i>JNDI</i> name.
+    */
+   public HomeHandleImpl(InitialContextState contextState, String name) {
+      super(contextState, name);
    }

+   /**
+    * Construct a HomeHandleImpl.
+    *
+    * <p>This constructor is used by the container invoker.
+    *
+    * @param name    <code>EJBHome</code> <i>JNDI</i> name.
+    */
+   public HomeHandleImpl(String name) {
+      super(null, name);
+   }
+
    // Public --------------------------------------------------------
+

-   // Handle implementation -----------------------------------------
-   public EJBHome getEJBHome()
-      throws RemoteException
-   {
+   /**
+    * HomeHandle implementation.
+    *
+    * @return  <code>EJBHome</code> reference.
+    *
+    * @throws RemoteException    Could not get EJBHome.
+    */
+   public EJBHome getEJBHome() throws RemoteException {
        try {
-
-         return (EJBHome) new InitialContext().lookup(name);
-
-        }
+          return lookupEJBHome();
+       }
        catch (NamingException e) {
-
-            e.printStackTrace();
-            throw new RemoteException("Could not get EJBHome");
-        }
+          e.printStackTrace();
+          throw new RemoteException("Could not get EJBHome");
+       }
    }

    // Package protected ---------------------------------------------
Index: jrmp/interfaces/HomeProxy.java
===================================================================
RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/jrmp/interfaces/HomeProxy.java,v
retrieving revision 1.19
diff -u -r1.19 HomeProxy.java
--- jrmp/interfaces/HomeProxy.java      2000/12/07 15:44:42     1.19
+++ jrmp/interfaces/HomeProxy.java      2000/12/08 05:51:26
@@ -1,248 +1,214 @@
-/*
-* JBoss, the OpenSource EJB server
-*
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
-*/
+/**
+ * JBoss, the OpenSource EJB server
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
 package org.jboss.ejb.plugins.jrmp.interfaces;

-import java.io.IOException;
+import java.io.*;
+import java.rmi.*;
 import java.lang.reflect.Method;
-import java.rmi.MarshalledObject;
-
-import javax.naming.Name;

-import javax.ejb.EJBHome;
-import javax.ejb.EJBObject;
-import javax.ejb.Handle;
-import javax.ejb.HomeHandle;
-import javax.ejb.EJBMetaData;
+import javax.ejb.*;
 import org.jboss.ejb.CacheKey;

-import org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker;
-
 /**
-*      <description>
-*
-*      @see <related>
-*      @author Rickard �berg ([EMAIL PROTECTED])
-*              @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
-*      @version $Revision: 1.19 $
-*/
+ * An EJB home proxy class.
+ *
+ * @version $Revision: 1.18 $
+ * @author  Rickard �berg ([EMAIL PROTECTED])
+ *     @author  <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
+ * @author  Jason Dillon <a 
+href="mailto:[EMAIL PROTECTED]">&lt;[EMAIL PROTECTED]&gt;</a>
+ */
 public class HomeProxy
-extends GenericProxy
+   extends GenericProxy
 {
-    // Constants -----------------------------------------------------
-
-    // Attributes ----------------------------------------------------
-
-    EJBMetaData ejbMetaData;
-    // Static --------------------------------------------------------
-    static Method getEJBMetaData;
-    static Method getHomeHandle;
-    static Method removeByHandle;
-    static Method removeByPrimaryKey;
-    static Method removeObject;
-    static Method toStr;
-    static Method eq;
-    static Method hash;
-
-    static
-    {
-        try
-        {
-            // EJB methods
-            getEJBMetaData = EJBHome.class.getMethod("getEJBMetaData", new Class[0]);
-            getHomeHandle = EJBHome.class.getMethod("getHomeHandle", new Class[0]);
-            removeByHandle = EJBHome.class.getMethod("remove", new Class[] 
{Handle.class});
-            removeByPrimaryKey = EJBHome.class.getMethod("remove", new Class[] 
{Object.class});
-            // Get the "remove" method from the EJBObject
-            removeObject = EJBObject.class.getMethod("remove", new Class[0]);
-
-            // Object methods
-            toStr = Object.class.getMethod("toString", new Class[0]);
-            eq = Object.class.getMethod("equals", new Class[] { Object.class });
-            hash = Object.class.getMethod("hashCode", new Class[0]);
-        } catch (Exception e)
-        {
-            e.printStackTrace();
-        }
-    }
-
-
-    // Constructors --------------------------------------------------
-    public HomeProxy()
-    {
-        // For Externalizable to work
-    }
-
-    public HomeProxy(String name, EJBMetaData ejbMetaData, ContainerRemote container, 
boolean optimize)
-    {
-        super(name, container, optimize);
-
-        this.ejbMetaData = ejbMetaData;
-    }
-
-    // Public --------------------------------------------------------
-
-    // InvocationHandler implementation ------------------------------
-    public Object invoke(Object proxy, Method m, Object[] args)
-    throws Throwable
-    {
-
-
-        // Normalize args to always be an array
-        // Isn't this a bug in the proxy call??
-        if (args == null)
-            args = new Object[0];
-
-        // Implement local methods
-        if (m.equals(toStr))
-        {
-            return name+"Home";
-        }
-        else if (m.equals(eq))
-        {
-            // equality of the proxy home is based on names...
-
-            return new Boolean(invoke(proxy,toStr, args).equals(name+"Home"));
-        }
-
-        else if (m.equals(hash))
-        {
-
-            return new Integer(this.hashCode());
-        }
-
-        // Implement local EJB calls
-        else if (m.equals(getHomeHandle))
-        {
-
-            return new HomeHandleImpl(name);
-        }
-
-
-        else if (m.equals(getEJBMetaData))
-        {
-
-            return ejbMetaData;
-        }
-
-
-        else if (m.equals(removeByHandle))
-        {
-
-            // First get the EJBObject
-            EJBObject object = ((Handle) args[0]).getEJBObject();
-
-            // remove the object from here
-            object.remove();
-
-            // Return Void
-            return Void.TYPE;
-        }
-
-        // The trick is simple we trick the container in believe it is a remove() on 
the instance
-        else if (m.equals(removeByPrimaryKey))
-        {
-
-            if (optimize && isLocal())
-            {
-                return container.invoke(
-                    // The first argument is the id
-                    new CacheKey(args[0]),
-                    // Pass the "removeMethod"
-                    removeObject,
-                    // this is a remove() on the object
-                    new Object[0],
-                    // Tx stuff
-                    tm != null ? tm.getTransaction() : null,
-                    // Security attributes
-                    getPrincipal(), getCredential());
-            } else
-            {
-
-                // Build a method invocation that carries the identity of the target 
object
-                RemoteMethodInvocation rmi = new RemoteMethodInvocation(
-                    // The first argument is the id
-                    new CacheKey(args[0]),
-                    // Pass the "removeMethod"
-                    removeObject,
-                    // this is a remove() on the object
-                    new Object[0]);
-
-                // Set the transaction context
-                rmi.setTransaction(tm != null? tm.getTransaction() : null);
-
-                // Set the security stuff
-                // MF fixme this will need to use "thread local" and therefore same 
construct as above
-                // rmi.setPrincipal(sm != null? sm.getPrincipal() : null);
-                // rmi.setCredential(sm != null? sm.getCredential() : null);
-                // is the credential thread local? (don't think so... but...)
-                rmi.setPrincipal( getPrincipal() );
-                rmi.setCredential( getCredential() );
-
-                // Invoke on the remote server, enforce marshalling
-                return container.invoke(new MarshalledObject(rmi));
-            }
-        }
-
-        // If not taken care of, go on and call the container
-        else
-        {
-
-            // Delegate to container
-            // Optimize if calling another bean in same EJB-application
-            if (optimize && isLocal())
-            {
-                return container.invokeHome( // The method and arguments for the 
invocation
-                    m, args,
-                    // Transaction attributes
-                    tm != null ? tm.getTransaction() : null,
-                    // Security attributes
-                    getPrincipal(), getCredential());
-            } else
-            {
-                // Create a new MethodInvocation for distribution
-                RemoteMethodInvocation rmi = new RemoteMethodInvocation(null, m, 
args);
-
-                // Set the transaction context
-                rmi.setTransaction(tm != null? tm.getTransaction() : null);
-
-                // Set the security stuff
-                // MF fixme this will need to use "thread local" and therefore same 
construct as above
-                // rmi.setPrincipal(sm != null? sm.getPrincipal() : null);
-                // rmi.setCredential(sm != null? sm.getCredential() : null);
-                // is the credential thread local? (don't think so... but...)
-                rmi.setPrincipal( getPrincipal() );
-                rmi.setCredential( getCredential() );
-
-                // Invoke on the remote server, enforce marshalling
-                return container.invokeHome(new MarshalledObject(rmi)).get();
-            }
-        }
-    }
-
-    public void writeExternal(java.io.ObjectOutput out)
-    throws IOException
-    {
-        super.writeExternal(out);
-
-        out.writeObject(ejbMetaData);
-    }
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   /** The EJB meta-data for the <code>EJBHome</code> reference. */
+   protected EJBMetaData ejbMetaData;
+
+   // Static --------------------------------------------------------
+
+   /** <code>EJBHome.getEJBMetaData()</code> method reference. */
+   protected static Method getEJBMetaData;
+
+   /** <code>EJBHome.getHomeHandle()</code> method reference. */
+   protected static Method getHomeHandle;
+
+   /** <code>EJBHome.removeByHandle()</code> method reference. */
+   protected static Method removeByHandle;
+
+   /** <code>EJBHome.removeByPrimaryKey()</code> method reference. */
+   protected static Method removeByPrimaryKey;
+
+   /** <code>EJBObject.removeObject()</code> method reference. */
+   protected static Method removeObject;

-    public void readExternal(java.io.ObjectInput in)
-    throws IOException, ClassNotFoundException
-    {
-        super.readExternal(in);
-
-        ejbMetaData = (EJBMetaData)in.readObject();
+   /**
+    * Initialize <code>EJBHome</code> and <code>EJBObject</code>
+    * method references.
+    */
+   static {
+       try {
+          Class empty[] = {};
+          Class type = EJBHome.class;
+
+          getEJBMetaData = type.getMethod("getEJBMetaData", empty);
+          getHomeHandle = type.getMethod("getHomeHandle", empty);
+          removeByHandle = type.getMethod("remove", new Class[] {
+             Handle.class
+          });
+          removeByPrimaryKey = type.getMethod("remove", new Class[] {
+             Object.class
+          });
+
+          // Get the "remove" method from the EJBObject
+          removeObject = EJBObject.class.getMethod("remove", empty);
+       }
+       catch (Exception e) {
+          e.printStackTrace();
+       }
     }
-    // Package protected ---------------------------------------------

-    // Protected -----------------------------------------------------

-    // Private -------------------------------------------------------
+   // Constructors --------------------------------------------------
+
+   /**
+    * Default constructor for externalization.
+    */
+   public HomeProxy() {}
+
+   /**
+    * Construct a HomeProxy.
+    *
+    * @param name
+    * @param ejbMetaData
+    * @param container
+    * @param optimize
+    */
+   public HomeProxy(String name, EJBMetaData ejbMetaData,
+                    ContainerRemote container, boolean optimize)
+   {
+      super(name, container, optimize);
+      this.ejbMetaData = ejbMetaData;
+   }
+
+   // Public --------------------------------------------------------
+
+       /**
+    * InvocationHandler implementation.
+    *
+    * @param proxy   The proxy object.
+    * @param m       The method being invoked.
+    * @param args    The arguments for the method.
+    *
+    * @throws Throwable    Any exception or error thrown while processing.
+    */
+   public final Object invoke(Object proxy, Method m, Object[] args)
+      throws Throwable
+   {
+      // Normalize args to always be an array
+      // Isn't this a bug in the proxy call??
+      if (args == null)
+         args = new Object[0];
+
+      // Implement local methods
+      if (m.equals(toStr)) {
+         return name + "Home";
+      }
+      else if (m.equals(eq)) {
+         // equality of the proxy home is based on names...
+         Object temp = invoke(proxy,toStr, args);
+         return new Boolean(temp.equals(name + "Home"));
+      }
+      else if (m.equals(hash)) {
+         return hashCode(this);
+      }
+      // Implement local EJB calls
+      else if (m.equals(getHomeHandle)) {
+         return new HomeHandleImpl(contextState, name);
+      }
+      else if (m.equals(getEJBMetaData)) {
+         return ejbMetaData;
+      }
+      else if (m.equals(removeByHandle)) {
+         // First get the EJBObject
+         EJBObject object = ((Handle) args[0]).getEJBObject();
+
+         // remove the object from here
+         object.remove();
+
+         // Return Void
+         return Void.TYPE;
+      }
+      // The trick is simple we trick the container in believe it is a
+      // remove() on the instance
+      else if (m.equals(removeByPrimaryKey)) {
+         Object id = new CacheKey(args[0]);
+         return invokeContainer(id, removeObject, new Object[0]);
+      }
+      // If not taken care of, go on and call the container
+      else {
+         return invokeHome(m, args);
+      }
+   }
+
+   /**
+    * Invoke the container to handle this <code>EJBHome</code> method
+    * invocation.
+    *
+    * @param m
+    * @param args
+    *
+    * @throws Throwable
+    */
+   private Object invokeHome(Method m, Object[] args)
+      throws Throwable
+   {
+      Object result;
+
+      // Optimize if calling another bean in same EJB-application
+      if (optimize && isLocal()) {
+         result = container.invokeHome(m, args, getTransaction(),
+                                       getPrincipal(), getCredential());
+      }
+      else {
+         MarshalledObject mo = createMarshalledObject(null, m, args);
+         result = container.invokeHome(mo).get();
+      }
+
+      return result;
+   }
+
+   /**
+    * Externalization support.
+    */
+   public void writeExternal(ObjectOutput out)
+      throws IOException
+   {
+      super.writeExternal(out);
+      out.writeObject(ejbMetaData);
+   }
+
+   /**
+    * Externalization support.
+    */
+   public void readExternal(ObjectInput in)
+      throws IOException, ClassNotFoundException
+   {
+      super.readExternal(in);
+      ejbMetaData = (EJBMetaData)in.readObject();
+   }
+
+   // Package protected ---------------------------------------------

-    // Inner classes -------------------------------------------------
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
 }
Index: jrmp/server/JRMPContainerInvoker.java
===================================================================
RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/jrmp/server/JRMPContainerInvoker.java,v
retrieving revision 1.30
diff -u -r1.30 JRMPContainerInvoker.java
--- jrmp/server/JRMPContainerInvoker.java       2000/12/07 15:44:46     1.30
+++ jrmp/server/JRMPContainerInvoker.java       2000/12/08 05:51:26
@@ -41,17 +41,7 @@
 import org.jboss.ejb.ContainerInvokerContainer;
 import org.jboss.ejb.Interceptor;
 import org.jboss.ejb.ContainerInvoker;
-import org.jboss.ejb.plugins.jrmp.interfaces.RemoteMethodInvocation;
-import org.jboss.ejb.plugins.jrmp.interfaces.HomeProxy;
-import org.jboss.ejb.plugins.jrmp.interfaces.HomeHandleImpl;
-import org.jboss.ejb.plugins.jrmp.interfaces.StatelessSessionProxy;
-import org.jboss.ejb.plugins.jrmp.interfaces.StatefulSessionProxy;
-import org.jboss.ejb.plugins.jrmp.interfaces.EntityProxy;
-import org.jboss.ejb.plugins.jrmp.interfaces.GenericProxy;
-import org.jboss.ejb.plugins.jrmp.interfaces.ContainerRemote;
-import org.jboss.ejb.plugins.jrmp.interfaces.IteratorImpl;
-import org.jboss.ejb.plugins.jrmp.interfaces.EJBMetaDataImpl;
-import org.jboss.ejb.plugins.jrmp.interfaces.SecureSocketFactory;
+import org.jboss.ejb.plugins.jrmp.interfaces.*;

 import org.jboss.system.SecurityAssociation;

Index: jrmp12/interfaces/StatefulSessionProxy.java
===================================================================
RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/jrmp12/interfaces/StatefulSessionProxy.java,v
retrieving revision 1.5
diff -u -r1.5 StatefulSessionProxy.java
--- jrmp12/interfaces/StatefulSessionProxy.java 2000/12/07 15:44:46     1.5
+++ jrmp12/interfaces/StatefulSessionProxy.java 2000/12/08 05:51:26
@@ -6,7 +6,7 @@
  */
 package org.jboss.ejb.plugins.jrmp12.interfaces;

-import  org.jboss.ejb.plugins.jrmp.interfaces.ContainerRemote;
+import org.jboss.ejb.plugins.jrmp.interfaces.ContainerRemote;

 /**
  *     <description>
@@ -16,7 +16,7 @@
  *     @version $Revision: 1.5 $
  */
 public class StatefulSessionProxy
-   extends org.jboss.ejb.plugins.jrmp.interfaces.StatefulSessionProxy
+   extends org.jboss.ejb.plugins.jrmp.interfaces.SessionProxy
    implements org.jboss.proxy.InvocationHandler
 {
    public StatefulSessionProxy()
Index: jrmp12/interfaces/StatelessSessionProxy.java
===================================================================
RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/jrmp12/interfaces/StatelessSessionProxy.java,v
retrieving revision 1.5
diff -u -r1.5 StatelessSessionProxy.java
--- jrmp12/interfaces/StatelessSessionProxy.java        2000/12/07 15:44:46     1.5
+++ jrmp12/interfaces/StatelessSessionProxy.java        2000/12/08 05:51:26
@@ -16,7 +16,7 @@
  *     @version $Revision: 1.5 $
  */
 public class StatelessSessionProxy
-   extends org.jboss.ejb.plugins.jrmp.interfaces.StatelessSessionProxy
+   extends org.jboss.ejb.plugins.jrmp.interfaces.SessionProxy
    implements org.jboss.proxy.InvocationHandler
 {
    public StatelessSessionProxy()
Index: jrmp13/interfaces/StatefulSessionProxy.java
===================================================================
RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/jrmp13/interfaces/StatefulSessionProxy.java,v
retrieving revision 1.4
diff -u -r1.4 StatefulSessionProxy.java
--- jrmp13/interfaces/StatefulSessionProxy.java 2000/12/07 15:44:48     1.4
+++ jrmp13/interfaces/StatefulSessionProxy.java 2000/12/08 05:51:26
@@ -16,7 +16,7 @@
  *     @version $Revision: 1.4 $
  */
 public final class StatefulSessionProxy
-   extends org.jboss.ejb.plugins.jrmp.interfaces.StatefulSessionProxy
+   extends org.jboss.ejb.plugins.jrmp.interfaces.SessionProxy
    implements java.lang.reflect.InvocationHandler
 {
    public StatefulSessionProxy()
Index: jrmp13/interfaces/StatelessSessionProxy.java
===================================================================
RCS file: 
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/jrmp13/interfaces/StatelessSessionProxy.java,v
retrieving revision 1.4
diff -u -r1.4 StatelessSessionProxy.java
--- jrmp13/interfaces/StatelessSessionProxy.java        2000/12/07 15:44:48     1.4
+++ jrmp13/interfaces/StatelessSessionProxy.java        2000/12/08 05:51:26
@@ -16,7 +16,7 @@
  *     @version $Revision: 1.4 $
  */
 public final class StatelessSessionProxy
-   extends org.jboss.ejb.plugins.jrmp.interfaces.StatelessSessionProxy
+   extends org.jboss.ejb.plugins.jrmp.interfaces.SessionProxy
    implements java.lang.reflect.InvocationHandler
 {
    public StatelessSessionProxy()
---->8----

SessionProxy.java ----8<----
/*
 * JBoss, the OpenSource EJB server
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package org.jboss.ejb.plugins.jrmp.interfaces;

import java.io.*;
import java.lang.reflect.Method;

/**
 * An EJB session bean (stateless and stateful) proxy class.
 *
 * @version $Revision: 1.16 $
 * @author  Rickard �berg ([EMAIL PROTECTED])
 * @author  <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a>
 * @author  Jason Dillon <a 
href="mailto:[EMAIL PROTECTED]">&lt;[EMAIL PROTECTED]&gt;</a>
 */
public class SessionProxy
   extends BeanProxy
{
        // Constants -----------------------------------------------------

        // Attributes ----------------------------------------------------

   /** Stateful session bean identifier (or null for a stateless proxy). */
   protected Object id;

        // Static --------------------------------------------------------

        // Constructors --------------------------------------------------

   /**
    * Default constructor for externalization.
    */
   public SessionProxy() {}

   /**
    * Construct a SessionProxy for a stateful session bean.
    *
    * @param name
    * @param container
    * @param id
    * @param optimize
    */
        public SessionProxy(String name, ContainerRemote container,
                       Object id, boolean optimize)
   {
      super(name, container, optimize);
      this.id = id;
        }

   /**
    * Construct a SessionProxy for a a stateless session bean.
    *
    * @param name
    * @param container
    * @param optimize
    */
        public SessionProxy(String name, ContainerRemote container,
                       boolean optimize)
   {
      this(name, container, null, optimize);
        }

        // Public --------------------------------------------------------

        /**
    * InvocationHandler implementation.
    *
    * @param proxy   The proxy object.
    * @param m       The method being invoked.
    * @param args    The arguments for the method.
    *
    * @throws Throwable    Any exception or error thrown while processing.
    */
        public final Object invoke(Object proxy, Method m, Object[] args)
      throws Throwable
        {
                // Normalize args to always be an array
                // Isn't this a bug in the proxy call??
                if (args == null)
                        args = new Object[0];

                // Implement local methods
                if (m.equals(toStr)) {
         return name + (id == null ? ":Stateless" : ":" + id);
                }
                else if (m.equals(eq)) {
                        return invoke(proxy, isIdentical, args);
                }
                else if (m.equals(hash)) {
         // We base the stateless hash on the hash of the proxy...
         // MF XXX: it could be that we want to return the hash of the name?
         return hashCode(id == null ? this : id);
                }
                // Implement local EJB calls
                else if (m.equals(getHandle)) {
         return new SessionHandle(contextState, name, id);
                }
           else if (m.equals(getEJBHome)) {
         return getEJBHome();
      }
                else if (m.equals(getPrimaryKey)) {
         // MF FIXME
         // The spec says that SSB PrimaryKeys should not be returned and the
         // call should throw an exception.  However we need to expose the
         // field *somehow* so we can check for "isIdentical".

         // For now we use a non-spec compliant implementation and just return
         // the key as is See jboss1.0 for the PKHolder and the hack to be
         // spec-compliant and yet solve the problem

         // This should be the following call
         // throw new RemoteException("Session Beans do not expose
         // their keys, RTFS");

         // This is how it can be solved with a PKHolder
         // (extends RemoteException)
         // throw new PKHolder("RTFS", name);

         // This is non-spec compliant but will do for now

         // We can consider the name of the container to be the primary
         // key, since all stateless beans are equal within a home
         return (id == null) ? name : id;
                }
                else if (m.equals(isIdentical)) {
         // All stateless beans are identical within a home,
         // if the names are equal we are equal

         // MF FIXME
         // See above, this is not correct but works for now
         // (do jboss1.0 PKHolder hack in here)
         return isIdentical(args[0], (id == null) ? name : id);
                }
                // If not taken care of, go on and call the container
                else {
         return invokeContainer(id, m, args);
                }
        }

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   /**
    * Externalization support.
    */
   public void writeExternal(ObjectOutput out)
      throws IOException
   {
      super.writeExternal(out);
      out.writeObject(id);
   }

   /**
    * Externalization support.
    */
   public void readExternal(ObjectInput in)
      throws IOException, ClassNotFoundException
   {
      super.readExternal(in);
      id = in.readObject();
   }

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------
}
---->8----

InitialContextState.java ----8<----
/*
 * JBoss, the OpenSource EJB server
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.ejb.plugins.jrmp.interfaces;

import java.io.*;
import java.util.*;
import javax.naming.*;

/**
 *      An abstract base handle class from which all handles extend from.
 *
 *      @version $Revision: 1.6 $
 *      @author  Rickard �berg ([EMAIL PROTECTED])
 * @author  Jason Dillon <a 
href="mailto:[EMAIL PROTECTED]">&lt;[EMAIL PROTECTED]&gt;</a>
 */
public class InitialContextState
   implements Serializable
{
   /** The InitialContext enviroment (or null if unable to determine) */
   private Hashtable env;

   /**
    * Construct a InitialContextState.
    */
   public InitialContextState() {
      // save the current state
      save();
   }

   /**
    * Save the current <i>default</i> <code>InitialContext</code> enviroment.
    */
   private void save() {
      try {
         InitialContext ctx = null;
         try {
            ctx = new InitialContext();
            env = ctx.getEnvironment();
         }
         finally {
            if (ctx != null) ctx.close();
         }
      }
      catch (NamingException ignore) {}
   }

   /**
    * Restore an <code>InitialContext</code> from the previous state.
    *
    * @return  <code>InitialContext</code>
    *
    * @throws NamingException    Failed to create <code>InitialContext</code>.
    */
   public InitialContext restore() throws NamingException {
      InitialContext ctx;

      // if the environment is not null, then use it else assume there is
      // a system property set.
      if (env != null) {
         ctx = new InitialContext(env);
      }
      else {
         ctx = new InitialContext();
      }

      return ctx;
   }
}
---->8----

BeanProxy.java ----8<----
/**
 * jBoss, the OpenSource EJB server
 *
 * Distributable under GPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.ejb.plugins.jrmp.interfaces;

import java.rmi.*;
import java.lang.reflect.*;

import javax.ejb.*;
import javax.naming.*;

/**
 * An abstract base proxy class from which all bean proxys extend from.
 *
 * @version $Revision: 1.7 $
 * @author  Jason Dillon <a 
href="mailto:[EMAIL PROTECTED]">&lt;[EMAIL PROTECTED]&gt;</a>
 */
public abstract class BeanProxy
   extends GenericProxy
{
   // Constants -----------------------------------------------------

   // Attributes ----------------------------------------------------

   // Static --------------------------------------------------------

   /** <code>EJBObject.getPrimaryKey()</code> method reference. */
   protected static Method getPrimaryKey;

   /** <code>EJBObject.getHandle()</code> method reference. */
   protected static Method getHandle;

   /** <code>EJBObject.getEJBHome()</code> method reference. */
        protected static Method getEJBHome;

   /** <code>EJBObject.isIdentical()</code> method reference. */
   protected static Method isIdentical;

   /**
    * Initialize <code>EJBObject</code> method references.
    */
   static {
      try {
         Class[] empty = {};
         Class type = EJBObject.class;

                        getPrimaryKey = type.getMethod("getPrimaryKey", empty);
                        getHandle = type.getMethod("getHandle", empty);
                        getEJBHome = type.getMethod("getEJBHome", empty);
                        isIdentical = type.getMethod("isIdentical", new Class[] { type 
});
      }
      catch (Exception e) {
         e.printStackTrace();
      }
   }

   // Constructors --------------------------------------------------

   /**
    * Default constructor for externalization.
    */
   public BeanProxy() {}

   /**
    * Initialze a BeanProxy.
    *
    * @param name       <code>EJBHome</code> <i>JNDI</i> name.
    * @param container  ???
    * @param optimize   ???
    */
   protected BeanProxy(String name, ContainerRemote container,
                       boolean optimize)
   {
      super(name, container, optimize);
   }

   // Public --------------------------------------------------------

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   /**
    * Get a <code>EJBHome</code> reference for this proxy.
    *
    * @return  <code>EJBHome</code> reference.
    *
    * @throws NamingException    Failed to create InitalContext or lookup
    *                            EJBHome reference.
    */
   protected EJBHome getEJBHome() throws NamingException {
      InitialContext ctx = createInitialContext();
      EJBHome home;

      try {
         home = (EJBHome)ctx.lookup(name);
      }
      finally {
         ctx.close();
      }

      return home;
   }

   /**
    * Test the identitiy of an <code>EJBObject</code>.
    *
    * @param a    <code>EJBObject</code>.
    * @param b    Object to test identity with.
    * @return     True if objects are identical.
    *
    * @throws RemoteException    Failed to get primary key.
    */
   protected Boolean isIdentical(Object a, Object b) throws RemoteException {
      EJBObject ejb = (EJBObject)a;
      Object pk = ejb.getPrimaryKey();
      return new Boolean(pk.equals(b));
   }

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------
}

---->8----

SessionHandle.java ----8<----
/*
 * JBoss, the OpenSource EJB server
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.ejb.plugins.jrmp.interfaces;

import java.rmi.*;
import java.lang.reflect.*;
import javax.ejb.*;
import javax.naming.*;

/**
 *      An EJB session bean (stateful and stateless) handle.
 *
 *      @version $Revision: 1.5 $
 *      @author  Rickard �berg ([EMAIL PROTECTED])
 * @author  <a href="mailto:[EMAIL PROTECTED]>Marc Fleury</a>
 * @author  Jason Dillon <a 
href="mailto:[EMAIL PROTECTED]">&lt;[EMAIL PROTECTED]&gt;</a>
 */
public class SessionHandle
   extends AbstractHandle
   implements Handle
{
   // Constants -----------------------------------------------------

   // Attributes ----------------------------------------------------

   /** The primary key of the stateful session bean. */
   protected Object id;

   // Static --------------------------------------------------------

   /** <code>Handle.getEJBObject()</code> method reference. */
   protected static Method getEJBObjectMethod;

   /** Initialize <code>Handle</code> method references. */
   static {
      try {
         Class type = Handle.class;
         getEJBObjectMethod = type.getMethod("getEJBObject", new Class[0]);
      }
      catch (Exception e) {
         e.printStackTrace();
      }
   }

   // Constructors --------------------------------------------------

   /**
    * Construct a SessionHandle for stateful session beans.
    *
    * @param contextState  <code>InitialContextState</code> used to restore
    *                      the correct naming context.
    * @param name          <code>EJBHome</code> <i>JNDI</i> name for the
    *                      stateful session bean.
    * @param id            Primary key of the stateful session bean.
    */
   public SessionHandle(InitialContextState contextState, String name,
                        Object id)
   {
      super(contextState, name);
      this.id = id;
   }

   /**
    * Construct a SessionHandle for stateless session beans.
    *
    * @param contextState  <code>InitialContextState</code> used to restore
    *                      the correct naming context.
    * @param name          The invoker name of the stateless session bean.
    */
   public SessionHandle(InitialContextState contextState, String name) {
      this(contextState, name, null);
   }

   // Public --------------------------------------------------------

   /**
    * Handle implementation.
    *
    * @return  <code>EJBObject</code> reference.
    *
    * @throws RemoteException
    * @throws ServerException    Could not get EJBObject.
    */
   public EJBObject getEJBObject() throws RemoteException {
      EJBObject ejb;

      try {
         if (id == null) {
            ejb = getEJBObject("create");
         }
         else {
            ejb = invokeRemoteContainer();
         }
      }
      catch (Exception e) {
         throw new ServerException("Could not get EJBObject", e);
      }

      return ejb;
   }

   /** Invoke the remote container to restore stateless session beans. */
   private EJBObject invokeRemoteContainer() throws Exception {
      InitialContext ctx = createInitialContext();
      EJBObject ejb;

      try {
         ContainerRemote container =
            (ContainerRemote)ctx.lookup("invokers/" + name);

         // Create a new MethodInvocation for distribution
         RemoteMethodInvocation rmi = new RemoteMethodInvocation
            (null, getEJBObjectMethod, new Object[] { id });

         // MF FIXME: WE DEFINITLY NEED THE SECURITY ON SUCH A CALL...
         // We also need a pointer to the TM...:(

         // Set the transaction context
         // rmi.setTransaction(tm != null? tm.getTransaction() : null);

         // Set the security stuff
         // MF fixme this will need to use "thread local" and therefore same construct 
as above
         // rmi.setPrincipal(sm != null? sm.getPrincipal() : null);
         // rmi.setCredential(sm != null? sm.getCredential() : null);
         // is the credential thread local? (don't think so... but...)
         // rmi.setPrincipal( getPrincipal() );
         // rmi.setCredential( getCredential() );

         // Invoke on the remote server, enforce marshalling
         ejb = (EJBObject)container.invokeHome
            (new MarshalledObject(rmi)).get();
      }
      finally {
         if (ctx != null) ctx.close();
      }

      return ejb;
   }

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------
}

---->8----

AbstractHandle ----8<----
/*
 * JBoss, the OpenSource EJB server
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.ejb.plugins.jrmp.interfaces;

import java.io.*;
import java.lang.reflect.*;
import javax.ejb.*;
import javax.naming.*;

/**
 *      An abstract base handle class from which all handles extend from.
 *
 *      @version $Revision: 1.6 $
 * @author  Jason Dillon <a 
href="mailto:[EMAIL PROTECTED]">&lt;[EMAIL PROTECTED]&gt;</a>
 */
public abstract class AbstractHandle
   implements Serializable
{
   // Constants -----------------------------------------------------

   // Attributes ----------------------------------------------------

   /** <i>JNDI</i> name used for lookups. */
   protected String name;

   /** The InitialContextState used to restore the correct naming context.  */
   protected InitialContextState contextState;

   // Static --------------------------------------------------------

   // Constructors --------------------------------------------------

   /**
    * Initialize an AbstractHandle.
    *
    * @param contextState  <code>InitialContextState</code> used to restore
    *                      the correct naming context.
    * @param name          <i>JNDI</i> name.
    */
   public AbstractHandle(InitialContextState contextState, String name) {
      this.contextState = contextState;
      this.name = name;
   }

   // Public --------------------------------------------------------

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   /**
    * Create an <code>InitialContext</code> using the saved environment or
    * create a vanilla <code>InitialContext</code> when the enviroment
    * is <i>null</i>.
    *
    * @return  <code>InitialContext</code> suitable for the bean that this
    *          is a proxy for.
    *
    * @throws NamingException    Failed to create <code>InitialContext</code>.
    */
   protected final InitialContext createInitialContext()
      throws NamingException
   {
      if (contextState == null) {
         // HACK to allow lookups when using the HomeHandle created by
         // a JRMPContainerInvoker, which does not provide a contextState.
         return new InitialContext();
      }

      return contextState.restore();
   }

   /**
    * Get the <code>EJBHome</code> reference at the configured <i>JNDI</i>
    * name.
    *
    * @return  <code>EJBHome</code> reference.
    *
    * @throws NamingException    Failed to lookup <code>EJBHome</code>.
    */
   protected final EJBHome lookupEJBHome() throws NamingException {
      InitialContext ctx = createInitialContext();
      EJBHome home;

      try {
         home = (EJBHome)ctx.lookup(name);
      }
      finally {
         if (ctx != null) ctx.close();
      }

      return home;
   }

   /** Helper to perform the actual lookup and reflection. */
   private EJBObject getEJBObject(String method, Class types[],
                                  Object params[])
      throws Exception
   {
      EJBHome home = lookupEJBHome();
      Class type = home.getClass();
      Method finder = type.getMethod(method, types);

      return (EJBObject)finder.invoke(home, params);
   }

   /**
    * Get the <code>EJBObject</code> by reflecting to the given method
    * name with the given parameter.
    */
   protected final EJBObject getEJBObject(String method, Object id)
      throws Exception
   {
      return getEJBObject(method, new Class[] { id.getClass() },
                          new Object[] { id });
   }

   /**
    * Get the <code>EJBObject</code> by reflecting to the given method
    * name with no parameters.
    */
   protected final EJBObject getEJBObject(String method)
      throws Exception
   {
      return getEJBObject(method, new Class[0], new Object[0]);
   }

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------
}

---->8----


Reply via email to