/*
jBilling - The Enterprise Open Source Billing System
Copyright (C) 2003-2011 Enterprise jBilling Software Ltd. and Emiliano Conde
This file is part of jbilling.
jbilling 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.
jbilling 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with jbilling. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sapienter.jbilling.server.report;
import com.sapienter.jbilling.server.report.db.ReportDAS;
import com.sapienter.jbilling.server.report.db.ReportDTO;
import com.sapienter.jbilling.server.user.UserBL;
import com.sapienter.jbilling.server.util.Context;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.export.JRHtmlExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
import org.apache.log4j.Logger;
import org.springframework.jdbc.datasource.DataSourceUtils;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* ReportBL
*
* @author Brian Cowdery
* @since 08/03/11
*/
public class ReportBL {
private static final Logger LOG = Logger.getLogger(ReportBL.class);
public static final String SESSION_IMAGE_MAP = "jasper_images";
public static final String PARAMETER_ENTITY_ID = "entity_id";
public static final String PARAMETER_SUBREPORT_DIR = "SUBREPORT_DIR";
private ReportDTO report;
private Locale locale;
private Integer entityId;
private ReportDAS reportDas;
public ReportBL() {
_init();
}
public ReportBL(Integer id, Integer userId, Integer entityId) {
_init();
set(id);
setLocale(userId);
this.entityId = entityId;
}
public ReportBL(ReportDTO report, Locale locale, Integer entityId) {
_init();
this.report = report;
this.locale = locale;
this.entityId = entityId;
}
private void _init() {
this.reportDas = new ReportDAS();
}
public void set(Integer id) {
this.report = reportDas.find(id);
}
public void setLocale(Integer userId) {
this.locale = new UserBL(userId).getLocale();
}
public void setEntityId(Integer entityId) {
this.entityId = entityId;
}
public ReportDTO getEntity() {
return this.report;
}
/**
* Render report as HTML to the given HTTP response stream. This method also dumps
* the generated report image files into a session Map (<code>Map<String, byte[]></code>)
* so that they can be retrieved and rendered.
*
* @param response response stream
* @param session session to place images map
* @param imagesUrl the URL of the action where the image map can be accessed by name - e.g., "images?image="
*/
public void renderHtml(HttpServletResponse response, HttpSession session, String imagesUrl) {
PrintWriter writer = null;
try {
writer = response.getWriter();
} catch (IOException e) {
LOG.error("Exception occurred retrieving the print writer for the response stream.", e);
return;
}
JasperPrint print = run();
if (print != null) {
Map<String, byte[]> images = new HashMap<String, byte[]>();
response.setContentType("text/html");
session.setAttribute(SESSION_IMAGE_MAP, images);
JRHtmlExporter exporter = new JRHtmlExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, writer);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, images);
exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, imagesUrl);
try {
exporter.exportReport();
} catch (JRException e) {
LOG.error("Exception occurred exporting jasper report to HTML.", e);
}
}
}
/**
* Exports a report using the given format.
*
* @param format export type
* @return exported report
*/
public ReportExportDTO export(ReportExportFormat format) {
LOG.debug("Exporting report to " + format.name() + " ...");
JasperPrint print = run();
ReportExportDTO export = null;
if (print != null) {
try {
export = format.export(print);
} catch (JRException e) {
LOG.error("Exception occurred exporting jasper report to " + format.name(), e);
} catch (IOException e) {
LOG.error("Exception occurred getting exported bytes", e);
}
}
return export;
}
/**
* Run this report.
*
* This method assumes that the report object contains parameters that have been populated
* with a value to use when running the report.
*
* @return JasperPrint output file
*/
public JasperPrint run() {
return run(report.getName(),
report.getReportFile(),
report.getReportBaseDir(),
report.getParameterMap(),
locale,
entityId);
}
/**
* Run the given report design file with the given parameter list.
*
* @param reportName report name
* @param report report design file
* @param baseDir report base directory
* @param parameters report parameters
* @param locale user locale
* @param entityId entity ID
* @return JasperPrint output file
*/
public static JasperPrint run(String reportName, File report, String baseDir, Map<String, Object> parameters,
Locale locale, Integer entityId) {
// add user locale, entity id and sub report directory
parameters.put(JRParameter.REPORT_LOCALE, locale);
parameters.put(PARAMETER_ENTITY_ID, entityId);
parameters.put(PARAMETER_SUBREPORT_DIR, baseDir);
LOG.debug("Generating report " + report.getPath() + " ...");
LOG.debug(parameters.toString());
// get database connection
DataSource dataSource = Context.getBean(Context.Name.DATA_SOURCE);
Connection connection = DataSourceUtils.getConnection(dataSource);
// run report
FileInputStream inputStream = null;
JasperPrint print = null;
try {
inputStream = new FileInputStream(report);
print = JasperFillManager.fillReport(inputStream, parameters, connection);
print.setName(reportName);
} catch (FileNotFoundException e) {
LOG.error("Report design file " + report.getPath() + " not found.", e);
} catch (JRException e) {
LOG.error("Exception occurred generating jasper report.", e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
/* ignore*/
}
}
}
// release connection
DataSourceUtils.releaseConnection(connection, dataSource);
return print;
}
}