From d0f92829349bec782236b5ad0ef089b961cd4901 Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Thu, 8 Mar 2012 22:24:03 +0100 Subject: [PATCH] HttpTestCase in das Modul test verschoben und schweren Fehler korrigiert MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Schweren Denkfehler in der Klasse HttpTestCase und dem zugehörigen Response- Wrapper behoben: Der Servlet-Container ruft flush erst auf, wenn die Filter-Kette fertig abgearbeitet wurde. Da hat er aber wieder nur den ursprünglichen Response zur Verfügung und nicht mehr den Response-Wrapper, in den der Response hier zu Test-Zwecken verpackt wurde. Dementsprechend kann der Servlet-Container die Methode flush während der Finalisierung des Requests nur auf dem ursprünglichen Response-Objekt aufrufen -- nicht aber auf dem Response- Wrapper! Wenn der Response-Wrapper also (wie hier der Fall) ein spezielles flush benötigt, kann man sich dafür nicht auf den Servlet-Container verlassen!! Der Flush muss explizit auf angestoßen werden, wenn der Response-Wrapper keine Daten verschlucken soll. Dabei: * Den bisher als innere Klasse implementierten Response-Wrapper in LoggingHttpServletResponseWrapper umbenannt und in eine eigenständige Klasse umgewandelt. * LoggingHttpServletResponseFilter implementiert, mit dem sich der Response-Wrapper auch in enier normalen Java-Webanwendung verwenden lässt, um zu Protokollieren, wie ein Response-Objekt benutzt wird. --- cachecontrol/pom.xml | 12 - .../juplo/cachecontrol/HttpTestCase.java | 191 ----------- .../cachecontrol/ParameterGuessingTest.java | 6 + .../juplo/cachecontrol/RequestSizeTest.java | 11 +- pom.xml | 4 +- test/pom.xml | 37 ++- .../halbekunst/juplo/test/HttpTestCase.java | 84 +++++ .../LoggingHttpServletResponseFilter.java | 42 +++ .../LoggingHttpServletResponseWrapper.java | 310 ++++++++++++++++++ 9 files changed, 485 insertions(+), 212 deletions(-) delete mode 100644 cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/HttpTestCase.java create mode 100644 test/src/main/java/de/halbekunst/juplo/test/HttpTestCase.java create mode 100644 test/src/main/java/de/halbekunst/juplo/test/LoggingHttpServletResponseFilter.java create mode 100644 test/src/main/java/de/halbekunst/juplo/test/LoggingHttpServletResponseWrapper.java diff --git a/cachecontrol/pom.xml b/cachecontrol/pom.xml index 9fd31ebb..cc38b340 100644 --- a/cachecontrol/pom.xml +++ b/cachecontrol/pom.xml @@ -49,18 +49,6 @@ ${jpa.version} provided - - httpunit - httpunit - ${httpunit.version} - test - - - javax.servlet - servlet-api - - - ${pom.parent.groupId} ${pom.parent.artifactId}-test diff --git a/cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/HttpTestCase.java b/cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/HttpTestCase.java deleted file mode 100644 index bd28c91b..00000000 --- a/cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/HttpTestCase.java +++ /dev/null @@ -1,191 +0,0 @@ -package de.halbekunst.juplo.cachecontrol; - -import com.meterware.httpunit.WebResponse; -import com.meterware.servletunit.InvocationContext; -import com.meterware.servletunit.ServletRunner; -import com.meterware.servletunit.ServletUnitClient; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Enumeration; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; -import org.junit.Before; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * @author kai - */ -public abstract class HttpTestCase { - private final static Logger log = LoggerFactory.getLogger(HttpTestCase.class); - - private ServletRunner sr; - ServletUnitClient client; - int buffer = 2048; - - - @Before - public void init() throws Exception { - sr = new ServletRunner(ParameterGuessingTest.class.getResourceAsStream("/web.xml")); - client = sr.newClient(); - } - - protected WebResponse executeRequest(String uri) throws Exception { - log.debug("---------- GET: {}", uri); - InvocationContext invocation = client.newInvocation(uri); - HttpServletRequest request = invocation.getRequest(); - log.debug("Request - {}: {}", request.getMethod(), request.getProtocol()); - Enumeration headers = request.getHeaderNames(); - while (headers.hasMoreElements()) { - String header = headers.nextElement(); - Enumeration values = request.getHeaders(header); - while (values.hasMoreElements()) - log.debug("Request - {}: {}", header, values.nextElement()); - } - log.debug("Invocing service method."); - - /** - * We cannot call invocation.service(), because we have to wrap the - * response. Therefore this was coppied from InvocationContextImpl. - */ - TestHttpServletResponse wrappedResponse = new TestHttpServletResponse(invocation.getResponse()); - if (invocation.isFilterActive()) { - invocation.getFilter().doFilter(invocation.getRequest(), wrappedResponse, invocation.getFilterChain()); - } - else { - invocation.getServlet().service(invocation.getRequest(), wrappedResponse); - } - - WebResponse response = client.getResponse(invocation); - log.debug("Response - {}: {}", response.getResponseCode(), response.getResponseMessage()); - log.debug("Response - {}, {} bytes", response.getContentType(), wrappedResponse.getCount()); - for (String header : response.getHeaderFieldNames()) { - for (String value : response.getHeaderFields(header)) { - log.debug("Response - {}: {}", header, value); - } - } - return response; - } - - - class TestHttpServletResponse extends HttpServletResponseWrapper { - - private CountingServletOutputStream out; - private HttpServletResponse response; - private ServletOutputStream stream; - private PrintWriter writer; - private boolean committed = false; - - - TestHttpServletResponse(HttpServletResponse response) { - super(response); - this.response = response; - } - - - public long getCount() { - if (out == null) - return -1l; - else - return out.count; - } - - - @Override - public void flushBuffer() throws IOException { - committed = true; - super.flushBuffer(); - } - - @Override - public int getBufferSize() { - return buffer; - } - - @Override - public boolean isCommitted() { - return committed; - } - - @Override - public void reset() { - if (committed) - throw new IllegalStateException("call to reset() after response has been commited!"); - if (out != null) - out.count = 0; - super.reset(); - } - - @Override - public void resetBuffer() { - if (committed) - throw new IllegalStateException("call to resetBuffer() after response has been commited!"); - if (out != null) - out.count = 0; - super.resetBuffer(); - } - - @Override - public void setBufferSize(int size) { - if (out != null && out.count > 0) - throw new IllegalStateException("call to setBuffer() after content has been written!"); - buffer = size; - } - - @Override - public ServletOutputStream getOutputStream() throws IOException { - - if (writer != null) - throw new IllegalStateException("ServletOutputStream and PrintWriter cannot be requested both!"); - - if (stream == null) { - out = new CountingServletOutputStream(response.getOutputStream()); - stream = out; - } - - return stream; - } - - @Override - public PrintWriter getWriter() throws IOException { - - if (stream != null) - throw new IllegalStateException("ServletOutputStream and PrintWriter cannot be requested both!"); - - if (writer == null) { - out = new CountingServletOutputStream(response.getOutputStream()); - writer = new PrintWriter(out); - } - - return writer; - } - - - class CountingServletOutputStream extends ServletOutputStream { - - private ServletOutputStream out; - long count = 0l; - - - CountingServletOutputStream(ServletOutputStream out) { - this.out = out; - } - - - @Override - public void write(int i) throws IOException { - count++; - /** Simulate commit, when count is getting bigger then buffer */ - if (count == buffer + 1) { - log.debug("simulating commit because buffer overflow! buffer: {}, count: {}", buffer, count); - committed = true; - } - out.write(i); - } - } - } -} - diff --git a/cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/ParameterGuessingTest.java b/cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/ParameterGuessingTest.java index 4d0ce9ab..e7b64f68 100644 --- a/cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/ParameterGuessingTest.java +++ b/cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/ParameterGuessingTest.java @@ -1,6 +1,7 @@ package de.halbekunst.juplo.cachecontrol; import com.meterware.httpunit.WebResponse; +import de.halbekunst.juplo.test.HttpTestCase; import java.net.URLEncoder; import org.junit.Test; import org.junit.runner.RunWith; @@ -30,6 +31,11 @@ public class ParameterGuessingTest extends HttpTestCase { private final static Logger log = LoggerFactory.getLogger(ParameterGuessingTest.class); + public ParameterGuessingTest() { + super("src/test/resources/web.xml"); + } + + @Test public void testNothingSet() throws Exception { diff --git a/cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/RequestSizeTest.java b/cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/RequestSizeTest.java index 172e3ba4..2b3fec85 100644 --- a/cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/RequestSizeTest.java +++ b/cachecontrol/src/test/java/de/halbekunst/juplo/cachecontrol/RequestSizeTest.java @@ -1,6 +1,8 @@ package de.halbekunst.juplo.cachecontrol; import com.meterware.httpunit.WebResponse; +import de.halbekunst.juplo.test.HttpTestCase; +import de.halbekunst.juplo.test.LoggingHttpServletResponseWrapper; import java.net.URLEncoder; import org.junit.Test; import org.junit.runner.RunWith; @@ -26,6 +28,11 @@ public class RequestSizeTest extends HttpTestCase { private final static Logger log = LoggerFactory.getLogger(RequestSizeTest.class); + public RequestSizeTest() { + super("src/test/resources/web.xml"); + } + + @Test public void testSimpleRequestWithGzip() throws Exception { @@ -138,7 +145,7 @@ public class RequestSizeTest extends HttpTestCase { uri.append(URLEncoder.encode("/forwarded?n=" + i*128, "UTF-8")); try { WebResponse response = executeRequest(uri.toString()); - if (i*128 > 2048) + if (i*128 > LoggingHttpServletResponseWrapper.DEFAULT_BUFFER_SIZE) Assert.fail("Error expected while forwarding after " + i*128 + " bytes written!"); Assert.assertEquals("W/\"Hallo Welt!\"", response.getHeaderField(Headers.HEADER_ETAG)); Assert.assertEquals("Thu, 01 Jan 1970 00:00:00 GMT", response.getHeaderField(Headers.HEADER_LAST_MODIFIED)); @@ -153,7 +160,7 @@ public class RequestSizeTest extends HttpTestCase { Assert.assertTrue("Expires-Header passt nicht zum Date-Header! Unterschied: " + (expires-date)/1000 + " Sekunden.", date + 3600000 == expires); } catch (IllegalStateException e) { - if (i*128 > 2048) + if (i*128 > LoggingHttpServletResponseWrapper.DEFAULT_BUFFER_SIZE) log.debug("Expected error while forwarding after {} bytes written: {}", i*128, e.getMessage()); else Assert.fail("Unexpected error while forwarding after " + i*128 + " bytes written: " + e.getMessage()); diff --git a/pom.xml b/pom.xml index 4583d129..5e4bba18 100644 --- a/pom.xml +++ b/pom.xml @@ -36,10 +36,10 @@ 1.6.11 - 1.7 + 1.7.1 1.0 4.8.1 - 1.2.15 + 1.2.16 2.5 slf4j-log4j12 1.6.1 diff --git a/test/pom.xml b/test/pom.xml index 5fc6b1c4..d13cdbf4 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -14,15 +14,47 @@ Juplo - Test + + + + httpunit + httpunit + ${httpunit.version} + + + junit + junit + + + javax.servlet + servlet-api + + + + + junit + junit + ${junit.version} + + + org.springframework + spring-test + ${springframework.version} + provided + + + org.springframework spring-beans ${springframework.version} + provided org.springframework spring-context ${springframework.version} + provided javax.servlet @@ -30,11 +62,6 @@ ${servlet-api.version} provided - - org.springframework - spring-test - ${springframework.version} - diff --git a/test/src/main/java/de/halbekunst/juplo/test/HttpTestCase.java b/test/src/main/java/de/halbekunst/juplo/test/HttpTestCase.java new file mode 100644 index 00000000..76c46468 --- /dev/null +++ b/test/src/main/java/de/halbekunst/juplo/test/HttpTestCase.java @@ -0,0 +1,84 @@ +package de.halbekunst.juplo.test; + +import com.meterware.httpunit.WebResponse; +import com.meterware.servletunit.InvocationContext; +import com.meterware.servletunit.ServletRunner; +import com.meterware.servletunit.ServletUnitClient; +import java.io.File; +import java.util.Enumeration; +import javax.servlet.http.HttpServletRequest; +import org.junit.Before; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author kai + */ +public abstract class HttpTestCase { + + private final static Logger log = LoggerFactory.getLogger(HttpTestCase.class); + + private ServletRunner sr; + private File config; + public ServletUnitClient client; + + + public HttpTestCase(String config) { + this(new File(config)); + } + + public HttpTestCase(File config) { + if (!config.exists()) + throw new RuntimeException("web.xml is missing: " + config + " does not exist."); + this.config = config; + } + + + @Before + public void init() throws Exception { + sr = new ServletRunner(config, ""); // Dies ist der einzige Konstruktor, der die Context-Root der Webapp im Testfall korrekt initialisiert :/ + client = sr.newClient(); + } + + public WebResponse executeRequest(String uri) throws Exception { + log.debug("---------- GET: {}", uri); + InvocationContext invocation = client.newInvocation(uri); + HttpServletRequest request = invocation.getRequest(); + log.debug("Request - {}: {}", request.getMethod(), request.getProtocol()); + Enumeration headers = request.getHeaderNames(); + while (headers.hasMoreElements()) { + String header = headers.nextElement(); + Enumeration values = request.getHeaders(header); + while (values.hasMoreElements()) + log.debug("Request - {}: {}", header, values.nextElement()); + } + + log.debug("Invocing service method."); + + /** + * We cannot call invocation.service(), because we have to wrap the + * response. Therefore this was coppied from InvocationContextImpl. + */ + LoggingHttpServletResponseWrapper wrappedResponse = + new LoggingHttpServletResponseWrapper(uri, invocation.getResponse()); + if (invocation.isFilterActive()) { + invocation.getFilter().doFilter(invocation.getRequest(), wrappedResponse, invocation.getFilterChain()); + } + else { + invocation.getServlet().service(invocation.getRequest(), wrappedResponse); + } + long count = wrappedResponse.close(); + + WebResponse response = invocation.getServletResponse(); + log.debug("Response - {}: {}", response.getResponseCode(), response.getResponseMessage()); + log.debug("Response - {}, {} bytes", response.getContentType(), count); + for (String header : response.getHeaderFieldNames()) { + for (String value : response.getHeaderFields(header)) { + log.debug("Response - {}: {}", header, value); + } + } + return response; + } +} + diff --git a/test/src/main/java/de/halbekunst/juplo/test/LoggingHttpServletResponseFilter.java b/test/src/main/java/de/halbekunst/juplo/test/LoggingHttpServletResponseFilter.java new file mode 100644 index 00000000..b9dad518 --- /dev/null +++ b/test/src/main/java/de/halbekunst/juplo/test/LoggingHttpServletResponseFilter.java @@ -0,0 +1,42 @@ +package de.halbekunst.juplo.test; + +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author kai + */ +public class LoggingHttpServletResponseFilter implements Filter { + + private final static Logger log = LoggerFactory.getLogger(LoggingHttpServletResponseWrapper.class); + + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest)req; + HttpServletResponse response = (HttpServletResponse)res; + log.info("counting request {}", request.getRequestURI()); + LoggingHttpServletResponseWrapper wrappedResponse = + new LoggingHttpServletResponseWrapper(request.getRequestURI(), response); + chain.doFilter(request, wrappedResponse); + log.info("response-size: {}", wrappedResponse.close()); + } + + @Override + public void destroy() { + } +} diff --git a/test/src/main/java/de/halbekunst/juplo/test/LoggingHttpServletResponseWrapper.java b/test/src/main/java/de/halbekunst/juplo/test/LoggingHttpServletResponseWrapper.java new file mode 100644 index 00000000..f654f2a7 --- /dev/null +++ b/test/src/main/java/de/halbekunst/juplo/test/LoggingHttpServletResponseWrapper.java @@ -0,0 +1,310 @@ +package de.halbekunst.juplo.test; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.Date; +import java.util.Locale; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author kai + */ +public class LoggingHttpServletResponseWrapper implements HttpServletResponse { + + private final static Logger log = LoggerFactory.getLogger(LoggingHttpServletResponseWrapper.class); + + public final static int DEFAULT_BUFFER_SIZE = 1024; + + private static long count = 0; + + private final Long no; + private final HttpServletResponse response; + private CountingServletOutputStream out; + private ServletOutputStream stream; + private PrintWriter writer; + private int buffer = DEFAULT_BUFFER_SIZE; + private boolean committed = false; + + + LoggingHttpServletResponseWrapper(String name, HttpServletResponse response) { + no = ++count; + log.debug("New request {}: {}", no, name); + this.response = response; + } + + + public long close() throws IOException { + if (out == null) { + return -1l; + } + else { + if (writer != null) + writer.close(); + else + stream.close(); + long result = out.count; + out = null; + buffer = DEFAULT_BUFFER_SIZE; + return result; + } + } + + @Override + public void flushBuffer() throws IOException { + log.debug("{} -- flushing buffer", no); + committed = true; + response.flushBuffer(); + } + + @Override + public int getBufferSize() { + log.trace("{} -- getting buffer size: {}", no, buffer); + return buffer; + } + + @Override + public boolean isCommitted() { + Boolean result = committed || response.isCommitted(); + log.trace("{} -- commited? {}", no, result); + return result; + } + + @Override + public void reset() { + log.debug("{} -- reset!", no); + if (committed) + throw new IllegalStateException("call to reset() after response has been commited!"); + if (out != null) + out.count = 0; + response.reset(); + } + + @Override + public void resetBuffer() { + log.debug("{} -- resetting buffer", no); + if (committed) + throw new IllegalStateException("call to resetBuffer() after response has been commited!"); + if (out != null) + out.count = 0; + response.resetBuffer(); + } + + @Override + public void setBufferSize(int size) { + log.debug("{} -- setting buffer size to {}", no, size); + if (out != null && out.count > 0) + throw new IllegalStateException("call to setBuffer() after content has been written!"); + response.setBufferSize(size); + buffer = size; + } + + @Override + public ServletOutputStream getOutputStream() throws IOException { + log.debug("{} -- getting output stream", no); + + if (writer != null) + throw new IllegalStateException("ServletOutputStream and PrintWriter cannot be requested both!"); + + if (stream == null) { + log.debug("{} -- creating new servlet output stream", no); + out = new CountingServletOutputStream(response.getOutputStream()); + stream = out; + } + + return stream; + } + + @Override + public PrintWriter getWriter() throws IOException { + log.debug("{} -- getting print writer", no); + + if (stream != null) + throw new IllegalStateException("ServletOutputStream and PrintWriter cannot be requested both!"); + + if (writer == null) { + log.debug("{} -- creating new print writer", no); + out = new CountingServletOutputStream(response.getOutputStream()); + OutputStreamWriter streamWriter = new OutputStreamWriter(out, response.getCharacterEncoding()); + writer = new PrintWriter(streamWriter); + } + + return writer; + } + + @Override + public void addCookie(Cookie cookie) { + log.debug("{} -- adding cookie: {}", no, cookie); + response.addCookie(cookie); + } + + @Override + public boolean containsHeader(String name) { + Boolean result = response.containsHeader(name); + log.trace("{} -- contains header {}? {}", new Object[] { no, name, result }); + return result; + } + + @Override + public String encodeURL(String url) { + log.trace("{} -- encoding url {}", no, url); + return response.encodeURL(url); + } + + @Override + public String encodeRedirectURL(String url) { + log.trace("{} -- encoding redirect url {}", no, url); + return response.encodeRedirectURL(url); + } + + @Override + public String encodeUrl(String url) { + log.trace("{} -- encoding url {}", no, url); + return response.encodeUrl(url); + } + + @Override + public String encodeRedirectUrl(String url) { + log.trace("{} -- encoding redirect url {}", no, url); + return response.encodeRedirectUrl(url); + } + + @Override + public void sendError(int sc, String msg) throws IOException { + log.debug("{} -- sending error: {}. {}", new Object[] { no, sc, msg }); + response.sendError(sc, msg); + } + + @Override + public void sendError(int sc) throws IOException { + log.debug("{} -- sending error: {}", no, sc); + } + + @Override + public void sendRedirect(String location) throws IOException { + log.debug("{} -- sending redirect: {}", no, location); + response.sendRedirect(location); + } + + @Override + public void setDateHeader(String name, long date) { + log.debug("{} -- setting date header {} to {}", new Object[] { no, name, new Date(date) }); + response.setDateHeader(name, date); + } + + @Override + public void addDateHeader(String name, long date) { + log.debug("{} -- adding date header {}: {}", new Object[] { no, name, new Date(date) }); + response.addDateHeader(name, date); + } + + @Override + public void setHeader(String name, String value) { + log.debug("{} -- setting header {} to {}", new Object[] { no, name, value }); + response.setHeader(name, value); + } + + @Override + public void addHeader(String name, String value) { + log.debug("{} -- adding header {}: {}", new Object[] { no, name, value }); + response.addHeader(name, value); + } + + @Override + public void setIntHeader(String name, int value) { + log.debug("{} -- seting int header {} to {}", new Object[] { no, name, value }); + response.setIntHeader(name, value); + } + + @Override + public void addIntHeader(String name, int value) { + log.debug("{} -- adding int header {}: {}", new Object[] { no, name, value }); + response.addIntHeader(name, value); + } + + @Override + public void setStatus(int sc) { + log.debug("{} -- setting status to {}", no, sc); + response.setStatus(sc); + } + + @Override + public void setStatus(int sc, String sm) { + log.debug("{} -- setting status to {} (message: {})", new Object[] { no, sc, sm }); + response.setStatus(sc, sm); + } + + @Override + public String getCharacterEncoding() { + String result = response.getCharacterEncoding(); + log.trace("{} -- character encoding: {}", no, result); + return result; + } + + @Override + public String getContentType() { + String result = response.getContentType(); + log.trace("{} -- content type: {}", no, result); + return result; + } + + @Override + public void setCharacterEncoding(String charset) { + log.debug("{} -- setting character encoding to {}", no, charset); + response.setCharacterEncoding(charset); + } + + @Override + public void setContentLength(int len) { + log.debug("{} -- setting content length to {}", no, len); + response.setContentLength(len); + } + + @Override + public void setContentType(String type) { + log.debug("{} -- setting content type to {}", no, type); + response.setContentType(type); + } + + @Override + public void setLocale(Locale loc) { + log.debug("{} -- setting locale to {}", no, loc); + response.setLocale(loc); + } + + @Override + public Locale getLocale() { + Locale locale = response.getLocale(); + log.trace("{} -- locale: {}", no, locale); + return locale; + } + + + class CountingServletOutputStream extends ServletOutputStream { + + private ServletOutputStream out; + long count = 0l; + + + CountingServletOutputStream(ServletOutputStream out) { + this.out = out; + } + + + @Override + public void write(int i) throws IOException { + count++; + /** Simulate commit, when count is getting bigger then buffer */ + if (count == buffer + 1) { + log.info("{} -- simulating commit because buffer overflow! buffer: {}, count: {}", new Object[] { no, buffer, count }); + committed = true; + } + log.trace("{} -- writing byte {}: {}", new Object[] { no, count, (char)i }); + out.write(i); + } + } +} -- 2.20.1