User: slaboure
  Date: 01/08/19 11:27:49

  Added:       src/main/org/jboss/ejb/plugins/jrmp/interfaces
                        GenericProxyHA.java HASLSBTargetsManager.java
                        HomeProxyHA.java StatelessSessionProxyHA.java
  Log:
  First import of source for HA support for SLSB
  
  Revision  Changes    Path
  1.1                  
jbossmx/src/main/org/jboss/ejb/plugins/jrmp/interfaces/GenericProxyHA.java
  
  Index: GenericProxyHA.java
  ===================================================================
  /*
   * JBoss, the OpenSource J2EE WebOS
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  
  package org.jboss.ejb.plugins.jrmp.interfaces;
  
  import java.lang.reflect.Method;
  import java.util.Hashtable;
  import java.io.IOException;
  
  import java.rmi.MarshalledObject;
  import javax.naming.InitialContext;
  import javax.naming.Name;
  
  import javax.ejb.EJBObject;
  import javax.ejb.EJBHome;
  
  import org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker;
  
  /**
   *   Branched from GenericProxy for HA behaviour
   *
   *   @see GenericProxy
   *   @author Rickard Öberg ([EMAIL PROTECTED])
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Sacha Labourey</a>
   *   @version $Revision: 1.1 $
   *
   *   <p><b>Revisions:</b>
   *
   *   <p><b>20010819 Sacha Labourey:</b>
   *   <ul>
   *   <li> First import of sources
   *   </ul>
   */
  
  public class GenericProxyHA extends GenericProxy
  {
     public interface TargetsManager extends java.io.Serializable
     {
        void setFather (GenericProxyHA father);
        
        Hashtable getJndiTarget ();
        int numberOfRegisteredJndiTargets ();
        void jndiTargetHasFailed (Hashtable entry);
        
        ContainerRemote getRemoteTarget ();
        int numberOfRegisteredRemoteTargets ();
        void remoteTargetHasFailed (ContainerRemote target);
        
        void tick ();
     }
     // Constants -----------------------------------------------------
     
     // Attributes ----------------------------------------------------
     
     // Static --------------------------------------------------------
     
     protected ContainerRemote[] crs;
     protected Hashtable[] jndiProps;
     protected String completeHAAppName;
     protected Object resynchFlag = new Object ();
     
     protected TargetsManager manager = null;
     
     // Constructors --------------------------------------------------
     
     public GenericProxyHA ()
     {
        // For externalization to work
     }
     
     public GenericProxyHA (String name,ContainerRemote container,boolean optimize)
     {
        super(name, container, optimize);
     }
     
     public GenericProxyHA (String name,ContainerRemote container,boolean optimize, 
TargetsManager mgr)
     {
        super(name, container, optimize);
        this.manager = mgr;
        this.manager.setFather (this);
     }
     
     // Public --------------------------------------------------------
     
     /**
      *  Externalize this instance.
      *
      */
     public void writeExternal (java.io.ObjectOutput out)
     throws IOException
     {
        super.writeExternal (out);
        out.writeObject (this.crs);
        out.writeObject (this.jndiProps);
        out.writeUTF (completeHAAppName);
        out.writeObject (this.manager);
     }
     
     /**
      *  Un-externalize this instance.
      *
      */
     public void readExternal (java.io.ObjectInput in)
     throws IOException, ClassNotFoundException
     {
        super.readExternal (in);
        this.crs = (ContainerRemote[])in.readObject ();
        this.jndiProps = (Hashtable[])in.readObject ();
        this.completeHAAppName = in.readUTF ();
        this.manager = (TargetsManager)in.readObject ();
        manager.setFather (this);
     }
     
     public void setMultipleContainers (ContainerRemote[] containers, Hashtable[] 
jndiProps, String appPath)
     {
        crs = containers;
        this.jndiProps = jndiProps;
        this.completeHAAppName = appPath;
     }
     
     // Package protected ---------------------------------------------
     
     // Protected -----------------------------------------------------
     
     // simply delegates our calls to our manager
     //
     protected java.util.Hashtable getJndiTarget ()
     {
        return manager.getJndiTarget ();
     }
     
     protected int numberOfRegisteredJndiTargets ()
     {
        return manager.numberOfRegisteredJndiTargets ();
     }
     
     protected void jndiTargetHasFailed (Hashtable entry)
     {
        manager.jndiTargetHasFailed (entry);
     }
     
     protected ContainerRemote getRemoteTarget ()
     {
        return manager.getRemoteTarget ();
     }
     
     protected int numberOfRegisteredRemoteTargets ()
     {
        return manager.numberOfRegisteredRemoteTargets ();
     }
     
     protected void remoteTargetHasFailed (ContainerRemote target)
     {
        manager.remoteTargetHasFailed (target);
     }
     
     protected void tick ()
     {
        manager.tick ();
     }
     
     
     // Private -------------------------------------------------------
     
     // Inner classes -------------------------------------------------
  }
  
  
  
  
  1.1                  
jbossmx/src/main/org/jboss/ejb/plugins/jrmp/interfaces/HASLSBTargetsManager.java
  
  Index: HASLSBTargetsManager.java
  ===================================================================
  /*
   * JBoss, the OpenSource J2EE WebOS
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  
  package org.jboss.ejb.plugins.jrmp.interfaces;
  
  import java.util.Hashtable;
  import javax.naming.InitialContext;
  
  /**
   *   Test implementation of a TargetsManager
   *
   *   @see GenericProxyHA.TargetsManager
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Sacha Labourey</a>
   *   @version $Revision: 1.1 $
   *
   *   <p><b>Revisions:</b>
   *
   *   <p><b>20010819 Sacha Labourey:</b>
   *   <ul>
   *   <li> First import of sources
   *   </ul>
   */
  
  public class HASLSBTargetsManager implements GenericProxyHA.TargetsManager
  {
     
     protected transient int cursorRemote = 0;
     protected transient int cursorJndi = 0;
     
     protected volatile long DELAY_FOR_RESYNCH_AFTER_DEAD_CONTAINER = 5000; // 5 
seconds
     protected volatile long DELAY_FOR_RESYNCH_FOR_NORMAL_UPDATE = 30000; // 30 seconds
     protected transient volatile long nextResynch;
     protected transient volatile boolean updatingData = false;
     
     protected transient Object sync_1 = new Object ();
     
     protected transient java.util.Vector validJndiTargets = null;
     
     protected transient GenericProxyHA father = null;
     
     public HASLSBTargetsManager ()
     {
     }
     
     public HASLSBTargetsManager (long normalResynch, long deathResynch)
     {
        DELAY_FOR_RESYNCH_AFTER_DEAD_CONTAINER = deathResynch;
        DELAY_FOR_RESYNCH_FOR_NORMAL_UPDATE = normalResynch;
     }
     
     public void setFather (GenericProxyHA father)
     {
        this.father = father;
        if (father.jndiProps != null)
           validJndiTargets = new java.util.Vector (java.util.Arrays.asList 
(father.jndiProps));
        nextResynch = System.currentTimeMillis () + 
DELAY_FOR_RESYNCH_FOR_NORMAL_UPDATE;
        updatingData = false;
     }
     
     public java.util.Hashtable getJndiTarget ()
     {
        if (validJndiTargets.size () == 0)
        {
           findTargetsSynchronously ();
           if (validJndiTargets.size () == 0)
              return null;
        }
        cursorJndi = ( (cursorJndi + 1) % validJndiTargets.size () );
        return (Hashtable)(validJndiTargets.elementAt (cursorJndi));
     }
     
     public int numberOfRegisteredJndiTargets ()
     {
        return validJndiTargets.size ();
     }
     
     public void jndiTargetHasFailed (Hashtable entry)
     {
        validJndiTargets.remove (entry);
     }
     
     public ContainerRemote getRemoteTarget ()
     {
        if (father.crs.length == 0)
        {
           findTargetsSynchronously ();
           if (father.crs.length == 0)
              return null;
        }
        synchronized (father.crs)
        {
           cursorRemote = ( (cursorRemote + 1) % father.crs.length );
           return father.crs[cursorRemote];
        }
     }
     
     public int numberOfRegisteredRemoteTargets ()
     {
        return father.crs.length;
     }
     
     public void remoteTargetHasFailed (ContainerRemote target)
     {
        removeDeadTarget (target);
     }
     
     protected void removeDeadTarget (ContainerRemote target)
     {
        //System.out.println("Size before : " + Integer.toString(father.crs.length));
        if (father.crs != null)
           synchronized (father.crs)
           {
              //System.out.println("removeDeadTarget has been called");
              int length = father.crs.length;
              for (int i=0; i<length; ++i)
                 if (father.crs[i] == target)
                 {
                    ContainerRemote[] copy = new ContainerRemote[length - 1];
                    //Hashtable[] copyProps = new Hashtable[length - 1];
                    System.arraycopy (father.crs, 0, copy, 0, i);
                    //System.arraycopy(jndiProps, 0, copyProps, 0, i);
                    if ( (i+1) < length)
                    {
                       System.arraycopy (father.crs, i+1, copy, i, length - i - 1);
                       //System.arraycopy(jndiProps, i+1, copyProps, i, length - i - 
1);
                    }
                    father.crs = copy;
                    //jndiProps = copyProps;
                    resynchAtLeastAt (System.currentTimeMillis () + 
DELAY_FOR_RESYNCH_AFTER_DEAD_CONTAINER);
                    //System.out.println("Size before : " + 
Integer.toString(father.crs.length));
                    return;
                 }
           }
           // nothing found
     }
     
     protected void findTargetsSynchronously ()
     {
        // if this is called, it is because our target list is empty
        //
        //System.out.println("findTargetsSynchronously has been called");
        synchronized (this)
        {
           if (father.crs.length > 0)
              return; // the list has been probably refilled during our wait for the 
monitor
           
           updateContainers ();
        }
        
     }
     
     protected void findTargetsAsynchronously ()
     {
        //System.out.println("findTargetsAsynchronously has been called");
        updatingData = true;
        Thread t = new Thread ( new Runnable ()
        {
           
           public void run ()
           {
              try
              {
                 synchronized(this)
                 {
                    updateContainers ();
                 }
              } finally
              {
                 updatingData = false;
              }
           }
        }
        );
        
        t.start ();
        
     }
     
     public void tick ()
     {
        if (!updatingData) // this is done in order to do not have to wait on 
asynchronous updates
        {
           boolean resynch = false;
           synchronized (this)
           {
              long now = System.currentTimeMillis ();
              resynch = (now >= nextResynch);
              if (resynch)
              {
                 //System.out.println("Tick has decided to resynch. Next auto resynh 
at " + Long.toString(now + DELAY_FOR_RESYNCH_FOR_NORMAL_UPDATE ) + " (now is " + 
Long.toString (now) + " and old update value was: " + Long.toString(nextResynch) + 
")");
                 nextResynch = ( now + DELAY_FOR_RESYNCH_FOR_NORMAL_UPDATE ) ;
              }
           }
           if (resynch)
              findTargetsAsynchronously ();
        }
     }
     
     protected void resynchAtLeastAt (long when)
     {
        // only keep more urgent resynch need
        //
        if ( (nextResynch == 0) || (when < nextResynch) )
           nextResynch = when;
     }
     
     protected void updateContainers ()
     {
        //nextResynch = 0;
        //System.out.println("updateContainers has been called");
        
        if (father.jndiProps != null)
        {
           org.jboss.ha.HASmallConfigEntries haConfigs = null;
           
           for (int i=0; i<father.jndiProps.length; i++)
           {
              try
              {
                 //System.out.println("... Test with i = " + Integer.toString (i));
                 Object obj = new InitialContext (father.jndiProps[i]).lookup 
("/HA/HAConfigServer");
                 if (obj instanceof org.jboss.ha.HARemoteInfo)
                 {
                    haConfigs = ( 
(org.jboss.ha.HARemoteInfo)obj).getSmallConfigEntriesForApp (father.completeHAAppName);
                    if (haConfigs != null)
                       if (haConfigs.size () > 0)
                       {
                          ContainerRemote[] tmpCr = haConfigs.getContainers ();
                          Hashtable[] tmpJndi = haConfigs.getJndiProps ();
                          java.util.Vector tmpV = new java.util.Vector 
(java.util.Arrays.asList (tmpJndi)); // reduce time in synch zone
                          synchronized (father.crs)
                          {
                             father.crs = tmpCr;
                             father.jndiProps = tmpJndi;
                             validJndiTargets = tmpV;
                          }
                          this.DELAY_FOR_RESYNCH_AFTER_DEAD_CONTAINER = 
haConfigs.delayForResynchAfterDeath;
                          this.DELAY_FOR_RESYNCH_FOR_NORMAL_UPDATE = 
haConfigs.delayForRefresh;
                          
                          // This will have an impact only if the new value is smaller
                          //
                          resynchAtLeastAt (System.currentTimeMillis () + 
DELAY_FOR_RESYNCH_FOR_NORMAL_UPDATE);
                          
                          return;
                       }
                 }
              }
              catch (Exception e)
              {/*e.printStackTrace ();*/} // during debug phase only!!!
           }
        }
     }
     
  }
  
  
  
  1.1                  
jbossmx/src/main/org/jboss/ejb/plugins/jrmp/interfaces/HomeProxyHA.java
  
  Index: HomeProxyHA.java
  ===================================================================
  /*
   * JBoss, the OpenSource J2EE WebOS
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  
  package org.jboss.ejb.plugins.jrmp.interfaces;
  
  
  import java.io.IOException;
  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 org.jboss.ejb.CacheKey;
  
  import org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker;
  
  /**
   *   Branched from HomeProxy for HA behaviour
   *
   *   @see HomeProxy
   *   @author Rickard Öberg ([EMAIL PROTECTED])
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Sacha Labourey</a>
   *   @version $Revision: 1.1 $
   *
   *   <p><b>Revisions:</b>
   *
   *   <p><b>20010819 Sacha Labourey:</b>
   *   <ul>
   *   <li> First import of sources
   *   </ul>
   */
  
  public class HomeProxyHA extends GenericProxyHA
  {
     // 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 HomeProxyHA ()
     {
        // For Externalizable to work
     }
     
     public HomeProxyHA (String name, EJBMetaData ejbMetaData,
     ContainerRemote container, boolean optimize,
     TargetsManager mgr)
     {
        super (name, container, optimize, mgr);
        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
              getTransaction (),
              // 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.setTransactionPropagationContext (getTransactionPropagationContext 
());
              
              // 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 marshaling
              if (isLocal ())
              {
                 // We need to make sure marshaling of exceptions is done properly
                 try
                 {
                    return container.invoke (new MarshalledObject (rmi)).get ();
                 } catch (Throwable e)
                 {
                    throw (Throwable)new MarshalledObject (e).get ();
                 }
              } else
              {
                 // Marshaling is done by RMI
                 return container.invoke (new MarshalledObject (rmi)).get ();
              }
           }
        }
        
        // 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
              getTransaction (),
              // Security attributes
              getPrincipal (), getCredential ());
           } else
           {
              // Create a new MethodInvocation for distribution
              RemoteMethodInvocation rmi = new RemoteMethodInvocation (null, m, args);
              
              // Set the transaction propagation context
              rmi.setTransactionPropagationContext (getTransactionPropagationContext 
());
              
              // 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 marshaling
              if (isLocal ())
              {
                 // We need to make sure marshaling of exceptions is done properly
                 try
                 {
                    return container.invokeHome (new MarshalledObject (rmi)).get ();
                 } catch (Throwable e)
                 {
                    throw (Throwable)new MarshalledObject (e).get ();
                 }
              } else
              {
                 // Marshaling is done by RMI
                 // Marshaling is done by RMI
                 //
                 ContainerRemote aTarget = null;
                 java.rmi.RemoteException lastProblem = null;
                 
                 tick ();
                 
                 // this proxy must support concurrent invocations
                 //
                 while (true)
                 {
                    synchronized (crs)
                    {
                       aTarget = getRemoteTarget ();
                       if (numberOfRegisteredRemoteTargets () == 0)
                          throw ( (lastProblem==null)? new java.rmi.RemoteException 
("No more valid HA SLSB home availble") : lastProblem );
                    }
                    
                    try
                    {
                       return aTarget.invokeHome (new MarshalledObject (rmi)).get ();
                    }
                    catch (java.rmi.RemoteException e)
                    {
                       System.out.println ("A SLSB home target has failed with a 
RemoteException");
                       remoteTargetHasFailed (aTarget);
                       lastProblem = e;
                    }
                 }
              }
           }
        }
     }
     
     public void writeExternal (java.io.ObjectOutput out)
     throws IOException
     {
        super.writeExternal (out);
        
        out.writeObject (ejbMetaData);
     }
     
     public void readExternal (java.io.ObjectInput in)
     throws IOException, ClassNotFoundException
     {
        super.readExternal (in);
        
        ejbMetaData = (EJBMetaData)in.readObject ();
     }
     // Package protected ---------------------------------------------
     
     // Protected -----------------------------------------------------
     
     // Private -------------------------------------------------------
     
     // Inner classes -------------------------------------------------
  }
  
  
  
  1.1                  
jbossmx/src/main/org/jboss/ejb/plugins/jrmp/interfaces/StatelessSessionProxyHA.java
  
  Index: StatelessSessionProxyHA.java
  ===================================================================
  /*
   * JBoss, the OpenSource J2EE WebOS
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  
  package org.jboss.ejb.plugins.jrmp.interfaces;
  
  import java.lang.reflect.Method;
  import java.util.Hashtable;
  import java.io.IOException;
  
  import java.rmi.MarshalledObject;
  import javax.naming.InitialContext;
  import javax.naming.Name;
  
  import javax.ejb.EJBObject;
  import javax.ejb.EJBHome;
  
  import org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker;
  
  import org.jboss.ejb.plugins.jrmp.interfaces.StatelessHandleImpl;
  
  /**
   *   Branched from StatelessSessionProxy for HA behaviour
   *
   *   @see StatelessSessionProxy
   *   @author Rickard Öberg ([EMAIL PROTECTED])
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Sacha Labourey</a>
   *   @version $Revision: 1.1 $
   *
   *   <p><b>Revisions:</b>
   *
   *   <p><b>20010819 Sacha Labourey:</b>
   *   <ul>
   *   <li> First import of sources
   *   </ul>
   */
  
  public class StatelessSessionProxyHA extends GenericProxyHA
  {
     // Constants -----------------------------------------------------
     
     // Attributes ----------------------------------------------------
     
     // Static --------------------------------------------------------
     
     static Method getPrimaryKey;
     static Method getHandle;
     static Method getEJBHome;
     static Method isIdentical;
     static Method toStr;
     static Method eq;
     static Method hash;
     
     static
     {
        try
        {
           // EJBObject 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 StatelessSessionProxyHA ()
     {
        // For externalization to work
     }
     
     public StatelessSessionProxyHA (String name,ContainerRemote container,boolean 
optimize, TargetsManager mgr)
     {
        super (name, container, optimize, mgr);
     }
     
     // Public --------------------------------------------------------
     
     /**
      *  Externalize this instance.
      *
      */
     public void writeExternal (java.io.ObjectOutput out)
     throws IOException
     {
        super.writeExternal (out);
     }
     
     /**
      *  Un-externalize this instance.
      *
      */
     public void readExternal (java.io.ObjectInput in)
     throws IOException, ClassNotFoundException
     {
        super.readExternal (in);
     }
     
     // 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)
           args = new Object[0];
        
        // Implement local methods
        if (m.equals (toStr))
        {
           return name+":Stateless";
        }
        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 new Integer (this.hashCode ());
        }
        
        // Implement local EJB calls
        else if (m.equals (getHandle))
        {
           return new StatelessHandleImpl (null, name);
        }
        
        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 name;
        }
        
        
        else if (m.equals (getEJBHome))
        {
           
           Hashtable aServerProps = null;
           javax.naming.NamingException lastProblem = null;
           
           while (true)
           {
              synchronized (crs)
              {
                 aServerProps = getJndiTarget ();
                 
                 if (numberOfRegisteredJndiTargets () == 0)
                    throw ( (lastProblem==null)? new javax.naming.NamingException ("No 
more valid HA SLSB container availble") : lastProblem );
              }
              
              try
              {
                 return (EJBHome) new InitialContext (aServerProps).lookup (name);
              }
              catch (javax.naming.NamingException e)
              {
                 jndiTargetHasFailed (aServerProps);
                 lastProblem = e;
              }
           }
        }
        
        else if (m.equals (isIdentical))
        {
           // All stateless beans are identical within a home, if the names are equal 
we are equal
           return new Boolean (((EJBObject)args[0]).getPrimaryKey ().equals (name));
        }
        
        // 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
              null, m, args,
              // Transaction attributes
              getTransaction (),
              // Security attributes
              getPrincipal (), getCredential ());
           } else
           {
              // Create a new MethodInvocation for distribution
              RemoteMethodInvocation rmi = new RemoteMethodInvocation (null, m, args);
              
              // Set the transaction context
              rmi.setTransactionPropagationContext (getTransactionPropagationContext 
());
              
              // 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 marshaling
              if (isLocal ())
              {
                 // We need to make sure marshaling of exceptions is done properly
                 try
                 {
                    return container.invoke (new MarshalledObject (rmi)).get ();
                 } catch (Throwable e)
                 {
                    throw (Throwable)new MarshalledObject (e).get ();
                 }
              }
              else
              {
                 // Marshaling is done by RMI
                 //
                 ContainerRemote aTarget = null;
                 java.rmi.RemoteException lastProblem = null;
                 
                 tick ();
                 
                 // this proxy must support concurrent invocations
                 //
                 while (true)
                 {
                    synchronized (crs)
                    {
                       aTarget = getRemoteTarget ();
                       if (numberOfRegisteredRemoteTargets () == 0)
                          throw ( (lastProblem==null)? new java.rmi.RemoteException 
("No more valid HA SLSB container availble") : lastProblem );
                          
                    }
                    
                    try
                    {
                       return aTarget.invoke (new MarshalledObject (rmi)).get ();
                    }
                    catch (java.rmi.RemoteException e)
                    {
                       remoteTargetHasFailed (aTarget);
                       lastProblem = e;
                    }
                 }
              }
           }
        }
     }
     
     
     // Package protected ---------------------------------------------
     
     // Protected -----------------------------------------------------
     
     // Private -------------------------------------------------------
     
     // Inner classes -------------------------------------------------
  }
  
  
  
  

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

Reply via email to