You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by an...@apache.org on 2022/07/21 17:49:33 UTC

[sling-org-apache-sling-servlet-helpers] branch feature/sling-11486-check-for-close-writer created (now 89a9846)

This is an automated email from the ASF dual-hosted git repository.

andysch pushed a change to branch feature/sling-11486-check-for-close-writer
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlet-helpers.git


      at 89a9846  SLING-11486 - Added the support for a Check-for-Closed Test Writer

This branch includes the following new commits:

     new 89a9846  SLING-11486 - Added the support for a Check-for-Closed Test Writer

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[sling-org-apache-sling-servlet-helpers] 01/01: SLING-11486 - Added the support for a Check-for-Closed Test Writer

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

andysch pushed a commit to branch feature/sling-11486-check-for-close-writer
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlet-helpers.git

commit 89a98465b51f1d759ca79cd9495e869370db93f6
Author: Andreas Schaefer <he...@adobe.com>
AuthorDate: Thu Jul 21 10:49:23 2022 -0700

    SLING-11486 - Added the support for a Check-for-Closed Test Writer
---
 .../MockSlingHttpServletResponse.java              |   6 +
 .../sling/servlethelpers/ResponseBodySupport.java  | 239 ++++++++++++++++++++-
 .../apache/sling/servlethelpers/package-info.java  |   2 +-
 .../MockSlingHttpServletResponseTest.java          |  17 ++
 4 files changed, 262 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponse.java b/src/main/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponse.java
index 2f6d9f7..d9fc329 100644
--- a/src/main/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponse.java
+++ b/src/main/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponse.java
@@ -39,6 +39,8 @@ public class MockSlingHttpServletResponse extends SlingAdaptable implements Slin
 
     static final String CHARSET_SEPARATOR = ";charset=";
 
+    private boolean enableCheckForClosedWriter = false;
+
     private String contentType;
     private String characterEncoding;
     private int contentLength;
@@ -51,6 +53,10 @@ public class MockSlingHttpServletResponse extends SlingAdaptable implements Slin
     private final ResponseBodySupport bodySupport = new ResponseBodySupport();
     private final CookieSupport cookieSupport = new CookieSupport();
 
+    public void setEnableCheckForClosedWriter(boolean enableCheckForClosedWriter) {
+        bodySupport.setEnableCheckForClosedWriter(enableCheckForClosedWriter);
+    }
+
     @Override
     public String getContentType() {
         if (this.contentType == null) {
diff --git a/src/main/java/org/apache/sling/servlethelpers/ResponseBodySupport.java b/src/main/java/org/apache/sling/servlethelpers/ResponseBodySupport.java
index e40bdfe..aaf8eda 100644
--- a/src/main/java/org/apache/sling/servlethelpers/ResponseBodySupport.java
+++ b/src/main/java/org/apache/sling/servlethelpers/ResponseBodySupport.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
+import java.util.Locale;
 
 import javax.servlet.ServletOutputStream;
 import javax.servlet.WriteListener;
@@ -35,6 +36,7 @@ import org.apache.commons.lang3.StringUtils;
  */
 class ResponseBodySupport {
 
+    private boolean enableCheckForClosedWriter = false;
     private ByteArrayOutputStream outputStream;
     private ServletOutputStream servletOutputStream;
     private PrintWriter printWriter;
@@ -43,6 +45,12 @@ class ResponseBodySupport {
         reset();
     }
 
+    public void setEnableCheckForClosedWriter(boolean enableCheckForClosedWriter) {
+        this.enableCheckForClosedWriter = enableCheckForClosedWriter;
+        reset();
+    }
+
+
     public void reset() {
         outputStream = new ByteArrayOutputStream();
         servletOutputStream = null;
@@ -72,7 +80,8 @@ class ResponseBodySupport {
     public PrintWriter getWriter(String charset) {
         if (printWriter == null) {
             try {
-                printWriter = new PrintWriter(new OutputStreamWriter(getOutputStream(), defaultCharset(charset)));
+                PrintWriter printWriter1 = new PrintWriter(new OutputStreamWriter(getOutputStream(), defaultCharset(charset)));
+                printWriter = enableCheckForClosedWriter ? new CheckForClosedPrintWriter(printWriter1) : printWriter1;
             } catch (UnsupportedEncodingException ex) {
                 throw new RuntimeException("Unsupported encoding: " + defaultCharset(charset), ex);
             }
@@ -106,4 +115,232 @@ class ResponseBodySupport {
         return StringUtils.defaultString(charset, CharEncoding.UTF_8);
     }
 
+    private class CheckForClosedPrintWriter extends PrintWriter {
+
+        private final PrintWriter delegatee;
+
+        private boolean isClosed = false;
+
+        public CheckForClosedPrintWriter(PrintWriter delegatee) {
+            super(delegatee);
+            this.delegatee = delegatee;
+        }
+
+        private void checkClosed() {
+            if ( this.isClosed ) {
+                throw new WriterAlreadyClosedException();
+            }
+        }
+
+        @Override
+        public PrintWriter append(final char arg0) {
+            this.checkClosed();
+            return delegatee.append(arg0);
+        }
+
+        @Override
+        public PrintWriter append(final CharSequence arg0, final int arg1, final int arg2) {
+            this.checkClosed();
+            return delegatee.append(arg0, arg1, arg2);
+        }
+
+        @Override
+        public PrintWriter append(final CharSequence arg0) {
+            this.checkClosed();
+            return delegatee.append(arg0);
+        }
+
+        @Override
+        public boolean checkError() {
+            this.checkClosed();
+            return delegatee.checkError();
+        }
+
+        @Override
+        public void close() {
+            this.checkClosed();
+            this.isClosed = true;
+            delegatee.close();
+        }
+
+        @Override
+        public void flush() {
+            this.checkClosed();
+            delegatee.flush();
+        }
+
+        @Override
+        public PrintWriter format(final Locale arg0, final String arg1,
+                                  final Object... arg2) {
+            this.checkClosed();
+            return delegatee.format(arg0, arg1, arg2);
+        }
+
+        @Override
+        public PrintWriter format(final String arg0, final Object... arg1) {
+            this.checkClosed();
+            return delegatee.format(arg0, arg1);
+        }
+
+        @Override
+        public void print(final boolean arg0) {
+            this.checkClosed();
+            delegatee.print(arg0);
+        }
+
+        @Override
+        public void print(final char arg0) {
+            this.checkClosed();
+            delegatee.print(arg0);
+        }
+
+        @Override
+        public void print(final char[] arg0) {
+            this.checkClosed();
+            delegatee.print(arg0);
+        }
+
+        @Override
+        public void print(final double arg0) {
+            this.checkClosed();
+            delegatee.print(arg0);
+        }
+
+        @Override
+        public void print(final float arg0) {
+            this.checkClosed();
+            delegatee.print(arg0);
+        }
+
+        @Override
+        public void print(final int arg0) {
+            this.checkClosed();
+            delegatee.print(arg0);
+        }
+
+        @Override
+        public void print(final long arg0) {
+            this.checkClosed();
+            delegatee.print(arg0);
+        }
+
+        @Override
+        public void print(final Object arg0) {
+            this.checkClosed();
+            delegatee.print(arg0);
+        }
+
+        @Override
+        public void print(final String arg0) {
+            this.checkClosed();
+            delegatee.print(arg0);
+        }
+
+        @Override
+        public PrintWriter printf(final Locale arg0, final String arg1,
+        final Object... arg2) {
+            this.checkClosed();
+            return delegatee.printf(arg0, arg1, arg2);
+        }
+
+        @Override
+        public PrintWriter printf(final String arg0, final Object... arg1) {
+            this.checkClosed();
+            return delegatee.printf(arg0, arg1);
+        }
+
+        @Override
+        public void println() {
+            this.checkClosed();
+            delegatee.println();
+        }
+
+        @Override
+        public void println(final boolean arg0) {
+            this.checkClosed();
+            delegatee.println(arg0);
+        }
+
+        @Override
+        public void println(final char arg0) {
+            this.checkClosed();
+            delegatee.println(arg0);
+        }
+
+        @Override
+        public void println(final char[] arg0) {
+            this.checkClosed();
+            delegatee.println(arg0);
+        }
+
+        @Override
+        public void println(final double arg0) {
+            this.checkClosed();
+            delegatee.println(arg0);
+        }
+
+        @Override
+        public void println(final float arg0) {
+            this.checkClosed();
+            delegatee.println(arg0);
+        }
+
+        @Override
+        public void println(final int arg0) {
+            this.checkClosed();
+            delegatee.println(arg0);
+        }
+
+        @Override
+        public void println(final long arg0) {
+            this.checkClosed();
+            delegatee.println(arg0);
+        }
+
+        @Override
+        public void println(final Object arg0) {
+            this.checkClosed();
+            delegatee.println(arg0);
+        }
+
+        @Override
+        public void println(final String arg0) {
+            this.checkClosed();
+            delegatee.println(arg0);
+        }
+
+        @Override
+        public void write(final char[] arg0, final int arg1, final int arg2) {
+            this.checkClosed();
+            delegatee.write(arg0, arg1, arg2);
+        }
+
+        @Override
+        public void write(final char[] arg0) {
+            this.checkClosed();
+            delegatee.write(arg0);
+        }
+
+        @Override
+        public void write(final int arg0) {
+            this.checkClosed();
+            delegatee.write(arg0);
+        }
+
+        @Override
+        public void write(final String arg0, final int arg1, final int arg2) {
+            this.checkClosed();
+            delegatee.write(arg0, arg1, arg2);
+        }
+
+        @Override
+        public void write(final String arg0) {
+            this.checkClosed();
+            delegatee.write(arg0);
+        }
+
+    };
+
+    public class WriterAlreadyClosedException extends RuntimeException {
+    }
 }
diff --git a/src/main/java/org/apache/sling/servlethelpers/package-info.java b/src/main/java/org/apache/sling/servlethelpers/package-info.java
index 1a22083..2bcdb37 100644
--- a/src/main/java/org/apache/sling/servlethelpers/package-info.java
+++ b/src/main/java/org/apache/sling/servlethelpers/package-info.java
@@ -19,5 +19,5 @@
 /**
  * Mock implementation of selected Servlet-related Sling APIs.
  */
-@org.osgi.annotation.versioning.Version("1.8")
+@org.osgi.annotation.versioning.Version("1.9")
 package org.apache.sling.servlethelpers;
diff --git a/src/test/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponseTest.java b/src/test/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponseTest.java
index 1800b22..2ab0300 100644
--- a/src/test/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponseTest.java
+++ b/src/test/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponseTest.java
@@ -25,8 +25,11 @@ import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Mockito.when;
 
+import java.io.IOException;
+import java.io.Writer;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Locale;
@@ -38,6 +41,7 @@ import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.lang3.CharEncoding;
 import org.apache.sling.api.adapter.AdapterManager;
 import org.apache.sling.api.adapter.SlingAdaptable;
+import org.apache.sling.servlethelpers.ResponseBodySupport.WriterAlreadyClosedException;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -238,4 +242,17 @@ public class MockSlingHttpServletResponseTest {
         assertNotEquals(result1,  result2);
     }
 
+    @Test
+    public void testCheckForClosedWriter() throws IOException {
+        response.setEnableCheckForClosedWriter(true);
+        Writer writer = response.getWriter();
+        // Close it twice and make sure the second one fails
+        writer.close();
+        try {
+            writer.close();
+            fail("Subsequent Closing of a Check-for-Closed Writer was not failing");
+        } catch(WriterAlreadyClosedException e) {
+            // Expected
+        }
+    }
 }