Package org.apache.commons.dbcp.cpdsadapter

Source Code of org.apache.commons.dbcp.cpdsadapter.PooledConnectionImpl$PStmtKey

package org.apache.commons.dbcp.cpdsadapter;

/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
*    "Apache Turbine" must not be used to endorse or promote products
*    derived from this software without prior written permission. For
*    written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
*    "Apache Turbine", nor may "Apache" appear in their name, without
*    prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/

import java.util.Map;
import java.util.Iterator;
import java.util.EventObject;
import java.util.Vector;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.CallableStatement;
import java.sql.Statement;
import java.sql.SQLWarning;
import java.sql.SQLException;
import javax.sql.ConnectionEvent;
import javax.sql.ConnectionEventListener;
import javax.sql.PooledConnection;

import org.apache.commons.dbcp.*;
import org.apache.commons.pool.KeyedObjectPool;
import org.apache.commons.pool.KeyedPoolableObjectFactory;

/**
* Implementation of PooledConnection that is returned by
* PooledConnectionDataSource.
*
* @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
* @version $Id: PooledConnectionImpl.java,v 1.1 2002/08/05 06:42:01 jmcnally Exp $
*/
class PooledConnectionImpl
    implements PooledConnection, KeyedPoolableObjectFactory
{
    private static final String CLOSED =
        "Attempted to use PooledConnection after closed() was called.";

    /**
     * The JDBC database connection that represents the physical db connection.
     */
    private Connection connection = null;

    /**
     * The JDBC database logical connection.
     */
    private Connection logicalConnection = null;

    /**
     * ConnectionEventListeners
     */
    private Vector eventListeners;

    /**
     * flag set to true, once close() is called.
     */
    boolean isClosed;

    /** My pool of {*link PreparedStatement}s. */
    protected KeyedObjectPool pstmtPool = null;


    /**
     * Wrap the real connection.
     */
    PooledConnectionImpl(Connection connection, KeyedObjectPool pool)
    {
        this.connection = connection;
        eventListeners = new Vector();
        isClosed = false;
        if (pool != null)
        {
            pstmtPool = pool;
            pstmtPool.setFactory(this);           
        }
    }

    /**
     * Add an event listener.
     */
    public void addConnectionEventListener(ConnectionEventListener listener)
    {
        if ( !eventListeners.contains(listener) )
        {
            eventListeners.add(listener);
        }
    }

    /**
     * Closes the physical connection and marks this
     * <code>PooledConnection</code> so that it may not be used
     * to generate any more logical <code>Connection</code>s.
     *
     * @exception SQLException if an error occurs
     */
    public void close()
        throws SQLException
    {       
        isClosed = true;
        if (pstmtPool != null)
        {
            try
            {
                try
                {
                    pstmtPool.close();
                }
                finally
                {
                    pstmtPool = null;
                    connection.close();
                }
            }
            catch (Exception e)
            {
                if (e instanceof RuntimeException)
                {
                    throw (RuntimeException)e;
                }
                else
                {
                    throw new SQLException(e.getMessage());
                }
            }
        }
    }

    /**
     * Throws an SQLException, if isClosed() is true
     */
    private void assertOpen()
        throws SQLException
    {
        if ( isClosed )
        {
            throw new SQLException(CLOSED);
        }
    }

    /**
     * Returns a JDBC connection.
     *
     * @return The database connection.
     */
    public Connection getConnection()
        throws SQLException
    {
        assertOpen();
        // make sure the last connection is marked as closed
        if ( logicalConnection != null && !logicalConnection.isClosed() )
        {
            // should notify pool of error so the pooled connection can
            // be removed !FIXME!
            throw new SQLException("PooledConnection was reused, without" +
                                   "its previous Connection being closed.");
        }

        // the spec requires that this return a new Connection instance.
        logicalConnection = new ConnectionImpl(this, connection);
        return logicalConnection;
    }

    /**
     * Remove an event listener.
     */
    public void removeConnectionEventListener(ConnectionEventListener listener)
    {
        eventListeners.remove(listener);
    }

    /**
     * Closes the physical connection and checks that the logical connection
     * was closed as well.
     */
    protected void finalize()
        throws Throwable
    {
        // Closing the Connection ensures that if anyone tries to use it,
        // an error will occur.
        try
        {
            connection.close();
        }
        catch (Exception ignored)
        {
        }

        // make sure the last connection is marked as closed
        if ( logicalConnection != null && !logicalConnection.isClosed() )
        {
            throw new SQLException("PooledConnection was gc'ed, without" +
                                   "its last Connection being closed.");
        }       
    }

    /**
     * sends a connectionClosed event.
     */
    void notifyListeners()
    {
        ConnectionEvent event = new ConnectionEvent(this);
        Iterator i = eventListeners.iterator();
        while ( i.hasNext() )
        {
            ((ConnectionEventListener)i.next()).connectionClosed(event);
        }
    }

    // -------------------------------------------------------------------
    // The following code implements a PreparedStatement pool

    /**
     * Create or obtain a {*link PreparedStatement} from my pool.
     * @return a {*link PoolablePreparedStatement}
     */
    PreparedStatement prepareStatement(String sql)
        throws SQLException
    {
        if (pstmtPool == null)
        {
            return connection.prepareStatement(sql);
        }
        else
        {
            try {
                return (PreparedStatement)
                    pstmtPool.borrowObject(createKey(sql));
            } catch(RuntimeException e) {
                throw e;
            } catch(Exception e) {
                throw new SQLException(e.toString());
            }
        }
    }

    /**
     * Create or obtain a {*link PreparedStatement} from my pool.
     * @return a {*link PoolablePreparedStatement}
     */
    PreparedStatement prepareStatement(String sql, int resultSetType,
                                       int resultSetConcurrency)
        throws SQLException
    {
        if (pstmtPool == null)
        {
            return connection.prepareStatement(sql);
        }
        else
        {
            try {
                return (PreparedStatement) pstmtPool.borrowObject(
                    createKey(sql,resultSetType,resultSetConcurrency));
            } catch(RuntimeException e) {
                throw e;
            } catch(Exception e) {
                throw new SQLException(e.toString());
            }
        }
    }

    /**
     * Create a {*link PooledConnectionImpl.PStmtKey} for the given arguments.
     */
    protected Object createKey(String sql, int resultSetType,
                               int resultSetConcurrency) {
        return new PStmtKey(normalizeSQL(sql), resultSetType,
                            resultSetConcurrency);
    }

    /**
     * Create a {*link PooledConnectionImpl.PStmtKey} for the given arguments.
     */
    protected Object createKey(String sql) {
        return new PStmtKey(normalizeSQL(sql));
    }

    /**
     * Normalize the given SQL statement, producing a
     * cannonical form that is semantically equivalent to the original.
     */
    protected String normalizeSQL(String sql) {
        return sql.trim();
    }

    /**
     * My {*link KeyedPoolableObjectFactory} method for creating
     * {*link PreparedStatement}s.
     * @param obj the key for the {*link PreparedStatement} to be created
     */
    public Object makeObject(Object obj) {
        try {
            if(null == obj || !(obj instanceof PStmtKey)) {
                throw new IllegalArgumentException();
            } else {
                // _openPstmts++;
                PStmtKey key = (PStmtKey)obj;
                if(null == key._resultSetType && null ==
                   key._resultSetConcurrency)
                {
                    return new PoolablePreparedStatementStub(
                        connection.prepareStatement(key._sql),
                        key, pstmtPool, connection);
                } else {
                    return new PoolablePreparedStatementStub(
                        connection.prepareStatement(key._sql,
                        key._resultSetType.intValue(),
                        key._resultSetConcurrency.intValue()),
                        key, pstmtPool, connection);
                }
            }
        } catch(Exception e) {
            throw new RuntimeException(e.toString());
        }
    }

    /**
     * My {*link KeyedPoolableObjectFactory} method for destroying
     * {*link PreparedStatement}s.
     * @param key ignored
     * @param obj the {*link PreparedStatement} to be destroyed.
     */
    public void destroyObject(Object key, Object obj) {
        //_openPstmts--;
        try {
            ((DelegatingPreparedStatement)obj).getInnermostDelegate().close();
        } catch(SQLException e) {
            // ignored
        } catch(NullPointerException e) {
            // ignored
        } catch(ClassCastException e) {
            try {
                ((PreparedStatement)obj).close();
            } catch(SQLException e2) {
                // ignored
            } catch(ClassCastException e2) {
                // ignored
            }
        }
    }

    /**
     * My {*link KeyedPoolableObjectFactory} method for validating
     * {*link PreparedStatement}s.
     * @param key ignored
     * @param obj ignored
     * @return <tt>true</tt>
     */
    public boolean validateObject(Object key, Object obj) {
        return true;
    }

    /**
     * My {*link KeyedPoolableObjectFactory} method for activating
     * {*link PreparedStatement}s.
     * @param key ignored
     * @param obj ignored
     */
    public void activateObject(Object key, Object obj) {
        ((PoolablePreparedStatementStub)obj).activate();
    }

    /**
     * My {*link KeyedPoolableObjectFactory} method for passivating
     * {*link PreparedStatement}s.  Currently invokes {*link PreparedStatement#clearParameters}.
     * @param key ignored
     * @param obj a {*link PreparedStatement}
     */
    public void passivateObject(Object key, Object obj) {
        try {
            ((PreparedStatement)obj).clearParameters();
            ((PoolablePreparedStatementStub)obj).passivate();
        } catch(SQLException e) {
            // ignored
        } catch(NullPointerException e) {
            // ignored
        } catch(ClassCastException e) {
            // ignored
        }
    }

    /**
     * A key uniquely identifying {*link PreparedStatement}s.
     */
    class PStmtKey {
        protected String _sql = null;
        protected Integer _resultSetType = null;
        protected Integer _resultSetConcurrency = null;

        PStmtKey(String sql) {
            _sql = sql;
        }

        PStmtKey(String sql, int resultSetType, int resultSetConcurrency) {
            _sql = sql;
            _resultSetType = new Integer(resultSetType);
            _resultSetConcurrency = new Integer(resultSetConcurrency);
        }

        public boolean equals(Object that) {
            try {
                PStmtKey key = (PStmtKey)that;
                return( ((null == _sql && null == key._sql) || _sql.equals(key._sql)) &&
                        ((null == _resultSetType && null == key._resultSetType) || _resultSetType.equals(key._resultSetType)) &&
                        ((null == _resultSetConcurrency && null == key._resultSetConcurrency) || _resultSetConcurrency.equals(key._resultSetConcurrency))
                      );
            } catch(ClassCastException e) {
                return false;
            } catch(NullPointerException e) {
                return false;
            }
        }

        public int hashCode() {
            return(null == _sql ? 0 : _sql.hashCode());
        }

        public String toString() {
            StringBuffer buf = new StringBuffer();
            buf.append("PStmtKey: sql=");
            buf.append(_sql);
            buf.append(", resultSetType=");
            buf.append(_resultSetType);
            buf.append(", resultSetConcurrency=");
            buf.append(_resultSetConcurrency);
            return buf.toString();
        }
    }
}
TOP

Related Classes of org.apache.commons.dbcp.cpdsadapter.PooledConnectionImpl$PStmtKey

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