FileDocCategorySizeDatePackage
PoolConnEntry.javaAPI DocApache James 2.3.113827Fri Jan 12 12:56:34 GMT 2007org.apache.james.util.mordred

PoolConnEntry.java

/****************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one   *
 * or more contributor license agreements.  See the NOTICE file *
 * distributed with this work for additional information        *
 * regarding copyright ownership.  The ASF licenses this file   *
 * to you under the Apache License, Version 2.0 (the            *
 * "License"); you may not use this file except in compliance   *
 * with the License.  You may obtain a copy of the License at   *
 *                                                              *
 *   http://www.apache.org/licenses/LICENSE-2.0                 *
 *                                                              *
 * Unless required by applicable law or agreed to in writing,   *
 * software distributed under the License is distributed on an  *
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
 * KIND, either express or implied.  See the License for the    *
 * specific language governing permissions and limitations      *
 * under the License.                                           *
 ****************************************************************/

package org.apache.james.util.mordred;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.util.Map;

/**
 * An entry in a connection pool.
 *
 */
public class PoolConnEntry implements java.sql.Connection{
    private static final boolean DEEP_DEBUG = false;

    // States for connections (in use, being tested, or active)
    public final static int     AVAILABLE = 0;
    public final static int     ACTIVE = 1;

    private JdbcDataSource      container;

    private Connection          connection;
    private int                 status;
    private long                lockTime;
    private long                createDate;
    private long                lastActivity;
    private int                 id;
    private java.lang.Throwable trace;

    /**
     * Insert the method's description here.
     * Creation date: (8/24/99 11:43:45 AM)
     * @param conn java.sql.Connection
     */
    public PoolConnEntry(JdbcDataSource container, Connection conn, int id) {
        this.container = container;
        this.connection = conn;
        status = AVAILABLE;
        createDate = System.currentTimeMillis();
        lastActivity = System.currentTimeMillis();
        this.id = id;
    }

    /**
     * Locks an entry for anybody else using it
     */
    public synchronized boolean lock() throws SQLException {
        if (DEEP_DEBUG) {
            System.out.println("Trying to lock");
        }

        if (status != PoolConnEntry.AVAILABLE) {
            return false;
        }

        if (DEEP_DEBUG) {
            System.out.println("Available");
        }

        if (false) {
            //There really is no sense in doing this...
            //  maybe make it a conf option at some point, but really slows
            //  down the pooling.
            if (connection.isClosed()) {
                throw new SQLException("Connection has been closed.");
            }

            if (DEEP_DEBUG) {
                System.out.println("not closed");
            }
        }


        status = PoolConnEntry.ACTIVE;
        lockTime = System.currentTimeMillis();
        lastActivity = lockTime;
        trace = new Throwable();
        clearWarnings();
        if (DEEP_DEBUG) {
            System.out.println("Returning");
        }
        return true;
    }

    /**
     * Resets flags on an entry for reuse in the pool
     */
    public synchronized void unlock() {
        lastActivity = System.currentTimeMillis();
        trace = null;
        status = AVAILABLE;
    }

    /**
     * Simple method to log any warnings on an entry (connection), and
     * then clear them.
     * @throws java.sql.SQLException
     */
    public void clearWarnings() {
        try {
            SQLWarning currSQLWarning = connection.getWarnings();
            while (currSQLWarning != null) {
                StringBuffer logBuffer =
                    new StringBuffer(256)
                            .append("Warnings on connection ")
                            .append(id)
                            .append(currSQLWarning);
                container.debug(logBuffer.toString());
                currSQLWarning = currSQLWarning.getNextWarning();
            }
            connection.clearWarnings();
        } catch (SQLException sqle) {
            container.debug("Error while clearing exceptions on " + id);
            // It will probably get killed by itself before too long if this failed
        }
    }


    /**
     * Insert the method's description here.
     * Creation date: (8/24/99 11:43:19 AM)
     * @return a long representing the time this entry was created
     */
    public long getCreateDate() {
        return createDate;
    }

    /**
     * Insert the method's description here.
     * Creation date: (8/24/99 12:09:01 PM)
     * @return int
     */
    public int getId() {
        return id;
    }

    /**
     * Insert the method's description here.
     * Creation date: (8/24/99 11:43:19 AM)
     * @return long
     */
    public long getLastActivity() {
        return lastActivity;
    }

    /**
     * Insert the method's description here.
     * Creation date: (8/24/99 11:43:19 AM)
     * @return long
     */
    public long getLockTime() {
        return lockTime;
    }

    /**
     * Insert the method's description here.
     * Creation date: (8/24/99 11:43:19 AM)
     * @return int
     */
    public int getStatus() {
        return status;
    }

    /**
     * Insert the method's description here.
     * Creation date: (8/24/99 2:33:38 PM)
     * @return java.lang.Throwable
     */
    public java.lang.Throwable getTrace() {
        return trace;
    }

    /**
     * Need to clean up the connection
     */
    protected void finalize() {
        container.debug("Closing connection " + id);
        try {
            connection.close();
        } catch (SQLException ex) {
            StringBuffer warnBuffer =
                new StringBuffer(64)
                    .append("Cannot close connection ")
                    .append(id)
                    .append(" on finalize");
            container.warn(warnBuffer.toString());
        }
        // Dump the stack trace of whoever created this connection
        if (getTrace() != null) {
            StringWriter sout = new StringWriter();
            trace.printStackTrace(new PrintWriter(sout, true));
            container.info(sout.toString());
        }
    }

    public String getString() {
        StringBuffer poolConnStringBuffer =
            new StringBuffer(64)
                    .append(getId())
                    .append(": ")
                    .append(connection.toString());
        return poolConnStringBuffer.toString();
    }


    /*
     * New approach now actually has this implement a connection, as a wrapper.
     * All calls will be passed to underlying connection.
     * Except when closed is called, which will instead cause the releaseConnection on
     * the parent to be executed.
     *
     * These are the methods from java.sql.Connection
     */

    public void close() throws SQLException {
        clearWarnings();
        container.releaseConnection(this);
    }

    /**
     * Returns whether this entry is closed.
     *
     * @return whether the underlying conntection is closed
     */
    public boolean isClosed() throws SQLException {
        return connection.isClosed();
    }


    public final Statement createStatement() throws SQLException {
        return connection.createStatement();
    }

    public final PreparedStatement prepareStatement(final String sql) throws SQLException {
        return connection.prepareStatement(sql);
    }

    public final CallableStatement prepareCall(final String sql) throws SQLException {
        return connection.prepareCall(sql);
    }

    public final String nativeSQL(final String sql) throws SQLException {
        return connection.nativeSQL( sql );
    }

    public final void setAutoCommit(final boolean autoCommit) throws SQLException {
        connection.setAutoCommit( autoCommit );
    }

    public final boolean getAutoCommit() throws SQLException {
        return connection.getAutoCommit();
    }

    public final void commit() throws SQLException {
        connection.commit();
    }

    public final void rollback() throws SQLException {
        connection.rollback();
    }

    public final DatabaseMetaData getMetaData() throws SQLException {
        return connection.getMetaData();
    }

    public final void setReadOnly( final boolean readOnly ) throws SQLException {
        connection.setReadOnly( readOnly );
    }

    public final boolean isReadOnly() throws SQLException {
        return connection.isReadOnly();
    }

    public final void setCatalog( final String catalog ) throws SQLException {
        connection.setCatalog( catalog );
    }

    public final String getCatalog() throws SQLException {
        return connection.getCatalog();
    }

    public final void setTransactionIsolation( final int level ) throws SQLException {
        connection.setTransactionIsolation(level);
    }

    public final int getTransactionIsolation() throws SQLException {
        return connection.getTransactionIsolation();
    }

    public final SQLWarning getWarnings() throws SQLException {
        return connection.getWarnings();
    }

    public final Statement createStatement( final int resultSetType,
                                            final int resultSetConcurrency )
            throws SQLException {
        return connection.createStatement(resultSetType, resultSetConcurrency);
    }

    public final PreparedStatement prepareStatement( final String sql,
                                               final int resultSetType,
                                               final int resultSetConcurrency )
            throws SQLException {
        return connection.prepareStatement( sql, resultSetType, resultSetConcurrency);
    }

    public final CallableStatement prepareCall( final String sql,
                                          final int resultSetType,
                                          final int resultSetConcurrency )
            throws SQLException {
        return connection.prepareCall( sql, resultSetType, resultSetConcurrency );
    }

    public final Map getTypeMap() throws SQLException {
        return connection.getTypeMap();
    }

    public final void setTypeMap( final Map map ) throws SQLException {
        connection.setTypeMap( map );
    }

    /*-- JDBC_3_ANT_KEY */
    public final void setHoldability(int holdability)
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }

    public final int getHoldability()
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }

    public final java.sql.Savepoint setSavepoint()
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }

    public final java.sql.Savepoint setSavepoint(String savepoint)
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }

    public final void rollback(java.sql.Savepoint savepoint)
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }

    public final void releaseSavepoint(java.sql.Savepoint savepoint)
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }

    public final Statement createStatement(int resulSetType,
                                           int resultSetConcurrency,
                                           int resultSetHoldability)
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }

    public final PreparedStatement prepareStatement(String sql,
                                        int resulSetType,
                                        int resultSetConcurrency,
                                        int resultSetHoldability)
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }

    public final CallableStatement prepareCall(String sql,
                                        int resulSetType,
                                        int resultSetConcurrency,
                                        int resultSetHoldability)
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }

    public final PreparedStatement prepareStatement(String sql,
                                        int autoGeneratedKeys)
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }

    public final PreparedStatement prepareStatement(String sql,
                                        int[] columnIndexes)
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }

    public final PreparedStatement prepareStatement(String sql,
                                        String[] columnNames)
        throws SQLException
    {
        throw new SQLException("This is not a Jdbc 3.0 Compliant Connection");
    }
    /* JDBC_3_ANT_KEY --*/

}