All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.gjc.spi.base.ConnectionHolder Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
// Portions Copyright [2018-2021] Payara Foundation and/or affiliates

package com.sun.gjc.spi.base;

import com.sun.enterprise.util.i18n.StringManager;
import com.sun.gjc.common.DataSourceObjectBuilder;
import com.sun.gjc.spi.ManagedConnectionImpl;
import com.sun.gjc.util.MethodExecutor;
import com.sun.logging.LogDomains;

import jakarta.resource.ResourceException;
import java.sql.*;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Holds the java.sql.Connection object, which is to be
 * passed to the application program.
 *
 * @author Binod P.G
 * @version 1.0, 02/07/23
 */
public abstract class ConnectionHolder implements Connection {

    private static final Logger _logger = LogDomains.getLogger(ManagedConnectionImpl.class, LogDomains.RSR_LOGGER);
    protected Connection con;

    protected ManagedConnectionImpl mc;

    protected boolean wrappedAlready = false;

    protected boolean isClosed = false;

    protected boolean valid = true;

    protected boolean active = false;

    private jakarta.resource.spi.LazyAssociatableConnectionManager lazyAssocCm_;
    private jakarta.resource.spi.LazyEnlistableConnectionManager lazyEnlistCm_;

    private jakarta.resource.spi.ConnectionRequestInfo cxReqInfo_;

    private jakarta.resource.spi.ManagedConnectionFactory mcf_;

    protected int statementTimeout;
    protected boolean statementTimeoutEnabled;


    private MethodExecutor executor = null;

    public static enum ConnectionType {
        LAZY_ENLISTABLE, LAZY_ASSOCIATABLE, STANDARD
    }

    private ConnectionType myType_ = ConnectionType.STANDARD;

    /**
     * The active flag is false when the connection handle is
     * created. When a method is invoked on this object, it asks
     * the ManagedConnection if it can be the active connection
     * handle out of the multiple connection handles. If the
     * ManagedConnection reports that this connection handle
     * can be active by setting this flag to true via the setActive
     * function, the above method invocation succeeds; otherwise
     * an exception is thrown.
     */

    protected final static StringManager sm = StringManager.getManager(
            DataSourceObjectBuilder.class);


    /**
     * Constructs a Connection holder.
     *
     * @param con java.sql.Connection object.
     */
    public ConnectionHolder(Connection con, ManagedConnectionImpl mc,
                            jakarta.resource.spi.ConnectionRequestInfo cxRequestInfo) {
        this.con = con;
        this.mc = mc;
        mcf_ = mc.getMcf();
        cxReqInfo_ = cxRequestInfo;
        statementTimeout = mc.getStatementTimeout();
        executor = new MethodExecutor();
        if (statementTimeout > 0) {
            statementTimeoutEnabled = true;
        }
    }

    /**
     * Returns the actual connection in this holder object.
     *
     * @return Connection object.
     * @throws java.sql.SQLException
     */
    public Connection getConnection() throws SQLException {
        //To ensure that the actual connection is always returned and not a proxy
        return con.unwrap(java.sql.Connection.class);
    }

    /**
     * Sets the flag to indicate that, the connection is wrapped already or not.
     *
     * @param wrapFlag
     */
    public void wrapped(boolean wrapFlag) {
        this.wrappedAlready = wrapFlag;
    }

    /**
     * Returns whether it is wrapped already or not.
     *
     * @return wrapped flag.
     */
    public boolean isWrapped() {
        return wrappedAlready;
    }

    /**
     * Returns the ManagedConnection instance responsible
     * for this connection.
     *
     * @return ManagedConnection instance.
     */
    public ManagedConnectionImpl getManagedConnection() {
        return mc;
    }

    /**
     * Replace the actual java.sql.Connection object with the one
     * supplied. Also replace ManagedConnection link.
     *
     * @param con Connection object.
     * @param mc   ManagedConnection object.
     */
    public void associateConnection(Connection con, ManagedConnectionImpl mc) {
        this.mc = mc;
        this.con = con;
    }

    /**
     * Dis-associate ManagedConnection and actual-connection from this user connection.
     * Used when lazy-connection-association is ON.
     */
    public void dissociateConnection() {
        this.mc = null;
        this.con = null;
    }

    /**
     * Clears all warnings reported for the underlying connection  object.
     *
     * @throws SQLException In case of a database error.
     */
    @Override
    public void clearWarnings() throws SQLException {
        checkValidity();
        con.clearWarnings();
    }

    /**
     * Closes the logical connection.
     *
     * @throws SQLException In case of a database error.
     */
    @Override
    public void close() throws SQLException {
        if (isClosed) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "jdbc.duplicate_close_connection", this);
            }
            return;
        }

        isClosed = true;
        if (mc != null) {
            //mc might be null if this is a lazyAssociatable connection
            //and has not been associated yet or has been disassociated
            mc.connectionClosed(null, this);
        }
    }

    /**
     * Invalidates this object.
     */
    public void invalidate() {
        valid = false;
    }

    /**
     * Closes the physical connection involved in this.
     *
     * @throws SQLException In case of a database error.
     */
    void actualClose() throws SQLException {
        con.close();
    }

    /**
     * Commit the changes in the underlying Connection.
     *
     * @throws SQLException In case of a database error.
     */
    @Override
    public void commit() throws SQLException {
        checkValidity();
        con.commit();
    }

    /**
     * Creates a statement from the underlying Connection
     *
     * @return Statement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public Statement createStatement() throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        Statement stmt = con.createStatement();
        if (statementTimeoutEnabled) {
            try {
                stmt.setQueryTimeout(statementTimeout);
            } catch (SQLException ex) {
                stmt.close();
            }
        }
        return stmt;
    }

    /**
     * Creates a statement from the underlying Connection.
     *
     * @param resultSetType        Type of the ResultSet
     * @param resultSetConcurrency ResultSet Concurrency.
     * @return Statement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        Statement stmt = con.createStatement(resultSetType, resultSetConcurrency);
        if (statementTimeoutEnabled) {
            try {
                stmt.setQueryTimeout(statementTimeout);
            } catch (SQLException ex) {
                stmt.close();
            }
        }
        return stmt;
    }

    /**
     * Creates a statement from the underlying Connection.
     *
     * @param resultSetType        Type of the ResultSet
     * @param resultSetConcurrency ResultSet Concurrency.
     * @param resultSetHoldability ResultSet Holdability.
     * @return Statement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency,
                                     int resultSetHoldability) throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        Statement stmt = con.createStatement(resultSetType, resultSetConcurrency,
                resultSetHoldability);
        if (statementTimeoutEnabled) {
            try {
                stmt.setQueryTimeout(statementTimeout);
            } catch (SQLException ex) {
                stmt.close();
            }
        }
        return stmt;
    }

    /**
     * Retrieves the current auto-commit mode for the underlying  Connection.
     *
     * @return The current state of connection's auto-commit mode.
     * @throws SQLException In case of a database error.
     */
    @Override
    public boolean getAutoCommit() throws SQLException {
        checkValidity();
        return con.getAutoCommit();
    }

    /**
     * Retrieves the underlying Connection object's catalog name.
     *
     * @return Catalog Name.
     * @throws SQLException In case of a database error.
     */
    @Override
    public String getCatalog() throws SQLException {
        checkValidity();
        return con.getCatalog();
    }

    /**
     * Retrieves the current holdability of ResultSet objects created
     * using this connection object.
     *
     * @return holdability value.
     * @throws SQLException In case of a database error.
     */
    @Override
    public int getHoldability() throws SQLException {
        checkValidity();
        return con.getHoldability();
    }

    /**
     * Retrieves the DatabaseMetaDataobject from the underlying
     *  Connection  object.
     *
     * @return DatabaseMetaData object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
        checkValidity();
        return con.getMetaData();
    }

    /**
     * Retrieves this Connection object's current transaction isolation level.
     *
     * @return Transaction level
     * @throws SQLException In case of a database error.
     */
    @Override
    public int getTransactionIsolation() throws SQLException {
        checkValidity();
        return con.getTransactionIsolation();
    }

    /**
     * Retrieves the Map object associated with
     *  Connection Object.
     *
     * @return TypeMap set in this object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public Map> getTypeMap() throws SQLException {
        checkValidity();
        return con.getTypeMap();
    }

    /**
     * Retrieves the the first warning reported by calls on the underlying
     * Connection object.
     *
     * @return First  SQLWarning Object or null.
     * @throws SQLException In case of a database error.
     */
    @Override
    public SQLWarning getWarnings() throws SQLException {
        checkValidity();
        return con.getWarnings();
    }

    /**
     * Retrieves whether underlying Connection object is closed.
     *
     * @return true if Connection object is closed, false
     *         if it is closed.
     * @throws SQLException In case of a database error.
     */
    @Override
    public boolean isClosed() throws SQLException {
        return isClosed;
    }

    /**
     * Set the isClosed flag based on whether the underlying Connection
     * object is closed.
     *
     * @param flag true if Connection object is closed, false if
     * its not closed.
     */
    public void setClosed(boolean flag) {
        isClosed = flag;
    }

    /**
     * Retrieves whether this Connection object is read-only.
     *
     * @return true if  Connection  is read-only, false other-wise
     * @throws SQLException In case of a database error.
     */
    @Override
    public boolean isReadOnly() throws SQLException {
        checkValidity();
        return con.isReadOnly();
    }

    /**
     * Converts the given SQL statement into the system's native SQL grammer.
     *
     * @param sql SQL statement , to be converted.
     * @return Converted SQL string.
     * @throws SQLException In case of a database error.
     */
    @Override
    public String nativeSQL(String sql) throws SQLException {
        checkValidity();
        return con.nativeSQL(sql);
    }

    /**
     * Creates a  CallableStatement  object for calling database
     * stored procedures.
     *
     * @param sql SQL Statement
     * @return  CallableStatement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        CallableStatement stmt = con.prepareCall(sql);
        if (statementTimeoutEnabled) {
            stmt.setQueryTimeout(statementTimeout);
        }
        return stmt;
    }

    /**
     * Creates a  CallableStatement  object for calling database
     * stored procedures.
     *
     * @param sql                  SQL Statement
     * @param resultSetType        Type of the ResultSet
     * @param resultSetConcurrency ResultSet Concurrency.
     * @return  CallableStatement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public CallableStatement prepareCall(String sql, int resultSetType,
                                         int resultSetConcurrency) throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        CallableStatement stmt = con.prepareCall(sql, resultSetType, resultSetConcurrency);
        if (statementTimeoutEnabled) {
            stmt.setQueryTimeout(statementTimeout);
        }
        return stmt;
    }

    /**
     * Creates a  CallableStatement  object for calling database
     * stored procedures.
     *
     * @param sql                  SQL Statement
     * @param resultSetType        Type of the ResultSet
     * @param resultSetConcurrency ResultSet Concurrency.
     * @param resultSetHoldability ResultSet Holdability.
     * @return  CallableStatement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public CallableStatement prepareCall(String sql, int resultSetType,
                                         int resultSetConcurrency,
                                         int resultSetHoldability) throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        CallableStatement stmt = con.prepareCall(sql, resultSetType, resultSetConcurrency,
                resultSetHoldability);
        if (statementTimeoutEnabled) {
            stmt.setQueryTimeout(statementTimeout);
        }
        return stmt;
    }

    /**
     * Creates a  PreparedStatement  object for sending
     * paramterized SQL statements to database
     *
     * @param sql SQL Statement
     * @return  PreparedStatement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public PreparedStatement prepareStatement(final String sql) throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        PreparedStatement stmt = con.prepareStatement(sql);
        if (statementTimeoutEnabled) {
            try {
                stmt.setQueryTimeout(statementTimeout);
            } catch (SQLException ex) {
                stmt.close();
            }
        }
        return stmt;
    }

    /**
     * Creates a  PreparedStatement  object for sending
     * paramterized SQL statements to database
     *
     * @param sql               SQL Statement
     * @param autoGeneratedKeys a flag indicating AutoGeneratedKeys need to be returned.
     * @return  PreparedStatement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public PreparedStatement prepareStatement(final String sql, int autoGeneratedKeys) throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        PreparedStatement stmt = con.prepareStatement(sql, autoGeneratedKeys);
        if (statementTimeoutEnabled) {
            try {
                stmt.setQueryTimeout(statementTimeout);
            } catch (SQLException ex) {
                stmt.close();
            }
        }
        return stmt;
    }

    /**
     * Creates a  PreparedStatement  object for sending
     * paramterized SQL statements to database
     *
     * @param sql           SQL Statement
     * @param columnIndexes an array of column indexes indicating the columns that should be
     *                      returned from the inserted row or rows.
     * @return  PreparedStatement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public PreparedStatement prepareStatement(final String sql, int[] columnIndexes) throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        PreparedStatement stmt = con.prepareStatement(sql, columnIndexes);
        if (statementTimeoutEnabled) {
            try {
                stmt.setQueryTimeout(statementTimeout);
            } catch (SQLException ex) {
                stmt.close();
            }
        }
        return stmt;
    }

    /**
     * Creates a  PreparedStatement  object for sending
     * paramterized SQL statements to database
     *
     * @param sql                  SQL Statement
     * @param resultSetType        Type of the ResultSet
     * @param resultSetConcurrency ResultSet Concurrency.
     * @return  PreparedStatement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public PreparedStatement prepareStatement(final String sql, int resultSetType,
                                              int resultSetConcurrency) throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        PreparedStatement stmt = con.prepareStatement(sql, resultSetType, resultSetConcurrency);
        if (statementTimeoutEnabled) {
            try {
                stmt.setQueryTimeout(statementTimeout);
            } catch (SQLException ex) {
                stmt.close();
            }
        }
        return stmt;
    }

    /**
     * Creates a  PreparedStatement  object for sending
     * paramterized SQL statements to database
     *
     * @param sql                  SQL Statement
     * @param resultSetType        Type of the ResultSet
     * @param resultSetConcurrency ResultSet Concurrency.
     * @param resultSetHoldability ResultSet Holdability.
     * @return  PreparedStatement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public PreparedStatement prepareStatement(final String sql, int resultSetType,
                                              int resultSetConcurrency,
                                              int resultSetHoldability) throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        PreparedStatement stmt = con.prepareStatement(sql, resultSetType,
                resultSetConcurrency, resultSetHoldability);
        if (statementTimeoutEnabled) {
            try {
                stmt.setQueryTimeout(statementTimeout);
            } catch (SQLException ex) {
                stmt.close();
            }
        }
        return stmt;
    }

    /**
     * Creates a  PreparedStatement  object for sending
     * paramterized SQL statements to database
     *
     * @param sql         SQL Statement
     * @param columnNames Name of bound columns.
     * @return  PreparedStatement object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public PreparedStatement prepareStatement(final String sql, String[] columnNames) throws SQLException {
        checkValidity();
        jdbcPreInvoke();
        PreparedStatement stmt = con.prepareStatement(sql, columnNames);
        if (statementTimeoutEnabled) {
            try {
                stmt.setQueryTimeout(statementTimeout);
            } catch (SQLException ex) {
                stmt.close();
            }
        }
        return stmt;
    }

    /**
     * Removes the given Savepoint object from the current transaction.
     *
     * @param savepoint Savepoint object
     * @throws SQLException In case of a database error.
     */
    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
        checkValidity();
        con.releaseSavepoint(savepoint);
    }

    /**
     * Rolls back the changes made in the current transaction.
     *
     * @throws SQLException In case of a database error.
     */
    @Override
    public void rollback() throws SQLException {
        checkValidity();
        con.rollback();
    }

    /**
     * Rolls back the changes made after the savepoint.
     *
     * @throws SQLException In case of a database error.
     */
    @Override
    public void rollback(Savepoint savepoint) throws SQLException {
        checkValidity();
        con.rollback(savepoint);
    }

    /**
     * Sets the auto-commmit mode of the Connection object.
     *
     * @param autoCommit boolean value indicating the auto-commit mode.
     * @throws SQLException In case of a database error.
     */
    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
        checkValidity();
        con.setAutoCommit(autoCommit);
        mc.setLastAutoCommitValue(autoCommit);
    }

    /**
     * Sets the catalog name to the Connection object
     *
     * @param catalog Catalog name.
     * @throws SQLException In case of a database error.
     */
    @Override
    public void setCatalog(String catalog) throws SQLException {
        checkValidity();
        con.setCatalog(catalog);
    }

    /**
     * Sets the holdability of ResultSet objects created
     * using this Connection object.
     *
     * @param holdability A ResultSet holdability constant
     * @throws SQLException In case of a database error.
     */
    @Override
    public void setHoldability(int holdability) throws SQLException {
        checkValidity();
        con.setHoldability(holdability);
    }

    /**
     * Puts the connection in read-only mode as a hint to the driver to
     * perform database optimizations.
     *
     * @param readOnly true enables read-only mode, false disables it.
     * @throws SQLException In case of a database error.
     */
    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {
        checkValidity();
        con.setReadOnly(readOnly);
    }

    /**
     * Creates and unnamed savepoint and returns an object corresponding to that.
     *
     * @return Savepoint object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public Savepoint setSavepoint() throws SQLException {
        checkValidity();
        return con.setSavepoint();
    }

    /**
     * Creates a savepoint with the name and returns an object corresponding to that.
     *
     * @param name Name of the savepoint.
     * @return Savepoint object.
     * @throws SQLException In case of a database error.
     */
    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
        checkValidity();
        return con.setSavepoint(name);
    }

    /**
     * Creates the transaction isolation level.
     *
     * @param level transaction isolation level.
     * @throws SQLException In case of a database error.
     */
    @Override
    public void setTransactionIsolation(int level) throws SQLException {
        checkValidity();
        con.setTransactionIsolation(level);
        mc.setLastTransactionIsolationLevel(level);
    }


    /**
     * Checks the validity of this object
     */
    protected void checkValidity() throws SQLException {
        if (isClosed) throw new SQLException("Connection closed");
        if (!valid) throw new SQLException("Invalid Connection");
        if (active == false) {
            mc.checkIfActive(this);
        }
    }

    /**
     * Sets the active flag to true
     *
     * @param actv boolean
     */
    public void setActive(boolean actv) {
        active = actv;
    }

    /*
     * Here this is a no-op. In the LazyEnlistableConnectionHolder, it will
     * actually fire the lazyEnlist method of LazyEnlistableManagedConnection
     */
    protected void jdbcPreInvoke() throws SQLException {
        if (myType_ == ConnectionType.LAZY_ASSOCIATABLE) {
            performLazyAssociation();
        } else if (myType_ == ConnectionType.LAZY_ENLISTABLE) {
            performLazyEnlistment();
        }

    }

    protected void performLazyEnlistment() throws SQLException {
        try {
            if(lazyEnlistCm_ != null) {
                lazyEnlistCm_.lazyEnlist(mc);
            }
        } catch (ResourceException re) {
            String msg = sm.getString(
                    "jdbc.cannot_enlist", re.getMessage() +
                    " Cannnot Enlist ManagedConnection");

            SQLException sqle = new SQLException(msg);
            sqle.initCause(re);
            throw sqle;
        }

    }

    protected void performLazyAssociation() throws SQLException {
        if (mc == null) {
            try {
                if(lazyAssocCm_ != null) {
                    lazyAssocCm_.associateConnection(this, mcf_, cxReqInfo_);
                }
            } catch (ResourceException re) {
                String msg = sm.getString(
                        "jdbc.cannot_assoc", re.getMessage() +
                        " Cannnot Associate ManagedConnection");

                SQLException sqle = new SQLException(msg);
                sqle.initCause(re);
                throw sqle;
            }
        }
    }

    public void setConnectionType(ConnectionType type) {
        myType_ = type;
    }

    public ConnectionType getConnectionType() {
        return myType_;
    }

    public void setLazyAssociatableConnectionManager(
            jakarta.resource.spi.LazyAssociatableConnectionManager cm) {

        lazyAssocCm_ = cm;
    }

    public void setLazyEnlistableConnectionManager(
            jakarta.resource.spi.LazyEnlistableConnectionManager cm) {

        lazyEnlistCm_ = cm;
    }

/*
    public void setManagedConnection(ManagedConnection con) {
        this.mc = con;
    }
*/

    /**
     * Installs the given Map object as the tyoe map for this
     *  Connection  object.
     *
     * @param map Map a Map object to install.
     * @throws SQLException In case of a database error.
     */
    @Override
    public void setTypeMap(java.util.Map> map) throws SQLException {
        checkValidity();
        con.setTypeMap(map);
    }

    protected MethodExecutor getMethodExecutor() {
        return executor;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy