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

com.sun.gjc.spi.ManagedConnectionFactoryImpl Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2016 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 2017-2022 Payara Foundation and/or its affiliates

package com.sun.gjc.spi;

import com.sun.appserv.connectors.internal.spi.MCFLifecycleListener;
import com.sun.enterprise.util.i18n.StringManager;
import com.sun.gjc.common.DataSourceObjectBuilder;
import com.sun.gjc.common.DataSourceSpec;
import com.sun.gjc.monitoring.JdbcStatsProvider;
import com.sun.gjc.util.SQLTraceDelegator;
import com.sun.gjc.util.SQLTraceLogger;
import com.sun.gjc.util.SecurityUtils;
import com.sun.logging.LogDomains;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.resource.ResourceException;
import jakarta.resource.spi.ConfigProperty;
import jakarta.resource.spi.ConnectionRequestInfo;
import jakarta.resource.spi.ResourceAdapterAssociation;
import jakarta.resource.spi.ResourceAllocationException;
import jakarta.resource.spi.security.PasswordCredential;
import javax.sql.PooledConnection;
import org.glassfish.api.jdbc.ConnectionValidation;
import org.glassfish.api.jdbc.SQLTraceListener;
import org.glassfish.external.probe.provider.PluginPoint;
import org.glassfish.external.probe.provider.StatsProviderManager;
import org.glassfish.resourcebase.resources.api.PoolInfo;

/**
 * ManagedConnectionFactory implementation for Generic JDBC Connector.
 * This class is extended by the DataSource specific ManagedConnection factories
 * and the ManagedConnectionFactory for the DriverManager.
 *
 * @author Evani Sai Surya Kiran, Aditya Gore
 * @version 1.0, 02/08/03
 */

public abstract class ManagedConnectionFactoryImpl implements jakarta.resource.spi.ManagedConnectionFactory,
        jakarta.resource.spi.ValidatingManagedConnectionFactory, 
        MCFLifecycleListener, ResourceAdapterAssociation,
        java.io.Serializable, Externalizable {

    protected DataSourceSpec spec = new DataSourceSpec();
    protected transient DataSourceObjectBuilder dsObjBuilder;

    protected java.io.PrintWriter logWriter = null;
    protected transient jakarta.resource.spi.ResourceAdapter ra = null;

    private static Logger _logger;
    protected boolean statementWrapping;

    private JdbcObjectsFactory jdbcObjectsFactory = JdbcObjectsFactory.getInstance();
    protected SQLTraceDelegator sqlTraceDelegator;

    static {
        _logger = LogDomains.getLogger(ManagedConnectionFactoryImpl.class, LogDomains.RSR_LOGGER);
    }

    protected jakarta.resource.spi.LazyEnlistableConnectionManager cm_;
    protected boolean isLazyCm_;
    private int statementCacheSize = 0;
    private String statementCacheType = null;
    private long statementLeakTimeout = 0;
    private boolean statementLeakReclaim = false;

    //Jdbc Stats provider that is created
    private JdbcStatsProvider jdbcStatsProvider = null;

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

    /**
     * Creates a Connection Factory instance. The ConnectionManager implementation
     * of the resource adapter is used here.
     *
     * @return Generic JDBC Connector implementation of javax.sql.DataSource
     */
    @Override
    public Object createConnectionFactory() {
        logFine("In createConnectionFactory()");
        return jdbcObjectsFactory.getDataSourceInstance(this, null);
    }

    /**
     * Creates a Connection Factory instance. The ConnectionManager implementation
     * of the application server is used here.
     *
     * @param cxManager ConnectionManager passed by the application server
     * @return Generic JDBC Connector implementation of javax.sql.DataSource
     */
    @Override
    public Object createConnectionFactory(jakarta.resource.spi.ConnectionManager cxManager) {
        logFine("In createConnectionFactory(jakarta.resource.spi.ConnectionManager cxManager)");

        javax.sql.DataSource cf = jdbcObjectsFactory.getDataSourceInstance(this, cxManager);

        if (cxManager instanceof jakarta.resource.spi.LazyEnlistableConnectionManager) {
            cm_ = (jakarta.resource.spi.LazyEnlistableConnectionManager) cxManager;
            isLazyCm_ = true;
        }
        return cf;
    }

    /**
     * Creates a new physical connection to the underlying EIS resource
     * manager.
     *
     * @param subject       Subject instance passed by the application server
     * @param cxRequestInfo ConnectionRequestInfo which may be created
     *                      as a result of the invocation getConnection(user, password)
     *                      on the DataSource object
     * @return ManagedConnection object created
     * @throws ResourceException if there is an error in instantiating the DataSource 
     *      object used for the creation of the ManagedConnection object; or if there is an
     *      error in allocating the physical connection
     * @throws SecurityException if there no PasswordCredential object
     *      satisfying this request
     */
    @Override
    public abstract jakarta.resource.spi.ManagedConnection createManagedConnection
            (javax.security.auth.Subject subject, ConnectionRequestInfo cxRequestInfo) throws ResourceException;

    /**
     * Check if this ManagedConnectionFactoryImpl is equal to
     * another ManagedConnectionFactoryImpl.
     *
     * @param other ManagedConnectionFactoryImpl object for checking equality with
     * @return true    if the property sets of both the
     *         ManagedConnectionFactoryImpl objects are the same
     *         false	otherwise
     */
    @Override
    public abstract boolean equals(Object other);

    /**
     * Get the log writer for this ManagedConnectionFactoryImpl instance.
     *
     * @return PrintWriter associated with this ManagedConnectionFactoryImpl instance
     * @see setLogWriter
     */
    @Override
    public java.io.PrintWriter getLogWriter() {
        return logWriter;
    }

    /**
     * Get the ResourceAdapterImpl for this ManagedConnectionFactoryImpl instance.
     *
     * @return ResourceAdapterImpl associated with this ManagedConnectionFactoryImpl instance
     * @see setResourceAdapter
     */
    @Override
    public jakarta.resource.spi.ResourceAdapter getResourceAdapter() {
        logFine("In getResourceAdapter");
        return ra;
    }

    /**
     * Returns the hash code for this ManagedConnectionFactoryImpl.
     *
     * @return hash code for this ManagedConnectionFactoryImpl
     */
    @Override
    public int hashCode() {
        logFine("In hashCode");
        return spec.hashCode();
    }

    /**
     * Returns a matched ManagedConnection from the candidate
     * set of ManagedConnection objects.
     *
     * @param connectionSet Set of  ManagedConnection
     *                      objects passed by the application server
     * @param subject       passed by the application server
     *                      for retrieving information required for matching
     * @param cxRequestInfo ConnectionRequestInfo passed by the application server
     *                      for retrieving information required for matching
     * @return ManagedConnection that is the best match satisfying this request
     * @throws ResourceException if there is an error accessing the Subject
     *                           parameter or the Set of ManagedConnection
     *                           objects passed by the application server
     */
    @Override
    public jakarta.resource.spi.ManagedConnection matchManagedConnections(
            java.util.Set connectionSet, javax.security.auth.Subject subject, ConnectionRequestInfo cxRequestInfo)
            throws ResourceException {
        logFine("In matchManagedConnections");

        if (connectionSet == null) {
            return null;
        }


        PasswordCredential pc = SecurityUtils.getPasswordCredential(this, subject, cxRequestInfo);

        java.util.Iterator iter = connectionSet.iterator();
        ManagedConnectionImpl mc = null;

        while (iter.hasNext()) {
            try {
                mc = (ManagedConnectionImpl) iter.next();
            } catch (java.util.NoSuchElementException nsee) {
                _logger.log(Level.SEVERE, "jdbc.exc_iter");
                throw new ResourceException(nsee.getMessage());
            }
            if (pc == null && this.equals(mc.getManagedConnectionFactory())) {
                return mc;
            } else if (SecurityUtils.isPasswordCredentialEqual(pc, mc.getPasswordCredential())) {
                return mc;
            }
        }
        return null;
    }

    /**
     * This method returns a set of invalid ManagedConnection
     * objects chosen from a specified set of ManagedConnection
     * objects.
     *
     * @param connectionSet a set of ManagedConnection objects
     *                      that need to be validated.
     * @return a set of invalid ManagedConnection objects.
     * @throws ResourceException generic exception.
     */
    @Override
    public Set getInvalidConnections(Set connectionSet) throws ResourceException {
        Iterator iter = connectionSet.iterator();
        Set invalidConnections = new HashSet();
        while (iter.hasNext()) {
            ManagedConnectionImpl mc = (ManagedConnectionImpl) iter.next();
            try {
                isValid(mc);
            } catch (ResourceException re) {
                invalidConnections.add(mc);
                mc.connectionErrorOccurred(re, null);
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "jdbc.invalid_connection", re);
                }
            }
        }
        return invalidConnections;
    }

    //GJCINT

    /**
     * Checks if a ManagedConnection is to be validated or not
     * and validates it or returns.
     *
     * @param mc ManagedConnection to be validated
     * @throws ResourceException if the connection is not valid or
     *                           if validation method is not proper
     */
    void isValid(ManagedConnectionImpl mc) throws ResourceException {

        if (mc == null || mc.isTransactionInProgress()) {
            return;
        }

        String conVal = spec.getDetail(DataSourceSpec.CONNECTIONVALIDATIONREQUIRED);

        boolean connectionValidationRequired =
                (conVal == null) ? false : Boolean.valueOf(conVal.toLowerCase(Locale.getDefault()));
        if (!connectionValidationRequired) {
            return;
        }


        String validationMethod = spec.getDetail(DataSourceSpec.VALIDATIONMETHOD).toLowerCase(Locale.getDefault());

        mc.checkIfValid();
        /**
         * The above call checks if the actual physical connection
         * is usable or not.
         */
        java.sql.Connection con = mc.getActualConnection();

        switch (validationMethod) {
            case "custom-validation":
                isValidByCustomValidation(con, spec.getDetail(DataSourceSpec.VALIDATIONCLASSNAME));
                break;
            case "auto-commit":
                isValidByAutoCommit(con);
                break;
            case "meta-data":
                isValidByMetaData(con);
                break;
            case "table":
                isValidByTableQuery(con, spec.getDetail(DataSourceSpec.VALIDATIONTABLENAME));
                break;
            default:
                throw new ResourceException("The validation method is not proper");
        }
    }
    
    /**
     * Checks if a java.sql.Connection is valid or not
     * by doing a custom validation using the validation class name specified.
     *
     * @param con java.sql.Connection to be validated
     * @throws ResourceException if the connection is not valid
     */    
    protected void isValidByCustomValidation(java.sql.Connection con, 
            String validationClassName) throws ResourceException {
        boolean isValid = false;
        if (con == null) {
            throw new ResourceException("The connection is not valid as "
                    + "the connection is null");
        }
        
        // The timeout defaults to -1, which isn't actually a valid setting for the timeout
        int statementTimeout = Integer.valueOf(getStatementTimeout());
        if (statementTimeout == -1) {
            statementTimeout = 0;
        }
        
        try {
            Class validationClass = Thread.currentThread().getContextClassLoader().loadClass(validationClassName);
            ConnectionValidation valClass = (ConnectionValidation) validationClass.newInstance();
            isValid = valClass.isConnectionValid(con, statementTimeout);
        } catch (Exception e) {
            _logger.log(Level.INFO, "jdbc.exc_custom_validation", validationClassName);
            throw new ResourceException(e);
        }
        if (!isValid) {
            _logger.log(Level.INFO, "jdbc.exc_custom_validation", validationClassName);
            throw new ResourceException("Custom validation detected invalid connection");
        }
    }

    /**
     * Checks if a java.sql.Connection is valid or not
     * by checking its auto commit property.
     *
     * @param con java.sql.Connection to be validated
     * @throws ResourceException if the connection is not valid
     */
    protected void isValidByAutoCommit(java.sql.Connection con) throws ResourceException {
        if (con == null) {
            throw new ResourceException("The connection is not valid as "
                    + "the connection is null");
        }

        try {
            // Notice that using something like
            // dbCon.setAutoCommit(dbCon.getAutoCommit()) will cause problems with
            // some drivers like sybase
            // We do not validate connections that are already enlisted
            //in a transaction
            // We cycle autocommit to true and false to by-pass drivers that
            // might cache the call to set autocomitt
            // Also notice that some XA data sources will throw and exception if
            // you try to call setAutoCommit, for them this method is not recommended

            boolean ac = con.getAutoCommit();
            if (ac) {
                con.setAutoCommit(false);
            } else {
                con.rollback(); // prevents uncompleted transaction exceptions
                con.setAutoCommit(true);
            }

            con.setAutoCommit(ac);

        } catch (Exception sqle) {
            _logger.log(Level.INFO, "jdbc.exc_autocommit_validation");
            throw new ResourceException(sqle);
        }
    }

    /**
     * Checks if a java.sql.Connection is valid or not
     * by checking its meta data.
     *
     * @param con java.sql.Connection to be validated
     * @throws ResourceException if the connection is not valid
     */
    protected void isValidByMetaData(java.sql.Connection con) throws ResourceException {
        if (con == null) {
            throw new ResourceException("The connection is not valid as "
                    + "the connection is null");
        }

        try {
            con.getMetaData();
        } catch (Exception sqle) {
            _logger.log(Level.INFO, "jdbc.exc_metadata_validation");
            throw new ResourceException(sqle);
        }
    }

    /**
     * Checks if a java.sql.Connection is valid or not
     * by querying a table.
     *
     * @param con       java.sql.Connection to be validated
     * @param tableName table which should be queried
     * @throws ResourceException if the connection is not valid
     */
    protected void isValidByTableQuery(java.sql.Connection con,
                                       String tableName) throws ResourceException {
        if (con == null) {
            throw new ResourceException("The connection is not valid as "
                    + "the connection is null");
        }

        java.sql.PreparedStatement stmt = null;
        java.sql.ResultSet rs = null;
        
        final String statement = "SELECT COUNT(*) FROM " + tableName;
        int statementTimeout = Integer.valueOf(getStatementTimeout());
        
        // The timeout defaults to -1, which isn't actually a valid setting for the timeout
        if (statementTimeout == -1) {
            statementTimeout = 0;
        }
        
        try {
            stmt = con.prepareStatement(statement);
            stmt.setQueryTimeout(statementTimeout);
            rs = stmt.executeQuery();
        } catch (Exception sqle) {
            _logger.log(Level.INFO, "jdbc.exc_table_validation", tableName);
            throw new ResourceException(sqle);
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
            } catch (Exception e1) {
            }

            try {
                if (stmt != null) {
                    stmt.close();
                }
            } catch (Exception e2) {
            }
        }
    }

    /**
     * Sets the isolation level specified in the ConnectionRequestInfo
     * for the ManagedConnection passed.
     *
     * @param mc ManagedConnection
     * @throws ResourceException if the isolation property is invalid
     *                           or if the isolation cannot be set over the connection
     */
    protected void setIsolation(ManagedConnectionImpl mc) throws ResourceException {

        java.sql.Connection con = mc.getActualConnection();
        if (con == null) {
            return;
        }

        String tranIsolation = spec.getDetail(DataSourceSpec.TRANSACTIONISOLATION);
        if (tranIsolation != null && !tranIsolation.equals("")) {
            int tranIsolationInt = getTransactionIsolationInt(tranIsolation);
            try {
                con.setTransactionIsolation(tranIsolationInt);
                mc.setLastTransactionIsolationLevel(tranIsolationInt);
            } catch (java.sql.SQLException sqle) {
                _logger.log(Level.SEVERE, "jdbc.exc_tx_iso", sqle);
                throw new ResourceException("The transaction isolation could "
                        + "not be set: " + sqle.getMessage());
            }
        }
    }

    /**
     * Resets the isolation level for the ManagedConnection passed.
     * If the transaction level is to be guaranteed to be the same as the one
     * present when this ManagedConnection was created, as specified
     * by the ConnectionRequestInfo passed, it sets the transaction
     * isolation level from the ConnectionRequestInfo passed. Else,
     * it sets it to the transaction isolation passed.
     *
     * @param mc       ManagedConnection
     * @param tranIsol int
     * @throws ResourceException if the isolation property is invalid
     *                           or if the isolation cannot be set over the connection
     */
    void resetIsolation(ManagedConnectionImpl mc, int tranIsol) throws ResourceException {

        java.sql.Connection con = mc.getActualConnection();
        if (con == null) {
            return;
        }

        String tranIsolation = spec.getDetail(DataSourceSpec.TRANSACTIONISOLATION);
        if (tranIsolation != null && !tranIsolation.equals("")) {
            String guaranteeIsolationLevel = spec.getDetail(DataSourceSpec.GUARANTEEISOLATIONLEVEL);

            if (guaranteeIsolationLevel != null && !guaranteeIsolationLevel.equals("")) {
                boolean guarantee = Boolean.valueOf(guaranteeIsolationLevel.toLowerCase(Locale.getDefault()));

                if (guarantee) {
                    int tranIsolationInt = getTransactionIsolationInt(tranIsolation);
                    try {
                        if (tranIsolationInt != con.getTransactionIsolation()) {
                            con.setTransactionIsolation(tranIsolationInt);
                        }
                    } catch (java.sql.SQLException sqle) {
                        _logger.log(Level.SEVERE, "jdbc.exc_tx_iso", sqle);
                        throw new ResourceException("The isolation level could not be set: "
                                + sqle.getMessage());
                    }
                } else {
                    try {
                        if (tranIsol != con.getTransactionIsolation()) {
                            con.setTransactionIsolation(tranIsol);
                        }
                    } catch (java.sql.SQLException sqle) {
                        _logger.log(Level.SEVERE, "jdbc.exc_tx_iso", sqle);
                        throw new ResourceException("The isolation level could not be set: "
                                + sqle.getMessage());
                    }
                }
            }
        }
    }

    private void detectSqlTraceListeners() {
        //Check for sql-trace-listeners attribute.
        String sqlTraceListeners = getSqlTraceListeners();
        String delimiter = ",";
        
        if(sqlTraceListeners != null && !sqlTraceListeners.equals("null")) {
            if (sqlTraceDelegator == null) {
                sqlTraceDelegator = new SQLTraceDelegator(getPoolName(), getApplicationName(), getModuleName());
            }
            StringTokenizer st = new StringTokenizer(sqlTraceListeners, delimiter);
            while (st.hasMoreTokens()) {
                String sqlTraceListener = st.nextToken().trim();            
                if(!sqlTraceListener.equals("")) {
                    Class listenerClass = null;
                    SQLTraceListener listener = null;
                    Constructor[] constructors = null;
                    Class[] parameterTypes = null;                    
                    Object[] initargs = null;
                    //Load the listener class 
                    try {
                        listenerClass = Thread.currentThread().getContextClassLoader().loadClass(sqlTraceListener);
                    } catch (ClassNotFoundException ex) {
                        try {
                            listenerClass = this.getClass().getClassLoader().loadClass(sqlTraceListener);
                        }catch (ClassNotFoundException ex2) {
                            _logger.log(Level.SEVERE, "jdbc.sql_trace_listener_cnfe", sqlTraceListener);
                        }
                    }
                    if (listenerClass != null) {
                        Class[] intf = listenerClass.getInterfaces();
                        for (Class interfaceName : intf) {
                            if (interfaceName.getName().equals("org.glassfish.api.jdbc.SQLTraceListener")) {

                                try {

                                    constructors = listenerClass.getConstructors();
                                    for (Constructor constructor : constructors) {
                                        parameterTypes = constructor.getParameterTypes();
                                        //For now only the no argument constructors are allowed.
                                        //TODO should this be documented?
                                        if (parameterTypes != null && parameterTypes.length == 0) {
                                            listener = (SQLTraceListener) constructor.newInstance(initargs);
                                        }
                                    }
                                } catch (InstantiationException ex) {
                                    _logger.log(Level.SEVERE, "jdbc.sql_trace_listener_exception", ex.getMessage());
                                } catch (IllegalAccessException ex) {
                                    _logger.log(Level.SEVERE, "jdbc.sql_trace_listener_exception", ex.getMessage());
                                } catch (IllegalArgumentException ex) {
                                    _logger.log(Level.SEVERE, "jdbc.sql_trace_listener_exception", ex.getMessage());
                                } catch (InvocationTargetException ex) {
                                    _logger.log(Level.SEVERE, "jdbc.sql_trace_listener_exception", ex.getMessage());
                                } catch (SecurityException ex) {
                                    _logger.log(Level.SEVERE, "jdbc.sql_trace_listener_exception", ex.getMessage());
                                }
                                sqlTraceDelegator.registerSQLTraceListener(listener);
                            }
                        }
                    }
                }
            }
        }
    }


    /**
     * Gets the integer equivalent of the string specifying
     * the transaction isolation.
     *
     * @param tranIsolation string specifying the isolation level
     * @return tranIsolationInt    the java.sql.Connection constant
     *         for the string specifying the isolation.
     */
    private int getTransactionIsolationInt(String tranIsolation) throws ResourceException {
        if (tranIsolation.equalsIgnoreCase("read-uncommitted")) {
            return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
        } else if (tranIsolation.equalsIgnoreCase("read-committed")) {
            return java.sql.Connection.TRANSACTION_READ_COMMITTED;
        } else if (tranIsolation.equalsIgnoreCase("repeatable-read")) {
            return java.sql.Connection.TRANSACTION_REPEATABLE_READ;
        } else if (tranIsolation.equalsIgnoreCase("serializable")) {
            return java.sql.Connection.TRANSACTION_SERIALIZABLE;
        } else if (tranIsolation.equalsIgnoreCase("snapshot")) {  
            return fish.payara.sql.Connection.TRANSACTION_SNAPSHOT;
        } else {
            throw new ResourceException("Invalid transaction isolation; the transaction "
                    + "isolation level can be empty or any of the following: "
                    + "read-uncommitted, read-committed, repeatable-read, serializable, custom");
        }
    }

    /**
     * Common operation performed by all the child MCFs before returning a created mc
     */
    protected void validateAndSetIsolation(ManagedConnectionImpl mc) throws ResourceException {
        try {
            isValid(mc);
            setIsolation(mc);
        } catch (ResourceException e) {
            if (mc != null) {
                try {
                    mc.destroy();
                } catch (ResourceException e1) {
                    _logger.log(Level.WARNING, "jdbc.exc_destroy", e1);
                }
            }
            String msg = localStrings.getString("jdbc.exc_destroy", e.getMessage());
            ResourceAllocationException rae = new ResourceAllocationException(
                    msg, e);
            throw rae;
        }
    }

    private void detectStatementCachingSupport() {
        String cacheSize = getStatementCacheSize();
        if(cacheSize != null){
            try{
                statementCacheSize = Integer.parseInt(cacheSize);
                //TODO-SC FINE log-level with Pool Name (if possible)
                if(_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "StatementCaching Size : " + statementCacheSize);
                }
            }catch(NumberFormatException nfe){
                if(_logger.isLoggable(Level.FINE)) {
                    _logger.fine("Exception while setting StatementCacheSize : " +
                        nfe.getMessage());
                }
                //ignore
            }
        } 
    }

    /**
     * Set the log writer for this ManagedConnectionFactoryImpl instance.
     *
     * @param out PrintWriter passed by the application server
     * @see getLogWriter
     */
    @Override
    public void setLogWriter(java.io.PrintWriter out) {
        logWriter = out;
    }

    /**
     * Set the associated ResourceAdapterImpl JavaBean.
     *
     * @param ra ResourceAdapterImpl associated with this
     *           ManagedConnectionFactoryImpl instance
     * @see getResourceAdapter
     */
    @Override
    public void setResourceAdapter(jakarta.resource.spi.ResourceAdapter ra) {
        this.ra = ra;
    }

    /**
     * Sets the user name
     *
     * @param user String
     */
    @ConfigProperty(type = String.class, defaultValue = "APP")
    public void setUser(String user) {
        spec.setDetail(DataSourceSpec.USERNAME, user);
    }

    /**
     * Gets the user name
     *
     * @return user
     */
    public String getUser() {
        return spec.getDetail(DataSourceSpec.USERNAME);
    }

    /**
     * Sets the password
     *
     * @param passwd String
     */
    @ConfigProperty(type = String.class, defaultValue = "APP")
    public void setPassword(String passwd) {
        spec.setDetail(DataSourceSpec.PASSWORD, passwd);
    }

    /**
     * Gets the password
     *
     * @return passwd
     */
    public String getPassword() {
        return spec.getDetail(DataSourceSpec.PASSWORD);
    }

    /**
     * Sets the class name of the data source
     *
     * @param className String
     */
    @ConfigProperty(type = String.class, defaultValue = "org.h2.jdbcx.JdbcDataSource")
    public void setClassName(String className) {
        spec.setDetail(DataSourceSpec.CLASSNAME, className);
    }

    /**
     * Gets the class name of the data source
     *
     * @return className
     */
    public String getClassName() {
        return spec.getDetail(DataSourceSpec.CLASSNAME);
    }

    /**
     * Sets if connection validation is required or not
     *
     * @param conVldReq String
     */
    @ConfigProperty(type = String.class, defaultValue = "false")
    public void setConnectionValidationRequired(String conVldReq) {
        spec.setDetail(DataSourceSpec.CONNECTIONVALIDATIONREQUIRED, conVldReq);
    }

    /**
     * Returns if connection validation is required or not
     *
     * @return connection validation requirement
     */
    public String getConnectionValidationRequired() {
        return spec.getDetail(DataSourceSpec.CONNECTIONVALIDATIONREQUIRED);
    }

    /**
     * Sets the validation method required
     *
     * @param validationMethod String
     */
    @ConfigProperty(type = String.class, defaultValue = "")
    public void setValidationMethod(String validationMethod) {
        spec.setDetail(DataSourceSpec.VALIDATIONMETHOD, validationMethod);
    }

    /**
     * Returns the connection validation method type
     *
     * @return validation method
     */
    public String getValidationMethod() {
        return spec.getDetail(DataSourceSpec.VALIDATIONMETHOD);
    }

    /**
     * Sets the table checked for during validation
     *
     * @param table String
     */
    @ConfigProperty(type = String.class, defaultValue = "")
    public void setValidationTableName(String table) {
        spec.setDetail(DataSourceSpec.VALIDATIONTABLENAME, table);
    }

    /**
     * Returns the table checked for during validation
     *
     * @return table
     */
    public String getValidationTableName() {
        return spec.getDetail(DataSourceSpec.VALIDATIONTABLENAME);
    }

    /**
     * Sets the validation class name checked for during validation
     *
     * @param className String
     */
    public void setValidationClassName(String className) {
        try {
            Class validationClass = Thread.currentThread().getContextClassLoader().loadClass(className);
            boolean isAssignable = ConnectionValidation.class.isAssignableFrom(validationClass);
            if (isAssignable) {
                spec.setDetail(DataSourceSpec.VALIDATIONCLASSNAME, className);
            } else {
                //Validation Failed
                _logger.log(Level.SEVERE, "jdbc.set_custom_validation_class_name_failure", className);
                throw new ResourceException("The Custom validation class name is" +
                        "not valid as it does not implement " +
                        ConnectionValidation.class.getName());
            }
        } catch (ResourceException ex) {
            _logger.log(Level.SEVERE, "jdbc.set_custom_validation_class_name_failure",
                    ex.getMessage());
        } catch (ClassNotFoundException ex) {
            _logger.log(Level.SEVERE, "jdbc.set_custom_validation_class_name_failure",
                    ex.getMessage());
        }
    }

    /**
     * Returns the validation class name checked for during validation
     *
     * @return table
     */
    public String getValidationClassName() {
        return spec.getDetail(DataSourceSpec.VALIDATIONCLASSNAME);
    }

    /**
     * Sets the transaction isolation level
     *
     * @param trnIsolation String
     */
    @ConfigProperty(type = String.class, defaultValue = "")
    public void setTransactionIsolation(String trnIsolation) {
        spec.setDetail(DataSourceSpec.TRANSACTIONISOLATION, trnIsolation);
    }

    /**
     * Returns the transaction isolation level
     *
     * @return transaction isolation level
     */
    public String getTransactionIsolation() {
        return spec.getDetail(DataSourceSpec.TRANSACTIONISOLATION);
    }

    /**
     * Sets if the transaction isolation level is to be guaranteed
     *
     * @param guaranteeIsolation String
     */
    @ConfigProperty(type = String.class, defaultValue = "")
    public void setGuaranteeIsolationLevel(String guaranteeIsolation) {
        spec.setDetail(DataSourceSpec.GUARANTEEISOLATIONLEVEL, guaranteeIsolation);
    }

    /**
     * Returns the transaction isolation level
     *
     * @return isolation level guarantee
     */
    public String getGuaranteeIsolationLevel() {
        return spec.getDetail(DataSourceSpec.GUARANTEEISOLATIONLEVEL);
    }

    protected boolean isEqual(PasswordCredential pc, String user,
                              String password) {

        //if equal get direct connection else
        //get connection with user and password.

        String thisUser = (pc == null) ? null : pc.getUserName();
        char[] passwordArray = (pc == null) ? null : pc.getPassword();
        char[] tmpPasswordArray = (password == null) ? null : password.toCharArray();

        return (isStringEqual(thisUser, user) &&
                Arrays.equals(passwordArray, tmpPasswordArray));

    }

    private boolean isStringEqual(String str1, String str2) {
        return str1 == null ? str2 == null : str1.equals(str2);
    }

    /**
     * Sets the server name.
     *
     * @param serverName String
     * @see getServerName
     */
    @ConfigProperty(type = String.class, defaultValue = "localhost")
    public void setServerName(String serverName) {
        spec.setDetail(DataSourceSpec.SERVERNAME, serverName);
    }

    /**
     * Gets the server name.
     *
     * @return serverName
     * @see setServerName
     */
    public String getServerName() {
        return spec.getDetail(DataSourceSpec.SERVERNAME);
    }

    /**
     * Sets the port number.
     *
     * @param portNumber String
     * @see getPortNumber
     */
    @ConfigProperty(type = String.class, defaultValue = "1527")
    public void setPortNumber(String portNumber) {
        spec.setDetail(DataSourceSpec.PORTNUMBER, portNumber);
    }

    /**
     * Gets the port number.
     *
     * @return portNumber
     * @see setPortNumber
     */
    public String getPortNumber() {
        return spec.getDetail(DataSourceSpec.PORTNUMBER);
    }

    /**
     * Sets the database name.
     *
     * @param databaseName String
     * @see getDatabaseName
     */
    @ConfigProperty(type = String.class, defaultValue = "testdb")
    public void setDatabaseName(String databaseName) {
        spec.setDetail(DataSourceSpec.DATABASENAME, databaseName);
    }

    /**
     * Gets the database name.
     *
     * @return databaseName
     * @see setDatabaseName
     */
    public String getDatabaseName() {
        return spec.getDetail(DataSourceSpec.DATABASENAME);
    }

    /**
     * Sets the data source name.
     *
     * @param dsn String
     * @see getDataSourceName
     */
    @ConfigProperty(type = String.class, defaultValue = "")
    public void setDataSourceName(String dsn) {
        spec.setDetail(DataSourceSpec.DATASOURCENAME, dsn);
    }

    /**
     * Gets the data source name.
     *
     * @return dsn
     * @see setDataSourceName
     */
    public String getDataSourceName() {
        return spec.getDetail(DataSourceSpec.DATASOURCENAME);
    }

    /**
     * Set Statement Wrapping value
     *
     * @param wrapping String
     * @see  getStatementWrapping 
     */
    public void setStatementWrapping(String wrapping) {
        spec.setDetail(DataSourceSpec.STATEMENTWRAPPING, wrapping);
        computeStatementWrappingStatus();
    }

    /**
     * Gets the statement wrapping value
     *
     * @return String representing "true" or "false"
     * @see setStatementWrapping
     */
    public String getStatementWrapping() {
        return spec.getDetail(DataSourceSpec.STATEMENTWRAPPING);
    }

    public void setStatementCacheSize(String value){
        spec.setDetail(DataSourceSpec.STATEMENTCACHESIZE, value);
        detectStatementCachingSupport();
    }

    public String getStatementCacheSize(){
        return spec.getDetail(DataSourceSpec.STATEMENTCACHESIZE);
    }

    public void setStatementLeakTimeoutInSeconds(String value){
        spec.setDetail(DataSourceSpec.STATEMENTLEAKTIMEOUTINSECONDS, value);
        detectStatementLeakSupport();
    }

    public String getStatementLeakTimeoutInSeconds(){
        return spec.getDetail(DataSourceSpec.STATEMENTLEAKTIMEOUTINSECONDS);
    }

    public void setStatementLeakReclaim(String value) {
        spec.setDetail(DataSourceSpec.STATEMENTLEAKRECLAIM, value);
    }

    public String getStatementLeakReclaim() {
        return spec.getDetail(DataSourceSpec.STATEMENTLEAKRECLAIM);
    }

    public void setPoolMonitoringSubTreeRoot(String value) {
        spec.setDetail(DataSourceSpec.POOLMONITORINGSUBTREEROOT, value);
    }

    public String getPoolMonitoringSubTreeRoot() {
        return spec.getDetail(DataSourceSpec.POOLMONITORINGSUBTREEROOT);
    }

    public String getApplicationName() {
        return spec.getDetail(DataSourceSpec.APPLICATIONNAME);
    }

    public void setApplicationName(String value) {
        spec.setDetail(DataSourceSpec.APPLICATIONNAME, value);
        if (sqlTraceDelegator != null) {
            sqlTraceDelegator.setAppName(value);
        }
    }

    public String getModuleName() {
        return spec.getDetail(DataSourceSpec.MODULENAME);
    }

    public void setModuleName(String value) {
        spec.setDetail(DataSourceSpec.MODULENAME, value);
        if (sqlTraceDelegator != null) {
            sqlTraceDelegator.setModuleName(value);
        }
    }

    public String getPoolName() {
        return spec.getDetail(DataSourceSpec.POOLNAME);
    }

    public void setPoolName(String value) {
        spec.setDetail(DataSourceSpec.POOLNAME, value);
        if (sqlTraceDelegator != null) {
            sqlTraceDelegator.setPoolName(value);
        }
    }

    public String getStatementCacheType() {
        return spec.getDetail(DataSourceSpec.STATEMENTCACHETYPE);
    }

    public void setStatementCacheType(String statementCacheType) {
        spec.setDetail(DataSourceSpec.STATEMENTCACHETYPE, statementCacheType);
        this.statementCacheType = getStatementCacheType();
        if(this.statementCacheType == null || this.statementCacheType.trim().equals("")) {
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine(" Default StatementCaching Type : " +
                        localStrings.getString("jdbc.statement-cache.default.datastructure"));
            }
        } else {
            if(_logger.isLoggable(Level.FINE)) {
                _logger.fine("StatementCaching Type : " + this.statementCacheType);
            }
        }
    }
    
    public String getMaxCacheSize(){
        return spec.getDetail(DataSourceSpec.MAXCACHESIZE);
    }
    
    public void setMaxCacheSize(String maxCacheSize){
        spec.setDetail(DataSourceSpec.MAXCACHESIZE, maxCacheSize);
    }

    public String getNumberOfTopQueriesToReport() {
        return spec.getDetail(DataSourceSpec.NUMBEROFTOPQUERIESTOREPORT);
    }

    public void setNumberOfTopQueriesToReport(String numTopQueriesToReport) {
        spec.setDetail(DataSourceSpec.NUMBEROFTOPQUERIESTOREPORT, numTopQueriesToReport);
    }

    public String getTimeToKeepQueriesInMinutes() {
        return spec.getDetail(DataSourceSpec.TIMETOKEEPQUERIESINMINUTES);
    }

    public void setTimeToKeepQueriesInMinutes(String timeToKeepQueries) {
        spec.setDetail(DataSourceSpec.TIMETOKEEPQUERIESINMINUTES, timeToKeepQueries);
    }
    
    public String getInitSql() {
        return spec.getDetail(DataSourceSpec.INITSQL);
    }

    public void setInitSql(String initSql) {
        //TODO remove case where "null" is checked. Might be a CLI/GUI bug.
        if(initSql != null && !initSql.equalsIgnoreCase("null") && 
                !initSql.equals("")) {
            spec.setDetail(DataSourceSpec.INITSQL, initSql);
        }
    }
    
    /**
     * Set StatementTimeout value
     *
     * @param timeout String
     * @see  getStatementTimeout 
     */
    public void setStatementTimeout(String timeout) {
        spec.setDetail(DataSourceSpec.STATEMENTTIMEOUT, timeout);
    }

    /**
     * Gets the StatementTimeout value
     *
     * @return String representing "true" or "false"
     * @see setStatementTimeout
     */
    public String getStatementTimeout() {
        return spec.getDetail(DataSourceSpec.STATEMENTTIMEOUT);
    }
    
    public String getSqlTraceListeners() {
        return spec.getDetail(DataSourceSpec.SQLTRACELISTENERS);
    }

    public void setSqlTraceListeners(String sqlTraceListeners) {
        if(sqlTraceListeners != null) {
            spec.setDetail(DataSourceSpec.SQLTRACELISTENERS, sqlTraceListeners);
            detectSqlTraceListeners();
        }
    }

    public void setSlowQueryThresholdInSeconds(String seconds) {
        spec.setDetail(DataSourceSpec.SLOWSQLLOGTHRESHOLD, seconds);
        double threshold = Double.parseDouble(seconds);
        if (threshold > 0) {
            if (sqlTraceDelegator == null) {
                sqlTraceDelegator = new SQLTraceDelegator(getPoolName(), getApplicationName(), getModuleName());
            }
        }
    }

    public String getSlowQueryThresholdInSeconds() {
        return spec.getDetail(DataSourceSpec.SLOWSQLLOGTHRESHOLD);
    }

    public void setLogJdbcCalls(String enabled) {
        spec.setDetail(DataSourceSpec.LOGJDBCCALLS, enabled);
        if (Boolean.valueOf(enabled)) {
            if (sqlTraceDelegator == null) {
                sqlTraceDelegator = new SQLTraceDelegator(getPoolName(), getApplicationName(), getModuleName());
            }
            sqlTraceDelegator.registerSQLTraceListener(new SQLTraceLogger());
        }
    }
    
    public String getLogJdbcCalls() {
         return spec.getDetail(DataSourceSpec.LOGJDBCCALLS);       
    }
    
    /**
     * Sets the description.
     *
     * @param desc String
     * @see getDescription
     */
    @ConfigProperty(type = String.class, defaultValue = "H2 driver for datasource")
    public void setDescription(String desc) {
        spec.setDetail(DataSourceSpec.DESCRIPTION, desc);
    }

    /**
     * Gets the description.
     *
     * @return desc
     * @see setDescription
     */
    public String getDescription() {
        return spec.getDetail(DataSourceSpec.DESCRIPTION);
    }

    /**
     * Sets the network protocol.
     *
     * @param nwProtocol String
     * @see getNetworkProtocol
     */
    @ConfigProperty(type = String.class, defaultValue = "")
    public void setNetworkProtocol(String nwProtocol) {
        spec.setDetail(DataSourceSpec.NETWORKPROTOCOL, nwProtocol);
    }

    /**
     * Gets the network protocol.
     *
     * @return nwProtocol
     * @see setNetworkProtocol
     */
    public String getNetworkProtocol() {
        return spec.getDetail(DataSourceSpec.NETWORKPROTOCOL);
    }

    /**
     * Sets the role name.
     *
     * @param roleName String
     * @see getRoleName
     */
    @ConfigProperty(type = String.class, defaultValue = "")
    public void setRoleName(String roleName) {
        spec.setDetail(DataSourceSpec.ROLENAME, roleName);
    }

    /**
     * Gets the role name.
     *
     * @return roleName
     * @see setRoleName
     */
    public String getRoleName() {
        return spec.getDetail(DataSourceSpec.ROLENAME);
    }

    /**
     * Sets the login timeout.
     *
     * @param loginTimeOut String
     * @see getLoginTimeOut
     */
    @ConfigProperty(type = String.class, defaultValue = "0")
    public void setLoginTimeOut(String loginTimeOut) {
        spec.setDetail(DataSourceSpec.LOGINTIMEOUT, loginTimeOut);
    }

    /**
     * Gets the login timeout.
     *
     * @return loginTimeout
     * @see setLoginTimeOut
     */
    public String getLoginTimeOut() {
        return spec.getDetail(DataSourceSpec.LOGINTIMEOUT);
    }

    /**
     * Sets the delimiter.
     *
     * @param delim String
     * @see getDelimiter
     */
    @ConfigProperty(type = String.class, defaultValue = "#")
    public void setDelimiter(String delim) {
        spec.setDetail(DataSourceSpec.DELIMITER, delim);
    }

    /**
     * Gets the delimiter.
     *
     * @return delim
     * @see setDelimiter
     */
    public String getDelimiter() {
        return spec.getDetail(DataSourceSpec.DELIMITER);
    }

    public void setEscapeCharacter(String escapeCharacter){
        spec.setDetail(DataSourceSpec.ESCAPECHARACTER, escapeCharacter);
    }

    public String getEscapeCharacter(){
        return spec.getDetail(DataSourceSpec.ESCAPECHARACTER);
    }

      /**
     * Sets the driver specific properties.
     *
     * @param driverProps String
     * @see getDriverProperties
     */
    @ConfigProperty(type = String.class, defaultValue = "")
    public void setDriverProperties(String driverProps) {
        spec.setDetail(DataSourceSpec.DRIVERPROPERTIES, driverProps);
    }

    /**
     * Gets the driver specific properties.
     *
     * @return driverProps
     * @see setDriverProperties
     */
    public String getDriverProperties() {
        return spec.getDetail(DataSourceSpec.DRIVERPROPERTIES);
    }

    protected PoolInfo getPoolInfo(){
        return new PoolInfo(getPoolName(), getApplicationName(), getModuleName());
    }

    protected ManagedConnectionImpl constructManagedConnection(PooledConnection pc,
                                                           Connection sqlCon, PasswordCredential passCred,
                                                           ManagedConnectionFactoryImpl mcf) throws ResourceException {
        return new ManagedConnectionImpl(pc, sqlCon, passCred, mcf,
                getPoolInfo(), statementCacheSize, statementCacheType, sqlTraceDelegator,
                statementLeakTimeout, statementLeakReclaim);
    }

    /**
     * Returns the underlying datasource
     *
     * @return DataSource of jdbc vendor
     * @throws ResourceException
     */
    public Object getDataSource() throws ResourceException {
        if (dsObjBuilder == null) {
            dsObjBuilder = new DataSourceObjectBuilder(spec);
        }
        return dsObjBuilder.constructDataSourceObject();
    }

    protected static final int JVM_OPTION_STATEMENT_WRAPPING_ON = 1;
    protected static final int JVM_OPTION_STATEMENT_WRAPPING_OFF = 0;
    protected static final int JVM_OPTION_STATEMENT_WRAPPING_NOT_SET = -1;

    /**
     * This wrapStatement flag is used to enable disable wrapping the
     * statement objects. This can be enabled by passing jvm option,
     * com.sun.appserv.jdbc.wrapstatement = true.
     * This can be disabled by removing this option or by passing non true
     * value.
     * By default this will be disabled
     */
    private static int wrapStatement = JVM_OPTION_STATEMENT_WRAPPING_NOT_SET;

    static {
        wrapStatement = getStatementWrappingJVMOption();
    }

    /**
     * Gets the Statement Wrapping JVM Option (available in 8.2)
* Which will be deprecated in future versions. * * @return int representing the JVM Option value of statement wrapping. */ private static int getStatementWrappingJVMOption() { int result = JVM_OPTION_STATEMENT_WRAPPING_NOT_SET; String str = System.getProperty( "com.sun.appserv.jdbc.wrapJdbcObjects"); if ("true".equalsIgnoreCase(str)) { result = JVM_OPTION_STATEMENT_WRAPPING_ON; } else if ("false".equalsIgnoreCase(str)) { result = JVM_OPTION_STATEMENT_WRAPPING_OFF; } return result; } /** * 9.1 has attribute "wrap-statements" which will be overriden * when JVM option is specified as "true" or "false" * JVM Option will be deprecated in future versions. */ protected void computeStatementWrappingStatus() { boolean poolProperty = false; String statementWrappingString = getStatementWrapping(); if (statementWrappingString != null) poolProperty = Boolean.parseBoolean(statementWrappingString); if (wrapStatement == JVM_OPTION_STATEMENT_WRAPPING_ON || (wrapStatement == JVM_OPTION_STATEMENT_WRAPPING_NOT_SET && poolProperty)) { statementWrapping = true; } else { statementWrapping = false; } } /** * Returns whether statement wrapping is enabled or not.
* * @return boolean representing statementwrapping status */ public boolean isStatementWrappingEnabled() { return statementWrapping; } public JdbcObjectsFactory getJdbcObjectsFactory() { return jdbcObjectsFactory; } protected void logFine(String logMessage){ if(_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, logMessage); } } @Override public void mcfCreated() { String poolMonitoringSubTreeRoot = getPoolMonitoringSubTreeRoot(); String sqlTraceListeners = getSqlTraceListeners(); //Default values used in case sql tracing is OFF int sqlTraceCacheSize = 0; long timeToKeepQueries = 0; int maxCacheSize = 0; if(sqlTraceListeners != null && !sqlTraceListeners.equals("null")) { if(getNumberOfTopQueriesToReport() != null && !getNumberOfTopQueriesToReport().equals("null")) { //Some value is set for this property sqlTraceCacheSize = Integer.parseInt(getNumberOfTopQueriesToReport()); } else { //No property by this name. default to 10 queries sqlTraceCacheSize = 10; } if(getTimeToKeepQueriesInMinutes() != null && !getTimeToKeepQueriesInMinutes().equals("null")) { //Time-To-Keep-Queries property has been set timeToKeepQueries = Integer.parseInt(getTimeToKeepQueriesInMinutes()); } else { //Default to 5 minutes after which cache is pruned. timeToKeepQueries = 5; //Time to keep queries is set to 5 minutes because the timer //task will keep running till mcf is destroyed even if //monitoring is turned OFF. } if (getMaxCacheSize() != null && !getMaxCacheSize().equals("null")){ maxCacheSize = Integer.parseInt(getMaxCacheSize()); } else { //Default to 10000 entries maxCacheSize = 10000; } } if(_logger.isLoggable(Level.FINEST)) { _logger.finest("MCF Created"); } if (statementCacheSize > 0 || (sqlTraceListeners != null && !sqlTraceListeners.equals("null")) || statementLeakTimeout > 0) { jdbcStatsProvider = new JdbcStatsProvider(getPoolName(), getApplicationName(), getModuleName(), sqlTraceCacheSize, timeToKeepQueries, maxCacheSize); //get the poolname and use it to initialize the stats provider n register StatsProviderManager.register( "jdbc-connection-pool", PluginPoint.SERVER, poolMonitoringSubTreeRoot, jdbcStatsProvider); if(jdbcStatsProvider.getFreqSqlTraceCache() != null) { if(_logger.isLoggable(Level.FINEST)) { _logger.finest("Scheduling timer task for frequent sql trace caching"); } Timer timer = ((com.sun.gjc.spi.ResourceAdapterImpl) ra).getTimer(); jdbcStatsProvider.getFreqSqlTraceCache().scheduleTimerTask(timer); } if (jdbcStatsProvider.getSlowSqlTraceCache() != null) { if (_logger.isLoggable(Level.FINEST)) { _logger.finest("Scheduling timer task for slow sql trace caching"); } Timer timer = ((com.sun.gjc.spi.ResourceAdapterImpl) ra).getTimer(); jdbcStatsProvider.getSlowSqlTraceCache().scheduleTimerTask(timer); } if(_logger.isLoggable(Level.FINEST)) { _logger.finest("Registered JDBCRA Stats Provider"); } } } @Override public void mcfDestroyed() { if(_logger.isLoggable(Level.FINEST)) { _logger.finest("MCF Destroyed"); } if(jdbcStatsProvider != null) { if(jdbcStatsProvider.getFreqSqlTraceCache() != null) { if(_logger.isLoggable(Level.FINEST)) { _logger.finest("Canceling timer task for frequent sql trace caching"); } jdbcStatsProvider.getFreqSqlTraceCache().cancelTimerTask(); } if(jdbcStatsProvider.getSlowSqlTraceCache() != null) { if(_logger.isLoggable(Level.FINEST)) { _logger.finest("Canceling timer task for slow sql trace caching"); } jdbcStatsProvider.getSlowSqlTraceCache().cancelTimerTask(); } StatsProviderManager.unregister(jdbcStatsProvider); jdbcStatsProvider = null; if(_logger.isLoggable(Level.FINEST)) { _logger.finest("Unregistered JDBCRA Stats Provider"); } } } private void detectStatementLeakSupport() { String stmtLeakTimeout = getStatementLeakTimeoutInSeconds(); String stmtLeakReclaim = getStatementLeakReclaim(); if (stmtLeakTimeout != null) { statementLeakTimeout = Integer.parseInt(stmtLeakTimeout) * 1000L; statementLeakReclaim = Boolean.parseBoolean(stmtLeakReclaim); if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, "StatementLeakTimeout in seconds: " + statementLeakTimeout + " & StatementLeakReclaim: " + statementLeakReclaim + " for pool : " + getPoolInfo()); } } } @Override public void writeExternal(ObjectOutput out) throws IOException { } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { ra = com.sun.gjc.spi.ResourceAdapterImpl.getInstance(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy