[jboss-cvs] JBossAS SVN: r93296 - in projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core: connectionmanager and 7 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Sep 8 15:59:37 EDT 2009


Author: gurkanerdogdu
Date: 2009-09-08 15:59:36 -0400 (Tue, 08 Sep 2009)
New Revision: 93296

Added:
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/CachedConnectionManager.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/KeyConnectionAssociation.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/exception/JBossLocalXAException.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/exception/JBossLocalXAExceptionFormatter.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/AbstractConnectionListener.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/NoTxConnectionListener.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/TxConnectionListener.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/transaction/TransactionSynchronizer.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/xa/LocalXAResource.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/xa/XAResourceWrapperImpl.java
Modified:
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/api/ConnectionManager.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/AbstractConnectionManager.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionCounter.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionManagerImpl.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionRecord.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/ConnectionListener.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/notx/NoTxConnectionManager.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/pool/AbstractPool.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/pool/InternalManagedConnectionPool.java
   projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/tx/TxConnectionManager.java
Log:
[JBJCA-167] Generic Connection Manager Implementation

Modified: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/api/ConnectionManager.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/api/ConnectionManager.java	2009-09-08 19:22:26 UTC (rev 93295)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/api/ConnectionManager.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -22,37 +22,33 @@
 
 package org.jboss.jca.core.api;
 
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
+import org.jboss.jca.core.connectionmanager.AbstractConnectionManager;
+import org.jboss.jca.core.connectionmanager.transaction.JTATransactionChecker;
 
+import java.io.Serializable;
 
+import org.jboss.tm.TransactionTimeoutConfiguration;
+
 /**
  * The JBoss specific connection manager interface
  * @author <a href="mailto:gurkanerdogdu at yahoo.com">Gurkan Erdogdu</a>
  * @version $Rev$ $Date$
  */
-public interface ConnectionManager extends javax.resource.spi.ConnectionManager
-{
+public interface ConnectionManager extends 
+   javax.resource.spi.ConnectionManager,
+   Serializable,
+   TransactionTimeoutConfiguration,
+   JTATransactionChecker
+{   
    /**
-    * Document Me!
-    * @param errorRollback errorRollback
-    * @return time left
-    * @throws RollbackException if exception occurs
+    * Sets real connection manager.
+    * @param realConnectionManager real connection manager
     */
-   public long getTimeLeftBeforeTransactionTimeout(boolean errorRollback) throws RollbackException;
+   public void setRealConnectionManager(AbstractConnectionManager realConnectionManager);
    
    /**
-    * Document Me!
-    * @return transaction time out
-    * @throws SystemException if any exceptions
+    * Gets real connection manager instance.
+    * @return real connection manager
     */
-   public int getTransactionTimeout() throws SystemException;
-   
-   /**
-    * Document Me!
-    * @throws RollbackException rollbacked exception
-    * @throws SystemException system exception
-    */
-   public void checkTransactionActive() throws RollbackException, SystemException;
-   
+   public AbstractConnectionManager getRealConnectionManager();
 }


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/api/ConnectionManager.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date

Modified: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/AbstractConnectionManager.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/AbstractConnectionManager.java	2009-09-08 19:22:26 UTC (rev 93295)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/AbstractConnectionManager.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -22,25 +22,42 @@
 
 package org.jboss.jca.core.connectionmanager;
 
+import org.jboss.jca.common.api.JBossResourceException;
 import org.jboss.jca.core.connectionmanager.listener.ConnectionCacheListener;
 import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
 import org.jboss.jca.core.connectionmanager.listener.ConnectionListenerFactory;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionState;
+import org.jboss.jca.core.connectionmanager.pool.api.ManagedConnectionPool;
 import org.jboss.jca.core.connectionmanager.transaction.JTATransactionChecker;
 
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.resource.ResourceException;
-import javax.resource.spi.ManagedConnection;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.security.auth.Subject;
 import javax.transaction.RollbackException;
 import javax.transaction.SystemException;
+import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
 
+import org.jboss.logging.Logger;
+
+import org.jboss.security.SubjectFactory;
 import org.jboss.tm.TransactionTimeoutConfiguration;
+import org.jboss.util.NotImplementedException;
 
 
+
 /**
  * AbstractConnectionManager.
+ * 
  * @author <a href="mailto:gurkanerdogdu at yahoo.com">Gurkan Erdogdu</a>
  * @version $Rev$ $Date$
  *
@@ -53,23 +70,424 @@
    JTATransactionChecker
 
 {
+   /**Log instance*/
+   private Logger log = Logger.getLogger(getClass());
    
    /**
-    * {@inheritDoc}
+    * Note that this copy has a trailing / unlike the original in
+    * JaasSecurityManagerService.
     */
-   public ConnectionListener createConnectionListener(ManagedConnection managedConnection, Object context) 
-      throws ResourceException
+   private static final String SECURITY_MGR_PATH = "java:/jaas/";
+   
+   /**Connection manager pooling strategy*/
+   private ManagedConnectionPool poolingStrategy;
+   
+   /**Security domain jndi name*/
+   private String securityDomainJndiName;
+   
+   /**SubjectFactory*/
+   private SubjectFactory subjectFactory;
+   
+   /**Log trace*/
+   private boolean trace;
+   
+   /**Number of retry to allocate connection*/
+   private int allocationRetry;
+
+   /**Interval between retries*/
+   private long allocationRetryWaitMillis;
+
+   /**Startup/ShutDown flag*/
+   private AtomicBoolean shutdown = new AtomicBoolean(false);
+   
+   /**Cached connection manager*/
+   private CachedConnectionManager cachedConnectionManager;
+   
+   /**Jndi name*/
+   private String jndiName;
+   
+   /**
+    * Creates a new instance of connection manager.   
+    */
+   protected AbstractConnectionManager()
    {
-      // TODO Auto-generated method stub
+      this.trace = log.isTraceEnabled();
+   }
+   
+   /**
+    * Gets log.
+    * @return log instance
+    */
+   protected Logger getLog()
+   {
+      return this.log;
+   }
+   
+   /**
+    * Sets pooling strategy.
+    * @param poolingStrategy pooling strategy
+    */
+   public void setPoolingStrategy(ManagedConnectionPool poolingStrategy)
+   {
+      this.poolingStrategy = poolingStrategy;
+   }
+   
+   /**
+    * Gets pooling strategy.
+    * @return pooling strategy
+    */
+   public ManagedConnectionPool getPoolingStrategy()
+   {
+      return this.poolingStrategy;
+   }   
+   
+   /**
+    * Sets cached connection manager.
+    * @param cachedConnectionManager cached connection manager
+    */
+   public void setCachedConnectionManager(CachedConnectionManager cachedConnectionManager)
+   {
+      this.cachedConnectionManager = cachedConnectionManager;
+   }
+   
+   
+   /**
+    * Sets shut down flag.
+    * @param shutDown shut down flag
+    */
+   public void setShutDown(boolean shutDown)
+   {
+      this.shutdown.set(shutDown);
+   }
+   
+   /**
+    * Gets cached connection manager.
+    * @return cached connection manager
+    */
+   public CachedConnectionManager getCachedConnectionManager()
+   {
+      return this.cachedConnectionManager;
+   }
+   
+   /**
+    * Gets jndi name.
+    * @return jndi name
+    */
+   public String getJndiName()
+   {
+      return jndiName;
+   }
+
+   /**
+    * Sets jndi name.
+    * @param jndiName jndi name
+    */
+   public void setJndiName(String jndiName)
+   {
+      this.jndiName = jndiName;
+   }
+   
+   /**
+    * Sets security domain jndi name.
+    * @param securityDomainJndiName security jndi name
+    */
+   public void setSecurityDomainJndiName(String securityDomainJndiName)
+   {
+      if (securityDomainJndiName != null && securityDomainJndiName.startsWith(SECURITY_MGR_PATH))
+      {
+         securityDomainJndiName = securityDomainJndiName.substring(SECURITY_MGR_PATH.length());
+         log.warn("WARNING: UPDATE YOUR SecurityDomainJndiName! REMOVE " + SECURITY_MGR_PATH);
+      }
+      
+      this.securityDomainJndiName = securityDomainJndiName;
+   }
+
+   /**
+    * Gets security domain jndi name.
+    * @return security domain jndi name
+    */
+   public String getSecurityDomainJndiName()
+   {
+      return securityDomainJndiName;
+   }
+ 
+   /**
+    * Gets subject factory instance.
+    * @return subject factory
+    */
+   public SubjectFactory getSubjectFactory()
+   {
+      return subjectFactory;
+   }
+
+   /**
+    * Sets subject factory.
+    * @param subjectFactory subject factory
+    */
+   public void setSubjectFactory(SubjectFactory subjectFactory)
+   {
+      this.subjectFactory = subjectFactory;
+   }
+   
+   
+   /**
+    * Gets managed connection factory.
+    * @return managed connection factory
+    */
+   public javax.resource.spi.ManagedConnectionFactory getManagedConnectionFactory()
+   {
+      if (this.poolingStrategy == null)
+      {
+         if (this.log.isTraceEnabled())
+         {
+            log.trace("No pooling strategy found! for connection manager : " + this);
+            
+            return null;
+         }
+      }
+      else
+      {
+         return poolingStrategy.getManagedConnectionFactory();   
+      }
+      
       return null;
    }
+   
+   /**
+    * Set the number of allocation retries
+    * @param number retry number
+    */
+   public void setAllocationRetry(int number)
+   {
+      if (number >= 0)
+         allocationRetry = number;
+   }
 
    /**
+    * Get the number of allocation retries
+    * @return The number of retries
+    */
+   public int getAllocationRetry()
+   {
+      return allocationRetry;
+   }
+
+   /**
+    * Set the wait time between each allocation retry
+    * @param millis wait in ms
+    */
+   public void setAllocationRetryWaitMillis(long millis)
+   {
+      if (millis > 0)
+         allocationRetryWaitMillis = millis;
+   }
+
+   /**
+    * Get the wait time between each allocation retry
+    * @return The millis
+    */
+   public long getAllocationRetryWaitMillis()
+   {
+      return allocationRetryWaitMillis;
+   }
+   
+   /**
+    * Public for use in testing pooling functionality by itself.
+    * called by both allocateConnection and reconnect.
+    * 
+    * @param subject a <code>Subject</code> value
+    * @param cri a <code>ConnectionRequestInfo</code> value
+    * @return a <code>ManagedConnection</code> value
+    * @exception ResourceException if an error occurs
+    */
+   public ConnectionListener getManagedConnection(Subject subject, ConnectionRequestInfo cri) throws ResourceException
+   {
+      return getManagedConnection(null, subject, cri);
+   }
+   
+   /**
+    * Get the managed connection from the pool.
+    * 
+    * @param transaction the transaction for track by transaction
+    * @param subject the subject
+    * @param cri the ConnectionRequestInfo
+    * @return a managed connection
+    * @exception ResourceException if an error occurs
+    */
+   protected ConnectionListener getManagedConnection(Transaction transaction, Subject subject, 
+         ConnectionRequestInfo cri) throws ResourceException
+   {
+      ResourceException failure = null;
+
+      if (this.shutdown.get())
+      {
+         throw new ResourceException("The connection manager is shutdown " + jndiName);  
+      }
+      
+      // First attempt
+      try
+      {
+         return this.poolingStrategy.getConnection(transaction, subject, cri);
+      }
+      catch (ResourceException e)
+      {
+         failure = e;
+         
+         // Retry?
+         if (this.allocationRetry != 0)
+         {
+            for (int i = 0; i < this.allocationRetry; i++)
+            {
+               if (this.shutdown.get())
+               {
+                  throw new ResourceException("The connection manager is shutdown " + jndiName);  
+               }
+
+               if (this.trace)
+               {
+                  log.trace("Attempting allocation retry for cri=" + cri);  
+               }
+
+               try
+               {
+                  if (allocationRetryWaitMillis != 0)
+                  {
+                     Thread.sleep(allocationRetryWaitMillis);  
+                  }
+
+                  return poolingStrategy.getConnection(transaction, subject, cri);
+               }
+               catch (ResourceException re)
+               {
+                  failure = re;
+               }
+               catch (InterruptedException ie)
+               {
+                  JBossResourceException.rethrowAsResourceException("getManagedConnection retry wait was interrupted " +
+                        jndiName, ie);
+               }
+            }
+         }
+      }
+
+      // If we get here all retries failed, throw the lastest failure
+      throw new ResourceException("Unable to get managed connection for " + jndiName, failure);
+   }
+   
+   /**
+    * Kill given connection listener wrapped connection instance.
+    * @param cl connection listener that wraps connection
+    * @param kill kill connection or not
+    */
+   public void returnManagedConnection(ConnectionListener cl, boolean kill)
+   {
+      ManagedConnectionPool localStrategy = cl.getManagedConnectionPool();
+      if (localStrategy != this.poolingStrategy)
+      {
+         kill = true;  
+      }
+
+      try
+      {
+         if (!kill && cl.getState().equals(ConnectionState.NORMAL))
+         {
+            cl.tidyup();  
+         }
+      }
+      catch (Throwable t)
+      {
+         log.warn("Error during tidy up connection" + cl, t);
+         kill = true;
+      }
+      
+      try
+      {
+         localStrategy.returnConnection(cl, kill);
+      }
+      catch (ResourceException re)
+      {
+         // We can receive notification of an error on the connection
+         // before it has been assigned to the pool. Reduce the noise for
+         // these errors
+         if (kill)
+         {
+            log.debug("resourceException killing connection (error retrieving from pool?)", re);  
+         }
+         else
+         {
+            log.warn("resourceException returning connection: " + cl.getManagedConnection(), re);  
+         }
+      }
+   }
+   
+   
+   /**
+    * Gets connection handle instance.
+    * @param mcf managed connection factory
+    * @param cri connection request info
+    * @return ne wconnection
+    * @throws ResourceException for exception
+    */
+   public Object allocateConnection(ManagedConnectionFactory mcf, ConnectionRequestInfo cri) throws ResourceException
+   {
+      //Check for pooling!
+      if (this.poolingStrategy == null)
+      {
+         throw new ResourceException("You are trying to use a connection factory that has been shut down: " +
+               "ManagedConnectionFactory is null.");         
+      }
+
+      //it is an explicit spec requirement that equals be used for matching rather than ==.
+      if (!this.poolingStrategy.getManagedConnectionFactory().equals(mcf))
+      {
+         throw new ResourceException("Wrong ManagedConnectionFactory sent to allocateConnection!");  
+      }
+
+      // Pick a managed connection from the pool
+      Subject subject = getSubject();
+      ConnectionListener cl = getManagedConnection(subject, cri);
+
+      // Tell each connection manager the managed connection is active
+      reconnectManagedConnection(cl);
+
+      // Ask the managed connection for a connection
+      Object connection = null;
+      try
+      {
+         connection = cl.getManagedConnection().getConnection(subject, cri);
+      }
+      catch (Throwable t)
+      {
+         try 
+         {
+            managedConnectionDisconnected(cl);
+         }
+         catch (ResourceException re)
+         {
+            log.trace("Get exception from managedConnectionDisconnected, maybe delist() have problem" + re);            
+            returnManagedConnection(cl, true);
+         }
+         JBossResourceException.rethrowAsResourceException(
+               "Unchecked throwable in ManagedConnection.getConnection() cl=" + cl, t);
+      }
+
+      // Associate managed connection with the connection
+      registerAssociation(cl, connection);
+      
+      if (this.cachedConnectionManager != null)
+      {
+         this.cachedConnectionManager.registerConnection(this, cl, connection, cri);  
+      }
+      
+      return connection;
+   }
+   
+   
+   /**
     * {@inheritDoc}
     */
    public TransactionManager getTransactionManagerInstance()
    {
-      // TODO Auto-generated method stub
       return null;
    }
 
@@ -78,7 +496,6 @@
     */
    public boolean isTransactional()
    {
-      // TODO Auto-generated method stub
       return false;
    }
 
@@ -87,8 +504,7 @@
     */
    public long getTimeLeftBeforeTransactionTimeout(boolean arg0) throws RollbackException
    {
-      // TODO Auto-generated method stub
-      return 0;
+      return -1;
    }
 
    /**
@@ -96,8 +512,7 @@
     */
    public int getTransactionTimeout() throws SystemException
    {
-      // TODO Auto-generated method stub
-      return 0;
+      throw new NotImplementedException("NYI: getTransactionTimeout()");
    }
 
    /**
@@ -105,17 +520,40 @@
     */
    public void checkTransactionActive() throws RollbackException, SystemException
    {
-      // TODO Auto-generated method stub
-      
+      //Do Nothing as default
    }
 
    /**
     * {@inheritDoc}
     */
-   public void disconnect(Collection<ConnectionRecord> conns, Set<String> unsharableResources) throws ResourceException
+   public void disconnect(Collection<ConnectionRecord> conRecords, Set<String> unsharableResources) 
+      throws ResourceException
    {
-      // TODO Auto-generated method stub
-      
+      // if we have an unshareable connection do not remove the association
+      // nothing to do
+      if (unsharableResources.contains(this.jndiName))
+      {
+         log.trace("disconnect for unshareable connection: nothing to do");
+         
+         return;
+      }
+
+      Set<ConnectionListener> cls = new HashSet<ConnectionListener>();
+      for (Iterator<ConnectionRecord> i = conRecords.iterator(); i.hasNext();)
+      {
+         ConnectionRecord cr = i.next();
+         ConnectionListener cl = cr.getConnectionListener();
+         cr.setConnectionListener(null);
+         unregisterAssociation(cl, cr.getConnection());
+         if (!cls.contains(cl))
+         {
+            cls.add(cl);
+         }
+      }
+      for (Iterator<ConnectionListener> i = cls.iterator(); i.hasNext();)
+      {
+         disconnectManagedConnection((ConnectionListener) i.next());  
+      }      
    }
 
    /**
@@ -123,8 +561,42 @@
     */
    public void reconnect(Collection<ConnectionRecord> conns, Set<String> unsharableResources) throws ResourceException
    {
-      // TODO Auto-generated method stub
+      // if we have an unshareable connection the association was not removed
+      // nothing to do
+      if (unsharableResources.contains(jndiName))
+      {
+         log.trace("reconnect for unshareable connection: nothing to do");
+         return;
+      }
+
+      Map<ConnectionRequestInfo, ConnectionListener> criToCLMap = 
+            new HashMap<ConnectionRequestInfo, ConnectionListener>();
       
+      for (Iterator<ConnectionRecord> i = conns.iterator(); i.hasNext();)
+      {
+         ConnectionRecord cr = i.next();
+         if (cr.getConnectionListener() != null)
+         {
+            //This might well be an error.
+            log.warn("reconnecting a connection handle that still has a managedConnection! "
+                  + cr.getConnectionListener().getManagedConnection() + " " + cr.getConnection());
+         }
+         ConnectionListener cl = (ConnectionListener) criToCLMap.get(cr.getCri());
+         if (cl == null)
+         {
+            cl = getManagedConnection(getSubject(), cr.getCri());
+            criToCLMap.put(cr.getCri(), cl);
+            //only call once per managed connection, when we get it.
+            reconnectManagedConnection(cl);
+         }
+
+         cl.getManagedConnection().associateConnection(cr.getConnection());
+         registerAssociation(cl, cr.getConnection());
+         cr.setConnectionListener(cl);
+      }
+      
+      criToCLMap.clear();
+      
    }
 
    /**
@@ -132,8 +604,120 @@
     */
    public void transactionStarted(Collection<ConnectionRecord> conns) throws SystemException
    {
-      // TODO Auto-generated method stub
+      //reimplement in subclasses      
+   }
+   
+   
+   /**
+    * Unregister association.
+    * @param cl connection listener
+    * @param c connection
+    */
+   //does NOT put the mc back in the pool if no more handles. Doing so would introduce a race condition
+   //whereby the mc got back in the pool while still enlisted in the tx.
+   //The mc could be checked out again and used before the delist occured.
+   public void unregisterAssociation(ConnectionListener cl, Object c)
+   {
+      cl.unregisterConnection(c);
+   }
+   
+   /**
+    * Invoked to reassociate a managed connection.
+    * 
+    * @param cl the managed connection
+    * @throws ResourceException for exception
+    */
+   protected void reconnectManagedConnection(ConnectionListener cl) throws ResourceException
+   {
+      try
+      {
+         managedConnectionReconnected(cl);
+      }
+      catch (Throwable t)
+      {
+         disconnectManagedConnection(cl);
+         JBossResourceException.rethrowAsResourceException("Unchecked throwable in managedConnectionReconnected() cl="
+               + cl, t);
+      }
+   }
+
+   /**
+    * Invoked when a managed connection is no longer associated
+    * 
+    * @param cl the managed connection
+    */
+   protected void disconnectManagedConnection(ConnectionListener cl)
+   {
+      try
+      {
+         managedConnectionDisconnected(cl);
+      }
+      catch (Throwable t)
+      {
+         log.warn("Unchecked throwable in managedConnectionDisconnected() cl=" + cl, t);
+      }
+   }
+   
+   /**
+    * For polymorphism.
+    * <p>
+    * 
+    * Do not invoke directly, use reconnectManagedConnection
+    * which does the relevent exception handling
+    * @param cl connection listener
+    * @throws ResourceException for exception
+    */
+   protected void managedConnectionReconnected(ConnectionListener cl) throws ResourceException
+   {
+      //Nothing as default
+   }
+
+   /**
+    * For polymorphism.
+    * <p>
+    * 
+    * Do not invoke directly, use disconnectManagedConnection
+    * which does the relevent exception handling
+    * @param cl connection listener
+    * @throws ResourceException for exception
+    */
+   protected void managedConnectionDisconnected(ConnectionListener cl) throws ResourceException
+   {
+      //Nothing as default
+   }
+
+   /**
+    * Register connection with connection listener.
+    * @param cl connection listener
+    * @param c connection 
+    * @throws ResourceException exception
+    */
+   private void registerAssociation(ConnectionListener cl, Object c) throws ResourceException
+   {
+      cl.registerConnection(c);
+   }
+   
+   
+   /**
+    * Gets subject.
+    * @return subject
+    */
+   private Subject getSubject()
+   {
+      Subject subject = null;
       
+      if (subjectFactory != null && securityDomainJndiName != null)
+      {
+         subject = subjectFactory.createSubject(securityDomainJndiName);
+      } 
+      
+      if (trace)
+      {
+         log.trace("subject: " + subject);  
+      }
+      
+      return subject;
    }
 
+
 }


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/AbstractConnectionManager.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date

Added: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/CachedConnectionManager.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/CachedConnectionManager.java	                        (rev 0)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/CachedConnectionManager.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -0,0 +1,649 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, 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.jca.core.connectionmanager;
+
+import org.jboss.jca.core.connectionmanager.listener.ConnectionCacheListener;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.transaction.TransactionSynchronizer;
+import org.jboss.jca.spi.ComponentStack;
+
+import java.lang.reflect.Method;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.jboss.logging.Logger;
+
+import org.jboss.tm.TxUtils;
+import org.jboss.tm.usertx.UserTransactionListener;
+import org.jboss.tm.usertx.client.ServerVMClientUserTransaction.UserTransactionStartedListener;
+import org.jboss.util.Strings;
+
+/**
+ * CacheConnectionManager.
+ * @version $Rev$ $Date$
+ *
+ */
+public class CachedConnectionManager implements
+   UserTransactionStartedListener,
+   UserTransactionListener,
+   ComponentStack
+{
+   /**Log instance*/
+   private static Logger log = Logger.getLogger(CachedConnectionManager.class);
+   
+   /**Log trace*/
+   private boolean trace;
+   
+   /**Debug flag*/
+   private boolean debug;
+   
+   /**Error flag*/
+   private boolean error;
+   
+   /**Transaction Manager instance*/
+   private TransactionManager transactionManager;
+   
+   /**
+    * ThreadLocal that holds current calling meta-programming aware
+    * object, used in case someone is idiotic enough to cache a
+    * connection between invocations.and want the spec required
+    * behavior of it getting hooked up to an appropriate
+    * ManagedConnection on each method invocation.
+    */
+   private final ThreadLocal<LinkedList<Object>> currentObjects = new ThreadLocal<LinkedList<Object>>();
+
+   /**
+    * The variable <code>objectToConnectionManagerMap</code> holds the
+    * map of meta-aware object to set of connections it holds, used by
+    * the idiot spec compliant behavior.
+    */
+   private final Map<KeyConnectionAssociation, Map<ConnectionCacheListener, Collection<ConnectionRecord>>> 
+   objectToConnectionManagerMap = new HashMap<KeyConnectionAssociation, 
+                                              Map<ConnectionCacheListener, Collection<ConnectionRecord>>>();
+
+   /**
+    * Connection stacktraces
+    */
+   private Map<Object, Throwable> connectionStackTraces = new WeakHashMap<Object, Throwable>();
+
+   /**
+    * Creates a new instance.
+    */
+   public CachedConnectionManager()
+   {
+      this.trace = log.isTraceEnabled();
+   }
+   
+   /**
+    * Gets transaction manager.
+    * @return transaction manager
+    */
+   public TransactionManager getTransactionManager()
+   {
+      return this.transactionManager;
+   }
+
+   /**
+    * Sets transaction manager.
+    * @param transactionManager transaction manager
+    */
+   public void setTransactionManager(TransactionManager transactionManager)
+   {
+      this.transactionManager = transactionManager;
+      
+      // FIXME we should be injecting onto the synchronizer directly
+      if (this.transactionManager != null)
+      {
+         TransactionSynchronizer.setTransactionManager(transactionManager);
+      }
+         
+   }
+   
+   
+   /**
+    * {@inheritDoc}
+    */
+   public void userTransactionStarted() throws SystemException
+   {
+      KeyConnectionAssociation key = peekMetaAwareObject();
+      if (trace)
+      {
+         log.trace("user tx started, key: " + key);  
+      }
+      if (key == null)
+      {
+         return; //not participating properly in this management scheme.  
+      }
+
+      Map<ConnectionCacheListener, Collection<ConnectionRecord>> cmToConnectionsMap = key.getCMToConnectionsMap();
+      Iterator<Entry<ConnectionCacheListener, Collection<ConnectionRecord>>> cmToConnectionsMapIterator = 
+         cmToConnectionsMap.entrySet().iterator();
+      
+      while (cmToConnectionsMapIterator.hasNext())
+      {
+         Entry<ConnectionCacheListener, Collection<ConnectionRecord>> entry = cmToConnectionsMapIterator.next();
+         ConnectionCacheListener cm = (ConnectionCacheListener) entry.getKey();
+         Collection<ConnectionRecord> conns =  entry.getValue();
+         
+         cm.transactionStarted(conns);
+      }
+   }
+   
+   /**
+    * 
+    * @return stack last meta-aware object
+    */
+   KeyConnectionAssociation peekMetaAwareObject()
+   {
+      LinkedList<Object> stack = currentObjects.get();
+      if (stack == null)
+      {
+         return null;  
+      }
+      
+      if (!stack.isEmpty())
+      {
+         return (KeyConnectionAssociation) stack.getLast();  
+      }
+      
+      else
+      {
+         return null;  
+      }
+   }
+   
+   
+   /**
+    * {@inheritDoc}
+    */
+   @SuppressWarnings("unchecked")
+   public void popMetaAwareObject(Set unsharableResources) throws ResourceException
+   {
+      LinkedList<Object> stack = this.currentObjects.get();
+      KeyConnectionAssociation oldKey = (KeyConnectionAssociation) stack.removeLast();
+      if (this.trace)
+      {
+         log.trace("popped object: " + Strings.defaultToString(oldKey));  
+      }
+
+      if (!stack.contains(oldKey))
+      {
+         disconnect(oldKey, unsharableResources);
+      } // end of if ()
+       
+      if (this.debug)
+      {
+         if (closeAll(oldKey.getCMToConnectionsMap()) && this.error)
+         {
+            throw new ResourceException("Some connections were not closed, " +
+                  "see the log for the allocation stacktraces");  
+         }
+      }
+      
+   }
+
+   /**
+    * Register connection.
+    * @param cm connection manager
+    * @param cl connection listener
+    * @param connection connection handle
+    * @param cri connection request info.
+    */
+   public void registerConnection(ConnectionCacheListener cm, ConnectionListener cl, 
+         Object connection, ConnectionRequestInfo cri)
+   {
+      if (this.debug)
+      {
+         synchronized (this.connectionStackTraces)
+         {
+            this.connectionStackTraces.put(connection, new Throwable("STACKTRACE"));
+         }
+      }
+
+      KeyConnectionAssociation key = peekMetaAwareObject();
+      
+      if (this.trace)
+      {
+         log.trace("registering connection from connection manager " + cm +
+               ", connection : " + connection + ", key: " + key);  
+      }
+      
+      if (key == null)
+      {
+         return; //not participating properly in this management scheme.  
+      }
+
+      ConnectionRecord cr = new ConnectionRecord(cl, connection, cri);
+      Map<ConnectionCacheListener, Collection<ConnectionRecord>> cmToConnectionsMap = key.getCMToConnectionsMap();
+      Collection<ConnectionRecord> conns = cmToConnectionsMap.get(cm);
+      if (conns == null)
+      {
+         conns = new ArrayList<ConnectionRecord>();
+         cmToConnectionsMap.put(cm, conns);
+      }
+      
+      conns.add(cr);
+   }
+
+   /**
+    * Unregister connection.
+    * @param cm connection manager
+    * @param connection connection handle
+    */
+   public void unregisterConnection(ConnectionCacheListener cm, Object connection)
+   {
+      if (this.debug)
+      {
+         CloseConnectionSynchronization cas = getCloseConnectionSynchronization(false);
+         if (cas != null)
+         {
+            cas.remove(connection);  
+         }
+         
+         synchronized (this.connectionStackTraces)
+         {
+            this.connectionStackTraces.remove(connection);
+         }
+      }
+
+      KeyConnectionAssociation key = peekMetaAwareObject();
+      
+      if (this.trace)
+      {
+         log.trace("unregistering connection from connection manager " + cm +
+               ", object: " + connection + ", key: " + key);  
+      }
+      
+      if (key == null)
+      {
+         return; //not participating properly in this management scheme.  
+      }
+
+      Map<ConnectionCacheListener, Collection<ConnectionRecord>> cmToConnectionsMap = key.getCMToConnectionsMap();
+      Collection<ConnectionRecord> conns = cmToConnectionsMap.get(cm);
+      if (conns == null)
+      {
+         return; // Can happen if connections are "passed" between contexts  
+      }
+      
+      for (Iterator<ConnectionRecord> i = conns.iterator(); i.hasNext();)
+      {
+         if ((i.next()).getConnection() == connection)
+         {
+            i.remove();
+            return;
+         }
+      }
+      
+      throw new IllegalStateException("Trying to return an unknown connection2! " + connection);
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   @SuppressWarnings("unchecked")
+   public void pushMetaAwareObject(final Object rawKey, Set unsharableResources) throws ResourceException
+   {
+      LinkedList<Object> stack = this.currentObjects.get();
+      if (stack == null)
+      {
+         if (this.trace)
+         {
+            log.trace("new stack for key: " + Strings.defaultToString(rawKey));  
+         }
+         
+         stack = new LinkedList<Object>();         
+         currentObjects.set(stack);         
+      }
+      else
+      {
+         if (trace)
+         {
+            log.trace("old stack for key: " + Strings.defaultToString(rawKey));  
+         }
+      }
+      
+      KeyConnectionAssociation key = new KeyConnectionAssociation(rawKey);
+      if (!stack.contains(key))
+      {
+         reconnect(key, unsharableResources);
+      }
+      
+      stack.addLast(key);      
+   }
+   
+   /**
+    * The <code>reconnect</code> method gets the cmToConnectionsMap
+    * from objectToConnectionManagerMap, copies it to the key, and
+    * reconnects all the connections in it.
+    *
+    * @param key a <code>KeyConnectionAssociation</code> value
+    * @param unsharableResources a <code>Set</code> value
+    * @exception ResourceException if an error occurs
+    */
+   @SuppressWarnings("unchecked")
+   private void reconnect(KeyConnectionAssociation key, Set unsharableResources) throws ResourceException
+   {
+      Map<ConnectionCacheListener, Collection<ConnectionRecord>> cmToConnectionsMap = null;
+      synchronized (this.objectToConnectionManagerMap)
+      {
+         cmToConnectionsMap = this.objectToConnectionManagerMap.get(key);
+         if (cmToConnectionsMap == null)
+         {
+            return;  
+         }
+      }
+      key.setCMToConnectionsMap(cmToConnectionsMap);
+      Iterator<Entry<ConnectionCacheListener, Collection<ConnectionRecord>>> cmToConnectionsMapIterator = 
+         cmToConnectionsMap.entrySet().iterator();
+      
+      while (cmToConnectionsMapIterator.hasNext())
+      {
+         Entry<ConnectionCacheListener, Collection<ConnectionRecord>> entry = cmToConnectionsMapIterator.next();
+         ConnectionCacheListener cm = (ConnectionCacheListener) entry.getKey();
+         Collection<ConnectionRecord> conns =  entry.getValue();
+         
+         cm.reconnect(conns, unsharableResources);
+      }
+   }
+   
+   /**
+    * Disconnect connections.
+    * @param key key
+    * @param unsharableResources resource
+    * @throws ResourceException exception
+    */
+   @SuppressWarnings("unchecked")
+   private void disconnect(KeyConnectionAssociation key, Set unsharableResources) throws ResourceException
+   {
+      Map<ConnectionCacheListener, Collection<ConnectionRecord>> cmToConnectionsMap = null;
+      cmToConnectionsMap = key.getCMToConnectionsMap();
+      if (!cmToConnectionsMap.isEmpty())
+      {
+         synchronized (objectToConnectionManagerMap)
+         {
+            objectToConnectionManagerMap.put(key, cmToConnectionsMap);
+         }
+         Iterator<Entry<ConnectionCacheListener, Collection<ConnectionRecord>>> cmToConnectionsMapIterator = 
+            cmToConnectionsMap.entrySet().iterator();
+         
+         while (cmToConnectionsMapIterator.hasNext())
+         {
+            Entry<ConnectionCacheListener, Collection<ConnectionRecord>> entry = cmToConnectionsMapIterator.next();
+            ConnectionCacheListener cm = (ConnectionCacheListener) entry.getKey();
+            Collection<ConnectionRecord> conns =  entry.getValue();
+            
+            cm.disconnect(conns, unsharableResources);
+         }
+      }
+   }
+   
+   /**
+    * Describe <code>unregisterConnectionCacheListener</code> method here.
+    * This is a shutdown method called by a connection manager.  It will remove all reference
+    * to that connection manager from the cache, so cached connections from that manager
+    * will never be recoverable.
+    * Possibly this method should not exist.
+    * 
+    * @param cm a <code>ConnectionCacheListener</code> value
+    */   
+   public void unregisterConnectionCacheListener(ConnectionCacheListener cm)
+   {
+      if (trace)
+      {
+         log.trace("unregisterConnectionCacheListener: " + cm);  
+      }
+      
+      synchronized (objectToConnectionManagerMap)
+      {
+         Iterator<Map<ConnectionCacheListener, Collection<ConnectionRecord>>> it = 
+               this.objectToConnectionManagerMap.values().iterator();
+         
+         while (it.hasNext())
+         {
+            Map<ConnectionCacheListener, Collection<ConnectionRecord>> cmToConnectionsMap = it.next();
+            if (cmToConnectionsMap != null)
+            {
+               cmToConnectionsMap.remove(cm);  
+            }
+         }
+      }
+   }
+   
+   
+   /**
+    * Close all connections.
+    * @param cmToConnectionsMap connection manager to connections
+    * @return true if close
+    */
+   private boolean closeAll(Map<ConnectionCacheListener, Collection<ConnectionRecord>> cmToConnectionsMap)
+   {
+      if (!debug)
+      {
+         return false;  
+      }
+
+      boolean unclosed = false;
+
+      Collection<Collection<ConnectionRecord>> connections = cmToConnectionsMap.values();
+      if (connections.size() != 0)
+      {
+         for (Iterator<Collection<ConnectionRecord>> i = connections.iterator(); i.hasNext();)
+         {
+            Collection<ConnectionRecord> conns = i.next();
+            for (Iterator<ConnectionRecord> j = conns.iterator(); j.hasNext();)
+            {
+               Object c = (j.next()).getConnection();
+               CloseConnectionSynchronization cas = getCloseConnectionSynchronization(true);
+               if (cas == null)
+               {
+                  unclosed = true;
+                  closeConnection(c);
+               }
+               else
+               {
+                  cas.add(c);  
+               }
+            }
+         }
+      }
+      
+      return unclosed;
+   }
+   
+   /**
+    * Gets close sync. instance.
+    * @param createIfNotFound create if not found
+    * @return sync. instance
+    */
+   private CloseConnectionSynchronization getCloseConnectionSynchronization(boolean createIfNotFound)
+   {
+      try
+      {
+         Transaction tx = null;
+         if (this.transactionManager != null)
+         {
+            tx = this.transactionManager.getTransaction();  
+         }
+        
+         if (tx != null)
+         {
+            TransactionSynchronizer.lock(tx);
+            try
+            {
+               CloseConnectionSynchronization cas = (CloseConnectionSynchronization) 
+                                                   TransactionSynchronizer.getCCMSynchronization(tx);
+               
+               if (cas == null && createIfNotFound && TxUtils.isActive(tx))
+               {
+                  cas = new CloseConnectionSynchronization();
+                  TransactionSynchronizer.registerCCMSynchronization(tx, cas);
+               }
+               
+               return cas;
+            }
+            finally
+            {
+               TransactionSynchronizer.unlock(tx);
+            }
+         }
+      }
+      catch (Throwable t)
+      {
+         log.debug("Unable to synchronize with transaction", t);
+      }
+      
+      return null;
+   }
+   
+   
+   /**
+    * Close connection handle.
+    * @param connectionHandle connection handle
+    */
+   private void closeConnection(Object connectionHandle)
+   {
+      try
+      {
+         Throwable exception;
+         
+         synchronized (connectionStackTraces)
+         {
+            exception = (Throwable) connectionStackTraces.remove(connectionHandle);
+         }
+         
+         Method m = connectionHandle.getClass().getMethod("close", new Class[]{});
+         
+         try
+         {
+            if (exception != null)
+            {
+               log.info("Closing a connection for you.  Please close them yourself: " + connectionHandle, exception);  
+            }
+            else
+            {
+               log.info("Closing a connection for you.  Please close them yourself: " + connectionHandle);  
+            }
+            
+            m.invoke(connectionHandle, new Object[]{});
+         }
+         catch (Throwable t)
+         {
+            log.info("Throwable trying to close a connection for you, please close it yourself", t);
+         }
+      }
+      catch (NoSuchMethodException nsme)
+      {
+         log.info("Could not find a close method on alleged connection objects.  Please close your own connections.");
+      }
+   }
+   
+   
+   /**
+    * Close synch. class. 
+    */
+   private class CloseConnectionSynchronization implements Synchronization
+   {
+      /**Connection handles*/
+      CopyOnWriteArraySet<Object> connections = new CopyOnWriteArraySet<Object>();
+      
+      /**Closing flag*/
+      AtomicBoolean closing = new AtomicBoolean(false);
+
+      /**
+       * Creates a new instance.
+       */
+      public CloseConnectionSynchronization()
+      {
+         
+      }
+
+      /**
+       * Add new connection handle.
+       * @param c connection handle
+       */
+      public  void add(Object c)
+      {
+         if (closing.get())
+         {
+            return;  
+         }
+         connections.add(c);
+      }
+
+      /**
+       * Removes connection handle.
+       * @param c connection handle
+       */
+      public  void remove(Object c)
+      {
+         if (closing.get())
+         {
+            return;  
+         }
+         
+         connections.remove(c);
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public void beforeCompletion()
+      {
+         //No-action
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public void afterCompletion(int status)
+      {
+         this.closing.set(true);
+         
+         for (Iterator<Object> i = connections.iterator(); i.hasNext();)
+         {
+            closeConnection(i.next());  
+         }
+        
+         connections.clear();
+      }
+   }
+   
+}


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/CachedConnectionManager.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Modified: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionCounter.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionCounter.java	2009-09-08 19:22:26 UTC (rev 93295)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionCounter.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -124,7 +124,7 @@
     * Gets timed out connections.
     * @return timeout
     */
-   public int getTimedOut()
+   public int getTimedOutCount()
    {
       return timedOut;
    }
@@ -132,7 +132,7 @@
    /**
     * Increment timeout connection.
     */
-   public void incTimedOut()
+   public void incTimedOutCount()
    {
       ++timedOut;
    }

Modified: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionManagerImpl.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionManagerImpl.java	2009-09-08 19:22:26 UTC (rev 93295)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionManagerImpl.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -35,16 +35,20 @@
  */
 public class ConnectionManagerImpl implements ConnectionManager
 {
-   /** Serial version UID */
-   static final long serialVersionUID = 0L;
-
+   /**Serial version UID*/
+   private static final long serialVersionUID = 2843159124540746692L;
+ 
+   /**Real connection manager*/
+   private transient AbstractConnectionManager realConnectionManager;
+   
    /**
-    * Default constructor
+    * Creates a new instance of connection manager.
     */
    public ConnectionManagerImpl()
    {
+      
    }
-
+   
    /**
     * Allocate a connection
     * @param mcf The managed connection factory
@@ -56,7 +60,7 @@
                                     ConnectionRequestInfo cxRequestInfo)
       throws ResourceException
    {
-      throw new ResourceException("NYI");
+      return this.realConnectionManager.allocateConnection(mcf, cxRequestInfo);
    }
 
    /**
@@ -64,8 +68,7 @@
     */
    public void checkTransactionActive() throws RollbackException, SystemException
    {
-      // TODO Auto-generated method stub
-      
+      this.realConnectionManager.checkTransactionActive();
    }
 
    /**
@@ -73,8 +76,7 @@
     */
    public long getTimeLeftBeforeTransactionTimeout(boolean errorRollback) throws RollbackException
    {
-      // TODO Auto-generated method stub
-      return 0;
+      return this.realConnectionManager.getTimeLeftBeforeTransactionTimeout(errorRollback);
    }
 
    /**
@@ -82,7 +84,22 @@
     */
    public int getTransactionTimeout() throws SystemException
    {
-      // TODO Auto-generated method stub
-      return 0;
+      return this.realConnectionManager.getTransactionTimeout();
    }
+
+   /**
+    * {@inheritDoc}
+    */
+   public AbstractConnectionManager getRealConnectionManager()
+   {
+      return this.realConnectionManager;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void setRealConnectionManager(AbstractConnectionManager realConnectionManager)
+   {
+      this.realConnectionManager = realConnectionManager;
+   }
 }

Modified: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionRecord.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionRecord.java	2009-09-08 19:22:26 UTC (rev 93295)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/ConnectionRecord.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -26,7 +26,7 @@
 import javax.resource.spi.ConnectionRequestInfo;
 
 /**
- * Information about a connection
+ * Information about a connection.
  *
  * @author <a href="mailto:d_jencks at users.sourceforge.net">David Jencks</a>
  * @author <a href="mailto:adrian at jboss.org">Adrian Brock</a>
@@ -35,7 +35,7 @@
  */
 public class ConnectionRecord 
 {
-   private ConnectionListener cl;
+   private ConnectionListener connectionListener;
    private final Object connection;
    private final ConnectionRequestInfo cri;
    
@@ -49,7 +49,7 @@
                             final Object connection, 
                             final ConnectionRequestInfo cri)
    {
-      this.cl = cl;
+      this.connectionListener = cl;
       this.connection = connection;
       this.cri = cri;
    }
@@ -57,23 +57,23 @@
    /**
     * @return the cl
     */
-   ConnectionListener getCl()
+   public ConnectionListener getConnectionListener()
    {
-      return cl;
+      return connectionListener;
    }
 
    /**
     * @param cl the cl to set
     */
-   void setCl(ConnectionListener cl)
+   void setConnectionListener(ConnectionListener cl)
    {
-      this.cl = cl;
+      this.connectionListener = cl;
    }
 
    /**
     * @return the connection
     */
-   Object getConnection()
+   public Object getConnection()
    {
       return connection;
    }
@@ -81,7 +81,7 @@
    /**
     * @return the cri
     */
-   ConnectionRequestInfo getCri()
+   public ConnectionRequestInfo getCri()
    {
       return cri;
    }

Added: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/KeyConnectionAssociation.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/KeyConnectionAssociation.java	                        (rev 0)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/KeyConnectionAssociation.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -0,0 +1,104 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, 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.jca.core.connectionmanager;
+
+import org.jboss.jca.core.connectionmanager.listener.ConnectionCacheListener;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.util.Strings;
+
+
+/**
+ * The class <code>KeyConnectionAssociation</code> wraps objects so they may be used in hashmaps
+ * based on their object identity rather than equals implementation. Used for keys.
+ * 
+ * @author gurkanerdogdu
+ * @version $Rev$ $Date$
+ */
+final class KeyConnectionAssociation
+{
+   //key
+   private final Object metaAwareObject;
+
+   //map of cm to list of connections for that cm.
+   private Map<ConnectionCacheListener, Collection<ConnectionRecord>> cmToConnectionsMap;
+
+   /**
+    * Creates a new instance.
+    * @param metaAwareObject meta aware object
+    */
+   KeyConnectionAssociation(final Object metaAwareObject)
+   {
+      this.metaAwareObject = metaAwareObject;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean equals(Object other)
+   {
+      return (other instanceof KeyConnectionAssociation) && 
+            this.metaAwareObject == ((KeyConnectionAssociation) other).metaAwareObject;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String toString()
+   {
+      return Strings.defaultToString(this.metaAwareObject);
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public int hashCode()
+   {
+      return System.identityHashCode(this.metaAwareObject);
+   }
+
+   /**
+    * Set map instance.
+    * @param cmToConnectionsMap connection manager to connections
+    */
+   public void setCMToConnectionsMap(Map<ConnectionCacheListener, Collection<ConnectionRecord>> cmToConnectionsMap)
+   {
+      this.cmToConnectionsMap = cmToConnectionsMap;
+   }
+
+   /**
+    * 
+    * @return map instance
+    */
+   public Map<ConnectionCacheListener, Collection<ConnectionRecord>> getCMToConnectionsMap()
+   {
+      if (cmToConnectionsMap == null)
+      {
+         cmToConnectionsMap = new HashMap<ConnectionCacheListener, Collection<ConnectionRecord>>();
+      }
+      
+      return cmToConnectionsMap;
+   }
+}


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/KeyConnectionAssociation.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Added: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/exception/JBossLocalXAException.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/exception/JBossLocalXAException.java	                        (rev 0)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/exception/JBossLocalXAException.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -0,0 +1,173 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.jca.core.connectionmanager.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import javax.transaction.xa.XAException;
+
+import org.jboss.util.NestedThrowable;
+
+/**
+ * JBossLocalXAException
+ *
+ * @author <a href="mailto:d_jencks at users.sourceforge.net">David Jencks</a>
+ * @author <a href="mailto:adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision$
+ */
+public class JBossLocalXAException extends XAException implements NestedThrowable
+{
+   /**Serial version UID*/
+   private static final long serialVersionUID = -6208145503935506281L;
+   
+   /**Cause*/
+   private final Throwable t;
+
+   /**
+    * Creates a new instance.
+    */
+   public JBossLocalXAException()
+   {
+      super();
+      t = null;
+   }
+
+   /**
+    * Creates a new instance.
+    * @param errcode error code
+    */   
+   public JBossLocalXAException(int errcode)
+   {
+      super(errcode);
+      t = null;
+   }
+
+   /**
+    * Creates a new instance.
+    * @param message message
+    */   
+   public JBossLocalXAException(String message)
+   {
+      super(message);
+      t = null;
+   }
+
+   /**
+    * Creates a new instance.
+    * @param message message
+    * @param errorcode error code
+    */   
+   public JBossLocalXAException(String message, int errorcode)
+   {
+      super(message);
+      this.errorCode = errorcode;
+      t = null;
+   }
+
+   /**
+    * Creates a new instance.
+    * @param message message
+    * @param t cause
+    */
+   public JBossLocalXAException(String message, Throwable t)
+   {
+      super(message);
+      this.t = t;
+   }
+
+   /**
+    * Creates a new instance.
+    * @param message message
+    * @param t cause
+    * @param errorcode error code
+    */   
+   public JBossLocalXAException(String message, int errorcode, Throwable t)
+   {
+      super(message);
+      this.errorCode = errorcode;
+      this.t = t;
+   }
+
+   // Implementation of org.jboss.util.NestedThrowable
+
+   /**
+    * {@inheritDoc}
+    */
+   public Throwable getNested()
+   {
+      return t;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Throwable getCause()
+   {
+      return t;
+   }
+
+   /**
+    * Returns the composite throwable message.
+    *
+    * @return  The composite throwable message.
+    */
+   public String getMessage()
+   {
+      return NestedThrowable.Util.getMessage(super.getMessage(), t);
+   }
+
+   /**
+    * Prints the composite message and the embedded stack trace to the
+    * specified print stream.
+    *
+    * @param stream  Stream to print to.
+    */
+   public void printStackTrace(final PrintStream stream)
+   {
+      if (t == null || NestedThrowable.PARENT_TRACE_ENABLED)
+         super.printStackTrace(stream);
+      NestedThrowable.Util.print(t, stream);
+   }
+
+   /**
+    * Prints the composite message and the embedded stack trace to the
+    * specified print writer.
+    *
+    * @param writer  Writer to print to.
+    */
+   public void printStackTrace(final PrintWriter writer)
+   {
+      if (t == null || NestedThrowable.PARENT_TRACE_ENABLED)
+         super.printStackTrace(writer);
+      NestedThrowable.Util.print(t, writer);
+   }
+
+   /**
+    * Prints the composite message and the embedded stack trace to
+    * <tt>System.err</tt>.
+    */
+   public void printStackTrace()
+   {
+      printStackTrace(System.err);
+   }
+}


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/exception/JBossLocalXAException.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Added: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/exception/JBossLocalXAExceptionFormatter.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/exception/JBossLocalXAExceptionFormatter.java	                        (rev 0)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/exception/JBossLocalXAExceptionFormatter.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.jca.core.connectionmanager.exception;
+
+import javax.transaction.xa.XAException;
+
+import org.jboss.logging.Logger;
+import org.jboss.tm.XAExceptionFormatter;
+
+/**
+ * JBossLocalXAExceptionFormatter.java
+ *
+ * @author <a href="mailto:igorfie at yahoo dot com">Igor Fedorenko</a>.
+ * @author <a href="mailto:d_jencks at users.sourceforge.net">David Jencks</a>
+ * @author <a href="mailto:adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision$
+ */
+
+public class JBossLocalXAExceptionFormatter implements XAExceptionFormatter
+{
+
+   /**
+    * Creates a new formatter.
+    */
+   public JBossLocalXAExceptionFormatter()
+   {
+      
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public void formatXAException(XAException xae, Logger log)
+   {
+      try
+      {
+         log.warn("JBoss Local XA wrapper error: ", ((JBossLocalXAException) xae).getCause());
+      }
+      catch (Exception e)
+      {
+         log.warn("Problem trying to format XAException: ", e);
+      }
+   }
+}


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/exception/JBossLocalXAExceptionFormatter.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Added: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/AbstractConnectionListener.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/AbstractConnectionListener.java	                        (rev 0)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/AbstractConnectionListener.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -0,0 +1,431 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, 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.jca.core.connectionmanager.listener;
+
+import org.jboss.jca.core.connectionmanager.AbstractConnectionManager;
+import org.jboss.jca.core.connectionmanager.CachedConnectionManager;
+import org.jboss.jca.core.connectionmanager.pool.api.ManagedConnectionPool;
+
+import java.util.Iterator;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionEvent;
+import javax.resource.spi.ManagedConnection;
+import javax.transaction.SystemException;
+
+import org.jboss.logging.Logger;
+
+/**
+ * Abstract implementation of the {@link ConnectionListener} interface
+ * contract.
+ * 
+ * @author gurkanerdogdu
+ * @version $Rev$ $Date$
+ *
+ */
+public abstract class AbstractConnectionListener implements ConnectionListener
+{
+   private Logger log = Logger.getLogger(getClass());
+   
+   /**Wraps managed connection instance*/
+   private final ManagedConnection managedConnection;
+   
+   /**Managed connection pool for this connection*/
+   private final ManagedConnectionPool managedConnectionPool;
+   
+   /**Pool internal context*/
+   private final Object internalManagedPoolContext;
+   
+   /**Connection State*/
+   private ConnectionState state = ConnectionState.NORMAL;
+   
+   /**Connection handles*/
+   private final CopyOnWriteArrayList<Object> connectionHandles = new CopyOnWriteArrayList<Object>();
+      
+   /**Track by transaction or not*/
+   private AtomicBoolean trackByTx = new AtomicBoolean(false);
+   
+   /**Connection permit*/
+   private boolean permit;
+   
+   /**Connection last use*/
+   private long lastUse;
+   
+   /**Connection last validated time*/
+   private long lastValidated;
+   
+   /**Log trace*/
+   protected boolean trace;
+   
+   /**Connection Manager*/
+   private AbstractConnectionManager cm;
+      
+   /**
+    * Creates a new instance of the listener that is responsible for
+    * tracking the owned connection instance.
+    * @param managedConnection managed connection
+    * @param managedConnectionPool managed connection pool
+    * @param context pool internal context
+    * @param cm connection manager
+    */
+   protected AbstractConnectionListener(AbstractConnectionManager cm, ManagedConnection managedConnection, 
+         ManagedConnectionPool managedConnectionPool, Object context)
+   {
+      this.cm = cm;
+      this.managedConnection = managedConnection;
+      this.managedConnectionPool = managedConnectionPool;
+      this.internalManagedPoolContext = context;
+      trace = this.log.isTraceEnabled();
+      lastUse = System.currentTimeMillis();
+   }
+   
+   /**
+    * Gets cached connection manager
+    * @return cached connection manager
+    */
+   protected CachedConnectionManager getCachedConnectionManager()
+   {
+      return this.cm.getCachedConnectionManager();
+   }
+   
+   /**
+    * Gets connection manager.
+    * @return connection manager
+    */
+   protected AbstractConnectionManager getConnectionManager()
+   {
+      return this.cm;
+   }
+   
+   /**
+    * Gets logger.
+    * @return logger instance
+    */
+   protected Logger getLog()
+   {
+      return this.log;
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public void delist() throws ResourceException
+   {
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void enlist() throws SystemException
+   {
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public Object getContext()
+   {
+      return this.internalManagedPoolContext;
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public long getLastValidatedTime()
+   {      
+      return this.lastValidated;
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public ManagedConnection getManagedConnection()
+   {      
+      return this.managedConnection;
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public ManagedConnectionPool getManagedConnectionPool()
+   {      
+      return this.managedConnectionPool;
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public ConnectionState getState()
+   {      
+      return this.state;
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void grantPermit(boolean value)
+   {      
+      this.permit = value;
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public boolean hasPermit()
+   {      
+      return this.permit;
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public boolean isManagedConnectionFree()
+   {      
+      return this.connectionHandles.isEmpty();
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public boolean isTimedOut(long timeout)
+   {      
+      return lastUse < timeout;
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public boolean isTrackByTx()
+   {      
+      return this.trackByTx.get();
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void registerConnection(Object handle)
+   {
+      this.connectionHandles.add(handle);      
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void setLastValidatedTime(long lastValidated)
+   {
+      this.lastValidated = lastValidated;      
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void setState(ConnectionState newState)
+   {
+      this.state = newState;      
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void setTrackByTx(boolean trackByTx)
+   {      
+      this.trackByTx.set(trackByTx);
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void tidyup() throws ResourceException
+   {
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void unregisterConnection(Object handle)
+   {
+      if (!this.connectionHandles.remove(handle))
+      {
+         log.info("Unregistered handle that was not registered! " + handle + " for managedConnection: " + 
+               this.managedConnection);
+      }
+      
+      if (trace)
+      {
+         log.trace("unregisterConnection: " + this.connectionHandles.size() + " handles left");  
+      }            
+   }
+   
+   /**
+    * Unregister connections.
+    */
+   protected  void unregisterConnections()
+   {
+      try
+      {
+         Iterator<Object> itHandles = this.connectionHandles.iterator();
+         
+         while (itHandles.hasNext())
+         {
+            Object handle = itHandles.next();
+            this.log.info("Unregister connection handle : " + handle + " from Cached connection manager");
+            //getCcm().unregisterConnection(BaseConnectionManager2.this, i.next());
+         }
+      }
+      finally
+      {
+         this.connectionHandles.clear();
+      }
+   }
+   
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void used()
+   {
+      this.lastUse = System.currentTimeMillis();      
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void connectionClosed(ConnectionEvent event)
+   {
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void connectionErrorOccurred(ConnectionEvent event)
+   {
+      if (state == ConnectionState.NORMAL)
+      {
+         if (event != null)
+         {
+            Throwable cause = event.getException();
+            if (cause == null)
+            {
+               cause = new Exception("No exception was reported");  
+            }
+            
+            log.warn("Connection error occured: " + this, cause);
+         }
+         else
+         {
+            Throwable cause = new Exception("No exception was reported");
+            log.warn("Unknown Connection error occured: " + this, cause);
+         }
+      }
+      
+      try
+      {
+         unregisterConnections();
+      }
+      catch (Throwable t)
+      {
+         //ignore, it wasn't checked out.
+      }
+      
+      if (event != null && event.getSource() != getManagedConnection())
+      {
+         log.warn("Notified of error on a different managed connection?");  
+      }
+      
+      getConnectionManager().returnManagedConnection(this, true);      
+      
+   }
+   
+   
+   /**
+    * {@inheritDoc}
+    */   
+   public void localTransactionCommitted(ConnectionEvent event)
+   {
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void localTransactionRolledback(ConnectionEvent event)
+   {
+   }
+
+   /**
+    * {@inheritDoc}
+    */   
+   public void localTransactionStarted(ConnectionEvent event)
+   {
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   // For debugging
+   public String toString()
+   {
+      StringBuffer buffer = new StringBuffer(100);
+      buffer.append(getClass().getName()).append('@').append(Integer.toHexString(System.identityHashCode(this)));
+      buffer.append("[state=");
+      
+      if (state.equals(ConnectionState.NORMAL))
+      {
+         buffer.append("NORMAL");  
+      }
+      else if (state.equals(ConnectionState.DESTROY))
+      {
+         buffer.append("DESTROY");  
+      }
+      else if (state.equals(ConnectionState.DESTROYED))
+      {
+         buffer.append("DESTROYED");  
+      }
+      else
+      {
+         buffer.append("UNKNOWN?");  
+      }
+      buffer.append(" managed connection=").append(this.managedConnection);
+      buffer.append(" connection handles=").append(this.connectionHandles.size());
+      buffer.append(" lastUse=").append(lastUse);
+      buffer.append(" permit=").append(permit);
+      buffer.append(" trackByTx=").append(trackByTx.get());
+      buffer.append(" managed connection pool=").append(this.managedConnectionPool);
+      buffer.append(" pool internal context=").append(this.internalManagedPoolContext);
+      toString(buffer);
+      buffer.append(']');
+      
+      return buffer.toString();
+   }
+   
+   /**
+    * Add specific properties.
+    * @param buffer buffer instance
+    */
+   // For debugging
+   protected void toString(StringBuffer buffer)
+   {
+      
+   }
+      
+}


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/AbstractConnectionListener.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/ConnectionListener.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/ConnectionListener.java	2009-09-08 19:22:26 UTC (rev 93295)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/ConnectionListener.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -169,9 +169,9 @@
    /**
     * Set the last time, in milliseconds, that this connection was validated.
     * 
-    * @param interval the last time the connection was validated in
+    * @param lastValidated the last time the connection was validated in
     *           milliseconds.
     */
-   void setLastValidatedTime(long interval);
+   void setLastValidatedTime(long lastValidated);
 
 }

Added: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/NoTxConnectionListener.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/NoTxConnectionListener.java	                        (rev 0)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/NoTxConnectionListener.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -0,0 +1,75 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, 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.jca.core.connectionmanager.listener;
+
+import org.jboss.jca.core.connectionmanager.AbstractConnectionManager;
+import org.jboss.jca.core.connectionmanager.pool.api.ManagedConnectionPool;
+
+import javax.resource.spi.ConnectionEvent;
+import javax.resource.spi.ManagedConnection;
+
+
+/**
+ * NoTx Connection Listener.
+ * 
+ * @author <a href="mailto:gurkanerdogdu at yahoo.com">Gurkan Erdogdu</a> 
+ * @version $Rev$ $Date$
+ * @see AbstractConnectionListener
+ */
+public class NoTxConnectionListener extends AbstractConnectionListener
+{
+   /**
+    * Creates a new no-tx listener.
+    * @param cm connection manager
+    * @param mc managed connection
+    * @param mcp managed connection pool
+    * @param context context
+    */
+   public NoTxConnectionListener(final AbstractConnectionManager cm, final ManagedConnection mc, 
+         final ManagedConnectionPool mcp, final Object context)
+   {
+      super(cm, mc, mcp, context);
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public void connectionClosed(ConnectionEvent ce)
+   {
+      try
+      {
+         getCachedConnectionManager().unregisterConnection(getConnectionManager(), ce.getConnectionHandle());
+      }
+      catch (Throwable t)
+      {
+         getLog().info("Throwable from unregisterConnection", t);
+      }
+
+      getConnectionManager().unregisterAssociation(this, ce.getConnectionHandle());
+      
+      if (isManagedConnectionFree())
+      {
+         getConnectionManager().returnManagedConnection(this, false);
+      }
+   }
+
+}


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/NoTxConnectionListener.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Added: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/TxConnectionListener.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/TxConnectionListener.java	                        (rev 0)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/TxConnectionListener.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -0,0 +1,656 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008-2009, 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.jca.core.connectionmanager.listener;
+
+import org.jboss.jca.common.api.JBossResourceException;
+import org.jboss.jca.core.connectionmanager.AbstractConnectionManager;
+import org.jboss.jca.core.connectionmanager.pool.api.ManagedConnectionPool;
+import org.jboss.jca.core.connectionmanager.transaction.TransactionSynchronizer;
+import org.jboss.jca.core.connectionmanager.tx.TxConnectionManager;
+import org.jboss.jca.core.connectionmanager.xa.LocalXAResource;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionEvent;
+import javax.resource.spi.LocalTransaction;
+import javax.resource.spi.ManagedConnection;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.xa.XAResource;
+
+import org.jboss.tm.TxUtils;
+
+
+/**
+ * Tx connection listener.
+ * @author <a href="mailto:gurkanerdogdu at yahoo.com">Gurkan Erdogdu</a> 
+ * @version $Rev$ $Date$
+ *
+ */
+public class TxConnectionListener extends AbstractConnectionListener
+{
+   
+   /**Transaction synch. instance*/
+   private TransactionSynchronization transactionSynchronization;
+   
+   /**XAResource instance*/
+   private final XAResource xaResource;
+
+   /** Whether there is a local transaction */
+   private AtomicBoolean localTransaction = new AtomicBoolean(false);
+
+   /**
+    * Creates a new tx listener.
+    * @param cm connection manager
+    * @param mc managed connection
+    * @param mcp managed connection pool
+    * @param context context
+    * @param xaResource xaresource instance
+    * @throws ResourceException if aexception while creating
+    */
+   public TxConnectionListener(final AbstractConnectionManager cm, final ManagedConnection mc, 
+         final ManagedConnectionPool mcp, final Object context, final XAResource xaResource)
+      throws ResourceException
+   {
+      super(cm, mc, mcp, context);
+
+      this.xaResource = xaResource;
+      
+      if (xaResource instanceof LocalXAResource)
+      {
+         ((LocalXAResource) xaResource).setConnectionListener(this);  
+      }
+
+   }   
+   
+   /**
+    * {@inheritDoc}
+    */
+   public void enlist() throws SystemException
+   {
+      // This method is a bit convulted, but it has to be such because
+      // there is a race condition in the transaction manager where it
+      // unlocks during the enlist of the XAResource. It does this 
+      // to avoid distributed deadlocks and to ensure the transaction
+      // timeout can fail a badly behaving resource during the enlist.
+      //
+      // When two threads in the same transaction are trying to enlist 
+      // connections they could be from the same resource manager 
+      // or even the same connection when tracking the connection by transaction.
+      //
+      // For the same connection, we only want to do the real enlist once.
+      // For two connections from the same resource manager we don't
+      // want the join before the initial start request.
+      //
+      // The solution is to build up a list of unenlisted resources
+      // in the TransactionSynchronizer and then choose one of the
+      // threads that is contending in the transaction to enlist them
+      // in order. The actual order doesn't really matter as it is the
+      // transaction manager that calculates the enlist flags and determines
+      // whether the XAResource was already enlisted.
+      //
+      // Once there are no unenlisted resources the threads are released
+      // to return the result of the enlistments.
+      //
+      // In practice, a thread just takes a snapshot to try to avoid one
+      // thread having to do all the work. If it did not do them all
+      // the next waiting thread will do the next snapshot until there
+      // there is either no snapshot or no waiting threads.
+      //
+      // A downside to this design is a thread could have its resource enlisted by
+      // an earlier thread while it enlists some later thread's resource.
+      // Since they are all a part of the same transaction, this is probably
+      // not a real issue.
+      
+      // No transaction associated with the thread
+      TransactionManager tm = getConnectionManager().getTransactionManagerInstance();
+      int status = tm.getStatus();
+      if (status == Status.STATUS_NO_TRANSACTION)
+      {
+         if (transactionSynchronization != null && transactionSynchronization.currentTx != null)
+         {
+            String error = "Attempt to use connection outside a transaction when already a tx!";
+            if (trace)
+            {
+               getLog().trace(error + " " + this);  
+            }
+            
+            throw new IllegalStateException(error);
+         }
+         if (trace)
+         {
+            getLog().trace("No transaction, no need to enlist: " + this);  
+         }
+         
+         return;
+      }
+      
+      // Inactive transaction
+      Transaction threadTx = tm.getTransaction();
+      if (threadTx == null || status != Status.STATUS_ACTIVE)
+      {
+         String error = "Transaction " + threadTx + " is not active " + TxUtils.getStatusAsString(status);
+         if (trace)
+         {
+            getLog().trace(error + " cl=" + this);  
+         }
+         
+         throw new IllegalStateException(error);
+      }
+
+      if (trace)
+      {
+         getLog().trace("Pre-enlist: " + this + " threadTx=" + threadTx);  
+      }
+      
+      // Our synchronization 
+      TransactionSynchronization ourSynchronization = null;
+
+      // Serializes enlistment when two different threads are enlisting 
+      // different connections in the same transaction concurrently
+      TransactionSynchronizer synchronizer = null;
+
+      TransactionSynchronizer.lock(threadTx);
+      try
+      {
+         // Interleaving should have an unenlisted transaction
+         // TODO We should be able to do some sharing shouldn't we?
+         if (!isTrackByTx() && transactionSynchronization != null)
+         {
+            String error = "Can't enlist - already a tx!";
+            if (trace)
+            {
+               getLog().trace(error + " " + this);  
+            }
+            throw new IllegalStateException(error);
+         }
+         
+         // Check for different transaction
+         if (transactionSynchronization != null && !transactionSynchronization.currentTx.equals(threadTx))
+         {
+            String error = "Trying to change transaction " + threadTx + " in enlist!";
+            if (trace)
+            {
+               getLog().trace(error + " " + this);  
+            }
+            throw new IllegalStateException(error);
+         }
+
+         // Get the synchronizer
+         try
+         {
+            if (this.trace)
+            {
+               getLog().trace("Get synchronizer " + this + " threadTx=" + threadTx);  
+            }
+            
+            synchronizer = TransactionSynchronizer.getRegisteredSynchronizer(threadTx);
+         }
+         catch (Throwable t)
+         {
+            setTrackByTx(false);
+            TxConnectionManager.rethrowAsSystemException("Cannot register synchronization", threadTx, t);
+         }
+
+         // First time through, create a transaction synchronization
+         if (transactionSynchronization == null)
+         {
+            TransactionSynchronization synchronization = new TransactionSynchronization(threadTx, isTrackByTx());
+            synchronizer.addUnenlisted(synchronization);
+            transactionSynchronization = synchronization;
+         }
+         
+         ourSynchronization = transactionSynchronization;
+      }
+      finally
+      {
+         TransactionSynchronizer.unlock(threadTx);
+      }
+
+      // Perform the enlistment(s)
+      CopyOnWriteArrayList<Synchronization> unenlisted = synchronizer.getUnenlisted();
+      if (unenlisted != null)
+      {
+         try
+         {
+            for (int i = 0; i < unenlisted.size(); ++i)
+            {
+               TransactionSynchronization sync = (TransactionSynchronization) unenlisted.get(i);
+               if (sync.enlist())
+               {
+                  synchronizer.addEnlisted(sync);  
+               }
+            }
+         }
+         finally
+         {
+            synchronizer.enlisted();
+         }
+      }
+      
+      // What was the result of our enlistment?
+      if (this.trace)
+      {
+         getLog().trace("Check enlisted " + this + " threadTx=" + threadTx);  
+      }
+      
+      ourSynchronization.checkEnlisted();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void delist() throws ResourceException
+   {
+      if (trace)
+         getLog().trace("delisting " + this);
+
+      try
+      {
+         if (!isTrackByTx() && transactionSynchronization != null)
+         {
+            Transaction tx = transactionSynchronization.currentTx;
+            TransactionSynchronization synchronization = transactionSynchronization;
+            transactionSynchronization = null;
+            if (TxUtils.isUncommitted(tx))
+            {
+               TransactionSynchronizer synchronizer = TransactionSynchronizer.getRegisteredSynchronizer(tx);
+               if (synchronization.enlisted)
+                  synchronizer.removeEnlisted(synchronization);
+               if (!tx.delistResource(getXAResource(), XAResource.TMSUSPEND))
+               {
+                  throw new ResourceException("Failure to delist resource: " + this);  
+               }
+            }
+         }
+      }
+      catch (Throwable t)
+      {
+         JBossResourceException.rethrowAsResourceException("Error in delist!", t);
+      }
+   }
+
+   //local will return this, xa will return one from mc.
+   /**
+    * Get XA resource.
+    * @return xa resource
+    */
+   protected XAResource getXAResource()
+   {
+      return xaResource;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void connectionClosed(ConnectionEvent ce)
+   {
+      if (trace)
+         getLog().trace("connectionClosed called mc=" + this.getManagedConnection());
+      if (this.getManagedConnection() != (ManagedConnection)ce.getSource())
+         throw new IllegalArgumentException("ConnectionClosed event received from wrong ManagedConnection! Expected: " +
+               this.getManagedConnection() + ", actual: " + ce.getSource());
+      try
+      {
+         this.getCachedConnectionManager().unregisterConnection(this.getConnectionManager(), ce.getConnectionHandle());
+      }
+      catch (Throwable t)
+      {
+         getLog().info("throwable from unregister connection", t);
+      }
+
+      try
+      {
+         if (wasFreed(ce.getConnectionHandle()))
+         {
+            delist();
+            if (trace)
+               getLog().trace("isManagedConnectionFree=true mc=" + this.getManagedConnection());
+            this.getConnectionManager().returnManagedConnection(this, false);
+         }
+         else
+         {
+            if (trace)
+               getLog().trace("isManagedConnectionFree=false mc=" + this.getManagedConnection());
+         }
+      }
+      catch (Throwable t)
+      {
+         getLog().error("Error while closing connection handle!", t);
+         this.getConnectionManager().returnManagedConnection(this, true);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void localTransactionStarted(ConnectionEvent ce)
+   {
+      localTransaction.set(true);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void localTransactionCommitted(ConnectionEvent ce)
+   {
+      localTransaction.set(false);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void localTransactionRolledback(ConnectionEvent ce)
+   {
+      localTransaction.set(false);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void tidyup() throws ResourceException
+   {
+      // We have a hanging transaction
+      if (localTransaction.get())
+      {
+         LocalTransaction local = null;
+         ManagedConnection mc = getManagedConnection();
+         try
+         {
+            local = mc.getLocalTransaction();
+         }
+         catch (Throwable t)
+         {
+            JBossResourceException.rethrowAsResourceException("Unfinished local transaction - " +
+                  "error getting local transaction from " + this, t);
+         }
+         if (local == null)
+            throw new ResourceException("Unfinished local transaction but managed connection does not " +
+                  "provide a local transaction. " + this);
+         else
+         {
+            local.rollback();
+            getLog().debug("Unfinished local transaction was rolled back." + this);
+         }
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void connectionErrorOccurred(ConnectionEvent ce)
+   {
+      transactionSynchronization = null;
+      super.connectionErrorOccurred(ce);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   //Important method!!
+   public boolean isManagedConnectionFree()
+   {
+      if (isTrackByTx() && transactionSynchronization != null)
+         return false;
+      return super.isManagedConnectionFree();
+   }
+
+   /**
+    * This method changes the number of handles or 
+    * the track-by-tx value depending on the parameter passed in
+    * @param handle The handle; if <code>null</code> track-by-tx is changed
+    * @return True if the managed connection was freed
+    */
+   synchronized boolean wasFreed(Object handle)
+   {
+      if (handle != null)
+      {
+         if (isManagedConnectionFree())
+         {
+            // This shouldn't really happen now all the state is changed atomically
+            return false;
+         }
+
+         // Change the number of handles
+         getConnectionManager().unregisterAssociation(this, handle);
+      }
+      else
+      {
+         if (!isTrackByTx())
+         {
+            // Only change the state once
+            return false;
+         }
+
+         // Set track-by-tx to false
+         setTrackByTx(false);
+      }
+      
+      // Return if the managed connection was just freed
+      return isManagedConnectionFree();
+   }
+         
+   
+   /**
+    * Transaction sync. class. 
+    */
+   private class TransactionSynchronization implements Synchronization
+   {
+      /**Error message*/
+      private final Throwable failedToEnlist = 
+         new Throwable("Unabled to enlist resource, see the previous warnings.");
+      
+      /** Transaction */
+      private Transaction currentTx;
+      
+      /** This is the status when we were registered */
+      private boolean wasTrackByTx;
+
+      /** Whether we are enlisted */
+      private boolean enlisted = false;
+      
+      /** Any error during enlistment */
+      private Throwable enlistError;
+      
+      /**
+       * Create a new TransactionSynchronization.
+       * 
+       * @param trackByTx whether this is track by connection
+       */
+      public TransactionSynchronization(Transaction tx, boolean trackByTx)
+      {
+         this.currentTx = tx;
+         this.wasTrackByTx = trackByTx;
+      }
+      
+      /**
+       * Get the result of the enlistment.
+       * 
+       * @throws SystemExeption for any error
+       */
+      public void checkEnlisted() throws SystemException
+      {
+         if (this.enlistError != null)
+         {
+            String error = "Error enlisting resource in transaction=" + this.currentTx;
+            if (TxConnectionListener.this.trace)
+            {
+               TxConnectionListener.this.getLog().trace(error + " " + TxConnectionListener.this);  
+            }
+
+            // Wrap the error to give a reasonable stacktrace since the resource
+            // could have been enlisted by a different thread
+            if (enlistError == failedToEnlist)
+            {
+               throw new SystemException(failedToEnlist + " tx=" + this.currentTx);  
+            }
+            else
+            {
+               SystemException e = new SystemException(error);
+               e.initCause(enlistError);
+               throw e;
+            }
+         }
+         if (!enlisted)
+         {
+            String error = "Resource is not enlisted in transaction=" + currentTx;
+            if (trace)
+            {
+               getLog().trace(error + " " + TxConnectionListener.this);  
+            }
+            throw new IllegalStateException("Resource was not enlisted.");
+         }
+      }
+      
+      /**
+       * Enlist the resource
+       * 
+       * @return true when enlisted, false otherwise
+       */
+      public boolean enlist()
+      {
+         if (TxConnectionListener.this.trace)
+         {
+            TxConnectionListener.this.getLog().trace("Enlisting resource " + TxConnectionListener.this);  
+         }
+         try
+         {
+            XAResource resource = getXAResource();
+            if (!currentTx.enlistResource(resource))
+            {
+               enlistError = failedToEnlist;  
+            }
+         }
+         catch (Throwable t)
+         {
+            enlistError = t;
+         }
+
+         synchronized (this)
+         {
+            if (enlistError != null)
+            {
+               if (trace)
+               {
+                  getLog().trace("Failed to enlist resource " + TxConnectionListener.this, enlistError);  
+               }
+               
+               setTrackByTx(false);
+               transactionSynchronization = null;
+               
+               return false;
+            }
+            
+            if (trace)
+            {
+               getLog().trace("Enlisted resource " + TxConnectionListener.this);  
+            }
+            
+            enlisted = true;
+            return true;
+         }
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      public void beforeCompletion()
+      {
+         //No-op
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public void afterCompletion(int status)
+      {
+         // The connection got destroyed during the transaction
+         if (getState().equals(ConnectionState.DESTROYED))
+         {
+            return;  
+         }
+         
+         // Are we still in the original transaction?
+         if (!this.equals(transactionSynchronization))
+         {
+            // If we are interleaving transactions we have nothing to do
+            if (!wasTrackByTx)
+            {
+               return;  
+            }
+            else
+            {
+               // There is something wrong with the pooling
+               String message = "afterCompletion called with wrong tx! Expected: " +
+                  this + ", actual: " + transactionSynchronization;
+               IllegalStateException e = new IllegalStateException(message);
+               getLog().error("There is something wrong with the pooling?", e);
+            }
+         }
+         // "Delist"
+         transactionSynchronization = null;
+         // This is where we close when doing track by transaction
+         if (wasTrackByTx)
+         {
+            if (trace)
+            {
+               getLog().trace("afterCompletion(" + status + ") isTrackByTx=" + isTrackByTx() +
+                     " for " + TxConnectionListener.this);
+            }
+
+            if (wasFreed(null))
+            {
+               getConnectionManager().returnManagedConnection(TxConnectionListener.this, false);  
+            }
+         }
+      }
+      
+      /**
+       * {@inheritDoc}
+       */
+      public String toString()
+      {
+         StringBuffer buffer = new StringBuffer();
+         buffer.append("TxSync").append(System.identityHashCode(this));
+         buffer.append("{tx=").append(currentTx);
+         buffer.append(" wasTrackByTx=").append(wasTrackByTx);
+         buffer.append(" enlisted=").append(enlisted);
+         buffer.append("}");
+         return buffer.toString();
+      }
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   // For debugging
+   protected void toString(StringBuffer buffer)
+   {
+      buffer.append(" xaResource=").append(xaResource);
+      buffer.append(" txSync=").append(transactionSynchronization);
+   }
+}


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/listener/TxConnectionListener.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Modified: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/notx/NoTxConnectionManager.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/notx/NoTxConnectionManager.java	2009-09-08 19:22:26 UTC (rev 93295)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/notx/NoTxConnectionManager.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -22,6 +22,14 @@
 
 package org.jboss.jca.core.connectionmanager.notx;
 
+import org.jboss.jca.core.connectionmanager.AbstractConnectionManager;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.listener.NoTxConnectionListener;
+
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ManagedConnection;
+
 /**
  * Non transactional connection manager implementation.
  * 
@@ -29,7 +37,27 @@
  * @version $Rev$ $Date$
  *
  */
-public class NoTxConnectionManager
+public class NoTxConnectionManager extends AbstractConnectionManager
 {
+   /**
+    * Default constructor.
+    */
+   public NoTxConnectionManager()
+   {
+      
+   }
 
+   /**
+    * {@inheritDoc}
+    */
+   public ConnectionListener createConnectionListener(ManagedConnection managedConnection, Object context) 
+      throws ResourceException
+   {
+      ConnectionListener cli = new NoTxConnectionListener(this, managedConnection, getPoolingStrategy(), context);
+      managedConnection.addConnectionEventListener(cli);
+      
+      return cli;
+
+   }
+
 }


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/notx/NoTxConnectionManager.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date

Modified: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/pool/AbstractPool.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/pool/AbstractPool.java	2009-09-08 19:22:26 UTC (rev 93295)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/pool/AbstractPool.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -266,7 +266,7 @@
       
       if (trackByTransaction == null || trackByTx == null)
       {
-         cl = getSimpleConnection(subject, cri, separateNoTx);
+         cl = getSimpleConnection(subject, cri, subPoolContext);
       } //end of if trackByTransaction   
       
       //Transaction old connections
@@ -292,27 +292,21 @@
     * @return connection listener
     * @throws ResourceException
     */
-   private ConnectionListener getSimpleConnection(Subject subject, ConnectionRequestInfo cri, boolean separateNoTx)
+   private ConnectionListener getSimpleConnection(final Subject subject, final ConnectionRequestInfo cri, 
+         final SubPoolContext subPoolContext)
       throws ResourceException
    {
       ConnectionListener cl = null;
-      SubPoolContext subPoolContext = null;
-      Object key = null;
       InternalManagedConnectionPool imcp = null;
       
       try
       {  
-         //Find key for pool
-         key = getKey(subject, cri, separateNoTx);
-         
-         //Get pool context from key
-         subPoolContext = getSubPool(key, subject, cri);
-         
          //Find internal managed pool
          imcp = subPoolContext.getSubPool();
          
          //Get connection from imcp
          cl = imcp.getConnection(subject, cri);
+         
          if (this.traceEnabled)
          {
             dump("Got connection from pool : " + cl);
@@ -329,7 +323,6 @@
          }
 
          // The IMCP is down - retry
-         subPoolContext = getSubPool(key, subject, cri);
          imcp = subPoolContext.getSubPool();
 
          // Make sure that IMCP is running


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/pool/AbstractPool.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date

Modified: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/pool/InternalManagedConnectionPool.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/pool/InternalManagedConnectionPool.java	2009-09-08 19:22:26 UTC (rev 93295)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/pool/InternalManagedConnectionPool.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -452,7 +452,7 @@
          ConnectionListener cl = (ConnectionListener) cls.get(0);
          if (cl.isTimedOut(timeout) && shouldRemove())
          {
-            connectionCounter.incTimedOut();
+            connectionCounter.incTimedOutCount();
             // We need to destroy this one
             cls.remove(0);
             if (destroy == null)
@@ -687,9 +687,9 @@
     * Gets timed out.
     * @return timed out
     */
-   public int getTimedOut()
+   public int getTimedOutCount()
    {
-      return this.connectionCounter.getTimedOut();
+      return this.connectionCounter.getTimedOutCount();
    }
    
    /**

Added: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/transaction/TransactionSynchronizer.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/transaction/TransactionSynchronizer.java	                        (rev 0)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/transaction/TransactionSynchronizer.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -0,0 +1,335 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.jca.core.connectionmanager.transaction;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import javax.transaction.RollbackException;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.jboss.logging.Logger;
+import org.jboss.tm.TransactionLocal;
+import org.jboss.util.NestedRuntimeException;
+
+/**
+ * Organizes transaction synchronization done by JCA.
+ * 
+ * <p> 
+ * This class exists to make sure all Tx synchronizations
+ * are invoked before the cached connection manager closes any
+ * closed connections.
+ *
+ * @author <a href="mailto:adrian at jboss.org">Adrian Brock</a>
+ * @author gurkanerdogdu
+ * @version $Rev$ $Date$
+ */
+public class TransactionSynchronizer implements Synchronization
+{
+   /** The logger */
+   private static Logger log = Logger.getLogger(TransactionSynchronizer.class);
+
+   /** The transaction synchronizations */
+   private static TransactionLocal txSynchs;
+   
+   /** The transaction */
+   private Transaction tx;
+   
+   /** The enlisting thread */
+   private Thread enlistingThread;
+   
+   /** Unenlisted */
+   private CopyOnWriteArrayList<Synchronization> unenlisted;
+   
+   /** Enlisted */
+   private CopyOnWriteArrayList<Synchronization> enlisted;
+   
+   /** The cached connection manager synchronization */
+   private Synchronization ccmSynch;
+
+   /** 
+    * Initialization. 
+    * @param tm transaction manager
+    */
+   public static void setTransactionManager(TransactionManager tm)
+   {
+      txSynchs = new TransactionLocal(tm);
+   }
+   
+   /**
+    * Create a new transaction synchronizer
+    * 
+    * @param tx the transaction to synchronize with
+    */
+   private TransactionSynchronizer(Transaction tx)
+   {
+      this.tx = tx;
+   }
+   
+   /**
+    * Add a new Tx synchronization that has not been enlisted
+    * 
+    * @param synch the synchronization
+    */
+   public void addUnenlisted(Synchronization synch)
+   {
+      unenlisted.add(synch);
+   }
+   
+   /**
+    * Get the unenlisted synchronizations
+    * and say we are enlisting if some are returned.
+    * 
+    * @return the unenlisted synchronizations
+    */
+   public CopyOnWriteArrayList<Synchronization> getUnenlisted()
+   {
+      Thread currentThread = Thread.currentThread();
+      while (enlistingThread != null && enlistingThread != currentThread)
+      {
+         boolean interrupted = false;
+         try
+         {
+            wait();
+         }
+         catch (InterruptedException e)
+         {
+            interrupted = true;
+         }
+         
+         if (interrupted)
+         {
+            currentThread.interrupt();  
+         }
+      }
+      CopyOnWriteArrayList<Synchronization> result = unenlisted;
+      
+      unenlisted = null;
+      
+      if (result != null)
+      {
+         enlistingThread = currentThread;  
+      }
+      return result;
+   }
+   
+   /**
+    * The synchronization is now enlisted
+    * 
+    * @param synch the synchronization
+    */
+   public void addEnlisted(Synchronization synch)
+   {
+      enlisted.add(synch);
+   }
+   
+   /**
+    * Remove an enlisted synchronization
+    * 
+    * @param synch the synchronization
+    * @return true when the synchronization was enlisted
+    */
+   public boolean removeEnlisted(Synchronization synch)
+   {
+      return enlisted.remove(synch);
+   }
+   
+   /**
+    * This thread has finished enlisting.
+    */
+   public void enlisted()
+   {
+      Thread currentThread = Thread.currentThread();
+      if (enlistingThread == null || enlistingThread != currentThread)
+      {
+         log.warn("Thread " + currentThread + " not the enlisting thread " + 
+               enlistingThread, new Exception("STACKTRACE"));
+         
+         return;
+      }
+      
+      enlistingThread = null;
+      notifyAll();
+   }
+   
+   /**
+    * Get a registered transaction synchronizer.
+    *
+    * @param tx the transaction
+    * @throws SystemException sys. exception
+    * @throws RollbackException rollback exception
+    * @return the registered transaction synchronizer for this transaction
+    */
+   public static TransactionSynchronizer getRegisteredSynchronizer(Transaction tx) 
+      throws SystemException, RollbackException
+   {
+      TransactionSynchronizer result = (TransactionSynchronizer) txSynchs.get(tx);
+      if (result == null)
+      {
+         result = new TransactionSynchronizer(tx);
+         tx.registerSynchronization(result);
+         txSynchs.set(tx, result);
+      }
+      return result;
+   }
+   
+   /**
+    * Check whether we have a CCM synchronization
+    * 
+    * @param tx the transaction
+    * @return synch
+    */
+   public static Synchronization getCCMSynchronization(Transaction tx)
+   {
+      TransactionSynchronizer ts = (TransactionSynchronizer) txSynchs.get(tx);
+      if (ts != null)
+      {
+         return ts.ccmSynch;  
+      }
+      else
+      {
+         return null;  
+      }
+   }
+   
+   /**
+    * Register a new CCM synchronization
+    * 
+    * @param tx the transaction
+    * @param synch the synchronization
+    * @throws Exception e
+    */
+   public static void registerCCMSynchronization(Transaction tx, Synchronization synch) 
+      throws Exception
+   {
+      TransactionSynchronizer ts = getRegisteredSynchronizer(tx);
+      ts.ccmSynch = synch;
+   }
+   
+   /**
+    * Lock for the given transaction
+    * 
+    * @param tx the transaction
+    */
+   public static void lock(Transaction tx)
+   {
+      try
+      {
+         txSynchs.lock(tx);
+      }
+      catch (InterruptedException e)
+      {
+         throw new NestedRuntimeException("Unable to get synchronization", e);
+      }
+   }
+   
+   /**
+    * Unlock for the given transaction
+    * 
+    * @param tx the transaction
+    */
+   public static void unlock(Transaction tx)
+   {
+      txSynchs.unlock(tx);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void beforeCompletion()
+   {
+      if (enlisted != null)
+      {
+         int i = 0;
+         while (i < enlisted.size())
+         {
+            Synchronization synch = enlisted.get(i);
+            invokeBefore(synch);
+            ++i;
+         }
+      }
+      
+      if (ccmSynch != null)
+      {
+         invokeBefore(ccmSynch);  
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void afterCompletion(int status)
+   {
+      if (enlisted != null)
+      {
+         int i = 0;
+         while (i < enlisted.size())
+         {
+            Synchronization synch = enlisted.get(i);
+            invokeAfter(synch, status);
+            ++i;
+         }
+      }
+      
+      if (ccmSynch != null)
+      {
+         invokeAfter(ccmSynch, status);  
+      }
+   }
+
+   /**
+    * Invoke a beforeCompletion
+    * 
+    * @param synch the synchronization
+    */
+   protected void invokeBefore(Synchronization synch)
+   {
+      try
+      {
+         synch.beforeCompletion();
+      }
+      catch (Throwable t)
+      {
+         log.warn("Transaction " + tx + " error in before completion " + synch, t);
+      }
+   }
+
+   /**
+    * Invoke an afterCompletion
+    * 
+    * @param synch the synchronization
+    * @param status the status of the transaction
+    */
+   protected void invokeAfter(Synchronization synch, int status)
+   {
+      try
+      {
+         synch.afterCompletion(status);
+      }
+      catch (Throwable t)
+      {
+         log.warn("Transaction " + tx + " error in after completion " + synch, t);
+      }
+   }
+}


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/transaction/TransactionSynchronizer.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Modified: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/tx/TxConnectionManager.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/tx/TxConnectionManager.java	2009-09-08 19:22:26 UTC (rev 93295)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/tx/TxConnectionManager.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -1,6 +1,6 @@
 /*
  * JBoss, Home of Professional Open Source.
- * Copyright 2008-2009, Red Hat Middleware LLC, and individual contributors
+ * Copyright 2006, 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.
  *
@@ -19,17 +19,517 @@
  * 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.jca.core.connectionmanager.tx;
 
+import org.jboss.jca.common.api.JBossResourceException;
+import org.jboss.jca.core.connectionmanager.AbstractConnectionManager;
+import org.jboss.jca.core.connectionmanager.ConnectionRecord;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+import org.jboss.jca.core.connectionmanager.listener.TxConnectionListener;
+import org.jboss.jca.core.connectionmanager.xa.LocalXAResource;
+import org.jboss.jca.core.connectionmanager.xa.XAResourceWrapperImpl;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnection;
+import javax.security.auth.Subject;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+
+import org.jboss.tm.TransactionTimeoutConfiguration;
+import org.jboss.tm.TxUtils;
+import org.jboss.util.NestedRuntimeException;
+
 /**
- * Transactional connection manager implementation.
+ * The TxConnectionManager is a JBoss ConnectionManager
+ * implementation for jca adapters implementing LocalTransaction and XAResource support.
  * 
- * @author <a href="mailto:gurkanerdogdu at yahoo.com">Gurkan Erdogdu</a>
- * @version $Rev$ $Date$
+ * It implements a ConnectionEventListener that implements XAResource to
+ * manage transactions through the Transaction Manager. To assure that all
+ * work in a local transaction occurs over the same ManagedConnection, it
+ * includes a xid to ManagedConnection map.  When a Connection is requested
+ * or a transaction started with a connection handle in use, it checks to
+ * see if a ManagedConnection already exists enrolled in the global
+ * transaction and uses it if found. Otherwise a free ManagedConnection
+ * has its LocalTransaction started and is used.  From the
+ * BaseConnectionManager2, it includes functionality to obtain managed
+ * connections from
+ * a ManagedConnectionPool mbean, find the Subject from a SubjectSecurityDomain,
+ * and interact with the CachedConnectionManager for connections held over
+ * transaction and method boundaries.  Important mbean references are to a
+ * ManagedConnectionPool supplier (typically a JBossManagedConnectionPool), and a
+ * RARDeployment representing the ManagedConnectionFactory.
  *
+ * This connection manager has to perform the following operations:
+ *
+ * 1. When an application component requests a new ConnectionHandle,
+ *    it must find a ManagedConnection, and make sure a
+ *    ConnectionEventListener is registered. It must inform the
+ *    CachedConnectionManager that a connection handle has been given
+ *    out. It needs to count the number of handles for each
+ *    ManagedConnection.  If there is a current transaction, it must
+ *    enlist the ManagedConnection's LocalTransaction in the transaction
+ *    using the ConnectionEventListeners XAResource XAResource implementation.
+ * Entry point: ConnectionManager.allocateConnection.
+ * written.
+ *
+ * 2. When a ConnectionClosed event is received from the
+ *    ConnectionEventListener, it must reduce the handle count.  If
+ *    the handle count is zero, the XAResource should be delisted from
+ *    the Transaction, if any. The CachedConnectionManager must be
+ *    notified that the connection is closed.
+ * Entry point: ConnectionEventListener.ConnectionClosed.
+ * written
+ *
+ *3. When a transaction begun notification is received from the
+ * UserTransaction (via the CachedConnectionManager, all
+ * managedConnections associated with the current object must be
+ * enlisted in the transaction.
+ *  Entry point: (from
+ * CachedConnectionManager)
+ * ConnectionCacheListener.transactionStarted(Transaction,
+ * Collection). The collection is of ConnectionRecord objects.
+ * written.
+ *
+ * 5. When an "entering object" notification is received from the
+ * CachedConnectionInterceptor, all the connections for the current
+ * object must be associated with a ManagedConnection.  if there is a
+ * Transaction, the XAResource must be enlisted with it.
+ *  Entry point: ConnectionCacheListener.reconnect(Collection conns) The Collection
+ * is of ConnectionRecord objects.
+ * written.
+ *
+ * 6. When a "leaving object" notification is received from the
+ * CachedConnectionInterceptor, all the managedConnections for the
+ * current object must have their XAResources delisted from the
+ * current Transaction, if any, and cleanup called on each
+ * ManagedConnection.
+ * Entry point: ConnectionCacheListener.disconnect(Collection conns).
+ * written.
+ *
+ * @author <a href="mailto:d_jencks at users.sourceforge.net">David Jencks</a>
+ * @author <a href="mailto:adrian at jboss.org">Adrian Brock</a>
+ * @author <a href="weston.price at jboss.com">Weston Price</a>
+ * @version $Revision: 77961 $
  */
-public class TxConnectionManager
+public class TxConnectionManager extends AbstractConnectionManager
 {
+   /**Transaction manager instance*/
+   private TransactionManager tm;
 
+   /**Interleaving or not*/
+   private boolean interleaving;
+
+   /**Local tx or not*/
+   private boolean localTransactions;
+   
+   /**XA resource timeout*/
+   private int xaResourceTimeout = 0;
+   
+   /**Xid pad*/
+   private boolean padXid;
+   
+   /**XA resource wrapped or not*/
+   private boolean wrapXAResource;
+
+   /**Same RM override*/
+   private Boolean isSameRMOverrideValue;
+   
+   /**Log trace*/
+   private boolean trace = getLog().isTraceEnabled();
+      
+   /**
+    * Default managed TxConnectionManager constructor for mbean instances.
+    */
+   public TxConnectionManager()
+   {
+   }
+
+   /**
+    * Gets transaction manager instance.
+    * @return transaction manager
+    */
+   public TransactionManager getTransactionManagerInstance()
+   {
+      return tm;
+   }
+
+   /**
+    * Sets transaction manager.
+    * @param tm transaction manager
+    */
+   public void setTransactionManagerInstance(TransactionManager tm)
+   {
+      this.tm = tm;
+   }
+
+   /**
+    * Gets track connection by tx.
+    * @return track connection by tx
+    */
+   @Deprecated
+   public boolean isTrackConnectionByTx()
+   {
+      getLog().warn("isTrackConnectionByTx() is deprecated in favor of isInterleaving()");
+      return !isInterleaving();
+   }
+
+   /**
+    * Set track connection by tx.
+    * @param trackConnectionByTx track connection by tx
+    */
+   @Deprecated
+   public void setTrackConnectionByTx(boolean trackConnectionByTx)
+   {
+      getLog().warn("setTrackConnectionByTx(boolean value) is deprecated in favor of setInterleaving(boolean value)");
+      setInterleaving(!trackConnectionByTx);
+   }
+
+   /**
+    * Gets interleaving flag.
+    * @return interleaving flag
+    */
+   public boolean isInterleaving()
+   {
+      return interleaving;
+   }
+   
+   /**
+    * Sets interleaving flag.
+    * @param value interleaving
+    */
+   public void setInterleaving(boolean value)
+   {
+      this.interleaving = value;
+   }
+   
+   /**
+    * Returns local tx or not.
+    * @return local tx or not
+    */
+   public boolean isLocalTransactions()
+   {
+      return localTransactions;
+   }
+
+   /**
+    * Sets local transaction or not.
+    * @param localTransactions local transaction flag
+    */
+   public void setLocalTransactions(boolean localTransactions)
+   {
+      this.localTransactions = localTransactions;
+      if (localTransactions)
+         setInterleaving(false);
+   }
+
+   /**
+    * Gets XA resource transaction time out.
+    * @return xa resource transaction timeout
+    */
+   public int getXAResourceTransactionTimeout()
+   {
+      return xaResourceTimeout;
+   }
+   
+   /**
+    * Sets XA resource transaction timeout.
+    * @param timeout xa resource transaction timeout
+    */
+   public void setXAResourceTransactionTimeout(int timeout)
+   {
+      this.xaResourceTimeout = timeout;
+   }
+   
+   /**
+    * Get the IsSameRMOverrideValue value.
+    * 
+    * @return the IsSameRMOverrideValue value.
+    */
+   public Boolean getIsSameRMOverrideValue()
+   {
+      return isSameRMOverrideValue;
+   }
+   
+   /**
+    * Returns true if wrap xa resource.
+    * @return true if wrap xa resource
+    */
+   public boolean getWrapXAResource()
+   {      
+      return wrapXAResource;      
+   }
+   
+   /**
+    * Sets use xa wrapper.
+    * @param useXAWrapper use xa wrapper
+    */
+   public void setWrapXAResource(boolean useXAWrapper)
+   {
+      this.wrapXAResource = useXAWrapper;
+      
+   }
+   
+   /**
+    * Gets pad.
+    * @return pad 
+    */
+   public boolean getPadXid()
+   {
+      return this.padXid;
+      
+   }
+   
+   /**
+    * Sets pad.
+    * @param padXid pad
+    */
+   public void setPadXid(boolean padXid)
+   {
+      this.padXid = padXid;
+   }
+   /**
+    * Set the IsSameRMOverrideValue value.
+    * 
+    * @param isSameRMOverrideValue The new IsSameRMOverrideValue value.
+    */
+   public void setIsSameRMOverrideValue(Boolean isSameRMOverrideValue)
+   {
+      this.isSameRMOverrideValue = isSameRMOverrideValue;
+   }
+   
+   /**
+    * Gets time left.
+    * @param errorRollback error rollback
+    * @return time left
+    * @throws RollbackException if exception
+    */
+   public long getTimeLeftBeforeTransactionTimeout(boolean errorRollback) throws RollbackException
+   {
+      if (tm == null)
+         throw new IllegalStateException("No transaction manager: " + getCachedConnectionManager());
+      if (tm instanceof TransactionTimeoutConfiguration)
+         return ((TransactionTimeoutConfiguration) tm).getTimeLeftBeforeTransactionTimeout(errorRollback);
+      return -1;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void checkTransactionActive() throws RollbackException, SystemException
+   {
+      if (tm == null)
+         throw new IllegalStateException("No transaction manager: " + getCachedConnectionManager());
+      Transaction tx = tm.getTransaction();
+      if (tx != null)
+      {
+         int status = tx.getStatus();
+         // Only allow states that will actually succeed
+         if (status != Status.STATUS_ACTIVE && status != Status.STATUS_PREPARING && 
+               status != Status.STATUS_PREPARED && status != Status.STATUS_COMMITTING)
+            throw new RollbackException("Transaction " + tx + " cannot proceed " + TxUtils.getStatusAsString(status));
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public ConnectionListener getManagedConnection(Subject subject, ConnectionRequestInfo cri)
+      throws ResourceException
+   {
+      Transaction trackByTransaction = null;
+      try
+      {
+         Transaction tx = tm.getTransaction();
+         if (tx != null && !TxUtils.isActive(tx))
+            throw new ResourceException("Transaction is not active: tx=" + tx);
+         if (!interleaving)
+            trackByTransaction = tx;
+      }
+      catch (Throwable t)
+      {
+         JBossResourceException.rethrowAsResourceException("Error checking for a transaction.", t);
+      }
+
+      if (this.trace)
+         getLog().trace("getManagedConnection interleaving=" + interleaving + " tx=" + trackByTransaction);
+      return super.getManagedConnection(trackByTransaction, subject, cri);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void transactionStarted(Collection<ConnectionRecord> crs) throws SystemException
+   {
+      Set<ConnectionListener> cls = new HashSet<ConnectionListener>();
+      for (Iterator<ConnectionRecord> i = crs.iterator(); i.hasNext(); )
+      {
+         ConnectionRecord cr = i.next();
+         ConnectionListener cl = cr.getConnectionListener();
+         if (!cls.contains(cl))
+         {
+            cls.add(cl);
+            cl.enlist();
+         }
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected void managedConnectionReconnected(ConnectionListener cl) throws ResourceException
+   {
+      try
+      {
+         cl.enlist();
+      }
+      catch (Throwable t)
+      {
+         if (trace)
+         {
+            getLog().trace("Could not enlist in transaction on entering meta-aware object! " + cl, t);  
+         }
+         throw new JBossResourceException("Could not enlist in transaction on entering meta-aware object!", t);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected void managedConnectionDisconnected(ConnectionListener cl) throws ResourceException
+   {
+      Throwable throwable = null;
+      try
+      {
+         cl.delist();
+      }
+      catch (Throwable t)
+      {
+         throwable = t;
+      }
+
+      //if there are no more handles and tx is complete, we can return to pool.
+      if (cl.isManagedConnectionFree())
+      {
+         if (trace)
+            getLog().trace("Disconnected isManagedConnectionFree=true" + " cl=" + cl);
+         returnManagedConnection(cl, false);
+      }
+      else if (trace)
+      {
+         getLog().trace("Disconnected isManagedConnectionFree=false" + " cl=" + cl);
+      }
+
+      // Rethrow the error
+      if (throwable != null)
+      {
+         JBossResourceException.rethrowAsResourceException(
+               "Could not delist resource, probably a transaction rollback? ", throwable);  
+      }      
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public ConnectionListener createConnectionListener(ManagedConnection mc, Object context)
+      throws ResourceException
+   {
+      XAResource xaResource = null;
+      
+      if (localTransactions)
+      {
+         xaResource = new LocalXAResource(this);
+    
+         if (xaResourceTimeout != 0)
+            getLog().debug("XAResource transaction timeout cannot be set for local transactions: " + getJndiName());
+      }
+      
+      else
+      {
+         
+         if (this.wrapXAResource)
+         {
+            String eisProductName = null;
+            String eisProductVersion = null;
+
+            try
+            {
+               eisProductName = mc.getMetaData().getEISProductName();
+               eisProductVersion = mc.getMetaData().getEISProductVersion();
+            }
+            catch (ResourceException re)
+            {
+               // Ignore
+            }
+
+            getLog().trace("Generating XAResourceWrapper for TxConnectionManager" + this);
+            xaResource = new XAResourceWrapperImpl(mc.getXAResource(), padXid, 
+                  isSameRMOverrideValue, eisProductName, eisProductVersion);
+         }
+         
+         else
+         {
+            getLog().trace("Not wrapping XAResource.");
+            xaResource = mc.getXAResource();
+         }
+                                
+         if (xaResourceTimeout != 0)
+         {
+            try
+            {
+               if (!xaResource.setTransactionTimeout(xaResourceTimeout))
+                  getLog().debug("XAResource does not support transaction timeout configuration: " + getJndiName());
+            }
+            catch (XAException e)
+            {
+               throw new JBossResourceException("Unable to set XAResource transaction timeout: " + getJndiName(), e);
+            }
+         }
+      }
+
+      ConnectionListener cli = new TxConnectionListener(this, mc, getPoolingStrategy(), context, xaResource);
+      mc.addConnectionEventListener(cli);
+      return cli;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean isTransactional()
+   {
+      return !TxUtils.isCompleted(tm);
+   }
+   
+   /**
+    * RethrowAsSystemException.
+    * @param context context
+    * @param tx transaction
+    * @param t throwable
+    * @throws SystemException system exception
+    */
+   public static void rethrowAsSystemException(String context, Transaction tx, Throwable t)
+      throws SystemException
+   {
+      if (t instanceof SystemException)
+         throw (SystemException) t;
+      if (t instanceof RuntimeException)
+         throw (RuntimeException) t;
+      if (t instanceof Error)
+         throw (Error) t;
+      if (t instanceof RollbackException)
+         throw new IllegalStateException(context + " tx=" + tx + " marked for rollback.");
+      throw new NestedRuntimeException(context + " tx=" + tx + " got unexpected error ", t);
+   }
+   
 }

Added: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/xa/LocalXAResource.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/xa/LocalXAResource.java	                        (rev 0)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/xa/LocalXAResource.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -0,0 +1,252 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.jca.core.connectionmanager.xa;
+
+import org.jboss.jca.core.connectionmanager.AbstractConnectionManager;
+import org.jboss.jca.core.connectionmanager.exception.JBossLocalXAException;
+import org.jboss.jca.core.connectionmanager.listener.ConnectionListener;
+
+import javax.resource.ResourceException;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import org.jboss.logging.Logger;
+import org.jboss.tm.LastResource;
+
+/**
+ * Local XA resource implementation.
+ * 
+ * @author <a href="mailto:gurkanerdogdu at yahoo.com">Gurkan Erdogdu</a>
+ * @version $Rev$ $Date$
+ */
+public class LocalXAResource implements XAResource, LastResource
+{
+   /** Log instance */
+   private static Logger log = Logger.getLogger(LocalXAResource.class);
+
+   /** Connection listener */
+   private ConnectionListener cl;
+
+   /** Log trace */
+   private boolean trace;
+   
+   /**Connection manager*/
+   private AbstractConnectionManager connectionManager = null;
+
+   /**
+    * <code>warned</code> is set after one warning about a local participant in
+    * a multi-branch jta transaction is logged.
+    */
+   private boolean warned = false;
+
+   /** Current transction branch id */
+   private Xid currentXid;
+
+   /**
+    * Creates a new instance.
+    * @param connectionManager connection manager
+    */
+   public LocalXAResource(AbstractConnectionManager connectionManager)
+   {
+      this.trace = log.isTraceEnabled();
+      this.connectionManager = connectionManager;
+   }
+
+   /**
+    * Sets connection listener.
+    * 
+    * @param cl connection listener
+    */
+   public void setConnectionListener(ConnectionListener cl)
+   {
+      this.cl = cl;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void start(Xid xid, int flags) throws XAException
+   {
+      if (this.trace)
+      {
+         log.trace("start, xid: " + xid + ", flags: " + flags);  
+      }
+      
+      if (this.currentXid != null && flags == XAResource.TMNOFLAGS)
+      {
+         throw new JBossLocalXAException("Trying to start a new tx when old is not complete! old: " +
+               currentXid + ", new " + xid + ", flags " + flags, XAException.XAER_PROTO);
+      }
+      
+      if (this.currentXid == null && flags != XAResource.TMNOFLAGS)
+      {
+         throw new JBossLocalXAException("Trying to start a new tx with wrong flags!  new " + xid +
+               ", flags " + flags, XAException.XAER_PROTO);
+      }
+
+      if (this.currentXid == null)
+      {
+         try
+         {
+            this.cl.getManagedConnection().getLocalTransaction().begin();
+         }
+         catch (ResourceException re)
+         {
+            throw new JBossLocalXAException("Error trying to start local tx: ", XAException.XAER_RMERR, re);
+         }
+         catch (Throwable t)
+         {
+            throw new JBossLocalXAException("Throwable trying to start local transaction!", XAException.XAER_RMERR, t);
+         }
+
+         this.currentXid = xid;
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void end(Xid xid, int flags) throws XAException
+   {
+      if (this.trace)
+      {
+         log.trace("end on xid: " + xid + " called with flags " + flags);  
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void commit(Xid xid, boolean onePhase) throws XAException
+   {
+      if (!xid.equals(this.currentXid))
+      {
+         throw new JBossLocalXAException("wrong xid in commit: expected: " + this.currentXid +
+               ", got: " + xid, XAException.XAER_PROTO);
+         
+      }
+      
+      this.currentXid = null;
+
+      try
+      {
+         this.cl.getManagedConnection().getLocalTransaction().commit();
+      }
+      catch (ResourceException re)
+      {
+         this.connectionManager.returnManagedConnection(this.cl, true);
+         
+         if (this.trace)
+         {
+            log.trace("commit problem: ", re);  
+         }
+         
+         throw new JBossLocalXAException("could not commit local tx", XAException.XA_RBROLLBACK, re);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void forget(Xid xid) throws XAException
+   {
+      throw new JBossLocalXAException("forget not supported in local tx", XAException.XAER_RMERR);
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public int getTransactionTimeout() throws XAException
+   {
+      // TODO implement this javax.transaction.xa.XAResource method
+      return 0;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean isSameRM(XAResource xaResource) throws XAException
+   {
+      return xaResource == this;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public int prepare(Xid xid) throws XAException
+   {
+      if (!this.warned)
+      {
+         log.warn("Prepare called on a local tx. Use of local transactions on a jta transaction with more " +
+               "than one branch may result in inconsistent data in some cases of failure.");  
+      }
+      warned = true;
+      
+      return XAResource.XA_OK;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Xid[] recover(int flag) throws XAException
+   {
+      throw new JBossLocalXAException("no recover with local-tx only resource managers", XAException.XAER_RMERR);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void rollback(Xid xid) throws XAException
+   {
+      if (!xid.equals(this.currentXid))
+      {
+         throw new JBossLocalXAException("wrong xid in rollback: expected: " +
+               this.currentXid + ", got: " + xid, XAException.XAER_PROTO);  
+      }
+      this.currentXid = null;
+      try
+      {
+         this.cl.getManagedConnection().getLocalTransaction().rollback();
+      }
+      catch (ResourceException re)
+      {
+         this.connectionManager.returnManagedConnection(this.cl, true);
+        
+         if (this.trace)
+         {
+            log.trace("rollback problem: ", re);  
+         }
+         
+         throw new JBossLocalXAException("could not rollback local tx", XAException.XAER_RMERR, re);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean setTransactionTimeout(int seconds) throws XAException
+   {
+      // TODO implement this javax.transaction.xa.XAResource method
+      return false;
+   }
+}


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/xa/LocalXAResource.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Added: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/xa/XAResourceWrapperImpl.java
===================================================================
--- projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/xa/XAResourceWrapperImpl.java	                        (rev 0)
+++ projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/xa/XAResourceWrapperImpl.java	2009-09-08 19:59:36 UTC (rev 93296)
@@ -0,0 +1,264 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.jca.core.connectionmanager.xa;
+import org.jboss.jca.core.connectionmanager.xa.api.XidWrapper;
+
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import org.jboss.logging.Logger;
+import org.jboss.tm.XAResourceWrapper;
+
+/**
+ * A XAResourceWrapper.
+ * 
+ * @author <a href="weston.price at jboss.com">Weston Price</a>
+ * @author <a href="jesper.pedersen at jboss.org">Jesper Pedersen</a>
+ * @version $Revision$
+ */
+public class XAResourceWrapperImpl implements XAResourceWrapper
+{
+   /**Serial version UID*/
+   private static final long serialVersionUID = -7463658256795280905L;
+
+   /**Log instance*/
+   private static Logger log = Logger.getLogger(XAResourceWrapperImpl.class);
+   
+   /** The xaResource */
+   private XAResource xaResource;
+   
+   /**Pad*/
+   private boolean pad;
+
+   /**Override Rm Value*/
+   private Boolean overrideRmValue;
+
+   /**Product name*/
+   private String productName;
+
+   /**Product version*/
+   private String productVersion;
+   
+   /**
+    * Creates a new wrapper instance.
+    * @param resource xaresource
+    */
+   public XAResourceWrapperImpl(XAResource resource)
+   {
+      this(resource, false, Boolean.FALSE, null, null);
+   }
+
+   /**
+    * Creates a new wrapper instance.
+    * @param resource xaresource
+    * @param pad pad
+    */   
+   public XAResourceWrapperImpl(XAResource resource, boolean pad)
+   {
+      this(resource, pad, Boolean.FALSE, null, null);
+   }
+
+   /**
+    * Creates a new wrapper instance.
+    * @param resource xaresource
+    * @param pad pad
+    * @param override override
+    */   
+   public XAResourceWrapperImpl(XAResource resource, boolean pad, Boolean override)
+   {
+      this(resource, pad, override, null, null);
+   }
+
+
+   /**
+    * Creates a new wrapper instance.
+    * @param resource xaresource
+    * @param pad pad
+    * @param override override
+    * @param productName product name
+    * @param productVersion product version
+    */   
+   public XAResourceWrapperImpl(XAResource resource, boolean pad, Boolean override, 
+         String productName, String productVersion)
+   {
+      this.overrideRmValue = override;
+      this.pad = pad;
+      this.xaResource = resource;
+      this.productName = productName;
+      this.productVersion = productVersion;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void commit(Xid xid, boolean onePhase) throws XAException
+   {
+      xid = convertXid(xid);
+      xaResource.commit(xid, onePhase);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void end(Xid xid, int flags) throws XAException
+   {
+      xid = convertXid(xid);
+      xaResource.end(xid, flags);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void forget(Xid xid) throws XAException
+   {
+      xid = convertXid(xid);
+      xaResource.forget(xid);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public int getTransactionTimeout() throws XAException
+   {
+      return xaResource.getTransactionTimeout();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean isSameRM(XAResource resource) throws XAException
+   {
+      if (overrideRmValue != null)
+      {
+         if (log.isTraceEnabled())
+         {
+            log.trace("Executing isSameRM with override value" + overrideRmValue + " for XAResourceWrapper" + this);
+         }
+         return overrideRmValue.booleanValue();
+      }
+      else
+      {
+         if (resource instanceof XAResourceWrapper)
+         {
+            XAResourceWrapper other = (XAResourceWrapper)resource;
+            return xaResource.isSameRM(other.getResource());
+         }
+         else
+         {
+            return xaResource.isSameRM(resource);
+         }
+         
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public int prepare(Xid xid) throws XAException
+   {
+      xid = convertXid(xid);
+      return xaResource.prepare(xid);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Xid[] recover(int flag) throws XAException
+   {
+      return xaResource.recover(flag);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void rollback(Xid xid) throws XAException
+   {
+      xid = convertXid(xid);      
+      xaResource.rollback(xid);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean setTransactionTimeout(int flag) throws XAException
+   {
+      return xaResource.setTransactionTimeout(flag);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void start(Xid xid, int flags) throws XAException
+   {
+      xid = convertXid(xid);
+      xaResource.start(xid, flags);
+   }
+
+   /**
+    * Get the XAResource that is being wrapped
+    * @return The XAResource
+    */
+   public XAResource getResource()
+   {
+      return xaResource;
+   }
+
+   /**
+    * Get product name
+    * @return Product name of the instance if defined; otherwise <code>null</code>
+    */
+   public String getProductName()
+   {
+      return productName;
+   }
+
+   /**
+    * Get product version
+    * @return Product version of the instance if defined; otherwise <code>null</code>
+    */
+   public String getProductVersion()
+   {
+      return productVersion;
+   }
+
+   /**
+    * Return wrapper for given xid.
+    * @param xid xid
+    * @return return wrapper
+    */
+   private Xid convertXid(Xid xid)
+   {
+      if (xid instanceof XidWrapper)
+         return xid;
+      else
+         return new XidWrapperImpl(pad, xid);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String toString()
+   {
+      return super.toString();
+   }
+}


Property changes on: projects/jboss-jca/trunk/core/src/main/java/org/jboss/jca/core/connectionmanager/xa/XAResourceWrapperImpl.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native




More information about the jboss-cvs-commits mailing list