// ------------------------------------------------------------------------------
// Copyright 2000 by Matt Luker. All rights reserved.
//
// Revision:
//
// $Header: /cvsroot/lumberjack/lumberjack/src/java/com/redstarhackers/db/OracleConnMgr.java,v 1.2 2000/03/20 04:39:53 mluker Exp $
//
// $Log: OracleConnMgr.java,v $
// Revision 1.2 2000/03/20 04:39:53 mluker
// Merged changes from 0.8.1
//
// Revision 1.1.6.1 2000/03/20 03:47:11 mluker
// Further Oracle work--almost done.
//
// Revision 1.1 2000/03/05 00:04:36 mluker
// Database utility code
//
//
//
// ------------------------------------------------------------------------------
package com.redstarhackers.db;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.PropertyResourceBundle;
import java.io.FileInputStream;
import java.sql.SQLException;
/**
* <p>OrcaleConnMgr provides a connection to a database. The class uses
* the Singleton design pattern in order to control the number of connections made
* to oracle. Currently, only non-transactional connections (those with
* <code>autoCommit</code> set to <code>true</code>) are cached. Transactional
* connections are spawned every time <code>getTransactionalConnection()</code> method
* is called.</p>
*
* <p>Current concurrency issues have been resolved. Queries requiring
* no transactional state can use <code>getConnection()</code> or
* <code>getReadOnlyConnection()</code>. Any query requiring a transactional state
* should use <code>getTransactionalConnection()</code>. The transactional connection
* should be disposed of when the query is done via a <code>Connection.close()</code>
* method. This is because these are not cached, and therefore, need to be cleaned up.</p>
*
* @author Matt Luker
* @version $Revision: 1.2 $
*/
/*
* OrcaleConnMgr provides simplified connectivity to a database.
*
* Copyright (C) 2000, Matt Luker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
/*
* If you have any questions about this software,
* or need to report a bug, please contact me.
*
* Matt Luker
* Norwood, MA
* kostya@redstarhackers.com
*
* TTGOG
*/
public class OracleConnMgr implements DBConnMgr {
public static final String CONFIG_PROPERTY="com.redstarhackers.db.OracleConfig";
public static String CONFIG_RESOURCE="com.redstarhackers.db.OracleConfig";
/**
* <p>Returns an instance of the <code>CSConnection</code> class. This controls
* access to the instantiation of the class. This is important for controlling
* how connections are made and managing them.</p>
*
* <p>This is basically a <code>Factory Method</code> design pattern
* (<u>Design Patterns</u>, Gamma 107) for implementing the <code>Singleton</code>
* pattern(Gamma 127).</p>
*
* @returns a <code>Connection</code> to the database.
* @exception java.sql.SQLException if anything goes wrong with making
* the connection to the database.
*/
public static OracleConnMgr getInstance() throws SQLException {
// Check to see if we have initialized the class
if (__initialized==false) {
initialize();
}
// If this is the first time this method is called, the
// instance variable will be null. We need to get an instance
// in that case ...
if (__instance==null) {
__instance=new OracleConnMgr();
}
return __instance;
}
/**
* Returns the JDBC Driver class name being used by this class.
*
* @returns the JDBC driver class name.
*/
public static String getJdbcDriver() throws SQLException {
// If this is called before we have been initialized, make
// sure to initialize the class.
if (__initialized==false) {
initialize();
}
return __jdbcDriver;
}
/**
* Returns the URL used by JDBC to connect to the database.
*
* @returns the URL used by JDBC
*/
public static String getJdbcUrl() throws SQLException {
if (__initialized==false) {
initialize();
}
return __jdbcUrl;
}
/**
* Returns the database connection for this instance of the class.
*
* @returns the database <code>Connection</code>
* @throws java.sql.SQLException if anything goes wrong with getting a connection
*/
public Connection getConnection() throws SQLException {
return getStandardConnection();
}
/**
* Returns the database connection for this instance of the class.
*
* @returns the database <code>Connection</code>
*/
public Connection getStandardConnection() throws SQLException {
return createStandardConnection();
}
/**
* Returns the database connection for this instance of the class.
*
* @returns the database <code>Connection</code>
*/
public Connection getTransactionalConnection() throws SQLException {
return createTransactionalConnection();
}
/**
* Returns the database connection for this instance of the class.
*
* @returns the database <code>Connection</code>
*/
public Connection getReadOnlyConnection() throws SQLException {
return createReadOnlyConnection();
}
/**
* Initializes the class with all the needed database information.
*
* @see com.quickbuy.db.OracleDBConstants
* @see com.quickbuy.db.CSConnection#setdefaults()
* @see com.quickbuy.db.CSConnection#loadConfig()
* @see com.quickbuy.db.CSConnection#applyConfig()
*/
private static void initialize() throws SQLException {
setDefaults(); // set the class variables to the defaults
loadConfig(); // load the configuration from the PropertyResourceBundle
applyConfig(); // apply the configuration values to the class variables, overwriting the defaults
// Create the JDBC URL from the settings
if (__protocol==OracleDBConstants.FAT_JDBC_PROTOCOL) { // for FAT
__jdbcUrl=__protocol+"@"+__dbName;
} else { // for THIN
__jdbcUrl=__protocol+"@"+__host+":"+__port+":"+__sid;
}
// OK, we are initialized and good to go ...
__initialized=true;
}
/**
* Load the default settings from <code>OracleDBConstants</code>.
*
* @see com.quickbuy.db.OracleDBConstants
*/
private static void setDefaults() {
__jdbcDriver=OracleDBConstants.DEFAULT_JDBC_DRIVER;
__protocol=OracleDBConstants.DEFAULT_JDBC_PROTOCOL;
__host=OracleDBConstants.DEFAULT_HOST;
__port=OracleDBConstants.DEFAULT_PORT;
__sid=OracleDBConstants.DEFAULT_SID;
__dbName=OracleDBConstants.DEFAULT_DB_NAME;
__options=OracleDBConstants.DEFAULT_DB_OPTIONS;
__username=OracleDBConstants.DEFAULT_USERNAME;
__password=OracleDBConstants.DEFAULT_PASSWORD;
String userConfig=System.getProperty(CONFIG_PROPERTY);
if (userConfig!=null)
CONFIG_RESOURCE=userConfig;
}
/**
* Load the configuration settings from the <code>PropertyResourceBundle</code> text file.
* These settings supercede default settings.
*
*/
private static void loadConfig() {
PropertyResourceBundle configBundle=null;
__config=new Properties();
try {
// Get the bundle from the classpath
configBundle=(PropertyResourceBundle)PropertyResourceBundle.getBundle(CONFIG_RESOURCE);
String key=null;
String value=null;
// Now pull out all the keys and put it in a normal Properties object
for (Enumeration keys=configBundle.getKeys(); keys.hasMoreElements(); ) {
key=(String)keys.nextElement();
value=(String)configBundle.getObject(key);
__config.put(key, value);
}
} catch (MissingResourceException ex) {
// We've initialized __config to a harmless, empty Properties object, so there isn't
// really any need to panic or anything. It just will fall back to the defaults.
}
}
/**
* Take the settinfs loaded from the configuration file and overwrite the default settings
* for the class.
*/
private static void applyConfig() throws SQLException {
/* From the config file ...
* # jdbcdriver - JDBC driver name to use for connecting to the
* # database.
* # protocol - JDBC protocol string for accessing the DB.
* # e.g. jdbc:oracle:
* # host - the host that the database is running on.
* # port - port that the database is running on.
* # dbname - name of the database.
*/
String value;
// Check JDBC Driver
if ((value=__config.getProperty("jdbcdriver")) != null)
__jdbcDriver=value;
// Check protocol for the url
if ((value=__config.getProperty("protocol")) != null)
__protocol=value;
// Check host
if ((value=__config.getProperty("host")) != null)
__host=value;
// Check port
if ((value=__config.getProperty("port")) != null)
__port=value;
// Check sid
if ((value=__config.getProperty("sid")) != null)
__sid=value;
// Check database name
if ((value=__config.getProperty("dbname")) != null)
__dbName=value;
// Check options
if ((value=__config.getProperty("options")) != null)
__options=value;
// Check username
if ((value=__config.getProperty("username")) != null)
__username=value;
// Check password
if ((value=__config.getProperty("password")) != null)
__password=value;
// OK, let's get the properties for the database connection pool
__connectionPoolConfig=new Properties(); // get the values when we start using it
}
/**
* The constructor for this class, which is not accessible outside the class. This
* enforces creation of instances and access to instances of the class to be made
* through <code>getInstance()</code>.
*/
private OracleConnMgr() throws SQLException {
// Load the driver for jdbc
try {
Class.forName(__jdbcDriver).newInstance();
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Creates a standard, auto-commit connection to the database.
*
* @returns a <code>Connection</code> to the database.
*/
private Connection createStandardConnection() throws SQLException {
Connection conn;
conn=createConnection();
conn.setAutoCommit(true);
conn.setReadOnly(false);
return conn;
}
private Connection createTransactionalConnection() throws SQLException {
Connection conn;
conn=createConnection();
conn.setAutoCommit(false);
conn.setReadOnly(false);
return conn;
}
private Connection createReadOnlyConnection() throws SQLException {
Connection conn;
conn=createConnection();
conn.setAutoCommit(true);
conn.setReadOnly(true);
return conn;
}
private Connection createConnection() throws SQLException {
return createDirectConnection();
}
private Connection createPooledConnection() throws SQLException {
Connection conn=null;
System.out.println("# createPooledConnection() ##########################################################");
System.out.println("# JDBC Driver:\t"+__jdbcDriver);
System.out.println("# JDBC URL:\t"+__jdbcUrl);
System.out.println("# Connection Pool Config:\n# "+__connectionPoolConfig);
System.out.println("# Getting a pooled connection to the database ...");
try {
conn=DriverManager.getConnection(__jdbcUrl, __connectionPoolConfig);
System.out.println("# SUCCESS: conn=="+conn.toString());
} catch (SQLException ex) {
System.out.println("# FAILED to get a connection!");
System.out.println("########################################################## createPooledConnection() #");
throw ex;
}
System.out.println("########################################################## createPooledConnection() #");
return conn;
}
private Connection createDirectConnection() throws SQLException {
Connection conn=null;
System.out.println("# createDirectConnection() ##########################################################");
System.out.println("# JDBC Driver:\t\t"+__jdbcDriver);
System.out.println("# JDBC URL:\t\t"+__jdbcUrl);
System.out.println("# username/password:\t"+__username+"/"+__password);
System.out.println("# Getting a direct connection to the database ...");
try {
conn=DriverManager.getConnection(__jdbcUrl, __username, __password);
System.out.println("# SUCCESS: conn=="+conn.toString());
} catch (SQLException ex) {
System.out.println("# FAILED to get a connection!");
System.out.println("########################################################## createDirectConnection() #");
throw ex;
}
System.out.println("########################################################## createDirectConnection() #");
return conn;
}
/** The state of the class: initialized or not. */
private static boolean __initialized=false;
/** The configuration settings from file. */
private static Properties __config;
/** The configuration settings from file. */
private static Properties __connectionPoolConfig;
/** Instance of the class. */
private static OracleConnMgr __instance;
/** JDBC driver class name. */
private static String __jdbcDriver="";
/** URL for making a connection to the database via JDBC. */
private static String __jdbcUrl="";
/** Protocol to use when connecting via JDBC. */
private static String __protocol="";
/** Host that the database is running on. */
private static String __host="";
/** Port that the database is running on at the host. */
private static String __port="";
/** The SID for the database. */
private static String __sid="";
/** The database name. */
private static String __dbName="";
/** The database connection options, passed in as a part of the URL. */
private static String __options="";
/** The username. */
private static String __username="";
/** The password. */
private static String __password="";
/** The standard, auto-commit, read/write connection to the database. */
private Connection _csStandardConn;
/** The read-only connection to the database. */
private Connection _csReadOnlyConn;
}