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

com.landawn.abacus.dataSource.AbstractConnectionManager Maven / Gradle / Ivy

/*
 * Copyright (c) 2015, Haiyang Li. All rights reserved.
 */

package com.landawn.abacus.dataSource;

import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_EVICT_DELAY;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_INITIAL_SIZE;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_LIVE_TIME;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_MAX_ACTIVE;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_MAX_IDLE;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_MAX_IDLE_TIME;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_MAX_OPEN_PREPARED_STATEMENTS_PER_CONNECTION;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_MAX_WAIT;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_MIN_IDLE;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_TEST_ON_BORROW;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_TEST_ON_RETURN;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DEFAULT_VALIDATION_QUERY;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.DRIVER;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.EVICT_DELAY;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.INITIAL_SIZE;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.JNDI_CONTEXT_FACTORY;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.JNDI_NAME;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.JNDI_PROVIDER_URL;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.LIVE_TIME;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.MAX_ACTIVE;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.MAX_IDLE;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.MAX_IDLE_TIME;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.MAX_OPEN_PREPARED_STATEMENTS_PER_CONNECTION;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.MAX_WAIT_TIME;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.MIN_IDLE;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.PASSWORD;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.PERF_LOG;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.SQL_LOG;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.TEST_ON_BORROW;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.TEST_ON_RETURN;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.URL;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.USER;
import static com.landawn.abacus.dataSource.DataSourceConfiguration.VALIDATION_QUERY;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import com.landawn.abacus.exception.AbacusException;
import com.landawn.abacus.exception.UncheckedException;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.util.N;

/**
 * 
 * @since 0.8
 * 
 * @author Haiyang Li
 */
abstract class AbstractConnectionManager implements ConnectionManager {
    private static final Logger logger = LoggerFactory.getLogger(AbstractConnectionManager.class);

    protected final Map properties;
    protected final Properties connectionProperties;
    protected volatile long lastSQLExecutionFailureTime;

    public AbstractConnectionManager(Map props) {
        properties = new HashMap<>();
        connectionProperties = new Properties();
        connectionProperties.putAll(props);

        if (props.containsKey(JNDI_NAME)) {
            connectionProperties.remove(JNDI_NAME);
            properties.put(JNDI_NAME, props.get(JNDI_NAME).toString());
        }

        if (props.containsKey(JNDI_CONTEXT_FACTORY)) {
            connectionProperties.remove(JNDI_CONTEXT_FACTORY);
            properties.put(JNDI_CONTEXT_FACTORY, props.get(JNDI_CONTEXT_FACTORY).toString());
        }

        if (props.containsKey(JNDI_PROVIDER_URL)) {
            connectionProperties.remove(JNDI_PROVIDER_URL);
            properties.put(JNDI_PROVIDER_URL, props.get(JNDI_PROVIDER_URL).toString());
        }

        if (props.containsKey(DRIVER)) {
            connectionProperties.remove(DRIVER);
            properties.put(DRIVER, props.get(DRIVER).toString());
        }

        if (props.containsKey(URL)) {
            connectionProperties.remove(URL);
            properties.put(URL, props.get(URL).toString());
        }

        if (props.containsKey(USER)) {
            connectionProperties.remove(USER);
            properties.put(USER, props.get(USER).toString());
        }

        if (props.containsKey(PASSWORD)) {
            connectionProperties.remove(PASSWORD);
            properties.put(PASSWORD, props.get(PASSWORD).toString());
        }

        if (props.containsKey(INITIAL_SIZE)) {
            connectionProperties.remove(INITIAL_SIZE);
            properties.put(INITIAL_SIZE, props.get(INITIAL_SIZE).toString());
        } else {
            properties.put(INITIAL_SIZE, String.valueOf(DEFAULT_INITIAL_SIZE));
        }

        if (props.containsKey(MIN_IDLE)) {
            connectionProperties.remove(MIN_IDLE);
            properties.put(MIN_IDLE, props.get(MIN_IDLE).toString());
        } else {
            properties.put(MIN_IDLE, String.valueOf(DEFAULT_MIN_IDLE));
        }

        if (props.containsKey(MAX_IDLE)) {
            connectionProperties.remove(MAX_IDLE);
            properties.put(MAX_IDLE, props.get(MAX_IDLE).toString());
        } else {
            properties.put(MAX_IDLE, String.valueOf(DEFAULT_MAX_IDLE));
        }

        if (props.containsKey(MAX_ACTIVE)) {
            connectionProperties.remove(MAX_ACTIVE);
            properties.put(MAX_ACTIVE, props.get(MAX_ACTIVE).toString());
        } else {
            properties.put(MAX_ACTIVE, String.valueOf(DEFAULT_MAX_ACTIVE).toString());
        }

        if (props.containsKey(MAX_OPEN_PREPARED_STATEMENTS_PER_CONNECTION)) {
            connectionProperties.remove(MAX_OPEN_PREPARED_STATEMENTS_PER_CONNECTION);
            properties.put(MAX_OPEN_PREPARED_STATEMENTS_PER_CONNECTION, props.get(MAX_OPEN_PREPARED_STATEMENTS_PER_CONNECTION).toString());
        } else {
            properties.put(MAX_OPEN_PREPARED_STATEMENTS_PER_CONNECTION, String.valueOf(DEFAULT_MAX_OPEN_PREPARED_STATEMENTS_PER_CONNECTION));
        }

        if (props.containsKey(LIVE_TIME)) {
            connectionProperties.remove(LIVE_TIME);
            properties.put(LIVE_TIME, props.get(LIVE_TIME).toString());
        } else {
            properties.put(LIVE_TIME, String.valueOf(DEFAULT_LIVE_TIME));
        }

        if (props.containsKey(MAX_IDLE_TIME)) {
            connectionProperties.remove(MAX_IDLE_TIME);
            properties.put(MAX_IDLE_TIME, props.get(MAX_IDLE_TIME).toString());
        } else {
            properties.put(MAX_IDLE_TIME, String.valueOf(DEFAULT_MAX_IDLE_TIME));
        }

        if (props.containsKey(MAX_WAIT_TIME)) {
            connectionProperties.remove(MAX_WAIT_TIME);
            properties.put(MAX_WAIT_TIME, props.get(MAX_WAIT_TIME).toString());
        } else {
            properties.put(MAX_WAIT_TIME, String.valueOf(DEFAULT_MAX_WAIT));
        }

        if (props.containsKey(EVICT_DELAY)) {
            connectionProperties.remove(EVICT_DELAY);
            properties.put(EVICT_DELAY, props.get(EVICT_DELAY).toString());
        } else {
            properties.put(EVICT_DELAY, String.valueOf(DEFAULT_EVICT_DELAY));
        }

        if (props.containsKey(VALIDATION_QUERY)) {
            connectionProperties.remove(VALIDATION_QUERY);
            properties.put(VALIDATION_QUERY, props.get(VALIDATION_QUERY).toString());
        } else {
            String validationQuery = DEFAULT_VALIDATION_QUERY;
            String url = props.get(URL) == null ? null : props.get(URL).toString();

            if (N.notNullOrEmpty(url)) {
                url = url.toLowerCase();

                if ((url.indexOf("oracle") >= 0)) {
                    validationQuery = "SELECT 1 FROM dual";
                } else if ((url.indexOf("db2") >= 0)) {
                    validationQuery = "SELECT 1 FROM sysibm.sysdummy1";
                } else if (url.indexOf("hsql") >= 0) {
                    validationQuery = "SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS";
                }
            }

            properties.put(VALIDATION_QUERY, validationQuery);
        }

        if (props.containsKey(TEST_ON_BORROW)) {
            connectionProperties.remove(TEST_ON_BORROW);
            properties.put(TEST_ON_BORROW, props.get(TEST_ON_BORROW).toString());
        } else {
            properties.put(TEST_ON_BORROW, String.valueOf(DEFAULT_TEST_ON_BORROW));
        }

        if (props.containsKey(TEST_ON_RETURN)) {
            connectionProperties.remove(TEST_ON_RETURN);
            properties.put(TEST_ON_RETURN, props.get(TEST_ON_RETURN).toString());
        } else {
            properties.put(TEST_ON_RETURN, String.valueOf(DEFAULT_TEST_ON_RETURN));
        }

        if (props.containsKey(SQL_LOG)) {
            connectionProperties.remove(SQL_LOG);
            properties.put(SQL_LOG, props.get(SQL_LOG).toString());
        } else {
            properties.put(SQL_LOG, Boolean.FALSE.toString());
        }

        if (props.containsKey(PERF_LOG)) {
            connectionProperties.remove(PERF_LOG);
            properties.put(PERF_LOG, props.get(PERF_LOG).toString());
        } else {
            properties.put(PERF_LOG, String.valueOf(Long.MAX_VALUE));
        }
    }

    @Override
    public Map getProperties() {
        return properties;
    }

    @Override
    public Properties getConnectionProperties() {
        return connectionProperties;
    }

    @Override
    public synchronized void updateLastSQLExecutionFailureTime() {
        lastSQLExecutionFailureTime = System.currentTimeMillis();
    }

    protected DataSource createJNDIDataSource(Map properties) {
        String jndiName = connectionProperties.getProperty(JNDI_NAME);

        try {
            Properties jndiProps = new Properties();

            if (properties.get(JNDI_CONTEXT_FACTORY) != null) {
                jndiProps.put(Context.INITIAL_CONTEXT_FACTORY, properties.get(JNDI_CONTEXT_FACTORY));
            }

            if (properties.get(JNDI_PROVIDER_URL) != null) {
                jndiProps.put(Context.PROVIDER_URL, properties.get(JNDI_PROVIDER_URL));
            }

            InitialContext ctx = (jndiProps.size() == 0) ? new InitialContext() : new InitialContext(jndiProps);

            return (DataSource) ctx.lookup(jndiName);
        } catch (NamingException e) {
            String msg = "Failed to bind to JNDI: " + jndiName + ". " + AbacusException.getErrorMsg(e);
            logger.warn(msg);
            throw new UncheckedException(msg, e);
        }
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = (prime * result) + ((connectionProperties == null) ? 0 : connectionProperties.hashCode());
        result = (prime * result) + ((properties == null) ? 0 : properties.hashCode());

        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (obj instanceof AbstractConnectionManager) {
            AbstractConnectionManager other = (AbstractConnectionManager) obj;

            return N.equals(connectionProperties, other.connectionProperties) && N.equals(properties, other.properties);
        }

        return false;
    }

    @Override
    public String toString() {
        return "{properties=" + properties + ", connectionProperties=" + connectionProperties + "}";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy