DbModelMysql.java
/*
* This file is part of Waarp Project (named also Waarp or GG).
*
* Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
* tags. See the COPYRIGHT.txt in the distribution for a full listing of
* individual contributors.
*
* All Waarp Project is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Waarp . If not, see <http://www.gnu.org/licenses/>.
*/
package org.waarp.common.database.model;
import com.mysql.jdbc.Driver;
import io.netty.util.internal.PlatformDependent;
import org.waarp.common.database.DbAdmin;
import org.waarp.common.database.DbConnectionPool;
import org.waarp.common.database.DbConstant;
import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
import org.waarp.common.logging.SysErrLogger;
import org.waarp.common.logging.WaarpLogger;
import org.waarp.common.logging.WaarpLoggerFactory;
import org.waarp.common.utility.WaarpSystemUtil;
import javax.sql.ConnectionPoolDataSource;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Timer;
/**
* MySQL Database Model implementation
*/
public abstract class DbModelMysql extends DbModelCommonMariadbMySql {
/**
* Internal Logger
*/
private static final WaarpLogger logger =
WaarpLoggerFactory.getLogger(DbModelMysql.class);
private static final DbType type = DbType.MySQL;
private static final String MYSQL_CONNECTION_POOL_DATA_SOURCE_JRE6 =
"com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource";
private static final String MYSQL_CONNECTION_POOL_DATA_SOURCE_JRE8 =
"com.mysql.cj.jdbc.MysqlConnectionPoolDataSource";
public static final String MYSQL_DRIVER_JRE6 = "com.mysql.jdbc.Driver";
public static final String MYSQL_DRIVER_JRE8 = "com.mysql.cj.jdbc.Driver";
private static final String
CANNOT_INITIALIZE_MYSQL_CONNECTION_POOL_DATA_SOURCE =
"Cannot initialize MysqlConnectionPoolDataSource";
protected static class DbTypeResolverMySQL
extends DbModelAbstract.DbTypeResolver {
@Override
public final String getType(final int sqlType) {
return DBType.getType(sqlType);
}
@Override
public final String getCreateTable() {
return "CREATE TABLE IF NOT EXISTS ";
}
@Override
public final String getCreateIndex() {
return "CREATE INDEX ";
}
@Override
public final DbType getDbType() {
return type;
}
}
static {
dbTypeResolver = new DbTypeResolverMySQL();
}
protected ConnectionPoolDataSource mysqlConnectionPoolDataSource;
protected DbConnectionPool pool;
@Override
public final DbType getDbType() {
return type;
}
/**
* @return a ConnectionPoolDataSource as MysqlConnectionPoolDataSource
*
* @throws WaarpDatabaseNoConnectionException if class not found
*/
private ConnectionPoolDataSource createMysqlConnectionPoolDataSource(
final String dbServer, final String dbUser, final String dbPwd)
throws WaarpDatabaseNoConnectionException {
Class<?> mysqlConnectionPoolDataSourceClass = null;
if (PlatformDependent.javaVersion() >= 8) {
try {
Class.forName(MYSQL_DRIVER_JRE8);
mysqlConnectionPoolDataSourceClass =
Class.forName(MYSQL_CONNECTION_POOL_DATA_SOURCE_JRE8);
} catch (final Exception e) {
try {
mysqlConnectionPoolDataSourceClass =
Class.forName(MYSQL_CONNECTION_POOL_DATA_SOURCE_JRE6);
} catch (final ClassNotFoundException classNotFoundException) {
try {
mysqlConnectionPoolDataSourceClass =
Class.forName(MYSQL_CONNECTION_POOL_DATA_SOURCE_JRE8);
} catch (final ClassNotFoundException e2) {
logger.error(CANNOT_INITIALIZE_MYSQL_CONNECTION_POOL_DATA_SOURCE);
throw new WaarpDatabaseNoConnectionException(
CANNOT_INITIALIZE_MYSQL_CONNECTION_POOL_DATA_SOURCE, e);
}
}
}
} else {
try {
mysqlConnectionPoolDataSourceClass =
Class.forName(MYSQL_CONNECTION_POOL_DATA_SOURCE_JRE6);
} catch (final ClassNotFoundException e) {
logger.error(CANNOT_INITIALIZE_MYSQL_CONNECTION_POOL_DATA_SOURCE);
throw new WaarpDatabaseNoConnectionException(
CANNOT_INITIALIZE_MYSQL_CONNECTION_POOL_DATA_SOURCE, e);
}
}
try {
final ConnectionPoolDataSource cpds =
(ConnectionPoolDataSource) WaarpSystemUtil.newInstance(
mysqlConnectionPoolDataSourceClass);
Method method = mysqlConnectionPoolDataSourceClass.getMethod("setUrl",
dbServer.getClass());
method.invoke(cpds, dbServer);
method = mysqlConnectionPoolDataSourceClass.getMethod("setUser",
dbUser.getClass());
method.invoke(cpds, dbUser);
method = mysqlConnectionPoolDataSourceClass.getMethod("setPassword",
dbPwd.getClass());
method.invoke(cpds, dbPwd);
return cpds;
} catch (final Exception e) {
throw new WaarpDatabaseNoConnectionException(
CANNOT_INITIALIZE_MYSQL_CONNECTION_POOL_DATA_SOURCE, e);
}
}
/**
* Create the object and initialize if necessary the driver
*
* @param dbserver
* @param dbuser
* @param dbpasswd
* @param timer
* @param delay
*
* @throws WaarpDatabaseNoConnectionException
*/
protected DbModelMysql(final String dbserver, final String dbuser,
final String dbpasswd, final Timer timer,
final long delay)
throws WaarpDatabaseNoConnectionException {
this();
mysqlConnectionPoolDataSource =
createMysqlConnectionPoolDataSource(dbserver, dbuser, dbpasswd);
// Create a pool with no limit
pool = new DbConnectionPool(mysqlConnectionPoolDataSource, timer, delay);
logger.info("Some info: MaxConn: {} LogTimeout: {} ForceClose: {}",
pool.getMaxConnections(), pool.getLoginTimeout(),
pool.getTimeoutForceClose());
}
/**
* Create the object and initialize if necessary the driver
*
* @param dbserver
* @param dbuser
* @param dbpasswd
*
* @throws WaarpDatabaseNoConnectionException
*/
protected DbModelMysql(final String dbserver, final String dbuser,
final String dbpasswd)
throws WaarpDatabaseNoConnectionException {
this();
mysqlConnectionPoolDataSource =
createMysqlConnectionPoolDataSource(dbserver, dbuser, dbpasswd);
// Create a pool with no limit
pool = new DbConnectionPool(mysqlConnectionPoolDataSource);
logger.warn(
"Some info: MaxConn: " + pool.getMaxConnections() + " LogTimeout: " +
pool.getLoginTimeout() + " ForceClose: " + pool.getTimeoutForceClose());
}
/**
* Create the object and initialize if necessary the driver
*
* @throws WaarpDatabaseNoConnectionException
*/
protected DbModelMysql() throws WaarpDatabaseNoConnectionException {
if (DbModelFactory.classLoaded.contains(type.name())) {
return;
}
try {
DriverManager.registerDriver(new Driver());
DbModelFactory.classLoaded.add(type.name());
} catch (final SQLException e) {
// SQLException
logger.error(
"Cannot register Driver " + type.name() + ' ' + e.getMessage());
DbConstant.error(e);
throw new WaarpDatabaseNoConnectionException(
"Cannot load database drive:" + type.name(), e);
}
}
@Override
public final void releaseResources() {
if (pool != null) {
try {
pool.dispose();
} catch (final SQLException ignored) {
SysErrLogger.FAKE_LOGGER.ignoreLog(ignored);
}
}
pool = null;
}
@Override
public synchronized int currentNumberOfPooledConnections() {
if (pool != null) {
return pool.getActiveConnections();
}
return DbAdmin.getNbConnection();
}
@Override
public final Connection getDbConnection(final String server,
final String user,
final String passwd)
throws SQLException {
synchronized (this) {
if (pool != null) {
try {
return pool.getConnection();
} catch (final SQLException e) {
// try to renew the pool
try {
mysqlConnectionPoolDataSource =
createMysqlConnectionPoolDataSource(server, user, passwd);
} catch (final WaarpDatabaseNoConnectionException e1) {
logger.debug("Cannot found MySQLPooled class", e1);
pool.dispose();
pool = null;
return super.getDbConnection(server, user, passwd);
}
pool.resetPoolDataSource(mysqlConnectionPoolDataSource);
try {
return pool.getConnection();
} catch (final SQLException e2) {
pool.dispose();
pool = null;
return super.getDbConnection(server, user, passwd);
}
}
}
}
return super.getDbConnection(server, user, passwd);
}
}