FileDocCategorySizeDatePackage
BaseWrapperManagedConnection.javaAPI DocJBoss 4.2.119105Fri Jul 13 21:01:14 BST 2007org.jboss.resource.adapter.jdbc

BaseWrapperManagedConnection

public abstract class BaseWrapperManagedConnection extends Object implements javax.resource.spi.ManagedConnection
BaseWrapperManagedConnection
author
David Jencks
author
Adrian Brock
version
$Revision: 57189 $

Fields Summary
protected final BaseWrapperManagedConnectionFactory
mcf
protected final Connection
con
protected final Properties
props
private final int
transactionIsolation
private final boolean
readOnly
private final Collection
cels
private final Set
handles
private PreparedStatementCache
psCache
protected final Object
stateLock
protected boolean
inManagedTransaction
protected EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean
inLocalTransaction
protected boolean
jdbcAutoCommit
protected boolean
underlyingAutoCommit
protected boolean
jdbcReadOnly
protected boolean
underlyingReadOnly
protected int
jdbcTransactionIsolation
protected boolean
destroyed
Constructors Summary
public BaseWrapperManagedConnection(BaseWrapperManagedConnectionFactory mcf, Connection con, Properties props, int transactionIsolation, int psCacheSize)


       
                                    
                                    
                                    
                                    
       
   
      this.mcf = mcf;
      this.con = con;
      this.props = props;
      if (psCacheSize > 0)
          psCache = new PreparedStatementCache(psCacheSize);

      if (transactionIsolation == -1)
         this.transactionIsolation = con.getTransactionIsolation();
      else
      {
         this.transactionIsolation = transactionIsolation;
         con.setTransactionIsolation(transactionIsolation);
      }

      readOnly = con.isReadOnly();

      if (mcf.getNewConnectionSQL() != null)
      {
         Statement s = con.createStatement();
         try
         {
            s.execute(mcf.getNewConnectionSQL());
         }
         finally
         {
            s.close();
         }
      }

      underlyingReadOnly = readOnly;
      jdbcReadOnly = readOnly;
      jdbcTransactionIsolation = this.transactionIsolation;
   
Methods Summary
public voidaddConnectionEventListener(javax.resource.spi.ConnectionEventListener cel)

      synchronized (cels)
      {
         cels.add(cel);
      }
   
public voidassociateConnection(java.lang.Object handle)

      if (!(handle instanceof WrappedConnection))
         throw new JBossResourceException("Wrong kind of connection handle to associate" + handle);
      ((WrappedConnection)handle).setManagedConnection(this);
      synchronized(handles)
      {
         handles.add(handle);
      }
   
protected voidbroadcastConnectionError(java.lang.Throwable e)

      synchronized (stateLock)
      {
         if (destroyed)
         {
            Logger log = getLog();
            if (log.isTraceEnabled())
               log.trace("Not broadcasting error, already destroyed " + this, e);
            return;
         }
      }
      
      Exception ex = null;
      if (e instanceof Exception)
         ex = (Exception) e;
      else
         ex = new ResourceAdapterInternalException("Unexpected error", e);
      ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.CONNECTION_ERROR_OCCURRED, ex);
      Collection copy = null;
      synchronized(cels)
      {
         copy = new ArrayList(cels);
      }
      for (Iterator i = copy.iterator(); i.hasNext(); )
      {
         ConnectionEventListener cel = (ConnectionEventListener)i.next();
         try
         {
            cel.connectionErrorOccurred(ce);
         }
         catch (Throwable t)
         {
            getLog().warn("Error notifying of connection error for listener: " + cel, t);
         }
      }
   
booleancanUse(CachedPreparedStatement cachedps)

      // Nobody is using it so we are ok
      if (cachedps.isInUse() == false)
         return true;
      
      // Cannot reuse prepared statements in auto commit mode
      // if will close the previous usage of the PS
      if (underlyingAutoCommit == true)
         return false;
      
      // We have been told not to share
      return mcf.sharePS;
   
protected voidcheckException(java.sql.SQLException e)

      connectionError(e);
      throw new JBossResourceException("SQLException", e);
   
private voidcheckIdentity(javax.security.auth.Subject subject, javax.resource.spi.ConnectionRequestInfo cri)

      Properties newProps = mcf.getConnectionProperties(subject, cri);
      if (!props.equals(newProps))
      {
         throw new JBossResourceException("Wrong credentials passed to getConnection!");
      } // end of if ()
   
protected voidcheckState()

      synchronized (stateLock)
      {
         // Check readonly
         if (jdbcReadOnly != underlyingReadOnly)
         {
            con.setReadOnly(jdbcReadOnly);
            underlyingReadOnly = jdbcReadOnly;
         }
      }
   
voidcheckTransaction()
The checkTransaction method makes sure the adapter follows the JCA autocommit contract, namely all statements executed outside a container managed transaction or a component managed transaction should be autocommitted. To avoid continually calling setAutocommit(enable) before and after container managed transactions, we keep track of the state and check it before each transactional method call.

      synchronized (stateLock)
      {
         if (inManagedTransaction)
            return;

         // Check autocommit
         if (jdbcAutoCommit != underlyingAutoCommit)
         {
            con.setAutoCommit(jdbcAutoCommit);
            underlyingAutoCommit = jdbcAutoCommit;
         }
      }

      if (jdbcAutoCommit == false && inLocalTransaction.set(true) == false)
      {
         ArrayList copy;
         synchronized(cels)
         {
            copy = new ArrayList(cels);
         }
         ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_STARTED);
         for (int i = 0; i < copy.size(); ++i)
         {
            ConnectionEventListener cel = (ConnectionEventListener) copy.get(i);
            try
            {
               cel.localTransactionStarted(ce);
            }
            catch (Throwable t)
            {
               getLog().trace("Error notifying of connection committed for listener: " + cel, t);
            }
         }
      }
      
      checkState();
   
public booleancheckValid()

      SQLException e = mcf.isValidConnection(con);

      if (e == null)
         // It's ok
         return true;
      else
      {
         getLog().warn("Destroying connection that is not valid, due to the following exception: " + con, e);
         broadcastConnectionError(e);
         return false;
      }
   
public voidcleanup()

      synchronized (handles)
      {
         for (Iterator i = handles.iterator(); i.hasNext(); )
         {
            WrappedConnection lc = (WrappedConnection)i.next();
            lc.setManagedConnection(null);
         }
         handles.clear();
      }
      //reset all the properties we know about to defaults.
      synchronized (stateLock)
      {
         jdbcAutoCommit = true;
         jdbcReadOnly = readOnly;
         if (jdbcTransactionIsolation != transactionIsolation)
         {
            try
            {
               con.setTransactionIsolation(jdbcTransactionIsolation);
               jdbcTransactionIsolation = transactionIsolation;
            }
            catch (SQLException e)
            {
               mcf.log.warn("Error resetting transaction isolation ", e);
            }
         }
      }
   
voidcloseHandle(WrappedConnection handle)

      synchronized (stateLock)
      {
         if (destroyed)
            return;
      }

      synchronized(handles)
      {
         handles.remove(handle);
      }
      ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.CONNECTION_CLOSED);
      ce.setConnectionHandle(handle);
      Collection copy = null;
      synchronized(cels)
      {
         copy = new ArrayList(cels);
      }
      for (Iterator i = copy.iterator(); i.hasNext(); )
      {
         ConnectionEventListener cel = (ConnectionEventListener)i.next();
         cel.connectionClosed(ce);
      }
   
voidconnectionError(java.lang.Throwable t)

      if (t instanceof SQLException == false || mcf.isExceptionFatal((SQLException) t))
         broadcastConnectionError(t);
   
public voiddestroy()

      synchronized (stateLock)
      {
         destroyed = true;
      }

      cleanup();
      try
      {
         con.close();
      }
      catch (SQLException ignored)
      {
         getLog().trace("Ignored error during close: ", ignored);
      }
   
java.sql.CallableStatementdoPrepareCall(java.lang.String sql, int resultSetType, int resultSetConcurrency)

      return con.prepareCall(sql, resultSetType, resultSetConcurrency);
   
java.sql.PreparedStatementdoPrepareStatement(java.lang.String sql, int resultSetType, int resultSetConcurrency)

      return con.prepareStatement(sql, resultSetType, resultSetConcurrency);
   
java.sql.ConnectiongetConnection()

      if (con == null)
         throw new SQLException("Connection has been destroyed!!!");
      return con;
   
public java.lang.ObjectgetConnection(javax.security.auth.Subject subject, javax.resource.spi.ConnectionRequestInfo cri)

      checkIdentity(subject, cri);
      WrappedConnection lc =  new WrappedConnection(this);
      synchronized (handles)
      {
         handles.add(lc);
      }
      return lc;
   
intgetJdbcTransactionIsolation()

      return jdbcTransactionIsolation;
   
protected org.jboss.logging.LoggergetLog()

      return mcf.log;
   
public java.io.PrintWritergetLogWriter()

      // TODO: implement this javax.resource.spi.ManagedConnection method
      return null;
   
public javax.resource.spi.ManagedConnectionMetaDatagetMetaData()

      // TODO: implement this javax.resource.spi.ManagedConnection method
      return null;
   
intgetQueryTimeout()

      return mcf.getQueryTimeout();
   
intgetTrackStatements()

      return mcf.trackStatements;
   
booleanisJdbcAutoCommit()

      return inManagedTransaction? false: jdbcAutoCommit;
   
booleanisJdbcReadOnly()

      return jdbcReadOnly;
   
booleanisTransactionQueryTimeout()

      return mcf.isTransactionQueryTimeout;
   
voidjdbcCommit()

      synchronized (stateLock)
      {
         if (inManagedTransaction)
            throw new SQLException("You cannot commit during a managed transaction!");
         if (jdbcAutoCommit)
            throw new SQLException("You cannot commit with autocommit set!");
      }
      con.commit();

      if (inLocalTransaction.set(false))
      {
         ArrayList copy;
         synchronized(cels)
         {
            copy = new ArrayList(cels);
         }
         ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_COMMITTED);
         for (int i = 0; i < copy.size(); ++i)
         {
            ConnectionEventListener cel = (ConnectionEventListener) copy.get(i);
            try
            {
               cel.localTransactionCommitted(ce);
            }
            catch (Throwable t)
            {
               getLog().trace("Error notifying of connection committed for listener: " + cel, t);
            }
         }
      }
   
voidjdbcRollback()

      synchronized (stateLock)
      {
         if (inManagedTransaction)
            throw new SQLException("You cannot rollback during a managed transaction!");
         if (jdbcAutoCommit)
            throw new SQLException("You cannot rollback with autocommit set!");
      }
      con.rollback();

      if (inLocalTransaction.set(false))
      {
         ArrayList copy;
         synchronized(cels)
         {
            copy = new ArrayList(cels);
         }
         ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK);
         for (int i = 0; i < copy.size(); ++i)
         {
            ConnectionEventListener cel = (ConnectionEventListener) copy.get(i);
            try
            {
               cel.localTransactionRolledback(ce);
            }
            catch (Throwable t)
            {
               getLog().trace("Error notifying of connection rollback for listener: " + cel, t);
            }
         }
      }
   
voidjdbcRollback(java.sql.Savepoint savepoint)

      synchronized (stateLock)
      {
         if (inManagedTransaction)
            throw new SQLException("You cannot rollback during a managed transaction!");
         if (jdbcAutoCommit)
            throw new SQLException("You cannot rollback with autocommit set!");
      }
      con.rollback(savepoint);
   
java.sql.CallableStatementprepareCall(java.lang.String sql, int resultSetType, int resultSetConcurrency)

      if (psCache != null)
      {
         PreparedStatementCache.Key key = new PreparedStatementCache.Key(sql, PreparedStatementCache.Key.CALLABLE_STATEMENT, resultSetType, resultSetConcurrency);
         CachedCallableStatement cachedps = (CachedCallableStatement)psCache.get(key);
         if (cachedps != null)
         {
            if (canUse(cachedps))
               cachedps.inUse();
            else
               return doPrepareCall(sql, resultSetType, resultSetConcurrency);
         }
         else
         {
            CallableStatement cs = doPrepareCall(sql, resultSetType, resultSetConcurrency);
            cachedps = new CachedCallableStatement(cs);
            psCache.insert(key, cachedps);
         }
         return cachedps;
      }
      else
         return doPrepareCall(sql, resultSetType, resultSetConcurrency);
   
java.sql.PreparedStatementprepareStatement(java.lang.String sql, int resultSetType, int resultSetConcurrency)

      if (psCache != null)
      {
         PreparedStatementCache.Key key = new PreparedStatementCache.Key(sql, PreparedStatementCache.Key.PREPARED_STATEMENT, resultSetType, resultSetConcurrency);
         CachedPreparedStatement cachedps = (CachedPreparedStatement) psCache.get(key);
         if (cachedps != null)
         {
            if (canUse(cachedps))
               cachedps.inUse();
            else
               return doPrepareStatement(sql, resultSetType, resultSetConcurrency);
         }
         else
         {
            PreparedStatement ps = doPrepareStatement(sql, resultSetType, resultSetConcurrency);
            cachedps = new CachedPreparedStatement(ps);
            psCache.insert(key, cachedps);
         }
         return cachedps;
      }
      else
         return doPrepareStatement(sql, resultSetType, resultSetConcurrency);
   
public voidremoveConnectionEventListener(javax.resource.spi.ConnectionEventListener cel)

      synchronized (cels)
      {
         cels.remove(cel);
      }
   
voidsetJdbcAutoCommit(boolean jdbcAutoCommit)

      synchronized (stateLock)
      {
         if (inManagedTransaction)
            throw new SQLException("You cannot set autocommit during a managed transaction!");
         this.jdbcAutoCommit = jdbcAutoCommit;
      }

      if (jdbcAutoCommit && inLocalTransaction.set(false))
      {
         ArrayList copy;
         synchronized(cels)
         {
            copy = new ArrayList(cels);
         }
         ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_COMMITTED);
         for (int i = 0; i < copy.size(); ++i)
         {
            ConnectionEventListener cel = (ConnectionEventListener) copy.get(i);
            try
            {
               cel.localTransactionCommitted(ce);
            }
            catch (Throwable t)
            {
               getLog().trace("Error notifying of connection committed for listener: " + cel, t);
            }
         }
      }
   
voidsetJdbcReadOnly(boolean readOnly)

      synchronized (stateLock)
      {
         if (inManagedTransaction)
            throw new SQLException("You cannot set read only during a managed transaction!");
         this.jdbcReadOnly = readOnly;
      }
   
voidsetJdbcTransactionIsolation(int isolationLevel)

      synchronized (stateLock)
      {
         this.jdbcTransactionIsolation = isolationLevel;
         con.setTransactionIsolation(jdbcTransactionIsolation);
      }
   
public voidsetLogWriter(java.io.PrintWriter param1)

      // TODO: implement this javax.resource.spi.ManagedConnection method