com.pari.nm.modules.jobs.PcbImportJob.java Source code

Java tutorial

Introduction

Here is the source code for com.pari.nm.modules.jobs.PcbImportJob.java

Source

package com.pari.nm.modules.jobs;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.Key;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.io.FileUtils;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import sun.misc.BASE64Decoder;

import com.pari.api.utils.HeuristicDescriptor;
import com.pari.base.so.DiscoveredDevice;
import com.pari.base.so.defs.IPAddressBase;
import com.pari.ic.ICEntity;
import com.pari.jelly.beans.Device;
import com.pari.jms.events.PerDeviceConfigBackupStatus;
import com.pari.jms.events.PerDeviceImportStatus;
import com.pari.logger.PariLogger;
import com.pari.logger.PariLoggerFactory;
import com.pari.nm.events.ConfigBackupEventHandler;
import com.pari.nm.events.DeviceImportEventHandler;
import com.pari.nm.events.EventManager;
import com.pari.nm.gui.guimessages.JobStatus;
import com.pari.nm.gui.guimessages.PcbImportJobStatus;
import com.pari.nm.gui.guimessages.ZIPImportFileResultMsg;
import com.pari.nm.gui.guiservices.FTPServerType;
import com.pari.nm.gui.guiservices.FtpServerDetails;
import com.pari.nm.modules.cspc.ConnectionStatusEnum;
import com.pari.nm.modules.cspc.CspcConnectionStatusDetails;
import com.pari.nm.modules.cspc.CspcConnectionStatusThread;
import com.pari.nm.modules.cspc.CspcInfoManager;
import com.pari.nm.modules.cspc.CspcXMLUtils;
import com.pari.nm.modules.customers.Customer;
import com.pari.nm.modules.customers.CustomerInstance;
import com.pari.nm.modules.customers.CustomerManager;
import com.pari.nm.modules.customers.CustomerWingInstanceManager;
import com.pari.nm.modules.inventory.HeuristicManager;
import com.pari.nm.modules.messaging.Messenger;
import com.pari.nm.modules.msgdefs.JobStatusIf;
import com.pari.nm.modules.msgdefs.MessageTypes;
import com.pari.nm.modules.msgdefs.PcbImportJobMsg;
import com.pari.nm.modules.msgdefs.VirtualDeviceRefresh;
import com.pari.nm.modules.parser.config.VoipPhone;
import com.pari.nm.modules.session.ClientSessionManager;
import com.pari.nm.modules.session.UserDetails;
import com.pari.nm.modules.session.UsersFactory;
import com.pari.nm.modules.topology.DeviceManager;
import com.pari.nm.utils.Constants;
import com.pari.nm.utils.ServerAuditConstants;
import com.pari.nm.utils.ServerAuditLog;
import com.pari.nm.utils.backup.PariFTP;
import com.pari.nm.utils.backup.PariSFTP;
import com.pari.nm.utils.backup.SCPHandler;
import com.pari.nm.utils.backup.TFTPHandler;
import com.pari.nm.utils.db.InventoryDBHelper;
import com.pari.nm.utils.db.ServerDBHelper;
import com.pari.nm.utils.db.VOIPDBHelper;
import com.pari.pcb.PCBFile;
import com.pari.pcb.PCBFileIf;
import com.pari.pcb.ZIP2PCBv2Converter;
import com.pari.pcb.zip.ZIPProcessor;
import com.pari.pcb.zip.ZIPProcessorProgressListener;
import com.pari.reports.custom.NCCMCustomReportHandler;
import com.pari.reports.custom.management.ReportDefManagerImpl;
import com.pari.server.ServerProperties;
import com.pari.swim.ScriptInfo;
import com.pari.swim.ScriptInfo.ScriptType;
import com.pari.utils.xml.XMLUtil;

public class PcbImportJob implements JobStatusIf, Job {
    int jobId;
    int jobRunId;
    String[] keys;
    String pcbFileName;
    String grpName;
    int customerId = -1;
    int instanceId = -1;
    String wingInstanceName = null;
    String customerName = null;
    Customer customer = null;
    CustomerInstance cInst = null;
    int uId;
    String login;
    int noOfVirtsAdded = 0;
    static PariLogger logger = null;
    int state;
    Set<String> devs = Collections.synchronizedSet(new HashSet<String>());
    int noThreads = Constants.NO_OF_PCB_IMPORT_THREADS;
    List<VirtualDeviceRefresh> virtsAdded = new Vector<VirtualDeviceRefresh>();
    // static Map<String, String> currentCustomerJobs = new HashMap<String, String>();
    static ConcurrentHashMap<String, AtomicInteger> currentCustomerJobTokens = new ConcurrentHashMap<String, AtomicInteger>();
    static ConcurrentHashMap<String, PriorityBlockingQueue<Integer>> runnableTokens = new ConcurrentHashMap<String, PriorityBlockingQueue<Integer>>();
    static ConcurrentHashMap<String, Integer> currentCustomerRunningToken = new ConcurrentHashMap<String, Integer>();
    String custWingUniqueId = "";
    int token = 0;
    String profileName = null;
    int nccmJobId = -1;
    int nccmJobRunId = -1;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {

        long t = System.currentTimeMillis();
        // to give enough time for client to register for the jobstatus messages
        try {
            Thread.sleep(5000);
        } catch (Exception ee) {
        }
        logger = PariLoggerFactory.getLogger(Constants.NM_LOGGER);
        JobDetail job = context.getJobDetail();
        jobId = InventoryDBHelper.getJobId(job.getName(), job.getGroup());
        jobRunId = job.getJobDataMap().getInt("jobrunid");
        keys = (String[]) job.getJobDataMap().get("PCBSelectedDevices");
        int numDevs = (keys == null) ? 0 : keys.length;
        pcbFileName = (String) job.getJobDataMap().get("PCBFileName");
        grpName = (String) job.getJobDataMap().get("GroupName");
        login = (String) job.getJobDataMap().get("login");
        uId = ((Integer) job.getJobDataMap().get("userId")).intValue();
        customerId = ((Integer) job.getJobDataMap().get("CustomerID")).intValue();
        wingInstanceName = (String) job.getJobDataMap().get("WingInstanceName");
        custWingUniqueId = customerId + "_" + wingInstanceName;
        int row_id = -1;
        int version = -1;
        Key key = null;
        Map<String/* deivceIp */, PerDeviceImportStatus> perDeviceImportStatus = null;
        Map<String/* deivceIp */, PerDeviceConfigBackupStatus> perDeviceConfigBackupStatus = null;
        nccmJobId = ((Integer) job.getJobDataMap().get("nccmJobId")).intValue();
        nccmJobRunId = ((Integer) job.getJobDataMap().get("nccmJobRunId")).intValue();
        profileName = (String) job.getJobDataMap().get("profileName");

        // Fix for Duplicate device issue with parallel device import jobs for same customer
        // For a customer, only 1 import job will run at a time and other jobs need to wait until previous
        // import jobs are done.
        if (currentCustomerJobTokens.containsKey(custWingUniqueId)) {
            token = currentCustomerJobTokens.get(custWingUniqueId).incrementAndGet();
            logger.debug("The token for customer " + customerId + " is " + token);
            runnableTokens.get(custWingUniqueId).offer(token);
        } else {
            AtomicInteger retVal = currentCustomerJobTokens.putIfAbsent(custWingUniqueId, new AtomicInteger(0));
            // This can happen first time if two threads simultaneously try to put value in currentCustomerJobTokens
            // If one thread puts the value, other thread will get some return value...
            if (retVal != null) {
                token = currentCustomerJobTokens.get(custWingUniqueId).incrementAndGet();
                runnableTokens.get(custWingUniqueId).offer(token);
            } else {
                PriorityBlockingQueue<Integer> pbq = new PriorityBlockingQueue<Integer>();
                runnableTokens.put(custWingUniqueId, pbq);
                pbq.offer(token);
            }
            currentCustomerRunningToken.put(custWingUniqueId, -1);
            logger.debug("The token for customer " + customerId + " is " + token);
        }

        if (runnableTokens.get(custWingUniqueId) != null) {
            if (currentCustomerRunningToken.get(custWingUniqueId) == -1) {
                currentCustomerRunningToken.put(custWingUniqueId, runnableTokens.get(custWingUniqueId).peek());
            }

            if (runnableTokens.get(custWingUniqueId).peek() != currentCustomerRunningToken.get(custWingUniqueId)) {
                logMsg("Waiting for previous VSEM Import Jobs on same customer to finish.");

                while (runnableTokens.get(custWingUniqueId).peek() != currentCustomerRunningToken
                        .get(custWingUniqueId)) {
                    try {
                        Thread.sleep(1 * 60 * 1000);
                    } catch (Exception e) {
                        logger.error("Error while waiting for VSEM Jobs to finish...", e);
                    }
                }
            }

            // removing the head of queue
            runnableTokens.get(custWingUniqueId).poll();
        }

        try {
            String zipFileName = job.getJobDataMap().getString("ZIPFILE");
            PCBFileIf pcbFile = null;
            if (customerId >= 0) {
                row_id = ServerDBHelper.insertPcbImportLog(customerId, System.currentTimeMillis(),
                        "NCCM Device file import is in progress.", wingInstanceName);
                try {
                    processCustomerAndInstance(row_id);
                } catch (Exception ex) {
                    logger.error("Exception while processing customer instance information", ex);
                    return;
                }
            }
            if (zipFileName != null) {
                logger.debug("Processing zip file:" + zipFileName);
                PcbImportJobStatus jobStatus = new PcbImportJobStatus(jobId, jobRunId, 10, "Processing zip file.",
                        JobStatus.RUNNING);
                ClientSessionManager.getInstance().sendJobStatusMessages(jobId, jobStatus);

                ZIPImportListener zipListener = new ZIPImportListener();
                logger.debug("processing zip file : " + zipFileName + " Job: " + jobId + " Runid: " + jobRunId);
                ZIPProcessor zipProcessor = ZIPProcessor.open(new File(zipFileName), zipListener, customerId);
                try {
                    while (zipListener.inProgress) {
                        Thread.sleep(3000);
                    }
                    String err = zipProcessor.getErrorMessage();
                    if (err != null && !err.isEmpty()) {
                        context.setResult("Completed");
                        JobRun.logJobCompletionStatus(jobId, jobRunId, false);
                        jobStatus = new PcbImportJobStatus(jobId, jobRunId, 100, err, JobStatus.FAILED);
                        logMsg(err); // CSCua41383
                        // CSCua44590: Customer upload summary shows wrong msg when an invalid file is imported
                        ServerDBHelper.updatePcbImportLog(customerId, row_id, err);
                        ClientSessionManager.getInstance().sendJobStatusMessages(jobId, jobStatus);
                        return;
                    }
                    String[] deviceNames = zipProcessor.getDeviceNames();
                    int numZipDevs = (deviceNames == null) ? 0 : deviceNames.length;
                    ZIPImportFileResultMsg msg = new ZIPImportFileResultMsg(jobId, jobRunId, 10,
                            "ZIP Import successful", zipProcessor.getFileResultMap(), zipProcessor.getNumEntries(),
                            numZipDevs, zipProcessor.getErrorMessage(), zipProcessor.getWarningMessage());
                    ClientSessionManager.getInstance().sendJobStatusMessages(jobId, msg);
                    if (deviceNames == null || numZipDevs == 0) {
                        context.setResult("Completed");
                        JobRun.logJobCompletionStatus(jobId, jobRunId, false);
                        // CSCua44590: Updated the Displaying Message.
                        ServerDBHelper.updatePcbImportLog(customerId, row_id,
                                "Unable to find any valid devices in the zip file.");
                        jobStatus = new PcbImportJobStatus(jobId, jobRunId, 100,
                                "Unable to find any valid devices in the zip file.", JobStatus.FAILED);
                        logMsg("Unable to find any valid devices in the zip file."); // CSCua41383
                        ClientSessionManager.getInstance().sendJobStatusMessages(jobId, jobStatus);
                        return;
                    }
                    jobStatus = new PcbImportJobStatus(jobId, jobRunId, 10,
                            "Processed ZIP file. Found out " + numZipDevs + " devices from "
                                    + zipProcessor.getNumEntries() + " files. Converting to VSEM file.",
                            JobStatus.RUNNING);
                    ClientSessionManager.getInstance().sendJobStatusMessages(jobId, jobStatus);

                    logger.debug("Zip processing done for file: " + zipFileName + " Job: " + jobId + " Runid: "
                            + jobRunId);
                    List<HeuristicDescriptor> heus = HeuristicManager.getInstance()
                            .getHeuristics(PCBFile.DEVICE_FAMILY);
                    File f = new File(zipFileName);
                    File f1 = f.getParentFile();
                    File f2 = new File(f1, "TEMP");
                    f2.mkdir();
                    File f3 = new File(f2, "PCB_" + System.nanoTime());
                    f3.mkdir();
                    pcbFileName = f3.getAbsolutePath();
                    ZIP2PCBv2Converter converter = new ZIP2PCBv2Converter();
                    converter.exportToVSEMFile(zipProcessor, f3, null, heus);
                    logger.debug("Exported to VSEM file");
                    jobStatus = new PcbImportJobStatus(jobId, jobRunId, 10, "Exported "
                            + zipProcessor.getDeviceNames().length + " devices to VSEM file. Starting import...",
                            JobStatus.RUNNING);
                    ClientSessionManager.getInstance().sendJobStatusMessages(jobId, jobStatus);
                    version = 2;
                    f.delete(); // CSCtz18817
                } finally {
                    zipProcessor.cleanup();
                }
            } else {
                key = getKey(customerId);
                logger.debug("Checking PCB Version for file: " + pcbFileName);
                try {
                    version = getPCBFileVersion(pcbFileName, key);
                } catch (Exception ex) {
                    // CSCtz03087:Job State not getting populated properly in Inventory job logs
                    context.setResult("Completed");
                    JobRun.logJobCompletionStatus(jobId, jobRunId, false);
                    PcbImportJobStatus jobStatus = new PcbImportJobStatus(jobId, jobRunId, 100,
                            "Not a valid PCB/VSEM File", JobStatus.FAILED);
                    logMsg("Not a valid PCB/VSEM File"); // CSCua41383
                    // CSCua44590: Customer upload summary shows wrong msg when an invalid file is imported
                    ServerDBHelper.updatePcbImportLog(customerId, row_id, "Not a valid PCB/VSEM File");
                    ClientSessionManager.getInstance().sendJobStatusMessages(jobId, jobStatus);
                    return;
                }
                logger.debug("Found out PCB Version in pcb File: " + pcbFileName + " to be " + version);
            }
            PcbImportJobMsg pcbImMsg = null;
            if (version == 1) {
                pcbFile = processPcbV1(key);
                logger.debug("Job: " + jobId + " Number of thread for PCB import: " + noThreads);
                pcbImMsg = new PcbImportJobMsg(keys, pcbFile, customerId, grpName, wingInstanceName, this, row_id);
                numDevs = (keys == null) ? 0 : keys.length;
                Messenger.getInstance().publish(MessageTypes.TRIGGER_PCBIMPORT, pcbImMsg);
            } else {
                try {
                    String login = "Unknown " + uId;
                    UserDetails user = UsersFactory.getUser(uId);
                    if (user != null) {
                        login = user.getLogin();
                    }
                    // Pass jobId also so that DeviceAdder where device list is prepared for custom reports can maintain
                    // map of jobId and device list. This will make sure things work fine in case of parallel vsem
                    // imports.

                    UserDetails historyUserObj = UsersFactory.getUser(InventoryDBHelper.getJobCreatorId(nccmJobId));
                    String historyUser = login;

                    if (historyUserObj != null)
                        historyUser = historyUserObj.getLogin();

                    VSEMImporter vsemImporter = new VSEMImporter(pcbFileName, customerId, wingInstanceName, grpName,
                            this, row_id, login, jobId, new JobParameters(jobId, nccmJobId, historyUser));
                    try {
                        vsemImporter.importVsem();
                    } catch (Exception expr) {
                        context.setResult("Completed");
                        JobRun.logJobCompletionStatus(jobId, jobRunId, false);
                        ServerDBHelper.updatePcbImportLog(customerId, row_id, expr.getMessage());
                        PcbImportJobStatus jobStatus = new PcbImportJobStatus(jobId,
                                job.getJobDataMap().getInt("jobrunid"), 10, "Validate Licenses.",
                                JobStatus.RUNNING);
                        jobStatus = new PcbImportJobStatus(jobId, job.getJobDataMap().getInt("jobrunid"), 100,
                                expr.getMessage(), JobStatus.FAILED);
                        logMsg("No sufficient license found." + expr.getMessage());
                        ClientSessionManager.getInstance().sendJobStatusMessages(jobId, jobStatus);
                        return;
                    }
                    numDevs = vsemImporter.getNumberOfDevices();
                    perDeviceImportStatus = vsemImporter.getPerDeviceImportStatus();
                    perDeviceConfigBackupStatus = vsemImporter.getPerDeviceConfigBackupStatus();
                    /*XMLImporter xmlImporter = new XMLImporter(pcbFileName, customerId, wingInstanceName, grpName, this,
                        row_id, login, jobId);
                    xmlImporter.importXml();
                    numDevs = xmlImporter.getNumberOfDevices();
                    perDeviceImportStatus = xmlImporter.getPerDeviceImportStatus();
                    perDeviceConfigBackupStatus = xmlImporter.getPerDeviceConfigBackupStatus();*/
                    noThreads = 0;
                } catch (Throwable ex) {
                    logger.error("Exception while importing from VSEM File: " + pcbFile, ex);
                }
            }
            if (noThreads > numDevs) {
                noThreads = numDevs;
            }

            int size = numDevs;
            System.out.println("Number of devices = " + size);
            while (noThreads > 0) {
                try {
                    Thread.sleep(2000);
                    logger.debug("Job: " + jobId + ". " + noThreads + " more to go.");
                } catch (Exception ee) {
                }
            }
            DeviceImportEventHandler evt = new DeviceImportEventHandler();
            if (virtsAdded.size() > 0) {
                Iterator<VirtualDeviceRefresh> it = virtsAdded.iterator();
                while (it.hasNext()) {
                    VirtualDeviceRefresh deviceAddedMsg = it.next();
                    try {
                        DeviceManager.getInstance().processDevice(MessageTypes.VIRUAL_DEVICE_DISCOVERED,
                                deviceAddedMsg);
                        Messenger.getInstance().publish(MessageTypes.DEVICE_CONFIG_CHANGED,
                                deviceAddedMsg.getNodeId() + "");
                        try {
                            ServerAuditLog.getInstance().logAudit(login, ServerAuditConstants.DEVICE_MANAGEMENT,
                                    ServerAuditConstants.DEVICE_MANAGEMENT_DEVICE_STATE,
                                    "Virtual Device (" + deviceAddedMsg.getDeviceName() + ") added.", -1, -1);
                        } catch (Exception ee) {
                        }
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }
            if (version == 1) {
                // look for voip phones
                String voipList = pcbFile.getAttributeValue("ExtendedAttributes", "VoipList");
                if (voipList != null) {
                    populateVoIPPhones(voipList);
                }
            }

            context.setResult("Completed");
            if (state != JobStatus.FAILED) {
                state = JobStatus.SUCCESS;
            }
            JobRun.logJobCompletionStatus(jobId, jobRunId, (state == JobStatus.SUCCESS ? true : false));
            PcbImportJobStatus jobStatus = new PcbImportJobStatus(jobId, jobRunId, 100, "Completed", state);
            logger.error("Finished executing job: " + jobId + " in " + ((System.currentTimeMillis() - t) / 1000)
                    + " secs");
            ClientSessionManager.getInstance().sendJobStatusMessages(jobId, jobStatus);
            ServerAuditLog.getInstance().logAudit(login, ServerAuditConstants.DEVICE_MANAGEMENT,
                    ServerAuditConstants.DEVICE_MANAGEMENT_DISCOVERY, "Pcb/Zip Import Task Triggered.", jobId,
                    jobRunId);
            ServerDBHelper.updatePcbImportLog(customerId, row_id,
                    (state == 1) ? "NCCM Device File import partially successfull."
                            : "Successfully imported the NCCM Device File .");
            setDeviceImportEventParameters(job, numDevs, row_id, evt);
            evt.setJobStatus((state == JobStatus.SUCCESS) ? "Success" : "Failed");
            evt.setPerDeviceImportStatus(perDeviceImportStatus);
            EventManager.getInstance().sendEvent(evt);

            if (perDeviceConfigBackupStatus != null && !perDeviceConfigBackupStatus.isEmpty()) {
                ConfigBackupEventHandler cfgbkpEvt = new ConfigBackupEventHandler();
                cfgbkpEvt.setJobId(jobId);
                cfgbkpEvt.setJobRunId(jobRunId);
                cfgbkpEvt.setJobName(job.getName());
                cfgbkpEvt.setCount(perDeviceConfigBackupStatus.size());
                cfgbkpEvt.setUserId(uId);
                cfgbkpEvt.setPerDeviceConfigBackupStatus(perDeviceConfigBackupStatus);
                cfgbkpEvt.setJobStatus((state == JobStatus.SUCCESS) ? "Success" : "Failed");
                EventManager.getInstance().sendEvent(cfgbkpEvt);
            }
        } catch (Exception ee) {
            ServerDBHelper.updatePcbImportLog(customerId, row_id, ee.getMessage());
            ee.printStackTrace();
            logger.error("Error while importing PCB File", ee);
            logMsg("Error while importing PCB File: " + ee.getMessage()); // CSCtx75737
            context.setResult("Completed"); // CSCtx75737 - Setting State of the Job.
            JobRun.logJobCompletionStatus(jobId, jobRunId, false);
            PcbImportJobStatus jobStatus = new PcbImportJobStatus(jobId, jobRunId, 100, "Completed",
                    JobStatus.FAILED);
            ClientSessionManager.getInstance().sendJobStatusMessages(jobId, jobStatus);
            DeviceImportEventHandler evt = new DeviceImportEventHandler();
            setDeviceImportEventParameters(job, numDevs, row_id, evt);
            evt.setJobStatus("Failed");
            evt.setStatus(Constants.PCB_IMPORT_FAIL);
            EventManager.getInstance().sendEvent(evt);

            if (perDeviceConfigBackupStatus != null && !perDeviceConfigBackupStatus.isEmpty()) {
                ConfigBackupEventHandler cfgbkpEvt = new ConfigBackupEventHandler();
                cfgbkpEvt.setJobId(jobId);
                cfgbkpEvt.setJobRunId(jobRunId);
                cfgbkpEvt.setJobName(job.getName());
                cfgbkpEvt.setCount(perDeviceConfigBackupStatus.size());
                cfgbkpEvt.setUserId(uId);
                cfgbkpEvt.setPerDeviceConfigBackupStatus(perDeviceConfigBackupStatus);
                cfgbkpEvt.setJobStatus("Failed");
                EventManager.getInstance().sendEvent(cfgbkpEvt);
            }
        } finally {
            try {
                // Invoke custom report engine after vsem import job is complete - generates report for devices in vsem
                // CustomReportHandler handler = CustomReportHandler.getInstance();
                // handler.generateReport();
                CustomReportJobDetails jobDetails = new CustomReportJobDetails();
                jobDetails.setJobDesc("Job triggered due to device import");
                jobDetails.setVsemFileName(pcbFileName, customerId);
                jobDetails.setVsemImportJobId(jobId);
                List<ScriptInfo> list = ReportDefManagerImpl.getInstance().getBasicScriptInfoByType(ScriptType.Top,
                        customerId);

                // if a vsem file is being imported for a customer, then all the scripts which belong to him as well as
                // the scripts which belong to all customers should be executed.
                if (customerId != ICEntity.ALL_CUSTOMER_ID) {
                    list.addAll(ReportDefManagerImpl.getInstance().getBasicScriptInfoByType(ScriptType.Top,
                            ICEntity.ALL_CUSTOMER_ID));
                }

                // customerId);
                Set<String> devices = new HashSet<String>();
                StringBuilder devIds = new StringBuilder();
                // Get unique list of devices associated with all the scripts.
                for (ScriptInfo script : list) {
                    Set<Device> devSet = NCCMCustomReportHandler.getInstance().getDeviceList(script, false, jobId);
                    for (Device dev : devSet) {
                        devices.add(dev.getDeviceID());
                    }
                }

                int i = 0;
                for (String device : devices) {
                    devIds.append("D").append(device);
                    if (i < (devices.size() - 1)) {
                        devIds.append(",");
                    }
                    i++;
                }

                if (list.size() > 0) {
                    jobDetails.setDevices(devIds.toString());
                    JobMgr.getInstance().scheduleRunNowCustomReportJob(uId, jobDetails);
                }

                if (pcbFileName != null) {
                    pushToBackupServer();
                }
            } catch (Exception ee) {
                ee.printStackTrace();
            } finally {
                if (runnableTokens.get(custWingUniqueId) != null) {
                    // Remove from currentCustomerJob if all threads have finished
                    if (runnableTokens.get(custWingUniqueId).isEmpty()) {
                        currentCustomerJobTokens.remove(custWingUniqueId);
                    } else {
                        // Getting and setting the latest token to the current customer.
                        currentCustomerRunningToken.put(custWingUniqueId,
                                runnableTokens.get(custWingUniqueId).peek());
                    }
                }
            }
        }
    }

    private void setDeviceImportEventParameters(JobDetail job, int numDevs, int row_id,
            DeviceImportEventHandler evt) {
        if (customer != null) // CSCua78200
        {
            evt.setCustomerName(customer.getCustomerName());
            evt.setCustomerId(customerId);
            evt.setCspcInstance(wingInstanceName);
        }
        evt.setJobId(jobId);
        evt.setJobRunId(jobRunId);
        evt.setJobName(job.getName());
        evt.setRow_id(row_id);
        evt.setCount(numDevs);
        evt.setPcbFileName(pcbFileName);
        evt.setUserId(uId);
    }

    private PCBFileIf processPcbV1(Key key) throws Exception {
        PCBFileIf pcbFile;
        if (key == null) {
            pcbFile = PCBFile.open(new File(pcbFileName));
        } else {
            pcbFile = openCustomerPCBFile(key);
        }
        if (keys == null) {
            // No devices passed. Try and get all the devices from the PCB File.
            for (String devId : pcbFile.getDeviceNames()) {
                // The device names in PCB are really IP addresses.
                // And there are some devices with special names (e.g. "ExtendedAttributes" etc) we need to skip them
                if (IPAddressBase.validateIpAddress(devId)) {
                    devs.add(devId);
                }
            }
            keys = devs.toArray(new String[devs.size()]);

        }
        String discDevicesList = pcbFile.getAttributeValue("ExtendedAttributes", "DiscoveredDevices");
        if (discDevicesList != null) {
            populateDiscoveredList(discDevicesList, customerId, instanceId);
        }
        return pcbFile;
    }

    private void processCustomerAndInstance(int row_id) throws Exception {
        if (customerId != -1) {
            customer = CustomerManager.getInstance().getCustomerById(customerId);
            if (customer == null) {
                PariLoggerFactory.getLogger(Constants.JOB_LOGGER)
                        .info("No customer with customer id :" + customerId + " exists.");
                ServerDBHelper.updatePcbImportLog(customerId, row_id,
                        "NCCM Device File import Failed. No such customer.");
                throw new Exception("No customer with customer id :" + customerId + " exists.");
            }
            customerName = customer.getCustomerName();
            if (wingInstanceName != null) {
                cInst = CustomerWingInstanceManager.getInstance().getCustomerInstanceByName(customerId,
                        wingInstanceName);
                if (cInst == null) {
                    PariLoggerFactory.getLogger(Constants.JOB_LOGGER).info("No CSPC instance with name: "
                            + wingInstanceName + " in customer :" + customerName + " exists.");
                    ServerDBHelper.updatePcbImportLog(customerId, row_id,
                            "NCCM Device File import Failed. No such CSPC instance.");
                    throw new Exception("No CSPC instance with name: " + wingInstanceName + " in customer :"
                            + customerName + " exists.");
                }
            }
            if (cInst != null) {
                instanceId = cInst.getInstanceId();
            }
        }
        if (customerId != -1 && instanceId != -1) {
            try {
                CspcConnectionStatusDetails connStatusObj = CspcInfoManager.getInstance()
                        .getCspcConnectionStatusInfoObj(customerId, instanceId);
                connStatusObj.setLastComm(System.currentTimeMillis());
                connStatusObj.setNextHeartBeatTime(
                        System.currentTimeMillis() + CspcConnectionStatusThread.HEARTBEAT_INTERVAL);
                connStatusObj.setConnectionStatus(ConnectionStatusEnum.UP, false);
                connStatusObj.setComment("Received Collection profile from CSPC.", true);
            } catch (Exception ex) {
                logger.error("Error while retrieving Cspc Connection Status details:" + ex);
            }
        }
    }

    private int getPCBFileVersion(String pcbFileName, Key key) throws Exception {
        return PCBFile.getVersion(new File(pcbFileName), key, false, 0);
    }

    private static void populateDiscoveredList(String discDevicesList, int customerId, int instanceId) {
        try {
            InputStream fin = new ByteArrayInputStream(discDevicesList.getBytes());
            DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = docBuilder.parse(fin);
            Element docRoot = doc.getDocumentElement();
            populateDiscoveredList(docRoot, customerId, instanceId);
        } catch (Exception ex) {
            logger.warn("Error processing discovered device list", ex);
        }
    }

    public static void populateDiscoveredList(Element docRoot, int customerId, int instanceId) throws Exception {
        if (!docRoot.getTagName().equals("DiscoveredDeviceList")) {
            throw new Exception("Invalid format. Expecting: DiscoveredDeviceList, found " + docRoot.getTagName());
        }
        NodeList devList = docRoot.getElementsByTagName("DiscoveredDevice");
        int numCh = devList.getLength();
        for (int i = 0; i < numCh; i++) {
            Element specRoot = (Element) devList.item(i);
            String tagName = specRoot.getTagName();
            if (!tagName.equals("DiscoveredDevice")) {
                throw new Exception("Invalid format. Expecting: DiscoveredDevice, found " + tagName);
            }
            DiscoveredDevice dev = new DiscoveredDevice();
            dev.setCustomer_id(customerId);
            dev.setInstanceId(instanceId);
            NodeList aList = specRoot.getElementsByTagName("IpAddress");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setIpAddress(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("HostName");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setNodeName(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("MACAddress");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setMacAddress(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("Description");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setDescription(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("DeviceFamily");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setDevice_family(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("ProductFamily");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setProduct_family(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("ProductModel");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setProduct_model(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("OSName");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setOsName(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("OSVersion");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setOsVersion(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("VendorName");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setVendor_name(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("IsManaged");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setManaged(nn.getNodeValue().trim().equalsIgnoreCase("yes"));
            }
            aList = specRoot.getElementsByTagName("DiscoveryMethod");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setDiscovery_method(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("DiscoveryCredential");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setDiscovery_credential(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("DiscoveryTime");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setDiscovery_time(nn.getNodeValue().trim());
            }
            aList = specRoot.getElementsByTagName("DiscoveredFrom");
            if (aList.getLength() > 0) {
                Node n = aList.item(0);
                Node nn = n.getFirstChild();
                dev.setDiscovered_from(nn.getNodeValue().trim());
            }
            InventoryDBHelper.insertDiscoveredDevice(dev);
        }
    }

    private void populateVoIPPhones(String voipPhoneList) {
        try {
            InputStream fin = new ByteArrayInputStream(voipPhoneList.getBytes());
            DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = docBuilder.parse(fin);
            Element docRoot = doc.getDocumentElement();
            if (!docRoot.getTagName().equals("VoipPhoneList")) {
                throw new Exception("Invalid format. Expecting: VoipPhoneList, found " + docRoot.getTagName());
            }
            HashMap<Integer, ArrayList<VoipPhone>> phonesMap = new HashMap<Integer, ArrayList<VoipPhone>>();
            ConcurrentHashMap<String, Integer> custIpMap = CustomerManager.getInstance()
                    .getCustomerIpMap(customerId);
            List<Element> phoneElementList = XMLUtil.getFirstLevelChildElementsByTagName(docRoot, "VoipPhone");
            if ((phoneElementList != null) && (phoneElementList.size() > 0) && (custIpMap != null)
                    && (custIpMap.size() > 0)) {
                for (Element voipPhoneElem : phoneElementList) {
                    VoipPhone phone = new VoipPhone();
                    String ipAddress = XMLUtil.getChildText(voipPhoneElem, "IpAddress");
                    if (ipAddress != null) {
                        phone.setIpAddress(ipAddress.trim());
                    }
                    String phoneModel = XMLUtil.getChildText(voipPhoneElem, "PhoneModel");
                    if (phoneModel != null) {
                        phone.setModel(phoneModel.trim());
                    }
                    String vendorName = XMLUtil.getChildText(voipPhoneElem, "VendorName");
                    if (vendorName != null) {
                        phone.setVendorName(vendorName.trim());
                    }
                    String macAddress = XMLUtil.getChildText(voipPhoneElem, "MACAddress");
                    if (macAddress != null) {
                        phone.setMacAddress(macAddress.trim());
                    }
                    String switchInterface = XMLUtil.getChildText(voipPhoneElem, "SwitchInterface");
                    if (switchInterface != null) {
                        phone.setSwitchInterface(switchInterface.trim());
                    }
                    String serialNumber = XMLUtil.getChildText(voipPhoneElem, "SerialNumber");
                    if (serialNumber != null) {
                        phone.setSerialNumber(serialNumber.trim());
                    }
                    String userName = XMLUtil.getChildText(voipPhoneElem, "UserName");
                    if (userName != null) {
                        phone.setUserName(userName.trim());
                    }
                    String extension = XMLUtil.getChildText(voipPhoneElem, "UserName");
                    if (extension != null) {
                        phone.setPhoneNumber(extension.trim());
                    }
                    String switchIpAddress = XMLUtil.getChildText(voipPhoneElem, "SwitchIpAddress");
                    Integer deviceId = custIpMap.get(switchIpAddress);
                    if ((deviceId != null) && (deviceId.intValue() != -1)) {
                        phone.setSwitchNodeId(deviceId);
                        ArrayList<VoipPhone> phonesList = phonesMap.get(deviceId);
                        if (phonesList == null) {
                            phonesList = new ArrayList<VoipPhone>();
                            phonesMap.put(deviceId, phonesList);
                        }
                        phonesList.add(phone);
                    }
                }
            }
            if (phonesMap.size() > 0) {
                try {
                    VOIPDBHelper.saveVOIPPhones(customerId, instanceId, phonesMap);
                } catch (Exception ex) {
                    logger.warn("Error while saving VOIP Phones for the customer: " + customerId + " instance="
                            + instanceId, ex);
                }
            }
        } catch (Exception ex) {
            logger.warn(
                    "Error while saving VOIP Phones for the customer: " + customerId + " instance=" + instanceId,
                    ex);
        }
    }

    private Key getKey(int customerId) throws Exception {
        if (customerId == -1) {
            return null;
        }
        Customer cust = CustomerManager.getInstance().getCustomerById(customerId);
        if (cust == null) {
            throw (new Exception("No customer with the given cust id."));
        }
        String keyStr = cust.getSecurityKey();
        if (keyStr == null) {
            throw (new Exception("Key is null"));
        }
        BASE64Decoder decoder = new BASE64Decoder();
        byte bytes[] = decoder.decodeBuffer(keyStr);
        ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
        ObjectInputStream objin = new ObjectInputStream(bin);
        return (Key) objin.readObject();
    }

    @Override
    public void executionComplete(String msg, boolean status, String... devices) {
        if (noThreads > 0) {
            noThreads--;
        }
        logger.debug(
                "Job: " + jobId + ". " + noThreads + " more to go. Thread: " + Thread.currentThread().getName());
    }

    @Override
    public void logMsg(String log) {
        JobRun.logJob(jobId, jobRunId, log);
    }

    @Override
    public void setState(int state) {
        if (this.state != JobStatus.FAILED) {
            this.state = state;
        }
    }

    @Override
    public void statusUpdate(String msg, boolean msgType, int perComplete, Object... keys) {
        HashMap<String, String> msgMap = (HashMap<String, String>) keys[0];
        noOfVirtsAdded += msgMap.size();
        PcbImportJobStatus jobStatus = new PcbImportJobStatus(jobId, jobRunId, 99, msgMap, JobStatus.RUNNING,
                msgType ? JobStatus.MSG_INFO : JobStatus.MSG_ERROR);
        ClientSessionManager.getInstance().sendJobStatusMessages(jobId, jobStatus);
        logger.debug(jobStatus.toString());
    }

    @Override
    public void executionComplete(String[] msg, boolean status, String... keys) {

    }

    private PCBFileIf openCustomerPCBFile(Key key) throws Exception {
        try {
            return PCBFile.open(new File(pcbFileName), key, null);
        } catch (Exception ex) {
            return PCBFile.open(new File(pcbFileName), null);
        }
    }

    public void addVirtDeviceAddedMsg(VirtualDeviceRefresh dRefresh) {
        virtsAdded.add(dRefresh);
    }

    private class ZIPImportListener implements ZIPProcessorProgressListener {
        boolean inProgress = true;

        @Override
        public void updateProgress(String fileName, int currentFileIndex, int fileCount) {
            PcbImportJobStatus jobStatus = new PcbImportJobStatus(jobId, jobRunId, 10,
                    "Processing zip file. " + currentFileIndex + " of " + fileCount + " done.", JobStatus.RUNNING);
            ClientSessionManager.getInstance().sendJobStatusMessages(jobId, jobStatus);
            logger.debug("Done with file: " + currentFileIndex + " of " + fileCount);
        }

        @Override
        public void processCompleted() {
            logger.debug("Done processing zip file");
            inProgress = false;
        }

    }

    private void pushToBackupServer() {
        File uploadFile = new File(pcbFileName);
        boolean isDeleteFile = true;
        String renamedFile = null;

        if (profileName != null) {
            String finalProfileName = profileName;
            String[] profileNames = profileName.split("_");

            if (profileNames.length == 2) {
                finalProfileName = profileNames[0] != null && !profileNames[0].equals("") ? profileNames[0]
                        : "_" + profileNames[1];
            } else if (profileNames.length > 2) {
                finalProfileName = profileName.substring(0, profileName.lastIndexOf("_"));
            }

            String cpName = finalProfileName;
            FtpServerDetails ftpServerDetails = ServerDBHelper.getFtpServerPreferences(cpName);

            if (ftpServerDetails != null) {
                int customJobId = nccmJobId != -1 ? nccmJobId : jobId;
                int customJobRunId = nccmJobRunId != -1 ? nccmJobRunId : jobRunId;
                JobRun.logJob(customJobId, customJobRunId, CspcXMLUtils.logMsgInStdFormat("", null, "",
                        System.currentTimeMillis(), "File backup is configured for this Collection Profile"));
                String formatedName = cpName + "_" + jobId + "_" + jobRunId + "_" + System.currentTimeMillis()
                        + ".zip";
                Path path = Paths.get(uploadFile.getAbsolutePath());
                renamedFile = path.getParent() + File.separator + formatedName;
                File formatedFile = new File(path.getParent() + File.separator + formatedName);
                uploadFile.renameTo(formatedFile);

                FTPServerType serverType = ftpServerDetails.getServerType();
                String fileName = formatedFile.getName();
                String successMsg = "Backup file: " + fileName + " uploaded successfully into "
                        + serverType.toString() + " server: " + ftpServerDetails.getFtpServer();
                successMsg += serverType.equals(FTPServerType.TFTP) ? ""
                        : " and directory: " + ftpServerDetails.getDestDir();
                String startMsg = "Backup file: " + fileName + " uploaded started";
                String formatedMsg = CspcXMLUtils.logMsgInStdFormat("", null, "", System.currentTimeMillis(),
                        startMsg);
                JobRun.logJob(customJobId, customJobRunId, formatedMsg);
                if (serverType.equals(FTPServerType.SFTP)) {
                    try {
                        logger.info("Backup:  LocalFile:" + formatedFile);
                        logger.info(
                                "Backup:  DestFile:" + ftpServerDetails.getDestDir() + File.separator + fileName);
                        PariSFTP pariSFTP = new PariSFTP(customJobId, customJobRunId);
                        pariSFTP.uploadFileSFTP(ftpServerDetails.getFtpServer(), ftpServerDetails.getServerPort(),
                                ftpServerDetails.getUserName(), ftpServerDetails.getPassword(),
                                formatedFile.getAbsolutePath(),
                                ftpServerDetails.getDestDir() + File.separator + fileName, this,
                                serverType.equals(FTPServerType.SFTP));
                        JobRun.logJob(customJobId, customJobRunId, CspcXMLUtils.logMsgInStdFormat("", null, "",
                                System.currentTimeMillis(), successMsg));
                    } catch (Exception ex) {
                        String msg = "Failed to upload the backup file " + formatedFile + " Reason:"
                                + ex.getMessage();
                        logger.warn(msg);
                        JobRun.logJob(customJobId, customJobRunId,
                                CspcXMLUtils.logMsgInStdFormat("", null, "", System.currentTimeMillis(), msg));
                    }
                } else if (serverType.equals(FTPServerType.FTP)) {
                    PariFTP pftp = new PariFTP(ftpServerDetails.getFtpServer(), ftpServerDetails.getUserName(),
                            ftpServerDetails.getPassword(), ftpServerDetails.getDestDir(), customJobId,
                            customJobRunId);
                    String errMsg = pftp.uploadFile(formatedFile.getAbsolutePath(),
                            ftpServerDetails.getServerPort());
                    if (errMsg != null) {
                        String msg = "Failed to upload the backup file to " + ftpServerDetails.getFtpServer()
                                + " Reason :" + errMsg;
                        logger.warn(msg);
                        JobRun.logJob(customJobId, customJobRunId,
                                CspcXMLUtils.logMsgInStdFormat("", null, "", System.currentTimeMillis(), msg));
                    } else {
                        JobRun.logJob(customJobId, customJobRunId, CspcXMLUtils.logMsgInStdFormat("", null, "",
                                System.currentTimeMillis(), successMsg));
                    }
                } else if (serverType.equals(FTPServerType.TFTP)) {
                    TFTPHandler tftp = new TFTPHandler(ftpServerDetails.getFtpServer(), customJobId,
                            customJobRunId);
                    String errMsg = tftp.uploadFile(formatedFile.getAbsolutePath(),
                            ftpServerDetails.getServerPort());
                    if (errMsg != null) {
                        String msg = "Failed to upload the backup file to " + ftpServerDetails.getFtpServer()
                                + " Reason :" + errMsg;
                        logger.warn(msg);
                        JobRun.logJob(customJobId, customJobRunId,
                                CspcXMLUtils.logMsgInStdFormat("", null, "", System.currentTimeMillis(), msg));
                    } else {
                        JobRun.logJob(customJobId, customJobRunId, CspcXMLUtils.logMsgInStdFormat("", null, "",
                                System.currentTimeMillis(), successMsg));
                    }
                } else if (serverType.equals(FTPServerType.LOCAL)) {
                    File backupFile = new File(ServerProperties.getCollectionProfileDir().getAbsolutePath()
                            + File.separator + formatedFile.getName());
                    formatedFile.renameTo(backupFile);
                    successMsg = "Backup file: " + fileName + " is available in the directory :"
                            + backupFile.getAbsolutePath();
                    JobRun.logJob(customJobId, customJobRunId,
                            CspcXMLUtils.logMsgInStdFormat("", null, "", System.currentTimeMillis(), successMsg));
                    isDeleteFile = false;
                } else if (serverType.equals(FTPServerType.SCP)) {
                    SCPHandler scp = new SCPHandler(ftpServerDetails.getFtpServer(), customJobId, customJobRunId,
                            ftpServerDetails.getUserName(), ftpServerDetails.getPassword(),
                            ftpServerDetails.getDestDir());
                    String errMsg = scp.uploadFile(formatedFile.getAbsolutePath(),
                            ftpServerDetails.getServerPort());
                    if (errMsg != null) {
                        String msg = "Failed to upload the backup file to " + ftpServerDetails.getFtpServer()
                                + " Reason :" + errMsg;
                        logger.warn(msg);
                        JobRun.logJob(customJobId, customJobRunId,
                                CspcXMLUtils.logMsgInStdFormat("", null, "", System.currentTimeMillis(), msg));
                    } else {
                        JobRun.logJob(customJobId, customJobRunId, CspcXMLUtils.logMsgInStdFormat("", null, "",
                                System.currentTimeMillis(), successMsg));
                    }
                }
            }
        }
        if (isDeleteFile) {
            deletePCBFile(renamedFile != null ? renamedFile : pcbFileName);
        }

    }

    private void deletePCBFile(String fileName) {
        try {
            File f = new File(fileName);
            // CSCtz18817
            if (f.isDirectory()) {
                FileUtils.deleteDirectory(f);
            } else {
                f.delete();
            }
        } catch (IOException e) {
            logger.error("Unalbe to delete the file", e);
        }

    }
}