User: azakkerman
  Date: 01/05/22 15:12:57

  Added:       src/main/org/jboss/tm/plugins/tyrex CoordinatorInvoker.java
                        CoordinatorRemote.java
                        CoordinatorRemoteInterface.java
                        ResourceInvoker.java ResourceRemote.java
                        ResourceRemoteInterface.java
                        TransactionManagerService.java
                        TransactionManagerServiceMBean.java
                        TyrexTransactionPropagationContextManager.java
                        TyrexTxPropagationContext.java
  Log:
  Initial commit of Tyrex distributed transaction manager support in JBoss. Support 
added for using JBoss with any TM that supports javax.transaction.TransactionManager 
interface.
  
  Revision  Changes    Path
  1.1                  
jboss/src/main/org/jboss/tm/plugins/tyrex/CoordinatorInvoker.java
  
  Index: CoordinatorInvoker.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.tm.plugins.tyrex;
  
  // We need this to make a proxy for the OMG Coordinator for the remote site
  import java.lang.reflect.Proxy;
  import java.lang.reflect.Method;
  
  // OMG CORBA related stuff (used by Tyrex for transaction context propagation)
  import org.omg.CosTransactions.Coordinator;
  import org.omg.CosTransactions.Resource;
  
  import java.lang.reflect.Method;
  import java.lang.reflect.InvocationHandler;
  
  import java.io.Externalizable;
  import java.io.IOException;
  
  import org.jboss.logging.Logger;
  
  /**
   *  This is the InvocationHandler for the Proxy to the originator's Coordinator.
   *  We allow only register_resource() method to be called to register the
   *  subordinate transaction as a Resource with the Coordinator.
   *
   *   @see org.omg.CosTransactions.Coordinator#register_resource,
   *        java.lang.reflect.Proxy,
   *        java.lang.reflect.InvocationHandler,
   *        CoordinatorRemote,
   *        ResourceRemote
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
   *   @version $Revision: 1.1 $
   */
  
  class CoordinatorInvoker implements InvocationHandler, Externalizable {
  
      private static Method register_resource;
  
      static {
        try {
          register_resource = Coordinator.class.getMethod("register_resource",
                                                          new Class[] 
{Resource.class});
        }
        catch (Exception e) {
          e.printStackTrace();
        }
      }
  
      private CoordinatorRemoteInterface remoteCoordinator;
  
      public CoordinatorInvoker() {
        // for externalization to work
      }
  
      protected CoordinatorInvoker (Coordinator coord) {
        try {
          remoteCoordinator = new CoordinatorRemote(coord);
        } catch (Exception e) {
          e.printStackTrace();
          Logger.warning("CoordinatorInvoker could not instantiate properly, there 
will be problems with this transaction!");
        }
      }
  
      public void writeExternal(java.io.ObjectOutput out) throws IOException {
        out.writeObject(remoteCoordinator);
      }
  
      public void readExternal(java.io.ObjectInput in) throws IOException, 
ClassNotFoundException{
        remoteCoordinator = (CoordinatorRemoteInterface) in.readObject();
      }
  
      public Object invoke (Object proxy, Method method, Object[] args)
          throws Throwable {
  
          if (method.equals(register_resource)) {
  
            // Wrap the Resource in a serializable Proxy and ship it with the
            // call to the CoordinatorRemote
            Resource serializableResource =
                (Resource) Proxy.newProxyInstance (getClass().getClassLoader(),
                                                   new Class[] {Resource.class},
                                                   new ResourceInvoker((Resource) 
args[0])); // args should be not null
            // DEBUG          Logger.debug("TyrexTxPropagationContex: Created Proxy 
for Resource, calling Proxy for Coordinator");
            // call our Coordinator
            remoteCoordinator.register_resource(serializableResource);
            // register_resource in our remoteCoordinator is a 'void' method call
            // we ignore the RecoveryCoordinator for now
            return null;
          }
          else {
            // all this trickery was only for the purpose of the remote
            // Tyrex instance being able to register it's transaction as a
            // resource, so we do not support any other methods besides 
"register_resource"
            throw new Exception("CoordinatorInvoker Proxy was called through an 
unknown method");
          }
      }
  }
  
  
  1.1                  jboss/src/main/org/jboss/tm/plugins/tyrex/CoordinatorRemote.java
  
  Index: CoordinatorRemote.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.tm.plugins.tyrex;
  
  import java.rmi.Remote;
  import java.rmi.RemoteException;
  import java.lang.reflect.Proxy;
  
  import org.omg.CosTransactions.Coordinator;
  import org.omg.CosTransactions._CoordinatorImplBase;
  import org.omg.CosTransactions.RecoveryCoordinator;
  import org.omg.CosTransactions.Resource;
  
  import org.omg.CosTransactions.Inactive;
  
  import org.jboss.logging.Logger;
  /**
   *   RMI Remote Proxy that enables the remote Transaction Manager
   *   to register the subordinate transaction as a resource
   *   with the originator's Coordinator
   *
   *   @see CoordinatorRemoteInterface, CoordinatorInvoker, ResourceRemote
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
   *   @version $Revision: 1.1 $
   */
  
  public class CoordinatorRemote extends java.rmi.server.UnicastRemoteObject 
implements CoordinatorRemoteInterface {
  
    private org.omg.CosTransactions._CoordinatorImplBase localCoordinator;
  
    protected CoordinatorRemote(Coordinator coord) throws RemoteException {
      localCoordinator = (org.omg.CosTransactions._CoordinatorImplBase) coord;
    }
  
    public void register_resource(Resource serializableResource) throws Inactive, 
RemoteException {
      // DEBUG    Logger.debug("CoordinatorRemote: Registering resource");
      RecoveryCoordinator recoveryCoord = 
localCoordinator.register_resource(serializableResource);
      // ignore the recovery coordinator for now
      // DEBUG    Logger.debug("CoordinatorRemote: Resource registered");
    }
  }
  
  
  1.1                  
jboss/src/main/org/jboss/tm/plugins/tyrex/CoordinatorRemoteInterface.java
  
  Index: CoordinatorRemoteInterface.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.tm.plugins.tyrex;
  
  import java.rmi.Remote;
  import java.lang.reflect.Proxy;
  import java.rmi.RemoteException;
  
  import org.omg.CosTransactions.Resource;
  import org.omg.CosTransactions.Inactive;
  
  /**
   *   Subset of the org.omg.CosTransactions.Coordinator interface
   *   necessary to register a remote subordinate transaction
   *
   *   @see org.omg.CosTransactions.Coordinator,
   *        org.omg.CosTransactions.Resource,
   *        CoordinatorRemote
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
   *   @version $Revision: 1.1 $
   */
  
  public interface CoordinatorRemoteInterface extends Remote {
    public void register_resource(Resource serializableResource) throws Inactive, 
RemoteException;
  }
  
  
  1.1                  jboss/src/main/org/jboss/tm/plugins/tyrex/ResourceInvoker.java
  
  Index: ResourceInvoker.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.tm.plugins.tyrex;
  
  import java.lang.reflect.Method;
  import java.lang.reflect.InvocationHandler;
  
  import org.omg.CosTransactions.Coordinator;
  import org.omg.CosTransactions.Resource;
  
  import java.lang.reflect.Method;
  import java.lang.reflect.InvocationHandler;
  
  import java.io.Externalizable;
  import java.io.IOException;
  
  import org.jboss.logging.Logger;
  
  /**
   *   This is the InvocationHandler for the Proxy we hand over to the
   *   originator's Coordinator to control our subordinate transaction
   *
   *   @see org.omg.CosTransactions.Resource,
   *        java.lang.reflect.Proxy,
   *        java.lang.reflect.InvocationHandler,
   *        ResourceRemote,
   *        CoordinatorRemote
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
   *   @version $Revision: 1.1 $
   */
  
  public class ResourceInvoker implements InvocationHandler, Externalizable {
  
    private static Method prepare;
    private static Method rollback;
    private static Method commit;
    private static Method commit_one_phase;
    private static Method forget;
  
    static {
      try {
        // get all the methods through which we may get called
        prepare = Resource.class.getMethod("prepare", null);
        rollback = Resource.class.getMethod("rollback", null);
        commit = Resource.class.getMethod("commit", null);
        commit_one_phase = Resource.class.getMethod("commit_one_phase", null);
        forget = Resource.class.getMethod("forget", null);
      }
      catch (Exception e) {
        e.printStackTrace();
      }
    }
  
    private ResourceRemoteInterface remoteResource;
  
    public ResourceInvoker() {
      // for externalization to work
    }
  
    public ResourceInvoker(Resource res) {
      try {
        remoteResource = new ResourceRemote(res);
      } catch (Exception e) {
        e.printStackTrace();
        remoteResource = null;
        Logger.warning("ResourceInvoker did not initialize properly! Ther will be 
problems with this transaction!");
      }
    }
  
    public void writeExternal(java.io.ObjectOutput out) throws IOException {
      out.writeObject(remoteResource);
    }
  
    public void readExternal(java.io.ObjectInput in) throws IOException, 
ClassNotFoundException {
      this.remoteResource = (ResourceRemoteInterface) in.readObject();
    }
  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  
      // Just call the appropriate method on our RemoteCoordinator
  
      if (method.equals(prepare)) {
        // DEBUG      Logger.debug("ResourceInvoker: calling prepare()");
        remoteResource.prepare();
        return null;
      }
      else if (method.equals(rollback)) {
        // DEBUG      Logger.debug("ResourceInvoker: calling rollback()");
        remoteResource.rollback();
        return null;
      }
      else if (method.equals(commit)) {
        // DEBUG      Logger.debug("ResourceInvoker: calling commit()");
        remoteResource.commit();
        return null;
      }
      else if (method.equals(commit_one_phase)) {
        // DEBUG      Logger.debug("ResourceInvoker: calling commit_one_phase()");
        remoteResource.commit_one_phase();
        return null;
      }
      else if (method.equals(forget)) {
        // DEBUG      Logger.debug("ResourceInvoker: calling forget()");
        remoteResource.forget();
        return null;
      }
      else {
        throw new Exception("ResourceInvoker: called through an unknown method!");
      }
    }
  }
  
  
  1.1                  jboss/src/main/org/jboss/tm/plugins/tyrex/ResourceRemote.java
  
  Index: ResourceRemote.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.tm.plugins.tyrex;
  
  import java.rmi.RemoteException;
  
  import org.omg.CosTransactions.HeuristicCommit;
  import org.omg.CosTransactions.HeuristicMixed;
  import org.omg.CosTransactions.HeuristicHazard;
  import org.omg.CosTransactions.HeuristicRollback;
  import org.omg.CosTransactions.NotPrepared;
  
  import org.omg.CosTransactions.Vote;
  
  import org.omg.CosTransactions.Resource;
  import org.omg.CosTransactions._ResourceImplBase;
  
  import org.jboss.logging.Logger;
  
  /**
   *   RMI Remote Proxy that enables the Coordinator on the originating
   *   side to control the subordinate transaction
   *
   *   @see ResourceRemoteInterface,  ResourceInvoker, CoordinatorRemote
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
   *   @version $Revision: 1.1 $
   */
  
  public class ResourceRemote extends java.rmi.server.UnicastRemoteObject implements 
ResourceRemoteInterface {
  
    private _ResourceImplBase localResource;
  
    protected ResourceRemote(Resource resource) throws RemoteException{
      localResource = (_ResourceImplBase) resource;
    }
  
    public Vote prepare() throws HeuristicMixed, HeuristicHazard, RemoteException {
      //DEBUG    Logger.debug("ResourceRemote: preparing ...");
      return localResource.prepare();
    }
  
    public void rollback() throws HeuristicCommit, HeuristicMixed, HeuristicHazard, 
RemoteException {
      //DEBUG    Logger.debug("ResourceRemote: rolling back ...");
      localResource.rollback();
      //DEBUG    Logger.debug("ResourceRemote: rolled back.");
    }
  
    public void commit() throws NotPrepared, HeuristicRollback,
                         HeuristicMixed, HeuristicHazard, RemoteException {
      //DEBUG    Logger.debug("ResourceRemote: committing ...");
      localResource.commit();
      //DEBUG    Logger.debug("ResourceRemote: committed.");
    }
  
    public void commit_one_phase() throws HeuristicHazard, RemoteException {
      //DEBUG    Logger.debug("ResourceRemote: One phase committing ...");
      localResource.commit_one_phase();
      //DEBUG    Logger.debug("ResourceRemote: committed.");
    }
  
    public void forget() throws RemoteException{
      //DEBUG    Logger.debug("ResourceRemote: forgetting ...");
      localResource.forget();
      //DEBUG    Logger.debug("ResourceRemote: forgot.");
    }
  }
  
  
  1.1                  
jboss/src/main/org/jboss/tm/plugins/tyrex/ResourceRemoteInterface.java
  
  Index: ResourceRemoteInterface.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.tm.plugins.tyrex;
  
  import java.rmi.Remote;
  import java.rmi.RemoteException;
  
  import org.omg.CosTransactions.HeuristicCommit;
  import org.omg.CosTransactions.HeuristicMixed;
  import org.omg.CosTransactions.HeuristicHazard;
  import org.omg.CosTransactions.HeuristicRollback;
  import org.omg.CosTransactions.NotPrepared;
  
  import org.omg.CosTransactions.Vote;
  
  /**
   *   Subset of org.omg.CosTransactions.Resource interface
   *   that is necessary for the originator's Coordinator to control
   *   the subordinate remote transaction's completion/rollback
   *
   *   @see org.omg.CosTransactions.Resource, ResourceRemote
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
   *   @version $Revision: 1.1 $
   */
  
  interface ResourceRemoteInterface extends Remote {
    public Vote prepare() throws HeuristicMixed, HeuristicHazard, RemoteException;
    public void rollback() throws HeuristicCommit, HeuristicMixed, HeuristicHazard, 
RemoteException;
    public void commit() throws NotPrepared, HeuristicRollback,
                         HeuristicMixed, HeuristicHazard, RemoteException;
    public void commit_one_phase() throws HeuristicHazard, RemoteException;
    public void forget() throws RemoteException;
  }
  
  
  1.1                  
jboss/src/main/org/jboss/tm/plugins/tyrex/TransactionManagerService.java
  
  Index: TransactionManagerService.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  
  package org.jboss.tm.plugins.tyrex;
  
  import java.io.File;
  import java.net.URL;
  import java.rmi.server.UnicastRemoteObject;
  import java.rmi.RemoteException;
  import java.rmi.ServerException;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.Hashtable;
  
  import javax.naming.InitialContext;
  import javax.naming.Context;
  import javax.naming.Reference;
  import javax.naming.Name;
  import javax.naming.NamingException;
  import javax.naming.NameParser;
  import javax.naming.spi.ObjectFactory;
  
  import javax.management.MBeanServer;
  import javax.management.ObjectName;
  
  import javax.transaction.TransactionManager;
  import tyrex.tm.TransactionDomain;
  import org.omg.CosTransactions.PropagationContext;
  import org.omg.CosTransactions.TransactionFactory;
  import org.omg.CosTSPortability.Sender;
  import org.omg.CosTSPortability.Receiver;
  
  import org.jboss.logging.Logger;
  import org.jboss.util.ServiceMBeanSupport;
  
  /**
   *  This is a JMX service which manages the Tyrex TransactionManager 
(tyrex.exolab.org).
   *  The service creates it and binds a Reference to it into JNDI. It also initializes
   *  the object that manages Tyrex TransactionPropagationContext.
   *
   *  @see TyrexTransactionPropagationContextManager, tyrex.tm.TransactionDomain
   *  @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
   *  @version $Revision: 1.1 $
   */
  public class TransactionManagerService
     extends ServiceMBeanSupport
     implements TransactionManagerServiceMBean, ObjectFactory
  {
     // Constants -----------------------------------------------------
     public static String JNDI_NAME = "java:/TransactionManager";
     public static String JNDI_TPC_SENDER = "java:/TPCSender";
     public static String JNDI_TPC_RECEIVER = "java:/TPCReceiver";
     public static String JNDI_IMPORTER = 
"java:/TransactionPropagationContextImporter";
     public static String JNDI_EXPORTER = 
"java:/TransactionPropagationContextExporter";
  
     // Attributes ----------------------------------------------------
  
     MBeanServer server;
  
     String config_file = "domain.xml";
  
  
     // Static --------------------------------------------------------
  
     static TransactionDomain txDomain = null;
     static TransactionManager tm = null;
     static TransactionFactory txFactory = null; //implements Sender and Receiver as 
well
     static TyrexTransactionPropagationContextManager tpcManager = null;
  
     // ServiceMBeanSupport overrides ---------------------------------
  
     public String getName()
     {
        return "Tyrex Transaction manager";
     }
  
     protected ObjectName getObjectName(MBeanServer server, ObjectName name)
        throws javax.management.MalformedObjectNameException
     {
        this.server = server;
        return new ObjectName(OBJECT_NAME);
     }
  
     protected void startService()
        throws Exception
     {
        // Create txDomain singleton if we did not do it yet.
        if (txDomain == null) {
          txDomain = tyrex.tm.TransactionDomain.createDomain( config_file );
          txDomain.recover();
          tm = txDomain.getTransactionManager();
          txFactory = txDomain.getTransactionFactory();
        }
  
        // Bind reference to TM in JNDI
        // Tyrex TM does not implement the tx importer and exporter
        // interfaces. These are handled through a different class.
        bindRef(JNDI_NAME, "javax.transaction.TransactionManager");
        bindRef(JNDI_TPC_SENDER, "org.omg.CosTSPortability.Sender");
        bindRef(JNDI_TPC_RECEIVER, "org.omg.CosTSPortability.Receiver");
  
        // This Manager implements the importer and exporter interfaces
        // but relies on the org.omg.CosTSPortability Sender and Receiver
        // to be bound in the JNDI as TPCSender and TPCReceiver
        // so we can initialize it only after we bind these names to JNDI
        if (tpcManager == null) {
          tpcManager = new TyrexTransactionPropagationContextManager();
        }
        bindRef(JNDI_IMPORTER, "org.jboss.tm.TransactionPropagationContextImporter");
        bindRef(JNDI_EXPORTER, "org.jboss.tm.TransactionPropagationContextFactory");
     }
  
     protected void stopService()
     {
        try {
           // Remove TM
           Context ctx = new InitialContext();
           ctx.unbind(JNDI_NAME);
           ctx.unbind(JNDI_TPC_SENDER);
           ctx.unbind(JNDI_TPC_RECEIVER);
           ctx.unbind(JNDI_IMPORTER);
           ctx.unbind(JNDI_EXPORTER);
        } catch (Exception e) {
           log.exception(e);
        }
     }
  
    public String getConfigFileName() {
      return this.config_file;
    }
  
    public void setConfigFileName(String name) {
      this.config_file = name;
    }
  
     // ObjectFactory implementation ----------------------------------
  
     public Object getObjectInstance(Object obj, Name name,
                                     Context nameCtx, Hashtable environment)
        throws Exception
     {
        NameParser parser;
        Name tmName = null;
        Name senderName = null;
        Name receiverName = null;
        Name exporterName = null;
        Name importerName = null;
  
        if (nameCtx != null) {
          parser = nameCtx.getNameParser(nameCtx.getNameInNamespace());
        } else {
          Context ctx = new InitialContext();
          parser = ctx.getNameParser(ctx.getNameInNamespace());
        }
  
        try {
          tmName = parser.parse("TransactionManager");
          senderName = parser.parse("TPCSender");
          receiverName = parser.parse("TPCReceiver");
          exporterName = parser.parse("TransactionPropagationContextImporter");
          importerName = parser.parse("TransactionPropagationContextExporter");
        }
        catch (NamingException e) {
          e.printStackTrace();
        }
  
  // DEBUG      Logger.debug("Obtaining object instance for: " + name);
  // DEBUG
     /*
        Logger.debug("My composite names: " + tmName +
                     ", " + senderName +
                     ", " + receiverName +
                     ", " + exporterName +
                     ", " + importerName);
      */
        if (name.endsWith(tmName)) {
          // Return the transaction manager
          return tm;
        }
        else if (name.endsWith(senderName) ||
                 name.endsWith(receiverName)) {
          return txFactory;
        }
        else if (name.endsWith(exporterName) ||
                 name.endsWith(importerName)) {
          return tpcManager;
        }
        else {
          Logger.warning("TransactionManagerService: requested an unknown object:" + 
name);
          return null;
        }
  
     }
  
  
     // Private -------------------------------------------------------
  
     private void bindRef(String jndiName, String className)
        throws Exception
     {
        Reference ref = new Reference(className, getClass().getName(), null);
        new InitialContext().bind(jndiName, ref);
     }
  }
  
  
  
  1.1                  
jboss/src/main/org/jboss/tm/plugins/tyrex/TransactionManagerServiceMBean.java
  
  Index: TransactionManagerServiceMBean.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  
  package org.jboss.tm.plugins.tyrex;
  
  /**
   *   MBean interface for the Tyrex TransactionManager
   *   (not all calls are implemented)
   *
   *   @see TransactionManagerService
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
   *   @version $Revision: 1.1 $
   */
  public interface TransactionManagerServiceMBean
     extends org.jboss.util.ServiceMBean
  {
     // Constants -----------------------------------------------------
     public static final String OBJECT_NAME = ":service=TransactionManager";
  
     // Public --------------------------------------------------------
     public String getConfigFileName();
  
     public void setConfigFileName(String name);
  }
  
  
  
  
  1.1                  
jboss/src/main/org/jboss/tm/plugins/tyrex/TyrexTransactionPropagationContextManager.java
  
  Index: TyrexTransactionPropagationContextManager.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.tm.plugins.tyrex;
  
  import javax.naming.Name;
  import javax.naming.Context;
  import javax.naming.InitialContext;
  import javax.naming.Reference;
  import javax.transaction.Transaction;
  import javax.transaction.TransactionManager;
  
  import org.jboss.logging.Logger;
  
  import tyrex.tm.TransactionDomain;
  import org.omg.CosTransactions.PropagationContextHolder;
  import org.omg.CosTransactions.PropagationContext;
  import org.omg.CosTSPortability.Sender;
  import org.omg.CosTSPortability.Receiver;
  
  /**
   *   This object implements the TransactionPropagationContext importer and
   *   exporter for JBoss.
   *
   *   @see TransactionManagerService
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
   *   @version $Revision: 1.1 $
   */
  
  public class TyrexTransactionPropagationContextManager implements
      org.jboss.tm.TransactionPropagationContextFactory,
      org.jboss.tm.TransactionPropagationContextImporter
  {
  // -- Constants -------------------------------------------------------
  
    private static String JNDI_TPC_SENDER = "java:/TPCSender";
    private static String JNDI_TPC_RECEIVER = "java:/TPCReceiver";
    private static String JNDI_TM = "java:/TransactionManager";
  
  // -- Private stuff ---------------------------------------------------
    private Sender sender = null;
    private Receiver receiver = null;
    private TransactionManager tm = null;
  
  // -- Constructors ----------------------------------------------------
    protected TyrexTransactionPropagationContextManager() {
      try {
        Context ctx = new InitialContext();
        this.sender = (Sender) ctx.lookup(JNDI_TPC_SENDER);
        this.receiver = (Receiver) ctx.lookup(JNDI_TPC_RECEIVER);
        this.tm = (TransactionManager) ctx.lookup(JNDI_TM);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  
  
  // ------------ TransactionPropagationContextFactory methods ------------
    /**
     * Return a transaction propagation context associated with
     * transaction that the calling thread came in with
     */
    public Object getTransactionPropagationContext() {
      Object tpc = null;
  
      try {
        if (tm.getTransaction() != null) {
  
          PropagationContextHolder tpcHolder = new PropagationContextHolder();
          sender.sending_request(0,tpcHolder);
  
          // now modify the tpc that is inside this tpcHolder and package it
          // into a serializable entity
          tpc = new TyrexTxPropagationContext(tpcHolder.value);
          // DEBUG        Logger.debug("Exporting a transaction");
        } else {
          // this tpc represents a null transaction and will be propagated to remote 
side
          tpc = new TyrexTxPropagationContext();
          // DEBUG        Logger.debug("Exporting null transaction");
        }
      } catch (Exception e) {
        // DEBUG
        Logger.warning ("TyrexTransactionPropagationContextManager: unable to create 
propagation ctx!");
        e.printStackTrace();
      } finally {
        return tpc;
      }
  
    }
  
     /**
      *  Return a transaction propagation context for the transaction
      *  given as an argument, or <code>null</code>
      *  if the argument is <code>null</code> or of a type unknown to
      *  this factory.
      */
    public Object getTransactionPropagationContext(Transaction tx) {
      Transaction oldTx = null;
      Object tpc = null;
  
      try {
        oldTx = tm.getTransaction();
        if ( (tx == null) || (tx.equals(oldTx)) ) {
          // we are being called in the context of this transaction
          tpc = getTransactionPropagationContext();
        }
        else {
          tm.suspend();
          tm.resume(tx);
          tpc = getTransactionPropagationContext();
          tm.suspend();
          tm.resume(oldTx);
        }
      } catch (Exception e) {
        e.printStackTrace();
      } finally {
          return tpc;
      }
    }
  
  // ------------- TransactionPropagationContextImporter methods -----------
  
    public Transaction importTransactionPropagationContext(Object tpc) {
      if (tpc instanceof TyrexTxPropagationContext) {
        Transaction oldTx;
        try {
          // DEBUG        Logger.debug ("TyrexTransactionPropagationContextManager: 
importing tpc.");
          oldTx = tm.suspend(); //cleanup the incoming thread
          PropagationContext omgTpc = ((TyrexTxPropagationContext) 
tpc).getPropagationContext();
  
          Transaction newTx = null; // if omgTpc is null, then newTx will remain null
  
          if (omgTpc != null) {
            receiver.received_request(0, omgTpc);
            // transaction gets resumed during the call
            // to txFactory, since we need just the transaction object,
            // get it and then suspend the transaction
            newTx = tm.getTransaction();
            tm.suspend();
            // now restart the original transaction
            if (oldTx != null)
              tm.resume(oldTx);
          } else {
            //DEBUG          Logger.debug("Importing null transaction");
          }
          // DEBUG        Logger.debug ("TyrexTransactionPropagationContextManager: 
transaction imported.");
          return newTx;
        } catch (Exception e) {
          e.printStackTrace();
          return null;
        }
      }
      else {
        Logger.warning("TyrexTransactionPropagationContextManager: unknown Tx 
PropagationContex");
        return null;
      }
    }
  }
  
  
  1.1                  
jboss/src/main/org/jboss/tm/plugins/tyrex/TyrexTxPropagationContext.java
  
  Index: TyrexTxPropagationContext.java
  ===================================================================
  /*
   * JBoss, the OpenSource EJB server
   *
   * Distributable under LGPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.tm.plugins.tyrex;
  
  import java.io.Externalizable;
  import java.io.ObjectOutput;
  import java.io.ObjectInput;
  import java.io.IOException;
  
  import org.jboss.logging.Logger;
  
  // OMG CORBA related stuff (used by Tyrex for transaction context propagation)
  import org.omg.CosTransactions.PropagationContext;
  import org.omg.CosTransactions.TransIdentity;
  import org.omg.CosTransactions.Coordinator;
  import org.omg.CosTransactions.Resource;
  import org.omg.CosTransactions.otid_t;
  
  // We need this to make a proxy for the OMG Coordinator for the remote site
  import java.lang.reflect.Proxy;
  
  /**
   *   This class wraps the OMG PropagationContext to be able to pass it
   *   via RMI. Currently we are only taking care of top-level transaction
   *   (no nested transactions) by sending via RMI only
   *   - timeout value
   *   - otid (@see org.omg.CosTransactions.otid_t - representation of Xid)
   *   - Coordinator's Proxy
   *
   *
   *   @see org.omg.CosTransactions.PropagationContext,
   *        org.omg.CosTransactions.otid_t,
   *        org.omg.CosTransactions.Coordinator,
   *        java.lang.reflect.Proxy
   *   @author <a href="mailto:[EMAIL PROTECTED]";>Anatoly Akkerman</a>
   *   @version $Revision: 1.1 $
   */
  
  public class TyrexTxPropagationContext implements Externalizable {
  
    public TyrexTxPropagationContext() {
      // public, no args constructor for externalization to work
  
      this.isNull = true;
    }
  
    protected TyrexTxPropagationContext (PropagationContext tpc) {
      this.isNull = false; // this is not a null Propagation Context
      this.timeout = tpc.timeout;
      this.coord = (Coordinator) Proxy.newProxyInstance(getClass().getClassLoader(),
                                          new Class[] {Coordinator.class},
                                          new CoordinatorInvoker(tpc.current.coord));
      this.otid = tpc.current.otid;
      // DEBUG    Logger.debug("TyrexTxPropagationContext: created new tpc");
    }
  
    // this is called on the remote side
    protected PropagationContext getPropagationContext() {
  
      if ( !isNull && (tpc == null) ) {
        // create once
        tpc = new PropagationContext( this.timeout,
                                      new TransIdentity(this.coord,
                                                        null,
                                                        this.otid),
                                      new TransIdentity[0], // no parents, but not null
                                      null);
      }
  
      // DEBUG    Logger.debug("TyrexTxPropagationContext recreated 
PropagationContext");
      return tpc;
    }
  
    public void writeExternal(ObjectOutput out) throws IOException {
      try {
        out.writeBoolean(this.isNull);
        if (! isNull) {
          out.writeInt(this.timeout);
          // DEBUG       Logger.debug("TPC: wrote timeout");
          out.writeObject((Proxy) this.coord);
          // DEBUG       Logger.debug("TPC: wrote CoordinatorProxy");
          out.writeObject(this.otid); // otid implements IDLEntity which extends 
Serializable
          // DEBUG       Logger.debug("TPC: wrote otid");
        }
      } catch (Exception e) {
        Logger.warning("Unable to externalize tpc!");
        e.printStackTrace();
        throw new IOException(e.toString());
      }
    }
  
    public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {
      try {
        this.isNull = in.readBoolean();
        if (!isNull) {
          this.timeout = in.readInt();
          // DEBUG      Logger.debug("TPC: read timeout");
          this.coord = (Coordinator) in.readObject();
          // DEBUG      Logger.debug("TPC: read coordinator");
          this.otid = (otid_t) in.readObject();
          // DEBUG      Logger.debug("TPC: read otid");
        }
      } catch (Exception e) {
        e.printStackTrace();
        throw new IOException (e.toString());
      }
    }
  
    /*
     * The fields of PropagationContext that we want to send to the remote side
     */
  
    protected int timeout;
    // this is a Proxy for the local transaction coordinator
    // since we need to serialize the Coordinator and it is not serializable
    protected Coordinator coord;
    protected otid_t otid;
  
    // this is a special field that gets propagated to the remote side to
    // indicate that this is a null propagation context (i.e. it represents a
    // null transaction). Simply using a null TyrexTxPropagationContext in RMI
    // calls crashes because of NullPointerException in serialization of a
    // method invocation
    protected boolean isNull;
  
    // cached copy of tpc, so that we need to create it only once
    // on the remote side
    protected PropagationContext tpc = null;
  }
  
  

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

Reply via email to