1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts2.views.jasperreports;
22
23 import java.io.ByteArrayOutputStream;
24 import java.io.File;
25 import java.io.IOException;
26 import java.util.HashMap;
27 import java.util.Map;
28
29 import javax.servlet.ServletContext;
30 import javax.servlet.ServletException;
31 import javax.servlet.ServletOutputStream;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.servlet.http.HttpServletResponse;
34
35 import net.sf.jasperreports.engine.JRException;
36 import net.sf.jasperreports.engine.JRExporter;
37 import net.sf.jasperreports.engine.JRExporterParameter;
38 import net.sf.jasperreports.engine.JRParameter;
39 import net.sf.jasperreports.engine.JasperExportManager;
40 import net.sf.jasperreports.engine.JasperFillManager;
41 import net.sf.jasperreports.engine.JasperPrint;
42 import net.sf.jasperreports.engine.JasperReport;
43 import net.sf.jasperreports.engine.export.JRCsvExporter;
44 import net.sf.jasperreports.engine.export.JRCsvExporterParameter;
45 import net.sf.jasperreports.engine.export.JRHtmlExporter;
46 import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
47 import net.sf.jasperreports.engine.export.JRRtfExporter;
48 import net.sf.jasperreports.engine.export.JRXlsExporter;
49 import net.sf.jasperreports.engine.export.JRXmlExporter;
50 import net.sf.jasperreports.engine.util.JRLoader;
51
52 import org.apache.commons.logging.Log;
53 import org.apache.commons.logging.LogFactory;
54 import org.apache.struts2.ServletActionContext;
55 import org.apache.struts2.dispatcher.StrutsResultSupport;
56
57 import com.opensymphony.xwork2.ActionInvocation;
58 import com.opensymphony.xwork2.util.TextUtils;
59 import com.opensymphony.xwork2.util.ValueStack;
60
61 /***
62 * <!-- START SNIPPET: description -->
63 *
64 * Generates a JasperReports report using the specified format or PDF if no
65 * format is specified.
66 *
67 * <!-- END SNIPPET: description -->
68 * <p />
69 * <b>This result type takes the following parameters:</b>
70 *
71 * <!-- START SNIPPET: params -->
72 *
73 * <ul>
74 *
75 * <li><b>location (default)</b> - the location where the compiled jasper report
76 * definition is (foo.jasper), relative from current URL.</li>
77 *
78 * <li><b>dataSource (required)</b> - the EL expression used to retrieve the
79 * datasource from the value stack (usually a List).</li>
80 *
81 * <li><b>parse</b> - true by default. If set to false, the location param will
82 * not be parsed for EL expressions.</li>
83 *
84 * <li><b>format</b> - the format in which the report should be generated. Valid
85 * values can be found in {@link JasperReportConstants}. If no format is
86 * specified, PDF will be used.</li>
87 *
88 * <li><b>contentDisposition</b> - disposition (defaults to "inline", values are
89 * typically <i>filename="document.pdf"</i>).</li>
90 *
91 * <li><b>documentName</b> - name of the document (will generate the http header
92 * <code>Content-disposition = X; filename=X.[format]</code>).</li>
93 *
94 * <li><b>delimiter</b> - the delimiter used when generating CSV reports. By
95 * default, the character used is ",".</li>
96 *
97 * <li><b>imageServletUrl</b> - name of the url that, when prefixed with the
98 * context page, can return report images.</li>
99 *
100 * </ul>
101 *
102 * <p>
103 * This result follows the same rules from {@link StrutsResultSupport}.
104 * Specifically, all parameters will be parsed if the "parse" parameter is not
105 * set to false.
106 * </p>
107 * <!-- END SNIPPET: params -->
108 *
109 * <b>Example:</b>
110 *
111 * <pre><!-- START SNIPPET: example1 -->
112 * <result name="success" type="jasper">
113 * <param name="location">foo.jasper</param>
114 * <param name="dataSource">mySource</param>
115 * <param name="format">CSV</param>
116 * </result>
117 * <!-- END SNIPPET: example1 --></pre>
118 * or for pdf
119 * <pre><!-- START SNIPPET: example2 -->
120 * <result name="success" type="jasper">
121 * <param name="location">foo.jasper</param>
122 * <param name="dataSource">mySource</param>
123 * </result>
124 * <!-- END SNIPPET: example2 --></pre>
125 *
126 */
127 public class JasperReportsResult extends StrutsResultSupport implements JasperReportConstants {
128
129 private static final long serialVersionUID = -2523174799621182907L;
130
131
132 private final static Log LOG = LogFactory.getLog(JasperReportsResult.class);
133
134
135 protected String dataSource;
136 protected String format;
137 protected String documentName;
138 protected String contentDisposition;
139 protected String delimiter;
140 protected String imageServletUrl = "/images/";
141
142 public JasperReportsResult() {
143 super();
144 }
145
146 public JasperReportsResult(String location) {
147 super(location);
148 }
149
150 public String getImageServletUrl() {
151 return imageServletUrl;
152 }
153
154 public JasperReportsResult setImageServletUrl(final String imageServletUrl) {
155 this.imageServletUrl = imageServletUrl;
156 return this;
157 }
158
159 public JasperReportsResult setDataSource(String dataSource) {
160 this.dataSource = dataSource;
161 return this;
162 }
163
164 public JasperReportsResult setFormat(String format) {
165 this.format = format;
166 return this;
167 }
168
169 public JasperReportsResult setDocumentName(String documentName) {
170 this.documentName = documentName;
171 return this;
172 }
173
174 public JasperReportsResult setContentDisposition(String contentDisposition) {
175 this.contentDisposition = contentDisposition;
176 return this;
177 }
178
179 public JasperReportsResult setDelimiter(String delimiter) {
180 this.delimiter = delimiter;
181 return this;
182 }
183
184 protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
185 if (this.format == null) {
186 this.format = FORMAT_PDF;
187 }
188
189 if (dataSource == null) {
190 String message = "No dataSource specified...";
191 LOG.error(message);
192 throw new RuntimeException(message);
193 }
194
195 if (LOG.isDebugEnabled()) {
196 LOG.debug("Creating JasperReport for dataSource = " + dataSource + ", format = " + this.format);
197 }
198
199 HttpServletRequest request = (HttpServletRequest) invocation.getInvocationContext().get(ServletActionContext.HTTP_REQUEST);
200 HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().get(ServletActionContext.HTTP_RESPONSE);
201
202
203 ValueStack stack = invocation.getStack();
204 ValueStackDataSource stackDataSource = new ValueStackDataSource(stack, dataSource);
205
206 format = conditionalParse(format, invocation);
207 dataSource = conditionalParse(dataSource, invocation);
208
209 if (contentDisposition != null) {
210 contentDisposition = conditionalParse(contentDisposition, invocation);
211 }
212
213 if (documentName != null) {
214 documentName = conditionalParse(documentName, invocation);
215 }
216
217
218 if (!TextUtils.stringSet(format)) {
219 format = FORMAT_PDF;
220 }
221
222 if (!"contype".equals(request.getHeader("User-Agent"))) {
223
224
225
226 ServletContext servletContext = (ServletContext) invocation.getInvocationContext().get(ServletActionContext.SERVLET_CONTEXT);
227 String systemId = servletContext.getRealPath(finalLocation);
228 Map parameters = new ValueStackShadowMap(stack);
229 File directory = new File(systemId.substring(0, systemId.lastIndexOf(File.separator)));
230 parameters.put("reportDirectory", directory);
231 parameters.put(JRParameter.REPORT_LOCALE, invocation.getInvocationContext().getLocale());
232
233 byte[] output;
234 JasperPrint jasperPrint;
235
236
237 try {
238 JasperReport jasperReport = (JasperReport) JRLoader.loadObject(systemId);
239
240 jasperPrint =
241 JasperFillManager.fillReport(jasperReport,
242 parameters,
243 stackDataSource);
244 } catch (JRException e) {
245 LOG.error("Error building report for uri " + systemId, e);
246 throw new ServletException(e.getMessage(), e);
247 }
248
249
250 try {
251 if (contentDisposition != null || documentName != null) {
252 final StringBuffer tmp = new StringBuffer();
253 tmp.append((contentDisposition == null) ? "inline" : contentDisposition);
254
255 if (documentName != null) {
256 tmp.append("; filename=");
257 tmp.append(documentName);
258 tmp.append(".");
259 tmp.append(format.toLowerCase());
260 }
261
262 response.setHeader("Content-disposition", tmp.toString());
263 }
264
265 if (format.equals(FORMAT_PDF)) {
266 response.setContentType("application/pdf");
267
268
269 output = JasperExportManager.exportReportToPdf(jasperPrint);
270 } else {
271 JRExporter exporter;
272
273 if (format.equals(FORMAT_CSV)) {
274 response.setContentType("text/plain");
275 exporter = new JRCsvExporter();
276 } else if (format.equals(FORMAT_HTML)) {
277 response.setContentType("text/html");
278
279
280
281 Map imagesMap = new HashMap();
282
283 request.getSession(true).setAttribute("IMAGES_MAP", imagesMap);
284 exporter = new JRHtmlExporter();
285 exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, imagesMap);
286 exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, request.getContextPath() + imageServletUrl);
287
288 exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
289 request.getSession().setAttribute("net.sf.jasperreports.j2ee.jasper_print", jasperPrint);
290
291 } else if (format.equals(FORMAT_XLS)) {
292 response.setContentType("application/vnd.ms-excel");
293 exporter = new JRXlsExporter();
294 } else if (format.equals(FORMAT_XML)) {
295 response.setContentType("text/xml");
296 exporter = new JRXmlExporter();
297 } else if (format.equals(FORMAT_RTF)) {
298 response.setContentType("application/rtf");
299 exporter = new JRRtfExporter();
300 } else {
301 throw new ServletException("Unknown report format: " + format);
302 }
303
304 output = exportReportToBytes(jasperPrint, exporter);
305 }
306 } catch (JRException e) {
307 String message = "Error producing " + format + " report for uri " + systemId;
308 LOG.error(message, e);
309 throw new ServletException(e.getMessage(), e);
310 }
311
312 response.setContentLength(output.length);
313
314 ServletOutputStream ouputStream;
315
316 try {
317 ouputStream = response.getOutputStream();
318 ouputStream.write(output);
319 ouputStream.flush();
320 ouputStream.close();
321 } catch (IOException e) {
322 LOG.error("Error writing report output", e);
323 throw new ServletException(e.getMessage(), e);
324 }
325 } else {
326
327 try {
328 ServletOutputStream outputStream;
329 response.setContentType("application/pdf");
330 response.setContentLength(0);
331 outputStream = response.getOutputStream();
332 outputStream.close();
333 } catch (IOException e) {
334 LOG.error("Error writing report output", e);
335 throw new ServletException(e.getMessage(), e);
336 }
337 }
338 }
339
340 /***
341 * Run a Jasper report to CSV format and put the results in a byte array
342 *
343 * @param jasperPrint The Print object to render as CSV
344 * @param exporter The exporter to use to export the report
345 * @return A CSV formatted report
346 * @throws net.sf.jasperreports.engine.JRException
347 * If there is a problem running the report
348 */
349 private byte[] exportReportToBytes(JasperPrint jasperPrint, JRExporter exporter) throws JRException {
350 byte[] output;
351 ByteArrayOutputStream baos = new ByteArrayOutputStream();
352
353 exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
354 exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, baos);
355 if (delimiter != null) {
356 exporter.setParameter(JRCsvExporterParameter.FIELD_DELIMITER, delimiter);
357 }
358
359 exporter.exportReport();
360
361 output = baos.toByteArray();
362
363 return output;
364 }
365 }