/*==========================================================================*\ | $Id: ReportGenerationWorkerThread.java,v 1.2 2011/12/25 21:18:25 stedwar2 Exp $ |*-------------------------------------------------------------------------*| | Copyright (C) 2006-2011 Virginia Tech | | This file is part of Web-CAT. | | Web-CAT is free software; you can redistribute it and/or modify | it under the terms of the GNU Affero General Public License as published | by the Free Software Foundation; either version 3 of the License, or | (at your option) any later version. | | Web-CAT 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 General Public License for more details. | | You should have received a copy of the GNU Affero General Public License | along with Web-CAT; if not, see <http://www.gnu.org/licenses/>. \*==========================================================================*/ package org.webcat.reporter; import java.io.File; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.eclipse.birt.report.engine.api.EngineException; import org.eclipse.birt.report.engine.api.IEngineTask; import org.eclipse.birt.report.engine.api.IPageHandler; import org.eclipse.birt.report.engine.api.IRunTask; import org.webcat.core.MutableArray; import org.webcat.jobqueue.WorkerThread; import org.webcat.reporter.messaging.ReportCompleteMessage; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.foundation.NSTimestamp; //------------------------------------------------------------------------- /** * A worker thread that generates reports using the BIRT reporting engine. * * @author Tony Allevato * @author Last changed by $Author: stedwar2 $ * @version $Revision: 1.2 $, $Date: 2011/12/25 21:18:25 $ */ public class ReportGenerationWorkerThread extends WorkerThread<ReportGenerationJob> { //~ Constructors .......................................................... // ---------------------------------------------------------- /** * Initializes a new instance of the ReportGenerationWorkerThread class. */ public ReportGenerationWorkerThread() { super(ReportGenerationJob.ENTITY_NAME); } //~ Methods ............................................................... // ---------------------------------------------------------- /** * Called by the superclass to carry out the tasks for this job. */ @Override protected void processJob() { ReportGenerationJob job = currentJob(); GeneratedReport report = job.generatedReport(); EOEditingContext ec = localContext(); log.info("Processing report for: " + job.user().userName() + " (template: " + job.generatedReport().reportTemplate().name() + ")"); ensureReportDirectoryExists(report); //int dataSetRefs = countDataSetReferences(job.reportTemplate()); // Register the GeneratedReport object with the tracker so that the // progress page can observe it. //log.debug("Registering job with tracker"); //ReportGenerationTracker.getInstance().startReportForJobId( // job.id().intValue(), report.id().intValue(), dataSetRefs); runReport(report); if (isCancelling()) { // Delete the GeneratedReport (and accompanying file) if it was // already created by this point. ec.deleteObject(report); ec.saveChanges(); return; } storeErrorsInReportObject(report); report.setGeneratedTime(new NSTimestamp()); report.setIsComplete(true); ec.saveChanges(); // Send a notification that the report was completed. new ReportCompleteMessage(report).send(); } // ---------------------------------------------------------- /** * Ensures that the directory that will contain generated report documents * for this user exists. */ private void ensureReportDirectoryExists(GeneratedReport report) { File reportDir = new File(report.generatedReportDir()); if (!reportDir.exists()) { reportDir.mkdirs(); } } // ---------------------------------------------------------- /** * Spawns the BIRT report engine task that runs the report. */ private void runReport(GeneratedReport report) { ReportGenerationJob job = currentJob(); String reportPath = report.generatedReportFile(); List<Exception> exceptions = null; org.mozilla.javascript.Context.enter(); try { log.debug("Generation thread: setting up run task"); runTask = Reporter.getInstance().setupRunTaskForJob(job); runTask.setErrorHandlingOption(IEngineTask.CANCEL_ON_ERROR); IPageHandler pageHandler = ReportPageRenderer.getInstance() .createPageHandlerForReport(report); runTask.setPageHandler(pageHandler); log.debug("Generation thread: running BIRT reporting task"); runTask.run(reportPath); exceptions = new ArrayList<Exception>(runTask.getErrors()); if (exceptions.isEmpty()) { exceptions = null; } runTask.close(); runTask = null; } catch (EngineException e) { // Error creating process, so record it log.error("Exception generating " + reportPath, e); // This exception won't be thrown after the call to runTask.run, // so we don't need to worry about checking if exceptions is null // and clobbering anything already in there. exceptions = new ArrayList<Exception>(); exceptions.add(0, e); } org.mozilla.javascript.Context.exit(); // Copy the exceptions into a MutableArray that we can store in the // GeneratedReport EO, and log them to the console as well. errorsDuringRun = null; if (exceptions != null) { errorsDuringRun = new MutableArray(); for (Exception ex : exceptions) { log.error("Error generating report:", ex); errorsDuringRun.addObject(ex); } } } // ---------------------------------------------------------- /** * Merges the list of errors produced by the run task with any errors that * were produced by the result sets and stores them as a MutableArray * inside the GeneratedReport object. */ private void storeErrorsInReportObject(GeneratedReport report) { ReportGenerationJob job = currentJob(); MutableArray errors = ReportExceptionTranslator.translateExceptions( errorsDuringRun); // Pull any additional error information that was generated in the // result set from the report tracker. /*NSDictionary<String, Object> _extraInfo = ReportGenerationTracker.getInstance().lastErrorInfoForJobId( job.id().intValue()); if (_extraInfo != null) { MutableDictionary extraInfo = new MutableDictionary(_extraInfo); extraInfo.setObjectForKey("extraInfo", "entryKind"); errors.insertObjectAtIndex(extraInfo, 0); }*/ report.setErrors(errors); } // ---------------------------------------------------------- /** * Cancels the job by killing the BIRT report engine task. */ @Override protected void cancelJob() { ReportGenerationJob job = currentJob(); super.cancelJob(); runTask.cancel(); //ReportGenerationTracker.getInstance().removeReportIdForJobId( // job.id().intValue()); log.info("ReportGenerationJob with id " + job.id().intValue() + " was cancelled"); } //~ Static/instance variables ............................................. private IRunTask runTask; private MutableArray errorsDuringRun; static Logger log = Logger.getLogger(ReportGenerationWorkerThread.class); }