All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.ibm.as400.access.ConnectionList Maven / Gradle / Ivy

There is a newer version: 11.1
Show 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()
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy