/**
  * Sets the abandoned object removal configuration.
  *
  * @param abandonedConfig the new configuration to use. This is used by value.
  * @see AbandonedConfig
  */
 public void setAbandonedConfig(AbandonedConfig abandonedConfig) {
   if (abandonedConfig == null) {
     this.abandonedConfig = null;
   } else {
     this.abandonedConfig = new AbandonedConfig();
     this.abandonedConfig.setLogAbandoned(abandonedConfig.getLogAbandoned());
     this.abandonedConfig.setLogWriter(abandonedConfig.getLogWriter());
     this.abandonedConfig.setRemoveAbandonedOnBorrow(abandonedConfig.getRemoveAbandonedOnBorrow());
     this.abandonedConfig.setRemoveAbandonedOnMaintenance(
         abandonedConfig.getRemoveAbandonedOnMaintenance());
     this.abandonedConfig.setRemoveAbandonedTimeout(abandonedConfig.getRemoveAbandonedTimeout());
     this.abandonedConfig.setUseUsageTracking(abandonedConfig.getUseUsageTracking());
   }
 }
  /**
   * {@inheritDoc}
   *
   * <p>Successive activations of this method examine objects in sequence, cycling through objects
   * in oldest-to-youngest order.
   */
  @Override
  public void evict() throws Exception {
    assertOpen();

    if (idleObjects.size() > 0) {

      PooledObject<T> underTest = null;
      EvictionPolicy<T> evictionPolicy = getEvictionPolicy();

      synchronized (evictionLock) {
        EvictionConfig evictionConfig =
            new EvictionConfig(
                getMinEvictableIdleTimeMillis(), getSoftMinEvictableIdleTimeMillis(), getMinIdle());

        boolean testWhileIdle = getTestWhileIdle();

        for (int i = 0, m = getNumTests(); i < m; i++) {
          if (evictionIterator == null || !evictionIterator.hasNext()) {
            evictionIterator = new EvictionIterator(idleObjects);
          }
          if (!evictionIterator.hasNext()) {
            // Pool exhausted, nothing to do here
            return;
          }

          try {
            underTest = evictionIterator.next();
          } catch (NoSuchElementException nsee) {
            // Object was borrowed in another thread
            // Don't count this as an eviction test so reduce i;
            i--;
            evictionIterator = null;
            continue;
          }

          if (!underTest.startEvictionTest()) {
            // Object was borrowed in another thread
            // Don't count this as an eviction test so reduce i;
            i--;
            continue;
          }

          // User provided eviction policy could throw all sorts of crazy
          // exceptions. Protect against such an exception killing the
          // eviction thread.
          boolean evict;
          try {
            evict = evictionPolicy.evict(evictionConfig, underTest, idleObjects.size());
          } catch (Throwable t) {
            // Slightly convoluted as SwallowedExceptionListener uses
            // Exception rather than Throwable
            PoolUtils.checkRethrow(t);
            swallowException(new Exception(t));
            // Don't evict on error conditions
            evict = false;
          }

          if (evict) {
            destroy(underTest);
            destroyedByEvictorCount.incrementAndGet();
          } else {
            if (testWhileIdle) {
              boolean active = false;
              try {
                factory.activateObject(underTest);
                active = true;
              } catch (Exception e) {
                destroy(underTest);
                destroyedByEvictorCount.incrementAndGet();
              }
              if (active) {
                if (!factory.validateObject(underTest)) {
                  destroy(underTest);
                  destroyedByEvictorCount.incrementAndGet();
                } else {
                  try {
                    factory.passivateObject(underTest);
                  } catch (Exception e) {
                    destroy(underTest);
                    destroyedByEvictorCount.incrementAndGet();
                  }
                }
              }
            }
            if (!underTest.endEvictionTest(idleObjects)) {
              // TODO - May need to add code here once additional
              // states are used
            }
          }
        }
      }
    }
    AbandonedConfig ac = this.abandonedConfig;
    if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
      removeAbandoned(ac);
    }
  }
 /**
  * Will a check be made for abandoned objects when the evictor runs?
  *
  * @return {@code true} if abandoned object removal is configured to be activated when the evictor
  *     runs otherwise {@code false}
  * @see AbandonedConfig#getRemoveAbandonedOnMaintenance()
  */
 @Override
 public boolean getRemoveAbandonedOnMaintenance() {
   AbandonedConfig ac = this.abandonedConfig;
   return ac != null && ac.getRemoveAbandonedOnMaintenance();
 }