/* JFox, the OpenSource J2EE Application Server
 *
 * Copyright (C) 2002 huihoo.org
 * Distributable under GNU LGPL license
 * See the GNU Lesser General Public License for more details.
 */

package org.huihoo.jfox.pool;

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.lang.reflect.Proxy;

/**
 * 
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class SimpleObjectPool extends AbstractObjectPool implements SimpleObjectPoolMBean {
  //已从池中取出的对象数目
  private volatile int numWorking = 0;
  private List pool = new ArrayList();

  /** the number of "sleeping" instances in the pool. */
  private int maxRest = 10;

  private int initNum = 5;

  public SimpleObjectPool(ObjectFactory factory) {
    this(factory,5,10);
  }

  public SimpleObjectPool(ObjectFactory factory, int initNum, int maxRest){
    super(factory);
    this.factory = factory;
    this.initNum = initNum;
    this.maxRest = maxRest;
  }

  public SimpleObjectPool(String objectFactoryClassName, String poolableClassName) {
    super(objectFactoryClassName, poolableClassName);
  }

  public SimpleObjectPool(String objectFactoryClassName, String poolableClassName, int initNum, int maxRest) {
    super(objectFactoryClassName, poolableClassName);
    this.initNum = initNum;
    this.maxRest = maxRest;
  }
  /**
   * retrieve Object from object pool
   * @return
   */
  public PoolableObject retrieveObject() throws Exception {
    PoolableObject obj = null;
    try {
      synchronized(pool) {
        obj = (PoolableObject)pool.remove(0);
      }
    }
    catch(Exception e) {
      obj = factory.makeObject();
    }
    if(obj != null) {
      obj.activate();
    }
    numWorking++;
    return obj;
  }

  /**
   * restore the retrived object to object pool
   * @return true if object passivate && push success, false if failed
   */
  public boolean restoreObject(PoolableObject obj) {
    numWorking--;

    PoolableObject realObject = obj;

    if(Proxy.isProxyClass(obj.getClass())) {
      realObject = ((PoolableObjectInvocationHandler)Proxy.getInvocationHandler(obj)).getPoolableObject();
    }

    if(factory.validateObject(realObject)) {
      try {
        obj.passivate();
        synchronized(pool){
          if(pool.size() < maxRest) {
            pool.add(realObject);
            return true;
          }
        }
      }
      catch(Exception e){
        // do nothing , just jump to below
      }
    }

    // failed
    try {
      factory.destroyObject(realObject);
    }
    catch(Exception e) {
      // ignored
    }
    return false;
  }

  public boolean removeObject(PoolableObject obj) {
    return pool.remove(obj);
  }

  // clear the pool
  public void clear() {
    Iterator iter = pool.iterator();
    while(iter.hasNext()) {
      try {
        factory.destroyObject((PoolableObject)iter.next());
      }
      catch(Exception e) {
        // ignore error, keep destroying the rest
      }
    }
    synchronized (pool){
      pool.clear();
    }
  }

  public int getWorking() {
    return numWorking;
  }

  public int getRest() {
    return pool.size();
  }

  protected void doInit() throws Exception {
    int i = initNum;
    while(i-- > 0){
      try {
        pool.add(factory.makeObject());
      }
      catch(Exception e){
        throw new RuntimeException(e.getMessage());
      }
    }

  }

  // just do clear
  protected void doDestroy() throws Exception {
    this.clear();
  }

  public int getInitNum() {
    return initNum;
  }

  public int getMaxRest() {
    return maxRest;
  }

  public static void main(String[] args) {

  }
}
