/***********************************************************
Copyright (C) 2004 VeriSign, Inc.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

http://www.verisign.com/nds/naming/namestore/techdocs.html
***********************************************************/
package com.verisign.epp.interfaces;

import java.util.Properties;
import java.util.Vector;

import com.verisign.epp.codec.gen.EPPCodec;
import com.verisign.epp.codec.gen.EPPCodecException;
import com.verisign.epp.pool.parser.EPPSchemaCachingParserPool;
import com.verisign.epp.pool.transformer.EPPTransformerPool;
import com.verisign.epp.util.EPPEnv;
import com.verisign.epp.util.EPPEnvException;
import com.verisign.epp.util.EPPEnvSingle;
import com.verisign.epp.util.EnvException;
import com.verisign.epp.util.Environment;

/**
 * This class represents a logical application. it should be instantiated once
 * in the application life cycle. Its primary function is to initialize all the
 * utilities and connection pool associated with interfaces. At the termination
 * of the program, this entity will offer resources to close all established the
 * connections gracefully, and it performs all cleanup tasks associated with
 * utility functions.
 */
public class EPPApplication {
	/**
	 * Was the parser pool initialized?
	 */
	private static boolean poolsInitialized = false;

	/**
	 * EPP environment instance used to hold the EPP SDK configuration properties
	 */
	private EPPEnvSingle env = EPPEnvSingle.getInstance();

	/**
	 * Initialize {@code EPPApplication} using the passed in configuration file
	 * and {@link ClassLoader}.
	 *
	 * @param aConfigFile
	 *           Configuration file name to initialize {@code EPPApplication}
	 *           with.
	 * @param aClassLoader
	 *           Used to look for the configuration file in the classpath.
	 *
	 * @exception EPPCommandException
	 *               Error initializing with the configuration file
	 */
	public void initialize(String aConfigFile, ClassLoader aClassLoader) throws EPPCommandException {

		try {
			this.env.envInitialize(aConfigFile, aClassLoader);
		}
		catch (EnvException e) {
			throw new EPPCommandException("EnvException caught :" + e.getMessage());
		}

		this.initialize();
	}

	/**
	 * Initialize {@code EPPApplication} using the passed in {@link Properties}
	 * object.
	 *
	 * @param aProperties
	 *           EPP configuration properties to initialize
	 *           {@code EPPApplication} with.
	 *
	 * @throws EPPCommandException
	 *            Error initializing with the properties
	 */
	public void initialize(Properties aProperties) throws EPPCommandException {

		Environment.setProperties(aProperties);

		this.initialize();
	}

	/**
	 * Initialize {@code EPPApplication} using the passed in configuration file.
	 *
	 * @param aConfigFile
	 *           Configuration file name to initialize {@code EPPApplication}
	 *           with.
	 *
	 * @exception EPPCommandException
	 *               Error initializing with the configuration file
	 */
	public void initialize(String aConfigFile) throws EPPCommandException {

		try {
			this.env.envInitialize(aConfigFile);
		}
		catch (EnvException e) {
			throw new EPPCommandException("EnvException caught :" + e.getMessage());
		}

		this.initialize();
	}

	/**
	 * Initializing {@code EPPApplication} after the configuration has been
	 * already initialized via {@link EPPEnvSingle} or one of its base classes.
	 *
	 * @exception EPPCommandException
	 *               Error initializing {@code EPPApplication}
	 */
	public void initialize() throws EPPCommandException {


		/**
		 * Initialize the EPPCodec
		 */
		try {
			// gets the list of all the
			// protocolExtensions,CommandResponseExtensions and MapFactories
			Vector protocolExts = null;
			Vector commandExts = null;

			try {
				protocolExts = EPPEnv.getProtocolExtensions();
			}
			catch (EPPEnvException ex) {
				// If we get an EPPEnvException here, it most likely indicates
				// that the EPP.ProtocolExtensions is set to null in the config
				// file.
				protocolExts = null;
			}

			try {
				commandExts = EPPEnv.getCmdResponseExtensions();
			}
			catch (EPPEnvException ex) {
				// If we get an EPPEnvException here, it most likely indicates
				// that the EPP.CmdRspExtensions is set to null in the config file.
				commandExts = null;
			}

			Vector extensionsVector = new Vector();

			if ((protocolExts != null) && protocolExts.elements().hasMoreElements()) {
				for (int i = 0; i < protocolExts.size(); i++) {
					extensionsVector.addElement(protocolExts.elementAt(i));
				}
			}

			if ((commandExts != null) && commandExts.elements().hasMoreElements()) {
				for (int j = 0; j < commandExts.size(); j++) {
					extensionsVector.addElement(commandExts.elementAt(j));
				}
			}

			// end if
			// Now instantiate the Codec instance with both the mapfactories and
			// extension factories
			EPPCodec.getInstance().init(EPPEnv.getMapFactories(), extensionsVector);
		}

		catch (EPPEnvException e) {
			throw new EPPCommandException("EPPApplication.initialze():  when initializing EPPCodec: " + e);
		}
		catch (EPPCodecException e) {
			throw new EPPCommandException("EPPApplication.initialze():  when initializing EPPCodec: " + e);
		}

		// Initialize the Parser Pool
		initXmlPools();

	}

	/**
	 * Initialize the XML pools, which include the parser and transformer pools.
	 */
	private void initXmlPools() {
		// Pools not initialized?
		if (!poolsInitialized) {

			// Get reference to each of the pool instances, which will initialize
			// them if they are not already initialized.
			EPPSchemaCachingParserPool.getInstance();
			EPPTransformerPool.getInstance();

			poolsInitialized = true;
		}
	}

	/**
	 * Instance method responsible for Cleanup and termination of the
	 * EPPApplication.
	 *
	 * @exception EPPCommandException
	 *               Not currently thrown
	 */
	public void endApplication() throws EPPCommandException {
		// do nothing
	}
}
