protected virtual List <VW_TRI_PDF_METADATA> GetPDFMetadataList()
        {
            AppendAuditLogEvent("Loading PDF generation metadata from the view \"{0}\" ...", VW_TRI_PDF_METADATA_NAME);
            List <VW_TRI_PDF_METADATA> list = new List <VW_TRI_PDF_METADATA>(100);

            _baseDao.DoJDBCQueryWithRowCallbackDelegate(string.Format("SELECT * FROM {0}", VW_TRI_PDF_METADATA_NAME),
                                                        delegate(IDataReader reader)
            {
                NamedNullMappingDataReader dataReader = reader as NamedNullMappingDataReader;
                VW_TRI_PDF_METADATA m = new VW_TRI_PDF_METADATA();
                m.ID                  = dataReader.GetString(ID_COLUMN_NAME);
                m.DocumentType        = dataReader.GetString("DocumentType");
                m.Confidential        = dataReader.GetString("Confidential");
                m.DocumentDate        = dataReader.GetString("DocumentDate");
                m.IISFacilityNumber   = dataReader.GetString("IISFacilityNumber");
                m.ProgramNumber       = dataReader.GetString("ProgramNumber");
                m.Recipient           = dataReader.GetString("Recipient");
                m.DocumentDescription = dataReader.GetString("DocumentDescription");
                m.Originator          = dataReader.GetString("Originator");
                m.FileLocation        = dataReader.GetString("FileLocation");
                m.SubFileID           = dataReader.GetString("SubFileID");
                m.repType             = dataReader.GetString("repType");
                m.subId               = dataReader.GetString("subId");
                m.repId               = dataReader.GetString("repId");
                m.SubmissionYear      = dataReader.GetString("SubmissionYear");
                m.CASNumber           = dataReader.GetString("CASNumber");
                m.ChemicalName        = dataReader.GetString("ChemicalName");
                m.Revision            = dataReader.GetString("Revision");
                m.Program             = dataReader.GetString("Program");
                m.FiledDate           = dataReader.GetString("FiledDate");
                m.OriginatorType      = dataReader.GetString("OriginatorType");
                m.RecipientType       = dataReader.GetString("RecipientType");
                m.FormURL             = dataReader.GetString("FormURL");
                m.CSVFilename         = dataReader.GetString("CSVFilename");
                m.PDFFilename         = dataReader.GetString("PDFFilename");
                m.FileType            = dataReader.GetString("FileType");
                list.Add(m);
            });
            if (list.Count == 0)
            {
                AppendAuditLogEvent("The view \"{0}\" did not contain any records, this process will exit.", VW_TRI_PDF_METADATA_NAME);
            }
            else
            {
                if ((_maxFilesToGenerate < int.MaxValue) && (list.Count > _maxFilesToGenerate))
                {
                    AppendAuditLogEvent("Found {0} PDF generation metadata records in the view \"{1}\", but the number of files processed will be limited to the maximum number specified of {2} ...",
                                        list.Count.ToString(), VW_TRI_PDF_METADATA_NAME, _maxFilesToGenerate.ToString());
                    list.RemoveRange(_maxFilesToGenerate, list.Count - _maxFilesToGenerate);
                }
                else
                {
                    AppendAuditLogEvent("Found {0} PDF generation metadata records in the view \"{1}\" ...",
                                        list.Count.ToString(), VW_TRI_PDF_METADATA_NAME);
                }
            }
            return(list);
        }
        protected virtual void GeneratePDF(VW_TRI_PDF_METADATA metadata, int currentFileIndex, int maxFileIndex)
        {
            AppendAuditLogEvent("*** Starting PDF generation for file \"{0}\" ({1} of {2} total files)",
                                metadata.PDFFilename, currentFileIndex.ToString(), maxFileIndex.ToString());
            string outputPDFFilePath = null, outputCSVFilePath = null;
            string app_GeneratedPDF_ID = StringUtils.CreateSequentialGuid();

            try
            {
                string documentUri = _viewerBaseUri;
                if (!metadata.FormURL.StartsWith("/"))
                {
                    documentUri += "/";
                }
                documentUri += metadata.FormURL;

                outputPDFFilePath = Path.Combine(_outputFolderPath, metadata.PDFFilename);
                outputCSVFilePath = Path.Combine(_outputFolderPath, metadata.CSVFilename);

                // See http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf-0.9.9-doc.html for command line params

                string commandParams = "-O Portrait -q --disable-external-links --disable-internal-links ";

                commandParams += string.Format("-s {0} ", _pageType);
                if (_scalePercentage != 100)
                {
                    commandParams += string.Format("--zoom {0} ", ((float)_scalePercentage / 100f).ToString());
                }
                commandParams += string.Format("\"{0}\" \"{1}\"", documentUri, outputPDFFilePath);

                int retryAttempts = 2;
                do
                {
                    try
                    {
                        // Delete files if they already exist since they need to be regenerated anyway:
                        FileUtils.SafeDeleteFile(outputPDFFilePath);
                        FileUtils.SafeDeleteFile(outputCSVFilePath);

                        using (Process process = new Process())
                        {
                            process.StartInfo.FileName    = _pdfGeneratorExePath;
                            process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

                            process.StartInfo.Arguments = commandParams;

                            process.Start();

                            if (!process.WaitForExit(5 * 60 * 1000))
                            {
                                try
                                {
                                    process.Kill();
                                }
                                catch (Exception)
                                {
                                }
                                throw new ArgumentException("The PDF generation process did not finish in a reasonable amount of time, so the process has been aborted.");
                            }
                            if (process.ExitCode != 0)
                            {
                                throw new ArgumentException(string.Format("The PDF generation process exited with an error code: {0}.", process.ExitCode.ToString()));
                            }
                        }
                        if (!File.Exists(outputPDFFilePath))
                        {
                            throw new ArgumentException("The PDF generation process did not produce an output file, aborting export!");
                        }
                        break;
                    }
                    catch (Exception ex2)
                    {
                        if (retryAttempts > 0)
                        {
                            AppendAuditLogEvent("The PDF generation process failed, will pause then retry again.  Error: {0}",
                                                ExceptionUtils.GetDeepExceptionMessage(ex2));
                            Thread.Sleep(TimeSpan.FromSeconds(10));
                        }
                    }
                } while (retryAttempts-- > 0);

                string columnNamesString = StringUtils.Join(";", _csvColumnNames);
                _baseDao.DoSimpleQueryWithRowCallbackDelegate(VW_TRI_FILE_CSV_DEFINITION_NAME, ID_COLUMN_NAME, metadata.ID, columnNamesString,
                                                              delegate(IDataReader reader)
                {
                    //CsvExporter.ExportSingleCsvRow(_csvColumnNames, reader, true, outputCSVFilePath);
                    CsvExporter.ExportSingleCsvRow(reader, true, outputCSVFilePath);
                });

                if (!File.Exists(outputCSVFilePath))
                {
                    throw new ArgumentException("The CSV generation process did not produce an output file, aborting export!");
                }

                _baseDao.DoSimpleInsertOrUpdateOne(App_GeneratedPDF_NAME, "repId;repType", new object[] { metadata.repId, metadata.repType },
                                                   "App_GeneratedPDF_ID;repId;repType;Filename;IsGenerated;ErrorMsg", app_GeneratedPDF_ID,
                                                   metadata.repId, metadata.repType, outputPDFFilePath, true, null);

                AppendAuditLogEvent("*** Successfully finished PDF generation for file \"{0}\" ({1} of {2} total files)",
                                    metadata.PDFFilename, currentFileIndex.ToString(), maxFileIndex.ToString());
            }
            catch (Exception ex)
            {
                FileUtils.SafeDeleteFile(outputPDFFilePath);
                FileUtils.SafeDeleteFile(outputCSVFilePath);
                string errorMessage = string.Format("Failed PDF generation for file \"{0}\" ({1} of {2} total files) with error: {3}",
                                                    metadata.PDFFilename, currentFileIndex.ToString(), maxFileIndex.ToString(),
                                                    ExceptionUtils.GetDeepExceptionMessage(ex));
                AppendAuditLogEvent("*** " + errorMessage);
                if (errorMessage.Length > 4000)
                {
                    errorMessage = errorMessage.Substring(0, 4000);
                }
                try
                {
                    _baseDao.DoSimpleInsertOrUpdateOne(App_GeneratedPDF_NAME, "repId;repType", new object[] { metadata.repId, metadata.repType },
                                                       "App_GeneratedPDF_ID;repId;repType;Filename;IsGenerated;ErrorMsg", app_GeneratedPDF_ID,
                                                       metadata.repId, metadata.repType, null, false, errorMessage);
                }
                catch (Exception)
                {
                }
            }
        }