/*******************************************************************************
 * The information in this document is proprietary to VeriSign and the VeriSign
 * Registry Business. It may not be used, reproduced, or disclosed without the
 * written approval of the General Manager of VeriSign Information Services.
 * 
 * PRIVILEGED AND CONFIDENTIAL VERISIGN PROPRIETARY INFORMATION (REGISTRY
 * SENSITIVE INFORMATION)
 * Copyright (c) 2006 VeriSign, Inc. All rights reserved.
 * **********************************************************
 */

// jgould -- Dec 2, 2015

package com.verisign.epp.pool.parser;

import org.apache.commons.pool2.BaseObjectPool;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.SoftReferenceObjectPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.verisign.epp.util.EPPEnv;
import com.verisign.epp.util.EPPSchemaCachingParser;

/**
 * Singleton parser pool class that initializes the parser pool at
 * initialization, and provides a {@link #getPool()} to get the initialized
 * pool.
 */
public class EPPSchemaCachingParserPool {

	/**
	 * Factory to use for {@link EPPSchemaCachingParserPool}.
	 */
	private static class EPPSchemaCachingParserPoolFactory extends BasePooledObjectFactory<EPPSchemaCachingParser> {

		/**
		 * Category for logging
		 */
		    private static Logger cat = LoggerFactory.getLogger(EPPSchemaCachingParserPoolFactory.class);
		      

		/**
		 * Activating Parser by being borrowed from the pool.
		 * 
		 * @param aParser
		 *           Parser activating from the pool
		 */
		@Override
		public void activateObject(PooledObject<EPPSchemaCachingParser> aParser) throws Exception {
			cat.debug("Parser activating from the pool: " + aParser);
			super.activateObject(aParser);
		}

		/**
		 * Destroying Parser from the pool as the result of a validation error.
		 * 
		 * @param aParser
		 *           Parser being destroyed from the pool
		 */
		@Override
		public void destroyObject(PooledObject<EPPSchemaCachingParser> aParser) throws Exception {
			cat.debug("Parser being deleted from the pool: " + aParser);
			super.destroyObject(aParser);
		}

		/**
		 * Passivating Parser in the pool.
		 * 
		 * @param aParser
		 *           Parser being passivated in the pool
		 */
		@Override
		public void passivateObject(PooledObject<EPPSchemaCachingParser> aParser) throws Exception {
			cat.debug("Parser being passivated in the pool: " + aParser);
			super.passivateObject(aParser);
		}

		/**
		 * Create instance of {@link EPPSchemaCachingParser}.
		 */
		@Override
		public EPPSchemaCachingParser create() throws Exception {
			EPPSchemaCachingParser theParser = new EPPSchemaCachingParser();
			cat.debug("Parser created for the pool: " + theParser);
			return theParser;
		}

		/**
		 * Wrap a {@link EPPSchemaCachingParser} in a {@link DefaultPooledObject}.
		 */
		@Override
		public PooledObject<EPPSchemaCachingParser> wrap(EPPSchemaCachingParser aParser) {
			return new DefaultPooledObject<EPPSchemaCachingParser>(aParser);
		}

	}

	/**
	 * Category for logging
	 */
	    private static Logger cat = LoggerFactory.getLogger(EPPSchemaCachingParserPool.class);
	      

	/**
	 * Singleton instance
	 */
	private static EPPSchemaCachingParserPool instance = new EPPSchemaCachingParserPool();

	/**
	 * Contained parser pool
	 */
	private SoftReferenceObjectPool<EPPSchemaCachingParser> pool = null;

	/**
	 * Singleton {@code getInstance} method for accessing the
	 * {@code EPPSchemaCachingParserPool} instance.
	 * 
	 * @return {@code EPPSchemaCachingParserPool} Singleton instance.
	 */
	public static EPPSchemaCachingParserPool getInstance() {
		return instance;
	}

	/**
	 * Default constructor that will initialize the parser pool.
	 */
	private EPPSchemaCachingParserPool() {
		cat.info("EPPSchemaCachingParserPool: initializing pool with " + EPPEnv.getSchemaCachingParserPoolSize()
		      + " parsers");

		this.pool = new SoftReferenceObjectPool<EPPSchemaCachingParser>(new EPPSchemaCachingParserPoolFactory());

		try {
			this.pool.addObjects(EPPEnv.getSchemaCachingParserPoolSize());
		}
		catch (Exception ex) {
			cat.error("EPPSchemaCachingParserPool: Exception initializing the EPPSchemaCachingParserPool: " + ex);
		}

		cat.info("EPPSchemaCachingParserPool: pool initialized");
	}

	/**
	 * Gets the pool initialized by {@code EPPSchemaCachingParserPool} for
	 * getting and returning schema caching parsers.
	 * 
	 * @return Parser pool initialized by {@code EPPSchemaCachingParserPool}.
	 */
	public BaseObjectPool<EPPSchemaCachingParser> getPool() {
		return this.pool;
	}

}
