${database.allClassCopyright}package ${glPackageBaseCommon};
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Timestamp;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.seasar.dbflute.DBDef;
import org.seasar.dbflute.QLog;
import org.seasar.dbflute.XLog;
import org.seasar.dbflute.bhv.core.supplement.SequenceCacheKeyGenerator;
import org.seasar.dbflute.bhv.outsidesql.factory.OutsideSqlExecutorFactory;
import org.seasar.dbflute.cbean.sqlclause.SqlClauseCreator;
import org.seasar.dbflute.dbmeta.name.SqlNameFilter;
import org.seasar.dbflute.exception.IllegalDBFluteConfigAccessException;
import org.seasar.dbflute.jdbc.DataSourceHandler;
import org.seasar.dbflute.jdbc.NotClosingConnectionWrapper;
import org.seasar.dbflute.jdbc.PhysicalConnectionDigger;
import org.seasar.dbflute.jdbc.StatementConfig;
import org.seasar.dbflute.jdbc.ValueType;
import org.seasar.dbflute.s2dao.valuetype.TnValueTypes;
import org.seasar.dbflute.s2dao.valuetype.plugin.OracleAgent;
import org.seasar.dbflute.s2dao.valuetype.plugin.OracleDateType;
import org.seasar.dbflute.s2dao.valuetype.plugin.OracleArrayType;
import org.seasar.dbflute.s2dao.valuetype.plugin.OracleStructType;
import org.seasar.dbflute.twowaysql.DisplaySqlBuilder;
import org.seasar.dbflute.util.DfReflectionUtil;
#if ($database.isTargetContainerSeasar())
import org.seasar.extension.dbcp.ConnectionWrapper;
#end
#if ($database.isTargetContainerSpring())
import org.springframework.jdbc.datasource.DataSourceUtils;
#end
/**
* @author ${database.classAuthor}
*/
public class ${glDBFluteConfig} {
// ===================================================================================
// Definition
// ==========
/** Log instance. */
private static final Log _log = LogFactory.getLog(${glDBFluteConfig}.class);
#if ($database.isOutsideSqlPackageValid())
/** The default package of outside SQL. The default value is '${database.outsideSqlPackage}'. */
private static final String DEFAULT_OUTSIDE_SQL_PACKAGE = "${database.outsideSqlPackage}";
#else
/** The default package of outside SQL. */
private static final String DEFAULT_OUTSIDE_SQL_PACKAGE = null;
#end
#if ($database.isSqlLogRegistryValid())
/** The default value of whether it uses SQL Log Registry. The default value is true. */
private static final boolean DEFAULT_USE_SQL_LOG_REGISTRY = true;
#else
/** The default value of whether it uses SQL Log Registry. The default value is false. */
private static final boolean DEFAULT_USE_SQL_LOG_REGISTRY = false;
#end
/** Singleton instance. */
private static final ${glDBFluteConfig} _instance = new ${glDBFluteConfig}();
// ===================================================================================
// Attribute
// =========
// -----------------------------------------------------
// Configuration
// -------------
protected StatementConfig _defaultStatementConfig;
protected boolean _queryLogLevelInfo;
protected boolean _executeStatusLogLevelInfo;
protected String _logDateFormat;
protected String _logTimestampFormat;
protected DataSourceHandler _dataSourceHandler;
protected PhysicalConnectionDigger _physicalConnectionDigger;
protected SequenceCacheKeyGenerator _sequenceCacheKeyGenerator;
protected SqlClauseCreator _sqlClauseCreator;
protected SqlNameFilter _tableSqlNameFilter;
protected String _outsideSqlPackage = DEFAULT_OUTSIDE_SQL_PACKAGE;
protected OutsideSqlExecutorFactory _outsideSqlExecutorFactory;
protected boolean _useSqlLogRegistry = DEFAULT_USE_SQL_LOG_REGISTRY;
protected boolean _disableSelectIndex;
protected boolean _internalDebug;
// -----------------------------------------------------
// Database Dependency
// -------------------
#if ($database.isAvailableDatabaseDependency())
#if ($database.isDatabasePostgreSQL())
protected org.seasar.dbflute.dbway.WayOfPostgreSQL.OperandOfLikeSearch _fullTextSearchOperand
= org.seasar.dbflute.dbway.WayOfPostgreSQL.OperandOfLikeSearch.FULL_TEXT_SEARCH;
#end
#end
// -----------------------------------------------------
// Lock
// ----
protected boolean _locked = true; // at first locked
// ===================================================================================
// Constructor
// ===========
/**
* Constructor.
*/
private ${glDBFluteConfig}() { // adjusts default settings
_physicalConnectionDigger = new ImplementedPhysicalConnectionDigger();
if (isCurrentDBDef(DBDef.Oracle)) {
// date formatting has two points:
// o the DATE type of Oracle has seconds
// o it uses a date literal of Oracle
_logDateFormat = "timestamp $df:{yyyy-MM-dd HH:mm:ss}";
_logTimestampFormat = "timestamp $df:{" + DisplaySqlBuilder.DEFAULT_TIMESTAMP_FORMAT + "}";
}
#if ($database.isDatabaseOracle() && $database.isAvailableDatabaseNativeJDBC())
// treats as uses Oracle date of database native JDBC to get best performances
TnValueTypes.registerBasicValueType(DBDef.Oracle, java.util.Date.class, new ImplementedOracleDateType());
#end
}
// ===================================================================================
// Singleton
// =========
/**
* Get singleton instance.
* @return Singleton instance. (NotNull)
*/
public static ${glDBFluteConfig} getInstance() {
return _instance;
}
// ===================================================================================
// Default Statement Config
// ========================
public StatementConfig getDefaultStatementConfig() {
return _defaultStatementConfig;
}
public void setDefaultStatementConfig(StatementConfig defaultStatementConfig) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting defaultStatementConfig: " + defaultStatementConfig);
}
_defaultStatementConfig = defaultStatementConfig;
}
// ===================================================================================
// Query Log Level Info
// ====================
public void setQueryLogLevelInfo(boolean queryLogLevelInfo) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting queryLogLevelInfo: " + queryLogLevelInfo);
}
QLog.unlock();
QLog.setQueryLogLevelInfo(queryLogLevelInfo);
QLog.lock();
}
// ===================================================================================
// Execute Status Log Level Info
// =============================
public void setExecuteStatusLogLevelInfo(boolean executeStatusLogLevelInfo) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting executeStatusLogLevelInfo: " + executeStatusLogLevelInfo);
}
XLog.unlock();
XLog.setExecuteStatusLogLevelInfo(executeStatusLogLevelInfo);
XLog.lock();
}
// ===================================================================================
// Log Format
// ==========
public String getLogDateFormat() {
return _logDateFormat;
}
public void setLogDateFormat(String logDateFormat) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting logDateFormat: " + logDateFormat);
}
_logDateFormat = logDateFormat;
}
public String getLogTimestampFormat() {
return _logTimestampFormat;
}
public void setLogTimestampFormat(String logTimestampFormat) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting logTimestampFormat: " + logTimestampFormat);
}
_logTimestampFormat = logTimestampFormat;
}
// [DBFlute-0.9.0]
// ===================================================================================
// DataSource Handler
// ==================
/**
* @return The handler of data source. (Nullable)
*/
public DataSourceHandler getDataSourceHandler() {
return _dataSourceHandler;
}
/**
* @param dataSourceHandler The handler of data source. (Nullable)
*/
public void setDataSourceHandler(DataSourceHandler dataSourceHandler) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting dataSourceHandler: " + dataSourceHandler);
}
_dataSourceHandler = dataSourceHandler;
}
// [DBFlute-0.9.7.6]
// ===================================================================================
// PhysicalConnection Digger
// =========================
/**
* @return The digger of physical connection. (NotNull: has a default instance)
*/
public PhysicalConnectionDigger getPhysicalConnectionDigger() {
return _physicalConnectionDigger;
}
/**
* @param physicalConnectionDigger The digger of physical connection. (NotNull)
*/
public void setPhysicalConnectionDigger(PhysicalConnectionDigger physicalConnectionDigger) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting physicalConnectionDigger: " + physicalConnectionDigger);
}
if (physicalConnectionDigger == null) {
throw new IllegalArgumentException("The argument 'physicalConnectionDigger' should not be null.");
}
_physicalConnectionDigger = physicalConnectionDigger;
}
// [DBFlute-0.9.6.4]
// ===================================================================================
// Sequence Cache
// ==============
/**
* @return The key generator of sequence cache. (Nullable)
*/
public SequenceCacheKeyGenerator getSequenceCacheKeyGenerator() {
return _sequenceCacheKeyGenerator;
}
/**
* @param sequenceCacheKeyGenerator The key generator of sequence cache. (Nullable)
*/
public void setSequenceCacheKeyGenerator(SequenceCacheKeyGenerator sequenceCacheKeyGenerator) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting sequenceCacheKeyGenerator: " + sequenceCacheKeyGenerator);
}
_sequenceCacheKeyGenerator = sequenceCacheKeyGenerator;
}
// [DBFlute-0.9.6.9]
// ===================================================================================
// SqlClause Creator
// =================
/**
* @return The creator of SQL clause. (Nullable)
*/
public SqlClauseCreator getSqlClauseCreator() {
return _sqlClauseCreator;
}
/**
* @param sqlClauseCreator The creator of SQL clause. (Nullable)
*/
public void setSqlClauseCreator(SqlClauseCreator sqlClauseCreator) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting sqlClauseCreator: " + sqlClauseCreator);
}
_sqlClauseCreator = sqlClauseCreator;
}
// [DBFlute-0.9.7.6]
// ===================================================================================
// TableSqlName Filter
// ===================
/**
* @return The SQL name filter for table. (Nullable)
*/
public SqlNameFilter getTableSqlNameFilter() {
return _tableSqlNameFilter;
}
/**
* Set the SQL name filter for table.
* This setting should be called before container's initialization.
* (its exact meaning is: before class loading of DBMeta for table)
* @param tableSqlNameFilter The SQL name filter for table. (Nullable)
*/
public void setTableSqlNameFilter(SqlNameFilter tableSqlNameFilter) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting tableSqlNameFilter: " + tableSqlNameFilter);
}
_tableSqlNameFilter = tableSqlNameFilter;
}
// ===================================================================================
// OutsideSql Package
// ==================
/**
* @return The package of outside SQL. (Nullable)
*/
public String getOutsideSqlPackage() {
return _outsideSqlPackage;
}
/**
* @param outsideSqlPackage The package of outside SQL. (Nullable)
*/
public void setOutsideSqlPackage(String outsideSqlPackage) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting outsideSqlPackage: " + outsideSqlPackage);
}
_outsideSqlPackage = outsideSqlPackage;
}
// [DBFlute-0.9.7.0]
// ===================================================================================
// OutsideSql Executor
// ===================
public OutsideSqlExecutorFactory getOutsideSqlExecutorFactory() {
return _outsideSqlExecutorFactory;
}
public void setOutsideSqlExecutorFactory(OutsideSqlExecutorFactory outsideSqlExecutorFactory) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting outsideSqlExecutorFactory: " + outsideSqlExecutorFactory);
}
_outsideSqlExecutorFactory = outsideSqlExecutorFactory;
}
// [DBFlute-0.8.2]
// ===================================================================================
// SQL Log Registry
// ================
public boolean isUseSqlLogRegistry() {
return _useSqlLogRegistry;
}
public void setUseSqlLogRegistry(boolean useSqlLogRegistry) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting useSqlLogRegistry: " + useSqlLogRegistry);
}
_useSqlLogRegistry = useSqlLogRegistry;
}
// [DBFlute-0.9.0]
// ===================================================================================
// Select Index
// ============
public boolean isDisableSelectIndex() {
return _disableSelectIndex;
}
public void setDisableSelectIndex(boolean disableSelectIndex) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting disableSelectIndex: " + disableSelectIndex);
}
_disableSelectIndex = disableSelectIndex;
}
// ===================================================================================
// Database Dependency
// ===================
#if ($database.isAvailableDatabaseDependency())
#if ($database.isDatabasePostgreSQL())
// -----------------------------------------------------
// Full-Text Search Operand
// ------------------------
public org.seasar.dbflute.dbway.WayOfPostgreSQL.OperandOfLikeSearch getFullTextSearchOperand() {
return _fullTextSearchOperand;
}
public void useDefaultFullTextSearchOperand() {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Using fullTextSearchOperand: Default");
}
_fullTextSearchOperand = org.seasar.dbflute.dbway.WayOfPostgreSQL.OperandOfLikeSearch.FULL_TEXT_SEARCH;
}
public void useOldFullTextSearchOperand() {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Using fullTextSearchOperand: Old");
}
_fullTextSearchOperand = org.seasar.dbflute.dbway.WayOfPostgreSQL.OperandOfLikeSearch.OLD_FULL_TEXT_SEARCH;
}
#end
#end
// ===================================================================================
// Internal Debug
// ==============
public boolean isInternalDebug() {
return _internalDebug;
}
public void setInternalDebug(boolean internalDebug) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Setting internalDebug: " + internalDebug);
}
_internalDebug = internalDebug;
}
// ===================================================================================
// Value Type
// ==========
/**
* Register the basic value type.
* This setting is shared per DBMS in the same class loader.
* @param keyType The type as key. (NotNull)
* @param valueType The basic value type. (NotNull)
*/
public void registerBasicValueType(Class> keyType, ValueType valueType) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Registering basic valueType: " + keyType + " = " + valueType);
}
TnValueTypes.registerBasicValueType(currentDBDef(), keyType, valueType);
}
public void removeBasicValueType(Class> keyType) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Removing basic valueType: " + keyType);
}
TnValueTypes.removeBasicValueType(currentDBDef(), keyType);
}
/**
* Register the plug-in value type.
* This setting is shared per DBMS in the same class loader.
* @param keyName The name as key. (NotNull)
* @param valueType The plug-in value type. (NotNull)
*/
public void registerPluginValueType(String keyName, ValueType valueType) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Registering plug-in valueType: " + keyName + " = " + valueType);
}
TnValueTypes.registerPluginValueType(currentDBDef(), keyName, valueType);
}
public void removePluginValueType(String keyName) {
assertNotLocked();
if (_log.isInfoEnabled()) {
_log.info("...Removing plug-in valueType: keyName=" + keyName);
}
TnValueTypes.removePluginValueType(currentDBDef(), keyName);
}
// ===================================================================================
// Configuration Lock
// ==================
public boolean isLocked() {
return _locked;
}
public void lock() {
if (_log.isInfoEnabled()) {
_log.info("...Locking the configuration of DBFlute");
}
_locked = true;
}
public void unlock() {
if (_log.isInfoEnabled()) {
_log.info("...Unlocking the configuration of DBFlute");
}
_locked = false;
}
protected void assertNotLocked() {
if (!isLocked()) {
return;
}
String msg = "The configuration of DBFlute is locked.";
throw new IllegalDBFluteConfigAccessException(msg);
}
// ===================================================================================
// Assist Helper
// =============
protected DBDef currentDBDef() {
return ${glDBCurrent}.getInstance().currentDBDef();
}
protected boolean isCurrentDBDef(DBDef currentDBDef) {
return ${glDBCurrent}.getInstance().isCurrentDBDef(currentDBDef);
}
// ===================================================================================
// Implemented Class
// =================
// -----------------------------------------------------
// Spring
// ------
protected static class SpringDBCPDataSourceHandler implements DataSourceHandler {
public Connection getConnection(DataSource ds) throws SQLException {
final Connection conn = getConnectionFromUtils(ds);
if (isConnectionTransactional(conn, ds)) {
return new NotClosingConnectionWrapper(conn);
} else {
return conn;
}
}
public Connection getConnectionFromUtils(DataSource ds) {
#if ($database.isTargetContainerSpring())
return DataSourceUtils.getConnection(ds);
#else
throw new UnsupportedOperationException("This method is only for Spring Framework.");
#end
}
public boolean isConnectionTransactional(Connection conn, DataSource ds) {
#if ($database.isTargetContainerSpring())
return DataSourceUtils.isConnectionTransactional(conn, ds);
#else
throw new UnsupportedOperationException("This method is only for Spring Framework.");
#end
}
@Override
public String toString() {
return "SpringDBCPDataSourceHandler(for Spring and Commons-DBCP)";
}
}
// -----------------------------------------------------
// Oracle
// ------
public static class ImplementedOracleAgent implements OracleAgent {
public Object toOracleDate(Timestamp timestamp) {
#if ($database.isAvailableOracleNativeJDBC())
return new oracle.sql.DATE(timestamp);
#else
throw new UnsupportedOperationException("This method is only for Oracle.");
#end
}
public Object toOracleArray(Connection conn, String arrayTypeName, Object arrayValue) throws SQLException {
#if ($database.isAvailableOracleNativeJDBC())
oracle.sql.ArrayDescriptor desc = oracle.sql.ArrayDescriptor.createDescriptor(arrayTypeName, conn);
return new oracle.sql.ARRAY(desc, conn, arrayValue);
#else
throw new UnsupportedOperationException("This method is only for Oracle.");
#end
}
public Object toStandardArray(Object oracleArray) throws SQLException {
#if ($database.isAvailableOracleNativeJDBC())
return ((oracle.sql.ARRAY)oracleArray).getArray();
#else
throw new UnsupportedOperationException("This method is only for Oracle.");
#end
}
public boolean isOracleArray(Object obj) {
#if ($database.isAvailableOracleNativeJDBC())
return obj instanceof oracle.sql.ARRAY;
#else
throw new UnsupportedOperationException("This method is only for Oracle.");
#end
}
public Object toOracleStruct(Connection conn, String structTypeName, Object[] attrs) throws SQLException {
#if ($database.isAvailableOracleNativeJDBC())
oracle.sql.StructDescriptor desc = new oracle.sql.StructDescriptor(structTypeName, conn);
return new ImplementedOracleStructWrapper(new oracle.sql.STRUCT(desc, conn, attrs));
#else
throw new UnsupportedOperationException("This method is only for Oracle.");
#end
}
public Object[] toStandardStructAttributes(Object oracleStruct) throws SQLException {
#if ($database.isAvailableOracleNativeJDBC())
return ((oracle.sql.STRUCT)oracleStruct).getAttributes();
#else
throw new UnsupportedOperationException("This method is only for Oracle.");
#end
}
public boolean isOracleStruct(Object obj) {
#if ($database.isAvailableOracleNativeJDBC())
return obj instanceof oracle.sql.STRUCT;
#else
throw new UnsupportedOperationException("This method is only for Oracle.");
#end
}
public PhysicalConnectionDigger getPhysicalConnectionDigger() {
return ${glDBFluteConfig}.getInstance().getPhysicalConnectionDigger();
}
}
#if ($database.isAvailableOracleNativeJDBC())
public static class ImplementedOracleStructWrapper implements oracle.sql.ORAData {
protected oracle.sql.STRUCT _struct;
public ImplementedOracleStructWrapper(oracle.sql.STRUCT struct) {
_struct = struct;
}
public oracle.sql.Datum toDatum(Connection conn) throws SQLException {
return _struct;
}
}
#end
public static class ImplementedOracleDateType extends OracleDateType {
@Override
protected OracleAgent createOracleAgent() {
return new ImplementedOracleAgent();
}
}
public static class ImplementedOracleArrayType extends OracleArrayType {
public ImplementedOracleArrayType(String arrayTypeName, Class> elementType) {
super(arrayTypeName, elementType);
}
@Override
protected OracleAgent createOracleAgent() {
return new ImplementedOracleAgent();
}
}
public static class ImplementedOracleStructType extends OracleStructType {
public ImplementedOracleStructType(String structTypeName, Class> entityType) {
super(structTypeName, entityType);
}
@Override
protected OracleAgent createOracleAgent() {
return new ImplementedOracleAgent();
}
}
// -----------------------------------------------------
// Physical Connection
// -------------------
public static class ImplementedPhysicalConnectionDigger implements PhysicalConnectionDigger {
public Connection digUp(Connection conn) throws SQLException {
if (conn instanceof NotClosingConnectionWrapper) {
conn = ((NotClosingConnectionWrapper) conn).getActualConnection();
}
conn = resolveS2DBCP(conn);
conn = resolveCommonsDBCP(conn);
return conn;
}
protected Connection resolveS2DBCP(Connection conn) {
#if ($database.isTargetContainerSeasar())
if (conn instanceof ConnectionWrapper) {
conn = ((ConnectionWrapper)conn).getPhysicalConnection();
}
#end
return conn;
}
protected Connection resolveCommonsDBCP(Connection conn) {
if ("org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper".equals(conn.getClass().getName())) {
conn = getFieldConnection(conn, "delegate");
}
if ("org.apache.commons.dbcp.PoolableConnection".equals(conn.getClass().getName())) {
conn = getFieldConnection(conn, "_conn");
}
return conn;
}
protected Connection getFieldConnection(Connection conn, String fieldName) {
Field field = DfReflectionUtil.getWholeField(conn.getClass(), fieldName);
return (Connection) DfReflectionUtil.getValueForcedly(field, conn);
}
}
}