Package org.jboss.test.jca.adapter

Source Code of org.jboss.test.jca.adapter.TestManagedConnection

/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.jca.adapter;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.resource.ResourceException;
import javax.resource.spi.ConnectionEvent;
import javax.resource.spi.ConnectionEventListener;
import javax.resource.spi.ConnectionRequestInfo;
import javax.resource.spi.LocalTransaction;
import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ManagedConnectionMetaData;
import javax.resource.spi.ResourceAdapterInternalException;
import javax.security.auth.Subject;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;

import org.jboss.logging.Logger;
import org.jboss.tm.TxUtils;

/**
* TestManagedConnection.java
*
* @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
* @author <a href="mailto:adrian@jboss.com">Adrian Brock</a>
* @version <tt>$Revision: 97477 $</tt>
*/
public class TestManagedConnection  implements ManagedConnection, XAResource, LocalTransaction
{
   public static final String STARTED = "STARTED";
   public static final String SUSPENDED = "SUSPENDED";
   public static final String ENDED = "ENDED";
   public static final String PREPARED = "PREPARED";

   public static final String LOCAL_NONE = "LOCAL_NONE";
   public static final String LOCAL_TRANSACTION = "LOCAL_TRANSACTION";
   public static final String LOCAL_COMMITTED = "LOCAL_COMMITTED";
   public static final String LOCAL_ROLLEDBACK = "LOCAL_ROLLEDBACK";

   private final int id;

   private Logger log = Logger.getLogger(getClass());
   private TestManagedConnectionFactory mcf;
   private HashSet handles = new HashSet();
   private HashSet listeners = new HashSet();

   private GlobalXID currentXid;

   private AtomicBoolean destroyed = new AtomicBoolean(false);

   private boolean failInPrepare = false;
   private boolean failInCommit = false;
   private static boolean failInStart = false;
   private static boolean failInEnd = false;

   private static int xaCode;

   private String localState = LOCAL_NONE;

   public static void setFailInStart(boolean fis, int xa)
   {
      failInStart = fis;
      xaCode = xa;
   }
   public static void setFailInEnd(boolean fie, int xa)
   {
     failInEnd = fie;
     xaCode = xa;

   }

   public TestManagedConnection (final TestManagedConnectionFactory mcf, final Subject subject, final TestConnectionRequestInfo cri, final int id)
   {
      this.mcf = mcf;
      this.id = id;
   }

   void setFailInPrepare(final boolean fail, final int xaCode)
   {
      this.failInPrepare = fail;
      this.xaCode = xaCode;
   }

   void setFailInCommit(final boolean fail, final int xaCode)
   {
      this.failInCommit = fail;
      this.xaCode = xaCode;
   }

   // implementation of javax.resource.spi.ManagedConnection interface

   public synchronized void destroy() throws ResourceException
   {
      log.info("Destroying connection: " + this);
      if (destroyed.get())
         return;
      cleanup();
      destroyed.set(true);
      currentXid = null;
   }

   public synchronized void cleanup() throws ResourceException
   {
      log.info("cleanup: " + this +" handles=" + handles);

      checkDestroyedResourceException();
      for (Iterator i = handles.iterator(); i.hasNext(); )
      {
         TestConnection c = (TestConnection)i.next();
         c.setMc(null);
         i.remove();
      }
   }

   public synchronized Object getConnection(Subject param1, ConnectionRequestInfo param2) throws ResourceException
   {
      log.info("getConnection " + this);

      checkDestroyedResourceException();

      if (param2 != null && ((TestConnectionRequestInfo) param2).failure.equals("getConnectionResource"))
         throw new ResourceException(this.toString());
      if (param2 != null && ((TestConnectionRequestInfo) param2).failure.equals("getConnectionRuntime"))
         throw new RuntimeException(this.toString());
      TestConnection c =  new TestConnection(this);
      handles.add(c);
      return c;
   }

   public synchronized void associateConnection(Object p) throws ResourceException
   {
      log.info("associateConnecton " + this + " connection=" + p);

      checkDestroyedResourceException();

      if (p instanceof TestConnection)
      {
         ((TestConnection)p).setMc(this);
         handles.add(p);
      }
      else
      {
         throw new ResourceException("wrong kind of Connection " + p);
      }
   }

   public synchronized void addConnectionEventListener(ConnectionEventListener cel)
   {
      log.info("addCEL: " + this + " " + cel);
      listeners.add(cel);
   }

   public synchronized void removeConnectionEventListener(ConnectionEventListener cel)
   {
      log.info("removeCEL: " + this + " " + cel);
      listeners.remove(cel);
   }

   public synchronized XAResource getXAResource() throws ResourceException
   {
      checkDestroyedResourceException();
      return this;
   }

   public LocalTransaction getLocalTransaction() throws ResourceException
   {
      return this;
   }

   public ManagedConnectionMetaData getMetaData() throws ResourceException
   {
      return null;
   }

   public void setLogWriter(PrintWriter param1) throws ResourceException
   {
   }

   public PrintWriter getLogWriter() throws ResourceException
   {
     return null;
   }

   // implementation of javax.transaction.xa.XAResource interface

   public List getListeners()
   {
      List result = null;

      synchronized (listeners)
      {
         result = new ArrayList(listeners);
      }

      return result;

   }
   public void start(Xid xid, int flags) throws XAException
   {
      long sleepInStart = mcf.getSleepInStart();
      if (flags == TMNOFLAGS && sleepInStart != 0)
         doSleep(sleepInStart);

      synchronized (this)
      {
         if(failInStart)
         {
            XAException xaex = new XAException(xaCode + "for" + this);
            xaex.errorCode = xaCode;
            broadcastConnectionError(xaex);
            throw xaex;
         }

         GlobalXID gid = new GlobalXID(xid);
         String flagString = TxUtils.getXAResourceFlagsAsString(flags);
         log.info("start with xid=" + gid + " flags=" + flagString + " for " + this);
         checkDestroyedXAException();
         Map xids = getXids();
         synchronized (xids)
         {
            String state = (String) xids.get(gid);
            if (state == null && flags != TMNOFLAGS)
            {
                XAException xaex = new XAException("Invalid start state=" + state + " xid=" + gid + " flags=" + flagString + " for " + this);
                xaex.errorCode = XAException.XAER_PROTO;
                throw xaex;
            }
            if (state != null && state != SUSPENDED && state != ENDED
                  && (state != STARTED || ((flags & TMJOIN) == 0))
                  && (state != STARTED || ((flags & TMRESUME) == 0))
               )
            {
                XAException xaex = new XAException("Invalid start state=" + state + " xid=" + gid + " flags=" + flagString + " for " + this);
                xaex.errorCode = XAException.XAER_PROTO;
                throw xaex;
            }

            if ((flags & TMJOIN) != 0 && mcf.failJoin)
            {
                XAException xaex = new XAException("Join is not allowed " + state + " xid=" + gid + " flags=" + flagString + " for " + this);
                xaex.errorCode = XAException.XAER_PROTO;
                throw xaex;
            }
            xids.put(gid, STARTED);
         }

         this.currentXid = gid;
      }
   }

   public void end(final Xid xid, final int flags) throws XAException
   {

      if(failInEnd)
      {
          XAException xaex = new XAException(xaCode + "for" + this);
          xaex.errorCode = xaCode;
          broadcastConnectionError(xaex);
          throw xaex;
      }

      long sleepInEnd = mcf.getSleepInEnd();
      if (flags != TMSUCCESS && sleepInEnd != 0)
         doSleep(sleepInEnd);

      synchronized (this)
      {
         GlobalXID gid = new GlobalXID(xid);
         String flagString = TxUtils.getXAResourceFlagsAsString(flags);
         log.info("end with xid=" + gid + " flags=" + flagString + " for " + this);
         // checkDestroyedXAException(); (check is broken, don't use with JBossTS)
         Map xids = getXids();
         synchronized (xids)
         {
            String state = (String) xids.get(gid);
            if (state != STARTED && state != SUSPENDED && state != ENDED)
            {
                XAException xaex = new XAException("Invalid end state=" + state + " xid=" + gid + " " + this);
                xaex.errorCode = XAException.XAER_PROTO;
                throw xaex;
            }
            if ((flags & TMSUSPEND) == 0)
               xids.put(gid, ENDED);
            else
               xids.put(gid, SUSPENDED);
         }

         this.currentXid = null;
      }
   }

   public synchronized void commit(Xid xid, boolean onePhase) throws XAException
   {
      GlobalXID gid = new GlobalXID(xid);
      log.info("commit with xid=" + gid + " onePhase=" + onePhase + " for " + this);
      checkDestroyedXAException();
      if (failInCommit)
      {
          XAException xaex = new XAException(xaCode + " for " + this);
          xaex.errorCode = xaCode;
          throw xaex;
      }
      Map xids = getXids();
      synchronized (xids)
      {
         String state = (String) xids.get(gid);
         if (onePhase)
         {
            if (state != SUSPENDED && state != ENDED)
            {
               XAException xaex = new XAException("Invalid one phase commit state=" + state + " xid=" + gid + " " + this);
               xaex.errorCode = XAException.XAER_PROTO;
               throw xaex;
            }
         }
         else
         {
            if (state != PREPARED)
            {
               XAException xaex = new XAException("Invalid two phase commit state=" + state + " xid=" + gid + " " + this);
               xaex.errorCode = XAException.XAER_PROTO;
               throw xaex;
            }
         }
         xids.remove(gid);
      }
   }

   public synchronized void rollback(Xid xid) throws XAException
   {
      GlobalXID gid = new GlobalXID(xid);
      log.info("rollback with xid=" + gid + " for " + this);
      checkDestroyedXAException();
      Map xids = getXids();
      synchronized (xids)
      {
         String state = (String) xids.get(gid);
         if (state != SUSPENDED && state != ENDED && state != PREPARED)
         {
            XAException xaex = new XAException("Invalid rollback state=" + state + " xid=" + gid + " " + this);
            xaex.errorCode = XAException.XAER_PROTO;
            throw xaex;
         }
         xids.remove(gid);
      }
   }

   public synchronized int prepare(Xid xid) throws XAException
   {
      GlobalXID gid = new GlobalXID(xid);
      log.info("prepare with xid=" + gid + " for " + this);
      checkDestroyedXAException();
      Map xids = getXids();
      synchronized (xids)
      {
         String state = (String) xids.get(gid);
         if (state != SUSPENDED && state != ENDED) {
            XAException xaex = new XAException("Invalid prepare state=" + state + " xid=" + gid + " " + this);
            xaex.errorCode = XAException.XAER_PROTO;
            throw xaex;
         }
         if (failInPrepare)
         {
            XAException xae = new XAException(xaCode + " for " + this);
            xae.errorCode = xaCode;
            throw xae;
         }
         xids.put(gid, PREPARED);
         return XA_OK;
      }
   }

   public synchronized void forget(Xid xid) throws XAException
   {
      GlobalXID gid = new GlobalXID(xid);
      log.info("forget with xid=" + gid + " for " + this);
      checkDestroyedXAException();
      Map xids = getXids();
      synchronized (xids)
      {
         xids.remove(gid);
      }
   }

   public Xid[] recover(int param1) throws XAException
   {
      return null;
   }

   public boolean isSameRM(XAResource xar) throws XAException
   {
      if (xar == null || xar instanceof TestManagedConnection == false)
         return false;
      TestManagedConnection other = (TestManagedConnection) xar;
      return (mcf == other.mcf);
   }

   public int getTransactionTimeout() throws XAException
   {
      return 0;
   }

   public boolean setTransactionTimeout(int param1) throws XAException
   {
      return false;
   }

   public String getLocalState()
   {
      return localState;
   }

   public void begin() throws ResourceException
   {
      localState = LOCAL_TRANSACTION;
   }

   public void sendBegin() throws ResourceException
   {
      begin();
      ConnectionEvent event = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_STARTED);
      Collection copy = new ArrayList(listeners);
      for (Iterator i = copy.iterator(); i.hasNext(); )
      {
         ConnectionEventListener cel = (ConnectionEventListener)i.next();
         try
         {
            cel.localTransactionStarted(event);
         }
         catch (Throwable ignored)
         {
            log.warn("Ignored", ignored);
         }
      }
   }

   public void commit() throws ResourceException
   {
      localState = LOCAL_COMMITTED;
   }

   public void sendCommit() throws ResourceException
   {
      commit();

      ConnectionEvent event = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_COMMITTED);
      Collection copy = new ArrayList(listeners);
      for (Iterator i = copy.iterator(); i.hasNext(); )
      {
         ConnectionEventListener cel = (ConnectionEventListener)i.next();
         try
         {
            cel.localTransactionCommitted(event);
         }
         catch (Throwable ignored)
         {
            log.warn("Ignored", ignored);
         }
      }
   }

   public void rollback() throws ResourceException
   {
      localState = LOCAL_ROLLEDBACK;
   }

   public void sendRollback() throws ResourceException
   {
      rollback();

      ConnectionEvent event = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK);
      Collection copy = new ArrayList(listeners);
      for (Iterator i = copy.iterator(); i.hasNext(); )
      {
         ConnectionEventListener cel = (ConnectionEventListener)i.next();
         try
         {
            cel.localTransactionRolledback(event);
         }
         catch (Throwable ignored)
         {
            log.warn("Ignored", ignored);
         }
      }
   }

   synchronized boolean isInTx()
   {
      log.info("isInTx: " + this);
      return currentXid != null;
   }

   Map getXids()
   {
      return mcf.getXids();
   }

   void connectionClosed(TestConnection handle)
   {
      if (destroyed.get())
         return;

      log.info("Connetion closed handle=" + handle + " for " + this);

      ConnectionEvent ce = new ConnectionEvent(this ,ConnectionEvent.CONNECTION_CLOSED);
      ce.setConnectionHandle(handle);
      Collection copy = new ArrayList(listeners);
      for (Iterator i = copy.iterator(); i.hasNext(); )
      {
         log.info("notifying 1 cel connectionClosed");
         ConnectionEventListener cel = (ConnectionEventListener)i.next();
         try
         {
            cel.connectionClosed(ce);
         }
         catch (Throwable ignored)
         {
            log.warn("Ignored", ignored);
         }
      }
      synchronized (this)
      {
         handles.remove(handle);
      }
   }

   protected void broadcastConnectionError(Throwable e)
   {
      if(destroyed.get())
         return;

      Exception ex = null;
      if (e instanceof Exception)
         ex = (Exception) e;
      else
         ex = new ResourceAdapterInternalException("Unexpected error", e);
      ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.CONNECTION_ERROR_OCCURRED, ex);
      Collection copy = null;
      synchronized(listeners)
      {
         copy = new ArrayList(listeners);
      }
      for (Iterator i = copy.iterator(); i.hasNext(); )
      {
         ConnectionEventListener cel = (ConnectionEventListener)i.next();
         try
         {
            cel.connectionErrorOccurred(ce);
         }
         catch (Throwable t)
         {
         }
      }
   }

   void connectionError(TestConnection handle, Exception e)
   {
      if (destroyed.get())
         return;

      log.info("Connetion error handle=" + handle + " for " + this, e);

      ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.CONNECTION_ERROR_OCCURRED, e);
      ce.setConnectionHandle(handle);
      Collection copy = new ArrayList(listeners);
      for (Iterator i = copy.iterator(); i.hasNext(); )
      {
         ConnectionEventListener cel = (ConnectionEventListener)i.next();
         try
         {
            cel.connectionErrorOccurred(ce);
         }
         catch (Throwable ignored)
         {
         }
      }
   }

   void checkDestroyedResourceException() throws ResourceException
   {
      if (destroyed.get())
         throw new ResourceException("Already destroyed " + this);
   }

   void checkDestroyedXAException() throws XAException
   {
      if (destroyed.get()) {
          XAException xaex = new XAException("Already destroyed " + this);
          xaex.errorCode = XAException.XAER_PROTO;
          throw xaex;
      }
   }

   public synchronized String toString()
   {
      StringBuffer buffer = new StringBuffer();
      buffer.append("TestManagedConnection#").append(id);
      buffer.append("{");
      buffer.append("xid=").append(currentXid);
      buffer.append(" destroyed=").append(destroyed.get());
      buffer.append("}");
      return buffer.toString();
   }

   public void doSleep(long sleep)
   {
      boolean interrupted = false;
      try
      {
         Thread.sleep(sleep);
      }
      catch (InterruptedException e)
      {
         interrupted = true;
      }
      if (interrupted)
         Thread.currentThread().interrupt();
   }

   public class GlobalXID
   {
      byte[] gid;
      int hashCode;
      String toString;

      public GlobalXID(Xid xid)
      {
         gid = xid.getGlobalTransactionId();
         hashCode = Arrays.hashCode(gid);
      }

      public int hashCode()
      {
         return hashCode;
      }

      public String toString()
      {
         return toString;
      }

      public boolean equals(Object obj)
      {
         if (obj == null || obj instanceof GlobalXID == false)
            return false;
         GlobalXID other = (GlobalXID) obj;
         return Arrays.equals(gid, other.gid);
      }
   }
}
TOP

Related Classes of org.jboss.test.jca.adapter.TestManagedConnection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.