/* * eGov suite of products aim to improve the internal efficiency,transparency, * accountability and the service delivery of the government organizations. * * Copyright (C) <2015> eGovernments Foundation * * The updated version of eGov suite of products as by eGovernments Foundation * is available at http://www.egovernments.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program 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 General Public License * along with this program. If not, see http://www.gnu.org/licenses/ or * http://www.gnu.org/licenses/gpl.html . * * In addition to the terms of the GPL license to be adhered to in using this * program, the following additional terms are to be complied with: * * 1) All versions of this program, verbatim or modified must carry this * Legal Notice. * * 2) Any misrepresentation of the origin of the material is prohibited. It * is required that all modified versions of this material be marked in * reasonable ways as different from the original version. * * 3) This license does not grant any rights to any user of the program * with regards to rights under trademark law for use of the trade names * or trademarks of eGovernments Foundation. * * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. */ package org.egov.infra.reporting.engine.jasper; import net.sf.jasperreports.engine.DefaultJasperReportsContext; import net.sf.jasperreports.engine.JRDataSource; import net.sf.jasperreports.engine.JREmptyDataSource; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRExporter; import net.sf.jasperreports.engine.JRExporterParameter; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.JasperReportsContext; import net.sf.jasperreports.engine.data.JRBeanArrayDataSource; import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; import net.sf.jasperreports.engine.export.JExcelApiExporter; import net.sf.jasperreports.engine.export.JRCsvExporter; import net.sf.jasperreports.engine.export.JRHtmlExporter; import net.sf.jasperreports.engine.export.JRHtmlExporterParameter; import net.sf.jasperreports.engine.export.JRPdfExporter; import net.sf.jasperreports.engine.export.JRPdfExporterParameter; import net.sf.jasperreports.engine.export.JRRtfExporter; import net.sf.jasperreports.engine.export.JRTextExporter; import net.sf.jasperreports.engine.export.JRTextExporterParameter; import net.sf.jasperreports.engine.query.JRHibernateQueryExecuterFactory; import net.sf.jasperreports.engine.util.JRLoader; import org.egov.infra.exception.ApplicationRuntimeException; import org.egov.infra.reporting.engine.AbstractReportService; import org.egov.infra.reporting.engine.ReportConstants; import org.egov.infra.reporting.engine.ReportOutput; import org.egov.infra.reporting.engine.ReportRequest; import org.hibernate.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.sql.Connection; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * Report service for generating reports using the JasperReports engine. Caches the report templates based on the template file to improve performance. */ public class JasperReportService extends AbstractReportService<JasperReport> { private static final Logger LOGGER = LoggerFactory.getLogger(JasperReportService.class); public static final String TEMPLATE_EXTENSION = ".jasper"; private static final String JASPER_PROPERTIES_FILE = "config/jasperreports.properties"; @PersistenceContext private EntityManager entityManager; static { // Set the system property for jasperreports properties file System.setProperty(DefaultJasperReportsContext.PROPERTIES_FILE, JASPER_PROPERTIES_FILE); } /** * @param templateCacheMinSize Minimum size of template cache * @param templateCacheMaxSize Maximum size of template cache */ public JasperReportService(final int templateCacheMinSize, final int templateCacheMaxSize) { super(templateCacheMinSize, templateCacheMaxSize); } /* * (non-Javadoc) * @see org.egov.infra.reporting.engine.AbstractReportService#getTemplateExtension () */ @Override protected String getTemplateExtension() { return TEMPLATE_EXTENSION; } /** * Returns exporter for given report format, jasper print object and output stream * @param reportInput Report Input object * @param jasperPrint Jasper print object * @param outputStream Report output stream * @return exporter for given report format, jasper print object and output stream */ private JRExporter getExporter(final ReportRequest reportInput, final JasperPrint jasperPrint, final OutputStream outputStream) { JRExporter exporter; switch (reportInput.getReportFormat()) { case PDF: exporter = new JRPdfExporter(); if (reportInput.isPrintDialogOnOpenReport()) { exporter.setParameter(JRPdfExporterParameter.PDF_JAVASCRIPT, "this.print()"); } break; case XLS: exporter = new JExcelApiExporter(); break; case RTF: exporter = new JRRtfExporter(); break; case HTM: exporter = new JRHtmlExporter(); exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.FALSE); exporter.setParameter(JRHtmlExporterParameter.IS_OUTPUT_IMAGES_TO_DIR, Boolean.FALSE); exporter.setParameter(JRHtmlExporterParameter.IMAGES_DIR_NAME, "/images"); break; case TXT: exporter = new JRTextExporter(); // TBD: from Jasper 3.6.1 - can be externalized exporter.setParameter(JRTextExporterParameter.CHARACTER_WIDTH, 6); exporter.setParameter(JRTextExporterParameter.CHARACTER_HEIGHT, 12); // exporter.setParameter(JRTextExporterParameter.PAGE_WIDTH, 800); // exporter.setParameter(JRTextExporterParameter.PAGE_HEIGHT, 500); exporter.setParameter(JRTextExporterParameter.LINE_SEPARATOR, "\r\n"); break; case CSV: exporter = new JRCsvExporter(); break; default: throw new ApplicationRuntimeException("Invalid report format [" + reportInput.getReportFormat() + "]"); } // Set common exporter parameters exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, ReportConstants.CHARACTER_ENCODING_UTF8); exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint); exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream); return exporter; } /** * Creates report for given report template, format, data source and parameters * @param reportInput Report Input object * @param dataSource Data source * @return Report output created using given input and data source */ private ReportOutput createReport(final ReportRequest reportInput, final JRDataSource dataSource) { try { final JasperPrint jasperPrint = JasperFillManager.fillReport(getTemplate(reportInput.getReportTemplate()), reportInput.getReportParams(), dataSource); final byte[] data = exportReport(reportInput, jasperPrint); return new ReportOutput(data, reportInput); } catch (final Exception e) { final String errMessage = "Exception in report creation!"; LOGGER.error(errMessage, e); throw new ApplicationRuntimeException(errMessage, e); } } /* * (non-Javadoc) * @see org.egov.infra.reporting.engine.AbstractReportService#createReportFromSql (org.egov.infra.reporting.engine.ReportRequest, java.sql.Connection) */ @Override protected ReportOutput createReportFromSql(final ReportRequest reportInput, final Connection connection) { try { final JasperPrint jasperPrint = JasperFillManager.fillReport(getTemplate(reportInput.getReportTemplate()), reportInput.getReportParams(), connection); final byte[] data = exportReport(reportInput, jasperPrint); return new ReportOutput(data, reportInput); } catch (final Exception e) { final String errMessage = "Exception in report creation!"; LOGGER.error(errMessage, e); throw new ApplicationRuntimeException(errMessage, e); } } /** * Exports the given jasper print object in required format by looking at the report input * @param reportInput The report input * @param jasperPrint The jasper print object * @return The exported report in the form of a byte array */ private byte[] exportReport(final ReportRequest reportInput, final JasperPrint jasperPrint) throws JRException, IOException { try { final ByteArrayOutputStream reportOutputStream = new ByteArrayOutputStream(); final JRExporter exporter = getExporter(reportInput, jasperPrint, reportOutputStream); exporter.exportReport(); final byte[] data = reportOutputStream.toByteArray(); reportOutputStream.close(); return data; } catch (final Exception e) { final String errMsg = "Exception in export report!"; LOGGER.error(errMsg, e); throw new ApplicationRuntimeException(errMsg, e); } } /* * (non-Javadoc) * @seeorg.egov.infstr.reporting.engine.AbstractReportService# createReportFromJavaBean(org.egov.infra.reporting.engine.ReportRequest) */ @Override @SuppressWarnings("unchecked") protected ReportOutput createReportFromJavaBean(final ReportRequest reportInput) { final Object reportData = reportInput.getReportInputData(); JRDataSource dataSource = null; if (reportData == null) { dataSource = new JREmptyDataSource(); } else if (reportData.getClass().isArray()) { dataSource = new JRBeanArrayDataSource((Object[]) reportData, false); } else if (reportData instanceof Collection) { dataSource = new JRBeanCollectionDataSource((Collection) reportData, false); } else { // Not an array/collection. Possibly a single object. Create a // data source with array of one object dataSource = new JRBeanArrayDataSource(new Object[] { reportData }, false); } return createReport(reportInput, dataSource); } /* * (non-Javadoc) * @see org.egov.infra.reporting.engine.AbstractReportService#createReportFromHql (org.egov.infra.reporting.engine.ReportRequest) */ @Override protected ReportOutput createReportFromHql(final ReportRequest reportInput) { try { Map<String, Object> reportParams = reportInput.getReportParams(); if (reportParams == null) { reportParams = new HashMap<String, Object>(); } reportParams.put(JRHibernateQueryExecuterFactory.PARAMETER_HIBERNATE_SESSION, entityManager.unwrap(Session.class)); JasperReportsContext jrc = DefaultJasperReportsContext.getInstance(); jrc.setValue(JRHibernateQueryExecuterFactory.PROPERTY_HIBERNATE_FIELD_MAPPING_DESCRIPTIONS, false); final JasperPrint jasperPrint = JasperFillManager.getInstance(jrc).fill(getTemplate(reportInput.getReportTemplate()), reportParams); final byte[] data = exportReport(reportInput, jasperPrint); return new ReportOutput(data, reportInput); } catch (final Exception e) { final String errMessage = "Exception in report creation!"; LOGGER.error(errMessage, e); throw new ApplicationRuntimeException(errMessage, e); } } /* * (non-Javadoc) * @see org.egov.infra.reporting.engine.AbstractReportService#loadTemplate(java .io.InputStream) */ @Override protected JasperReport loadTemplate(final InputStream templateInputStream) { try { return (JasperReport) JRLoader.loadObject(templateInputStream); } catch (final JRException e) { final String errMsg = "Exception while loading jasperreport template from inpust stream!"; LOGGER.error(errMsg, e); throw new ApplicationRuntimeException(errMsg, e); } } }