Author: davenewton Date: Fri Apr 25 09:04:45 2008 New Revision: 651634 URL: http://svn.apache.org/viewvc?rev=651634&view=rev Log: WW-2365 - https://issues.apache.org/struts/browse/WW-2365
- Added support for both report and export parameters. - Minor refactoring: - Moved some init and output code out of execute. - Normalized PDF reports to be the same as the rest. - Resulted in cleaner code, lower cyclometric comp. Still no tests for this result type. Modified: struts/struts2/trunk/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportsResult.java Modified: struts/struts2/trunk/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportsResult.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportsResult.java?rev=651634&r1=651633&r2=651634&view=diff ============================================================================== --- struts/struts2/trunk/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportsResult.java (original) +++ struts/struts2/trunk/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportsResult.java Fri Apr 25 09:04:45 2008 @@ -44,6 +44,7 @@ import net.sf.jasperreports.engine.export.JRCsvExporterParameter; 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.JRRtfExporter; import net.sf.jasperreports.engine.export.JRXlsExporter; import net.sf.jasperreports.engine.export.JRXmlExporter; @@ -128,21 +129,39 @@ private static final long serialVersionUID = -2523174799621182907L; - private final static Logger LOG = LoggerFactory.getLogger(JasperReportsResult.class); - protected String dataSource; protected String format; protected String documentName; protected String contentDisposition; protected String delimiter; protected String imageServletUrl = "/images/"; + + /** + * Names a report parameters map stack value, allowing + * additional report parameters from the action. + */ + protected String reportParameters; + + /** + * Names an exporter parameters map stack value, + * allowing the use of custom export parameters. + */ + protected String exportParameters; + /** + * Default ctor. + */ public JasperReportsResult() { super(); } + /** + * Default ctor with location. + * + * @param location Result location. + */ public JasperReportsResult(String location) { super(location); } @@ -175,161 +194,211 @@ this.delimiter = delimiter; } - protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception { - if (this.format == null) { - this.format = FORMAT_PDF; - } - - if (dataSource == null) { - String message = "No dataSource specified..."; - LOG.error(message); - throw new RuntimeException(message); - } + public String getReportParameters() { + return reportParameters; + } + + public void setReportParameters(String reportParameters) { + this.reportParameters = reportParameters; + } + + public String getExportParameters() { + return exportParameters; + } + + public void setExportParameters(String exportParameters) { + this.exportParameters = exportParameters; + } + + protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception { + // Will throw a runtime exception if no "datasource" property. TODO Best place for that is...? + initializeProperties(invocation); if (LOG.isDebugEnabled()) { - LOG.debug("Creating JasperReport for dataSource = " + dataSource + ", format = " + this.format); + LOG.debug("Creating JasperReport for dataSource = " + dataSource + ", format = " + format); } HttpServletRequest request = (HttpServletRequest) invocation.getInvocationContext().get(ServletActionContext.HTTP_REQUEST); HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().get(ServletActionContext.HTTP_RESPONSE); - //construct the data source for the report + // Handle IE special case: it sends a "contype" request first. + // TODO Set content type to config settings? + if ("contype".equals(request.getHeader("User-Agent"))) { + try { + response.setContentType("application/pdf"); + response.setContentLength(0); + + ServletOutputStream outputStream = response.getOutputStream(); + outputStream.close(); + } catch (IOException e) { + LOG.error("Error writing report output", e); + throw new ServletException(e.getMessage(), e); + } + return; + } + + // Construct the data source for the report. ValueStack stack = invocation.getStack(); ValueStackDataSource stackDataSource = new ValueStackDataSource(stack, dataSource); - format = conditionalParse(format, invocation); - dataSource = conditionalParse(dataSource, invocation); - - if (contentDisposition != null) { - contentDisposition = conditionalParse(contentDisposition, invocation); + // Determine the directory that the report file is in and set the reportDirectory parameter + // For WW 2.1.7: + // ServletContext servletContext = ((ServletConfig) invocation.getInvocationContext().get(ServletActionContext.SERVLET_CONFIG)).getServletContext(); + ServletContext servletContext = (ServletContext) invocation.getInvocationContext().get(ServletActionContext.SERVLET_CONTEXT); + String systemId = servletContext.getRealPath(finalLocation); + Map parameters = new ValueStackShadowMap(stack); + File directory = new File(systemId.substring(0, systemId.lastIndexOf(File.separator))); + parameters.put("reportDirectory", directory); + parameters.put(JRParameter.REPORT_LOCALE, invocation.getInvocationContext().getLocale()); + + // Add any report parameters from action to param map. + Map reportParams = (Map) stack.findValue(reportParameters); + if (reportParams != null) { + LOG.debug("Found report parameters; adding to parameters..."); + parameters.putAll(reportParams); } - if (documentName != null) { - documentName = conditionalParse(documentName, invocation); - } + byte[] output; + JasperPrint jasperPrint; - // (Map) ActionContext.getContext().getSession().get("IMAGES_MAP"); - if (!TextUtils.stringSet(format)) { - format = FORMAT_PDF; + // Fill the report and produce a print object + try { + JasperReport jasperReport = (JasperReport) JRLoader.loadObject(systemId); + jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, stackDataSource); + } catch (JRException e) { + LOG.error("Error building report for uri " + systemId, e); + throw new ServletException(e.getMessage(), e); } - if (!"contype".equals(request.getHeader("User-Agent"))) { - // Determine the directory that the report file is in and set the reportDirectory parameter - // For WW 2.1.7: - // ServletContext servletContext = ((ServletConfig) invocation.getInvocationContext().get(ServletActionContext.SERVLET_CONFIG)).getServletContext(); - ServletContext servletContext = (ServletContext) invocation.getInvocationContext().get(ServletActionContext.SERVLET_CONTEXT); - String systemId = servletContext.getRealPath(finalLocation); - Map parameters = new ValueStackShadowMap(stack); - File directory = new File(systemId.substring(0, systemId.lastIndexOf(File.separator))); - parameters.put("reportDirectory", directory); - parameters.put(JRParameter.REPORT_LOCALE, invocation.getInvocationContext().getLocale()); - - byte[] output; - JasperPrint jasperPrint; - - // Fill the report and produce a print object - try { - JasperReport jasperReport = (JasperReport) JRLoader.loadObject(systemId); - - jasperPrint = - JasperFillManager.fillReport(jasperReport, - parameters, - stackDataSource); - } catch (JRException e) { - LOG.error("Error building report for uri " + systemId, e); - throw new ServletException(e.getMessage(), e); + // Export the print object to the desired output format + try { + if (contentDisposition != null || documentName != null) { + final StringBuffer tmp = new StringBuffer(); + tmp.append((contentDisposition == null) ? "inline" : contentDisposition); + + if (documentName != null) { + tmp.append("; filename="); + tmp.append(documentName); + tmp.append("."); + tmp.append(format.toLowerCase()); + } + + response.setHeader("Content-disposition", tmp.toString()); } - // Export the print object to the desired output format - try { - if (contentDisposition != null || documentName != null) { - final StringBuffer tmp = new StringBuffer(); - tmp.append((contentDisposition == null) ? "inline" : contentDisposition); - - if (documentName != null) { - tmp.append("; filename="); - tmp.append(documentName); - tmp.append("."); - tmp.append(format.toLowerCase()); - } + JRExporter exporter; - response.setHeader("Content-disposition", tmp.toString()); - } + if (format.equals(FORMAT_PDF)) { + response.setContentType("application/pdf"); + exporter = new JRPdfExporter(); + } else if (format.equals(FORMAT_CSV)) { + response.setContentType("text/plain"); + exporter = new JRCsvExporter(); + } else if (format.equals(FORMAT_HTML)) { + response.setContentType("text/html"); + + // IMAGES_MAPS seems to be only supported as "backward compatible" from JasperReports 1.1.0 + + Map imagesMap = new HashMap(); + request.getSession(true).setAttribute("IMAGES_MAP", imagesMap); + + exporter = new JRHtmlExporter(); + exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, imagesMap); + exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, request.getContextPath() + imageServletUrl); + + // Needed to support chart images: + exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint); + request.getSession().setAttribute("net.sf.jasperreports.j2ee.jasper_print", jasperPrint); + } else if (format.equals(FORMAT_XLS)) { + response.setContentType("application/vnd.ms-excel"); + exporter = new JRXlsExporter(); + } else if (format.equals(FORMAT_XML)) { + response.setContentType("text/xml"); + exporter = new JRXmlExporter(); + } else if (format.equals(FORMAT_RTF)) { + response.setContentType("application/rtf"); + exporter = new JRRtfExporter(); + } else { + throw new ServletException("Unknown report format: " + format); + } + + Map exportParams = (Map) stack.findValue(exportParameters); + if (exportParams != null) { + LOG.debug("Found export parameters; adding to exporter parameters..."); + exporter.getParameters().putAll(exportParams); + } - if (format.equals(FORMAT_PDF)) { - response.setContentType("application/pdf"); + output = exportReportToBytes(jasperPrint, exporter); + } catch (JRException e) { + String message = "Error producing " + format + " report for uri " + systemId; + LOG.error(message, e); + throw new ServletException(e.getMessage(), e); + } - // response.setHeader("Content-disposition", "inline; filename=report.pdf"); - output = JasperExportManager.exportReportToPdf(jasperPrint); - } else { - JRExporter exporter; - - if (format.equals(FORMAT_CSV)) { - response.setContentType("text/plain"); - exporter = new JRCsvExporter(); - } else if (format.equals(FORMAT_HTML)) { - response.setContentType("text/html"); - - // IMAGES_MAPS seems to be only supported as "backward compatible" from JasperReports 1.1.0 - - Map imagesMap = new HashMap(); - - request.getSession(true).setAttribute("IMAGES_MAP", imagesMap); - exporter = new JRHtmlExporter(); - exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, imagesMap); - exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, request.getContextPath() + imageServletUrl); - // Needed to support chart images: - exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint); - request.getSession().setAttribute("net.sf.jasperreports.j2ee.jasper_print", jasperPrint); - - } else if (format.equals(FORMAT_XLS)) { - response.setContentType("application/vnd.ms-excel"); - exporter = new JRXlsExporter(); - } else if (format.equals(FORMAT_XML)) { - response.setContentType("text/xml"); - exporter = new JRXmlExporter(); - } else if (format.equals(FORMAT_RTF)) { - response.setContentType("application/rtf"); - exporter = new JRRtfExporter(); - } else { - throw new ServletException("Unknown report format: " + format); - } + response.setContentLength(output.length); - output = exportReportToBytes(jasperPrint, exporter); - } - } catch (JRException e) { - String message = "Error producing " + format + " report for uri " + systemId; - LOG.error(message, e); - throw new ServletException(e.getMessage(), e); - } + // Will throw ServletException on IOException. + writeReport(response, output); + } - response.setContentLength(output.length); + /** + * Writes report bytes to response output stream. + * + * @param response Current response. + * @param output Report bytes to write. + * @throws ServletException on stream IOException. + */ + private void writeReport(HttpServletResponse response, byte[] output) throws ServletException { + ServletOutputStream outputStream = null; + try { + outputStream = response.getOutputStream(); + outputStream.write(output); + outputStream.flush(); + } catch (IOException e) { + LOG.error("Error writing report output", e); + throw new ServletException(e.getMessage(), e); + } finally { + try { + if (outputStream != null) { + outputStream.close(); + } + } catch (IOException e) { + LOG.error("Error closing report output stream", e); + throw new ServletException(e.getMessage(), e); + } + } + } - ServletOutputStream ouputStream; + /** + * Sets up result properties, parsing etc. + * + * @param invocation Current invocation. + * @throws Exception on initialization error. + */ + private void initializeProperties(ActionInvocation invocation) throws Exception { + if (dataSource == null) { + String message = "No dataSource specified..."; + LOG.error(message); + throw new RuntimeException(message); + } + dataSource = conditionalParse(dataSource, invocation); - try { - ouputStream = response.getOutputStream(); - ouputStream.write(output); - ouputStream.flush(); - ouputStream.close(); - } catch (IOException e) { - LOG.error("Error writing report output", e); - throw new ServletException(e.getMessage(), e); - } - } else { - // Code to handle "contype" request from IE - try { - ServletOutputStream outputStream; - response.setContentType("application/pdf"); - response.setContentLength(0); - outputStream = response.getOutputStream(); - outputStream.close(); - } catch (IOException e) { - LOG.error("Error writing report output", e); - throw new ServletException(e.getMessage(), e); - } + format = conditionalParse(format, invocation); + if (!TextUtils.stringSet(format)) { + format = FORMAT_PDF; } - } + + if (contentDisposition != null) { + contentDisposition = conditionalParse(contentDisposition, invocation); + } + + if (documentName != null) { + documentName = conditionalParse(documentName, invocation); + } + + reportParameters = conditionalParse(reportParameters, invocation); + exportParameters = conditionalParse(exportParameters, invocation); + } /** * Run a Jasper report to CSV format and put the results in a byte array @@ -356,4 +425,5 @@ return output; } + }