class AtomikosJmsTopicSubscriberProxy extends AtomikosJmsMessageConsumerProxy
    implements TopicSubscriber {
  private static final Logger LOGGER =
      LoggerFactory.createLogger(AtomikosJmsTopicSubscriberProxy.class);

  public AtomikosJmsTopicSubscriberProxy(TopicSubscriber delegate, SessionHandleState state) {
    super(delegate, state);
  }

  private TopicSubscriber getDelegateTopicSubscriber() {
    if (LOGGER.isInfoEnabled()) LOGGER.logInfo(this + ": getDelegateTopicSubscriber()...");
    TopicSubscriber ret = (TopicSubscriber) getDelegate();
    if (LOGGER.isDebugEnabled())
      LOGGER.logDebug(this + ": getDelegateTopicSubscriber() returning " + ret);
    return ret;
  }

  public boolean getNoLocal() throws JMSException {
    if (LOGGER.isInfoEnabled()) LOGGER.logInfo(this + ": getNoLocal()...");
    boolean ret = false;
    try {
      ret = getDelegateTopicSubscriber().getNoLocal();
    } catch (Exception e) {
      handleException(e);
    }
    if (LOGGER.isDebugEnabled()) LOGGER.logDebug(this + ": getNoLocal() returning " + ret);
    return ret;
  }

  public Topic getTopic() throws JMSException {
    if (LOGGER.isInfoEnabled()) LOGGER.logInfo(this + ": getTopic()...");
    Topic ret = null;
    try {
      ret = getDelegateTopicSubscriber().getTopic();
    } catch (Exception e) {
      handleException(e);
    }
    if (LOGGER.isDebugEnabled()) LOGGER.logDebug(this + ": getTopic() returning " + ret);
    return ret;
  }

  public String toString() {
    return "atomikos TopicSubscriber proxy for " + getDelegate();
  }
}
/** A TransactionalResource that works with the JCA architecture. */
public class JcaTransactionalResource extends XATransactionalResource {
  private static final Logger LOGGER = LoggerFactory.createLogger(JcaTransactionalResource.class);

  private ManagedConnectionFactory mcf;

  private ManagedConnection connection;

  public JcaTransactionalResource(String servername, ManagedConnectionFactory mcf) {
    super(servername);
    this.mcf = mcf;
  }

  public JcaTransactionalResource(
      String servername, ManagedConnectionFactory mcf, XidFactory xidFactory) {
    super(servername, xidFactory);
    this.mcf = mcf;
  }

  public boolean usesXAResource(XAResource xares) {
    // used for XID creation; return false
    // since this task is taken over by a dedicated
    // resource. otherwise, deadlock occurs on the
    // first enlist of an XAResource that comes
    // from a pool limited to size 1!!!
    return false;
  }

  /*
   * @see com.atomikos.datasource.xa.XATransactionalResource#refreshXAConnection()
   */
  protected XAResource refreshXAConnection() throws ResourceException {
    if (LOGGER.isInfoEnabled()) {
      LOGGER.logInfo("refreshXAConnection() for resource: " + getName());
    }

    XAResource ret = null;
    if (connection != null) {
      try {
        connection.destroy();
      } catch (Exception normal) {
        // this can be expected, since this method is only called
        // if there is a connection problem
      }
    }

    try {

      LOGGER.logInfo("about to block for new connection...");
      // System.out.println ( "ABOUT TO BLOCK FOR NEW CONNECTION");
      connection = mcf.createManagedConnection(null, null);

    } catch (javax.resource.ResourceException e) {
      // ignore and return null: happens if resource is down
      // at this moment
      connection = null;
    } finally {
      // System.out.println ( "BLOCKING DONE");
      if (LOGGER.isInfoEnabled()) {
        LOGGER.logInfo("blocking done.");
      }
    }

    try {
      if (connection != null) ret = connection.getXAResource();
    } catch (javax.resource.ResourceException e) {
      LOGGER.logWarning("error getting XAResource: " + e.getMessage());

      throw new ResourceException("Error in getting XA resource", e);
    }

    LOGGER.logInfo("refreshXAConnection() done.");

    // System.out.println ( "DONE REFRESHXACONNECTION FOR RESOURCE: " +
    // getName() );

    return ret;
  }

  /** Overrides default close to include closing any open connections to the source. */
  public void close() throws ResourceException {
    super.close();
    try {
      if (connection != null) connection.destroy();
    } catch (Exception err) {
      // throw new ResourceException ( err.getMessage() );
      // exception REMOVED because it close clashes
      // with shutdown hooks (in which the order of TS and
      // DS shutdown is unpredictable)
    }
  }
}