stg.pr.engine.CProcessRequestEngine.java Source code

Java tutorial

Introduction

Here is the source code for stg.pr.engine.CProcessRequestEngine.java

Source

/**
 * Copyright (c) 2014 Mastek Ltd. All rights reserved.
 * 
 * This file is part of JBEAM. JBEAM 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.
 *
 * JBEAM 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 the specific language governing permissions and 
 * limitations.
 *
 *
 * $Revision: 3829 $
 *
 * 
 */

package stg.pr.engine;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.sql.DataSource;

import org.apache.commons.lang.SystemUtils;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import stg.customclassloader.CCustomClassLoaderFactory;
import stg.customclassloader.IPREClassLoaderClient;
import stg.database.CBeanException;
import stg.database.CDynamicDataContainer;
import stg.database.CDynamicDataContainerException;
import stg.database.CDynamicQueryException;
import stg.pr.beans.CProcessStatusBean;
import stg.pr.beans.ProcessReqParamsController;
import stg.pr.beans.ProcessReqParamsEntityBean;
import stg.pr.beans.ProcessRequestController;
import stg.pr.beans.ProcessRequestEntityBean;
import stg.pr.beans.ProcessRequestScheduleController;
import stg.pr.beans.ProcessRequestScheduleEntityBean;
import stg.pr.engine.IJOBMonitor.JOB_STATUS;
import stg.pr.engine.IProcessRequest.REQUEST_SOURCE;
import stg.pr.engine.IProcessRequest.REQUEST_STATUS;
import stg.pr.engine.IProcessRequest.REQUEST_TYPE;
import stg.pr.engine.datasource.IDataSourceFactory;
import stg.pr.engine.mailer.CMailer;
import stg.pr.engine.mailer.EMail;
import stg.pr.engine.scheduler.CRequestScheduler;
import stg.pr.engine.scheduler.IRequestIdGenerator;
import stg.pr.engine.scheduler.ISchedule.SCHEDULE_STATUS;
import stg.pr.engine.startstop.CStartEngine;
import stg.pr.engine.startstop.IReboot;
import stg.pr.engine.startstop.IStartStop;
import stg.pr.engine.startstop.IStopEvent;
import stg.pr.engine.vo.RequestStatusVO;
import stg.utils.CDate;
import stg.utils.CDateException;
import stg.utils.CSettings;
import stg.utils.Day;
import stg.utils.PREDataType;
import stg.utils.StringUtils;

import com.hazelcast.config.Config;
import com.hazelcast.config.ConfigLoader;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.Member;
import com.stg.logger.LogLevel;
import com.stg.logger.LoggingOutputStream;

//import de.schlichtherle.license.LicenseContent;
//import stg.pr.engine.license.LicenseParamImpl;
//import stg.pr.engine.license.LicenseRequestor;
//import stg.pr.engine.license.LicenseVerifier;

/**
 * This Class will act as an engine to execute requested processes in the
 * background.
 * <p>
 * It continuously scans the PROCESS_REQUEST table and executes queued requests
 * with status = 'Q' This Engine spawns threads for processnig multiple requests
 * at the same time thus taking maximum advantage of the CPU.
 * </p>
 * 
 * @version $Revision: 3829 $
 * @author Kedar C. Raybagkar
 **/
public class CProcessRequestEngine implements Runnable, IPREClassLoaderClient {

    // public instance constants and class constants

    // /** constant for defining the request log buffer size **/
    // public static final int REQUEST_LOG_BUFFER_SIZE = 32 * 1024; // 32 KB
    //    
    // /** constant for defining the engine log buffer size **/
    // public static int ENGINE_LOG_BUFFER_SIZE = 16 * 1024; // 16 KB

    // public instance variables

    // public class(static) variables

    // protected instance constants and class constants

    // protected instance variables

    // protected class(static) variables

    // package instance constants and class constants

    // package instance variables

    // package class(static) variables

    // private instance constants and class constants

    private static final String ORDER_BY_CLAUSE = "ORDER BY priority";

    /**
     * The version control system will update this revision variable and thus
     * the revision numbers will automatically get updated. Comment for
     * <code>REVISION</code>
     */
    private static final String REVISION = "$Revision: 3829 $";

    // private instance variables

    /**
     * Instance of CProcessRequestEngine. Comment for <code>instance_</code>.
     */
    private static CProcessRequestEngine instance_;

    /**
     * Maxium number of threads that the PRE will spawn for StandAlone Requests.
     */
    private final int iStandAloneMaximumThread_;

    /**
     * Maxium number of threads that the PRE will spawn for Group Request.
     */
    private final int iGroupMaximumThread_;

    /**
     * Increamented when a Thread is created and decreamented when the thread
     * processing is over for StandAlone Requests. This variable is identified
     * as volatile as multiple threads can modify the value.
     */
    private AtomicInteger iThreadCounter_;

    /**
     * Increamented when a Thread is created and decreamented when the thread
     * processing is over. This variable is identified as volatile as multiple
     * threads can modify the value.
     */
    private AtomicInteger iGrpThreadCounter_;

    /**
     * Connection which is been used by the Engine.
     */
    private Connection staticConnection_;

    /**
     * PrintWriter reference used to write engine log
     */
    private static Logger objEngineLogger_ = Logger.getLogger("Engine");

    /**
     * Reboot the engine. If the variable is set to true then the engine reboots
     * itself. Comment for <code>bReBoot</code>.
     */
    private AtomicBoolean bReBoot = new AtomicBoolean(false);

    /**
     * Sleep time before the engine reboots itself. Default value -1. Comment
     * for <code>lRebootSleepTime</code>.
     */
    private long lRebootSleepTime = -1;

    /**
     * Reboot counter that keeps the count of number of reboots. Default value
     * -1. Comment for <code>lRebootCounter</code>.
     */
    private AtomicInteger iRebootCounter = new AtomicInteger(-1);

    /**
     * The maximum number of reboots can the engine do. Default value -1.
     * Comment for <code>lRebootMaxCounter</code>.
     */
    private int lRebootMaxCounter = -1;

    /**
     * FILTER_CONDITION for the request_type. Comment for
     * <code>FILTER_CONDITION</code>.
     */
    private String FILTER_CONDITION;

    // /** Reference variable for the Connection Pool object for StandAlone
    // Service Engine
    // */
    // private ConnectionPool pool_;
    //    
    // /** Reference variable for the Connection Pool object for Grouped Service
    // Engine
    // */
    // private ConnectionPool poolGrouped_;

    // /**
    // * JDBC Connection Pool Manager.
    // * Comment for <code>poolManager_</code>.
    // */
    // private jdbc.pool.CConnectionPoolManager poolManager_;

    /**
     * This variable holds the time interval for which the engine waits when
     * there are no queued requests. The max size is picked up from waitinterval
     * property of pr.properties. Once the wait interval expires the engine once
     * again queries for queued requests. This value can be changed in the
     * properties file and re-loaded using
     * {@link stg.utils.CReloadPropertiesHandler} to reflect the change.
     * 
     */
    private long lWaitInterval_;

    /**
     * This variable holds the path where the request log file is created The
     * path is picked up from requestlogfilepath property of pr.properties This
     * path does not include the name of the file The name of the log file is
     * the Request Id picked up from the PROCESS_REQUEST table
     */
    private String strReqLogFilePath_;

    /**
     * This variable holds the http url with which the log file can file can be
     * viewed The path is picked up from requestlogfileurl property of
     * pr.properties This path does not include the name of the file The name of
     * the log file is the Request Id picked up from the PROCESS_REQUEST table
     */
    private String strReqLogFileUrl_;

    /**
     * This variable holds the extension for the request log file, for eg: html,
     * txt, etc.. The path is picked up from requestlogfileextension property of
     * pr.properties
     */
    private String strReqLogFileExtension_;

    /**
     * This variable holds the format in which date values have to be stored in
     * the Param_Val field of the PROCESS_REQ_PARAMS table The dateformat is
     * picked up from paramdateformat property of pr.properties
     */
    private SimpleDateFormat paramSimpleDateFormat_;

    /**
     * This variable holds the format in which time values (Datetime field
     * values) have to be stored in the Param_Val field of the
     * PROCESS_REQ_PARAMS table The timeformat is picked up from paramtimeformat
     * property of pr.properties
     */
    private SimpleDateFormat paramSimpleTimeFormat_;

    /**
     * This variables holds the date time format picture.
     */
    private SimpleDateFormat paramSimpleDateTimeFormat_;

    /**
     * This variable holds the delimiter which is to be used to delimit array
     * values while storing them as a string in the Param_Val field of the
     * PROCESS_REQ_PARAMS table It is picked up from paramarrvaluedelim property
     * of pr.properties
     */
    private String strParamArrValueDelim_;

    // /** This attribute is set to true when the engine exits the indefinite
    // loop
    // * This gives a signal to the addShutdownHook thread that the engine is
    // terminated and
    // * the resources can be released
    // */
    // private boolean bEngineTerminationConfirmed_;

    /**
     * This attribute is set to true when the engine exits the indefinite loop
     * This gives a signal to the addShutdownHook thread that the engine is
     * terminated and the resources can be released
     */
    private AtomicBoolean bEngineTerminated_ = new AtomicBoolean(false); // This variable can be
    // replaced with
    // tEngine_.isInterrupted()
    // ??

    /**
     * This attribute is set to true when the engine exits the indefinite loop
     * This gives a signal to the addShutdownHook thread that the engine is
     * terminated and the resources can be released
     */
    private AtomicBoolean bGroupedEngineTerminated_ = new AtomicBoolean(false); // This variable can be
    // replaced with
    // tMain_.isInterrupted()
    // ??

    /**
     * This thread object refers to the main thread instance that is spawned in
     * the startEngine() method. The scanning and execution of grouped requests
     * is done in this thread.
     */
    private Thread tEngine_;

    /**
     * This thread object refers to the thread instance that is spawned in the
     * startEngine() method. The scanning and execution of standalone requests
     * is done in this thread.
     */
    private Thread tMain_;

    /**
     * This thread object refers to the thread instance that is spawned in the
     * Shut Down hook placed on the main method. The termination of the engine
     * depends on this thread getting interrupted.
     */
    private Thread tInterrupt_;

    /**
     * This attribute is used to store the message that is repeatedly used
     * across from multiple places.
     */
    private MessageFormat mfSleepMessageForEngine_ = new MessageFormat(
            "Queued requests does not exist, {0} service will sleep for {1, number} seconds and scanning will re-start ....");

    /**
     * All the threads that are created by the engine are added in this vector
     * and as and when. the thread finishes the process then it is removed from
     * the vector.The terminateEngine() method will wait till all the threads
     * that are already in process gets over. The engine will not abort the
     * process if execution of some process is beeing processed.
     */
    private Vector<Thread> vectorThreads_;

    /**
     * All the threads that are created by the engine are added in this vector
     * and as and when. the thread finishes the process then it is removed from
     * the vector.The terminateEngine() method will wait till all the threads
     * that are already in process gets over. The engine will not abort the
     * process if execution of some process is beeing processed.
     */
    private Vector<Thread> vectorThreadsGroup_;

    /**
     * This attribute is used to store the extra query conditions for the
     * Dynamic Data Container.
     */
    private HashMap<String, String> hmWhereCondition_;

    /**
     * This attribute is used to store the value of the Group Engine ON or OFF.
     */
    private boolean bGroupEngineToBeStarted_;

    /**
     * This attribute is used to store the time interval of the Stuck Thread
     * Monitor.
     */
    private long lStuckThreadMonitorInterval_;

    /**
     * Thread that is created for monitoring the Stuck Threads.
     */
    private Thread tMonitorThread_;

    /**
     * This variable is used to store the instance of the CHttpServer.
     * 
     * Comment for <code>httpserver_</code>
     */
    private CHttpServer httpserver_;

    /**
     * This variable is used to store the Number of Stuck Threads that are
     * marked by the Monitor Thread.
     * 
     * Comment for <code>iStuckThreads_</code>
     */
    private final AtomicInteger iStuckThreads_ = new AtomicInteger(0);

    /**
     * This variable is used to store the Number of Stuck Threads that cross the
     * maximum limit.
     * 
     * Comment for <code>iStuckThreadThatCrossMaxLimit_</code>
     */
    private final AtomicInteger iStuckThreadThatCrossMaxLimit_ = new AtomicInteger(0);

    /**
     * Maximum queued requests to be fetched in a single fetch. Comment for
     * <code>iMaximumFetchSizeAtATime_</code>
     */
    private int iMaximumFetchSizeAtATime_;

    /**
     * The time interval after which, the Process Monitor will send escalation
     * mails. This is applicable only for JOBs that have crossed MAX STUCK
     * THREAD Limit. Comment for <code>jobMonitorEscalationTimeInterval_</code>
     */
    private int jobMonitorEscalationTimeInterval_;

    /**
     * This variable stores the message that will be set when the engine is
     * being terminated. Termination can occur if Stop Request is given and/or
     * if JDBC Exception occurs. Comment for <code>stopMessageForEmail_</code>
     */
    private volatile String stopMessageForEmail_;

    // /**
    // * Byte Array Output stream for writing exception to string.
    // * Comment for <code>bytes_</code>.
    // */
    // private ByteArrayOutputStream bytes_;

    // /**
    // * PrintWriter wrapper arround the Byte Array Output stream.
    // * Comment for <code>pwException_</code>.
    // */
    // private PrintWriter pwException_;

    /**
     * New Line character identifier. Comment for <code>NEW_LINE</code>.
     */
    private final String NEW_LINE = System.getProperty("line.separator");

    private PREInfo info = new PREInfoImpl();

    /**
     * Stores whether the cluster handshake process was done or not. True if
     * done and false if not done. It is expected that the group engine should
     * wait till the hand shake is true.
     */
    private boolean bClusterHandShakeDone_ = false;

    /**
     * Final variable to store the context.
     */
    private PREContextImpl context_;

    //   /**
    //    * License Content.
    //    */
    //   private LicenseContent licContent_;

    /**
     * Data Source for the queue.
     */
    private IDataSourceFactory dataSourceFactory_;

    private volatile HeartBeatState state_;

    private ConcurrentHashMap<String, Service> services_ = new ConcurrentHashMap<String, Service>();

    private Member member_;

    // /**
    // * Stores true if licensed.
    // */
    // private boolean bValidLicense_;

    // private class(static) variables

    // constructors

    /**
     * Constructor of the class.
     * <p>
     * This constructor accepts a String variable that has the path of the init
     * file that has the path of all the property files that have to be loaded.
     * The engine only accesses properties from the pr.properties file. However
     * if the processes, that have to be executed, require any more property
     * files, then the path of these files can also be mentioned in this init
     * file
     * </p>
     * 
     * <p>
     * <ul>
     * <li>
     * Once the property file is loaded using the CSettings class, all the
     * attributes that the engine might access are retrieved and initialized to
     * the corresponding private member variables</li>
     * 
     * <li>
     * The max size defined for both the log files are checked, against the
     * respective buffer sizes, to see that max size's specified are greater
     * than the buffer sizes</li>
     * 
     * <li>
     * Engine log file is initialized and a database connection pool is created</li>
     * 
     * <li>
     * A Shutdown hook is added that listens for a termination event for eg:
     * CTRL-C Once the event occurs appropriate action is taken to release
     * resources.</li>
     * </ul>
     * </p>
     * 
     * @param pstrInitFile
     *            String path of the init file that has the path of all the
     *            property files that have to be loaded
     * @param pstrLoggerFile
     *            Log4J.properties file.
     * @throws Exception
     * 
     */
    private CProcessRequestEngine(String pstrInitFile, String pstrLoggerFile, int iRebootCntr) throws Exception {

        try {
            PropertyConfigurator.configure(pstrLoggerFile);
            CSettings.getInstance().load(pstrInitFile);
            objEngineLogger_.log(LogLevel.NOTICE, info.toString());
            context_ = new PREContextImpl();
            context_.setPREinfo(info);
            if (objEngineLogger_.isInfoEnabled()) {
                objEngineLogger_.info("Initializing Engine");
            }
            setRebootCounter(iRebootCntr);
            //         System.setProperty("java.util.prefs.PreferencesFactory",
            //               "stg.utils.prefs.PREPreferencesFactoryImpl");
            //         System.setProperty("java.util.prefs.PreferencesFactory.file",
            //               CSettings.get("pr.java.util.prefs.PreferencesFactory.file",
            //                     null));
            //         try {
            //            installLic(); // always install the license so that if the
            //            // license is changed in between it will get
            //            // reflected.
            //            licContent_ = readLicense();
            //            LicenseVerifier.verify(licContent_);
            //            objEngineLogger_.log(LogLevel.NOTICE, "Licensed to "
            //                  + licContent_.getHolder().getName() + " for usage of "
            //                  + licContent_.getConsumerAmount() + " threads.");
            //            objEngineLogger_.log(LogLevel.NOTICE, "Valid up to "
            //                  + licContent_.getNotAfter());
            //            Day now = new Day();
            //            objEngineLogger_.log(LogLevel.NOTICE, "Days remaining "
            //                  + Math.abs(now.daysBetween(licContent_.getNotAfter())));
            //         } catch (LicenseContentException lce) {
            //            generateLicenseRequest();
            //            objEngineLogger_.log(LogLevel.FATAL, "Invalid license.");
            ////            System.err.println(lce.getLocalizedMessage());
            //            throw new Exception(lce.getLocalizedMessage());
            //         } catch (Exception e2) {
            //             objEngineLogger_.log(LogLevel.FATAL, "Invalid license.");
            //            generateLicenseRequest();
            ////            System.err.println(e2.getLocalizedMessage());
            //            throw new Exception(e2.getLocalizedMessage());
            //         }

            lStuckThreadMonitorInterval_ = Math
                    .abs(Long.parseLong(CSettings.get("pr.stuckthreadmonitorinterval", "0")));
            if (lStuckThreadMonitorInterval_ <= 0) {
                throw new IllegalArgumentException(
                        "Property stuckthreadmonitorinterval should be greater than zero");
            }
            if (objEngineLogger_.isEnabledFor(LogLevel.FINEST)) {
                objEngineLogger_.log(LogLevel.FINEST, "Redirecting System.out and System.err to log4j");
            }
            System.setErr(
                    new PrintStream(new LoggingOutputStream(Logger.getLogger("System.err"), Level.WARN), true));
            System.setOut(
                    new PrintStream(new LoggingOutputStream(Logger.getLogger("System.out"), Level.INFO), true));
        } catch (Exception e) {
            throw e;
        }

        if (objEngineLogger_.isInfoEnabled()) {
            objEngineLogger_.info("CLASSPATH=" + System.getProperty("java.class.path"));
        }

        strReqLogFilePath_ = CSettings.get("pr.requestlogfilepath");
        strReqLogFileUrl_ = CSettings.get("pr.requestlogfileurl");
        strReqLogFileExtension_ = CSettings.get("pr.requestlogfileextension");
        paramSimpleDateFormat_ = new SimpleDateFormat(CSettings.get("pr.paramdateformat"));
        paramSimpleTimeFormat_ = new SimpleDateFormat(CSettings.get("pr.paramtimeformat"));
        paramSimpleDateTimeFormat_ = new SimpleDateFormat(CSettings.get("pr.paramdatetimeformat"));
        strParamArrValueDelim_ = CSettings.get("pr.paramarrvaluedelim");

        FILTER_CONDITION = CSettings.get("pr.requesttypefilter", "XYZ");
        if (!FILTER_CONDITION.equals("INCLUDE") && !FILTER_CONDITION.equals("EXCLUDE")) {
            throw new CProcessRequestEngineException(
                    "Invalid FILTER type specified for property requesttypefilter.");
        }
        iStandAloneMaximumThread_ = CSettings.getInteger("pr.standalonemaxiumthreads");
        iGroupMaximumThread_ = CSettings.getInteger("pr.groupmaxiumthreads");
        if (iStandAloneMaximumThread_ <= 0) {
            throw new CProcessRequestEngineException("Invalid maximum threads for StandAlone engine configured.");
        }
        if (iGroupMaximumThread_ <= 0) {
            throw new CProcessRequestEngineException("Invalid maximum threads for Group engine configured.");
        }
        String strRequestTypes = CSettings.get("pr.processrequesttype", null);
        if (strRequestTypes == null) {
            throw new CProcessRequestEngineException(
                    "Invalid processrequesttype defined. There must be a default value.");
        }
        StringTokenizer tokenizer = new StringTokenizer(strRequestTypes, ",");
        StringBuffer buffer = new StringBuffer();
        while (tokenizer.hasMoreTokens()) {
            buffer.append("'");
            buffer.append(tokenizer.nextElement());
            buffer.append("'");
            buffer.append(",");
        }
        buffer.deleteCharAt(buffer.length() - 1);
        if (FILTER_CONDITION.equals("INCLUDE")) {
            FILTER_CONDITION = "req_type IN (" + buffer.toString() + ")";
        } else {
            FILTER_CONDITION = "req_type NOT IN (" + buffer.toString() + ")";
        }

        try {
            (CCustomClassLoaderFactory.getInstance()).getClassLoader(this);
            // dummy call As this is a SingleTon Factory Pattern
        } catch (Exception e) {
            throw e;
            // throw new CProcessRequestEngineException("ClassLoader: " +
            // e.getMessage());
        }

        iMaximumFetchSizeAtATime_ = Math.abs(
                Integer.parseInt(CSettings.get("pr.maximumfetchsizeinsinglefetch", CSettings.get("pr.dbcon"))));
        iThreadCounter_ = new AtomicInteger(1);
        iGrpThreadCounter_ = new AtomicInteger(1);
        setRebootMaxCounter(Integer.parseInt(CSettings.get("pr.rebootmaxcounter", "-1")));
        setRebootSleepTime(Long.parseLong(CSettings.get("pr.sleepbeforereboottime", "5")));

        hmWhereCondition_ = new HashMap<String, String>();
        hmWhereCondition_.put("getScheduledTime", " <= ");

        bGroupEngineToBeStarted_ = ((CSettings.get("pr.groupengine", "OFF").equals("OFF")) ? false : true);

        httpserver_ = new CHttpServer(); // instantiate http server

        // bEngineTerminationConfirmed_ = false;

        vectorThreads_ = new Vector<Thread>(); // Inital size will be equal to
        // the total threads
        vectorThreadsGroup_ = new Vector<Thread>(); // =================== ""
        // =======================

        // These NET properties are available only in JDK1.4.x and above.
        // Added by Kedar on July 31, 2004 .....SouthField Detroit USA
        System.setProperty("http.keepAlive", CSettings.get("pr.http.keepAlive", "true"));
        System.setProperty("http.maxConnections", CSettings.get("pr.http.maxConnections", "5"));
        System.setProperty("sun.net.client.defaultConnectTimeout",
                CSettings.get("pr.sun.net.client.defaultConnectTimeout", "10000"));
        System.setProperty("sun.net.client.defaultReadTimeout",
                CSettings.get("pr.sun.net.client.defaultReadTimeout", "10000"));

        try {
            jobMonitorEscalationTimeInterval_ = Math
                    .abs(Integer.parseInt(CSettings.get("pr.jobmonitorescalationtimeinterval", "30")));
        } catch (NumberFormatException e) {
            objEngineLogger_.error("Invalid value specified for jobmonitorescalationtimeinterval in properties.");
            if (objEngineLogger_.isInfoEnabled()) {
                objEngineLogger_.info("Defaulting jobmonitorescalationtimeinterval to 30 minutes.");
            }
            jobMonitorEscalationTimeInterval_ = 30;
        }

        /*
         * Anonymous inner class passed as a parameter to addShutdownHook This
         * thread is registered with the JVM, and the JVM starts this just
         * before shutting down. For eg: when u try to abort by pressing Ctrl-C.
         * Hence run method is called and in turn terminateEngine method is
         * called where resources are released.
         */
        if (objEngineLogger_.isInfoEnabled()) {
            objEngineLogger_.info("Add ShutDown Hook ....");
        }
        if (objEngineLogger_.isInfoEnabled()) {
            objEngineLogger_.info("ShutDown Hook Added....");
            objEngineLogger_.info("Initializing Connection Pool ....");
        }
        Class<?> c = Class.forName(
                CSettings.get("pr.dataSourceFactory", "stg.pr.engine.datasource.defaultimpl.PREDataSourceFactory"));
        Object obj = c.newInstance();
        if (obj instanceof IDataSourceFactory) {
            dataSourceFactory_ = (IDataSourceFactory) obj;
            if (!dataSourceFactory_.initialize(new File(CSettings.get("pr.dataSourceFactoryConfigFile")))) {
                throw new CProcessRequestEngineException("Could not initialize the data source factory.");
            }
        } else {
            throw new CProcessRequestEngineException("Class does not implement IDataSource");
        }

        if (objEngineLogger_.isInfoEnabled()) {
            objEngineLogger_.info("Initiating the cluster using the configuration from file "
                    + System.getProperty("hazelcast.config"));
        }
        Config config = ConfigLoader.load(System.getProperty("hazelcast.config"));
        Hazelcast.init(config);

        loadStartupClasses();

        for (Entry<String, Service> entry : services_.entrySet()) {
            Service service = entry.getValue();
            if (service instanceof Singleton<?>) {
                Singleton<?> singleton = (Singleton<?>) service;
                context_.addSingletonIfAbsent(entry.getKey(), singleton);
                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Service " + entry.getKey() + ":" + entry.getValue().getClass().getName()
                            + "made available to the context.. ");
                }
            } else {
                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Service " + entry.getKey() + ":" + entry.getValue().getClass().getName()
                            + "is unavailable to the context.. ");
                }
            }
        }

        startWebServer();

        //      if (CSettings.get("pr.reportService", "OFF").equalsIgnoreCase("ON")) {
        //         if (objEngineLogger_.isInfoEnabled()) {
        //            objEngineLogger_.info("Starting the Report Services.");
        //         }
        //         try {
        //            EngineConfig reportConfig = new EngineConfig();
        //            reportConfig.setBIRTHome(CSettings.get("pr.birt.home"));
        //            reportConfig.setLogConfig(CSettings.get("pr.birt.log.dir"),
        //                  java.util.logging.Level.parse(CSettings
        //                        .get("pr.birt.log.level")));
        //            reportConfig.setProperty("ThreadPoolServiceSize", CSettings
        //                  .getInt("pr.birt.threadpoolsize", 3));
        //            reportService = ReportService.getService(reportConfig);
        //            if (objEngineLogger_.isEnabledFor(LogLevel.NOTICE)) {
        //               objEngineLogger_.log(LogLevel.NOTICE,
        //                     "Report Services started");
        //            }
        //         } catch (ReportServiceException e) {
        //            objEngineLogger_.fatal("Report Service exception encountered",
        //                  e);
        //            if (objEngineLogger_.isEnabledFor(LogLevel.NOTICE)) {
        //               objEngineLogger_.log(LogLevel.NOTICE,
        //                     "Unable to start the report services.");
        //            }
        //         }
        //      }

        if (objEngineLogger_.isInfoEnabled()) {
            objEngineLogger_.info("Engine Initialized");
        }
        // This thread is now assigned upfront as in the Terminate engine if
        // called from Reboot Sequence then
        // the shutdown hook has to be removed from the Runtime instance.
        tInterrupt_ = new Thread("shutdown") {

            public void run() {
                objEngineLogger_.log(LogLevel.NOTICE, "ShutDown Hook In Running mode.");
                terminateEngine();
            }
        };
        Runtime.getRuntime().addShutdownHook(tInterrupt_);

    }

    private void loadStartupClasses() throws Exception {
        String str = CSettings.get("pr.startUpClasses");

        if (!(str == null || "".equals(str))) {
            Iterator<String> iter = StringUtils.listTokens(str, ';');
            while (iter.hasNext()) {
                String clazzName = iter.next();
                String key = clazzName;
                if (StringUtils.countTokens(clazzName, ':') > 1) {
                    key = StringUtils.extractTokenAt(clazzName, ':', 1);
                    clazzName = StringUtils.extractTokenAt(clazzName, ':', 2);
                }
                Class<?> clazz = Class.forName(clazzName);
                Object obj1 = clazz.newInstance();
                if (obj1 instanceof Service) {
                    Service instance = (Service) obj1;
                    instance.init(context_);
                    services_.put(key, instance);
                }
            }
        }
    }

    //   /**
    //    * 
    //    */
    //   private void generateLicenseRequest() throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidAlgorithmParameterException, IOException {
    //      LicenseRequestor licenseRequestor = new LicenseRequestor();
    //      licenseRequestor.generateRequest();
    //      return;
    //   }
    //
    // finalize method, if any

    // main method

    /**
     * Entry point of the engine It first checks whether one argument is passed.
     * If no argument is found an exception is thrown with an appropriate
     * message. If arguments are passed correctly an object of this class is
     * created and engine starts execution.
     * 
     * @param args
     *            expects args array of length 1, containing the path of init
     *            file
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        CProcessRequestEngine objPre = null;

        try {

            if (args.length < 2) {
                throw new Exception(
                        "Usage: java stg.pr.engine.CProcessRequestEngine <prinit.properties file path> <log4j.properties file path>");
            }
            if (!SystemUtils.IS_JAVA_1_6) {
                throw new Exception("Unable to start. Requires Java 1.6");
            }

            String str = System.getProperty("pre.reboot.attempt");
            int iRebtCnt = -1;
            if (str != null) {
                iRebtCnt = Integer.parseInt(str);
            }

            try {
                // if ("true".equalsIgnoreCase(System.getProperty("genlicreq",
                // "false"))) {
                // LicenseRequestor licenseRequestor = new LicenseRequestor();
                // licenseRequestor.generateRequest();
                // return;
                // }
                objPre = CProcessRequestEngine.getInstance(args[0], args[1], iRebtCnt);
                objPre.startEngine();
            } catch (Exception e) {
                if (objPre != null) {
                    if (!objPre.isReboot()) {
                        throw e;
                    }
                } else {
                    throw e;
                }
            }
        } catch (Exception e) {
            throw e;
        } finally {
            if (objPre != null) {
                if (objPre.isReboot() && objPre.getRebootCounter() > objPre.getRebootMaxCounter()) {
                    objPre.setReboot(false);
                }
            }
        }
        // System.exit(100);

    }

    // public methods of the class in the following order

    /**
     * Creates an instance of the CProcessRequestEngine.
     * 
     * @param pstrFile
     *            The initial properties file to be loaded by CSettings.
     * @param pstrLoggerFile
     *            Log4J.properties file.
     * @param iRebootCnt
     *            Reboot counter.
     * 
     * @return CProcessRequestEngine Engine
     * @throws Exception
     */
    protected synchronized static CProcessRequestEngine getInstance(String pstrFile, String pstrLoggerFile,
            int iRebootCnt) throws Exception {
        if (instance_ == null) {
            instance_ = new CProcessRequestEngine(pstrFile, pstrLoggerFile, iRebootCnt);
        }
        return (instance_);
    }

    /**
     * Returns the created instance of the Engine. May return null in case
     * engine is not started.
     * 
     * @return CProcessRequestEngine Engine.
     */
    public static CProcessRequestEngine getInstance() {
        // if (instance_ == null)
        // {
        // throw new CProcessRequestEngineException("Engine Not Started");
        // }
        return (instance_);
    }

    /**
     * Starts the StandAlone Request Service Engine & Grouped Request Service
     * Engine
     * 
     * @throws Exception
     *             in case of any errors.
     */
    public void startEngine() throws Exception {
        tMain_ = Thread.currentThread();
        // Sequence changed on 2.1.2006 by Kedar.
        // The initial sequence was that of starting the job monitor thread and
        // then starting the stand alone
        // engine and then group engine. But in the job monitor thread we are
        // checking for the stand alone engine
        // thread if not alive then do a shutdown of the job monitor thread.
        // This used to work well in case of
        // SUN Solaris 9 machine but failed on LINUX. Therefore this change is
        // made.
        if (objEngineLogger_.isInfoEnabled()) {
            objEngineLogger_.info("Starting the Engine..");
        }
        member_ = Hazelcast.getCluster().getLocalMember();
        Iterator<Member> iterator = Hazelcast.getCluster().getMembers().iterator(); // cluster_.getClusterTopology().getNodes().iterator();
        Member topoNode = iterator.next();
        if (topoNode.equals(member_)) {
            state_ = HeartBeatState.RUNNING;
            context_.getMap().put("state", state_);
        } else {
            state_ = HeartBeatState.PASSIVE;
            // if (!context_.getPREVersion().equals(strBundleDetailsArray_[1]))
            // {
            // throw new
            // CProcessRequestEngineException("Cluster configuration does not match.");
            // }
        }
        StringBuffer sbuffer = getDefaultEmailAttributes();
        sbuffer.append("Cluster Mode    : " + state_.name());
        sendDefaultMail(
                "Engine is starting..."
                        + (((getRebootCounter() > 0) ? "Reboot Attempt #" + getRebootCounter() : "")),
                sbuffer.toString(), true);
        if (Hazelcast.getConfig().getNetworkConfig().getJoin().getTcpIpConfig().getMembers().size() > 1) {
            objEngineLogger_.log(LogLevel.NOTICE, "PRE is configured for cluster mode on "
                    + Hazelcast.getConfig().getNetworkConfig().getJoin().getTcpIpConfig().getMembers().size()
                    + " different machines.");
        } else {
            objEngineLogger_.log(LogLevel.NOTICE,
                    "PRE is configured for cluster mode restricted to a single machine.");
        }
        objEngineLogger_.log(LogLevel.NOTICE, "Going into " + state_.name() + " mode.");
        ClusterListener listener = new ClusterListener(this);
        Hazelcast.getCluster().addMembershipListener(listener);
        if (state_.equals(HeartBeatState.PASSIVE)) {
            deactivate();
            if (state_.equals(HeartBeatState.STOP)) {
                objEngineLogger_.log(LogLevel.NOTICE, "Initiating " + state_.name() + "....");
                bEngineTerminated_.set(true);
                bGroupedEngineTerminated_.set(true);
                stopMessageForEmail_ = "Stop Request was initiated";
            } else {
                context_.getMap().put("state", HeartBeatState.RUNNING);
                state_ = HeartBeatState.RUNNING;
                objEngineLogger_.log(LogLevel.NOTICE, "Initiating " + state_.name() + "....");
            }
        }
        if (state_ == HeartBeatState.RUNNING) {
            CMailer.getInstance(CSettings.get("pr.mailtype")).loadAndTransportSerializedEmails(this);
        }
        // if (bValidLicense_) {
        tEngine_ = new Thread(this, "grpeng"); // Name the thread.
        tEngine_.start();
        // }

        if (lStuckThreadMonitorInterval_ > 0) {
            if (objEngineLogger_.isInfoEnabled()) {
                objEngineLogger_.info("Initializing JOB Monitor...");
            }
            tMonitorThread_ = new MonitorThread("JobMonitorThread");
            tMonitorThread_.start();
        } else {
            objEngineLogger_.log(LogLevel.NOTICE, "Monitor Thread is currently OFF. "
                    + "To Start the monitor thread to identify the STUCK THREAD, have the value of the stuckthreadmonitorinterval property to a non zero positive integer.");
        }

        try {
            startServiceEngine();
        } catch (CProcessRequestEngineException e) {
            objEngineLogger_.error("Error While Starting the Service Engine for Normal Requests", e);
            objEngineLogger_.error("Stand Alone engine aborted.. Wait till PRE terminiates..");
            throw e;
        } finally {
            // if (cluster_.getClusterTopology().getNodes().size() == 1) {
            // clusterMap_.remove("state");
            // }
        }
        objEngineLogger_.log(LogLevel.NOTICE, "Stand Alone engine stopped.. Wait till PRE terminates.");

    }

    /**
     * Thread for running StandAlone Service Engine.
     * 
     */
    public void run() {
        try {
            if (bGroupEngineToBeStarted_) {
                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Starting the Group Engine");
                }
                //            if (((Properties) licContent_.getExtra()).getProperty(
                //                  "groupEngine").equalsIgnoreCase("off")) {
                //               objEngineLogger_.log(LogLevel.NOTICE,
                //                     "Not licensed for Group Request Processing");
                //               bGroupEngineToBeStarted_ = false;
                //               return;
                //            }
                startGroupServiceEngine();
            } else {
                objEngineLogger_.log(LogLevel.NOTICE, "Group Engine Not Started. "
                        + "To Start the group engine have the value of the groupengine property to ON ");
            }
        } catch (Exception e) {
            objEngineLogger_.error("Error While Starting the Service Engine for Group Requests", e);
            // no need to throw exception. just log it.
        }
        objEngineLogger_.log(LogLevel.NOTICE, "Group Engine stopped.. Wait till PRE terminates.");
    }

    /**
     * Returns a list of classes that need to be loaded by the system
     * classloader
     * 
     * @return a String array with the classes that need to be loaded by the
     *         System classloader.
     */
    public String[] getSystemLoadedClasses() {
        StringTokenizer stz = new StringTokenizer(CSettings.get("pr.systemloadedclasses"), ";");
        String[] saSystemLoadedClasses = new String[stz.countTokens()];
        int iElement = 0;

        while (stz.hasMoreTokens()) {
            saSystemLoadedClasses[iElement] = stz.nextToken();
            iElement++;
        }

        return saSystemLoadedClasses;
    }

    /**
     * Returns the path from where the class loader will load the classes
     * 
     * @return a String with the path where the classes can be found
     */
    public String getCustomClassLoaderClassPath() {
        return CSettings.get("pr.objclasspathforclassloader");
    }

    /**
     * Indicates whether the custom classloader has to reload classes or not
     * 
     * @return a boolean indicating whether the custom classloader has to reload
     *         classes or not
     */
    public boolean isReload() {
        return (((CSettings.get("pr.reloadobjclasses").equals("Y")) ? true : false));
    }

    /**
     * To stop the engine.
     * 
     * @param pobj
     *            IStartStop
     */
    public void stopEngine(IStartStop pobj) {
        if (pobj instanceof IReboot) {
            objEngineLogger_.log(LogLevel.NOTICE, "Rebooting the engine.");
            setReboot(true);
            setRebootCounter(-1); // This is because someone is doing a reboot
            // and it is not happening due to error.
            setRebootSleepTime(1);
            context_.getMap().put("state", HeartBeatState.REBOOT);
            state_ = HeartBeatState.REBOOT;
        } else {
            context_.getMap().put("state", HeartBeatState.STOP);
            state_ = HeartBeatState.STOP;
        }
        bEngineTerminated_.set(true);
        bGroupedEngineTerminated_.set(true);
        stopMessageForEmail_ = (isReboot() ? "Reboot" : "Stop") + " 'Request' requested. Normal Termination.";
        if (objEngineLogger_.isInfoEnabled()) {
            objEngineLogger_.info("Stopping The StandAlone Service Engine ....");
        }
        if (vectorThreads_.size() == 0) {
            tMain_.interrupt();
        }
        if (objEngineLogger_.isInfoEnabled()) {
            objEngineLogger_.info("Stopping The Grouped Service Engine ....");
        }
        if (vectorThreadsGroup_.size() == 0) {
            if (tEngine_ != null) {
                tEngine_.interrupt();
            }
        }
        if (lStuckThreadMonitorInterval_ > 0) {
            if (objEngineLogger_.isInfoEnabled()) {
                objEngineLogger_.info("Stopping Monitor Thread");
            }
            tMonitorThread_.interrupt();
        }

        // if (httpserver_.isStarted())
        // {
        // if (objEngineLogger_.isInfoEnabled()) {
        // objEngineLogger_.info("Stopping Web Service");
        // }
        // httpserver_.stop();
        // }
        // stopWebServer();

        // closeAll();
    }

    // protected constructors and methods of the class

    // package constructors and methods of the class

    // private constructors and methods of the class

    /**
     * Starts service for scanning standalone requests
     * 
     * @throws Exception
     */
    private void startServiceEngine() throws Exception {
        try {
            objEngineLogger_.log(LogLevel.NOTICE, "Start Service Engine for Stand Alone Requests....");

            startServiceForNormalRequests();

        } catch (Exception e) {
            stopMessageForEmail_ = exceptionToString(e);
            objEngineLogger_.error("Exception caught in the main Stand Alone engine", e);
            throw e;
        } finally {
            if (tMonitorThread_.isAlive()) {
                tMonitorThread_.interrupt();
            }
            if (objEngineLogger_.isDebugEnabled()) {
                objEngineLogger_.debug(
                        "Finally Block of startServiceEngine(). Please wait till the termination is confirmed.");
            }
        }
    }

    /**
     * Starts the Stand Alone service engine.
     * 
     * Gets the connection from the pool and Continuously scans the
     * PROCESS_REQUEST table for queued standalone requests and executes them
     * sequentially
     * 
     * <p>
     * Scanning continues in a loop until the bEngineTerminated_ attribute is
     * false. This attribute is set to true when the engine is interrupted, and
     * this loop exits.
     * </p>
     * <p>
     * The query picks up requests, from the table PROCESS_REQUEST, that have
     * the Req_Stat='Q' and GRP_ST_IND = 'S'. If requests are found then each
     * record is processed sequentially If no records are found then the engine
     * waits for a specified time (picked up from property file) and then
     * resumes scanning
     * </p>
     * 
     * <p>
     * This method will <b>spawn Threads</b> for processing stand alone
     * requests, thus taking maximum advantage of the CPU. The threads are
     * created by taking into account the number of connections available in the
     * pool - 2. As two connections are internally used by the Engine, One for
     * making updates for status and another for processing Grouped Requests.
     * </p>
     * 
     * @throws CProcessRequestEngineException
     * 
     */
    private void startServiceForNormalRequests() throws CProcessRequestEngineException {
        boolean isQueuedReqFound = false;
        ProcessRequestController objPrCont_ = null;

        StringBuffer reqLogFileName;
        StringBuffer reqLogFileUrl;
        // final int iNoOfThreads_ = (bValidLicense_?Integer.MAX_VALUE:2);

        try {

            reqLogFileName = new StringBuffer(50);
            reqLogFileUrl = new StringBuffer(50);

            if (objEngineLogger_.isInfoEnabled()) {
                objEngineLogger_.info("Starting StandAlone Engine ....");
            }
            if (objEngineLogger_.isDebugEnabled()) {
                objEngineLogger_.info("Getting JDBC Connection for the StandAlone Engine ....");
            }
            // staticConnection_ =
            // poolManager_.getConnection(CSettings.get("pr.dsforstandaloneeng"));
            DataSource ds = dataSourceFactory_.getDataSource(CSettings.get("pr.dsforstandaloneeng"));
            if (ds == null) {
                throw new CProcessRequestEngineException("NullPointerException for DataSource");
            }
            staticConnection_ = ds.getConnection();
            CDynamicDataContainer objDdc_ = new CDynamicDataContainer();
            objDdc_.addWhereClause(FILTER_CONDITION);
            objDdc_.addOrderByClause(ORDER_BY_CLAUSE);

            ProcessRequestEntityBean objPrEb_ = new ProcessRequestEntityBean();

            objPrCont_ = new ProcessRequestController(staticConnection_);
            setRebootCounter(-1); // Ideally here the Engine can be considered
            // as started.
            checkClusterPRE();
            if (!tMain_.isInterrupted() || !bEngineTerminated_.get()) {
                objEngineLogger_.log(LogLevel.NOTICE, "Stand Alone Engine Started..");
            }
            Iterator<RequestStatusVO> failOverRequestIterator = context_.getFailedOverRequests().iterator();
            while (!tMain_.isInterrupted()) {
                context_.setPREActive(true);
                boolean bTerminate = false;
                //            try {
                //               LicenseVerifier.verify(readLicense());
                //            } catch (LicenseContentException lce) {
                //               bTerminate = true;
                //               objEngineLogger_.fatal(lce.getLocalizedMessage());
                //            } catch (Exception e) {
                //               bTerminate = true;
                //               objEngineLogger_.fatal(e.getLocalizedMessage());
                //            }
                if (bTerminate) {
                    if (tEngine_ != null) {
                        tEngine_.interrupt();
                    }
                    break;
                }
                try {
                    isQueuedReqFound = false;
                    boolean failOverRequest = false;
                    if (!bEngineTerminated_.get()) {
                        if (objEngineLogger_.isDebugEnabled()) {
                            objEngineLogger_.debug("Entered infintite loop, Initializing Request Entity Bean ....");
                        }
                        setReboot(false);
                        objPrEb_.initialize();
                        if (objEngineLogger_.isDebugEnabled()) {
                            objEngineLogger_.debug("Building query ....");
                        }

                        if (objEngineLogger_.isDebugEnabled()) {
                            objEngineLogger_.debug("Querying for queued requests ....");
                        }
                        if (failOverRequestIterator.hasNext()) {
                            RequestStatusVO vo = failOverRequestIterator.next();
                            objEngineLogger_.log(LogLevel.NOTICE,
                                    "Re-Executing Failed-Over Request #" + vo.getReqId());
                            objPrEb_.setReqId(vo.getReqId());
                            objPrEb_.setReqStat(vo.getStatus());
                            objDdc_.build(staticConnection_, objPrEb_);
                            objDdc_.setMaximumFetchSize(iMaximumFetchSizeAtATime_);
                            objDdc_.setPartialFetch(true);
                            failOverRequestIterator.remove();
                            isQueuedReqFound = objDdc_.executeQuery(staticConnection_, objPrCont_, objPrEb_);
                            failOverRequest = true;
                        } else {
                            objPrEb_.setReqStat(REQUEST_STATUS.QUEUED.getID());
                            objPrEb_.setGrpStInd(REQUEST_TYPE.STANDALONE.getID());
                            objPrEb_.setScheduledTime(getCurrentTimestamp(staticConnection_));

                            objDdc_.build(staticConnection_, objPrEb_, hmWhereCondition_);
                            objDdc_.setMaximumFetchSize(iMaximumFetchSizeAtATime_);
                            objDdc_.setPartialFetch(true);
                            // This has been added later by Kedar on 3/1/2003
                            isQueuedReqFound = objDdc_.executeQuery(staticConnection_, objPrCont_, objPrEb_);
                            failOverRequest = false;
                        }
                    } // If engine is not terminated then only do the above
                      // stuff.
                    if (isQueuedReqFound) {// pending requests exist

                        if (objEngineLogger_.isInfoEnabled()) {
                            objEngineLogger_.info("Queued requests exists ....");
                        }

                        // The bEngineTerminated_ flag with an OR condition was
                        // added on 21.01.2004 by Kedar.
                        // This is because if the StopEngine tires terminate the
                        // engine and if there is a process
                        // already running then the engine should not enter the
                        // while loop.
                        while (objDdc_.next() && !(tMain_.isInterrupted() || bEngineTerminated_.get())) {
                            if (iThreadCounter_.get() <= iStandAloneMaximumThread_
                            //                           && iThreadCounter_.get() <= licContent_
                            //                                 .getConsumerAmount()
                            )
                            // if ( iThreadCounter_ <
                            // CSettings.getInt(("pr.standalonemaximumthreads",
                            // "2")) && iThreadCounter_ <=
                            // licContent_.getConsumerAmount())
                            {

                                ProcessRequestEntityBean objPrEb = (ProcessRequestEntityBean) objDdc_.get();

                                reqLogFileName.delete(0, reqLogFileName.length());
                                reqLogFileUrl.delete(0, reqLogFileUrl.length());
                                reqLogFileName.append(strReqLogFilePath_);
                                reqLogFileName.append(objPrEb.getReqId());
                                reqLogFileName.append(".");
                                reqLogFileName.append(strReqLogFileExtension_);

                                reqLogFileUrl.append(strReqLogFileUrl_);
                                reqLogFileUrl.append(objPrEb.getReqId());
                                reqLogFileUrl.append(".");
                                reqLogFileUrl.append(strReqLogFileExtension_);

                                // objEngineLogger_.info("Initialize Request Log File ....");

                                updateRequestStatus(staticConnection_, objPrCont_, objPrEb,
                                        REQUEST_STATUS.LAUNCHING, reqLogFileUrl.toString());

                                // Create a new thread and start the process.
                                // Increament the Thread counter so that if
                                // thread counter reaches
                                // Maximum of the connections available in pool
                                // then the engine should not spawn a new
                                // thread.
                                ThreadProcess tp = new ThreadProcess("Thread-ReqId#" + objPrEb.getReqId());
                                // tp.join(); //Joins the new thread to the
                                // parent (tEngine).
                                addStandAloneProcess(tp);
                                tp.setProcessRequestEntityBean(objPrEb);
                                tp.setLogFileName(reqLogFileName.toString());
                                tp.setLogFileNameURL(reqLogFileUrl.toString());
                                tp.setPool(dataSourceFactory_); // So that the
                                // ThreadProcess
                                // can request
                                // connection
                                // from Pool
                                tp.setFailedOver(failOverRequest);
                                tp.start();
                            } // if ( iThreadCounter_ <
                              // iTotalConnectionsInPool_)

                            // If all the available threads are spawned then
                            // wait for 10 seconds. This should be
                            // parameterised.
                            // If thread.sleep is not called then for that while
                            // loop it will take a huge CPU time and rest of the
                            // threads will be slow.
                            // The above comment is debatable. So commented
                            // currently.
                            boolean bInWaitMode = false;
                            if (iThreadCounter_.get() > iStandAloneMaximumThread_) {
                                bInWaitMode = true;
                                if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                                    objEngineLogger_.log(LogLevel.FINE, "Maximum thread spawning capacity (#"
                                            + (iThreadCounter_.get() - 1)
                                            + ") has reached. Going into Wait mode till one of the JOB gets over.");
                                }
                            }
                            long lCurrentTime = System.currentTimeMillis();
                            while (iThreadCounter_.get() > iStandAloneMaximumThread_) {
                                // try
                                // {
                                // Thread.sleep(10000);
                                // }
                                // catch (InterruptedException ie)
                                // {
                                // System.exit(1);
                                // }
                            }
                            long lWaitTime = System.currentTimeMillis() - lCurrentTime;
                            if (bInWaitMode) {
                                bInWaitMode = false;
                                if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                                    objEngineLogger_.log(LogLevel.FINE, "Wait Over. Waited for #" + lWaitTime
                                            + " milliseconds for some JOB to get over.");
                                }
                            }

                        } // end of while(objDdc.next())

                    } // end of if objDdc.getTotalRows() > 0
                    else {
                        if (!failOverRequestIterator.hasNext()) { // no failover
                            // jobs.
                            lWaitInterval_ = (Math.abs(Long.parseLong(CSettings.get("pr.waitinterval"))));
                            if (!(bEngineTerminated_.get() || tMain_.isInterrupted())) {
                                if (objEngineLogger_.isInfoEnabled()) {
                                    objEngineLogger_.info(mfSleepMessageForEngine_
                                            .format(new Object[] { "StandAlone", lWaitInterval_ }));
                                }
                                try {
                                    Thread.yield();
                                    TimeUnit.SECONDS.sleep(lWaitInterval_);
                                    // Thread.sleep(lWaitInterval_);
                                } catch (InterruptedException ie) {
                                    if (objEngineLogger_.isInfoEnabled()) {
                                        objEngineLogger_.info("Engine Thread Interrupted ..");
                                    }
                                    break;
                                }
                            } else {
                                if (bEngineTerminated_.get()) {
                                    tMain_.interrupt();
                                }
                            }
                        }
                    } // end of else
                } catch (CDynamicDataContainerException cdce) {
                    // This is under the assumption that the IO Exception can
                    // never be thrown by the object
                    // executed by the Engine as it can only throw
                    // CProcessRequestEngineException. This exception
                    // means that something wrong has happened in the Engine
                    // itself and so engine should get terminated.
                    stopMessageForEmail_ = exceptionToString(cdce);
                    objEngineLogger_.fatal("CDynamicQueryException Caught. Terminating StandAlone Engine", cdce);
                    setReboot(true);
                    break;
                } catch (CDynamicQueryException cdqe) {
                    // This is under the assumption that the IO Exception can
                    // never be thrown by the object
                    // executed by the Engine as it can only throw
                    // CProcessRequestEngineException. This exception
                    // means that something wrong has happened in the Engine
                    // itself and so engine should get terminated.
                    stopMessageForEmail_ = exceptionToString(cdqe);
                    objEngineLogger_.fatal("CDynamicQueryException Caught. Terminating StandAlone Engine", cdqe);
                    setReboot(true);
                    break;
                } catch (IOException ioe) {
                    // This is under the assumption that the IO Exception can
                    // never be thrown by the object
                    // executed by the Engine as it can only throw
                    // CProcessRequestEngineException. This exception
                    // means that something wrong has happened in the
                    // Connection.
                    try {
                        staticConnection_ = refreshJDBCConnection(4, staticConnection_,
                                CSettings.get("pr.dsforstandaloneeng"));
                    } catch (Exception e) {
                        stopMessageForEmail_ = exceptionToString(ioe);
                        objEngineLogger_.fatal("IOException Caught. Terminating StandAlone Engine", ioe);
                        setReboot(true);
                        ;
                        break;
                    }
                } catch (SQLException se) {
                    // This is under the assumption that the SQL Exception can
                    // never be thrown by the object
                    // executed by the Engine as it can only throw
                    // CProcessRequestEngineException. This exception
                    // means that something wrong has happened in the
                    // Connection.
                    objEngineLogger_.error("SQLException caught", se);
                    try {
                        staticConnection_ = refreshJDBCConnection(4, staticConnection_,
                                CSettings.get("pr.dsforstandaloneeng"));
                        // StackTraceElement[] elements = se.getStackTrace();
                        // for (int i = 0; i < elements.length; i++) {
                        //                     
                        // }
                    } catch (Exception e) {
                        stopMessageForEmail_ = exceptionToString(se);
                        objEngineLogger_.fatal("SQLException Caught. Terminating StandAlone Engine", se);
                        setReboot(true);
                        break;
                    }
                } catch (RuntimeException ree) {
                    objEngineLogger_.error("Runtime Exception Caught", ree);
                    // Just catch; no need to throw exception.
                } catch (CProcessRequestEngineException cree) {
                    objEngineLogger_.error("CProcessRequestEngineException Caught", cree);
                    // Just catch; no need to throw exception.
                } catch (Exception e) {
                    objEngineLogger_.error("Exception Caught", e);
                    // Just catch; no need to throw exception.
                } catch (Error e) {
                    if (e instanceof ThreadDeath) {
                        objEngineLogger_.fatal("Process killed through the PRE Web Service");
                    } else {
                        stopMessageForEmail_ = exceptionToString(e);
                        objEngineLogger_.fatal(e);
                        throw e;
                    }
                }

            } // end of while true

        } catch (ConnectException e) {
            stopMessageForEmail_ = exceptionToString(e);
            objEngineLogger_.fatal("ConnectException Caught. Terminating StandAlone Engine", e);
            if (getRebootCounter() > 0) {
                setReboot(true);
            }
        } catch (SQLException e) {
            stopMessageForEmail_ = exceptionToString(e);
            objEngineLogger_.fatal("SQLException Caught. Terminating StandAlone Engine", e);
            if (getRebootCounter() > 0) {
                setReboot(true);
            }
        } catch (IOException e) {
            stopMessageForEmail_ = exceptionToString(e);
            objEngineLogger_.fatal("IOException Caught. Terminating StandAlone Engine", e);
            if (getRebootCounter() > 0) {
                setReboot(true);
            }
        } catch (Exception e) {
            throw new CProcessRequestEngineException(e.getMessage(), e);
        } // end of 1st try catch block
        finally {
            ((PREContextImpl) context_).setPREActive(false);
            if (objEngineLogger_.isInfoEnabled()) {
                objEngineLogger_.info("Releasing Stand Alone Resources And Confirming Termination ...");
            }
            if (objPrCont_ != null) {
                try {
                    objPrCont_.close();
                } catch (SQLException e) {
                    objEngineLogger_.error("Caught exception while closing PRController.", e);
                }
            }
            // pool_.stopShrinking();
            reqLogFileName = null; // Nullifying the variables.
            reqLogFileUrl = null; // Nullifying the variables.
            if (tInterrupt_ != null) {
                if (tInterrupt_.isAlive()) {
                    if (objEngineLogger_.isInfoEnabled()) {
                        objEngineLogger_.info("Interrupting Shutdown Hook from Stand Alone Requests...");
                    }
                    tInterrupt_.interrupt();
                }
            }
            bEngineTerminated_.set(true);
        }
    } // end of startServiceForNormalRequests

    /**
     * Processes a request and executes it.
     * 
     * <p>
     * <ul>
     * <li>
     * Fetches parameters for the request from the table PROCESS_REQ_PARAMS and
     * populates them in a hashmap</li>
     * <li>
     * Initializes Request LogFile with the name of the log file being <request
     * id>.log</li>
     * <li>
     * Instantiate an object of the class that is mentioned in the
     * process_class_nm field of the PROCESS_REQUEST table and then cast it to
     * IProcessRequest. If the cast fails an appropriate exception is logged in
     * the Engine and Request Log</li>
     * <li>
     * Updates the Req_Stat field in PROCESS_REQUEST table with 'P', calls
     * various set..() methods on the object, which set the parameters required
     * for the process, and then finally call the processRequest() method which
     * actually has the logic of the process. Depending on success or failure of
     * execution of the process, either 'S' or 'E' is updated in the
     * PROCESS_REQUEST table.</li>
     * </ul>
     * </p>
     * 
     * In Case of an Error ({@link java.lang.Error}) the error is logged and
     * thrown to the main Engine. This error may or may not get logged and
     * totaly depends on the JVM implementation.
     * 
     * @param pcon
     *            Connection object
     * @param pobjPrCont
     *            Controller object reference for table PROCESS_REQUEST
     * @param pobjPrEb
     *            EntityBean object reference for table PROCESS_REQUEST
     * @param pobjDdcParams
     *            DataContainer object reference for querying table
     *            PROCESS_REQ_PARAMS
     * @param pobjParamsCont
     *            Controller object reference for table PROCESS_REQ_PARAMS
     * @param pobjParamsEb
     *            EntityBean object reference for table PROCESS_REQ_PARAMS
     * @param objProcessRequest_
     *            Object of IProcessRequest.
     * @param logFileName
     *            Log file name against which the response stream is to be released.
     * @param pstrLogFileURL
     *            Logger file
     * @return bSuccess true if request is processed and executed successfully,
     *         else false
     * 
     */
    private boolean processEachRequest(Connection pcon, ProcessRequestController pobjPrCont,
            ProcessRequestEntityBean pobjPrEb, CDynamicDataContainer pobjDdcParams,
            ProcessReqParamsController pobjParamsCont, ProcessReqParamsEntityBean pobjParamsEb,
            ProcessRequestServicer objProcessRequest_, File logFileName, String pstrLogFileURL) {
        long lStartTime = System.currentTimeMillis();
        boolean bSuccess = true;
        //      Throwable objThrowable ;
        HashMap<String, Object> hmParams = null;
        // PrintWriter objRequestLogger_ = null;

        // IProcessRequest objProcessRequest_ = null;
        boolean bScheduleExists = false;
        boolean bScheduleExecuted = false;
        boolean retryPossible = pobjPrEb.getRetryCnt() < pobjPrEb.getRetryTimes();
        boolean toBeRetryed = false;
        long lProcessEndTime = 0;
        try {
            bScheduleExists = (pobjPrEb.getSchId() != 0);

            objEngineLogger_.log(LogLevel.NOTICE,
                    "Processing Stand Alone Request for request id " + pobjPrEb.getReqId());
            if (objEngineLogger_.isInfoEnabled()) {
                objEngineLogger_.info("Fetch parameters of request " + pobjPrEb.getReqId());
            }

            hmParams = fetchRequestParams(pcon, pobjPrEb.getReqId(), pobjDdcParams, pobjParamsCont, pobjParamsEb);

            // objEngineLogger_.info("Initialize Request Log File ....");
            //            
            // objRequestLogger_ = new PrintWriter(new CFileBufferedOutputStream
            // (new File(pstrLogFile.toString()),
            // iRequestLogFileMaxSize_,
            // REQUEST_LOG_BUFFER_SIZE, false), true);
            //            
            // objEngineLogger_.info("Instantiate the Process Class which has been requested .....");
            // objProcessRequest_ =
            // instantiateReqProcessObject(objRequestLogger_,
            // pobjPrEb.getProcessClassNm());

            if (objProcessRequest_ != null) {

                updateRequestStatus(pcon, pobjPrCont, pobjPrEb, REQUEST_STATUS.PROCESSING, pstrLogFileURL);

                objProcessRequest_.setDataSourceFactory(dataSourceFactory_);
                objProcessRequest_.setConnection(pcon);
                objProcessRequest_.setParams(hmParams);
                objProcessRequest_.setRequestId(pobjPrEb.getReqId());
                objProcessRequest_.setLogFile(logFileName);
                //            objProcessRequest_.setResponseWriter(objRequestLogger_);
                objProcessRequest_.setUserId(pobjPrEb.getUserId());
                objProcessRequest_.setSource(REQUEST_SOURCE.OFFLINE);

                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Execute method on object ....");
                }
                long lProcessStartTime = System.currentTimeMillis();
                if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                    objEngineLogger_.log(LogLevel.FINE, "{4}Elapsed Time before calling processRequest() method #"
                            + (lProcessStartTime - lStartTime) + " milliseconds");
                }
                boolean bJOBStatus = objProcessRequest_.processRequest();
                lProcessEndTime = System.currentTimeMillis();
                if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                    objEngineLogger_.log(LogLevel.FINE,
                            "{5}Elapsed Time taken by the JOB's underlying processRequest() to complete #"
                                    + (lProcessEndTime - lProcessStartTime) + " milliseconds");
                }
                if (bJOBStatus) {
                    updateRequestStatus(pcon, pobjPrCont, pobjPrEb, REQUEST_STATUS.COMPLETED, pstrLogFileURL);
                } else {
                    updateRequestStatus(pcon, pobjPrCont, pobjPrEb, REQUEST_STATUS.ERROR, pstrLogFileURL);
                    if (retryPossible)
                        toBeRetryed = true;
                }
            } // Process Class is instantiated
        } // try block
        catch (RuntimeException re) {
            if (retryPossible)
                toBeRetryed = true;
            //         objThrowable = re; // This line must be the first line in this
            // block.
            bSuccess = false;

            objEngineLogger_.fatal("RunTime Exception Caught..", re);
            //         re.printStackTrace(logFileName);
            try {
                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Update Request Status to Error due to Exception.");
                }
                updateRequestStatus(staticConnection_, pobjPrCont, pobjPrEb, REQUEST_STATUS.ERROR, pstrLogFileURL);

            } catch (Exception ex) {
                objEngineLogger_.error(ex);
                //            ex.printStackTrace(logFileName);
            }
        } catch (Exception e) {
            if (e instanceof CProcessRequestEngineException) {
                if (retryPossible)
                    toBeRetryed = true;
            }
            //         objThrowable = e; // This line must be the first line in this block.
            bSuccess = false;

            objEngineLogger_.log(LogLevel.NOTICE, "Exception Caught..");
            objEngineLogger_.error(e);
            //         e.printStackTrace(logFileName);
            try {
                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Update Request Status to Error due to Exception.");
                }
                updateRequestStatus(staticConnection_, pobjPrCont, pobjPrEb, REQUEST_STATUS.ERROR, pstrLogFileURL);

            } catch (Exception ex) {
                objEngineLogger_.error("Cound not update the request status to Error.", ex);
                //            ex.printStackTrace(logFileName);
            }
        } catch (ThreadDeath tderror) {
            toBeRetryed = false; // As this thread was killed there should not
            // be a retry option.
            //         objThrowable = tderror; // This line must be the first line in this
            // block.
            bSuccess = false;

            objEngineLogger_.fatal("Thread Has Been Terminated from the Web Service....Initiating cleanup...");
            try {
                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Update Request Status to Error due to Thread Termination.");
                }
                updateRequestStatus(staticConnection_, pobjPrCont, pobjPrEb, REQUEST_STATUS.KILLED, pstrLogFileURL);

            } catch (Exception ex) {
                objEngineLogger_.error("Unable to update due to ThreadDeath. ", ex);
            }
            throw tderror;
        } catch (Error error) {
            toBeRetryed = false;
            //         objThrowable = error; // This line must be the first line in this
            // block.
            bSuccess = false;

            objEngineLogger_.fatal("Error Encountered..", error);
            //         error.printStackTrace(logFileName);
            try {
                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Update Request Status to Error due to Exception.");
                }
                updateRequestStatus(staticConnection_, pobjPrCont, pobjPrEb, REQUEST_STATUS.ERROR, pstrLogFileURL);

            } catch (Exception ex) {
                objEngineLogger_.error("Caught Exception while updating the request status to Error.", ex);
                //            ex.printStackTrace(logFileName);
            }
            throw error;
        } finally {
            if (toBeRetryed) {
                try {
                    long newRequestId = proCreateRetry(pcon, pobjPrEb, pobjParamsEb, pobjDdcParams, pobjPrCont,
                            pobjParamsCont);
                    if (objEngineLogger_.isEnabledFor(LogLevel.NOTICE)) {
                        objEngineLogger_.log(LogLevel.NOTICE,
                                "The request will be retryed after " + pobjPrEb.getRetryTime() + " "
                                        + pobjPrEb.getRetryTimeUnit()
                                        + ((newRequestId != -1) ? ". New Request Id# " + newRequestId : ""));
                    }
                } catch (SQLException e) {
                    objEngineLogger_.error("Unable to retry the failed request due to SQLException", e);
                    toBeRetryed = false; // This way the
                    // sendScheduleUnExecutedMail may
                    // get called.
                } catch (ClassNotFoundException e) {
                    objEngineLogger_.error("Unable to retry the failed request due to ClassNotFoundException", e);
                    toBeRetryed = false; // This way the
                    // sendScheduleUnExecutedMail may
                    // get called.
                } catch (InstantiationException e) {
                    objEngineLogger_.error("Unable to retry the failed request due to InstantiationException", e);
                    toBeRetryed = false; // This way the
                    // sendScheduleUnExecutedMail may
                    // get called.
                } catch (IllegalAccessException e) {
                    objEngineLogger_.error("Unable to retry the failed request due to IllegalAccessException", e);
                    toBeRetryed = false; // This way the
                    // sendScheduleUnExecutedMail may
                    // get called.
                }
            }
            if (!toBeRetryed) {
                if (pobjPrEb.getSchId() != 0) {
                    REQUEST_TYPE type = null;
                    try {
                        type = REQUEST_TYPE.resolve(pobjPrEb.getGrpStInd());
                    } catch (IllegalArgumentException e) {
                        // this should never arise but still..
                        objEngineLogger_
                                .error("Unrecognized grouped/standalone indicator " + pobjPrEb.getGrpStInd());
                    }
                    if (type == REQUEST_TYPE.STANDALONE) {
                        try {
                            if (objEngineLogger_.isDebugEnabled()) {
                                objEngineLogger_.debug("Initializing Scheduler.");
                            }
                            CRequestScheduler crs = new CRequestScheduler(pobjPrEb.getSchId(), pobjPrEb, hmParams,
                                    paramSimpleDateFormat_, paramSimpleTimeFormat_, paramSimpleDateTimeFormat_,
                                    context_);
                            if (objEngineLogger_.isDebugEnabled()) {
                                objEngineLogger_.debug("Scheduler Initialized.");
                            }
                            crs.setConnection(pcon);
                            if (objEngineLogger_.isDebugEnabled()) {
                                objEngineLogger_.debug("Trying to Schedule....");
                            }
                            long lScheduleStartTime = System.currentTimeMillis();
                            if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                                objEngineLogger_.log(LogLevel.FINE,
                                        "{6}Elapsed Time taken to initialize the JOB's associated schedule #"
                                                + (lScheduleStartTime - lProcessEndTime) + " milliseconds");
                            }
                            crs.schedule();
                            long lScheduleEndTime = System.currentTimeMillis();
                            if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                                objEngineLogger_.log(LogLevel.FINE,
                                        "{7}Elapsed Time taken to complete the JOB's associated schedule #"
                                                + (lScheduleEndTime - lScheduleStartTime) + " milliseconds");
                            }
                            bScheduleExecuted = true;
                        } finally {
                            //TODO something
                        }
                    } // Request is a STANDALONE Request
                } // Schedule Id is not null
            }
            try {
                if (objProcessRequest_ != null) {
                    objEngineLogger_.log(LogLevel.NOTICE, "Request Processed for request id " + pobjPrEb.getReqId()
                            + " ...Initiating Clean Up Process..");
                    objProcessRequest_.endProcess();
                    objEngineLogger_.log(LogLevel.NOTICE,
                            "Cleanup Process executed for request id " + pobjPrEb.getReqId());
                }
            } catch (Throwable e) {
                objEngineLogger_.error("Caught Exception while updating the request status to Error.", e);
                // rare to get an exception. But if it comes then just log it.
            } finally {
                if (objProcessRequest_ != null) {
                    objProcessRequest_.close();
                }
            }

            // This has to be done because the user will never know if the
            // schedule
            // was not executed due to any exceptions.
            // The process_request table must be altered to have specific email
            // ids
            // associated for that request for mailing purpose from PRE. This
            // change
            // however is not made as of now but should be done in near future.
            // Kedar...30.06.2004....Atlanta US.
            if (bScheduleExists && pobjPrEb.getGrpStInd().equals(REQUEST_TYPE.STANDALONE.getID())
                    && !bScheduleExecuted && !toBeRetryed) {
                objEngineLogger_.log(LogLevel.NOTICE, "Associated schedule #" + pobjPrEb.getSchId()
                        + " could not be executed for the Request #" + pobjPrEb.getReqId());
                // String strEmailIds = ""; // Do not initialize it to null.
                try {
                    updateSchedule(SCHEDULE_STATUS.TERMINATED, pcon, pobjPrEb.getSchId());
                } catch (Exception e) {
                    //               objThrowable = e;
                    // This is relevent only if there is no primary error
                    // encountered. Otherwise,
                    // the main error will be hidden.
                }
                //            if (CSettings.get("pr.mailnotification", "OFF").equals("ON")) {
                //               sendScheduleUnExecutedMail(pobjPrEb.getReqId(), pobjPrEb
                //                     .getSchId(), pobjPrEb.getJobId(), pobjPrEb
                //                     .getJobName(), objThrowable, pobjPrEb.getEmailIds());
                //            } // CSettings.get("pr.mailnotification", "OFF").equals("ON")
            } // bScheduleExists && !bScheduleExecuted

            // if (objRequestLogger_ != null) {
            // objRequestLogger_.close();
            // }
            if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                objEngineLogger_.log(LogLevel.FINE, "{8}Elapsed Time for job execution #"
                        + (System.currentTimeMillis() - lStartTime) + " milliseconds");
            }
        }

        return bSuccess;
    } // end of processEachRequest

    /**
     * Returns the parameters associated with the request in a hashtable. </p>
     * <p>
     * However before the parameters are populated they are converted into the
     * datatype mentioned in the Param_Data_Type
     * 
     * <ul>
     * <li>
     * In case the data type for the field is mentioned as Date, then Param_Val
     * field should have a string value in the format as mentioned in the
     * paramdateformat property of pr.properties</li>
     * <li>
     * In case the data type for the field is mentioned as Timestamp, then
     * Param_Val field should have a string value with the date part, in the
     * format as mentioned in the paramdateformat property of pr.properties, and
     * with the time part in the format as mentioned in the paramtimeformat
     * property of pr.properties</li>
     * <li>
     * In case the data type for the field is some type of array, then Param_Val
     * field should have a string value with all the elements of array delimited
     * by a delimiter as mentioned in the paramarrvaluedelim property of
     * pr.properties</li>
     * </ul>
     * </p>
     * 
     * @param pcon
     *            Connection object
     * @param plReqId
     *            Request Id of the request for which the parameters are to be
     *            fetched
     * @param pobjDdcParams
     *            DataContainer object reference for querying table
     *            PROCESS_REQ_PARAMS
     * @param pobjParamsCont
     *            Controller object reference for table PROCESS_REQ_PARAMS
     * @param pobjParamsEb
     *            EntityBean object reference for table PROCESS_REQ_PARAMS
     * @return HashMap object that contains all the parameters after conversion
     *         to corresponding data type
     * @throws Exception
     * 
     */
    private HashMap<String, Object> fetchRequestParams(Connection pcon, long plReqId,
            CDynamicDataContainer pobjDdcParams, ProcessReqParamsController pobjParamsCont,
            ProcessReqParamsEntityBean pobjParamsEb) throws Exception {

        HashMap<String, Object> hmParams = null;
        Object objValue = null;

        try {

            pobjParamsEb.initialize();
            pobjParamsEb.setReqId(plReqId);
            pobjDdcParams.build(pcon, pobjParamsEb);
            pobjDdcParams.addOrderByClause("ORDER BY param_no ASC");

            if (objEngineLogger_.isDebugEnabled()) {
                objEngineLogger_.debug("Querying for parameters for this request ....");
            }
            pobjDdcParams.executeQuery(pcon, pobjParamsCont, pobjParamsEb);

            if (pobjDdcParams.getTotalRows() > 0) {
                if (objEngineLogger_.isDebugEnabled()) {
                    objEngineLogger_
                            .debug(pobjDdcParams.getTotalRows() + " parameters defined for this request ....");
                }
                hmParams = new LinkedHashMap<String, Object>();

                while (pobjDdcParams.next()) {
                    pobjParamsEb = (ProcessReqParamsEntityBean) pobjDdcParams.get();
                    objValue = convertToReqDataType(pobjParamsEb.getParamVal(), pobjParamsEb.getParamDataType());
                    hmParams.put(pobjParamsEb.getParamFld(), objValue);
                }
            } else {
                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("No parameters defined for this request ....");
                }
            }

        } catch (CProcessRequestEngineException cpree) {
            throw cpree;
        } catch (Exception e) {
            objEngineLogger_.error("Caught exception while fetching parameters.", e);
            throw e;
        } finally {
        }

        return hmParams;
    } // end of fetchRequestParams

    /**
     * Instantiate an object of the class, mentioned in the process_class_nm
     * field of the PROCESS_REQUEST table.
     * 
     * This class is loaded using a custom classloader that loads the latest
     * version of the class file from disk. The new object is then cast to
     * IProcessRequest. If the cast fails an appropriate exception is logged in
     * the Engine and Request Log
     * 
     * @param pstrClassName
     *            Class name to be instantiated.
     * @return An object reference to IProcessRequest interface
     * @throws LinkageError
     * @throws CProcessRequestEngineException
     *             when instantiation or casting fails
     * 
     */
    private ProcessRequestServicer instantiateReqProcessObject(String pstrClassName)
            throws LinkageError, CProcessRequestEngineException {

        ProcessRequestServicer objProcessRequest = null;

        try {

            long lLoadingClassStartTime = System.currentTimeMillis();
            ClassLoader pcl = (CCustomClassLoaderFactory.getInstance()).getClassLoader(this);

            if (objEngineLogger_.isDebugEnabled()) {
                objEngineLogger_.debug("Loading PRE class " + pstrClassName);
            }

            Class<?> objClass = pcl.loadClass(pstrClassName);
            long lLoadingClassEndTime = System.currentTimeMillis();
            if (objEngineLogger_.isEnabledFor(LogLevel.FINER)) {
                objEngineLogger_.log(LogLevel.FINER, "Loaded PRE " + objClass);
            }
            if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                objEngineLogger_.log(LogLevel.FINE, "{2}Elapsed Time to Load Class " + objClass + " #"
                        + (lLoadingClassEndTime - lLoadingClassStartTime));
            }
            Object obj = objClass.newInstance();
            if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                objEngineLogger_.log(LogLevel.FINE, "{3}Elapsed Time to instantiate Class " + objClass + " #"
                        + (System.currentTimeMillis() - lLoadingClassEndTime));
            }

            if (obj instanceof ProcessRequestServicer) {
                objProcessRequest = (ProcessRequestServicer) obj;
            } else {
                throw new CProcessRequestEngineException(
                        "The business object in the request does not implement IProcessRequest");
            }

        } catch (LinkageError le) {
            objEngineLogger_.error(le.getMessage(), le);
            throw le;
        } catch (Exception e) {
            objEngineLogger_.error(e.getMessage(), e);
            throw new CProcessRequestEngineException(e.getMessage());
        } finally {

        }

        return objProcessRequest;
    } // end of instantiateReqProcessObject

    /**
     * Converts String value passed as the first parameter into the data type as
     * specified by the second parameter
     * 
     * 
     * @param pstrValue
     *            String value that has to be converted
     * @param pstrReqDataType
     *            Data Type to which the string value has to be converted
     * @return converted object
     * @throws CProcessRequestEngineException
     *             when conversion fails
     * 
     */
    private Object convertToReqDataType(String pstrValue, String pstrReqDataType)
            throws CProcessRequestEngineException {
        try {
            if (pstrValue == null || pstrValue.equals("")) {
                return null;
            }
            PREDataType type = PREDataType.resolve(pstrReqDataType);
            if (type == null) {
                throw new CProcessRequestEngineException(
                        "Unknown Data Type associated with the parameter. Unable to convert.");
            }
            switch (type) {
            case BOOLEAN:
                return "true".equalsIgnoreCase(pstrValue);
            case INTEGER:
                return new Integer(pstrValue);
            case LONG:
                return new Long(pstrValue);
            case DOUBLE:
                return new Double(pstrValue);
            case DATE:
                return paramSimpleDateFormat_.parse(pstrValue);
            case TIMESTAMP:
                return new Timestamp(paramSimpleDateTimeFormat_.parse(pstrValue).getTime());
            //            return CDate
            //                  .getUDFTimestamp(pstrValue, strParamDateTimeFormat_);
            case STRING:
                return pstrValue;
            default:
                return convertStringToObjectArray(pstrValue, type, strParamArrValueDelim_);
            }
        } catch (CProcessRequestEngineException cpree) {
            throw cpree;
        } catch (Exception e) {
            throw new CProcessRequestEngineException(exceptionToString(e));
        }

    } // end of convertToReqDataType

    /**
     * Converts delimited string into the appropriate type of array as specified
     * 
     * 
     * @param pstrInput
     *            Delimited string that has to be converted to an appropriate
     *            type of array
     * @param pDataType
     *            Data type of the array
     * @param pstrArrDelim
     *            Delimiter used by pstrInput parameter to delimit elements
     * @return Object array with elements converted into an appropriate type as
     *         specified in pstrDataType
     * @throws Exception
     *             When conversion fails
     * 
     */
    private Object[] convertStringToObjectArray(String pstrInput, PREDataType pDataType, String pstrArrDelim)
            throws Exception {

        Object[] objRetValArr = null;
        int iElements = 0;

        StringTokenizer stzStr = new StringTokenizer(pstrInput, pstrArrDelim);
        switch (pDataType) {
        case BOOLEAN_ARRAY:
            objRetValArr = new Boolean[stzStr.countTokens()];
            while (stzStr.hasMoreTokens()) {
                objRetValArr[iElements] = "true".equalsIgnoreCase(stzStr.nextToken());
                iElements++;
            }
            break;
        case STRING_ARRAY:
            objRetValArr = new String[stzStr.countTokens()];
            while (stzStr.hasMoreTokens()) {
                objRetValArr[iElements] = stzStr.nextToken();
                iElements++;
            }
            break;
        case INTEGER_ARRAY:
            objRetValArr = new Integer[stzStr.countTokens()];
            while (stzStr.hasMoreTokens()) {
                objRetValArr[iElements] = Integer.valueOf(stzStr.nextToken());
                iElements++;
            }
            break;
        case LONG_ARRAY:
            objRetValArr = new Long[stzStr.countTokens()];
            while (stzStr.hasMoreTokens()) {
                objRetValArr[iElements] = Long.valueOf(stzStr.nextToken());
                iElements++;
            }
            break;
        case DOUBLE_ARRAY:
            objRetValArr = new Double[stzStr.countTokens()];
            while (stzStr.hasMoreTokens()) {
                objRetValArr[iElements] = Double.valueOf(stzStr.nextToken());
                iElements++;
            }
            break;
        case DATE_ARRAY:
            objRetValArr = new java.sql.Date[stzStr.countTokens()];
            while (stzStr.hasMoreTokens()) {
                objRetValArr[iElements] = paramSimpleDateFormat_.parse(stzStr.nextToken());
                iElements++;
            }
            break;
        default: // timestamp
            objRetValArr = new java.sql.Timestamp[stzStr.countTokens()];
            while (stzStr.hasMoreTokens()) {
                objRetValArr[iElements] = new java.sql.Timestamp(
                        paramSimpleDateTimeFormat_.parse(stzStr.nextToken()).getTime());
                iElements++;
            }
            break;
        }
        return objRetValArr;
    } // convertStringToObjectArray

    /**
     * Updates req_stat field and other appropriate fields in PROCESS_REQUEST
     * table depending on the preqStat parameter passed
     * 
     * @param pcon
     *            Connection object
     * @param pobjPrCont
     *            Controller object reference for table PROCESS_REQUEST
     * @param pobjPrEb
     *            EntityBean object reference for table PROCESS_REQUEST
     * @param preqStat
     *            status value that is to be updated
     * @param preqLogFileUrl
     *            Request Log File Url to be updated, only if status is Success
     *            / Error
     * @throws Exception
     */
    // Whether synchronized must be there or not Should be debated.
    private synchronized void updateRequestStatus(Connection pcon, ProcessRequestController pobjPrCont,
            ProcessRequestEntityBean pobjPrEb, // this variable is not being
            // used...Kedar...30/01/2004
            REQUEST_STATUS preqStat, String preqLogFileUrl) throws Exception {
        ProcessRequestController objPRController = null;
        try {
            RequestStatusVO vo = new RequestStatusVO();
            vo.setReqId(pobjPrEb.getReqId());
            if (objEngineLogger_.isDebugEnabled()) {
                objEngineLogger_.debug("Begin Transaction ...");
            }
            pcon.setAutoCommit(false);

            if (objEngineLogger_.isDebugEnabled()) {
                objEngineLogger_.debug("Update request table with status as '" + preqStat + "' ....");
            }
            if (preqStat == REQUEST_STATUS.LAUNCHING) {

                pobjPrEb.setReqStartDt(getCurrentTimestamp(pcon));
                vo.setStatus(preqStat.getID());
                context_.addOrUpdate(vo);

            } else if (preqStat == REQUEST_STATUS.COMPLETED || preqStat == REQUEST_STATUS.ERROR) {
                pobjPrEb.setReqEndDt(getCurrentTimestamp(pcon));
                pobjPrEb.setReqLogfileNm(preqLogFileUrl);
                pobjPrEb.setVerboseTimeElapsed(
                        stg.utils.Day.verboseTimeDifference(pobjPrEb.getReqEndDt(), pobjPrEb.getReqStartDt()));
                context_.remove(vo);
            } else {
                vo.setStatus(preqStat.getID());
                context_.addOrUpdate(vo);
            }

            pobjPrEb.setReqStat(preqStat.getID());
            pobjPrEb.setRStatus(false);

            objPRController = new ProcessRequestController(pcon);
            // if (!pobjPrCont.update(pobjPrEb)) {
            // throw new
            // Exception("Updation of request processing status failed ....");
            // }
            if (!objPRController.update(pobjPrEb)) {
                throw new Exception("Updation of request processing status failed ....");
            }

            if (objEngineLogger_.isDebugEnabled()) {
                objEngineLogger_.debug("Commit Transaction ...");
            }
            pcon.commit();

        } catch (Exception e) {

            try {
                objEngineLogger_.error("Rollback Transaction ...", e);
                pcon.rollback();
            } catch (Exception ex) {
                throw ex;
            }

            throw e;
        } finally {
            if (objPRController != null) {
                objPRController.close();
            }
            try {
                if (objEngineLogger_.isDebugEnabled()) {
                    objEngineLogger_.debug("Setting AutoCommit to true ...");
                }
                pcon.setAutoCommit(true);
            } catch (SQLException sqe) {
                throw sqe;
            }
        }

    }

    /**
     * Empties the Connection pool and closes the engine log file
     */
    private void closeAll() {
        objEngineLogger_.log(LogLevel.NOTICE, "Initiating Clean Shutdown");

        if (lStuckThreadMonitorInterval_ > 0) {
            objEngineLogger_.log(LogLevel.NOTICE, "Stopping Monitor Thread");
            if (tMonitorThread_.isAlive()) {
                tMonitorThread_.interrupt();
            } else {
                objEngineLogger_.log(LogLevel.NOTICE, "Monitor Thread already stopped.");
            }
        }
        while (!(vectorThreads_.isEmpty() && vectorThreadsGroup_.isEmpty())) // bGroupedEngineTerminationConfirmed_))
        {
            objEngineLogger_.log(LogLevel.NOTICE, "Waiting while the Current processes are finished....");
            if (objEngineLogger_.isInfoEnabled()) {
                objEngineLogger_.info("Total Standalone Processes running " + vectorThreads_.size());
                objEngineLogger_.info("Total Grouped    Processes running " + vectorThreadsGroup_.size());
                objEngineLogger_.info("Shutdown Hook Sleeping for 10 minutes...");
            }
            try {
                if (tInterrupt_ != null) {
                    Thread.yield();
                    TimeUnit.MINUTES.sleep(10);
                    // Thread.sleep(600000l);
                    // The following two lines are commented as suggested by
                    // Eclipse editor. Instead of these
                    // two lines the above two lines are used. We should get the
                    // same results....Kedar..23/09/2003
                    // tInterrupt_.yield();
                    // tInterrupt_.sleep(600000l);
                }
            } catch (InterruptedException ie) {
                // dummy exception. do nothing. The Running process will
                // interrupt this thread.
            }
        }
        if (tMonitorThread_ != null) {
            tMonitorThread_.interrupt();
            while (tMonitorThread_.isAlive()) {
            }
        }

        // if (objEngineLogger_.isInfoEnabled()) {
        // objEngineLogger_.info("Closing PreparedStatements ...");
        // }
        // if (objPrCont_ != null) {
        // objPrCont_.close();
        // }

        try {
            if (dataSourceFactory_ != null) {
                try {
                    if (staticConnection_ != null) {
                        staticConnection_.close();
                    }
                } catch (SQLException e) {
                    // No need to throw exception.
                }
                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Emptying Data Sources ....");
                }
                if (dataSourceFactory_.shutdown()) {
                    objEngineLogger_.info("All Data Source emptied successfully.");
                }
            }

        } catch (Exception e) {
            objEngineLogger_.error(e);
            // No need to throw exception. PRE is closing down.
        }

        // if (objEngineLogger_ != null) {
        // objEngineLogger_.info("Closing System Log ....");
        // objEngineLogger_.close();
        // }
        // if (httpserver_.isStarted())
        // {
        // if (objEngineLogger_.isInfoEnabled()) {
        // objEngineLogger_.info("Stoping Web Service");
        // }
        // httpserver_.stop();
        // }
        stopWebServer();
        if (!Thread.currentThread().getName().equals("shutdown")) {
            if (Hazelcast.getCluster().getMembers().size() == 1) {
                printPossibleMemoryLeaks();
            }
        }
        Iterator<Service> iter = services_.values().iterator();
        while (iter.hasNext()) {
            Service instance = iter.next();
            instance.destroy(context_);
            iter.remove();
        }
        //      if (reportService != null) {
        //         reportService.shutdown();
        //         if (objEngineLogger_.isInfoEnabled()) {
        //            objEngineLogger_
        //                  .info("Waiting for the current reports, if any, to finish.");
        //         }
        //         while (!reportService.isTerminated()) {
        //            try {
        //               TimeUnit.SECONDS.sleep(20);
        //            } catch (InterruptedException e) {
        //               e.printStackTrace();
        //            }
        //            if (objEngineLogger_.isInfoEnabled()) {
        //               objEngineLogger_.info("Waiting for Active("
        //                     + reportService.getCurrentActiveCount()
        //                     + ") and Pending("
        //                     + reportService.getCurrentPendingQueueSize()
        //                     + ") reports to be completed.");
        //            }
        //         }
        //      }
        if (objEngineLogger_.isInfoEnabled()) {
            objEngineLogger_.info("Engine Termination Confirmed....");
        }

        // bEngineTerminationConfirmed_ = true;
    }

    /**
     * This method is called when the engine is terminated
     * 
     * This method is called from the thread, that is attached to the shutdown
     * hook,when CTRL-C is pressed. The moment this method is called
     * bEngineTerminated_ is set to true and this method waits until the main
     * thread sets the bEngineTerminationConfirmed_ to true. Once
     * bEngineTerminationConfirmed_ is set to true, closeAll() method is called
     * which releases all resources
     * 
     */
    private void terminateEngine() {
        // a good practice.
        if (tMain_ != null) {
            objEngineLogger_.log(LogLevel.NOTICE, "Interrupting main engine thread ...");
            //         try {
            //            LicenseVerifier.verify(readLicense());
            //         } catch (Exception e) {
            //            if (stopMessageForEmail_ != null
            //                  || !"".equals(stopMessageForEmail_)) {
            //               stopMessageForEmail_ = stopMessageForEmail_
            //                     + "\n\nLicense has expired. Please contact the help desk and get it re-issued.\n";
            //            } else {
            //               stopMessageForEmail_ = "\n\nLicense has expired. Please contact the help desk and get it re-issued.\n";
            //            }
            //         }
            if (stopMessageForEmail_ == null) {
                stopMessageForEmail_ = "Engine is being stopped due to JVM is being terminated. "
                        + "Such a situation may arise by pressing ctrl+c.";
            }
            // int iRebootCnt = (iRebootCounter < 0)?0:iRebootCounter;
            StringBuffer sbuffer = getDefaultEmailAttributes();
            sbuffer.append("Stopped On      :");
            sbuffer.append(new Date());
            sbuffer.append(NEW_LINE);
            sbuffer.append(NEW_LINE);
            sbuffer.append("Engine is being terminated due to ");
            sbuffer.append(NEW_LINE);
            sbuffer.append(NEW_LINE);
            sbuffer.append(stopMessageForEmail_);
            if (isReboot() && getRebootCounter() >= getRebootMaxCounter()) { // This
                // condition
                // is
                // because
                // the
                // controller
                // will
                setReboot(false); // update the counter by 1 and then it will
                // not
            } // initiate a reboot.
            if (isReboot()) {
                createIniFile(CStartEngine.REBOOT, getRebootCounter());
                sbuffer.append(NEW_LINE);
                sbuffer.append(NEW_LINE);
                sbuffer.append("Engine will attempt a Reboot. Please do not try to start the engine manually. ");
                sbuffer.append("Engine will wait for ");
                // if ((double)lRebootSleepTime / 60000 < 1) {
                // sbuffer.append("#" + lRebootSleepTime +
                // " milliseconds before attempting restart.");
                // } else {
                sbuffer.append("#" + getRebootSleepTime() + " minute(s) before attempting restart.");
                // }
                // sbuffer.append(NEW_LINE);
                // sbuffer.append(NEW_LINE);
                // sbuffer.append("Attempt #");
                // sbuffer.append(iRebootCounter);
            } else {
                sbuffer.append(NEW_LINE);
                sbuffer.append(NEW_LINE);
                sbuffer.append("Contact help desk !!");
            }
            sendDefaultMail(
                    "Engine is being terminated." + ((isReboot()) ? " Engine will attempt Reboot sequence." : ""),
                    sbuffer.toString(), false);
            tMain_.interrupt();
            if (bGroupEngineToBeStarted_) {
                tEngine_.interrupt();
            }
            bEngineTerminated_.set(true);
            bGroupedEngineTerminated_.set(true);
            // waiting for the engine thread to complete its activity and
            // confirm
            closeAll();
            // while (!bEngineTerminationConfirmed_) {
            // try {
            // objEngineLogger_.debug("Waiting for all the other processes are terminated.");
            // this.wait();
            // } catch (InterruptedException e) {
            // objEngineLogger_.debug("Interrupted. Check if engine termination is confirmed.");
            // //do nothing.
            // }
            // }
            if (tInterrupt_ != Thread.currentThread()) {
                Runtime.getRuntime().removeShutdownHook(tInterrupt_);
            }

            // if (objEngineLogger_.isDebugEnabled()) {
            // objEngineLogger_.debug("Waiting for " +
            // CMailer.getCurrentlyRunningAsychMailThreadCount() +
            // " Asynchronous email(s) to be transported..");
            // }
            // while (CMailer.getCurrentlyRunningAsychMailThreadCount() > 0) {
            // //wait..do nothing This being a daemon thread will kill the non
            // daemon threads.
            // }
            // if (objEngineLogger_.isDebugEnabled()) {
            // objEngineLogger_.debug("Transported all Asynchronous Emails....");
            // }
            CSettings.getInstance().destroy();
            // CConnectionPoolManager.getInstance().destroy(true);
            // instance_ = null;
            // tMain_ = null;
            Iterator<Service> iter = services_.values().iterator();
            while (iter.hasNext()) {
                Service instance = iter.next();
                instance.destroy(context_);
                iter.remove();
            }
            //         if (reportService != null) {
            //            reportService.shutdown();
            //            while (!reportService.isTerminated()) {
            //               try {
            //                  TimeUnit.SECONDS.sleep(5);
            //                  if (objEngineLogger_.isInfoEnabled()) {
            //                     objEngineLogger_.info("Waiting for the BIRT Report service to terminate. Current pending report count #" + 
            //                           reportService.getCurrentActiveCount() + reportService.getCurrentPendingQueueSize());
            //                  }
            //               } catch (InterruptedException e) {
            //                  //
            //               }
            //            }
            //            try {
            //               reportService.destroy();
            //            } catch (Exception e) {
            //               e.printStackTrace();
            //            }
            //         }
            objEngineLogger_.log(LogLevel.NOTICE, "Engine Terminated.");
        } else {
            // objEngineLogger_.error("Engine thread null ...");
        }
    }

    /**
     * This inner class extends Thread and executes different StandAlone
     * requests.
     * 
     */
    class ThreadProcess extends Thread implements IJOBMonitor {
        /**
         * Stores the REVISION number of the class from the configuration
         * management tool.
         */
        public final String REVISION = "$Revision:: 3829              $";

        //      private PrintWriter objRequestLogger_;
        private ProcessRequestServicer objProcessRequest_;
        private Connection con_;
        private ProcessRequestController objPrCont_;
        private ProcessRequestEntityBean objPrEb_;
        private CDynamicDataContainer objDdcParams_;
        private ProcessReqParamsController objParamsCont_;
        private ProcessReqParamsEntityBean objParamsEb_;
        private String strLogFileName;
        private String strLogFileNameURL;
        // private IDataSourceFactory dataSourceFact_;

        private long lStartTimeInMillis_ = -1;

        private JOB_STATUS jobStatus_ = JOB_STATUS.NORMAL;

        private long jobCheckedAtTime_;

        private long lActualInitializedTimeInMillis_;

        private long lProcessEndTime_;

        private boolean failedOver;

        public ThreadProcess() {
            super();
            lActualInitializedTimeInMillis_ = System.currentTimeMillis();
        }

        public ThreadProcess(String name) {
            super(name);
            lActualInitializedTimeInMillis_ = System.currentTimeMillis();
        }

        public ProcessRequestServicer getIntantiatedObject() {
            return objProcessRequest_;
        }

        public void setConnection(Connection pcon) {
            con_ = pcon;
        }

        public void setProcessRequestEntityBean(ProcessRequestEntityBean pobjPREB) {
            objPrEb_ = pobjPREB;
        }

        public void setLogFileName(String pstrFileName) {
            strLogFileName = pstrFileName;
        }

        public void setLogFileNameURL(String pstrLogFileNameURL) {
            strLogFileNameURL = pstrLogFileNameURL;
        }

        public void setFailedOver(boolean failOver) {
            this.failedOver = failOver;
        }

        public void setPool(IDataSourceFactory dataSourceFactory_) {
            // dataSourceFact_ = dataSourceFactory_;
        }

        public void run() {
            lStartTimeInMillis_ = lProcessEndTime_ = System.currentTimeMillis(); // just
            // initializing
            // the
            // process
            // end
            // time
            if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                objEngineLogger_.log(LogLevel.FINE, "{1} Thread Wait Time #"
                        + (lStartTimeInMillis_ - lActualInitializedTimeInMillis_) + " milliseconds...");
            }
            boolean bScheduleExists = false;
            boolean bErrorBeforeCallingProcessRequest = true; // default will be
            // true.
            Throwable objThrowable = new Throwable();
            try {
                if (objPrEb_.getSchId() > 0) {
                    bScheduleExists = true;
                }
                con_ = dataSourceFactory_.getDataSource(CSettings.get("pr.dsforstandaloneeng")).getConnection();
                objPrCont_ = new ProcessRequestController(con_);
                objParamsCont_ = new ProcessReqParamsController(con_);
                objParamsEb_ = new ProcessReqParamsEntityBean();
                objDdcParams_ = new CDynamicDataContainer();

                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Initialize Request Log File ....");
                }

                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Instantiate the Process Class which has been requested .....");
                }
                objProcessRequest_ = instantiateReqProcessObject(objPrEb_.getProcessClassNm());
                objProcessRequest_.setFailedOver(failedOver);

                // If this boolean variable "bErrorBeforeCallingProcessRequest"
                // is true in finally block then it means
                // that the call to the method processEachRequest has not gone
                // thus the schedule is not done.
                // So send MAIL.
                bErrorBeforeCallingProcessRequest = false;
                processEachRequest(con_, objPrCont_, objPrEb_, objDdcParams_, objParamsCont_, objParamsEb_,
                        objProcessRequest_, new File(strLogFileName), strLogFileNameURL);
                lProcessEndTime_ = System.currentTimeMillis();
                // }
                // catch (InterruptedException ie)
                // {
                // objThrowable = ie;
                // try {
                // if (objEngineLogger_.isInfoEnabled()) {
                // objEngineLogger_.info("Update Request Status to Error due to Exception.");
                // }
                // updateRequestStatus(staticConnection_, objPrCont_, objPrEb_,
                // IProcessRequest.ERROR_STATUS, strLogFileNameURL);
                // } catch (Exception ex) {
                // objEngineLogger_.error(ex);
                // }
                // objEngineLogger_.log(LogLevel.NOTICE,
                // "Thread Process is being Killed. Initiating clean shutdown of the process. Request Id #"
                // + objPrEb_.getReqId(), ie);
                // }
                // catch (Exception e)
                // {
                // objThrowable = e;
                // try {
                // if (objEngineLogger_.isInfoEnabled()) {
                // objEngineLogger_.info("Update Request Status to Error due to Exception.");
                // }
                // updateRequestStatus(staticConnection_, objPrCont_, objPrEb_,
                // IProcessRequest.ERROR_STATUS, strLogFileNameURL);
                // } catch (Exception ex) {
                // objEngineLogger_.error(ex);
                // }
                // throw new IllegalArgumentException(e.getMessage());
                // }
                // catch (Error error)
                // {
                // objThrowable = error;
                // try {
                // if (objEngineLogger_.isInfoEnabled()) {
                // objEngineLogger_.info("Update Request Status to Error due to Exception.");
                // }
                // updateRequestStatus(staticConnection_, objPrCont_, objPrEb_,
                // IProcessRequest.ERROR_STATUS, strLogFileNameURL);
                // } catch (Exception ex) {
                // objEngineLogger_.error(ex);
                // }
                // throw new IllegalArgumentException(error.getMessage());
            } catch (Throwable throwable) {
                lProcessEndTime_ = System.currentTimeMillis();
                objThrowable = throwable;
                try {
                    if (objEngineLogger_.isInfoEnabled()) {
                        objEngineLogger_.info("Update Request Status to Error due to Exception.");
                    }
                    if (throwable instanceof ThreadDeath) {
                        updateRequestStatus(staticConnection_, objPrCont_, objPrEb_, REQUEST_STATUS.KILLED,
                                strLogFileNameURL);
                    } else {
                        updateRequestStatus(staticConnection_, objPrCont_, objPrEb_, REQUEST_STATUS.ERROR,
                                strLogFileNameURL);
                    }
                } catch (Exception ex) {
                    objEngineLogger_.error("Unable to update request status to Error", ex);
                }
                if (throwable instanceof RuntimeException) {
                    throw (RuntimeException) throwable;
                } else if (throwable instanceof Error) {
                    throw (Error) throwable;
                }
                throw new IllegalArgumentException(throwable.getMessage(), throwable);
            } finally {
                if (objParamsCont_ != null) {
                    try {
                        objParamsCont_.close();
                    } catch (SQLException e) {
                        objEngineLogger_.error("Exception caught while closing PRPController", e);
                    }
                }

                if (objPrCont_ != null) {
                    try {
                        objPrCont_.close();
                    } catch (SQLException e) {
                        objEngineLogger_.error("Exception caught while closing PRController", e);
                    }
                }
                objProcessRequest_ = null;
                // This has to be done because the user will never know if the
                // schedule
                // was not executed due to any exceptions.
                // The process_request table must be altered to have specific
                // email ids
                // associated for that request for mailing purpose from PRE.
                // This change
                // however is not made as of now but should be done in near
                // future.
                // Kedar...01.07.2004....Atlanta US.
                if (bScheduleExists && bErrorBeforeCallingProcessRequest) {
                    objEngineLogger_.log(LogLevel.NOTICE, "Associated schedule #" + objPrEb_.getSchId()
                            + " could not be executed for the Request #" + objPrEb_.getReqId());
                    try {
                        updateSchedule(SCHEDULE_STATUS.TERMINATED, con_, objPrEb_.getSchId());
                    } catch (Exception e) {
                        // This exception is already logged so no need to be
                        // logged.
                        if (objThrowable != null) {
                            objThrowable = e; // This is relevent only if there
                            // is no primary error
                            // encountered. Otherwise,
                            // the main error will be hidden.
                        }
                    }
                    if (CSettings.get("pr.mailnotification", "OFF").equals("ON")) {
                        sendScheduleUnExecutedMail(objPrEb_.getReqId(), objPrEb_.getSchId(), objPrEb_.getJobId(),
                                objPrEb_.getJobName(), objThrowable, objPrEb_.getEmailIds());
                    } // CSettings.get("pr.mailnotification",
                      // "OFF").equals("ON")
                } // bScheduleExists && !bScheduleExecuted
                try {
                    con_.close();
                } catch (SQLException e1) {
                    // No need to throw exception.
                }
                if (jobStatus_ == JOB_STATUS.STUCK && iStuckThreads_.get() > 0) {
                    // This variable is reduced by -1 as the stuck thread has
                    // finished its job.
                    iStuckThreads_.decrementAndGet();
                } else if ((jobStatus_ == JOB_STATUS.CRITICAL || jobStatus_ == JOB_STATUS.TOBETERMINATED)
                        && iStuckThreadThatCrossMaxLimit_.get() > 0) {
                    // This variable is reduced by -1 as the stuck thread has
                    // finished its job.
                    iStuckThreadThatCrossMaxLimit_.decrementAndGet();
                }

                // nullifying the variables.
                objPrCont_ = null;
                objPrEb_ = null;
                objDdcParams_ = null;
                objParamsCont_ = null;
                objParamsEb_ = null;
                strLogFileName = null;
                strLogFileNameURL = null;
                removeStandAloneProcess(this);
                if (vectorThreads_.size() == 0 && bEngineTerminated_.get()) {
                    // try {
                    // if (pool_ != null) {
                    // // pool_.stopShrinking();
                    // pool_.emptyPool(CSettings.get("pr.dsforstandaloneeng"));
                    // }
                    //                        
                    // } catch (Exception e) {
                    // objEngineLogger_.error(e);
                    // }
                    if (objEngineLogger_.isDebugEnabled()) {
                        objEngineLogger_.debug("StandAlone: Iterrupting Shutdown Hook...");
                    }
                    if (tInterrupt_ != null) {
                        // Earlier this thread if not null was then Alive as
                        // well. But because of Reboot sequence
                        // This thread can be not null but not alive and
                        // therfore this condition is added.
                        if (tInterrupt_.isAlive()) {
                            tInterrupt_.interrupt();
                        } else {
                            tMain_.interrupt();
                        }
                    } else {
                        tMain_.interrupt();
                    }
                    if (lStuckThreadMonitorInterval_ > 0) {
                        tMonitorThread_.interrupt();
                    }
                } // vectorThreads_.size() == 0 && bEngineTerminated_
                if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                    long lTime = System.currentTimeMillis();
                    objEngineLogger_.log(LogLevel.FINE, "{9}Clean-up Time delay for the Thread #"
                            + (lTime - lProcessEndTime_) + " milliseconds...");
                    objEngineLogger_.log(LogLevel.FINE, "{10}Elapsed Time for the Thread run() #"
                            + (lTime - lActualInitializedTimeInMillis_) + " milliseconds..");
                }
            } // End of finally block.
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IJOBMonitor#getInitializedTime()
         */
        public long getInitializedTime() {
            return lActualInitializedTimeInMillis_;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getStartTime()
         */
        public long getStartTime() {
            if (lStartTimeInMillis_ != -1) {
                return lStartTimeInMillis_;
            }
            return -1;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getConnection()
         */
        public Connection getConnection() {
            return con_;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getStuckThreadLimit()
         */
        public long getStuckThreadLimit() {
            return (TimeUnit.MINUTES.toMillis(objPrEb_.getStuckThreadLimit()));
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getStuckThreadMaxLimit()
         */
        public long getStuckThreadMaxLimit() {
            return (TimeUnit.MINUTES.toMillis(objPrEb_.getStuckThreadMaxLimit()));
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getRequestBean()
         */
        public ProcessRequestEntityBean getRequestBean() {
            return objPrEb_;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getUserId()
         */
        public String getUserId() {
            return objPrEb_.getUserId();
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#markStuckThread(boolean)
         */
        public void setJobStatus(JOB_STATUS status) {
            switch (status) {
            case STUCK:
                iStuckThreads_.incrementAndGet();

                break;
            case CRITICAL:
                iStuckThreads_.decrementAndGet(); // Reduce the thread from the Stuck Thread as
                iStuckThreadThatCrossMaxLimit_.incrementAndGet();
                break;
            default:
                break;
            }
            jobStatus_ = status;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#setMonitorCheckTime(long)
         */
        public void setMonitorCheckTime(long time) {
            this.jobCheckedAtTime_ = time;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getMonitorCheckTime()
         */
        public long getMonitorCheckTime() {
            return jobCheckedAtTime_;
        }

        @Override
        public JOB_STATUS getJobStatus() {
            return jobStatus_;
        }
    } // end of inner class ThreadProcess

    /**
     * Starts the service engine for the Grouped Requests. Gets the connection
     * from the pool and Continuously scans the PROCESS_REQUEST table for queued
     * grouped requests and executes them sequentially
     * 
     * <p>
     * Scanning continues in a loop until the tEngine_ thread is interrupted.
     * </p>
     * <p>
     * The query picks up requests, from the table PROCESS_REQUEST, that have
     * the Req_Stat='Q' and GRP_ST_IND = 'G'. If requests are found then each
     * record is processed sequentially depending on the sequence given in the
     * group. If no records are found then the engine waits for a specified time
     * (picked up from property file) and then resumes scanning
     * </p>
     * 
     */
    private void startGroupServiceEngine() {

        if (objEngineLogger_.isInfoEnabled()) {
            objEngineLogger_.info("Starting Group Service Engine...");
        }

        Connection conForGroupedRequest = null;
        PreparedStatement psm = null;
        PreparedStatement psmu = null;
        try {
            objEngineLogger_.log(Level.INFO, "Waiting for the cluster handshake.");
            while (!bClusterHandShakeDone_) {
                // wait do nothing.
                if (bEngineTerminated_.get() || bGroupedEngineTerminated_.get()) {
                    tEngine_.interrupt();
                    break; // break the while loop.
                }
            }
            if (!(bEngineTerminated_.get() || bGroupedEngineTerminated_.get())) {
                if (objEngineLogger_.isDebugEnabled()) {
                    objEngineLogger_.debug("Getting Connection from the pool ....");
                }
                // conForGroupedRequest =
                // poolManager_.getConnection(CSettings.get("pr.dsforgroupeng"));
                conForGroupedRequest = dataSourceFactory_.getDataSource(CSettings.get("pr.dsforgroupeng"))
                        .getConnection();

                psmu = conForGroupedRequest.prepareStatement(
                        "UPDATE process_request SET req_stat = ? WHERE grp_id = ? AND req_stat = ?");
                psm = conForGroupedRequest.prepareStatement(
                        "Select distinct grp_id from process_request where grp_st_ind = ? and req_stat = ? and scheduled_time <= ?");

                objEngineLogger_.log(LogLevel.NOTICE, "Group Service Engine Started....");
            }

            while (!tEngine_.isInterrupted()) {
                boolean bTerminate = false;
                //            try {
                //               LicenseVerifier.verify(readLicense());
                //            } catch (LicenseContentException lce) {
                //               bTerminate = true;
                //               objEngineLogger_.fatal(lce.getLocalizedMessage());
                //            } catch (Exception e) {
                //               bTerminate = true;
                //               objEngineLogger_.fatal(e.getLocalizedMessage());
                //            }
                if (bTerminate) {
                    if (tEngine_ != null) {
                        tEngine_.interrupt();
                    }
                    break;
                }

                ResultSet rs = null;
                try {
                    boolean bDoesRequestExists = false;
                    if (!bGroupedEngineTerminated_.get()) {
                        psm.clearParameters();
                        psm.setString(1, "G");
                        psm.setString(2, REQUEST_STATUS.QUEUED.getID());
                        psm.setTimestamp(3, getCurrentTimestamp(conForGroupedRequest));
                        rs = psm.executeQuery();
                        while (rs.next() && !tEngine_.isInterrupted()) {
                            if (iGrpThreadCounter_.get() <= iGroupMaximumThread_) {
                                long lGroupId = rs.getLong(1);
                                bDoesRequestExists = true;
                                try {
                                    if (objEngineLogger_.isInfoEnabled()) {
                                        objEngineLogger_.info("Begin Group Transaction ...");
                                    }
                                    conForGroupedRequest.setAutoCommit(false);
                                    if (objEngineLogger_.isDebugEnabled()) {
                                        objEngineLogger_.debug(
                                                "Update Status to... " + REQUEST_STATUS.LAUNCHING.getDescription());
                                    }
                                    psmu.setString(1, REQUEST_STATUS.LAUNCHING.getID());
                                    psmu.setLong(2, lGroupId);
                                    psmu.setString(3, REQUEST_STATUS.QUEUED.getID());
                                    psmu.executeUpdate();
                                    if (objEngineLogger_.isDebugEnabled()) {
                                        objEngineLogger_.debug("Commit Transaction ...");
                                    }
                                    conForGroupedRequest.commit();
                                    //
                                } catch (Exception e) {
                                    try {
                                        objEngineLogger_.error("Rollback Transaction ...", e);
                                        conForGroupedRequest.rollback();
                                    } catch (Exception ex) {
                                        throw ex;
                                    }

                                    throw e;
                                } finally {
                                    try {
                                        conForGroupedRequest.setAutoCommit(true);
                                    } catch (Exception ex) {
                                        if (objEngineLogger_.isEnabledFor(Level.WARN)) {
                                            objEngineLogger_.warn("Dummy Exception and can be ignored.", ex);
                                        }
                                    }
                                }
                                CGroupedThreadProcess cgtp = new CGroupedThreadProcess("Thread-Grp#" + lGroupId);
                                cgtp.setGroupId(lGroupId);
                                addGroupProcess(cgtp);
                                cgtp.start();
                                // startServiceForGroupedRequests(conForGroupedRequest,
                                // rs.getLong(1));
                            }
                            if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                                objEngineLogger_.log(LogLevel.FINE,
                                        "Group Engine: Maximum thread spawning capacity (#"
                                                + (iGrpThreadCounter_.get() - 1)
                                                + ") has reached. Going into Wait mode till one of the JOB gets over.");
                            }
                            long lCurrentTime = System.currentTimeMillis();
                            while (iGrpThreadCounter_.get() > iGroupMaximumThread_) {
                                // try
                                // {
                                // Thread.sleep(10000);
                                // }
                                // catch (InterruptedException ie)
                                // {
                                // System.exit(1);
                                // }
                            }
                            long lWaitTime = System.currentTimeMillis() - lCurrentTime;
                            if (objEngineLogger_.isEnabledFor(LogLevel.FINE)) {
                                objEngineLogger_.log(LogLevel.FINE, "Group Engine :Wait Over. Waited for #"
                                        + lWaitTime + " milliseconds for some JOB to get over.");
                            }
                        }
                    } // If group engine is not terminated.
                    if (!bDoesRequestExists) {
                        lWaitInterval_ = (Math.abs(Long.parseLong(CSettings.get("pr.waitinterval"))));
                        if (objEngineLogger_.isInfoEnabled()) {
                            objEngineLogger_.info(
                                    mfSleepMessageForEngine_.format(new Object[] { "Group", lWaitInterval_ }));
                        }
                        try {
                            Thread.yield();
                            TimeUnit.SECONDS.sleep(lWaitInterval_);
                            // Thread.sleep(lWaitInterval_);
                        } catch (InterruptedException ie) {
                            // This is not an exception.
                            objEngineLogger_.log(LogLevel.NOTICE, "Grouped Engine Thread Interrupted ..");
                            break;
                        }
                    } // end of else
                } catch (IOException ioe) {
                    // This is under the assumption that the IO Exception can
                    // never be thrown by the object
                    // executed by the Engine as it can only throw
                    // CProcessRequestEngineException. This exception
                    // means that something wrong has happened in the
                    // Connection.
                    try {
                        closeSQLStatement(psmu);
                        closeSQLStatement(psm);
                        conForGroupedRequest = refreshJDBCConnection(4, conForGroupedRequest,
                                CSettings.get("pr.dsforgroupeng"));
                        // Connection gets refereshed but not the statements.
                        // Therefore the statemetns are refreshed/recreated
                        // here.
                        psmu = conForGroupedRequest.prepareStatement(
                                "UPDATE process_request SET req_stat = ? WHERE grp_id = ? AND req_stat = ?");
                        psm = conForGroupedRequest.prepareStatement(
                                "Select distinct grp_id from process_request where grp_st_ind = ? and req_stat = ? and scheduled_time <= ?");

                    } catch (Exception e) {
                        stopMessageForEmail_ = exceptionToString(ioe);
                        objEngineLogger_.fatal(
                                "Grouped Request: IOException Caught. Terminating GroupedRequest Engine", ioe);
                        setReboot(true);
                        break;
                    }
                } catch (SQLException se) {
                    // This is under the assumption that the SQL Exception can
                    // never be thrown by the object
                    // executed by the Engine as it can only throw
                    // CProcessRequestEngineException. This exception
                    // means that something wrong has happened in the Engine
                    // itself and so engine should get terminated.
                    try {
                        closeSQLStatement(psmu);
                        closeSQLStatement(psm);
                        conForGroupedRequest = refreshJDBCConnection(4, conForGroupedRequest,
                                CSettings.get("pr.dsforgroupeng"));
                        // Connection gets refereshed but not the statements.
                        // Therefore the statemetns are refreshed/recreated
                        // here.
                        psmu = conForGroupedRequest.prepareStatement(
                                "UPDATE process_request SET req_stat = ? WHERE grp_id = ? AND req_stat = ?");
                        psm = conForGroupedRequest.prepareStatement(
                                "Select distinct grp_id from process_request where grp_st_ind = ? and req_stat = ? and scheduled_time <= ?");
                    } catch (Exception e) {
                        stopMessageForEmail_ = exceptionToString(se);
                        objEngineLogger_.fatal(
                                "Grouped Request: SQLException Caught. Terminating GroupedRequest Engine", se);
                        setReboot(true);
                        break;
                    }
                } catch (RuntimeException ree) {
                    objEngineLogger_.error("Grouped Request: Runtime Exception Caught", ree);
                    // no need to throw exception. Just catch.
                } catch (Exception e) {
                    objEngineLogger_.error("Grouped Request: Exception Caught", e);
                    // no need to throw exception. Just catch.
                } finally {
                    if (rs != null) {
                        rs.close();
                    }
                }
            } // end of while
        } catch (Exception e) {
            objEngineLogger_.fatal("Grouped Request Main: Exception Caught", e);
            // no need to throw exception. Just catch.
        } finally {
            closeSQLStatement(psmu);
            closeSQLStatement(psm);
            try {
                if (conForGroupedRequest != null) {
                    if (objEngineLogger_.isInfoEnabled()) {
                        objEngineLogger_.info("Releasing Grouped Connection to the pool ....");
                    }
                    conForGroupedRequest.close();
                }
            } catch (SQLException e) {
                // do nothing
            }
            // objEngineLogger_.log(LogLevel.NOTICE,
            // "Grouped Request Engine Stopped ..");
            if (objEngineLogger_.isDebugEnabled()) {
                objEngineLogger_.debug("Interrupting Shutdown Hook from Grouped Requests...");
            }
            // try {
            // poolManager_.emptyPool(CSettings.get("pr.dsforgroupeng"));
            // } catch (SQLException e) {
            // //do nothing
            // }
            if (tInterrupt_ != null) {
                if (tInterrupt_.isAlive()) {
                    tInterrupt_.interrupt();
                } else {
                    if (tMain_.isAlive()) {
                        tMain_.interrupt();
                    }
                }
            } else {
                if (tMain_.isAlive()) {
                    tMain_.interrupt();
                }
            }
        }
    } // end of method void startGroupServiceEngine()

    /**
     * <p>
     * The query picks up requests, from the table PROCESS_REQUEST, that have
     * the Req_Stat='Q' and GRP_ST_IND = 'G' for the specified group. If
     * requests are found then each record is processed sequentially depending
     * on the priority defined in the group. If no records are found then the
     * engine waits for a specified time (picked up from property file) and then
     * resumes scanning
     * </p>
     * 
     * @param pconForGroupedRequest
     *            Connection object.
     * @param plGroupId
     *            Group id to be serviced.
     * @throws CProcessRequestEngineException
     */
    private void startServiceForGroupedRequests(Connection pconForGroupedRequest, long plGroupId)
            throws CProcessRequestEngineException {
        boolean isQueuedReqFound = false;

        ProcessRequestController objPrCont_ = null;
        ProcessRequestController objPRC = null;
        ProcessReqParamsController objPRPC = null;
        ProcessReqParamsEntityBean objPRPEB = null;
        CDynamicDataContainer objCDC = null;

        StringBuffer reqLogFileName;
        StringBuffer reqLogFileUrl;

        try {

            reqLogFileName = new StringBuffer(50);
            reqLogFileUrl = new StringBuffer(50);

            objEngineLogger_.log(LogLevel.NOTICE, "Processing the Grouped Request for id " + plGroupId);
            if (objEngineLogger_.isInfoEnabled()) {
                objEngineLogger_.info("Starting service for scanning queued grouped requests ....");
            }
            CDynamicDataContainer objDdc_ = new CDynamicDataContainer();
            objDdc_.addWhereClause(FILTER_CONDITION);
            objDdc_.addOrderByClause(" Order By grp_id, grp_req_seq_no, priority");

            ProcessRequestEntityBean objPrEb_ = new ProcessRequestEntityBean();
            // ProcessReqParamsEntityBean objPrparamsEb_ = new
            // ProcessReqParamsEntityBean();
            objPRC = new ProcessRequestController(pconForGroupedRequest);
            objPRPC = new ProcessReqParamsController(pconForGroupedRequest);
            objPRPEB = new ProcessReqParamsEntityBean();
            objCDC = new CDynamicDataContainer();

            objPrCont_ = new ProcessRequestController(pconForGroupedRequest);

            try {

                if (objEngineLogger_.isInfoEnabled()) {
                    objEngineLogger_.info("Entered infintite loop, Initializing Request Entity Bean ....");
                }

                isQueuedReqFound = false;
                if (!bGroupedEngineTerminated_.get()) {
                    objPrEb_.initialize();
                    objPrEb_.setReqStat(REQUEST_STATUS.LAUNCHING.getID());
                    objPrEb_.setGrpStInd(REQUEST_TYPE.GROUPED.getID());
                    objPrEb_.setGrpId(plGroupId);
                    objPrEb_.setScheduledTime(getCurrentTimestamp(pconForGroupedRequest));

                    if (objEngineLogger_.isDebugEnabled()) {
                        objEngineLogger_.debug("Building query ....");
                    }
                    objDdc_.build(pconForGroupedRequest, objPrEb_, hmWhereCondition_);
                    // This has been added later by Kedar on 3/1/2003

                    if (objEngineLogger_.isDebugEnabled()) {
                        objEngineLogger_.debug("Querying for queued requests ...." + objDdc_.getQuery());
                    }

                    isQueuedReqFound = objDdc_.executeQuery(pconForGroupedRequest, objPrCont_, objPrEb_);
                }
                if (isQueuedReqFound) {// pending requests exist

                    if (objEngineLogger_.isDebugEnabled()) {
                        objEngineLogger_.debug("Queued requests exists ....");
                    }

                    boolean bToProcessOthers = true;
                    while (objDdc_.next()) {
                        ProcessRequestEntityBean objPrEb = (ProcessRequestEntityBean) objDdc_.get();
                        if (bToProcessOthers) {
                            if (tEngine_.isInterrupted() || bGroupedEngineTerminated_.get()) {
                                if (objEngineLogger_.isEnabledFor(LogLevel.NOTICE)) {
                                    objEngineLogger_.log(LogLevel.NOTICE,
                                            "The Engine is being terminated. The Group Request #"
                                                    + objPrEb.getGrpId()
                                                    + " even though not complete will be allowed to be executed once PRE is restarted.");
                                }
                                break;
                            }
                        } else {
                            if (tEngine_.isInterrupted() || bGroupedEngineTerminated_.get()) {
                                if (objEngineLogger_.isEnabledFor(LogLevel.NOTICE)) {
                                    objEngineLogger_.log(LogLevel.NOTICE,
                                            "The Engine is being terminated. Please wait till the remaining requests for the Group #"
                                                    + objPrEb.getGrpId() + " are marked as Cancelled.");
                                }
                            }
                        }
                        objPRPEB.initialize();

                        reqLogFileName.delete(0, reqLogFileName.length());
                        reqLogFileUrl.delete(0, reqLogFileUrl.length());
                        reqLogFileName.append(strReqLogFilePath_);
                        reqLogFileName.append(objPrEb.getReqId());
                        reqLogFileName.append(".");
                        reqLogFileName.append(strReqLogFileExtension_);

                        reqLogFileUrl.append(strReqLogFileUrl_);
                        reqLogFileUrl.append(objPrEb.getReqId());
                        reqLogFileUrl.append(".");
                        reqLogFileUrl.append(strReqLogFileExtension_);

                        // objEngineLogger_.debug("Initialize Request Log File ....");

                        if (bToProcessOthers) {
                            ProcessRequestServicer objProcessRequest_ = null;
                            updateRequestStatus(pconForGroupedRequest, objPRC, objPrEb, REQUEST_STATUS.LAUNCHING,
                                    reqLogFileUrl.toString());

                            if (objEngineLogger_.isInfoEnabled()) {
                                objEngineLogger_.info("Initialize Request Log File ....");
                            }

                            try {
                                if (objEngineLogger_.isInfoEnabled()) {
                                    objEngineLogger_
                                            .info("Instantiate the Process Class which has been requested .....");
                                }
                                objProcessRequest_ = instantiateReqProcessObject(objPrEb_.getProcessClassNm());

                                bToProcessOthers = processEachRequest(pconForGroupedRequest, objPRC, objPrEb,
                                        objCDC, objPRPC, objPRPEB, objProcessRequest_,
                                        new File(reqLogFileName.toString()), reqLogFileUrl.toString());
                            } catch (RuntimeException re) {
                                try {
                                    if (objEngineLogger_.isInfoEnabled()) {
                                        objEngineLogger_.info("Update Request Status to Error due to Exception.");
                                    }
                                    updateRequestStatus(staticConnection_, objPrCont_, objPrEb_,
                                            REQUEST_STATUS.ERROR, reqLogFileUrl.toString());
                                } catch (Exception e) {
                                    objEngineLogger_.error("Caught exception while updating status to Error. ", e);
                                }
                                throw re;
                            } catch (Exception e) {
                                try {
                                    if (objEngineLogger_.isInfoEnabled()) {
                                        objEngineLogger_.info("Update Request Status to Error due to Exception.");
                                    }
                                    updateRequestStatus(staticConnection_, objPrCont_, objPrEb_,
                                            REQUEST_STATUS.ERROR, reqLogFileUrl.toString());
                                } catch (Exception ex) {
                                    objEngineLogger_.error("Caught exception while updating status to Error. ", ex);
                                }
                                throw e;
                            } catch (Error error) {
                                try {
                                    if (objEngineLogger_.isInfoEnabled()) {
                                        objEngineLogger_.info("Update Request Status to Error due to Exception.");
                                    }
                                    updateRequestStatus(staticConnection_, objPrCont_, objPrEb_,
                                            REQUEST_STATUS.ERROR, reqLogFileUrl.toString());
                                } catch (Exception ex) {
                                    objEngineLogger_.error("Caught exception while updating status to Error. ", ex);
                                }
                                throw error;
                            } finally {
                                objProcessRequest_ = null;
                            }
                        } // If bToProcessOthers
                        else {
                            try {
                                if (objEngineLogger_.isInfoEnabled()) {
                                    objEngineLogger_.info("Update Request Status to "
                                            + REQUEST_STATUS.SUSPENDED.getDescription());
                                }
                                updateRequestStatus(pconForGroupedRequest, objPRC, objPrEb,
                                        REQUEST_STATUS.SUSPENDED, reqLogFileUrl.toString());
                            } catch (Exception e) {
                                objEngineLogger_.error("Caught exception while updating status to Error. ", e);
                                // do not throw just log it.
                            }
                        }

                    } // end of while(objDdc.next())

                    // If the engine is terminated then update the status of
                    // other grouped request to Q so that
                    // next time the remaining processes can be completed.
                    // Added on 30/04/2004....Kedar.
                    if ((tEngine_.isInterrupted() || bGroupedEngineTerminated_.get()) && bToProcessOthers) {
                        PreparedStatement psm = null;
                        try {
                            psm = pconForGroupedRequest.prepareStatement(
                                    "UPDATE process_request set req_stat = ? WHERE grp_id = ? and req_stat = ?");
                            psm.setString(1, REQUEST_STATUS.QUEUED.getID());
                            psm.setLong(2, plGroupId);
                            psm.setString(3, REQUEST_STATUS.LAUNCHING.getID());
                            psm.executeUpdate();
                        } catch (Exception e) {
                            objEngineLogger_.error("Caught exception while updating status to Queued. ", e);
                            // just log the exception. Need not be thrown.
                            // INFO Needs to be re-validated if this needs to be
                            // thrown.
                        } finally {
                            try {
                                if (psm != null) {
                                    psm.close();
                                }
                            } catch (Exception e) {
                                if (objEngineLogger_.isEnabledFor(Level.WARN)) {
                                    objEngineLogger_.warn("Exception can be ignored..Dummy exception.", e);
                                }
                            }
                        }

                    } // ((tEngine.isInterrupted() ||
                      // bGroupedEngineTerminated_))
                } // end of if objDdc.getTotalRows() > 0
            } catch (Exception e) {
                objEngineLogger_.error("Processing GroupedRequest: Exception Caught", e);
                // Just catch. No need to throw.
            }

        } catch (Exception e) {
            objEngineLogger_.error("Processing GroupedRequest: Exception Caught", e);
            // Just catch. No need to throw.
        } // end of 1st try catch block
        finally {
            objEngineLogger_.log(LogLevel.NOTICE, "Releasing Group Resources...");
            if (objPrCont_ != null) {
                try {
                    objPrCont_.close();
                } catch (SQLException e) {
                    objEngineLogger_.error("Processing GroupedRequest: Exception Caught while closing PRController",
                            e);
                }
            }
            if (objPRC != null) {
                try {
                    objPRC.close();
                } catch (SQLException e) {
                    objEngineLogger_.error("Processing GroupedRequest: Exception Caught while closing PRController",
                            e);
                }
            }
            if (objPRPC != null) {
                try {
                    objPRPC.close();
                } catch (SQLException e) {
                    objEngineLogger_
                            .error("Processing GroupedRequest: Exception Caught while closing PRPController", e);
                }
            }
            reqLogFileName = null; // Nullifying the variables.
            reqLogFileUrl = null; // Nullifying the variables.
            objEngineLogger_.log(LogLevel.NOTICE, "Grouped Request processed for id " + plGroupId);
        }
    } // end of method void startServiceForGroupedRequests

    /**
     * This inner class extends Thread and executes different Grouped requests.
     * 
     */
    class CGroupedThreadProcess extends Thread implements IJOBMonitor {

        /**
         * Stores the REVISION number of the class from the configuration
         * management tool.
         */
        public final String REVISION = "$Revision:: 3829              $";

        private Logger groupLogger_;

        private long lActualInitializedTimeInMillis_;

        private long lStartTimeInMillis_ = -1;

        public CGroupedThreadProcess() {
            super();
            groupLogger_ = Logger.getLogger("GroupEngine");
            lActualInitializedTimeInMillis_ = System.currentTimeMillis();
        }

        public CGroupedThreadProcess(String name) {
            super(name);
            groupLogger_ = Logger.getLogger("GroupEngine");
            lActualInitializedTimeInMillis_ = System.currentTimeMillis();
        }

        private long lGrpId_;

        private Connection conGrp_;

        private JOB_STATUS jobStatus_;

        private long jobCheckedAtTime_ = -1;

        public void setGroupId(long plGrpId) {
            lGrpId_ = plGrpId;
        }

        public IProcessRequest getIntantiatedObject() {
            return null;
        }

        public void run() {
            lStartTimeInMillis_ = System.currentTimeMillis();
            if (groupLogger_.isEnabledFor(LogLevel.FINE)) {
                groupLogger_.log(LogLevel.FINE, "{1}Thread Wait Time "
                        + (lStartTimeInMillis_ - lActualInitializedTimeInMillis_) + " milliseconds...");
            }
            try {
                // conGrp_ =
                // poolManager_.getConnection(CSettings.get("pr.dsforgroupeng"));
                conGrp_ = dataSourceFactory_.getDataSource(CSettings.get("pr.dsforgroupeng")).getConnection();
                startServiceForGroupedRequests(conGrp_, lGrpId_);
            } catch (Error error) {
                groupLogger_.fatal("java.lang.Error Caught", error);
                throw error;
            } catch (RuntimeException ree) {
                groupLogger_.fatal("Runtime Exception Caught", ree);
                throw ree;
            } catch (CProcessRequestEngineException cree) {
                groupLogger_.fatal("CProcessRequestEngineException Caught", cree);
                // Just catch. Can't throw a catched exception.
            } catch (Exception e) {
                groupLogger_.fatal("Exception Caught", e);
                // Just catch. Can't throw a catched exception.
            } finally {
                try {
                    conGrp_.close();
                } catch (SQLException e1) {
                    // do nothing
                }

                removeGroupProcess(this);
                if (vectorThreadsGroup_.size() == 0 && bGroupedEngineTerminated_.get()) {
                    // try
                    // {
                    // poolManager_.emptyPool(CSettings.get("pr.dsforgroupeng"));
                    // } catch (Exception e) {
                    // objEngineLogger_.error(e);
                    // }
                    if (groupLogger_.isDebugEnabled()) {
                        groupLogger_.debug("Grouped Engine: Iterrupting Shutdown Hook...");
                    }
                    if (tInterrupt_ != null) {
                        // Earlier this thread if not null was then Alive as
                        // well. But because of Reboot sequence
                        // This thread can be not null but not alive and
                        // therfore this condition is added.
                        if (tInterrupt_.isAlive()) {
                            tInterrupt_.interrupt();
                        } else {
                            tEngine_.interrupt();
                        }
                    } else {
                        tEngine_.interrupt();
                    }
                } // (vectorThreadsGroup_.size() == 0 &&
                  // bGroupedEngineTerminated_)
                if (groupLogger_.isEnabledFor(LogLevel.FINE)) {
                    groupLogger_.log(LogLevel.FINE, "{10}Elapsed Time for the Thread run() #"
                            + (System.currentTimeMillis() - lActualInitializedTimeInMillis_) + " milliseconds...");
                }
            } // finally
        } // run()

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getStartTime()
         */
        public long getStartTime() {
            return lStartTimeInMillis_;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getConnection()
         */
        public Connection getConnection() {
            return null;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getStuckThreadLimit()
         */
        public long getStuckThreadLimit() {
            return 0;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getStuckThreadMaxLimit()
         */
        public long getStuckThreadMaxLimit() {
            return 0;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getRequestBean()
         */
        public ProcessRequestEntityBean getRequestBean() {
            return null;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getUserId()
         */
        public String getUserId() {
            return null;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#markStuckThread(boolean)
         */
        public void setJobStatus(JOB_STATUS status) {
            jobStatus_ = status;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getStuckThread()
         */
        public int getStuckThread() {
            return jobStatus_.getID();
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#setMonitorCheckTime(long)
         */
        public void setMonitorCheckTime(long time) {
            this.jobCheckedAtTime_ = time;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IMonitorThread#getMonitorCheckTime()
         */
        public long getMonitorCheckTime() {
            return jobCheckedAtTime_;
        }

        /*
         * (non-Javadoc)
         * 
         * @see stg.pr.engine.IJOBMonitor#getInitializedTime()
         */
        public long getInitializedTime() {
            return lActualInitializedTimeInMillis_;
        }

        public JOB_STATUS getJobStatus() {
            return jobStatus_;
        }

    } // End of class CGroupedThreadProcess

    /**
     * Internal class to monitor the stuck thread.
     * 
     * @author Kedar C. Raybagkar
     */
    class MonitorThread extends Thread {
        /**
         * Stores the REVISION number of the class from the configuration
         * management tool.
         */
        public final String REVISION = "$Revision:: 3829              $";

        private Logger monitorLogger_;

        //      private Day dayLicenseAlert_ = null;

        public MonitorThread(String name) {
            super(name);
            monitorLogger_ = Logger.getLogger("JobMonitor");
            //         dayLicenseAlert_ = new Day();
        }

        /**
         * Message Format.
         */
        private MessageFormat mfSleepMessage_ = new MessageFormat("Will sleep for {0, number} minute(s).");

        /*
         * (non-Javadoc)
         * 
         * @see java.lang.Runnable#run()
         */
        public void run() {
            monitorLogger_.log(LogLevel.NOTICE, "Started...");
            try {
                // while (!tMonitorThread_.isInterrupted())
                while (true) {
                    // if (tMain_ != null)
                    // {
                    // if (!tMain_.isAlive())
                    // {
                    // break;
                    // }
                    // }
                    //               boolean bTerminate = false;
                    //               LicenseContent content = null;
                    //               try {
                    //                  content = readLicense();
                    //                  LicenseVerifier.verify(content);
                    //               } catch (LicenseContentException e) {
                    //                  bTerminate = true;
                    //                  monitorLogger_.fatal(e.getLocalizedMessage());
                    //               } catch (Exception e) {
                    //                  bTerminate = true;
                    //                  monitorLogger_.fatal(e.getLocalizedMessage());
                    //               }
                    //               if (bTerminate) {
                    //                  if (tEngine_ != null) {
                    //                     tEngine_.interrupt();
                    //                  }
                    //                  if (tMain_ != null) {
                    //                     tMain_.interrupt();
                    //                  }
                    //                  break;
                    //               }

                    //               if (dayLicenseAlert_.compareTo(content.getNotAfter()) * -1 <= Integer
                    //                     .parseInt(CSettings.get(
                    //                           "pr.licenseAlertDaysBeforeExpiry", "10"))
                    //                     && dayLicenseAlert_.compareTo(new Day()) == 0) {
                    //                  sendDefaultMail(
                    //                        "License will expire on "
                    //                              + content.getNotAfter(),
                    //                        "Please get the license renewed before it expires.",
                    //                        true);
                    //                  dayLicenseAlert_.advance(1);
                    //               }
                    try {
                        if (monitorLogger_.isInfoEnabled()) {
                            monitorLogger_
                                    .info(mfSleepMessage_.format(new Object[] { lStuckThreadMonitorInterval_ }));
                        }
                        Thread.yield();
                        TimeUnit.MINUTES.sleep(lStuckThreadMonitorInterval_);
                        // Thread.sleep(lStuckThreadMonitorInterval_);
                    } catch (InterruptedException e) {
                        monitorLogger_.log(LogLevel.NOTICE, "Thread Interrupted.");
                        // do nothing. This thread is supposed to be notified
                        // with Interrupted Exception.
                        // break;
                        // e.printStackTrace();
                    }
                    if (monitorLogger_.isInfoEnabled()) {
                        monitorLogger_.info("Checking for Stuck Threads.");
                    }
                    try {
                        boolean bProcessRRunning = checkForStuckThread();
                        if (bEngineTerminated_.get() || !tMain_.isAlive()) // Currently
                        // as
                        // the
                        // StandAlone
                        // Service
                        // Threads
                        // are
                        // monitored.
                        {
                            monitorLogger_.log(LogLevel.NOTICE,
                                    "Engine is being terminated...Stopping Job Monitor.");
                            if (bProcessRRunning) {
                                monitorLogger_.log(LogLevel.NOTICE,
                                        "Unable to stop JobMonitor as job(s) are currently running.");
                                startWebServer(); // Try restarting the web
                                // server if not started.
                            } else {
                                if (tEngine_ != null) {
                                    tEngine_.interrupt();
                                }
                                break;
                            }
                        }
                    } catch (Error error) {
                        monitorLogger_.error("Error caught", error);
                        // Monitor job should never get terminated.
                    } catch (RuntimeException re) {
                        monitorLogger_.error("RunTime Exception caught ", re);
                        // Monitor job should never get terminated.
                    } catch (Exception e) {
                        monitorLogger_.error("Exception caught", e);
                        // Monitor job should never get terminated.
                    }
                } // end of while
                if (tMonitorThread_.isInterrupted()) {
                    monitorLogger_.log(LogLevel.NOTICE, "Stopping the monitor thread.");
                }
            } catch (Throwable e) {
                monitorLogger_.error("Exception caught in Monitor Thread.", e);
                // No need to throw. Just catch and log.
            } finally {
                stopWebServer();
                // the following if condition is because the pool has its own
                // selfcheck thread running. This thread keeps on running
                // and therefore the engine does not terminiate. The thread runs
                // only if the connection idle time is > 0.
                // The closeAll() method tries to interrupt this thread thus
                // forcing it to break the cycle (loop). Therefore a new thread
                // is
                // spawned and the closeAll() method is called from there.
                // Kedar. 04/10/2008.
                // if
                // (poolManager_.getPoolAttributes(CSettings.get("pr.dsforstandaloneeng")).getConnectionIdleTimeout()
                // > 0
                // ||
                // poolManager_.getPoolAttributes(CSettings.get("pr.dsforgroupeng")).getConnectionIdleTimeout()
                // > 0) {
                Thread th = new Thread("JobMonitor-Clean-Shutdown") {
                    /*
                     * (non-Javadoc)
                     * 
                     * @see java.lang.Thread#run()
                     */
                    public void run() {
                        try {
                            closeAll();
                        } catch (Throwable t) {
                            // dummy catch.
                        } finally {
                            Hazelcast.shutdownAll();
                        }
                        super.run();
                    }
                };
                th.start();
                // }
            }
            if (monitorLogger_.isInfoEnabled()) {
                monitorLogger_.info("Checking to see if any pending emails are to be transported");
            }
            try {
                CMailer.getInstance(CSettings.get("pr.mailtype")).shutdown(instance_);
            } catch (Throwable e) {
                monitorLogger_.warn(e.getMessage(), e);
            }
            if (monitorLogger_.isInfoEnabled()) {
                monitorLogger_.log(LogLevel.NOTICE, "Monitor thread stopped.");
            }
        }

        /**
         * Method to check the status of each thread that is running.
         * 
         * @return boolean TRUE if there are any threads that are currently
         *         running else FALSE.
         */
        private boolean checkForStuckThread() {
            boolean bProcessAreRunningCurrently = false;
            if (monitorLogger_.isInfoEnabled()) {
                monitorLogger_.info("Currently Running Processes #" + vectorThreads_.size());
            }
            int iJobsTerminated = 0;
            StringBuffer messageBuffer = null;
            StringBuffer subjectBuffer = null;
            IJOBMonitor[] jobs = getStandAloneJobs();
            for (int i = 0; i < jobs.length; i++) {
                try {
                    bProcessAreRunningCurrently = true;
                    IJOBMonitor threadMonitor = jobs[i];
                    if (threadMonitor.getStartTime() > -1) {
                        long lCurrentTimeInMilis = System.currentTimeMillis(); // (new
                        // GregorianCalendar()).getTimeInMillis();
                        if (threadMonitor.getJobStatus().getID() > 0) {
                            if (monitorLogger_.isInfoEnabled()) {
                                monitorLogger_.info("STUCK. Still Running !! Request Id #"
                                        + threadMonitor.getRequestBean().getReqId() + " Job : "
                                        + threadMonitor.getRequestBean().getJobId() + " - "
                                        + threadMonitor.getRequestBean().getJobName());
                            }
                        }

                        if (threadMonitor.getJobStatus() == JOB_STATUS.NORMAL) {
                            if ((lCurrentTimeInMilis - threadMonitor.getStartTime()) > threadMonitor
                                    .getStuckThreadLimit()) {
                                threadMonitor.setJobStatus(JOB_STATUS.STUCK);
                                if (monitorLogger_.isInfoEnabled()) {
                                    monitorLogger_.info("Marked as STUCK !! Request Id"
                                            + threadMonitor.getRequestBean().getReqId());
                                    monitorLogger_
                                            .info("Setting the Thread Priority To Max #" + Thread.MAX_PRIORITY);
                                }
                                try {
                                    ((Thread) threadMonitor).setPriority(Thread.MAX_PRIORITY);
                                } catch (SecurityException e) {
                                    monitorLogger_.error("Unable to set the priority.", e);
                                    // dummy catch.
                                }
                                if (subjectBuffer == null) {
                                    subjectBuffer = new StringBuffer();
                                    messageBuffer = new StringBuffer();
                                }
                                subjectBuffer.delete(0, subjectBuffer.length());
                                messageBuffer.delete(0, messageBuffer.length());
                                subjectBuffer.append(" Request Id #");
                                subjectBuffer.append(threadMonitor.getRequestBean().getReqId());
                                subjectBuffer.append(" Job #");
                                subjectBuffer.append(threadMonitor.getRequestBean().getJobId());
                                subjectBuffer.append(" - ");
                                subjectBuffer.append(threadMonitor.getRequestBean().getJobName());
                                messageBuffer.append("Job Has Crossed The ");
                                messageBuffer.append(
                                        TimeUnit.MILLISECONDS.toMinutes(threadMonitor.getStuckThreadLimit()));
                                messageBuffer.append(" Minute(s) Stuck Thread Limit. The PRE has set the ");
                                messageBuffer.append(" priority of this thread to MAX.");
                                if (CSettings.get("pr.mailnotification", "OFF").equals("ON")) {
                                    try {
                                        CMailer.sendMonitorMail(CMailer.NORMAL, subjectBuffer.toString(),
                                                messageBuffer.toString());
                                    } catch (Throwable e) {
                                        monitorLogger_
                                                .error("Unable to send the Message due to : " + e.getMessage(), e);
                                        // Notification is not a must. So if PRE
                                        // is not able to send an email it
                                        // ignores the error.
                                    }
                                }
                            } // if ((lCurrentTimeInMilis -
                              // threadMonitor.getStartTime()) >
                              // threadMonitor.getStuckThreadLimit())
                        } // if stuckThread() == 0
                        if (threadMonitor.getJobStatus() == JOB_STATUS.STUCK) {
                            if ((lCurrentTimeInMilis - threadMonitor.getStartTime()) > threadMonitor
                                    .getStuckThreadMaxLimit()) {
                                threadMonitor.setJobStatus(JOB_STATUS.CRITICAL);
                                threadMonitor.setMonitorCheckTime(lCurrentTimeInMilis);
                                long lRequestId = threadMonitor.getRequestBean().getReqId();
                                monitorLogger_.warn("STUCK. Crossed the MAX Stuck Thread Limit. Request Id #"
                                        + lRequestId + " Job : " + threadMonitor.getRequestBean().getJobId() + " - "
                                        + threadMonitor.getRequestBean().getJobName());
                                if (subjectBuffer == null) {
                                    subjectBuffer = new StringBuffer();
                                    messageBuffer = new StringBuffer();
                                }
                                subjectBuffer.delete(0, subjectBuffer.length());
                                messageBuffer.delete(0, messageBuffer.length());
                                subjectBuffer.append(" Request Id #");
                                subjectBuffer.append(threadMonitor.getRequestBean().getReqId());
                                subjectBuffer.append(" Job #");
                                subjectBuffer.append(threadMonitor.getRequestBean().getJobId());
                                subjectBuffer.append(" - ");
                                subjectBuffer.append(threadMonitor.getRequestBean().getJobName());
                                messageBuffer.append("Job Has Crossed The ");
                                messageBuffer.append(
                                        TimeUnit.MILLISECONDS.toMinutes(threadMonitor.getStuckThreadMaxLimit()));
                                messageBuffer.append(" Minute(s) Stuck Thread MAX Limit. The job has taken");
                                messageBuffer.append(" time even after setting thread priority to MAX by PRE.");
                                if (CSettings.get("pr.terminateprocess", "N").equals("Y")) {
                                    if (threadMonitor.getIntantiatedObject() instanceof ITerminateProcess) {
                                        if (monitorLogger_.isInfoEnabled()) {
                                            monitorLogger_.info("Requesting termination of job \""
                                                    + ((threadMonitor.getRequestBean().getJobId() == null) ? ""
                                                            : threadMonitor.getRequestBean().getJobId()
                                                                    .toUpperCase(Locale.US))
                                                    + "\" Request #" + lRequestId);
                                        }
                                        messageBuffer.append(" PRE has initiated the termination process.");
                                        ((ITerminateProcess) threadMonitor.getIntantiatedObject())
                                                .terminate("Stuck Thread.");
                                        threadMonitor.setJobStatus(JOB_STATUS.TOBETERMINATED);
                                        iJobsTerminated++;
                                    }
                                }
                                if (CSettings.get("pr.mailnotification", "OFF").equals("ON")) {
                                    try {
                                        CMailer.sendMonitorMail(CMailer.CRITICAL, subjectBuffer.toString(),
                                                messageBuffer.toString());
                                    } catch (Throwable e) {
                                        monitorLogger_.error("Unable to send the Message due to : ", e);
                                        // Notification is not a must. So if PRE
                                        // is not able to send an email it
                                        // ignores the error.
                                    }
                                } // if pr.mailnotification equals ON
                            } // if ((lCurrentTimeInMilis -
                              // threadMonitor.getStartTime()) >
                              // threadMonitor.getStuckThreadMaxLimit())
                        } // stuckThread() == 1
                        else if (threadMonitor.getJobStatus().getID() >= 2) {

                            if ((lCurrentTimeInMilis - threadMonitor.getMonitorCheckTime()) > TimeUnit.MINUTES
                                    .toMillis(jobMonitorEscalationTimeInterval_)) {
                                threadMonitor.setMonitorCheckTime(lCurrentTimeInMilis);
                                long lRequestId = threadMonitor.getRequestBean().getReqId();
                                if (subjectBuffer == null) {
                                    subjectBuffer = new StringBuffer();
                                    messageBuffer = new StringBuffer();
                                }
                                subjectBuffer.delete(0, subjectBuffer.length());
                                messageBuffer.delete(0, messageBuffer.length());
                                subjectBuffer.append(" Request Id #");
                                subjectBuffer.append(threadMonitor.getRequestBean().getReqId());
                                subjectBuffer.append(" Job #");
                                subjectBuffer.append(threadMonitor.getRequestBean().getJobId());
                                subjectBuffer.append(" - ");
                                subjectBuffer.append(threadMonitor.getRequestBean().getJobName());
                                messageBuffer.append("Job is alive. Crossed ");
                                messageBuffer.append(TimeUnit.MILLISECONDS
                                        .toMinutes(lCurrentTimeInMilis - threadMonitor.getStartTime()));
                                messageBuffer.append(" minutes. Please attend this process.");
                                if (CSettings.get("pr.terminateprocess", "N").equals("Y")) {
                                    if (threadMonitor.getJobStatus() == JOB_STATUS.TOBETERMINATED) {
                                        if (monitorLogger_.isInfoEnabled()) {
                                            monitorLogger_.info("The job \""
                                                    + ((threadMonitor.getRequestBean().getJobId() == null) ? ""
                                                            : threadMonitor.getRequestBean().getJobId()
                                                                    .toUpperCase(Locale.US))
                                                    + "\" Request #" + lRequestId
                                                    + " is unable to terminate itself even after invoking the terminate method.");
                                        }
                                    }
                                }
                                if (CSettings.get("pr.mailnotification", "OFF").equals("ON")) {
                                    try {
                                        CMailer.sendMonitorMail(CMailer.CRITICAL, subjectBuffer.toString(),
                                                messageBuffer.toString());
                                    } catch (Throwable e) {
                                        monitorLogger_.error("Unable to send the Message due to : ", e);
                                        // Notification is not a must. So if PRE
                                        // is not able to send an email it
                                        // ignores the error.
                                    }
                                } // if pr.mailnotification equals ON
                            }
                        }
                    } // threadMonitor.getStartTime() > -1
                    if (bEngineTerminated_.get()) {
                        Object obj = threadMonitor.getIntantiatedObject();
                        if (obj instanceof IStopEvent) {
                            IStopEvent stopEvent = (IStopEvent) obj;
                            if (monitorLogger_.isInfoEnabled()) {
                                monitorLogger_.info("Notifiying Engine Stop Event to Request Id # "
                                        + threadMonitor.getRequestBean().getReqId() + " JOB #"
                                        + threadMonitor.getRequestBean().getJobId() + " - "
                                        + threadMonitor.getRequestBean().getJobName());
                            }
                            try {
                                stopEvent.notifyEngineStopEvent();
                            } catch (RuntimeException e) {
                                monitorLogger_.error("Caught Runtime Exception while notifying the stop event.", e);
                                // Engine is being terminated. So just log and
                                // go ahead.
                            } catch (Exception e) {
                                monitorLogger_.error("Caught Exception while notifying the stop event.", e);
                                // Engine is being terminated. So just log and
                                // go ahead.
                            }
                        }
                    }
                } catch (NullPointerException npe) {
                    // One of the thread has finished its job therefore the
                    // thread was removed and raised a nullpointer exception.
                }
            } // For loop vector threads iteration.
            if (monitorLogger_.isInfoEnabled()) {
                monitorLogger_.info("Current Stuck Threads are #" + iStuckThreads_
                        + " Threads That Crossed Max Limit #" + iStuckThreadThatCrossMaxLimit_);
            }
            boolean bBounce = false;
            if (iStandAloneMaximumThread_ == iStuckThreadThatCrossMaxLimit_.get()) {
                bBounce = true;
            }
            if ((bEngineTerminated_.get() || !tMain_.isAlive())
                    && (iStuckThreadThatCrossMaxLimit_.get() == getCurrentRunningStandAloneProcess()
                            && iStuckThreadThatCrossMaxLimit_.get() > 0)) { // Thread
                // main
                // is
                // dead
                // and
                // if
                // current
                // running
                // stand
                // alone
                // process
                // count
                // ==
                // stuck
                // thread
                // count.
                bBounce = true;
            }
            if (bBounce && iJobsTerminated > 0) {
                bBounce = false;
                if (monitorLogger_.isInfoEnabled()) {
                    monitorLogger_.info("Even though all the jobs have been identified as STUCK there are #"
                            + iJobsTerminated + " jobs whose terminate method is invoked.");
                    monitorLogger_.info(
                            "Engine will wait for the job(s) to terminate itself gracefully. Incase the job does not terminate itself, the PRE will try to forcefully terminate it.");
                }
            }
            if (bBounce) {
                String strMessage = "";
                if (isReboot()) {
                    strMessage = "Reboot(Abort)";
                } else if (bEngineTerminated_.get() || !tMain_.isAlive()) {
                    strMessage = "Shut Down (Abort)";
                } else {
                    strMessage = "Bounce (Abort)";
                }
                monitorLogger_.log(LogLevel.NOTICE, "Process Request Engine is being " + strMessage + " !!");
                monitorLogger_.log(LogLevel.NOTICE, "Please take a look at all the jobs with status equals \""
                        + REQUEST_STATUS.PROCESSING.getID() + "\". These jobs will not be reprocessed by the PRE.");
                if (isReboot() || (bEngineTerminated_.get() || !tMain_.isAlive())) {
                    monitorLogger_.log(LogLevel.NOTICE, "All the threads have gone into a STUCK MODE and the PRE "
                            + strMessage + " sequence has been executed.");
                } else {
                    monitorLogger_.log(LogLevel.NOTICE,
                            "All the threads have gone into a STUCK MODE and the PRE cannot therefore service any request.");
                }
                StringBuffer strBuffer = new StringBuffer();
                if (isReboot() || (bEngineTerminated_.get() || !tMain_.isAlive())) {
                    strBuffer.append("All the threads have gone into a STUCK MODE and the PRE " + strMessage
                            + " sequence has been executed.");
                } else {
                    strBuffer.append(
                            "All the threads have gone into a STUCK MODE and the PRE cannot therefore service ");
                    strBuffer.append("any request. Bouncing the PRE. ");
                }
                strBuffer.append("Please take a look at the PRE queue for all processes with status equal to \"");
                strBuffer.append(REQUEST_STATUS.PROCESSING.getID());
                strBuffer.append("\". These processes will not be reprocessed by the PRE after it is restarted. ");
                strBuffer.append("Please read the log file for details about the processes that were STUCK.");
                strBuffer.append(NEW_LINE);
                strBuffer.append(NEW_LINE);
                if (bEngineTerminated_.get() || !tMain_.isAlive()) {
                    strBuffer.append("Please start the PRE manually. PRE will not attempt a reboot sequence.");
                    strBuffer.append(NEW_LINE);
                    strBuffer.append(NEW_LINE);
                } else {
                    strBuffer.append(
                            "Please do not try to manually start the PRE. PRE will attempt a reboot sequence.");
                    strBuffer.append(NEW_LINE);
                    strBuffer.append(NEW_LINE);
                }
                strBuffer.append("Please contact Help Desk for further assistance.");
                if (CSettings.get("pr.mailnotification", "OFF").equals("ON")) {
                    // CMailer mailer =
                    // CMailer.getInstance(CSettings.get("pr.mailtype",
                    // "SMTP"));
                    EMail email = new EMail();
                    try {
                        email.setTORecipient(CSettings.get("mail.monitor." + CMailer.CRITICAL + "recepientTO"));
                        email.setCCRecipient(CSettings.get("mail.monitor." + CMailer.CRITICAL + "recepientCC"));
                    } catch (AddressException e) {
                        // Do nothing
                    }
                    email.setEMailId("CriticalState#" + System.currentTimeMillis());
                    email.setSubject("CRITICAL !!!  " + strMessage);
                    email.setMessageBody(strBuffer.toString());
                    try {
                        CMailer.getInstance(CSettings.get("pr.mailtype")).sendMail(email); // This should not be changed
                        // to sendAsyncMail as this
                        // thread needs to wait till
                        // the email is transported.
                    } catch (MessagingException e) {
                        monitorLogger_.error("Exception caught while sending email", e);
                    }
                }
                if (monitorLogger_.isEnabledFor(LogLevel.FINEST)) {
                    monitorLogger_.log(LogLevel.FINEST, "Generating INI file");
                }
                if (isReboot()) {
                    if (monitorLogger_.isInfoEnabled()) {
                        monitorLogger_.info("Reboot (Abort) !!!");
                    }
                    context_.getMap().put("state", HeartBeatState.REBOOT);
                    createIniFile(CStartEngine.REBOOT, -1);
                } else if (bEngineTerminated_.get() || !tMain_.isAlive()) {
                    if (monitorLogger_.isInfoEnabled()) {
                        monitorLogger_.info("Shut Down (Abort) !!!");
                    }
                    context_.getMap().put("state", HeartBeatState.STOP);
                } else {
                    context_.getMap().put("state", HeartBeatState.BOUNCE);
                    createIniFile(CStartEngine.BOUNCE, -1);
                }
                if (monitorLogger_.isInfoEnabled()) {
                    monitorLogger_.info("Shuting down the Mailer");
                }
                CMailer.getInstance(CSettings.get("pr.mailtype")).shutdown(instance_);
                if (monitorLogger_.isEnabledFor(LogLevel.FINEST)) {
                    monitorLogger_.log(LogLevel.FINEST, "Just before stopping the JVM");
                }
                Runtime.getRuntime().halt(2);
            }
            return bProcessAreRunningCurrently;
        }

    } // End of class MonitorThread

    /**
     * Returns the current running Stand Alone process.
     * 
     * @return int Current running thread count.
     */
    protected int getCurrentRunningStandAloneProcess() {
        return vectorThreads_.size();
    }

    /**
     * Returns the current running Grouped process.
     * 
     * @return int Current running thread count.
     */
    protected int getCurrentRunningGroupedProcess() {
        return vectorThreadsGroup_.size();
    }

    /**
     * Number of running threads that cross the Stuck Thread limit.
     * 
     * @return int
     */
    protected int getStuckThreads() {
        return iStuckThreads_.get();
    }

    /**
     * Number of running threads that cross the Stuck Thread maximum limit.
     * 
     * @return int
     */
    protected int getStuckThreadsThatCrossedMaxLimit() {
        return iStuckThreadThatCrossMaxLimit_.get();
    }

    /**
     * Update the schedule for the appropriate status and returns the additional
     * email ids associated with the schedule. Exception is logged as well as
     * thrown.
     * 
     * @param scheduleStatus
     *            String Schedule Status
     *            {@link stg.pr.engine.scheduler.ISchedule}
     * @param pcon
     *            Connection
     * @param plSchId
     *            long Schedule Id.
     * @throws Exception
     *             return Additional email ids
     */
    private boolean updateSchedule(SCHEDULE_STATUS scheduleStatus, Connection pcon, long plSchId) throws Exception {
        ProcessRequestScheduleController objPRSController = null;
        ProcessRequestScheduleEntityBean objPRSBean = null;
        boolean bReturnValue = false;
        try {
            pcon.setAutoCommit(false);
            objPRSBean = new ProcessRequestScheduleEntityBean();
            objPRSController = new ProcessRequestScheduleController(pcon);
            objPRSController.findByPrimaryKey(objPRSBean, plSchId);
            objPRSBean.setSchStat(scheduleStatus.getID());
            bReturnValue = objPRSController.update(objPRSBean);
            pcon.commit();
        } catch (SQLException e) {
            objEngineLogger_.error(
                    "Error while updating the schedule status (" + scheduleStatus + ") for schedule#" + plSchId, e);
            objEngineLogger_.error("Unable to get the additional email recepients..");
            throw e;
        } finally {
            if (objPRSController != null) {
                objPRSController.close();
            }
            try {
                pcon.setAutoCommit(true);
            } catch (SQLException e) {
                // do nothing.
                if (objEngineLogger_.isEnabledFor(Level.WARN)) {
                    objEngineLogger_.warn("Exception can be ignored..", e);
                }
            }
        }
        return bReturnValue;
    }

    /**
     * The RPE sends a mail if the pre is unable to execute the schedule
     * associated with the request.
     * 
     * @param plRequestId
     *            long Request Id
     * @param plScheduleId
     *            long Schedule Id
     * @param pstrJobId
     *            String Process Name
     * @param objThrowable
     *            Throwable
     * @param pstrAdditionalEmailRecipients
     */
    private void sendScheduleUnExecutedMail(long plRequestId, long plScheduleId, String pstrJobId,
            String pstrJobName, Throwable objThrowable, String pstrAdditionalEmailRecipients) {
        try {
            // CMailer mailer = CMailer.getInstance(CSettings.get("pr.mailtype",
            // "SMTP"));
            EMail email = new EMail();
            if (pstrAdditionalEmailRecipients != null) {
                try {
                    email.setTORecipient(CSettings.get("mail.recepientTO") + "," + pstrAdditionalEmailRecipients);
                } catch (AddressException e) {
                    objEngineLogger_.warn("Invalid Email Address of recepients. Schedule #" + plScheduleId
                            + " Email(s) #" + pstrAdditionalEmailRecipients, e);
                    objEngineLogger_.info("Setting default recepient address...");
                    email.setTORecipient(CSettings.get("mail.recepientTO"));
                }
            } else {
                email.setTORecipient(CSettings.get("mail.recepientTO"));
            }
            email.setEMailId("USR#" + plRequestId);
            email.setCCRecipient(CSettings.get("mail.recepientCC"));
            StringBuffer sbuf = new StringBuffer(100);
            sbuf.append("Request #");
            sbuf.append(plRequestId);
            sbuf.append(" Job Id #");
            sbuf.append(pstrJobId);
            sbuf.append(" :  Associated Schedule #");
            sbuf.append(plScheduleId);
            sbuf.append(" Could Not Be Executed !!");
            email.setSubject(sbuf.toString());

            sbuf.delete(0, sbuf.length());
            sbuf.append("Request  :");
            sbuf.append(plRequestId);
            sbuf.append(NEW_LINE);
            sbuf.append("Job Id   : ");
            sbuf.append(pstrJobId);
            sbuf.append(NEW_LINE);
            sbuf.append("Job Name : ");
            sbuf.append(pstrJobName);
            sbuf.append(NEW_LINE);
            sbuf.append(NEW_LINE);
            sbuf.append(
                    "The schedule associated with the request could not be executed because of the following reason:");
            sbuf.append(NEW_LINE);
            sbuf.append(NEW_LINE);
            if (objThrowable instanceof ThreadDeath) {
                sbuf.append("Error Message: Process was killed from the Web Service.");
                sbuf.append(NEW_LINE);
                sbuf.append(NEW_LINE);
                sbuf.append("Stack Trace: Not available.");

            } else {
                sbuf.append("Error Message: " + objThrowable.getMessage());
                sbuf.append(NEW_LINE);
                sbuf.append(NEW_LINE);
                sbuf.append("Stack Trace: " + exceptionToString(objThrowable));
            }
            sbuf.append(NEW_LINE);
            sbuf.append(NEW_LINE);
            sbuf.append("Corrective Action:");
            sbuf.append(NEW_LINE);
            sbuf.append(NEW_LINE);
            sbuf.append("\t\t Contact Support Team or Help Desk.");
            if (objThrowable instanceof ThreadDeath) {
                sbuf.append(" Please do not execute this process till you have a word with the support team.");
            }
            sbuf.append(NEW_LINE);
            email.setMessageBody(sbuf.toString());

            CMailer.getInstance(CSettings.get("pr.mailtype")).sendAsyncMail(email);
        } catch (Throwable e) {
            objEngineLogger_.error("Unable to send the Mail Message due to : ", e);
            // Need not be thrown. Email is a facility but not a necessity. Log
            // this error.
        }
    }

    /**
     * Sends a default mail to the monitor normal receipents named in
     * mail.properties.
     * 
     * @param pstrSubject
     *            String Mail subject.
     * @param pstrBody
     *            String Mail body.
     * @param bMethodIndicator
     *            True indicates message will be emailed through Asynchronous
     *            way.
     */
    private void sendDefaultMail(String pstrSubject, String pstrBody, boolean bMethodIndicator) {
        if (CSettings.get("pr.mailnotification", "OFF").equals("ON")) {
            try {
                // CMailer mailer =
                // CMailer.getInstance(CSettings.get("pr.mailtype", "SMTP"));
                EMail email = new EMail();
                email.setEMailId(Thread.currentThread() + "#" + System.currentTimeMillis());
                email.setTORecipient(CSettings.get("mail.monitor.normal.recepientTO", ""));
                email.setCCRecipient(CSettings.get("mail.monitor.normal.recepientCC", ""));
                email.setSubject(pstrSubject);
                email.setMessageBody(pstrBody);
                if (bMethodIndicator) {
                    CMailer.getInstance(CSettings.get("pr.mailtype")).sendAsyncMail(email);
                } else {
                    CMailer.getInstance(CSettings.get("pr.mailtype")).sendMail(email);
                }
            } catch (Throwable e) {
                objEngineLogger_.error("Exception while sending email", e);
                // Need not be thrown. Email is a facility but not a necessity.
                // Log this error.
            }
        }
    }

    /**
     * This method gets the status of all the currently running processes. If
     * the process implements {@link IProcessStatus} then the status is gathered
     * from the executed class.
     * 
     * @return Iterator of collection of {@link stg.pr.beans.CProcessStatusBean}
     */
    public Iterator<CProcessStatusBean> getProcessStatus() {
        ArrayList<CProcessStatusBean> alProcess = new ArrayList<CProcessStatusBean>();
        IJOBMonitor[] jobs = getStandAloneJobs();
        for (int i = 0; i < jobs.length; i++) {
            IJOBMonitor threadMonitor = jobs[i];
            Object obj = threadMonitor.getIntantiatedObject();
            ProcessRequestEntityBean objPRB = threadMonitor.getRequestBean();
            CProcessStatusBean objCPSB = new CProcessStatusBean();
            objCPSB.setStartTime(threadMonitor.getStartTime());
            objCPSB.setRequestId(objPRB.getReqId());
            objCPSB.setProcessName(objPRB.getJobId() + " - " + objPRB.getJobName());
            switch (threadMonitor.getJobStatus()) {
            case STUCK:
                objCPSB.setThreadStatus("Stuck. Warning!!");
                break;
            case CRITICAL:
                objCPSB.setThreadStatus("Stuck. Critical!!");
                break;
            default:
                objCPSB.setThreadStatus("Normal");
                break;
            }
            if (obj instanceof IProcessStatus) {
                IProcessStatus objStatus = (IProcessStatus) obj;
                try {
                    objCPSB.setStatus(objStatus.getStatus());
                } catch (Exception e) {
                    objCPSB.setStatus("Unable to determine the status. (Raised Exception)" + exceptionToString(e));
                    // this is again for information. Need not be thrown.
                }
            } else {
                objCPSB.setStatus("Status UnKnown. The class does not implement IProcessStatus.");
                // this is again for information. Need not be thrown.
            }
            alProcess.add(objCPSB);
        }
        return alProcess.iterator();
    }

    /**
     * Returns the Stack Trace.
     * 
     * @param throwable
     *            Throwable
     * @return String
     */
    private String exceptionToString(Throwable throwable) { // This method need
        // not synch as now
        // the bytes are
        // being created
        // within.
        ByteArrayOutputStream bytes_ = new ByteArrayOutputStream();
        PrintWriter pwException_ = new PrintWriter(bytes_, true);
        throwable.printStackTrace(pwException_);
        return bytes_.toString();
    }

    /**
     * Returns the version number of the class.
     * 
     * @return String
     */
    public String getVersion() {
        return REVISION;
    }

    /**
     * Returns the current timestamp.
     * 
     * The value is taken from Database if the property
     * <code>pr.currenttimestamp</code> is set to <b>DATABASE</b> otherwise the
     * server time where PRE is installed is returned. <b>By Default the Engine
     * will take the SERVER time where PRE is installed.</b>
     * 
     * @param con
     *            JDBC Connection
     * 
     * @return Current Timestamp
     * @throws SQLException
     * @throws IOException
     * @throws CDateException
     */
    private Timestamp getCurrentTimestamp(Connection con) throws CDateException, IOException, SQLException {
        if (CSettings.get("pr.currenttimestamp", "SERVER").equals("DATABASE")) {
            return CDate.getCurrentSQLTimestamp(con);
        }
        return new Timestamp((new Date()).getTime());
    }

    /**
     * Adds a job to the Stand Alone Process Vector.
     * 
     * Indicates that a new process has started.
     * 
     * @param t
     *            Job
     * @since 22.01
     */
    private synchronized void addStandAloneProcess(Thread t) {
        iThreadCounter_.incrementAndGet();
        vectorThreads_.add(t); // This is used while Termination of the Engine.
    }

    /**
     * Removes the job from the Stand Alone Process Vector.
     * 
     * Indicates that process has finished its job.
     * 
     * @param t
     *            Job
     * @since 22.01
     */
    private synchronized void removeStandAloneProcess(Thread t) {
        iThreadCounter_.decrementAndGet();
        vectorThreads_.remove(t); // This is used to remoce the thread.
    }

    /**
     * Adds a job to the Group Process Vector.
     * 
     * Indicates that a new process has started.
     * 
     * @param t
     *            Job
     * @since 22.01
     */
    private synchronized void addGroupProcess(Thread t) {
        iGrpThreadCounter_.incrementAndGet();
        vectorThreadsGroup_.add(t); // This is used while Termination of the
        // Engine.
    }

    /**
     * Removes a job from the Group Process Vector.
     * 
     * Indicates that a new process has started.
     * 
     * @param t
     *            Job
     * @since 22.01
     */
    private synchronized void removeGroupProcess(Thread t) {
        iGrpThreadCounter_.decrementAndGet();
        vectorThreadsGroup_.remove(t); // This is used while Termination of the
        // Engine.
    }

    /**
     * Returns the IJOBMonitor array for all the jobs in the Stand Alone Process
     * Vector.
     * 
     * @return Array of Jobs
     * @since 22.01
     */
    private synchronized IJOBMonitor[] getStandAloneJobs() {
        IJOBMonitor[] jobs = new IJOBMonitor[vectorThreads_.size()];
        for (int i = 0; i < jobs.length; i++) {
            jobs[i] = (IJOBMonitor) vectorThreads_.get(i);
        }
        return jobs;
    }

    /**
     * Creates a file that stores the message that needs to be passed to the
     * Controller.
     * 
     * This message can be for Bouncing or Rebooting the engine. Rebooting does
     * a clean shutdown of the engine where as in bounce, the engine simply
     * exits.
     * 
     * @param action
     * @param counter
     */
    private void createIniFile(String action, int counter) {
        String strTmpDir = System.getProperty("java.io.tmpdir");
        String strFileSeparator = System.getProperty("file.separator");
        if (!strTmpDir.endsWith(strFileSeparator)) {
            strTmpDir = strTmpDir + strFileSeparator;
        }
        File file = new File(strTmpDir + "pre.ini");
        try {
            PrintWriter ps = new PrintWriter(new FileWriter(file), true);
            ps.println("action=" + action);
            ps.println("counter=" + counter);
            ps.flush();
            ps.close();
        } catch (IOException e) {
        }
    }

    /**
     * Starts the web server if not started.
     * 
     * @return boolean True if started.
     */
    private boolean startWebServer() {
        if (!httpserver_.isStarted()) {
            /*
             * Starting the Web Services. The web server starts on the desired
             * port. If port not set then default port of 8080 is used.
             */
            if (CSettings.get("pr.webservice", "OFF").equals("ON")) {
                objEngineLogger_.log(LogLevel.NOTICE, "Starting Web Services");
                try {
                    httpserver_.start(Integer.parseInt(CSettings.get("pr.webserverport", "8080")));
                    while (!httpserver_.isStarted() && !httpserver_.isError()) {
                        // do nothing
                    }
                    if (httpserver_.isError()) {
                        objEngineLogger_.error("Unable to start the Web Service.", httpserver_.getError());
                    }
                    // httpserver_.start();
                } catch (NumberFormatException nfe) {
                    objEngineLogger_.error("Unable to start the Web Service. Invalid Port Number specified.", nfe);
                }
            }
        }
        return httpserver_.isStarted();
    }

    /**
     * Stops the web server is started.
     * 
     * @return boolean True if stopped.
     */
    private boolean stopWebServer() {
        if (httpserver_.isStarted()) {
            if (objEngineLogger_.isInfoEnabled()) {
                objEngineLogger_.info("Stopping Web Service");
            }
            httpserver_.stop();
        }
        return httpserver_.isStarted();
    }

    /**
     * Checks the other participating PRE in the cluster.
     */
    private void checkClusterPRE() {
        // String strAddressPort = CSettings.get("pr.clusteraddress", "");
        // if (strAddressPort.equals("")) {
        // objEngineLogger_.info("PRE is not configured in a cluster mode.");
        // bClusterHandShakeDone_ = true;
        // return;
        // }
        // if (!httpserver_.isStarted()) {
        // objEngineLogger_.info("Web Server is not started therefore PRE will not be able to check the cluster configuration");
        // objEngineLogger_.info("Web Server is a must for cluster configuration. Engine will terminate itself.");
        // bEngineTerminated_ = true;
        // bGroupedEngineTerminated_ = true;
        // tMain_.interrupt();
        // if (tEngine_ != null) {
        // tEngine_.interrupt();
        // }
        // bClusterHandShakeDone_ = true;
        // return;
        // }
        // String[] strAddressPortAry = strAddressPort.split(",");
        // if (strAddressPortAry.length == 0) {
        // objEngineLogger_.log(LogLevel.NOTICE,
        // "PRE is not configured in a cluster mode.");
        // bClusterHandShakeDone_ = true;
        // return;
        // }
        // for (int i = 0; i < strAddressPortAry.length; i++) {
        // if (strAddressPortAry[i] == null || strAddressPortAry[i].equals(""))
        // {
        // objEngineLogger_.error("Invalid cluster address configuration. Skipping Address "
        // + strAddressPortAry[i]);
        // } else {
        // objEngineLogger_.log(LogLevel.NOTICE,
        // "Doing handshake with the cluster PRE.. Address:Port#" +
        // strAddressPortAry[i]);
        // try {
        // PBEEncryptionRoutine routine = new PBEEncryptionRoutine();
        // String strRequest = routine.encode(getPRESignature());
        // if (objEngineLogger_.isEnabledFor(LogLevel.FINEST)) {
        // objEngineLogger_.log(LogLevel.FINEST, "presignature#" + strRequest);
        // }
        // String strVersionCheck = getURLOutput(strAddressPortAry[i],
        // "presignature=" + strRequest);
        //
        // strRequest = routine.encode(getQueueSignature());
        // if (objEngineLogger_.isEnabledFor(LogLevel.FINEST)) {
        // objEngineLogger_.log(LogLevel.FINEST, "queuesignature#" +
        // strRequest);
        // }
        // String strQueueCheck = getURLOutput(strAddressPortAry[i],
        // "queuesignature=" + strRequest);
        //
        // strRequest = routine.encode(getFilterSignature());
        // if (objEngineLogger_.isEnabledFor(LogLevel.FINEST)) {
        // objEngineLogger_.log(LogLevel.FINEST, "filtersignature#" +
        // strRequest);
        // }
        // String strFilterCheck = getURLOutput(strAddressPortAry[i],
        // "filtersignature=" + strRequest);
        // if (!strQueueCheck.equals("EQUALS") ||
        // !strVersionCheck.equals("EQUALS") ||
        // !strFilterCheck.equals("EQUALS")) {
        // objEngineLogger_.error("PRE Cluster configuration does not match. Please check the  "
        // +
        // "configuration...");
        // objEngineLogger_.log(LogLevel.NOTICE,
        // "Unable to start the PRE. PRE will exit.");
        // stopMessageForEmail_ =
        // "PRE Cluster configuration does not match. Please check the configuration.";
        // bEngineTerminated_ = true;
        // bGroupedEngineTerminated_ = true;
        // tMain_.interrupt();
        // if (tEngine_ != null) {
        // tEngine_.interrupt();
        // }
        // }
        // if (strVersionCheck.equals("EQUALS") &&
        // strQueueCheck.equals("EQUALS") && strFilterCheck.equals("EQUALS") ) {
        // // doURLInput(strAddressPortAry[i], getPRESignature());
        // objEngineLogger_.log(LogLevel.NOTICE,
        // "Another PRE is running against the same queue. Address:Port#" +
        // strAddressPortAry[i]);
        // stopMessageForEmail_ =
        // "Another PRE is running against the same queue. Address:Port#" +
        // strAddressPortAry[i];
        // bEngineTerminated_ = true;
        // bGroupedEngineTerminated_ = true;
        // tMain_.interrupt();
        // if (tEngine_ != null) {
        // tEngine_.interrupt();
        // }
        // }
        // } catch (IOException e) {
        // // subsequent PRE is not up. So continue.
        // } catch (CProcessRequestEngineException e) {
        // // subsequent PRE is not up. So continue.
        // }
        // }
        // } //end for
        bClusterHandShakeDone_ = true;
    }

    // /**
    // * Initiate handshake with the clustered PRE.
    // *
    // * @param strAddressPort
    // * @param strQuery
    // * @throws MalformedURLException
    // * @throws IOException
    // * @throws CProcessRequestEngineException
    // */
    // private String getURLOutput(String strAddressPort, String strQuery)
    // throws MalformedURLException, IOException, CProcessRequestEngineException
    // {
    // String strReturn = "Unknown";
    // BufferedReader reader = null;
    // StringBuffer buffer = new StringBuffer();
    // buffer.append("http://");
    // buffer.append(strAddressPort);
    // buffer.append("/status?");
    // buffer.append(strQuery);
    // //Exception must be thrown inorder to stop the PRE requesting the
    // clustered PRE to stop.
    // try {
    // URL url = new URL(buffer.toString());
    // HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();
    // objEngineLogger_.info("Handshake initiated...");
    // urlCon.setDoInput(true);
    // urlCon.setDoOutput(true);
    // reader = new BufferedReader(new
    // InputStreamReader(urlCon.getInputStream()));
    // strReturn = reader.readLine();
    // objEngineLogger_.log(LogLevel.FINEST, "Return Value# " + strReturn);
    // // if (strReturn.equals("MISMATCH")) {
    // // objEngineLogger_.log(LogLevel.NOTICE,
    // "Clustered PRE configuration does not match. Please correct the configuration. Cannot initiate stop request.");
    // // throw new CProcessRequestEngineException();
    // // } else if (strReturn.equals("EQUALS")) {
    // // objEngineLogger_.info("Configuration matched...");
    // // objEngineLogger_.info("Requesting stop....");
    // // } else {
    // //
    // objEngineLogger_.error("Unable to determine the response. Cannot initiate stop request.");
    // // throw new CProcessRequestEngineException();
    // // }
    // } catch (MalformedURLException e) {
    // objEngineLogger_.error("Malformed URL. Cluster address is not configured properly.");
    // objEngineLogger_.log(LogLevel.NOTICE,
    // "Unable to do the handshake with the clustered PRE.");
    // if (objEngineLogger_.isEnabledFor(LogLevel.FINER)) {
    // objEngineLogger_.log(LogLevel.FINER, "MalformedURLException", e);
    // }
    // throw e;
    // } catch (ConnectException e) {
    // objEngineLogger_.error("ConnectException. Clustered PRE not up.");
    // objEngineLogger_.log(LogLevel.NOTICE,
    // "Unable to do the handshake with the clustered PRE.");
    // if (objEngineLogger_.isEnabledFor(LogLevel.FINER)) {
    // objEngineLogger_.log(LogLevel.FINER, "ConnectException", e);
    // }
    // throw e;
    // }catch (IOException e) {
    // objEngineLogger_.error("Received IO Exception.");
    // objEngineLogger_.log(LogLevel.NOTICE,
    // "Unable to do the handshake with the clustered PRE.");
    // if (objEngineLogger_.isEnabledFor(LogLevel.FINER)) {
    // objEngineLogger_.log(LogLevel.FINER, "IOException", e);
    // }
    // throw e;
    // } finally {
    // if (reader != null) {
    // try {
    // reader.close();
    // } catch (IOException e) {
    // }
    // }
    // }
    // return strReturn;
    // }

    // /**
    // * Requests stop request to the clustered PRE.
    // * @param strAddressPort
    // * @param strQuery
    // */
    // private void doURLInput(String strAddressPort, String strQuery) {
    // BufferedReader reader = null;
    // StringBuffer buffer = new StringBuffer();
    // buffer.append("http://");
    // buffer.append(strAddressPort);
    // buffer.append("/stop?");
    // buffer.append(strQuery);
    // try {
    // URL url = new URL(buffer.toString());
    // HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();
    // urlCon = (HttpURLConnection) url.openConnection();
    // urlCon.setDoInput(true);
    // urlCon.setDoOutput(true);
    // reader = new BufferedReader(new
    // InputStreamReader(urlCon.getInputStream()));
    // String str = reader.readLine();
    // if (str.equals("STOPPED")) {
    // objEngineLogger_.log(LogLevel.NOTICE,
    // "Clustered PRE stopped successfully. Currently running JOBs will not be terminated.");
    // }
    // } catch (MalformedURLException e) {
    // objEngineLogger_.error("Malformed URL. Cluster address is not configured properly");
    // objEngineLogger_.log(LogLevel.NOTICE,
    // "Please check the clustered PRE manually. Unable to do handshake.");
    // if (objEngineLogger_.isEnabledFor(LogLevel.FINER)) {
    // objEngineLogger_.log(LogLevel.FINER, "MalformedURLException", e);
    // }
    // // exceptionToString(e);
    // } catch (IOException e) {
    // objEngineLogger_.error("IO Exception. Cluster address is not configured properly");
    // // exceptionToString(e);
    // objEngineLogger_.log(LogLevel.NOTICE,
    // "Please check the clustered PRE manually. Unable to do handshake.");
    // if (objEngineLogger_.isEnabledFor(LogLevel.FINER)) {
    // objEngineLogger_.log(LogLevel.FINER, "IOException", e);
    // }
    // } finally {
    // if (reader != null) {
    // try {
    // reader.close();
    // } catch (IOException e) {
    // }
    // }
    // }
    // }

    // /**
    // * Generates the Signature for filter conditions.
    // *
    // * @return PRE Singature
    // */
    // public String getFilterSignature() {
    // // int iSignature = -1;
    // objEngineLogger_.log(LogLevel.FINEST, "Generating Signature..");
    // StringBuffer buffer = new StringBuffer();
    // buffer.append(CSettings.get("pr.requesttypefilter"));
    // buffer.append("#");
    // buffer.append(CSettings.get("pr.processrequesttype"));
    // buffer.append(REVISION);
    // return buffer.toString();
    // }
    //
    // /**
    // * Generates the Signature for queue.
    // *
    // * @return PRE Singature
    // */
    // public String getQueueSignature() {
    // // int iSignature = -1;
    // objEngineLogger_.log(LogLevel.FINEST, "Generating Signature..");
    // // S =
    // dataSourceFactory_.getDataSource(CSettings.get("pr.dsforstandaloneeng")).getClass().getName();
    // // StringBuffer buffer = new StringBuffer();
    // // CPoolAttribute attributes =
    // poolManager_.getPoolAttributes(CSettings.get("pr.dsforstandaloneeng"));
    // // buffer.append(attributes.getURL());
    // // buffer.append(attributes.getUser());
    // //// buffer.append(attributes.getPassword()); //With new PBE algorithm in
    // JDBCPool the encrypted password will not be the same.
    // // buffer.append(attributes.getDriver());
    // // attributes =
    // poolManager_.getPoolAttributes(CSettings.get("pr.dsforgroupeng"));
    // // buffer.append(attributes.getURL());
    // // buffer.append(attributes.getUser());
    // //// buffer.append(attributes.getPassword()); //With new PBE algorithm in
    // JDBCPool the encrypted.
    // // buffer.append(attributes.getDriver());
    // // iSignature = buffer.toString().hashCode();
    // // buffer.delete(0, buffer.length());
    // // buffer.append("queuesignature=");
    // return "9810818y516dj17t418hoin13y6661001";
    // }
    //    
    // /**
    // * Generates the Signature for PRE.
    // *
    // * @return PRE Singature
    // */
    // public String getPRESignature() {
    // objEngineLogger_.log(LogLevel.FINEST, "Generating Signature..");
    // StringBuffer buffer = new StringBuffer();
    // buffer.append(strBundleDetailsArray_[0]);
    // buffer.append(strBundleDetailsArray_[1]);
    // buffer.append(strBundleDetailsArray_[2]);
    // return buffer.toString();
    // }

    /**
     * Refreshes the JDBC connection.
     * 
     * The method will check the passed connection if it is active. If found
     * active it will throw an exception. This method should be called only when
     * an IO or SQLException is received. The method expects that the passed
     * connection is not active.
     * 
     * The method then returns the connection to the pool and tries to get a new
     * connection from the pool identified by the parameter
     * <code>pstrPoolIdentifier</code>. This is done for <code>iTries</code>.
     * Even after the said tires if the JDBC connection is not refreshed then
     * the method throws an exception.
     * 
     * @param iTries
     *            Number of tries the method should do the refresh.
     * @param pcon
     *            Inactive JDBC Connection.
     * @param pstrPoolIdentifier
     *            Pool Identifier.
     * @return Connection
     * @throws Exception
     */
    private Connection refreshJDBCConnection(int iTries, Connection pcon, String pstrPoolIdentifier)
            throws Exception {
        try {
            // if (pcon instanceof jdbc.tuning.ConnectionWrapper) {
            // ConnectionWrapper wrapper = (ConnectionWrapper) pcon;
            // if (wrapper.isActive()) {
            // throw new
            // CProcessRequestEngineException("Connection is active.");
            // }
            // }
            pcon.close();
        } catch (SQLException sqle) {
            // dummy catch.
        }
        Exception exception = null;
        Connection con = null;
        for (int i = 0; i < iTries; i++) {
            if (objEngineLogger_.isInfoEnabled()) {
                objEngineLogger_
                        .info("Waiting for #" + lWaitInterval_ + " Seconds before refreshing the JDBC Connection");
            }
            try {
                Thread.yield();
                TimeUnit.SECONDS.sleep(lWaitInterval_);
                // Thread.sleep(lWaitInterval_);
            } catch (InterruptedException ie) {
                // do nothing
            }
            exception = null;
            if (objEngineLogger_.isDebugEnabled()) {
                objEngineLogger_.debug("Refreshing JDBCConnection. Try #" + (i + 1) + " of #" + iTries);
            }
            // it is expected to get exceptions.
            try {
                // con = poolManager_.getConnection(pstrPoolIdentifier);
                con = dataSourceFactory_.getDataSource(pstrPoolIdentifier).getConnection();
                if (objEngineLogger_.isDebugEnabled()) {
                    objEngineLogger_.debug("JDBCConnection refreshed...Restarting the infinite loop.");
                }
            } catch (SQLException sqle) {
                exception = sqle;
            } catch (IOException ioe) {
                exception = ioe;
            } catch (Exception e) {
                exception = e;
            }
            if (con != null)
                return con;
            if (objEngineLogger_.isDebugEnabled()) {
                objEngineLogger_.debug("Unable to refresh JDBCConnection even after attempt #" + (i + 1));
            }
        }
        throw exception;
    }

    /**
     * Kills the given process.
     * 
     * @param strRequestId
     * @param strUserId
     * @param strReason
     * @return ProcessRequestEntityBean
     */
    @SuppressWarnings("deprecation")
    protected synchronized ProcessRequestEntityBean killProcess(String strRequestId, String strUserId,
            String strReason) {
        for (Iterator<Thread> iterator = vectorThreads_.iterator(); iterator.hasNext();) {
            ThreadProcess tp = (ThreadProcess) iterator.next();
            ProcessRequestEntityBean bean = tp.getRequestBean();
            if (strRequestId.equals(bean.getReqId() + "")) {
                try {
                    objEngineLogger_.log(LogLevel.NOTICE, "JOB " + strRequestId + " is being terminated by user#"
                            + strUserId + " for reason " + strReason);
                    tp.stop();
                } catch (Throwable t) {
                }
                return bean;
            }
        }
        return null;
    }

    /**
     * Returns the {@link PREContext}.
     * 
     * @return PREContext
     */
    protected PREContext getContext() {
        return context_;
    }

    //   /**
    //    * Reads the license information.
    //    * 
    //    * @return license contents.
    //    * @throws Exception
    //    */
    //   private LicenseContent readLicense() throws Exception {
    //      LicenseManager lm = new LicenseManager(new LicenseParamImpl());
    //      return lm.verify();
    //   }

    //   /**
    //    * Installs the license.
    //    * 
    //    * @throws Exception
    //    */
    //   private void installLic() throws Exception {
    //      LicenseManager lm = new LicenseManager(new LicenseParamImpl());
    //      File licenseFile = new File(CSettings.get("pr.licensefile",
    //            "pre.license"));
    //      lm.install(licenseFile);
    //   }

    /**
     * @param st
     */
    private void closeSQLStatement(Statement st) {
        if (st == null)
            return;
        try {
            st.close();
        } catch (Throwable t) {
        }
    }

    /**
     * Invokes logical stop on the given process if the process has implemented
     * {@link ITerminateProcess}.
     * 
     * @param strRequestId
     * @param userId
     * @param reason
     * @return boolean True indicates the invoke of stop was a success otherwise
     *         false.
     */
    protected synchronized boolean invokeStopProcess(String strRequestId, String userId, String reason) {
        for (Iterator<Thread> iterator = vectorThreads_.iterator(); iterator.hasNext();) {
            ThreadProcess tp = (ThreadProcess) iterator.next();
            ProcessRequestEntityBean bean = tp.getRequestBean();
            if (userId == null || "".equals(userId)) {
                userId = "Not Supplied";
            }
            if (reason == null || "".equals(reason)) {
                reason = "User requested";
            }
            if (strRequestId.equals(bean.getReqId() + "")) {
                if (tp.getIntantiatedObject() instanceof ITerminateProcess) {
                    if (objEngineLogger_.isInfoEnabled()) {
                        objEngineLogger_.info("Requesting USER Logical Termination of job \""
                                + ((tp.getRequestBean().getJobId() == null) ? ""
                                        : tp.getRequestBean().getJobId().toUpperCase(Locale.US))
                                + "\" Request #" + strRequestId + " UserId #" + userId + " Reason : " + reason);
                    }
                    ((ITerminateProcess) tp.getIntantiatedObject()).terminate(reason);
                    tp.setJobStatus(JOB_STATUS.TOBETERMINATED);
                    return true;
                } else {
                    throw new RuntimeException("JOB does not implement ITerminateProcess process.");
                }
            }
        }
        return false;
    }

    /**
     * Returns true if to be rebooted.
     * 
     * @return boolean
     */
    protected boolean isReboot() {
        return bReBoot.get();
    }

    /**
     * Sets the reboot flag.
     * 
     * @param reboot
     * @return boolean
     */
    protected boolean setReboot(boolean reboot) {
        bReBoot.set(reboot);
        return reboot;
    }

    /**
     * Returns the sleep time.
     * 
     * @return long
     */
    protected long getRebootSleepTime() {
        return lRebootSleepTime;
    }

    /**
     * Set the sleep time.
     * 
     * @param lrebootsleeptime
     */
    protected void setRebootSleepTime(long lrebootsleeptime) {
        lRebootSleepTime = lrebootsleeptime;
    }

    /**
     * Returns the maximum reboot counter.
     * 
     * @return int
     */
    protected int getRebootMaxCounter() {
        return lRebootMaxCounter;
    }

    /**
     * Sets the reboot maximum counter.
     * 
     * @param lrebootmaxcounter
     */
    protected void setRebootMaxCounter(int lrebootmaxcounter) {
        lRebootMaxCounter = lrebootmaxcounter;
    }

    /**
     * Returns the current reboot counter.
     * 
     * @return int
     */
    protected int getRebootCounter() {
        return iRebootCounter.get();
    }

    /**
     * Sets the current reboot counter.
     * 
     * @param irebootcounter
     */
    protected void setRebootCounter(int irebootcounter) {
        iRebootCounter.set(irebootcounter);
    }

    /**
     * Activates the engine for the given state.
     * 
     * @param state
     */
    public void activate(HeartBeatState state) {
        objEngineLogger_.info("Activating state " + state.name() + " ...");
        synchronized (instance_) {
            if (state_ != state) {
                state_ = state;
                instance_.notifyAll();
            }
        }
    }

    /**
     * Deactivates the engine and plungs into un-conditional wait till activate
     * is called.
     */
    public void deactivate() {
        synchronized (instance_) {
            try {
                while (state_ == HeartBeatState.PASSIVE) {
                    instance_.wait();
                }
            } catch (InterruptedException e) {
                // do nothing.
            }
        }
    }

    /**
     * Returns the current heart beat state.
     * 
     * @return HeartBeatState
     */
    public HeartBeatState getHeartBeatState() {
        return state_;
    }

    private StringBuffer getDefaultEmailAttributes() {
        StringBuffer sbuffer = new StringBuffer(100);
        sbuffer.append("Product Name          :");
        sbuffer.append(info.getName());
        sbuffer.append(NEW_LINE);
        sbuffer.append("Product Version       :");
        sbuffer.append(info.getVersion());
        sbuffer.append(NEW_LINE);
        sbuffer.append("Packaged On           :");
        sbuffer.append(info.getBundledOn());
        sbuffer.append(NEW_LINE);
        sbuffer.append("Cluster Node          :");
        sbuffer.append(member_.getInetSocketAddress().toString());
        sbuffer.append(NEW_LINE);
        if (state_ != HeartBeatState.STOP) {
            try {
                sbuffer.append("Cluster Participants  :");
                for (String member : Hazelcast.getConfig().getNetworkConfig().getJoin().getTcpIpConfig()
                        .getMembers()) {
                    sbuffer.append("[");
                    sbuffer.append(member);
                    sbuffer.append("];");
                }
            } catch (IllegalStateException e) {
                sbuffer.append("Unable to retrieve as Cluster is being shutdown");
            }
        } else {
            sbuffer.append("Cluster Operation  : Shutdown");
        }
        sbuffer.append(NEW_LINE);
        return sbuffer;
    }

    /**
     * Prints all possible memory leaks. The caller should check if this
     * instance is the only instance on the cluster topology.
     */
    private void printPossibleMemoryLeaks() {
        for (Iterator<String> enumerator = context_.getAttributeNames().iterator(); enumerator.hasNext();) {
            String str = enumerator.next();
            System.err.println("Possible Memory Leak [Key#" + str + "\t Object#"
                    + context_.getAttribute(str).getClass().getName() + "]");
        }
    }

    /**
     * Creates or update the request on Retry.
     * 
     * @param pcon
     * @param prBean
     * @param pobjParamsEb
     * @param pobjDdcParams
     * @param pobjPrCont
     * @param pobjParamsCont
     * @return request id
     * @throws SQLException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    private long proCreateRetry(Connection pcon, ProcessRequestEntityBean prBean,
            ProcessReqParamsEntityBean pobjParamsEb, CDynamicDataContainer pobjDdcParams,
            ProcessRequestController pobjPrCont, ProcessReqParamsController pobjParamsCont)
            throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        boolean procreate = "CREATE".equals(CSettings.get("pr.retryOption", "UPDATE"));
        IRequestIdGenerator generator = null;
        long newRequestId = -1L;
        try {
            if (procreate) {
                Class<?> objClass = this.getClass().getClassLoader()
                        .loadClass(CSettings.get("pr.schedulerequestidgenerator"));
                Object obj = objClass.newInstance();
                if (obj instanceof IRequestIdGenerator) {
                    generator = (IRequestIdGenerator) obj;
                } else {
                    throw new ClassCastException("");
                }
                generator.setConnection(pcon);
                newRequestId = generator.generateRequestId();
            }
            ProcessRequestEntityBean prEBean;
            if (procreate) {
                prEBean = (ProcessRequestEntityBean) prBean.clone();
            } else {
                prEBean = prBean;
            }
            prEBean.setRStatus(false);
            if (procreate)
                prEBean.setReqId(newRequestId);
            prEBean.setReqStat(REQUEST_STATUS.QUEUED.getID());
            Day day = new Day(prBean.getScheduledTime());
            TimeUnit unit = TimeUnit.valueOf(prBean.getRetryTimeUnit());
            if (unit == TimeUnit.MINUTES) {
                day.advance(Calendar.MINUTE, prBean.getRetryTime());
            } else {
                day.advance(Calendar.HOUR_OF_DAY, prBean.getRetryTime());
            }
            prEBean.setScheduledTime(day.getTimestamp());
            prEBean.setRetryCnt(prEBean.getRetryCnt() + 1);
            pcon.setAutoCommit(false);
            if (procreate) {
                pobjPrCont.create(prEBean);
            } else {
                pobjPrCont.update(prEBean);
            }
            if (procreate) {
                pobjDdcParams.beforeFirst();
                while (pobjDdcParams.next()) {
                    ProcessReqParamsEntityBean paramsEBean = (ProcessReqParamsEntityBean) ((ProcessReqParamsEntityBean) pobjDdcParams
                            .get()).clone();
                    paramsEBean.setRStatus(false);
                    paramsEBean.setReqId(newRequestId);
                    pobjParamsCont.create(paramsEBean);
                }

            }
            pcon.commit();
            pcon.setAutoCommit(true);
        } catch (ClassNotFoundException cnfe) {
            throw cnfe;
        } catch (CBeanException e) {
            throw new SQLException(e);
        } catch (CDynamicDataContainerException e) {
            throw new SQLException(e);
        } finally {
            if (pcon != null) {
                pcon.setAutoCommit(true);
            }
        }
        return newRequestId;
    }

} // end of CProcessRequestEngine.java