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

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Locale;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.lib.conf.Configurable;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.util.Closeable;

/**
 * Commons DBCP basic pooling driver data source.
 * The commons-dbcp packages must be on the class path for this plugin to work,
 * as it WILL NOT fall back to non-DBCP mode if they are missing. For automatic
 * usage of Commons DBCP when available, use AutoDriverDataSource instead.
 */
public class DBCPDriverDataSource
extends SimpleDriverDataSource implements Configurable, Closeable {

    private static String DBCPPACKAGENAME = "org.apache.commons.dbcp2";
    private static String DBCPBASICDATASOURCENAME = "org.apache.commons.dbcp2.BasicDataSource";
    private static Class<?> _dbcpClass;
    private static Boolean _dbcpAvail;
    private static RuntimeException _dbcpEx;

    protected JDBCConfiguration conf;
    private volatile DataSource _ds;

    @Override
    public Connection getConnection(Properties props) throws SQLException {
        return getDBCPConnection(props);
    }

    @Override
    public void close() throws SQLException {
        try {
            if (_ds != null) {
                if (isDBCPLoaded(getClassLoader())) {
                    ((org.apache.commons.dbcp2.BasicDataSource)_dbcpClass.cast(_ds)).close();
                }
            }
        } catch (Exception e) {
            // no-op
        } catch (Throwable t) {
            // no-op
        } finally {
            _ds = null;
        }
    }

    protected Connection getDBCPConnection(Properties props) throws SQLException {
        Connection con = getDBCPDataSource(props).getConnection();
        if (con == null) {
            throw new SQLException(_eloc.get("dbcp-ds-null",
                DBCPBASICDATASOURCENAME, getConnectionDriverName(), getConnectionURL()).getMessage());
        }
        return con;
    }

    protected DataSource getDBCPDataSource(Properties props) {
        if (isDBCPLoaded(getClassLoader())) {
            if (_ds == null) {
                try {
                    Properties dbcpProps = updateDBCPProperties(props);
                    _ds = (DataSource) Configurations.newInstance(DBCPBASICDATASOURCENAME, conf,
                        dbcpProps, getClassLoader());
                } catch (Exception e) {
                    _dbcpEx = new RuntimeException(_eloc.get("driver-null", DBCPBASICDATASOURCENAME).getMessage(), e);
                }
                return _ds;
            } else {
                return _ds;
            }
        } else {
            // user choose DBCP, so fail if it isn't on the classpath
            if (_dbcpEx == null)
                _dbcpEx = new RuntimeException(_eloc.get("driver-null", DBCPBASICDATASOURCENAME).getMessage());
            throw _dbcpEx;
        }
    }

    /**
     * This method should not throw an exception, as it is called by
     * AutoDriverDataSource to determine if user already specified
     * to use Commons DBCP.
     * @return true if ConnectionDriverName contains org.apache.commons.dbcp2,
     *         otherwise false
     */
    protected boolean isDBCPDataSource() {
        return (getConnectionDriverName() != null &&
            getConnectionDriverName().toLowerCase(Locale.ENGLISH).indexOf(DBCPPACKAGENAME) >= 0);
    }

    /**
     * This method should not throw an exception, as it is called by
     * AutoDriverDataSource to determine if it should use DBCP or not
     * based on if org.apache.commons.dbcp2.BasicDataSource can be loaded.
     * @return true if Commons DBCP was found on the classpath, otherwise false
     */
    static protected boolean isDBCPLoaded(ClassLoader cl) {
        if (Boolean.TRUE.equals(_dbcpAvail) && (_dbcpClass != null)) {
            return true;
        } else if (Boolean.FALSE.equals(_dbcpAvail)) {
            return false;
        } else {
            // first time checking, so try to load it
            try {
                _dbcpClass = Class.forName(DBCPBASICDATASOURCENAME, true, cl);
                _dbcpAvail = Boolean.TRUE;
                return true;
            } catch (Exception e) {
                _dbcpAvail = Boolean.FALSE;
                // save exception details for later instead of throwing here
                _dbcpEx = new RuntimeException(_eloc.get("driver-null", DBCPBASICDATASOURCENAME).getMessage(), e);
            }
            return _dbcpAvail.booleanValue();
        }
    }

    /**
     * Normalize properties for Commons DBCP.  This should be done for every call from DataSourceFactory,
     * as we do not have a pre-configured Driver to reuse.
     * @param props
     * @return updated properties
     */
    private Properties updateDBCPProperties(Properties props) {
        Properties dbcpProps = mergeConnectionProperties(props);

        // only perform the following check for the first connection attempt (_driverClassName == null),
        // as multiple connections could be requested (like from SchemaTool) and isDBCPDriver() will be true
        if (isDBCPDataSource()) {
            String propDriver = hasProperty(dbcpProps, "driverClassName");
            if (propDriver == null || propDriver.trim().isEmpty()) {
                // if user specified DBCP for the connectionDriverName, then make sure they supplied a DriverClassName
                throw new RuntimeException(_eloc.get("connection-property-invalid", "DriverClassName",
                    propDriver).getMessage());
            }
            propDriver = hasProperty(dbcpProps, "url");
            if (propDriver == null || propDriver.trim().isEmpty()) {
                // if user specified DBCP for the connectionDriverName, then make sure they supplied a Url
                throw new RuntimeException(_eloc.get("connection-property-invalid", "URL",
                    propDriver).getMessage());
            }
        } else {
            // set Commons DBCP expected DriverClassName to the original connection driver name
            dbcpProps.setProperty(hasKey(dbcpProps, "driverClassName", "driverClassName"), getConnectionDriverName());
            // set Commons DBCP expected URL property
            dbcpProps.setProperty(hasKey(dbcpProps, "url", "url"), getConnectionURL());
        }

        // Commons DBCP requires non-Null username/password values in the connection properties
        if (hasKey(dbcpProps, "username") == null) {
            if (getConnectionUserName() != null)
                dbcpProps.setProperty("username", getConnectionUserName());
            else
                dbcpProps.setProperty("username", "");
        }
        // Commons DBCP requires non-Null username/password values in the connection properties
        if (hasKey(dbcpProps, "password") == null) {
            if (getConnectionPassword() != null)
                dbcpProps.setProperty("password", getConnectionPassword());
            else
                dbcpProps.setProperty("password", "");
        }

        // set some default properties for DBCP
        if (hasKey(dbcpProps, "maxActive") == null) {
            dbcpProps.setProperty("maxActive", "10");
        }
        if (hasKey(dbcpProps, "maxIdle") == null) {
            // by default we set maxIdle to the same value as maxActive.
            dbcpProps.setProperty("maxIdle", dbcpProps.getProperty("maxActive"));
        }
        if (hasKey(dbcpProps, "minIdle") == null) {
            dbcpProps.setProperty("minIdle", "0");
        }

        return dbcpProps;
    }

    /**
     * Merge the passed in properties with a copy of the existing _connectionProperties
     * @param props
     * @return Merged properties
     */
    private Properties mergeConnectionProperties(final Properties props) {
        Properties mergedProps = new Properties();
        mergedProps.putAll(getConnectionProperties());

        // need to map "user" to "username" for Commons DBCP
        String uid = removeProperty(mergedProps, "user");
        if (uid != null) {
            mergedProps.setProperty("username", uid);
        }

        // now, merge in any passed in properties
        if (props != null && !props.isEmpty()) {
            for (Iterator<Object> itr = props.keySet().iterator(); itr.hasNext();) {
                String key = (String)itr.next();
                String value = props.getProperty(key);
                // need to map "user" to "username" for Commons DBCP
                if ("user".equalsIgnoreCase(key)) {
                    key = "username";
                }
                // case-insensitive search for existing key
                String existingKey = hasKey(mergedProps, key);
                if (existingKey != null) {
                    // update existing entry
                    mergedProps.setProperty(existingKey, value);
                } else {
                    // add property to the merged set
                    mergedProps.setProperty(key, value);
                }
            }
        }
        return mergedProps;
    }

    /**
     * Case-insensitive search of the given properties for the given key.
     * @param props
     * @param key
     * @return Key name as found in properties or null if it was not found.
     */
    private String hasKey(Properties props, String key) {
        return hasKey(props, key, null);
    }

    /**
     * Case-insensitive search of the given properties for the given key.
     * @param props
     * @param key
     * @param defaultKey
     * @return Key name as found in properties or the given defaultKey if it was not found.
     */
    private String hasKey(Properties props, String key, String defaultKey)
    {
        if (props != null && key != null) {
            for (Iterator<Object> itr = props.keySet().iterator(); itr.hasNext();) {
                String entry = (String)itr.next();
                if (key.equalsIgnoreCase(entry))
                    return entry;
            }
        }
        return defaultKey;
    }

    private String hasProperty(Properties props, String key) {
        if (props != null && key != null) {
            String entry = hasKey(props, key);
            if (entry != null)
                return props.getProperty(entry);
        }
        return null;

    }

    private String removeProperty(Properties props, String key) {
        if (props != null && key != null) {
            String entry = hasKey(props, key);
            if (entry != null)
                return (String)props.remove(entry);
        }
        return null;
    }

    // Configurable interface methods
    @Override
    public void setConfiguration(Configuration conf) {
        if (conf instanceof JDBCConfiguration)
            this.conf = (JDBCConfiguration)conf;
    }

    @Override
    public void startConfiguration() {
        // no-op
    }

    @Override
    public void endConfiguration() {
        // no-op
    }

}

