gt:                 if (!mcWrapper.isStale()) {
context: /*******************************************************************************
   * Copyright (c) 1997, 2018 IBM Corporation and others.
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   *     IBM Corporation - initial API and implementation
   *******************************************************************************/
  package com.ibm.ejs.j2c;
  
  import javax.resource.NotSupportedException;
  import javax.resource.ResourceException;
  import javax.transaction.Synchronization;
  import javax.transaction.xa.XAException;
  import javax.transaction.xa.XAResource;
  import javax.transaction.xa.Xid;
  
  import com.ibm.websphere.ras.Tr;
  import com.ibm.websphere.ras.TraceComponent;
  import com.ibm.ws.Transaction.UOWCoordinator;
  import com.ibm.ws.j2c.TranWrapper;
  import com.ibm.ws.resource.ResourceRefInfo;
  import com.ibm.ws.tx.embeddable.EmbeddableWebSphereTransactionManager;
  
  /**
   * <P>XATransactionWrapper is a wrapper for the resource adapter's SPI XAResource object. It is
   * enlisted with the transaction manager and supports all the XAResource verbs as a two
   * phase capable XAResource.
   *
   * <P>Scope : EJB server
   *
   * <P>Object model : 1 instance per ManagedConnection (if required)
   *
   */
  
  public class XATransactionWrapper implements XAResource, Synchronization, TranWrapper {
  
      private final MCWrapper mcWrapper;
      private XAResource xaResource;
      private boolean enlisted = false;
      private boolean hasRollbackOccured = false;
      private static final TraceComponent tc = Tr.register(XATransactionWrapper.class,
                                                           J2CConstants.traceSpec,
                                                           J2CConstants.messageFile);
  
      protected XATransactionWrapper(MCWrapper mcWrapper) {
  
          final boolean isTracingEnabled = TraceComponent.isAnyTracingEnabled();
  
          if (isTracingEnabled && tc.isEntryEnabled()) {
              Tr.entry(this, tc, "<init>");
          }
  
          this.mcWrapper = mcWrapper;
  
          if (isTracingEnabled && tc.isEntryEnabled()) {
              Tr.exit(this, tc, "<init>");
          }
  
      }
  
      protected void initialize() throws ResourceException {
  
          if (xaResource == null) {
  
              try {
                  xaResource = mcWrapper.getManagedConnection().getXAResource();
              } catch (ResourceException e) {
                  com.ibm.ws.ffdc.FFDCFilter.processException(
                                                              e,
                                                              "com.ibm.ejs.j2c.XATransactionWrapper.initialize",
                                                              "149",
                                                              this);
                  Tr.error(tc, "FAILED_TO_OBTAIN_XAResource_J2CA0078", e, mcWrapper.gConfigProps.cfName);
                  throw e;
              } catch (Exception e) {
                  com.ibm.ws.ffdc.FFDCFilter.processException(
                                                              e,
                                                              "com.ibm.ejs.j2c.XATransactionWrapper.initialize",
                                                              "154",
                                                              this);
                  String pmiName = null;
                  if (mcWrapper != null) {
                      pmiName = mcWrapper.gConfigProps.cfName;
                  }
                  Tr.error(tc, "FAILED_TO_OBTAIN_XAResource_J2CA0078", new Object[] { e, pmiName });
                  ResourceException re = new ResourceException("initialize: caught Exception");
                  re.initCause(e);
                  throw re;
              }
  
          }
  
      }
  
      /**
       * Reinitializes its own state such that it may be placed in the PoolManagers
       * pool for reuse. The XAResource will be retained.
       */
      public void cleanup() {
          enlisted = false;
      }
  
      /**
       * Reinitializes its own state such that it may be reused.
       * The XAResource will be released.
       */
      public void releaseResources() {
          xaResource = null;
      }
  
      /**
       * Register the current object with the Synchronization manager for the current transaction
       *
       * @throws ResourceException.
       */
  
      @Override
      public boolean addSync() throws ResourceException {
  
          final boolean isTracingEnabled = TraceComponent.isAnyTracingEnabled();
  
          if (isTracingEnabled && tc.isEntryEnabled()) {
              Tr.entry(this, tc, "addSync");
          }
  
          UOWCoordinator uowCoord = mcWrapper.getUOWCoordinator();
  
          if (uowCoord == null) {
              java.lang.IllegalStateException e = new java.lang.IllegalStateException("addSync: illegal state exception. uowCoord is null");
              Object[] parms = new Object[] { "addSync", e };
              Tr.error(tc, "ILLEGAL_STATE_EXCEPTION_J2CA0079", parms);
              if (isTracingEnabled && tc.isEntryEnabled())
                  Tr.exit(this, tc, "addSync", e);
              throw e;
          }
  
          try {
              if (mcWrapper.isConnectionSynchronizationProvider()) {
                  throw new NotSupportedException();
              }
  
              /*
               * This code will remain here just in case we run into this
               * case. We should not be isEnlistmentDisabled in this code.
               *
               * Log a message and return, if isEnlistmentDisabled is true.
               */
              if (mcWrapper.isEnlistmentDisabled()) {
  
                  if (isTracingEnabled && tc.isDebugEnabled()) {
                      Tr.debug(this, tc, "Managed connection isEnlistmentDisabled is true.");
                      Tr.debug(this, tc, "Returning without registering.");
                  }
  
                  if (isTracingEnabled && tc.isEntryEnabled()) {
                      Tr.exit(this, tc, "addSync", false);
                  }
  
                  return false;
  
              }
  
              /*
               * Use our XATransactionWrapper
               */
              EmbeddableWebSphereTransactionManager tranMgr = mcWrapper.pm.connectorSvc.transactionManager;
              tranMgr.registerSynchronization(uowCoord, this);
  
          } catch (Exception e) {
              com.ibm.ws.ffdc.FFDCFilter.processException(
                                                          e,
                                                          "com.ibm.ejs.j2c.XATransactionWrapper.addSync",
                                                          "237",
                                                          this);
              Object[] parms = new Object[] { "addSync", e, "ResourceException" };
              Tr.error(tc, "REGISTER_WITH_SYNCHRONIZATION_EXCP_J2CA0026", parms);
              ResourceException re = new ResourceException("addSync: caught Exception");
              re.initCause(e);
              if (isTracingEnabled && tc.isEntryEnabled())
                  Tr.exit(this, tc, "addSync", e);
              throw re;
          }
  
          if (isTracingEnabled && tc.isEntryEnabled())
              Tr.exit(this, tc, "addSync", true);
          return true;
      }
  
      /**
       * Part of javax.transaction.Synchronization interface,
       * This method is called by the transaction manager after the transaction is committed or rolled back.
       *
       * @param status The status of the transaction completion.
       */
  
      @Override
      public void afterCompletion(int status) {
  
          final boolean isTracingEnabled = TraceComponent.isAnyTracingEnabled();
  
          if (isTracingEnabled && tc.isEntryEnabled()) {
              Tr.entry(this, tc, "afterCompletion");
          }
  
          this.hasRollbackOccured = false;
  
          if (isTracingEnabled && tc.isDebugEnabled()) {
  
              if (mcWrapper.getHandleCount() != 0) {
                  if (isTracingEnabled && tc.isDebugEnabled()) {
                      Tr.debug(this, tc, "Information:  handle not closed at end of UOW for resource " + mcWrapper.gConfigProps.cfName);
                  }
              }
  
          }
  
          if (mcWrapper.isMCAborted()) {
              if (isTracingEnabled && tc.isEntryEnabled())
                  Tr.exit(this, tc, "afterCompletion", "aborted");
              return;
          }
  
          /*
           * Mark the transaction complete in the wrapper
           */
  
          mcWrapper.transactionComplete();
  
          boolean shareable = mcWrapper.getConnectionManager().shareable();
  
          // If the connection is sharable, or it is non-sharable and the handleCount is
          // zero, then release it back to the poolManger, otherwise simply reset the
          // transaction related variables.
          //
          // Note: sharable connections are released at the end of transactions regardless of
          //  outstanding handles because we don't supports handled being associated to an active
          //  managedConnection outside of a sharing boundary.
          //
          if ((shareable) || (!shareable && mcWrapper.getHandleCount() == 0) || mcWrapper.isStale()) {
  
              if (isTracingEnabled && tc.isDebugEnabled()) {
                  Tr.debug(this, tc,
                           "Releasing the connection to the pool. shareable = " + shareable + "  handleCount = " + mcWrapper.getHandleCount() + "  isStale = " + mcWrapper.isStale());
              }
  
              try {
                  mcWrapper.releaseToPoolManager();
              } catch (Exception e) {
                  com.ibm.ws.ffdc.FFDCFilter.processException(
                                                              e,
                                                              "com.ibm.ejs.j2c.XATransactionWrapper.afterCompletion",
                                                              "291",
                                                              this);
                  if (isTracingEnabled && tc.isDebugEnabled()) {
                      Tr.debug(this, tc, "afterCompletionCode for resource " + mcWrapper.gConfigProps.cfName + ":  caught Exception", e);
                  }
  
              }
  
          } else {
              /*
               * The cleanup of the coordinator and enlisted flag
               */
              enlisted = false;
              mcWrapper.setUOWCoordinator(null);
          }
  
          if (isTracingEnabled && tc.isEntryEnabled()) {
              Tr.exit(this, tc, "afterCompletion");
          }
  
      }
  
      /**
       * Part of javax.transaction.Synchronization interface,
       * This method is called by the transaction manager prior to the start of the transaction completion process.
       */
  
      @Override
      public void beforeCompletion() {
  
          final boolean isTracingEnabled = TraceComponent.isAnyTracingEnabled();
  
          if (isTracingEnabled && tc.isEntryEnabled()) {
              Tr.entry(this, tc, "beforeCompletion");
              Tr.exit(this, tc, "beforeCompletion");
          }
  
      }
  
      /**
       * Excute a commit statement
       *
       * @param xid A global transaction identifier
       * @param onePhase If true, the resource manager should use a one-phase commit protocol to commit the work done on behalf of xid.
       *
       * @throws XAException An error has occurred. Possible XAExceptions are XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or
       *             XAER_PROTO.
       */
  
      @Override
      public void commit(Xid xid, boolean onePhase) throws XAException {
  
          final boolean isTracingEnabled = TraceComponent.isAnyTracingEnabled();
  
          if (isTracingEnabled && tc.isEntryEnabled()) {
              Tr.entry(this, tc, "commit");
          }
  
          try {
              xaResource.commit(xid, onePhase);
          } catch (XAException e) {
              processXAException(e);
              com.ibm.ws.ffdc.FFDCFilter.processException(
                                                          e,
                                                          "com.ibm.ejs.j2c.XATransactionWrapper.commit",
                                                          "378",
                                                          this);
              if (!mcWrapper.isStale()) {
                  Tr.error(tc, "XA_RESOURCE_ADAPTER_OPERATION_ID_EXCP_J2CA0027", "commit", xid, e, mcWrapper.gConfigProps.cfName);
              }
              if (isTracingEnabled && tc.isEntryEnabled())
                  Tr.exit(this, tc, "commit", e);
              throw e;
          } catch (Exception e) {
              com.ibm.ws.ffdc.FFDCFilter.processException(
                                                          e,
                                                          "com.ibm.ejs.j2c.XATransactionWrapper.commit",
                                                          "384",
                                                          this);
              if (!mcWrapper.shouldBeDestroyed()) {
                  mcWrapper.markTransactionError();
                  Tr.error(tc, "XA_RESOURCE_ADAPTER_OPERATION_ID_EXCP_J2CA0027", "commit", xid, e, mcWrapper.gConfigProps.cfName);
              }
              XAException xae = new XAException(XAException.XAER_RMFAIL);
              xae.initCause(e);
              if (isTracingEnabled && tc.isEntryEnabled())
                  Tr.exit(this, tc, "commit", e);
              throw xae;
          }
  
          if (isTracingEnabled && tc.isEntryEnabled())
              Tr.exit(this, tc, "commit");
      }
  
      /**
       * Ends the work performed on behalf of a transaction branch. The resource manager disassociates the XA resource from the transaction branch specified and let the transaction
       * be completed.
       *
       * <P>If TMSUSPEND is specified in flags, the transaction branch is temporarily suspended in incomplete state. The transaction context is in suspened state and must be resumed
       * via start with TMRESUME specified.
       *
       * <P>If TMFAIL is specified, the portion of work has failed. The resource manager may mark the transaction as rollback-only
       *
       * <P>If TMSUCCESS is specified, the portion of work has completed successfully.
       *
       * @param xid A global transaction identifier that is the same as what was used previously in the start method.
       * @param flags One of TMSUCCESS, TMFAIL, or TMSUSPEND.
       *
       * @throws XAException An error has occurred. Possible XAException values are XAER_RMERR, XAER_RMFAILED, XAER_NOTA, XAER_INVAL, XAER_PROTO, or XA_RB*.
       */
  
      @Override
      public void end(Xid xid, int flags) throws XAException {
  
          final boolean isTracingEnabled = TraceComponent.isAnyTracingEnabled();
  
          if (isTracingEnabled && tc.isEntryEnabled())
              Tr.entry(this, tc, "end");
  
          if (getMcWrapper().isMCAborted()) {
              Tr.exit(tc, "Connection was aborted. Exiting end.");
              return;
          }
  
          try {
              xaResource.end(xid, flags);
          } catch (XAException e) {
              processXAException(e);
              if (flags == XAResource.TMFAIL && ((e.errorCode >= XAException.XA_RBBASE) && (e.errorCode <= XAException.XA_RBEND))) {
                  // okay error codes for the rollback processing.
              } else {
                  com.ibm.ws.ffdc.FFDCFilter.processException(
                                                              e,
                                                              "com.ibm.ejs.j2c.XATransactionWrapper.end",
                                                              "417",
                                                              this);
  