/**
   * Tries to add a reuseable connection to the connection pool. Replace any not in use connections
   * to the same host and port. Will not add to the same host and port in use. Will replace oldest
   * not in use element (if any) if the pool is full.
   *
   * @param p_protocol The protocol for the connection
   * @param p_host The Hostname for the connection
   * @param p_port The port number for the connection
   * @param sc The base stream connection
   * @param dos The data output stream from the base connection
   * @param dis The data input stream from the base connection
   * @return true if the connection was added, otherwise false
   */
  synchronized boolean add(
      String p_protocol,
      String p_host,
      int p_port,
      StreamConnection sc,
      DataOutputStream dos,
      DataInputStream dis) {

    StreamConnectionElement oldestNotInUse = null;

    // find the last unused element
    Enumeration cons = m_connections.elements();
    while (cons.hasMoreElements()) {
      StreamConnectionElement sce = (StreamConnectionElement) cons.nextElement();

      if (sce.m_in_use) {
        if (p_host.equals(sce.m_host) && p_port == sce.m_port) {
          return false;
        }

        continue;
      }

      // if the connection is a duplicate, delete it
      if (p_host.equals(sce.m_host) && p_port == sce.m_port) {
        // no protocol duplicates on host and port
        sce.close();
        m_connections.removeElement(sce);
        break;
      } else {
        if (oldestNotInUse == null || sce.m_time < oldestNotInUse.m_time) {
          // save the oldest not in use, it may be removed later
          oldestNotInUse = sce;
        }
      }
    }

    /*
     * first check and see if the maximum number of connections
     * has been reached - if so delete the first one in the list (FIFO)
     *   or
     * if this port and host are already in the pool.
     */
    if (m_connections.size() >= m_max_connections) {
      if (oldestNotInUse == null) {
        return false;
      }

      oldestNotInUse.close();
      m_connections.removeElement(oldestNotInUse);
    }

    m_connections.addElement(new StreamConnectionElement(p_protocol, p_host, p_port, sc, dos, dis));
    return true;
  }
  /**
   * Return an instance of the stream connection element to the connection pool so it can be reused.
   * It is done in the method so it can be synchronized with the get method.
   *
   * @param returned The stream connection element to return
   */
  synchronized void returnForReuse(StreamConnectionElement returned) {
    returned.m_in_use = false;

    if (returned.m_removed) {
      // the connection was out too long
      returned.close();
      return;
    }

    returned.m_time = System.currentTimeMillis();
  }
  /**
   * get an available connection and set the boolean flag to true (unavailable) in the connection
   * pool. Also removes any stale connections, since this method gets called more than add or
   * remove.
   *
   * @param callerSecurityToken The security token of the caller
   * @param p_protocol The protocol for the connection
   * @param p_host The Hostname for the connection
   * @param p_port The port number for the connection
   * @return A stream connection element or null if not found
   */
  public synchronized StreamConnectionElement get(
      SecurityToken callerSecurityToken, String p_protocol, String p_host, int p_port) {

    StreamConnectionElement result = null;
    long c_time = System.currentTimeMillis();
    Enumeration cons = m_connections.elements();

    callerSecurityToken.checkIfPermissionAllowed(Permissions.MIDP);

    while (cons.hasMoreElements()) {
      StreamConnectionElement sce = (StreamConnectionElement) cons.nextElement();

      if ((c_time - sce.m_time) > m_connectionLingerTime) {
        if (!sce.m_in_use) {
          sce.close();
        } else {
          // signal returnToUse() to close
          sce.m_removed = true;
        }

        m_connections.removeElement(sce);
        continue;
      }

      if (p_host.equals(sce.m_host)
          && p_port == sce.m_port
          && p_protocol.equals(sce.m_protocol)
          && !sce.m_in_use) {
        result = sce;

        // do not break out so old connections can be removed
        continue;
      }
    }

    if (result != null) {
      result.m_in_use = true;
    }

    return result;
  }
 /**
  * Close connection and remove an instance of the stream connection element from the connection
  * pool.
  *
  * @param sce The stream connection element to remove
  */
 synchronized void remove(StreamConnectionElement sce) {
   sce.close();
   m_connections.removeElement(sce);
 }