001: /*
002: * $Header: /cvsroot/mvnforum/myvietnam/src/net/myvietnam/mvncore/db/DBUtils2.java,v 1.3 2007/05/16 04:19:17 phuongpdd Exp $
003: * $Author: phuongpdd $
004: * $Revision: 1.3 $
005: * $Date: 2007/05/16 04:19:17 $
006: *
007: * ====================================================================
008: *
009: * Copyright (C) 2002-2006 by MyVietnam.net
010: *
011: * All copyright notices regarding MyVietnam and MyVietnam CoreLib
012: * MUST remain intact in the scripts and source code.
013: *
014: * This library is free software; you can redistribute it and/or
015: * modify it under the terms of the GNU Lesser General Public
016: * License as published by the Free Software Foundation; either
017: * version 2.1 of the License, or (at your option) any later version.
018: *
019: * This library is distributed in the hope that it will be useful,
020: * but WITHOUT ANY WARRANTY; without even the implied warranty of
021: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
022: * Lesser General Public License for more details.
023: *
024: * You should have received a copy of the GNU Lesser General Public
025: * License along with this library; if not, write to the Free Software
026: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
027: *
028: * Correspondence and Marketing Questions can be sent to:
029: * info at MyVietnam net
030: *
031: * @author: Minh Nguyen
032: * @author: Mai Nguyen
033: */
034: package net.myvietnam.mvncore.db;
035:
036: import java.sql.*;
037:
038: import javax.sql.DataSource;
039:
040: import net.myvietnam.mvncore.SecondaryMVNCoreConfig;
041: import net.myvietnam.mvncore.service.MvnCoreInfoService;
042: import net.myvietnam.mvncore.service.MvnCoreServiceFactory;
043: import net.myvietnam.mvncore.util.DateUtil;
044:
045: import org.apache.commons.logging.Log;
046: import org.apache.commons.logging.LogFactory;
047:
048: /**
049: * A database utility class to handle all the database stuffs
050: * in the MyVietnam framework
051: */
052: public final class DBUtils2 {
053:
054: private static Log log = LogFactory.getLog(DBUtils2.class);
055:
056: private static int databaseType = DBUtils.DATABASE_UNKNOWN;
057:
058: private static boolean useDatasource = false;
059:
060: private static int maxTimeToWait = 2000;// 2 seconds
061:
062: private static int minutesBetweenRefresh = 30;// 30 minutes
063:
064: private static DBConnectionManager connectionManager = null;
065:
066: private static DataSource dataSource = null;
067:
068: private static long lastGetConnectionTime = 0;
069:
070: private static long lastCloseAllConnectionsTime = 0;
071:
072: private static MvnCoreInfoService mvnCoreInfo = MvnCoreServiceFactory
073: .getMvnCoreService().getMvnCoreInfoService();
074:
075: // static init of the class
076: static {
077: load();
078: }
079:
080: // @question: The online users's still keep accessing db.
081: // Can we reload database ?
082: private static void load() {
083: DBOptions dbOptions = SecondaryMVNCoreConfig.getDbOptions();
084:
085: databaseType = dbOptions.getDbType();
086: if (databaseType != DBUtils.DATABASE_UNKNOWN) {
087: log.info("Set DATABASE_TYPE = " + databaseType);
088: }
089: useDatasource = dbOptions.isUseDataSource();
090: if (useDatasource) {
091: String dataSourceName = "";
092: try {
093: javax.naming.Context context = new javax.naming.InitialContext();
094: // sample data source = java:comp/env/jdbc/MysqlDataSource
095: dataSourceName = dbOptions.getDataSourceName();
096: dataSource = (DataSource) context
097: .lookup(dataSourceName);
098: log.info("DBUtils2 : use datasource = "
099: + dataSourceName);
100: } catch (javax.naming.NamingException e) {
101: log.error("Cannot get DataSource: datasource name = "
102: + dataSourceName, e);
103: }
104: } else {
105: maxTimeToWait = dbOptions.getTimeout();
106: minutesBetweenRefresh = dbOptions.getRefreshMinutes();
107:
108: connectionManager = DBConnectionManager
109: .getDBConnectionManager(dbOptions);
110:
111: log
112: .info("DBUtils2 : use built-in DBConnectionManager (MAX_TIME_TO_WAIT = "
113: + maxTimeToWait
114: + ", MINUTES_BETWEEN_REFRESH = "
115: + minutesBetweenRefresh + ")");
116: }
117: log.info("DBUtils2 (re)loaded. Detailed info: "
118: + mvnCoreInfo.getProductVersion() + " (Build: "
119: + mvnCoreInfo.getProductReleaseDate() + ")");
120: }
121:
122: private DBUtils2() {// so cannot new an instance
123: }
124:
125: /**
126: * Use this method to get the database type. This method will automatically
127: * detect the database type. You could override this value by modifying
128: * the value in mvncore_db_DBOptions.properties
129: * @return : the database type
130: */
131: public static int getDatabaseType() {
132: if (databaseType == DBUtils.DATABASE_UNKNOWN) {
133: Connection connection = null;
134: try {
135: connection = DBUtils2.getConnection();
136: DatabaseMetaData dbmd = connection.getMetaData();
137: String databaseName = dbmd.getDatabaseProductName()
138: .toLowerCase();
139: if (databaseName.indexOf("oracle") != -1) {
140: databaseType = DBUtils.DATABASE_ORACLE;
141: } else if (databaseName.indexOf("sql server") != -1) {
142: databaseType = DBUtils.DATABASE_SQLSERVER;
143: } else if (databaseName.indexOf("mysql") != -1) {// "MySQL"
144: databaseType = DBUtils.DATABASE_MYSQL;
145: } else if (databaseName.indexOf("derby") != -1) {
146: databaseType = DBUtils.DATABASE_DERBY;
147: } else if (databaseName.indexOf("postgresql") != -1) {
148: databaseType = DBUtils.DATABASE_POSTGRESQL;
149: } else if (databaseName.indexOf("hsql") != -1) {
150: databaseType = DBUtils.DATABASE_HSQLDB;
151: } else if (databaseName.indexOf("sap") != -1) {// "SAP DB"
152: databaseType = DBUtils.DATABASE_SAPDB;
153: } else if (databaseName.indexOf("firebird") != -1) {//"firebird"
154: databaseType = DBUtils.DATABASE_FIREBIRD;
155: } else {
156: databaseType = DBUtils.DATABASE_GENERAL;
157: }
158: log.info("Auto detect DATABASE_TYPE = " + databaseType
159: + " ("
160: + DBUtils.getDatabaseTypeName(databaseType)
161: + ")");
162: } catch (Exception ex) {
163: log.error("Error when running getDatabaseType", ex);
164: } finally {
165: DBUtils2.closeConnection(connection);
166: }
167: }
168: return databaseType;
169: }
170:
171: /**
172: * Get a connection from the connection pool. The returned connection
173: * must be closed by calling DBUtils2.closeConnection()
174: * @return : a new connection from the pool if succeed
175: * @throws SQLException : if cannot get a connection from the pool
176: */
177: public static Connection getConnection() throws SQLException {
178:
179: long now = System.currentTimeMillis();
180: lastGetConnectionTime = now;
181: // now check if we have not close all connections to refresh
182: // after MINUTES_BETWEEN_REFRESH minutes, then will do it now
183: if (now - lastCloseAllConnectionsTime > DateUtil.MINUTE
184: * minutesBetweenRefresh) {
185: boolean isBalance = closeAllConnections();
186: if (isBalance == false) {
187: try {
188: // wait for the checked-out connections to be returned and closed
189: Thread.sleep(2000);
190: log
191: .debug("DBUtils2: sleep 2 seconds for checked-out connections to returned and closed.");
192: } catch (Exception ex) {
193: }
194: }
195: }
196:
197: Connection conection = null;
198:
199: if (useDatasource) {
200: if (dataSource != null) {
201: conection = dataSource.getConnection();
202: }
203: } else {
204: if (connectionManager != null) {
205: conection = connectionManager
206: .getConnection(maxTimeToWait);
207: } else {
208: log
209: .fatal("Assertion: DBUtils2.connectionManager == null");
210: }
211: }
212:
213: if (conection == null) {
214: throw new SQLException(
215: "DBUtils2: Cannot get connection from Connection Pool.");
216: }
217: return conection;
218: }
219:
220: /**
221: * Close all the connections that currently in the pool
222: * This method could be used to refresh the database connection
223: * @return true if the pool is empty and balance
224: * false if the pool has returned some connection to outside
225: */
226: public static boolean closeAllConnections() {
227: log.debug("DBUtils2.closeAllConnections is called.");
228: boolean retValue = true;// balance (default)
229: lastCloseAllConnectionsTime = System.currentTimeMillis();
230: if (useDatasource) {
231: if (dataSource != null) {
232: // do nothing here now
233: }
234: } else {
235: if (connectionManager != null) {
236: retValue = connectionManager.release();
237: } else {
238: log
239: .fatal("Assertion: DBUtils2.connectionManager == null");
240: }
241: }
242: return retValue;
243: }
244:
245: /**
246: * Use this method to return the connection to the connection pool
247: * Do not use this method to close connection that is not from
248: * the connection pool
249: * @param connection : the connection that needs to be returned to the pool
250: */
251: public static void closeConnection(Connection connection) {
252: if (connection == null)
253: return;
254:
255: if (useDatasource) {
256: try {
257: connection.close();
258: } catch (SQLException e) {
259: log.error("DBUtils2: Cannot close connection.", e);
260: }
261: } else {
262: //connectionManager.freeConnection(connection);
263: try {
264: connection.close();
265: } catch (SQLException e) {
266: log
267: .error("Assertion: this should not happen when release connection.");
268: }
269: }
270: }
271:
272: }
|