src.com.ibm.as400.access.ConnectionList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jt400-jdk8 Show documentation
Show all versions of jt400-jdk8 Show documentation
The Open Source version of the IBM Toolbox for Java
The newest version!
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: ConnectionList.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2003 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
// @C1 - 2008-06-06 - Added support for ProfileTokenCredential authentication
// by using AS400ConnectionPoolAuthentication class.
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.access;
import java.util.Vector; // Java 2
import java.io.IOException;
import java.util.Locale; //@B2A
/**
* ConnectionList is a list of connections specific to an IBM i system and userID. The
* connection list is used to create new connections and get connections from the pool.
* The connection list can remove connections that have exceeded inactivity time and
* replace connections that have exceeded the maximum use count or maximum lifetime.
**/
final class ConnectionList
{
// Values returned by checkConnectionExpiration().
// Note: These correspond to MRI text IDs in class MRI2.
private static final String NOT_EXPIRED = null;
private static final String EXPIRED_INACTIVE = "CL_REMUNUSED";
private static final String EXPIRED_MAX_LIFETIME = "CL_REMLIFE";
private static final String EXPIRED_MAX_USE_COUNT = "CL_REMUSECOUNT";
private static final String EXPIRED_MAX_USE_TIME = "CL_REMUSETIME";
private static final String EXPIRED_FAILED_PRETEST = "CL_REMPRETEST";
private String systemName_;
private String userID_;
private ConnectionPoolProperties properties_;
private Log log_;
private Vector connectionList_ = new Vector();
// Handles loading the appropriate resource bundle
//@CRS private static ResourceBundleLoader loader_;
/**
* Construct a ConnectionList object.
* @param systemName The system where the ConnectionList will exist.
* @param userID The name of the user.
* @param properties The properties of the ConnectionList.
**/
ConnectionList(String systemName, String userID, ConnectionPoolProperties properties)
{
if (systemName == null)
throw new NullPointerException("systemName");
if (systemName.length() == 0)
throw new ExtendedIllegalArgumentException("systemName", ExtendedIllegalArgumentException.LENGTH_NOT_VALID);
if (userID == null)
throw new NullPointerException("userID");
if (userID.length() == 0)
throw new ExtendedIllegalArgumentException("userID", ExtendedIllegalArgumentException.LENGTH_NOT_VALID);
if (properties == null)
throw new NullPointerException("properties");
this.systemName_ = systemName;
this.userID_ = userID;
this.properties_ = properties;
}
/**
* Sees if the specified connection is due for removal.
*
* @param poolItem The pool item.
* @return The MRI textID specifying the type of expiration, or null if not expired.
**/
private String checkConnectionExpiration(PoolItem poolItem)
{
// See if the item has exceeded the maximum inactivity time.
if ((properties_.getMaxInactivity() >= 0) &&
(poolItem.getInactivityTime() >= properties_.getMaxInactivity()))
{
return EXPIRED_INACTIVE;
}
// See if the item has exceeded the maximum use count.
if ((properties_.getMaxUseCount() >= 0) &&
(poolItem.getUseCount() >= properties_.getMaxUseCount()))
{
return EXPIRED_MAX_USE_COUNT;
}
// See if the item has exceeded the maximum lifetime.
if ( (properties_.getMaxLifetime() >= 0) &&
(poolItem.getLifeSpan() >= properties_.getMaxLifetime()))
{
return EXPIRED_MAX_LIFETIME;
}
// See if the item has exceeded the maximum use time.
if ((properties_.getMaxUseTime() >= 0) &&
(poolItem.getInUseTime() >= properties_.getMaxUseTime()))
{
return EXPIRED_MAX_USE_TIME;
}
return NOT_EXPIRED;
}
/**
* Close the connection.
**/
void close()
{
if (log_ != null || Trace.traceOn_)
log(ResourceBundleLoader.getText("CL_CLEANUP", new String[] {systemName_, userID_} ));
synchronized (connectionList_)
{
int size = connectionList_.size(); //@A5M
for (int i=0; i 0) &&
(getConnectionCount() >= properties_.getMaxConnections()))
{
if (log_ != null || Trace.traceOn_)
log(ResourceBundleLoader.getText("CL_CLEANUPEXP"));
// see if anything frees up
removeExpiredConnections(poolListeners);
// if that didn't do the trick, try shutting down unused connections
if (getConnectionCount() >= properties_.getMaxConnections())
{
if (log_ != null || Trace.traceOn_)
log(ResourceBundleLoader.getText("CL_CLEANUPOLD"));
shutDownOldest();
// if not enough connections were freed, throw an exception!
if (getConnectionCount() >= properties_.getMaxConnections())
{
throw new ConnectionPoolException(ConnectionPoolException.MAX_CONNECTIONS_REACHED); //@A1C
}
}
}
boolean threadUse = properties_.isThreadUsed();
// create a new connection
PoolItem sys = new PoolItem (systemName_, userID_, poolAuth, secure, locale, service, connect, threadUse, socketProperties, ccsid); //@B2C //@B4C //@C1C
//@B4D if (connect)
//@B4D {
//@B4D sys.getAS400Object().connectService(service);
//@B4D }
//@B4D if (!properties_.isThreadUsed()) //@A2A
//@B4D { //@A2A
//@B4D try
//@B4D { //@A2A //@A2A
//@B4D sys.getAS400Object().setThreadUsed(false); //@A2A
//@B4D } //@A2A
//@B4D catch (java.beans.PropertyVetoException e) //@A2A
//@B4D { //@A2A
//@B4D //Ignore //@A2A
//@B4D } //@A2A
//@B4D } //@A2A
// set the item is in use since we are going to return it to caller
sys.setInUse(true);
connectionList_.addElement(sys);
if (poolListeners != null)
{
ConnectionPoolEvent poolEvent = new ConnectionPoolEvent(sys.getAS400Object(), ConnectionPoolEvent.CONNECTION_CREATED); //@A5C
poolListeners.fireConnectionCreatedEvent(poolEvent);
}
if (log_ != null || Trace.traceOn_)
{
log(ResourceBundleLoader.getText("CL_CREATED", new String[] {systemName_, userID_} ));
}
return sys;
}
/**
* Return the poolItem in the list that contains this AS400 instance.
*
* @return The matching poolItem.
**/
PoolItem findElement(AS400 systemToFind)
{
synchronized (connectionList_)
{
int size = connectionList_.size();
for (int i=0; i=0; i--)
{
PoolItem p = (PoolItem)connectionList_.elementAt(i);
// Be conservative about removing in-use connections.
if (p.isInUse())
{
// Reclaim an in-use connection, only if its maxUseTime limit is exceeded.
if ((properties_.getMaxUseTime() >= 0) &&
(p.getInUseTime() >= properties_.getMaxUseTime()))
{
// Limit exceeded, so disconnect and remove the connection.
if (log_ != null || Trace.traceOn_) {
log(ResourceBundleLoader.getText(EXPIRED_MAX_USE_TIME, new String[] {systemName_, userID_} ));
}
if (Trace.traceOn_) {
log(Trace.WARNING, "Disconnecting pooled connection (currently in use) because it has exceeded the maximum use time limit of " + properties_.getMaxUseTime() + " milliseconds.");
}
p.getAS400Object().disconnectAllServices();
connectionList_.removeElementAt(i);
if (poolListeners != null)
{
ConnectionPoolEvent poolEvent = new ConnectionPoolEvent(p.getAS400Object(), ConnectionPoolEvent.CONNECTION_EXPIRED); //@A5C
poolListeners.fireConnectionExpiredEvent(poolEvent);
}
}
} // if p.inUse()
// The remaining cases are for connections that aren't currently in use.
// See if the pool item has failed a connection validity pretest.
else if (p.isFailedPretest())
{
// Failed a validation, so disconnect and remove the connection.
if (log_ != null || Trace.traceOn_) {
log(ResourceBundleLoader.getText(EXPIRED_FAILED_PRETEST, new String[] {systemName_, userID_} ));
}
if (Trace.traceOn_) {
log(Trace.DIAGNOSTIC, "Disconnecting pooled connection (not currently in use) because it has failed a validation pretest.");
}
p.getAS400Object().disconnectAllServices();
connectionList_.removeElementAt(i);
if (poolListeners != null)
{
ConnectionPoolEvent poolEvent = new ConnectionPoolEvent(p.getAS400Object(), ConnectionPoolEvent.CONNECTION_EXPIRED);
poolListeners.fireConnectionExpiredEvent(poolEvent);
}
}
// See if the connection has exceeded the maximum inactivity time.
else if ((properties_.getMaxInactivity() >= 0) &&
(p.getInactivityTime() >= properties_.getMaxInactivity()))
{
// Limit exceeded, so disconnect and remove the connection.
if (log_ != null || Trace.traceOn_) {
log(ResourceBundleLoader.getText(EXPIRED_INACTIVE, new String[] {systemName_, userID_} ));
}
if (Trace.traceOn_) {
log(Trace.DIAGNOSTIC, "Disconnecting pooled connection (not currently in use) because it has exceeded the maximum inactivity time limit of " + properties_.getMaxInactivity() + " milliseconds.");
}
p.getAS400Object().disconnectAllServices();
connectionList_.removeElementAt(i);
if (poolListeners != null)
{
ConnectionPoolEvent poolEvent = new ConnectionPoolEvent(p.getAS400Object(), ConnectionPoolEvent.CONNECTION_EXPIRED); //@A5C
poolListeners.fireConnectionExpiredEvent(poolEvent);
}
}
// See if the connection has exceeded the maximum use count.
else if ((properties_.getMaxUseCount() >= 0) &&
(p.getUseCount() >= properties_.getMaxUseCount()))
{
// Limit exceeded, so disconnect and remove the connection.
if (log_ != null || Trace.traceOn_) {
log(ResourceBundleLoader.getText(EXPIRED_MAX_USE_COUNT, new String[] {systemName_, userID_} ));
}
if (Trace.traceOn_) {
log(Trace.DIAGNOSTIC, "Disconnecting pooled connection (not currently in use) because it has exceeded the maximum use count of " + properties_.getMaxUseCount());
}
p.getAS400Object().disconnectAllServices();
connectionList_.removeElementAt(i);
if (poolListeners != null)
{
ConnectionPoolEvent poolEvent = new ConnectionPoolEvent(p.getAS400Object(), ConnectionPoolEvent.CONNECTION_EXPIRED); //@A5C //@B2C
poolListeners.fireConnectionExpiredEvent(poolEvent);
}
}
// See if the connection has exceeded the maximum lifetime.
else if ( (properties_.getMaxLifetime() >= 0) &&
(p.getLifeSpan() >= properties_.getMaxLifetime()))
{
// Limit exceeded, so disconnect and remove the connection.
if (log_ != null || Trace.traceOn_) {
log(ResourceBundleLoader.getText(EXPIRED_MAX_LIFETIME, new String[] {systemName_, userID_} ));
}
if (Trace.traceOn_) {
log(Trace.DIAGNOSTIC, "Disconnecting pooled connection (not currently in use) because it has exceeded the maximum lifetime limit of " + properties_.getMaxLifetime() + " milliseconds.");
}
p.getAS400Object().disconnectAllServices();
connectionList_.removeElementAt(i);
if (poolListeners != null)
{
ConnectionPoolEvent poolEvent = new ConnectionPoolEvent(p.getAS400Object(), ConnectionPoolEvent.CONNECTION_EXPIRED); //@A5C //@B2C
poolListeners.fireConnectionExpiredEvent(poolEvent);
}
}
}//end 'for' loop
}//@B1A end synchronized
}
/**
* Removes the connection from the pool if it is due for removal.
*
* @param poolItem The pool item.
* @param poolListeners The pool listeners to which events will be fired.
* @return true if the pool item was found and removed from the pool; false otherwise.
* @exception AS400SecurityException If a security error occured.
* @exception IOException If a communications error occured.
**/
boolean removeIfExpired(PoolItem poolItem, ConnectionPoolEventSupport poolListeners)
{
if (connectionList_.isEmpty()) return false;
boolean connectionIsExpired = false;
String expirationStatus = null;
synchronized (connectionList_)
{
expirationStatus = checkConnectionExpiration(poolItem);
if (expirationStatus == NOT_EXPIRED) {} // do nothing
else {
connectionList_.removeElement(poolItem);
connectionIsExpired = true;
}
}
// Now that we're out of the sync block (and the connection has been removed from connectionList_), disconnect the connection.
if (connectionIsExpired)
{
if ((log_ != null || Trace.traceOn_) && expirationStatus != null)
{
log(ResourceBundleLoader.getText(expirationStatus, new String[] {systemName_, userID_} ));
}
if (poolListeners != null)
{
ConnectionPoolEvent poolEvent = new ConnectionPoolEvent(poolItem.getAS400Object(), ConnectionPoolEvent.CONNECTION_EXPIRED);
poolListeners.fireConnectionExpiredEvent(poolEvent);
}
if (Trace.traceOn_) {
log(Trace.DIAGNOSTIC, "Disconnecting pooled connection (not currently in use) because it has expired.");
}
poolItem.getAS400Object().disconnectAllServices();
}
return connectionIsExpired;
}
//@A4A
/**
* New method to work with AS400ConnectionPool.removeFromPool().
**/
boolean removeUnusedElements()
{
synchronized (connectionList_)
{
if (connectionList_.size() > 0)
{
int size = connectionList_.size();
//if there are no more elements remaining in the list, remove and
//return false.
if (size == 0)
return false;
//incrementally search the list, looking for elements that are not in
//use to remove
for (int numToCheck = size - 1; numToCheck >= 0; numToCheck--)
{
PoolItem item = (PoolItem)connectionList_.elementAt(numToCheck);
if (!item.isInUse())
{
if (Trace.traceOn_) {
log(Trace.DIAGNOSTIC, "Disconnecting pooled connection (not currently in use) because removeFromPool() was called.");
}
item.getAS400Object().disconnectAllServices();
connectionList_.removeElementAt(numToCheck);
}
}// end 'for' loop
}//end if (connectionList_.size() > 0)
}//end synchronized
return true;
}
/**
* Remove the pool item in the list that contains this AS400 instance.
* The caller takes responsibility for subsequently calling disconnectAllServices().
* Called by AS400ConnectionPool.
**/
void removeElement(AS400 systemToFind)
{
synchronized(connectionList_) //@A3A
{
int size = connectionList_.size();
for (int i=0; i 0)
{
long t = 0;
int size = connectionList_.size();
for (int i=0; i t || oldest == 0)
{
oldest = i;
t = item.getInactivityTime();
}
}
}
//only disconnect oldest item if it is not in use
PoolItem item = (PoolItem)connectionList_.elementAt(oldest);
if (!item.isInUse())
{
if (Trace.traceOn_) {
log(Trace.DIAGNOSTIC, "Disconnecting pooled connection (not currently in use) during removal of oldest unallocated connections.");
}
item.getAS400Object().disconnectAllServices();
connectionList_.removeElementAt(oldest);
if (log_ != null || Trace.traceOn_)
log(ResourceBundleLoader.getText("CL_REMOLDCOMP", new String[] {systemName_, userID_} ));
}
}//end if (connectionList_.size() > 0)
}//end 'for' loop
}//end synchronized
}//end shutDownOldest()
}