Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ public JRCsvExporter createExporter(ActionInvocation invocation, JasperPrint jas
SimpleExporterInput input = new SimpleExporterInput(jasperPrint);
exporter.setExporterInput(input);

try (OutputStream responseStream = response.getOutputStream()) {
try {
OutputStream responseStream = response.getOutputStream();
WriterExporterOutput exporterOutput = new SimpleWriterExporterOutput(responseStream);
exporter.setExporterOutput(exporterOutput);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public HtmlExporter createExporter(ActionInvocation invocation, JasperPrint jasp
SimpleExporterInput input = new SimpleExporterInput(jasperPrint);
exporter.setExporterInput(input);

try (OutputStream responseStream = response.getOutputStream()) {
try {
OutputStream responseStream = response.getOutputStream();
SimpleHtmlExporterOutput exporterOutput = new SimpleHtmlExporterOutput(responseStream);
HtmlResourceHandler imageHandler = new WebHtmlResourceHandler(request.getContextPath() + imageServletUrl + "%s");
exporterOutput.setImageHandler(imageHandler);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public JRPdfExporter createExporter(ActionInvocation invocation, JasperPrint jas
SimpleExporterInput input = new SimpleExporterInput(jasperPrint);
exporter.setExporterInput(input);

try (OutputStream responseStream = response.getOutputStream()) {
try {
OutputStream responseStream = response.getOutputStream();
OutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(responseStream);
exporter.setExporterOutput(exporterOutput);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public JRRtfExporter createExporter(ActionInvocation invocation, JasperPrint jas
SimpleExporterInput input = new SimpleExporterInput(jasperPrint);
exporter.setExporterInput(input);

try (OutputStream responseStream = response.getOutputStream()) {
try {
OutputStream responseStream = response.getOutputStream();
WriterExporterOutput exporterOutput = new SimpleWriterExporterOutput(responseStream);
exporter.setExporterOutput(exporterOutput);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public JRXlsxExporter createExporter(ActionInvocation invocation, JasperPrint ja
SimpleExporterInput input = new SimpleExporterInput(jasperPrint);
exporter.setExporterInput(input);

try (OutputStream responseStream = response.getOutputStream()) {
try {
OutputStream responseStream = response.getOutputStream();
OutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(responseStream);
exporter.setExporterOutput(exporterOutput);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public JRXmlExporter createExporter(ActionInvocation invocation, JasperPrint jas
SimpleExporterInput input = new SimpleExporterInput(jasperPrint);
exporter.setExporterInput(input);

try (OutputStream responseOutput = response.getOutputStream()) {
try {
OutputStream responseOutput = response.getOutputStream();
XmlExporterOutput exporterOutput = new SimpleXmlExporterOutput(responseOutput);
exporter.setExporterOutput(exporterOutput);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
package org.apache.struts2.views.jasperreports7;

import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.WriteListener;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponseWrapper;
import net.sf.jasperreports.engine.JasperCompileManager;
import org.apache.struts2.ActionContext;
import org.apache.struts2.ActionInvocation;
Expand All @@ -29,6 +33,7 @@
import org.apache.struts2.util.ValueStack;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
Expand Down Expand Up @@ -303,6 +308,26 @@ public void testFormatLookupIsCaseInsensitive() throws Exception {
assertThat(response.getContentAsString()).contains("Qux Report");
}

public void testExportWritesNothingAfterClosingTheResponseStream() throws Exception {
for (String format : List.of(JasperReport7Constants.FORMAT_PDF, JasperReport7Constants.FORMAT_CSV,
JasperReport7Constants.FORMAT_HTML, JasperReport7Constants.FORMAT_RTF,
JasperReport7Constants.FORMAT_XML, JasperReport7Constants.FORMAT_XLSX)) {
// given
response.setCommitted(false);
response.reset();
ActionContext.getContext().withServletResponse(new StrictCloseResponse(response));
result.setDataSource("{#{'firstName':'ignore', 'lastName':'ignore'}}");
result.setReportParameters("#{'title':'Qux'}");
result.setFormat(format);

// when
result.execute(this.invocation);

// then
assertThat(response.getContentAsByteArray()).as(format).isNotEmpty();
}
}

public void testExportToRtf() throws Exception {
// given
result.setDataSource("{#{'firstName':'ignore', 'lastName':'ignore'}}");
Expand Down Expand Up @@ -386,6 +411,53 @@ private void compileAndUseReport(String jrxml) throws Exception {
result.setLocation(resource + ".jasper");
}

/**
* Behaves like a servlet container: once the output stream is closed, further writes are lost.
*/
private static class StrictCloseResponse extends HttpServletResponseWrapper {

private ServletOutputStream stream;

StrictCloseResponse(HttpServletResponse response) {
super(response);
}

@Override
public ServletOutputStream getOutputStream() throws IOException {
if (stream == null) {
ServletOutputStream delegate = super.getOutputStream();
stream = new ServletOutputStream() {
private boolean closed;

@Override
public void write(int b) throws IOException {
if (closed) {
throw new IOException("Stream closed");
}
delegate.write(b);
}

@Override
public void close() throws IOException {
closed = true;
delegate.close();
}

@Override
public boolean isReady() {
return delegate.isReady();
}

@Override
public void setWriteListener(WriteListener writeListener) {
delegate.setWriteListener(writeListener);
}
};
}
return stream;
}
}

private static final List<Map<String, String>> JR_MAP_ARRAY_DATA_SOURCE = Stream.<Map<String, String>>of(
new HashMap<>() {{
put("firstName", "Foo");
Expand Down
Loading