From dc24b5515ce531a21016641c5c5a887df8de4d49 Mon Sep 17 00:00:00 2001 From: Manfred Riem Date: Mon, 14 Aug 2023 17:17:10 -0500 Subject: [PATCH] Fixes #3412 - Fix TCK test --- .../core/api/WebApplicationPrintWriter.java} | 43 ++++----- .../core/api/WebApplicationResponse.java | 5 + .../DefaultWebApplicationPrintWriter.java | 94 +++++++++++++++++++ .../impl/DefaultWebApplicationResponse.java | 7 +- core/impl/src/main/java/module-info.java | 1 + ...efaultWebApplicationOutputStreamTest.java} | 42 ++------- .../DefaultWebApplicationResponseTest.java | 19 ++++ 7 files changed, 156 insertions(+), 55 deletions(-) rename core/{impl/src/test/java/cloud/piranha/core/impl/ServletOutputStreamTest.java => api/src/main/java/cloud/piranha/core/api/WebApplicationPrintWriter.java} (69%) create mode 100644 core/impl/src/main/java/cloud/piranha/core/impl/DefaultWebApplicationPrintWriter.java rename core/{tests/src/main/java/cloud/piranha/core/tests/ServletOutputStreamTest.java => impl/src/test/java/cloud/piranha/core/impl/DefaultWebApplicationOutputStreamTest.java} (72%) diff --git a/core/impl/src/test/java/cloud/piranha/core/impl/ServletOutputStreamTest.java b/core/api/src/main/java/cloud/piranha/core/api/WebApplicationPrintWriter.java similarity index 69% rename from core/impl/src/test/java/cloud/piranha/core/impl/ServletOutputStreamTest.java rename to core/api/src/main/java/cloud/piranha/core/api/WebApplicationPrintWriter.java index a9daa96bf9..70c23819d8 100644 --- a/core/impl/src/test/java/cloud/piranha/core/impl/ServletOutputStreamTest.java +++ b/core/api/src/main/java/cloud/piranha/core/api/WebApplicationPrintWriter.java @@ -25,31 +25,32 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -package cloud.piranha.core.impl; +package cloud.piranha.core.api; -import cloud.piranha.core.api.WebApplication; -import cloud.piranha.core.api.WebApplicationRequest; -import cloud.piranha.core.api.WebApplicationResponse; +import java.io.PrintWriter; +import java.io.Writer; /** - * The JUnit tests for the ServletOutputStream API. - * + * The WebApplicationPrintWriter API. + * * @author Manfred Riem (mriem@manorrock.com) */ -public class ServletOutputStreamTest extends cloud.piranha.core.tests.ServletOutputStreamTest { - - @Override - public WebApplication createWebApplication() { - return new DefaultWebApplication(); - } - - @Override - public WebApplicationRequest createWebApplicationRequest() { - return new DefaultWebApplicationRequest(); - } - - @Override - public WebApplicationResponse createWebApplicationResponse() { - return new DefaultWebApplicationResponse(); +public class WebApplicationPrintWriter extends PrintWriter { + + /** + * Stores the response object. + */ + protected WebApplicationResponse response; + + /** + * Constructor. + * + * @param response the response object. + * @param writer the writer. + * @param autoFlush the auto flush flag. + */ + public WebApplicationPrintWriter(WebApplicationResponse response, Writer writer, boolean autoFlush) { + super(writer, autoFlush); + this.response = response; } } diff --git a/core/api/src/main/java/cloud/piranha/core/api/WebApplicationResponse.java b/core/api/src/main/java/cloud/piranha/core/api/WebApplicationResponse.java index d44605c124..fe75f1b317 100644 --- a/core/api/src/main/java/cloud/piranha/core/api/WebApplicationResponse.java +++ b/core/api/src/main/java/cloud/piranha/core/api/WebApplicationResponse.java @@ -49,6 +49,11 @@ public interface WebApplicationResponse extends HttpServletResponse { * @return the content language. */ String getContentLanguage(); + + /** + * Get the content length. + */ + long getContentLength(); /** * {@return the cookies} diff --git a/core/impl/src/main/java/cloud/piranha/core/impl/DefaultWebApplicationPrintWriter.java b/core/impl/src/main/java/cloud/piranha/core/impl/DefaultWebApplicationPrintWriter.java new file mode 100644 index 0000000000..88080908ba --- /dev/null +++ b/core/impl/src/main/java/cloud/piranha/core/impl/DefaultWebApplicationPrintWriter.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2002-2023 Manorrock.com. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package cloud.piranha.core.impl; + +import cloud.piranha.core.api.WebApplicationPrintWriter; +import cloud.piranha.core.api.WebApplicationResponse; +import java.io.IOException; +import java.io.Writer; + +/** + * The PrintWriter for a WebApplicationResponse. + * + * @author Manfred Riem (mriem@manorrock.com) + */ +public class DefaultWebApplicationPrintWriter extends WebApplicationPrintWriter { + + /** + * Stores the content length. + */ + private long contentLength = -1; + + /** + * Stores the content written. + */ + private long contentWritten = 0; + + /** + * Constructor. + * + * @param response the response object. + * @param writer the writer. + * @param autoFlush the auto flush flag. + */ + public DefaultWebApplicationPrintWriter(WebApplicationResponse response, Writer writer, boolean autoFlush) { + super(response, writer, autoFlush); + contentLength = response.getContentLength() * 2; + } + + @Override + public void write(char[] characters) { + if (characters != null) { + for (int i = 0; i < characters.length; i++) { + write(characters[i]); + } + } + } + + @Override + public void write(String s) { + if (s != null) { + s.chars().forEach(c -> write(c)); + } + } + + @Override + public void write(int c) { + super.write(c); + if (contentLength > 0) { + contentWritten++; + if (contentWritten > contentLength) { + try { + response.flushBuffer(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + } + } +} diff --git a/core/impl/src/main/java/cloud/piranha/core/impl/DefaultWebApplicationResponse.java b/core/impl/src/main/java/cloud/piranha/core/impl/DefaultWebApplicationResponse.java index 95096c1292..65ace4ab4c 100644 --- a/core/impl/src/main/java/cloud/piranha/core/impl/DefaultWebApplicationResponse.java +++ b/core/impl/src/main/java/cloud/piranha/core/impl/DefaultWebApplicationResponse.java @@ -316,6 +316,11 @@ public String getCharacterEncoding() { public String getContentLanguage() { return contentLanguage; } + + @Override + public long getContentLength() { + return contentLength; + } @Override public String getContentType() { @@ -409,7 +414,7 @@ public synchronized PrintWriter getWriter() throws IOException { setCharacterEncoding(ISO_8859_1); } gotWriter = true; - writer = new PrintWriter(new OutputStreamWriter(webApplicationOutputStream, characterEncoding), false); + writer = new DefaultWebApplicationPrintWriter(this, new OutputStreamWriter(webApplicationOutputStream, characterEncoding), false); } result = writer; } else { diff --git a/core/impl/src/main/java/module-info.java b/core/impl/src/main/java/module-info.java index cf8a182427..8f10a49ac4 100644 --- a/core/impl/src/main/java/module-info.java +++ b/core/impl/src/main/java/module-info.java @@ -37,4 +37,5 @@ opens cloud.piranha.core.impl; requires transitive cloud.piranha.core.api; requires transitive cloud.piranha.resource.impl; + requires java.base; } diff --git a/core/tests/src/main/java/cloud/piranha/core/tests/ServletOutputStreamTest.java b/core/impl/src/test/java/cloud/piranha/core/impl/DefaultWebApplicationOutputStreamTest.java similarity index 72% rename from core/tests/src/main/java/cloud/piranha/core/tests/ServletOutputStreamTest.java rename to core/impl/src/test/java/cloud/piranha/core/impl/DefaultWebApplicationOutputStreamTest.java index ec9c5135c8..b95dc8ee3c 100644 --- a/core/tests/src/main/java/cloud/piranha/core/tests/ServletOutputStreamTest.java +++ b/core/impl/src/test/java/cloud/piranha/core/impl/DefaultWebApplicationOutputStreamTest.java @@ -25,11 +25,8 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -package cloud.piranha.core.tests; +package cloud.piranha.core.impl; -import cloud.piranha.core.api.WebApplication; -import cloud.piranha.core.api.WebApplicationRequest; -import cloud.piranha.core.api.WebApplicationResponse; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.WriteListener; import java.io.IOException; @@ -37,49 +34,28 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; /** - * The JUnit tests for the ServletOutputStream API. - * + * The JUnit tests for the DefaultWebApplicationResponse class. + * * @author Manfred Riem (mriem@manorrock.com) */ -public abstract class ServletOutputStreamTest { - - /** - * Create a web application. - * - * @return the web application. - */ - public abstract WebApplication createWebApplication(); - - /** - * Create a web application request. - * - * @return the web application request. - */ - public abstract WebApplicationRequest createWebApplicationRequest(); - - /** - * Create a web application response. - * - * @return the web application response. - */ - public abstract WebApplicationResponse createWebApplicationResponse(); - +class DefaultWebApplicationOutputStreamTest { + /** * Test isReady method. - * + * * @throws Exception when a serious error occurs. */ void testIsReady() throws Exception { - WebApplicationResponse response = createWebApplicationResponse(); + DefaultWebApplicationResponse response = new DefaultWebApplicationResponse(); ServletOutputStream outputStream = response.getOutputStream(); assertFalse(outputStream.isReady()); } - + /** * Test setWriteListener method. */ void testWriteListener() throws Exception { - WebApplicationResponse response = createWebApplicationResponse(); + DefaultWebApplicationResponse response = new DefaultWebApplicationResponse(); ServletOutputStream outputStream = response.getOutputStream(); outputStream.setWriteListener(new WriteListener() { @Override diff --git a/core/impl/src/test/java/cloud/piranha/core/impl/DefaultWebApplicationResponseTest.java b/core/impl/src/test/java/cloud/piranha/core/impl/DefaultWebApplicationResponseTest.java index e8a5fb2ad6..5d6ee299c8 100644 --- a/core/impl/src/test/java/cloud/piranha/core/impl/DefaultWebApplicationResponseTest.java +++ b/core/impl/src/test/java/cloud/piranha/core/impl/DefaultWebApplicationResponseTest.java @@ -192,6 +192,25 @@ void testFlushBuffer() { fail(); } } + + /** + * Test flushBuffer method. + * + * @throws Exception when a serious error occurs. + */ + @Test + void testFlushBuffer2() throws Exception { + DefaultWebApplicationResponse response = new DefaultWebApplicationResponse(); + response.setContentLength(20); + PrintWriter writer = response.getWriter(); + writer.print("0123456789"); + writer.print("0123456789"); + writer.print("0123456789"); + writer.print("0123456789"); + writer.println("And we flushed!"); + response.addIntHeader("header1", 12345); + assertNull(response.getHeader("header1")); + } /** * Test getBufferSize method.