📄 connectionpool.java
字号:
/*
* @(#)ConnectionPool
*
* Copyright (c) 1998 Karl Moss. All Rights Reserved.
*
* You may study, use, modify, and distribute this software for any
* purpose provided that this copyright notice appears in all copies.
*
* This software is provided WITHOUT WARRANTY either expressed or
* implied.
*
* @author Karl Moss
* @version 1.0
* @date 11Mar98
*
*/
package javaservlets.jdbc;
import java.sql.*;
/**
* <p>This class serves as a JDBC connection repository. Since
* creating database connections is one of the most time
* intensive aspects of JDBC, we'll create a pool of connections.
* Each connection can be used and then replaced back into the
* pool.
*
* <p>A properties file 'ConnectionPool.cfg' will be used to
* specify the types of JDBC connections to create, as well as
* the minimum and maximum size of the pool. The format of
* the configuration file is:
*
* #(comment)
* JDBCDriver=<JDBC driver name>
* JDBCConnectionURL=<JDBC Connection URL>
* ConnectionPoolSize=<minimum size of the pool>
* ConnectionPoolMax=<maximum size of the pool, or -1 for none>
* ConnectionUseCount=<maximum usage count for one connection>
* ConnectionTimeout=<maximum idle lifetime (in minutes) of
* a connection>
* <other property for JDBC connection>=<value>
*
* <p>Any number of additional properties may be given (such
* as username and password) as required by the JDBC driver.
*
*/
public class ConnectionPool
implements javaservlets.timer.TimerListener
{
// JDBC Driver name
String m_JDBCDriver;
// JDBC Connection URL
String m_JDBCConnectionURL;
// Minimum size of the pool
int m_ConnectionPoolSize;
// Maximum size of the pool
int m_ConnectionPoolMax;
// Maximum number of uses for a single connection, or -1 for
// none
int m_ConnectionUseCount;
// Maximum connection idle time (in minutes)
int m_ConnectionTimeout;
// Additional JDBC properties
java.util.Properties m_JDBCProperties;
// The Connection pool. This is a vector of ConnectionObject
// objects
java.util.Vector m_pool;
// The maximum number of simultaneous connections as reported
// by the JDBC driver
int m_MaxConnections = -1;
// Our Timer object
javaservlets.timer.Timer m_timer;
/**
* <p>Initializes the ConnectionPool object using
* 'ConnectionPool.cfg' as the configuration file
*
* @return true if the ConnectionPool was initialized
* properly
*/
public boolean initialize() throws Exception
{
return initialize("javaservlets/jdbc/ConnectionPool.cfg");
}
/**
* <p>Initializes the ConnectionPool object with the specified
* configuration file
*
* @param config Configuration file name
* @return true if the ConnectionPool was initialized
* properly
*/
public boolean initialize(String config) throws Exception
{
// Load the configuration parameters. Any leftover parameters
// from the configuration file will be considered JDBC
// connection attributes to be used to establish the
// JDBC connections
boolean rc = loadConfig(config);
if (rc) {
// Properties were loaded; attempt to create our pool
// of connections
createPool();
// Start our timer so we can timeout connections. The
// clock cycle will be 20 seconds
m_timer = new javaservlets.timer.Timer(this, 20);
m_timer.start();
}
return rc;
}
/**
* <p>Destroys the pool and it's contents. Closes any open
* JDBC connections and frees all resources
*/
public void destroy()
{
try {
// Stop our timer thread
if (m_timer != null) {
// m_timer.stop();
m_timer = null;
}
// Clear our pool
if (m_pool != null) {
// Loop throught the pool and close each connection
for (int i = 0; i < m_pool.size(); i++) {
close((ConnectionObject) m_pool.elementAt(i));
}
}
m_pool = null;
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* <p>Gets an available JDBC Connection. Connections will be
* created if necessary, up to the maximum number of connections
* as specified in the configuration file.
*
* @return JDBC Connection, or null if the maximum
* number of connections has been exceeded
*/
public synchronized java.sql.Connection getConnection()
{
// If there is no pool it must have been destroyed
if (m_pool == null) {
return null;
}
java.sql.Connection con = null;
ConnectionObject connectionObject = null;
int poolSize = m_pool.size();
// Get the next available connection
for (int i = 0; i < poolSize; i++) {
// Get the ConnectionObject from the pool
ConnectionObject co = (ConnectionObject)
m_pool.elementAt(i);
// If this is a valid connection and it is not in use,
// grab it
if (co.isAvailable()) {
connectionObject = co;
break;
}
}
// No more available connections. If we aren't at the
// maximum number of connections, create a new entry
// in the pool
if (connectionObject == null) {
if ((m_ConnectionPoolMax < 0) ||
((m_ConnectionPoolMax > 0) &&
(poolSize < m_ConnectionPoolMax))) {
// Add a new connection.
int i = addConnection();
// If a new connection was created, use it
if (i >= 0) {
connectionObject = (ConnectionObject)
m_pool.elementAt(i);
}
}
else {
trace("Maximum number of connections exceeded");
}
}
// If we have a connection, set the last time accessed,
// the use count, and the in use flag
if (connectionObject != null) {
connectionObject.inUse = true;
connectionObject.useCount++;
touch(connectionObject);
con = connectionObject.con;
}
return con;
}
/**
* <p>Places the connection back into the connection pool,
* or closes the connection if the maximum use count has
* been reached
*
* @param Connection object to close
*/
public synchronized void close(java.sql.Connection con)
{
// Find the connection in the pool
int index = find(con);
if (index != -1) {
ConnectionObject co = (ConnectionObject)
m_pool.elementAt(index);
// If the use count exceeds the max, remove it from
// the pool.
if ((m_ConnectionUseCount > 0) &&
(co.useCount >= m_ConnectionUseCount)) {
trace("Connection use count exceeded");
removeFromPool(index);
}
else {
// Clear the use count and reset the time last used
touch(co);
co.inUse = false;
}
}
}
/**
* <p>Prints the contents of the connection pool to the
* standard output device
*/
public void printPool()
{
System.out.println("--ConnectionPool--");
if (m_pool != null) {
for (int i = 0; i < m_pool.size(); i++) {
ConnectionObject co = (ConnectionObject)
m_pool.elementAt(i);
System.out.println("" + i + "=" + co);
}
}
}
/**
* <p>Removes the ConnectionObject from the pool at the
* given index
*
* @param index Index into the pool vector
*/
private synchronized void removeFromPool(int index)
{
// Make sure the pool and index are valid
if (m_pool != null) {
if (index < m_pool.size()) {
// Get the ConnectionObject and close the connection
ConnectionObject co = (ConnectionObject)
m_pool.elementAt(index);
close(co);
// Remove the element from the pool
m_pool.removeElementAt(index);
}
}
}
/**
* <p>Closes the connection in the given ConnectionObject
*
* @param connectObject ConnectionObject
*/
private void close(ConnectionObject connectionObject)
{
if (connectionObject != null) {
if (connectionObject.con != null) {
try {
// Close the connection
connectionObject.con.close();
}
catch (Exception ex) {
// Ignore any exceptions during close
}
// Clear the connection object reference
connectionObject.con = null;
}
}
}
/**
* <p>Loads the given configuration file. All global
* properties (such as JDBCDriver) will be
* read and removed from the properties list. Any leftover
* properties will be returned. Returns null if the
* properties could not be loaded
*
* @param name Configuration file name
* @return true if the configuration file was loaded
*/
private boolean loadConfig(String name)
throws Exception
{
boolean rc = false;
// Get our class loader
ClassLoader cl = getClass().getClassLoader();
// Attempt to open an input stream to the configuration file.
// The configuration file is considered to be a system
// resource.
java.io.InputStream in;
if (cl != null) {
in = cl.getResourceAsStream(name);
}
else {
in = ClassLoader.getSystemResourceAsStream(name);
}
// If the input stream is null, then the configuration file
// was not found
if (in == null) {
throw new Exception("ConnectionPool configuration file '" +
name + "' not found");
}
else {
try {
m_JDBCProperties = new java.util.Properties();
// Load the configuration file into the properties table
m_JDBCProperties.load(in);
// Got the properties. Pull out the properties that we
// are interested in
m_JDBCDriver = consume(m_JDBCProperties, "JDBCDriver");
m_JDBCConnectionURL = consume(m_JDBCProperties,
"JDBCConnectionURL");
m_ConnectionPoolSize = consumeInt(m_JDBCProperties,
"ConnectionPoolSize");
m_ConnectionPoolMax = consumeInt(m_JDBCProperties,
"ConnectionPoolMax");
m_ConnectionTimeout = consumeInt(m_JDBCProperties,
"ConnectionTimeout");
m_ConnectionUseCount = consumeInt(m_JDBCProperties,
"ConnectionUseCount");
rc = true;
}
finally {
// Always close the input stream
if (in != null) {
try {
in.close();
}
catch (Exception ex) {
}
}
}
}
return rc;
}
/**
* <p>Consumes the given property and returns the value.
*
* @param properties Properties table
* @param key Key of the property to retrieve and remove from
* the properties table
* @return Value of the property, or null if not found
*/
private String consume(java.util.Properties p, String key)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -