/*******************************************************************************
 * 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.EPPXMLSignatureSchemaCachingParser;

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

	/**
	 * Factory to use for {@link EPPXMLSignatureParserPool}.
	 */
	private static class EPPXMLSignatureParserPoolFactory
	      extends BasePooledObjectFactory<EPPXMLSignatureSchemaCachingParser> {

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

		/**
		 * Activating Parser by being borrowed from the pool.
		 * 
		 * @param aParser
		 *           Parser activating from the pool
		 */
		@Override
		public void activateObject(PooledObject<EPPXMLSignatureSchemaCachingParser> 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<EPPXMLSignatureSchemaCachingParser> 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<EPPXMLSignatureSchemaCachingParser> aParser) throws Exception {
			cat.debug("Parser being passivated in the pool: " + aParser);
			super.passivateObject(aParser);
		}

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

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

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

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

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

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

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

		this.pool = new SoftReferenceObjectPool<EPPXMLSignatureSchemaCachingParser>(
		      new EPPXMLSignatureParserPoolFactory());

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

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

	/**
	 * Gets the pool initialized by {@code EPPXMLSignatureParserPool} for getting
	 * and returning XML Signature parsers.
	 * 
	 * @return XML Signature parser pool initialized by
	 *         {@code EPPXMLSignatureParserPool} if initialized; {@code null}
	 *         otherwise.
	 */
	public BaseObjectPool<EPPXMLSignatureSchemaCachingParser> getPool() {
		return this.pool;
	}

}
