Package com.scooterframework.orm.sqldataexpress.config

Source Code of com.scooterframework.orm.sqldataexpress.config.DatabaseConfig

/*
*   This software is distributed under the terms of the FSF
*   Gnu Lesser General Public License (see lgpl.txt).
*
*   This program is distributed WITHOUT ANY WARRANTY. See the
*   GNU General Public License for more details.
*/
package com.scooterframework.orm.sqldataexpress.config;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Properties;
import java.util.Set;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mchange.v2.c3p0.DataSources;
import com.scooterframework.admin.ApplicationConfig;
import com.scooterframework.admin.PropertyFileChangeMonitor;
import com.scooterframework.admin.PropertyReader;
import com.scooterframework.common.logging.LogUtil;
import com.scooterframework.common.util.Converters;
import com.scooterframework.common.util.NamedProperties;
import com.scooterframework.common.util.PropertyFileUtil;
import com.scooterframework.common.util.Util;
import com.scooterframework.orm.sqldataexpress.connection.DatabaseConnectionContext;
import com.scooterframework.transaction.Transaction;

/**
* <p>DatabaseConfig class configs the data access application during startup
* time. After instantiated, it is a readonly object. </p>
*
* <p>Mappings between sql data type name, sql data typ code and java type name
* are specified here. By default, all entries in java.sql.Type class are listed here.</p>
*
* <p>Developers can override or add more here. See below for examples.</p>
*
* <p>All items are of the following format separated by comma. </p>
* <pre>
*   Format: {sql data type name}:{sql data type}:{java class name}
*
*   ARRAY:2003:java.sql.Array           //Types.ARRAY
*   BIGINT:-5:java.lang.Long            //Types.BIGINT
*   BINARY:-2:byte[]                    //Types.BINARY
*   BIT:-7:java.lang.Boolean            //Types.BIT
*   BLOB:2004:java.sql.Blob             //Types.BLOB
*   BOOLEAN:16:java.lang.Boolean        //Types.BOOLEAN
*   CHAR:1:java.lang.String             //Types.CHAR
*   CLOB:2005:java.sql.Clob             //Types.CLOB
*   DATALINK:70:java.lang.Object        //Types.DATALINK
*   DATE:91:java.sql.Timestamp          //Types.DATE
*   DECIMAL:3:java.lang.BigDecimal      //Types.DECIMAL
*   DISTINCT:2001:java.lang.Object      //Types.DISTINCT
*   DOUBLE:8:java.lang.Double           //Types.DOUBLE
*   FLOAT:6:java.lang.Double            //Types.FLOAT
*   INTEGER:4:java.lang.Integer         //Types.INTEGER
*   JAVA_OBJECT:2000:java.lang.Object   //Types.JAVA_OBJECT
*   LONGVARBINARY:-4:byte[]             //Types.LONGVARBINARY
*   LONGVARCHAR:-1:java.lang.String     //Types.LONGVARCHAR
*   LONGVARCHAR:-15:java.lang.String    //Types.NCHAR
*   NCLOB:2011:java.sql.Clob            //Types.NCLOB
*   NULL:0:java.lang.Object             //Types.NULL
*   NUMERIC:2:java.lang.BigDecimal      //Types.NUMERIC
*   NVARCHAR:-9:java.lang.String        //Types.NVARCHAR
*   OTHER:1111:java.lang.Object         //Types.OTHER
*   REAL:7:java.lang.Double             //Types.REAL
*   REF:2006:java.sql.Ref               //Types.REF
*   ROWID:-8:java.lang.Integer          //Types.ROWID
*   SMALLINT:5:java.lang.Integer        //Types.SMALLINT
*   SQLXML:2009:java.lang.String        //Types.SQLXML
*   STRUCT:2002:java.sql.Struct         //Types.STRUCT
*   TIME:92:java.sql.Time               //Types.TIME
*   TIMESTAMP:93:java.sql.Timestamp     //Types.TIMESTAMP
*   TINYINT:-6:java.lang.Integer        //Types.TINYINT
*   VARBINARY:-3:byte[]                 //Types.VARBINARY
*   VARCHAR:12:java.lang.String         //Types.VARCHAR

*  Special for ORACLE:
*   NUMBER:2:java.lang.BigDecimal       //Types.NUMERIC
*   VARCHAR2:12:java.lang.String        //Types.VARCHAR
* </pre>
*
* <p>Developers can add more types at startup time by adding those types
*    in database property file.</p>
*
* @author (Fei) John Chen
*/
public class DatabaseConfig extends Observable implements Observer {
    private LogUtil log = LogUtil.getLogger(this.getClass().getName());
   
    /**
     * A hyphen "-" is used to link composite primary key fields.
     */
    public static final String PRIMARY_KEY_SEPARATOR = "-";

    /**
     * Property file for database properties.
     */
    public static final String DATA_PROPERTIES_FILE = "database.properties";

    /**
     * All allowed transaction types: "JDBC JTA CMT"
     */
    public static final String ALLOWED_TRANSACTION_TYPES = "JDBC JTA CMT";

    /**
     * Key to represent a property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_NAME_PREFIX = "database.connection";

    /**
     * Key to represent connection <tt>name</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_NAME = "name";

    /**
     * Key to represent <tt>transactionType</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_TRANSACTION_TYPE = "transaction.type";

    /**
     * Key to represent <tt>dataSourceName</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_DATASOURCE_NAME = "data_source_name";

    /**
     * Key to represent <tt>beforeConenction</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_BEFORE = "before_connection";

    /**
     * Key to represent <tt>afterConnection</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_AFTER = "after_connection";

    /**
     * Key to represent <tt>timeout</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_TIMEOUT = "timeout";

    /**
     * Key to represent <tt>username</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_USERNAME = "username";

    /**
     * Key to represent <tt>password</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_PASSWORD = "password";

    /**
     * Key to represent <tt>driver</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_DRIVER = "driver";

    /**
     * Key to represent <tt>url</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_URL = "url";

    /**
     * Key to represent <tt>readonly</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_READONLY = "readonly";

    /**
     * Key to represent <tt>readonly</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_AUTOCOMMIT = "autocommit";

    /**
     * Key to represent <tt>transactionIsolationLevel</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_TRANSACTION_ISOLATION_LEVEL = "transaction_isolation_level";

    /**
     * Key to represent <tt>vendor</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_VENDOR = "vendor";

    /**
     * Key to represent <tt>schema</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_SCHEMA = "schema";

    /**
     * Key to represent <tt>use_login_as_schema</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_USE_LOGIN_AS_SCHEMA = "use_login_as_schema";

    /**
     * Key to represent <tt>use_login_for_connection</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_USE_LOGIN_FOR_CONNECTION = "use_login_for_connection";

    /**
     * Key to represent <tt>adapterClassName</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_ADAPTER_CLASS_NAME = "adapterClassName";

    /**
     * Key to represent <tt>max_pool_size</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_MAX_POOL_SIZE = "max_pool_size";

    /**
     * Key to represent <tt>min_pool_size</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_MIN_POOL_SIZE = "min_pool_size";

    /**
     * Key to represent <tt>acquire_increment</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_ACQUIRE_INCREMENT = "acquire_increment";

    /**
     * Key to represent <tt>initial_pool_size</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_INITIAL_POOL_SIZE = "initial_pool_size";

    /**
     * Key to represent <tt>max_idle_time</tt> property in database connection properties.
     */
    public static final String KEY_DB_CONNECTION_MAX_IDLE_TIME = "max_idle_time";

    public static final String BUILTIN_DATABASE_NAME_H2         = "H2";
    public static final String BUILTIN_DATABASE_NAME_HSQLDB     = "HsqlDB";
    public static final String BUILTIN_DATABASE_NAME_MYSQL      = "MySQL";
    public static final String BUILTIN_DATABASE_NAME_ORACLE     = "Oracle";
    public static final String BUILTIN_DATABASE_NAME_POSTGRESQL = "PostgreSQL";
    public static final String BUILTIN_DATABASE_NAME_SQLSERVER  = "SQLServer";
    public static final String BUILTIN_DATABASE_NAME_SYBASE     = "Sybase";
    public static final Set<String> ALL_BUILTIN_DATABASE_VENDORS = new HashSet<String>();

    //****************************************************
    // Default values for keys in the properties file
    //****************************************************
    public static final String DEFAULT_VALUE_defaultTransactionType = Transaction.JDBC_TRANSACTION_TYPE;
    public static final String DEFAULT_VALUE_defaultDatabaseConnection = null;
    public static final String DEFAULT_VALUE_gloablTableNamingPrefix = "";
    public static final String DEFAULT_VALUE_gloablTableNamingSuffix = "";
    public static final String DEFAULT_VALUE_usePluralTableName = "true";
    public static final String DEFAULT_VALUE_autoAuditCreate = null;
    public static final String DEFAULT_VALUE_autoAuditUpdate = null;
    public static final String DEFAULT_VALUE_additionalSQLDataTypeMapping = null;
    public static final int DEFAULT_VALUE_max_pool_size = 5;
    public static final int DEFAULT_VALUE_min_pool_size = 3;
    public static final int DEFAULT_VALUE_acquire_increment = 3;
    public static final int DEFAULT_VALUE_initial_pool_size = 3;
    public static final int DEFAULT_VALUE_max_idle_time = 0;

    private static final DatabaseConfig me = new DatabaseConfig();
    private Properties appProperties = null;

    private String defaultTransactionType = DEFAULT_VALUE_defaultTransactionType;
    private String defaultDatabaseConnection = DEFAULT_VALUE_defaultDatabaseConnection;
    private String gloablTableNamingPrefix = DEFAULT_VALUE_gloablTableNamingPrefix;
    private String gloablTableNamingSuffix = DEFAULT_VALUE_gloablTableNamingSuffix;
    private String usePluralTableName = DEFAULT_VALUE_usePluralTableName;
    private String autoAuditCreate = DEFAULT_VALUE_autoAuditCreate;
    private String autoAuditUpdate = DEFAULT_VALUE_autoAuditUpdate;
    private String additionalSQLDataTypeMapping = DEFAULT_VALUE_additionalSQLDataTypeMapping;

    private List<String> autoAuditListForCreate = null;
    private List<String> autoAuditListForUpdate = null;
    private Map<String, NamedProperties> databaseConnectionsMap = new HashMap<String, NamedProperties>();
    private List<String> referenceDataNames = new ArrayList<String>();
    private Map<String, NamedProperties> referenceDataMap = new HashMap<String, NamedProperties>();
    private Map<String, ComboPooledDataSource> connectionPoolDataSourcesMap = new HashMap<String, ComboPooledDataSource>();

    /**
     * <p>A map of SQL data type name and its corresponding type (Integer).</p>
     */
    public final Map<String, Integer> allSQLDataNameTypesMap = new HashMap<String, Integer>();

    /**
     * <p>A map of SQL data type code and its corresponding java class type name.</p>
     */
    public final Map<Integer, String> allSQLTypeJavaNamesMap = new HashMap<Integer, String>();

    private DatabaseConfig() {
        init();
        PropertyFileChangeMonitor.getInstance().registerObserver(this, DATA_PROPERTIES_FILE);
    }

    private void clear() {
        if (autoAuditListForCreate != null) autoAuditListForCreate.clear();
        if (autoAuditListForUpdate != null) autoAuditListForUpdate.clear();
        databaseConnectionsMap.clear();
        referenceDataNames.clear();
        referenceDataMap.clear();
        allSQLDataNameTypesMap.clear();
        allSQLTypeJavaNamesMap.clear();
        connectionPoolDataSourcesMap.clear();
    }

    private void init() {
        clear();

        ALL_BUILTIN_DATABASE_VENDORS.add(BUILTIN_DATABASE_NAME_H2.toUpperCase());
        ALL_BUILTIN_DATABASE_VENDORS.add(BUILTIN_DATABASE_NAME_HSQLDB.toUpperCase());
        ALL_BUILTIN_DATABASE_VENDORS.add(BUILTIN_DATABASE_NAME_MYSQL.toUpperCase());
        ALL_BUILTIN_DATABASE_VENDORS.add(BUILTIN_DATABASE_NAME_ORACLE.toUpperCase());
        ALL_BUILTIN_DATABASE_VENDORS.add(BUILTIN_DATABASE_NAME_POSTGRESQL.toUpperCase());
        ALL_BUILTIN_DATABASE_VENDORS.add(BUILTIN_DATABASE_NAME_SQLSERVER.toUpperCase());
        ALL_BUILTIN_DATABASE_VENDORS.add(BUILTIN_DATABASE_NAME_SYBASE.toUpperCase());

        List<String> allSQLTypesList = new ArrayList<String>();
        allSQLTypesList.add("ARRAY:2003:java.sql.Array");           //Types.ARRAY
        allSQLTypesList.add("BIGINT:-5:java.lang.Long");            //Types.BIGINT
        allSQLTypesList.add("BINARY:-2:byte[]");                    //Types.BINARY
        allSQLTypesList.add("BIT:-7:java.lang.Boolean");            //Types.BIT
        allSQLTypesList.add("BLOB:2004:java.sql.Blob");             //Types.BLOB
        allSQLTypesList.add("BOOLEAN:16:java.lang.Boolean");        //Types.BOOLEAN
        allSQLTypesList.add("CHAR:1:java.lang.String");             //Types.CHAR
        allSQLTypesList.add("CLOB:2005:java.sql.Clob");             //Types.CLOB
        allSQLTypesList.add("DATALINK:70:java.lang.Object");        //Types.DATALINK
        allSQLTypesList.add("DATE:91:java.sql.Timestamp");          //Types.DATE
        allSQLTypesList.add("DECIMAL:3:java.lang.BigDecimal");      //Types.DECIMAL
        allSQLTypesList.add("DISTINCT:2001:java.lang.Object");      //Types.DISTINCT
        allSQLTypesList.add("DOUBLE:8:java.lang.Double");           //Types.DOUBLE
        allSQLTypesList.add("FLOAT:6:java.lang.Double");            //Types.FLOAT
        allSQLTypesList.add("INTEGER:4:java.lang.Integer");         //Types.INTEGER
        allSQLTypesList.add("JAVA_OBJECT:2000:java.lang.Object");   //Types.JAVA_OBJECT
        allSQLTypesList.add("LONGVARCHAR:-16:java.lang.String");    //Types.LONGNVARCHAR
        allSQLTypesList.add("LONGVARBINARY:-4:byte[]");             //Types.LONGVARBINARY
        allSQLTypesList.add("LONGVARCHAR:-1:java.lang.String");     //Types.LONGVARCHAR
        allSQLTypesList.add("NCHAR:-15:java.lang.String");          //Types.NCHAR
        allSQLTypesList.add("CLOB:2011:java.sql.Clob");             //Types.NCLOB
        allSQLTypesList.add("NVARCHAR:-9:java.lang.String");        //Types.NVARCHAR
        allSQLTypesList.add("NULL:0:java.lang.Object");             //Types.NULL
        allSQLTypesList.add("NUMERIC:2:java.lang.BigDecimal");      //Types.NUMERIC
        allSQLTypesList.add("OTHER:1111:java.lang.Object");         //Types.OTHER
        allSQLTypesList.add("REAL:7:java.lang.Double");             //Types.REAL
        allSQLTypesList.add("REF:2006:java.sql.Ref");               //Types.REF
        allSQLTypesList.add("ROWID:-8:java.lang.Integer");          //Types.ROWID
        allSQLTypesList.add("SMALLINT:5:java.lang.Integer");        //Types.SMALLINT
        allSQLTypesList.add("SQLXML:2009:java.lang.String");        //Types.SQLXML
        allSQLTypesList.add("STRUCT:2002:java.sql.Struct");         //Types.STRUCT
        allSQLTypesList.add("TIME:92:java.sql.Time");               //Types.TIME
        allSQLTypesList.add("TIMESTAMP:93:java.sql.Timestamp");     //Types.TIMESTAMP
        allSQLTypesList.add("TINYINT:-6:java.lang.Integer");        //Types.TINYINT
        allSQLTypesList.add("VARBINARY:-3:byte[]");                 //Types.VARBINARY
        allSQLTypesList.add("VARCHAR:12:java.lang.String");         //Types.VARCHAR
        allSQLTypesList.add("NUMBER:2:java.lang.BigDecimal");       //Types.NUMERIC
        allSQLTypesList.add("VARCHAR2:12:java.lang.String");        //Types.VARCHAR

        loadProperties();

        defaultTransactionType = getProperty("default.transaction.type", DEFAULT_VALUE_defaultTransactionType);
        if (ALLOWED_TRANSACTION_TYPES.indexOf(defaultTransactionType) == -1) {
            throw new IllegalArgumentException("The value of default.transaction.type " +
                    "\"" + defaultTransactionType + "\" in properties file is " +
                    "not valid. The allowed transaction types are \"" + ALLOWED_TRANSACTION_TYPES + "\".");
        }

        gloablTableNamingPrefix = getProperty("global.table.naming.prefix", DEFAULT_VALUE_gloablTableNamingPrefix);
        gloablTableNamingSuffix = getProperty("global.table.naming.suffix", DEFAULT_VALUE_gloablTableNamingSuffix);
        usePluralTableName = getProperty("use.plural.table.name", DEFAULT_VALUE_usePluralTableName);

        String nameValueSpliter = "=";
        String propertyDelimiter = ",";

        Enumeration<?> en = appProperties.keys();
        while (en.hasMoreElements()) {
            String key = (String) en.nextElement();
            if (key == null) continue;
            if (key.startsWith("database.connection")) {
                String name = key.substring(key.lastIndexOf('.') + 1);
                Properties p = PropertyFileUtil.parseNestedPropertiesFromLine(getProperty(key), nameValueSpliter, propertyDelimiter);
                p.setProperty(KEY_DB_CONNECTION_NAME, name);
                checkConnectionPoolProperties(name, p);
                if (databaseConnectionsMap.containsKey(name)) {
                    NamedProperties np = databaseConnectionsMap.get(name);
                    np.setProperties(p);
                }
                else {
                    NamedProperties np = new NamedProperties(name, p);
                    databaseConnectionsMap.put(name, np);
                }
            }
            else
            if (key.startsWith("reference.data")) {
                String name = key.substring(key.lastIndexOf('.') + 1);
                Properties p = PropertyFileUtil.parseNestedPropertiesFromLine(getProperty(key), nameValueSpliter, propertyDelimiter);
                if (referenceDataMap.containsKey(name)) {
                    NamedProperties np = referenceDataMap.get(name);
                    np.setProperties(p);
                }
                else {
                    NamedProperties np = new NamedProperties(name, p);
                    referenceDataNames.add(name);
                    referenceDataMap.put(name, np);
                }
            }
        }

        defaultDatabaseConnection = getProperty("default.database.connection.name", DEFAULT_VALUE_defaultDatabaseConnection);
        if (defaultDatabaseConnection != null && !databaseConnectionsMap.keySet().contains(defaultDatabaseConnection)) {
          log.error("There is no definition for default database connection " + defaultDatabaseConnection);
        }

        autoAuditCreate = getProperty("autoaudit.create.timestamp.fields", DEFAULT_VALUE_autoAuditCreate);
        if (autoAuditCreate != null) {
            autoAuditListForCreate = Converters.convertStringToList(autoAuditCreate.toLowerCase());
        }

        autoAuditUpdate = getProperty("autoaudit.update.timestamp.fields", DEFAULT_VALUE_autoAuditUpdate);
        if (autoAuditUpdate != null) {
            autoAuditListForUpdate = Converters.convertStringToList(autoAuditUpdate.toLowerCase());
        }

        //populate sql maps
        additionalSQLDataTypeMapping = getProperty("additional_sql_data_type_mapping", DEFAULT_VALUE_additionalSQLDataTypeMapping);
        allSQLTypesList.addAll(Converters.convertStringToList(additionalSQLDataTypeMapping));

        allSQLDataNameTypesMap.clear();
        allSQLTypeJavaNamesMap.clear();

        int totalTypes = allSQLTypesList.size();
        for (int i = 0; i < totalTypes; i++) {
            String entry = allSQLTypesList.get(i);
            String[] items = entry.split(":");
            String typeName = items[0].trim();
            String typeCode = items[1].trim();
            String javaName = items[2].trim();
            Integer sqlDataTypeCode = Util.getSafeInteger(typeCode);
            allSQLDataNameTypesMap.put(typeName, sqlDataTypeCode);
            allSQLTypeJavaNamesMap.put(sqlDataTypeCode, javaName);
        }
    }

    private void checkConnectionPoolProperties(String connectionName, Properties p) {
      boolean autoCommit = ("true".equalsIgnoreCase(p.getProperty(DatabaseConnectionContext.KEY_AUTOCOMMIT)))?true:false;
       
     
        String maxPoolSize = p.getProperty(KEY_DB_CONNECTION_MAX_POOL_SIZE, "" + DEFAULT_VALUE_max_pool_size);
        if (Integer.parseInt(maxPoolSize) == 0) {
            p.setProperty(KEY_DB_CONNECTION_MAX_POOL_SIZE, maxPoolSize);
            log.debug("No connection pool for " + connectionName + ", because max_pool_size is " + maxPoolSize);
            return;
        }

        Properties c3p0props = new Properties();
        c3p0props.setProperty("maxPoolSize", maxPoolSize);

        String minPoolSize = p.getProperty(KEY_DB_CONNECTION_MIN_POOL_SIZE, "" + DEFAULT_VALUE_min_pool_size);
        p.setProperty(KEY_DB_CONNECTION_MIN_POOL_SIZE, minPoolSize);
        c3p0props.setProperty("minPoolSize", minPoolSize);

        String acquireIncrement = p.getProperty(KEY_DB_CONNECTION_ACQUIRE_INCREMENT, "" + DEFAULT_VALUE_acquire_increment);
        p.setProperty(KEY_DB_CONNECTION_ACQUIRE_INCREMENT, acquireIncrement);
        c3p0props.setProperty("acquireIncrement", acquireIncrement);

        String initialPoolSize = p.getProperty(KEY_DB_CONNECTION_INITIAL_POOL_SIZE, "" + DEFAULT_VALUE_initial_pool_size);
        p.setProperty(KEY_DB_CONNECTION_INITIAL_POOL_SIZE, initialPoolSize);
        c3p0props.setProperty("initialPoolSize", initialPoolSize);

        String maxIdleTime = p.getProperty(KEY_DB_CONNECTION_MAX_IDLE_TIME, "" + DEFAULT_VALUE_max_idle_time);
        p.setProperty(KEY_DB_CONNECTION_MAX_IDLE_TIME, maxIdleTime);
        c3p0props.setProperty("maxIdleTime", maxIdleTime);

        try {
            String driver = p.getProperty(KEY_DB_CONNECTION_DRIVER);
            if (driver == null) throw new IllegalArgumentException("Driver class is not specified for connection " + connectionName);

            String url = p.getProperty(KEY_DB_CONNECTION_URL);
            if (url == null) throw new IllegalArgumentException("Database url is not specified for connection " + connectionName);

            String username = p.getProperty(KEY_DB_CONNECTION_USERNAME);
            String password = p.getProperty(KEY_DB_CONNECTION_PASSWORD);

            System.setProperty("com.mchange.v2.c3p0.management.ManagementCoordinator", "com.mchange.v2.c3p0.management.NullManagementCoordinator");

            ComboPooledDataSource cpds = new ComboPooledDataSource(connectionName);
      cpds.setDriverClass(driver);
            cpds.setJdbcUrl(url);
      cpds.setUser(username);
      cpds.setPassword(password);
     
      cpds.setAutoCommitOnClose(autoCommit);
     
      cpds.setMaxPoolSize(Integer.parseInt(maxPoolSize));
      cpds.setMinPoolSize(Integer.parseInt(minPoolSize));
      cpds.setAcquireIncrement(Integer.parseInt(acquireIncrement));
      cpds.setInitialPoolSize(Integer.parseInt(initialPoolSize));
      cpds.setMaxIdleTime(Integer.parseInt(maxIdleTime));

            connectionPoolDataSourcesMap.put(connectionName, cpds);
            log.debug("created ds for " + connectionName + " with properties: " + c3p0props);
    } catch (Throwable e) {
      log.error("Failed to create data source for " + connectionName + " with properties: " + c3p0props + ": " + e.getMessage());
    }
    }

    private void loadProperties() {
        if (appProperties != null) appProperties.clear();

        appProperties = PropertyReader.loadPropertiesFromFile(DATA_PROPERTIES_FILE);

        if (appProperties == null) appProperties = new Properties();
    }


    public static DatabaseConfig getInstance() {
        return me;
    }

    /**
     * Returns map of sql data type name / data type code.
     * @return map
     */
    public Map<String, Integer> getSQLDataNameTypesMap() {
        return allSQLDataNameTypesMap;
    }

    /**
     * Returns map of sql data type code / java type name.
     * @return map
     */
    public Map<Integer, String> getSQLTypeJavaNamesMap() {
        return allSQLTypeJavaNamesMap;
    }

    /**
     * Required method by <tt>Observer</tt> interface.
     */
    public void update(Observable o, Object arg) {
        init();

        super.setChanged();
        super.notifyObservers();
    }

    /**
     * Returns all properties.
     */
    public Properties getProperties() {
        return appProperties;
    }

    /**
     * Returns a String property corresponding to a key.
     */
    public String getProperty(String key) {
        return appProperties.getProperty(key);
    }

    /**
     * Returns a String property corresponding to a key. If the returned
     * property is null, the default value of the property is returned.
     */
    public String getProperty(String key, String defaultValue) {
        return appProperties.getProperty(key, defaultValue);
    }

    /**
     * Returns default transaction type
     */
    public String getDefaultTransactionType() {
        return defaultTransactionType;
    }

    /**
     * Returns global table naming prefix
     */
    public String getGlobalTableNamingPrefix() {
        return gloablTableNamingPrefix;
    }

    /**
     * Returns global table naming suffix
     */
    public String getGlobalTableNamingSuffix() {
        return gloablTableNamingSuffix;
    }

    /**
     * Checks if using plural nones as table name
     */
    public boolean usePluralTableName() {
        return ("true".equalsIgnoreCase(usePluralTableName))?true:false;
    }

    /**
     * Returns a full table name. A full table name includes global table name
     * prefix and suffix.
     *
     * <p>
     * For example, in a crm schema, all tables might have prefix "CRM_".
     * Therefore, a <tt>USER</tt> table's full name is <tt>CRM_USER</tt>.
     * </p>
     *
     * @param table a slim table name
     * @return a full table name
     */
    public String getFullTableName(String table) {
      if (table == null) throw new IllegalArgumentException("Error in getFullTableName(): table cannot be null.");

      if (table.indexOf('.') != -1) return table;

        String tablePrefix = getGlobalTableNamingPrefix();
        String tableSuffix = getGlobalTableNamingSuffix();

        String fullTableName = table;
        if (!fullTableName.toUpperCase().startsWith(tablePrefix.toUpperCase())) fullTableName = tablePrefix + fullTableName;
        if (!fullTableName.toUpperCase().endsWith(tableSuffix.toUpperCase())) fullTableName = fullTableName + tableSuffix;

        return fullTableName;
    }

    /**
     * Returns a simple table name. A simple table name does not include global
     * table name prefix and suffix.
     *
     * <p>
     * For example, if the table name is "CRM_users_US" which has a prefix
     * "CRM_" and a suffix "_US", the returned slim table name is just
     * "users". Both the prefix and the suffix are removed in the return value.
     * </p>
     *
     * @param fullTableName a full table name
     * @return a simple table name
     */
    public String getSimpleTableName(String fullTableName) {
        String tablePrefix = getGlobalTableNamingPrefix().toUpperCase();
        String tableSuffix = getGlobalTableNamingSuffix().toUpperCase();

        String slimName = fullTableName.toUpperCase();
        if (slimName.startsWith(tablePrefix)) slimName = slimName.substring(tablePrefix.length());
        if (slimName.endsWith(tableSuffix)) slimName = slimName.substring(0, slimName.length() - tableSuffix.length());

        return slimName;
    }

    /**
     * Checks if the current running environment is development environment.
     *
     * @return true if the current running environment is development.
     */
    public boolean isInDevelopmentEnvironment() {
        return ApplicationConfig.getInstance().isInDevelopmentEnvironment();
    }

    /**
     * Returns default database connection name
     */
    public String getDefaultDatabaseConnectionName() {
        return defaultDatabaseConnection;
    }

    public String tryToUseTestDatabaseConnection() {
      String testDatabaseConnectionName = null;
      if (defaultDatabaseConnection.endsWith("_development")) {
        int lastUnderscore = defaultDatabaseConnection.indexOf('_');
        testDatabaseConnectionName = defaultDatabaseConnection.substring(0, lastUnderscore);
        testDatabaseConnectionName = testDatabaseConnectionName + "_test";
        if (getPredefinedDatabaseConnectionProperties(testDatabaseConnectionName).size() > 0) {
          defaultDatabaseConnection = testDatabaseConnectionName;
        }
      }
      return testDatabaseConnectionName;
    }

    public void restoreDefaultDatabaseConnectionName() {
      defaultDatabaseConnection = getProperty("default.database.connection.name", DEFAULT_VALUE_defaultDatabaseConnection);
    }

    /**
     * Returns default database connection properties
     */
    public Properties getDefaultDatabaseConnectionProperties() {
        return getPredefinedDatabaseConnectionProperties(getDefaultDatabaseConnectionName());
    }

    /**
     * Returns database connection properties
     */
    public Properties getPredefinedDatabaseConnectionProperties(String connName) {
      if (connName == null)
        throw new IllegalArgumentException("Error in " +
            "getPredefinedDatabaseConnectionProperties: connName cannot be null.");

        NamedProperties np = databaseConnectionsMap.get(connName);
        return (np != null)?np.getProperties():(new Properties());
    }

    /**
     * Returns database connection names
     */
    public Iterator<String> getPredefinedDatabaseConnectionNames() {
        return databaseConnectionsMap.keySet().iterator();
    }

    /**
     * Returns properties of reference data specified by the name
     */
    public Properties getReferenceDataProperties(String referenceDataName) {
        NamedProperties np = referenceDataMap.get(referenceDataName);
        return (np != null)?np.getProperties():(new Properties());
    }

    /**
     * Returns a list of all reference data names
     *
     * @return list of reference data names
     */
    public List<String> getReferenceDataNames() {
        return referenceDataNames;
    }

    /**
     * Returns a map of all reference data
     *
     * @return map of reference data
     */
    public Map<String, NamedProperties> getReferenceDataMap() {
        return referenceDataMap;
    }

    /**
     * Checks if auto audit is allowed for create operation.
     */
    public boolean allowAutoAuditCreate() {
        return (autoAuditCreate != null)?true:false;
    }

    /**
     * Checks if auto audit is allowed for update operation.
     */
    public boolean allowAutoAuditUpdate() {
        return (autoAuditUpdate != null)?true:false;
    }

    /**
     * Returns list of potential column names that are automatically audited
     * for create operation.
     */
    public List<String> getAutoAuditListForCreate() {
        return autoAuditListForCreate;
    }

    /**
     * Returns list of potential column names that are automatically audited
     * for update operation.
     */
    public List<String> getAutoAuditListForUpdate() {
        return autoAuditListForUpdate;
    }

    /**
     * Checks if a column is auto audited for create operation.
     */
    public boolean isAutoAuditCreate(String column) {
        if (autoAuditListForCreate != null && column != null) {
            return autoAuditListForCreate.contains(column.toLowerCase());
        }
        return false;
    }

    /**
     * Checks if a column is auto audited for update operation.
     */
    public boolean isAutoAuditUpdate(String column) {
        if (autoAuditListForUpdate != null && column != null) {
            return autoAuditListForUpdate.contains(column.toLowerCase());
        }
        return false;
    }

    /**
     * Checks if a vendor name is allowed.
     */
    public static boolean isBuiltInVendorName(String vendor) {
      if (vendor == null)
        throw new IllegalArgumentException("Vendor name is empty.");
        return ALL_BUILTIN_DATABASE_VENDORS.contains(vendor.toUpperCase());
    }

    /**
     * Returns pooled data source for a connection name
     */
    public DataSource getPooledDataSource(String connectionName) {
      return connectionPoolDataSourcesMap.get(connectionName);
    }

    /**
     * Returns pooled data source for default connection name
     */
    public DataSource getPooledDataSource() {
        return getPooledDataSource(getDefaultDatabaseConnectionName());
    }

    /**
     * Destroys all connection pools if there is any.
     */
  public void destroy() {
    try {
            for (Map.Entry<String, ComboPooledDataSource> entry : connectionPoolDataSourcesMap.entrySet()) {
                DataSources.destroy(entry.getValue());
            }
    } catch (SQLException ex) {
      log.error("ERROR ERROR ERROR failed to close connection pool: " + ex.getMessage());
    }
  }
}
TOP

Related Classes of com.scooterframework.orm.sqldataexpress.config.DatabaseConfig

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.