0001: //** Copyright Statement ***************************************************
0002: //The Salmon Open Framework for Internet Applications (SOFIA)
0003: // Copyright (C) 1999 - 2002, Salmon LLC
0004: //
0005: // This program is free software; you can redistribute it and/or
0006: // modify it under the terms of the GNU General Public License version 2
0007: // as published by the Free Software Foundation;
0008: //
0009: // This program is distributed in the hope that it will be useful,
0010: // but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0012: // GNU General Public License for more details.
0013: //
0014: // You should have received a copy of the GNU General Public License
0015: // along with this program; if not, write to the Free Software
0016: // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0017: //
0018: // For more information please visit http://www.salmonllc.com
0019: //** End Copyright Statement ***************************************************
0020: package com.salmonllc.sql;
0021:
0022: /////////////////////////
0023: //$Archive: /SOFIA/SourceCode/com/salmonllc/sql/DBConnection.java $
0024: //$Author: Dan $
0025: //$Revision: 42 $
0026: //$Modtime: 10/15/04 2:35p $
0027: /////////////////////////
0028:
0029: import java.sql.*;
0030: import java.util.*;
0031:
0032: import javax.naming.*;
0033: import javax.sql.DataSource;
0034:
0035: import com.salmonllc.properties.Props;
0036: import com.salmonllc.util.MessageLog;
0037:
0038: /**
0039: * This class abstracts and simplifies the process of getting database connections from connection pools and connection managers, provides some transaction support as well as a wrapper for the java.sql.Connection class.
0040: * The constructor for this class is private. The only way to get an instance of the class is to use one of the static "getConnection" methods shown below.<BR><BR>
0041: * An important note:<BR>
0042: * In order for connection pooling to operate properly, the connection must be released when it is no longer needed.<BR><BR>
0043: * Example usage:<BR>
0044: * <pre>
0045: * DBConnection conn = null;
0046: * try {
0047: * conn =DBConnection.getConnection("Application1");
0048: * ...Sql Statements using the connection
0049: * }
0050: * catch (SQLException e) {
0051: * ..handle error
0052: * }
0053: * finally {
0054: * if (conn != null)
0055: * conn.freeConnection();
0056: * }
0057: * </pre>
0058: *@see java.sql.Connection
0059: *@see java.sql.Statement
0060: *@see java.sql.PreparedStatement
0061: */
0062: public class DBConnection {
0063: // Connection type for a Sybase DBMS.
0064: public static final String SYBASE_CONNECTION = Props.DBMSTYPE_SYBASE;
0065:
0066: // Connection type for a DB2 DBMS.
0067: public static final String DB2_CONNECTION = Props.DBMSTYPE_DB2;
0068:
0069: //Connection type for a DB2-VSE DBMS.
0070: public static final String DB2VSE_CONNECTION = Props.DBMSTYPE_DB2VSE;
0071:
0072: //Connection type for a DB2-MVS DBMS.
0073: public static final String DB2MVS_CONNECTION = Props.DBMSTYPE_DB2MVS;
0074:
0075: //Connection type for a DB2-400 DBMS;
0076: //Added by DR, 8 Jan 2003
0077: public static final String DB2400_CONNECTION = Props.DBMSTYPE_DB2400;
0078:
0079: // Connection type for a SQL Anywhere DBMS.
0080: public static final String SQLANYWHERE_CONNECTION = Props.DBMSTYPE_SQLANYWHERE;
0081:
0082: //Connection type for a Microsoft SQL Server DBMS.
0083: public static final String MSSQLSEVER_CONNECTION = Props.DBMSTYPE_MSSQLSERVER;
0084:
0085: //Connection type for an Oracle Server DBMS.
0086: public static final String ORACLE_CONNECTION = Props.DBMSTYPE_ORACLE;
0087:
0088: //Connection type for an MySql Server DBMS.
0089: public static final String MYSQL_CONNECTION = Props.DBMSTYPE_MYSQL;
0090:
0091: //Connection type for an Ingres Server DBMS.
0092: public static final String INGRES_CONNECTION = Props.DBMSTYPE_INGRES;
0093:
0094: //Connection type for an Firebird/Interbase Server DBMS.
0095: public static final String FIREBIRDSQL_CONNECTION = Props.DBMSTYPE_FIREBIRDSQL;
0096:
0097: //Connection type for an Firebird/Interbase Server DBMS.
0098: public static final String ANSISQL92_CONNECTION = Props.DBMSTYPE_ANSISQL92;
0099:
0100: //Connection type for an Postgres Server DBMS.
0101: public static final String POSTGRES_CONNECTION = Props.DBMSTYPE_POSTGRES;
0102:
0103: private Connection _conn;
0104: private String _type;
0105: private boolean _direct;
0106: private long _created = 0;
0107: private long _lastUsed = 0;
0108: private long _lastDuration = 0;
0109: private boolean _inUse = false;
0110: private String _databaseDriver;
0111: private String _username;
0112: private String _password;
0113: private String _databaseUrl;
0114: private DataSource _dsDataSource;
0115:
0116: private DBConnection _next;
0117: private DBConnection _prior;
0118: private DBConnectionList _list;
0119: private boolean _verifyConnection = false;
0120: private String _verifyConnectionStatement;
0121: private int _verifyConnectionMaxAge = 0;
0122:
0123: private Vector _retrieves = new Vector();
0124:
0125: private static Hashtable _connections = new Hashtable();
0126:
0127: private String _lastSql = null;
0128:
0129: private boolean _dataSource;
0130: private static Hashtable _dataSources = new Hashtable();
0131: private Hashtable _connectionParms;
0132: private String _dbName;
0133:
0134: private DataDictionary _dd;
0135: private boolean _transactionStarted;
0136: private static String DEFAULT_VERIFY_STATEMENT = "SELECT 1";
0137: private String _application, _profileName;
0138:
0139: /**
0140: * This method was created in VisualAge.
0141: * @param conn java.sql.Connection
0142: * @param type java.lang.String
0143: */
0144: DBConnection(Connection conn, String type, boolean direct,
0145: boolean dataSource) {
0146: _type = type;
0147: _conn = conn;
0148: _direct = direct;
0149: _dataSource = dataSource;
0150: }
0151:
0152: /**
0153: * Create a DBConnection
0154: *
0155: * @param conn java.sql.Connection
0156: * @param type The database type (mySQL, DB2, Oracle, etc..)
0157: * @param direct If true, by-pass the local connection pool
0158: * @param dataSource If true, use the app-server dataSource specified in the properties file
0159: * @param dbName Database name. Used by various implementations. Usually null.
0160: */
0161: DBConnection(Connection conn, String type, boolean direct,
0162: boolean dataSource, String dbName) {
0163: this (conn, type, direct, dataSource);
0164: _dbName = dbName;
0165: }
0166:
0167: /**
0168: * Marks the logical beginning of a transaction.
0169: * The transaction must be completed later in the code via a call to either commit or rollback methods.
0170: * @see DBConnection#commit
0171: * @see DBConnection#rollback
0172: */
0173: public void beginTransaction() throws java.sql.SQLException {
0174: verify();
0175:
0176: try {
0177: _conn.setAutoCommit(false);
0178: } catch (SQLException e) {
0179: if (getDBMS().equals(SYBASE_CONNECTION)
0180: || getDBMS().equals(MSSQLSEVER_CONNECTION)) {
0181: Statement s = _conn.createStatement();
0182: s.execute("begin transaction");
0183: s.close();
0184: }
0185: }
0186: _transactionStarted = true;
0187:
0188: }
0189:
0190: /**
0191: * Marks the logical beginning of a transaction.
0192: * The transaction must be completed later in the code via a call to either commit or rollback methods.
0193: * @exception java.sql.SQLException The SQL Exception.
0194: * @see DBConnection#commit
0195: * @see DBConnection#rollback
0196: */
0197: public void beginTransaction(String fromWhere)
0198: throws java.sql.SQLException {
0199: MessageLog.writeDebugMessage("BeginTransaction-->" + fromWhere,
0200: this );
0201: System.err.println("BeginTransaction-->" + fromWhere);
0202: beginTransaction();
0203: }
0204:
0205: /**
0206: * This method commits a transaction started by a call to the beginTransaction method.
0207: * @see DBConnection#beginTransaction
0208: * @see DBConnection#rollback
0209: */
0210: public void commit() {
0211: verify();
0212:
0213: try {
0214: if (getDBMS().equals(ORACLE_CONNECTION)) {
0215: Statement s = _conn.createStatement();
0216: s.execute("commit");
0217: s.close();
0218: }
0219: _conn.commit();
0220: _conn.setAutoCommit(true);
0221: _transactionStarted = false;
0222: } catch (Exception e) {
0223: //System.err.println("DBConnection.commit " + e);
0224: }
0225:
0226: }
0227:
0228: /**
0229: * This method commits a transaction started by a call to the beginTransaction method.
0230: * @see DBConnection#beginTransaction
0231: * @see DBConnection#rollback
0232: */
0233: public void commit(String fromWhere) {
0234:
0235: MessageLog.writeDebugMessage("Commit-->" + fromWhere, this );
0236: System.err.println("Commit-->" + fromWhere);
0237: commit();
0238: }
0239:
0240: private static String computeDBMS(String databaseURL) {
0241: String DBMS = SQLANYWHERE_CONNECTION;
0242: if (databaseURL.startsWith("jdbc:sybase:"))
0243: DBMS = SYBASE_CONNECTION;
0244: else if (databaseURL.startsWith("jdbc:db2:"))
0245: DBMS = DB2_CONNECTION;
0246: else if (databaseURL.startsWith("jdbc:oracle:"))
0247: DBMS = ORACLE_CONNECTION;
0248: else if (databaseURL.startsWith("jdbc:mysql:"))
0249: DBMS = MYSQL_CONNECTION;
0250: else if (databaseURL.startsWith("jdbc:edbc:"))
0251: DBMS = INGRES_CONNECTION;
0252: else if (databaseURL.startsWith("jdbc:firebirdsql:"))
0253: DBMS = FIREBIRDSQL_CONNECTION;
0254: else if (databaseURL.startsWith("jdbc:microsoft:"))
0255: DBMS = MSSQLSEVER_CONNECTION;
0256: else if (databaseURL.startsWith("jdbc:attunity:"))
0257: DBMS = ANSISQL92_CONNECTION;
0258: else if (databaseURL.startsWith("jdbc:postgresql:"))
0259: DBMS = POSTGRES_CONNECTION;
0260: return DBMS;
0261: }
0262:
0263: /**
0264: * SQL statements without parameters are normally executed using Statement objects. If the same SQL statement is executed many times, it is more efficient to use a PreparedStatement
0265: * @return a new Statement object
0266: * @exception java.sql.SQLException
0267: */
0268: public java.sql.Statement createStatement()
0269: throws java.sql.SQLException {
0270: verify();
0271: return new DBStatement(_conn.createStatement(), this );
0272: }
0273:
0274: /**
0275: * Returns the connection back to the connection pool for use by other processes.
0276: */
0277: public synchronized void freeConnection() {
0278: if (!_direct && !_dataSource) {
0279: try {
0280: for (int i = 0; i < _retrieves.size(); i++) {
0281: ((DataStore) _retrieves.elementAt(i))
0282: .cancelRetrieve();
0283: ((DataStore) _retrieves.elementAt(i))
0284: .waitForCancel();
0285: _retrieves.removeAllElements();
0286: }
0287:
0288: if (_transactionStarted)
0289: rollback();
0290: // synchronized (_list) {
0291: _list.freeConnection(this );
0292: // _inUse = false;
0293: // _lastDuration = System.currentTimeMillis() - _lastUsed;
0294: // }
0295: } catch (Exception e) {
0296: MessageLog.writeErrorMessage("freeConnection()", e,
0297: this );
0298: }
0299: } else if (_conn != null) {
0300: try {
0301: _conn.close();
0302: } catch (Exception e) {
0303: MessageLog.writeErrorMessage("freeConnection()", e,
0304: this );
0305: }
0306: }
0307: }
0308:
0309: /**
0310: * This method was created in VisualAge.
0311: * @return java.lang.String
0312: * @param DBMS java.lang.String
0313: * @param jdbcDriver java.lang.String
0314: * @param databaseURL java.lang.String
0315: * @param userID java.lang.String
0316: * @param password java.lang.String
0317: * @param dbName java.lang.String
0318: */
0319: private static String generateSpec(String DBMS, String jdbcDriver,
0320: String databaseURL, String userID, String password,
0321: String dbName, String connectionParms) {
0322: int size = (DBMS == null ? 0 : DBMS.length());
0323: size += (jdbcDriver == null ? 0 : jdbcDriver.length());
0324: size += (databaseURL == null ? 0 : databaseURL.length());
0325: size += (userID == null ? 0 : userID.length());
0326: size += (password == null ? 0 : password.length());
0327:
0328: StringBuffer sb = new StringBuffer(size);
0329:
0330: if (DBMS != null)
0331: sb.append(DBMS);
0332: if (jdbcDriver != null)
0333: sb.append(jdbcDriver);
0334: if (databaseURL != null)
0335: sb.append(databaseURL);
0336: if (userID != null)
0337: sb.append(userID);
0338: if (password != null)
0339: sb.append(password);
0340: if (dbName != null)
0341: sb.append(dbName);
0342: if (connectionParms != null)
0343: sb.append(connectionParms);
0344: return sb.toString();
0345: }
0346:
0347: /**
0348: * This method will create a new database connection using the information passed to it.
0349: * @return The connection created from the passed.
0350: * @param maxConnections The maximum number of database connections of this type that can be used concurrently.
0351: * @param waitTimeout The time in milliseconds to wait for a connection before throwing an exception.
0352: * @param idleTimeout The time in milliseconds for a connection to remain idle before it is disconnected from the database.
0353: * @param DBMS The name of the DBMS you are using.
0354: * @param jdbcDriver The name of the jdbc driver for this connection.
0355: * @param databaseURL The url for the specific database that you want to connect to.
0356: * @param userID A valid user in the specified database.
0357: * @param password The password for the specified user.
0358: * @param dbName The database name used for this connection.
0359: * @param connectionParms A string of semicolon seperated values that tell the connection and datastores that use it how to behave
0360: * @exception java.sql.SQLException
0361: */
0362: public static synchronized DBConnection getConnection(
0363: int maxConnections, long waitTimeout, long idleTimeout,
0364: String DBMS, String jdbcDriver, String databaseURL,
0365: String userID, String password, String dbName,
0366: String connectionParms) throws java.sql.SQLException {
0367:
0368: if (DBMS == null)
0369: DBMS = computeDBMS(databaseURL);
0370:
0371: String spec = generateSpec(DBMS, jdbcDriver, databaseURL,
0372: userID, password, dbName, connectionParms);
0373: DBConnectionList list = null;
0374: if (_connections.containsKey(spec)) {
0375: list = (DBConnectionList) _connections.get(spec);
0376: list.setMax(maxConnections);
0377: list.setWaitTimeOut(waitTimeout);
0378: list.setIdleTimeOut(idleTimeout);
0379: } else {
0380: list = new DBConnectionList(maxConnections, waitTimeout,
0381: idleTimeout, DBMS, jdbcDriver, databaseURL, userID,
0382: password, dbName, connectionParms);
0383: _connections.put(spec, list);
0384: }
0385:
0386: return list.getConnection();
0387:
0388: }
0389:
0390: /**
0391: * This method will create a new database connection using the information passed to it.
0392: * @return The connection created from the passed.
0393: * @param maxConnections The maximum number of database connections of this type that can be used concurrently.
0394: * @param waitTimeout The time in milliseconds to wait for a connection before throwing an exception.
0395: * @param idleTimeout The time in milliseconds for a connection to remain idle before it is disconnected from the database.
0396: * @param DBMS The name of the DBMS you are using.
0397: * @param jdbcDriver The name of the jdbc driver for this connection.
0398: * @param databaseURL The url for the specific database that you want to connect to.
0399: * @param userID A valid user in the specified database.
0400: * @param password The password for the specified user.
0401: * @param dbName The database name used for this connection.
0402: * @exception java.sql.SQLException
0403: */
0404: public static synchronized DBConnection getConnection(
0405: int maxConnections, long waitTimeout, long idleTimeout,
0406: String DBMS, String jdbcDriver, String databaseURL,
0407: String userID, String password, String dbName)
0408: throws java.sql.SQLException {
0409: return getConnection(maxConnections, waitTimeout, idleTimeout,
0410: DBMS, jdbcDriver, databaseURL, userID, password,
0411: dbName, null);
0412: }
0413:
0414: /**
0415: * This method returns the default database connection for a particular application.
0416: * @return the default connection for a particular application as indicated in the properties file.
0417: * @param application The name to search under for connection information.
0418: * @exception java.sql.SQLException
0419: */
0420: public static DBConnection getConnection(String application)
0421: throws java.sql.SQLException {
0422:
0423: return getConnection(application, null);
0424:
0425: }
0426:
0427: /**
0428: * This method will search a properties file for a particular application for information on connecting to a database
0429: * with the specified name and returns a DBConnection attached to it.
0430: * @return The connection created from the information found in the property file.
0431: * @param name The name to search under for connection information.
0432: * @exception java.sql.SQLException
0433: */
0434: public static DBConnection getConnection(String application,
0435: String name) throws java.sql.SQLException {
0436: String profileName = name;
0437: Props p = Props.getProps(application, null);
0438:
0439: String def = p.getProperty(Props.DB_DEFAULT);
0440: if (def != null)
0441: def += ".";
0442: else
0443: def = "";
0444:
0445: if (name == null)
0446: name = def;
0447: else
0448: name += ".";
0449:
0450: String dbms = p.getProperty(name + Props.DB_DBMS);
0451: String driver = p.getProperty(name + Props.DB_DRIVER);
0452: String url = p.getProperty(name + Props.DB_URL);
0453: String user = p.getProperty(name + Props.DB_USER);
0454: String pass = p.getProperty(name + Props.DB_PASSWORD);
0455: String dataSource = p.getProperty(name + Props.DB_DATASOURCE);
0456: String dbName = p.getProperty(name + Props.DB_NAME);
0457: String dbParms = p.getProperty(name + Props.DB_PARMS);
0458:
0459: int maxConn = p.getIntProperty(name + Props.DB_MAX_CONNECTIONS);
0460: if (maxConn == -1)
0461: maxConn = 50;
0462: int waitTimeOut = p.getIntProperty(name
0463: + Props.DB_WAIT_TIME_OUT);
0464: if (waitTimeOut == -1)
0465: waitTimeOut = 60000;
0466: int idleTimeOut = p.getIntProperty(name
0467: + Props.DB_IDLE_TIME_OUT);
0468: if (idleTimeOut == -1)
0469: idleTimeOut = 3600000;
0470: boolean verifyConnection = p.getBooleanProperty(name
0471: + Props.DB_VERIFY_CONNECTION);
0472: String verifyConnectionStatement = p.getProperty(name
0473: + Props.DB_VERIFY_CONNECTION_STATEMENT);
0474: int verifyConnectionMaxAge = p.getIntProperty(name
0475: + Props.DB_VERIFY_CONNECTION_MAXAGE);
0476: if (verifyConnectionStatement == null)
0477: verifyConnectionStatement = DEFAULT_VERIFY_STATEMENT;
0478:
0479: if (dataSource == null) {
0480: DBConnection dbConn = getConnection(maxConn, waitTimeOut,
0481: idleTimeOut, dbms, driver, url, user, pass, dbName,
0482: dbParms);
0483: dbConn.setVerifyConnection(verifyConnection);
0484: dbConn
0485: .setVerifyConnectionStatement(verifyConnectionStatement);
0486: dbConn.setVerifyConnectionMaxAge(verifyConnectionMaxAge);
0487: dbConn.setApplication(application);
0488: dbConn.setProfileName(profileName);
0489: return dbConn;
0490: } else {
0491: try {
0492: DataSource ds = (DataSource) _dataSources
0493: .get(dataSource);
0494: if (ds == null) {
0495: Context ctx = new InitialContext();
0496:
0497: if (dataSource.indexOf("/") != -1)
0498: ds = (DataSource) ctx.lookup(dataSource);
0499: else
0500: ds = (DataSource) ctx.lookup("jdbc/"
0501: + dataSource);
0502:
0503: _dataSources.put(dataSource, ds);
0504: }
0505: Connection con = null;
0506: if (user != null)
0507: con = ds.getConnection(user, pass);
0508: else
0509: con = ds.getConnection();
0510: if (dbms == null) {
0511: DatabaseMetaData md = con.getMetaData();
0512: url = md.getURL();
0513: dbms = computeDBMS(url);
0514: }
0515: DBConnection dbc = new DBConnection(con, dbms, false,
0516: true, dbName);
0517: dbc.setDataSource(ds);
0518: dbc.setVerifyConnection(verifyConnection);
0519: dbc
0520: .setVerifyConnectionStatement(verifyConnectionStatement);
0521: dbc.setVerifyConnectionMaxAge(verifyConnectionMaxAge);
0522: dbc.setConnectionParms(parseConnectionParms(dbParms));
0523: dbc.setApplication(application);
0524: dbc.setProfileName(profileName);
0525: return dbc;
0526: } catch (NamingException ex) {
0527: throw new SQLException(ex.toString());
0528: }
0529: }
0530:
0531: }
0532:
0533: /**
0534: * This method returns an enumeration of all the connection pools maintained by the system.
0535: */
0536: public static Enumeration getConnectionLists() {
0537: return _connections.elements();
0538: }
0539:
0540: /**
0541: * This method returns the DBMS that the object is connected to.
0542: * @return SYBASE_CONNECTION, DB2_CONNECTION or SQLANYWHERE_CONNECTION.
0543: */
0544: public String getDBMS() {
0545: return _type;
0546: }
0547:
0548: /**
0549: * This method returns the DBName used by the connection (used for DB2)
0550: */
0551: public String getDBName() {
0552: if (_dbName == null && _list != null)
0553: return _list.getDBName();
0554: else
0555: return _dbName;
0556: }
0557:
0558: /**
0559: * Use this method to get a connection to the database without using connection pooling.
0560: * @param url The url for the specific database that you want to connect to.
0561: * @param driverName The name of the jdbc driver for this connection.
0562: * @param user A valid user in the specified database.
0563: * @param passwd The password for the specified user.
0564: */
0565: public static DBConnection getDirectConnection(String url,
0566: String driverName, String user, String passwd)
0567: throws java.sql.SQLException {
0568: String type = computeDBMS(url);
0569:
0570: return getDirectConnection(type, url, driverName, null, user,
0571: passwd);
0572: }
0573:
0574: /**
0575: * Use this method to get a connection to the database without using connection pooling.
0576: * @param url The url for the specific database that you want to connect to.
0577: * @param driverName The name of the jdbc driver for this connection.
0578: * @param user A valid user in the specified database.
0579: * @param passwd The password for the specified user.
0580: */
0581: public static DBConnection getDirectConnection(String dbms,
0582: String url, String driverName, String user, String passwd)
0583: throws java.sql.SQLException {
0584: return getDirectConnection(dbms, url, driverName, null, user,
0585: passwd);
0586: }
0587:
0588: /**
0589: * Use this method to get a connection to the database without using connection pooling.
0590: * @param dbms The Database Management System you are using.
0591: * @param url The url for the specific database that you want to connect to.
0592: * @param driverName The name of the jdbc driver for this connection.
0593: * @param user A valid user in the specified database.
0594: * @param passwd The password for the specified user.
0595: */
0596: public static DBConnection getDirectConnection(String dbms,
0597: String url, String driverName, String dbName, String user,
0598: String passwd) throws java.sql.SQLException {
0599: try {
0600: Class.forName(driverName);
0601: Connection connection = DriverManager.getConnection(url,
0602: user, passwd);
0603: DBConnection dbc = new DBConnection(connection, dbms, true,
0604: false, dbName);
0605: dbc.setDatabaseDriver(driverName);
0606: dbc.setDatabaseUrl(url);
0607: dbc.setPassword(passwd);
0608: dbc.setUserName(user);
0609: dbc.setCreated(System.currentTimeMillis());
0610: return dbc;
0611: } catch (ClassNotFoundException ex) {
0612: System.err
0613: .println("Cannot find the database driver classes.");
0614: System.err.println(ex);
0615: } catch (SQLException ex) {
0616: System.err.println(ex);
0617: throw new java.sql.SQLException(ex.toString());
0618: }
0619:
0620: return null;
0621:
0622: }
0623:
0624: /**
0625: * This method will return whether the Connection is currently being used.
0626: */
0627: public boolean getInUse() {
0628: return _inUse;
0629: }
0630:
0631: /**
0632: * This method will return the actual JDBC connection that this class is a wrapper for.
0633: */
0634: public Connection getJDBCConnection() {
0635: return _conn;
0636: }
0637:
0638: /**
0639: * This method will return that time in millseconds that it took between the last time the connection was requested and released
0640: */
0641: public long getLastDuration() {
0642: return _lastDuration;
0643: }
0644:
0645: /**
0646: * This method will return the last SQL statement that was executed on the connection
0647: */
0648: public String getLastSQL() {
0649: return _lastSql;
0650: }
0651:
0652: /**
0653: * This method will return that time in millseconds that the connection was last used.
0654: */
0655: public long getLastUsed() {
0656: return _lastUsed;
0657: }
0658:
0659: DBConnection getNext() {
0660: return _next;
0661: }
0662:
0663: DBConnection getPrior() {
0664: return _prior;
0665: }
0666:
0667: /**
0668: * A SQL stored procedure call statement is handled by creating a CallableStatement for it. The CallableStatement provides methods for setting up its IN and OUT parameters, and methods for executing it.
0669: * @return a new CallableStatement object containing the pre-compiled SQL statement
0670: * @param sql a SQL statement that may contain one or more '?' parameter placeholders. Typically this statement is a JDBC function call escape string.
0671: * @exception java.sql.SQLException
0672: */
0673: public java.sql.CallableStatement prepareCall(String sql)
0674: throws java.sql.SQLException {
0675: verify();
0676: MessageLog.writeSQLMessage("prepareCall()", sql, this );
0677: setLastSQL(sql);
0678: return _conn.prepareCall(sql);
0679: }
0680:
0681: /**
0682: * A SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement object. This object can then be used to efficiently execute this statement multiple times.
0683: * @return a new PreparedStatement object containing the pre-compiled statement.
0684: * @param sql a SQL statement that may contain one or more '?' IN parameter placeholders
0685: * @exception java.sql.SQLException
0686: */
0687: public java.sql.PreparedStatement prepareStatement(String sql)
0688: throws java.sql.SQLException {
0689: verify();
0690: MessageLog.writeSQLMessage("prepareStatement()", sql, this );
0691: setLastSQL(sql);
0692: return _conn.prepareStatement(sql);
0693: }
0694:
0695: synchronized void registerRetrieve(DataStore d) {
0696: for (int i = 0; i < _retrieves.size(); i++) {
0697: if ((DataStore) _retrieves.elementAt(i) == d)
0698: return;
0699: }
0700: _retrieves.addElement(d);
0701: }
0702:
0703: /**
0704: * This method rolls back a transaction started by a call to the beginTransaction method.
0705: * @see DBConnection#beginTransaction
0706: * @see DBConnection#commit
0707: */
0708: public void rollback() {
0709: verify();
0710:
0711: try {
0712: if (getDBMS().equals(ORACLE_CONNECTION)) {
0713: Statement s = _conn.createStatement();
0714: s.execute("rollback");
0715: s.close();
0716: }
0717: _conn.rollback();
0718: _conn.setAutoCommit(true);
0719: _transactionStarted = false;
0720: } catch (Exception e) {
0721: //System.err.println("DBConnection.rollback " + e);
0722: }
0723: }
0724:
0725: /**
0726: * This method rolls back a transaction started by a call to the beginTransaction method.
0727: * @see DBConnection#beginTransaction
0728: * @see DBConnection#commit
0729: */
0730: public void rollback(String fromWhere) {
0731: MessageLog.writeDebugMessage("Rollback-->" + fromWhere, this );
0732: System.err.println("Rollback-->" + fromWhere);
0733: rollback();
0734: }
0735:
0736: void setDBName(String dbName) {
0737: _dbName = dbName;
0738: }
0739:
0740: /**
0741: * This method will set whether the Connection is currently being used.
0742: */
0743: void setInUse(boolean inUse) {
0744: _inUse = inUse;
0745: }
0746:
0747: void setJDBCConnection(Connection conn) {
0748: _conn = conn;
0749: }
0750:
0751: /**
0752: * This method will set whether the last duration for the connection.
0753: */
0754: void setLastDuration(long lastDuration) {
0755: _lastDuration = lastDuration;
0756: }
0757:
0758: /**
0759: * This method will set the last SQL statement that was executed on the connection
0760: */
0761: void setLastSQL(String sql) {
0762: _lastSql = sql;
0763: }
0764:
0765: /**
0766: * This method will set whether the Connection is currently being used.
0767: */
0768: void setLastUsed(long lastUsed) {
0769: _lastUsed = lastUsed;
0770: _lastDuration = 0;
0771: }
0772:
0773: void setList(DBConnectionList list) {
0774: _list = list;
0775: }
0776:
0777: void setNext(DBConnection conn) {
0778: _next = conn;
0779: }
0780:
0781: void setPrior(DBConnection conn) {
0782: _prior = conn;
0783: }
0784:
0785: synchronized void unregisterRetrieve(DataStore d) {
0786: for (int i = 0; i < _retrieves.size(); i++) {
0787: if ((DataStore) _retrieves.elementAt(i) == d) {
0788: _retrieves.removeElement(d);
0789: }
0790: }
0791:
0792: }
0793:
0794: private Connection newConnection() throws SQLException,
0795: ClassNotFoundException {
0796: if (_list != null)
0797: return _list.createConnection();
0798: else {
0799: Class.forName(_databaseDriver);
0800: return DriverManager.getConnection(_databaseUrl, _username,
0801: _password);
0802: }
0803: }
0804:
0805: /**
0806: * This method was created in VisualAge.
0807: */
0808: private void verify() {
0809: if (!_verifyConnection)
0810: return;
0811: try {
0812: if (_conn == null || _conn.isClosed()) {
0813: if (_dsDataSource != null)
0814: _conn = _dsDataSource.getConnection();
0815: else {
0816: Class.forName(_databaseDriver);
0817: _conn = newConnection();
0818: }
0819: } else {
0820: if (_verifyConnectionMaxAge > 0) {
0821: long lNow = System.currentTimeMillis();
0822: long lDiff = lNow - _created;
0823: if (lDiff > (long) (_verifyConnectionMaxAge * 1000)) {
0824: _conn.close();
0825: try {
0826: if (_dsDataSource != null)
0827: _conn = _dsDataSource.getConnection();
0828: else
0829: _conn = newConnection();
0830: setCreated(System.currentTimeMillis());
0831: MessageLog.writeInfoMessage(
0832: "Connection re-established.", this );
0833: } catch (Exception ex) {
0834: MessageLog
0835: .writeInfoMessage(
0836: "Failed to re-establish connection.",
0837: this );
0838: }
0839: }
0840: }
0841: Statement st = _conn.createStatement();
0842: ResultSet r = st
0843: .executeQuery(_verifyConnectionStatement == null ? DEFAULT_VERIFY_STATEMENT
0844: : _verifyConnectionStatement);
0845: r.close();
0846: st.close();
0847: }
0848: } catch (Exception e) {
0849: try {
0850: if (_conn != null)
0851: _conn.close();
0852: if (_dsDataSource != null)
0853: _conn = _dsDataSource.getConnection();
0854: else {
0855: Class.forName(_databaseDriver);
0856: _conn = newConnection();
0857: }
0858: setCreated(System.currentTimeMillis());
0859: MessageLog.writeInfoMessage(
0860: "Connection re-established.", this );
0861: } catch (Exception ex) {
0862: MessageLog.writeInfoMessage(
0863: "Failed to re-establish connection.", this );
0864: }
0865: }
0866: }
0867:
0868: /**
0869: * This method will store the datasource the connection was created with.
0870: */
0871: void setDataSource(DataSource ds) {
0872: _dsDataSource = ds;
0873: }
0874:
0875: /**
0876: * This method will store the database driver the connection was created with.
0877: */
0878: void setDatabaseDriver(String driverName) {
0879: _databaseDriver = driverName;
0880: }
0881:
0882: /**
0883: * This method will store the username the connection was created with.
0884: */
0885: void setUserName(String user) {
0886: _username = user;
0887: }
0888:
0889: /**
0890: * This method will store the password the connection was created with.
0891: */
0892: void setPassword(String pass) {
0893: _password = pass;
0894: }
0895:
0896: /**
0897: * This method will store the database Url the connection was created with.
0898: */
0899: void setDatabaseUrl(String url) {
0900: _databaseUrl = url;
0901: }
0902:
0903: /**
0904: * This method will indicate whether a connection should be verified.
0905: */
0906: void setVerifyConnection(boolean bVerify) {
0907: _verifyConnection = bVerify;
0908: }
0909:
0910: /**
0911: * This method will set the connection verify statement.
0912: */
0913: void setVerifyConnectionStatement(String sVerifyStatement) {
0914: _verifyConnectionStatement = sVerifyStatement;
0915: }
0916:
0917: /**
0918: * This method will set the connections verification max age in seconds.
0919: * If the connection is older than the max age the connection will be reestablished.
0920: */
0921: void setVerifyConnectionMaxAge(int iMaxAge) {
0922: _verifyConnectionMaxAge = iMaxAge;
0923: }
0924:
0925: /**
0926: * This method will set the creation time of the connection.
0927: */
0928: void setCreated(long lCreated) {
0929: _created = lCreated;
0930: }
0931:
0932: /**
0933: * This method returns a connection parameter
0934: * @param key
0935: * @return
0936: */
0937: String getConnectionParm(String key) {
0938: if (_connectionParms != null)
0939: return (String) _connectionParms.get(key);
0940: else
0941: return (String) _list.getConnectionParm(key);
0942: }
0943:
0944: /**
0945: * Returns a Hashtable of connection parms used for this connection
0946: * @return
0947: */
0948: Hashtable getConnectionParms() {
0949: if (_connectionParms != null)
0950: return _connectionParms;
0951: else
0952: return _list.getConnectionParms();
0953:
0954: }
0955:
0956: static Hashtable parseConnectionParms(String parms) {
0957: Hashtable tab = new Hashtable();
0958: if (parms == null)
0959: return tab;
0960: StringTokenizer st = new StringTokenizer(parms, ";");
0961: while (st.hasMoreTokens()) {
0962: String tok = st.nextToken();
0963: int pos = tok.indexOf("=");
0964: if (pos == -1)
0965: pos = tok.indexOf(":");
0966: if (pos != -1) {
0967: String key = tok.substring(0, pos).trim();
0968: String val = tok.substring(pos + 1).trim();
0969: tab.put(key, val);
0970: }
0971: }
0972: return tab;
0973:
0974: }
0975:
0976: void setConnectionParms(Hashtable hashtable) {
0977: _connectionParms = hashtable;
0978: }
0979:
0980: /**
0981: * @return true if a transaction has been started on this connection but not yet committed or rolled back. If the transaction has not been, it will be rolled back when the connection has been returned to the pool.
0982: */
0983: public boolean isTransactionStarted() {
0984: return _transactionStarted;
0985: }
0986:
0987: /**
0988: * Returns a data dictionary object containing information on the tables in this database. The DataDictionary object should only be used for the time that the connection object is help (between the DBConnection.getConnection() and DBConnection.freeConnection() methods)
0989: */
0990: public DataDictionary getDataDictionary() {
0991: String cacheDD = getConnectionParm(DataStore.CONNECTION_PARM_CACHE_DATADICTIONARY);
0992: if (cacheDD != null && cacheDD.equalsIgnoreCase("false")) {
0993: _dd = null;
0994: return new DataDictionary(this );
0995: }
0996:
0997: if (_dd == null)
0998: _dd = new DataDictionary(this );
0999: return _dd;
1000: }
1001:
1002: /**
1003: * @return Returns the application.
1004: */
1005: String getApplication() {
1006: return _application;
1007: }
1008:
1009: /**
1010: * @return Returns the profileName.
1011: */
1012: String getProfileName() {
1013: return _profileName;
1014: }
1015:
1016: /**
1017: * @param application The application to set.
1018: */
1019: private void setApplication(String application) {
1020: _application = application;
1021: }
1022:
1023: /**
1024: * @param profileName The profileName to set.
1025: */
1026: private void setProfileName(String profileName) {
1027: _profileName = profileName;
1028: }
1029: }
|