001: /*
002: * ConnectionManager.java
003: *
004: * Copyright (C) 2002, 2003, 2004, 2005, 2006 Takis Diakoumis
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: */
021:
022: package org.executequery.datasource;
023:
024: import java.sql.Connection;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.Map;
028: import java.util.Vector;
029: import javax.sql.DataSource;
030: import org.executequery.JDBCProperties;
031: import org.underworldlabs.jdbc.DataSourceException;
032: import org.underworldlabs.util.SystemProperties;
033: import org.executequery.databasemediators.DatabaseConnection;
034: import org.executequery.databasemediators.DatabaseDriver;
035: import org.executequery.util.Log;
036:
037: /* ----------------------------------------------------------
038: * CVS NOTE: Changes to the CVS repository prior to the
039: * release of version 3.0.0beta1 has meant a
040: * resetting of CVS revision numbers.
041: * ----------------------------------------------------------
042: */
043:
044: /**
045: * Manages all data source connections across multiple
046: * sources and associated connection pools.
047: *
048: * @author Takis Diakoumis
049: * @version $Revision: 1.7 $
050: * @date $Date: 2006/10/01 03:12:50 $
051: */
052: public class ConnectionManager {
053:
054: /** the connection 'container' */
055: private static Map<DatabaseConnection, ConnectionPool> connectionPools;
056:
057: /** private constructor to prevent instantiation */
058: private ConnectionManager() {
059: }
060:
061: /**
062: * Creates a stored data source for the specified database
063: * connection properties object.
064: *
065: * @param the database connection properties object
066: */
067: public static void createDataSource(
068: DatabaseConnection databaseConnection)
069: throws DataSourceException {
070:
071: // check the connection has a driver
072: if (databaseConnection.getJDBCDriver() == null) {
073: long driverId = databaseConnection.getDriverId();
074: DatabaseDriver driver = JDBCProperties
075: .getDatabaseDriver(driverId);
076: if (driver != null) {
077: databaseConnection.setJDBCDriver(driver);
078: } else {
079: throw new DataSourceException(
080: "No JDBC driver specified");
081: }
082: }
083:
084: ConnectionDataSource dataSource = new ConnectionDataSource(
085: databaseConnection);
086:
087: // associate the connection pool with the data source
088: ConnectionPool pool = new ConnectionPool(dataSource);
089: //pool.setPoolScheme(SystemProperties.getIntProperty("connection.scheme"));
090: pool.setMinimumConnections(SystemProperties.getIntProperty(
091: "user", "connection.initialcount"));
092: pool.setMaximumConnections(5);
093: pool.ensureCapacity();
094:
095: // TODO: ?????????????????
096: //pool.setMinConns(determineMinimumConnections());
097:
098: if (connectionPools == null) {
099: connectionPools = new HashMap<DatabaseConnection, ConnectionPool>();
100: }
101: connectionPools.put(databaseConnection, pool);
102: databaseConnection.setConnected(true);
103: }
104:
105: /**
106: * Returns a connection from the pool of the specified type.
107: *
108: * @param the stored database connection properties object
109: * @return the connection itself
110: */
111: public static synchronized Connection getConnection(
112: DatabaseConnection databaseConnection)
113: throws DataSourceException {
114:
115: if (databaseConnection == null) {
116: return null;
117: }
118:
119: if (connectionPools == null
120: || !connectionPools.containsKey(databaseConnection)) {
121: createDataSource(databaseConnection);
122: }
123: ConnectionPool pool = connectionPools.get(databaseConnection);
124:
125: Connection connection = pool.getConnection();
126:
127: /*
128: // set some additional saved connection properties
129: try {
130: //connection.setAutoCommit(databaseConnection.isAutoCommit());
131: int txLevel = databaseConnection.getTransactionIsolation();
132: if (txLevel != -1) {
133: connection.setTransactionIsolation(txLevel);
134: }
135: }
136: catch (SQLException e) {
137: try {
138: connection.close();
139: } catch (SQLException e2) {}
140: // re-throw
141: throw new DataSourceException(e);
142: } */
143: return connection;
144: }
145:
146: /**
147: * Closes all connections and removes the pool of the specified type.
148: *
149: * @param the stored database connection properties object
150: */
151: public static synchronized void closeConnection(
152: DatabaseConnection databaseConnection)
153: throws DataSourceException {
154:
155: if (connectionPools.containsKey(databaseConnection)) {
156: Log.info("Disconnecting from data source "
157: + databaseConnection.getName());
158: ConnectionPool pool = connectionPools
159: .get(databaseConnection);
160: pool.close();
161: connectionPools.remove(databaseConnection);
162: pool = null;
163: databaseConnection.setConnected(false);
164: }
165: }
166:
167: /**
168: * Closes all connections and removes the pool of the specified type.
169: *
170: * @param the stored database connection properties object
171: */
172: public static void close() throws DataSourceException {
173: if (connectionPools == null || connectionPools.isEmpty()) {
174: return;
175: }
176:
177: // iterate and close all the pools
178: for (Iterator i = connectionPools.keySet().iterator(); i
179: .hasNext();) {
180: DatabaseConnection dc = (DatabaseConnection) i.next();
181: ConnectionPool pool = connectionPools.get(dc);
182: pool.close();
183: }
184: connectionPools.clear();
185: }
186:
187: /**
188: * Retrieves the data source objetc of the specified connection.
189: *
190: * @return the data source object
191: */
192: public static DataSource getDataSource(
193: DatabaseConnection databaseConnection) {
194: if (connectionPools == null
195: || !connectionPools.containsKey(databaseConnection)) {
196: return null;
197: }
198: return connectionPools.get(databaseConnection).getDataSource();
199: }
200:
201: /**
202: * Sets the transaction isolation level to that specified
203: * for <i>all</i> connections in the pool of the specified connection.
204: *
205: * @param the isolation level
206: * @see java.sql.Connection for possible values
207: */
208: public static void setTransactionIsolationLevel(
209: DatabaseConnection databaseConnection, int isolationLevel)
210: throws DataSourceException {
211: if (connectionPools == null
212: || connectionPools.containsKey(databaseConnection)) {
213: ConnectionPool pool = connectionPools
214: .get(databaseConnection);
215: pool.setTransactionIsolationLevel(isolationLevel);
216: }
217: }
218:
219: /**
220: * Returns a collection of database connection property
221: * objects that are active (connected).
222: *
223: * @return a collection of active connections
224: */
225: public static Vector<DatabaseConnection> getActiveConnections() {
226: if (connectionPools == null || connectionPools.isEmpty()) {
227: return new Vector<DatabaseConnection>(0);
228: }
229: Vector<DatabaseConnection> connections = new Vector<DatabaseConnection>(
230: connectionPools.size());
231: for (Iterator i = connectionPools.keySet().iterator(); i
232: .hasNext();) {
233: connections.add((DatabaseConnection) i.next());
234: }
235: return connections;
236: }
237:
238: /**
239: * Returns the open connection count for the specified connection.
240: *
241: * @param dc - the connection to be polled
242: */
243: public static int getOpenConnectionCount(DatabaseConnection dc) {
244: ConnectionPool pool = connectionPools.get(dc);
245: if (pool != null) {
246: return pool.getSize();
247: }
248: return 0;
249: }
250:
251: /**
252: * Returns a connection from the pool of the specified name.
253: *
254: * @param the name of the stored database connection
255: * @return the connection itself
256: */
257: public static Connection getConnection(String name) {
258: return null;
259: }
260:
261: /**
262: * Returns the number of pools currently active.
263: *
264: * @return number of active pools
265: */
266: public static int getActiveConnectionPoolCount() {
267: if (connectionPools == null) {
268: return 0;
269: }
270: return connectionPools.size();
271: }
272:
273: /**
274: * Closes the connection completely. The specified connection
275: * is not returned to the pool.
276: *
277: * @param the connection be closed
278: */
279: public static void close(DatabaseConnection databaseConnection,
280: Connection connection) throws DataSourceException {
281: if (connectionPools == null || connectionPools.isEmpty()) {
282: return;
283: }
284: if (connectionPools.containsKey(databaseConnection)) {
285: ConnectionPool pool = connectionPools
286: .get(databaseConnection);
287: pool.close(connection);
288: }
289: }
290:
291: /**
292: * Returns whether the specified connection [driver] supports transactions.
293: *
294: * @param databaseConnection the connection to be polled
295: * @return true | false
296: */
297: public static boolean isTransactionSupported(
298: DatabaseConnection databaseConnection) {
299: if (connectionPools.containsKey(databaseConnection)) {
300: ConnectionPool pool = connectionPools
301: .get(databaseConnection);
302: return pool.isTransactionSupported();
303: }
304: return false;
305: }
306:
307: /**
308: * Retrieves the maximum use count for each open connection
309: * before being closed.
310: *
311: * @return the max connection use count
312: */
313: public static int getMaxUseCount() {
314: return 50;
315: }
316:
317: }
|