juneau-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamesbog...@apache.org
Subject [juneau] branch master updated: JUNEAU-80 - DefaultHandler should not close the underlying output stream.
Date Sat, 03 Feb 2018 20:28:49 GMT
This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new f3dcd74  JUNEAU-80 - DefaultHandler should not close the underlying output stream.
f3dcd74 is described below

commit f3dcd74120494348f6e3c1f3264751a0e9048833
Author: JamesBognar <jamesbognar@apache.org>
AuthorDate: Sat Feb 3 15:28:46 2018 -0500

    JUNEAU-80 - DefaultHandler should not close the underlying output
    stream.
---
 .../encoders/{GzipEncoder.java => Finishable.java} | 77 ++++++++-----------
 .../org/apache/juneau/encoders/GzipEncoder.java    | 14 ++--
 juneau-doc/src/main/javadoc/overview.html          |  7 ++
 .../apache/juneau/rest/FinishablePrintWriter.java  | 89 +++++++++++-----------
 .../juneau/rest/FinishableServletOutputStream.java | 78 +++++++++++++++++++
 .../java/org/apache/juneau/rest/RestResponse.java  | 56 ++++----------
 .../org/apache/juneau/rest/StreamResource.java     |  1 +
 .../juneau/rest/response/DefaultHandler.java       | 15 ++--
 8 files changed, 191 insertions(+), 146 deletions(-)

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/GzipEncoder.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/Finishable.java
similarity index 66%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/GzipEncoder.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/Finishable.java
index 8ebad4c..c86c116 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/GzipEncoder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/Finishable.java
@@ -1,46 +1,31 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.
 The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance            *
-// * with the License.  You may obtain a copy of the License at                         
                                    *
-// *                                                                                    
                                    *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                        
                                    *
-// *                                                                                    
                                    *
-// * Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the        *
-// * specific language governing permissions and limitations under the License.         
                                    *
-// ***************************************************************************************************************************
-package org.apache.juneau.encoders;
-
-import java.io.*;
-import java.util.zip.*;
-
-/**
- * Encoder for handling <js>"gzip"</js> encoding and decoding.
- */
-public class GzipEncoder extends Encoder {
-
-	@Override /* Encoder */
-	public OutputStream getOutputStream(OutputStream os) throws IOException {
-		return new GZIPOutputStream(os) {
-			@Override /* OutputStream */
-			public final void close() throws IOException {
-				finish();
-				super.close();
-			}
-		};
-	}
-
-	@Override /* Encoder */
-	public InputStream getInputStream(InputStream is) throws IOException {
-		return new GZIPInputStream(is);
-	}
-
-	/**
-	 * Returns <code>[<js>"gzip"</js>]</code>.
-	 */
-	@Override /* Encoder */
-	public String[] getCodings() {
-		return new String[]{"gzip"};
-	}
-}
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.
 The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance            *
+// * with the License.  You may obtain a copy of the License at                         
                                    * 
+// *                                                                                    
                                    *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                        
                                    *
+// *                                                                                    
                                    *
+// * Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the        *
+// * specific language governing permissions and limitations under the License.         
                                    *
+// ***************************************************************************************************************************
+package org.apache.juneau.encoders;
+
+import java.io.*;
+
+/**
+ * Interface that identifies an output stream has having a <code>finish()</code>
method.
+ */
+public interface Finishable {
+
+	/**
+	 * Finishes writing compressed data to the output stream without closing the underlying
stream. 
+	 * 
+	 * <p>
+	 * Use this method when applying multiple filters in succession to the same output stream.
+	 * 
+	 * @throws IOException
+	 */
+	void finish() throws IOException;
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/GzipEncoder.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/GzipEncoder.java
index 8ebad4c..1596af5 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/GzipEncoder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/GzipEncoder.java
@@ -22,13 +22,7 @@ public class GzipEncoder extends Encoder {
 
 	@Override /* Encoder */
 	public OutputStream getOutputStream(OutputStream os) throws IOException {
-		return new GZIPOutputStream(os) {
-			@Override /* OutputStream */
-			public final void close() throws IOException {
-				finish();
-				super.close();
-			}
-		};
+		return new FinishableGZIPOutputStream(os);
 	}
 
 	@Override /* Encoder */
@@ -43,4 +37,10 @@ public class GzipEncoder extends Encoder {
 	public String[] getCodings() {
 		return new String[]{"gzip"};
 	}
+	
+	private static class FinishableGZIPOutputStream extends GZIPOutputStream implements Finishable
{
+		FinishableGZIPOutputStream(OutputStream out) throws IOException {
+			super(out);
+		}
+	}
 }
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 9ed4114..18d8491 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -13356,6 +13356,13 @@
 					<li>{@link org.apache.juneau.rest.ReaderResourceBuilder}
 					<li>{@link org.apache.juneau.rest.StreamResourceBuilder}
 				</ul>
+			<li>
+				{@link org.apache.juneau.rest.RestResponse#getNegotiatedOutputStream()} now returns a

+				{@link org.apache.juneau.rest.FinishableServletOutputStream} and {@link org.apache.juneau.rest.RestResponse#getNegotiatedWriter()}
+				now returns a {@link org.apache.juneau.rest.FinishablePrintWriter} that allows you to
finish the output
+				without closing the stream.
+				<br>The {@link org.apache.juneau.rest.response.DefaultHandler} class now calls
<code>finish()</code>
+				instead of <code>close()</code> on the stream.
 		</ul>
 
 		<h5 class='topic'>juneau-rest-client</h5>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/GzipEncoder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/FinishablePrintWriter.java
similarity index 65%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/GzipEncoder.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/FinishablePrintWriter.java
index 8ebad4c..4af84f4 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/GzipEncoder.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/FinishablePrintWriter.java
@@ -1,46 +1,43 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.
 The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance            *
-// * with the License.  You may obtain a copy of the License at                         
                                    *
-// *                                                                                    
                                    *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                        
                                    *
-// *                                                                                    
                                    *
-// * Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the        *
-// * specific language governing permissions and limitations under the License.         
                                    *
-// ***************************************************************************************************************************
-package org.apache.juneau.encoders;
-
-import java.io.*;
-import java.util.zip.*;
-
-/**
- * Encoder for handling <js>"gzip"</js> encoding and decoding.
- */
-public class GzipEncoder extends Encoder {
-
-	@Override /* Encoder */
-	public OutputStream getOutputStream(OutputStream os) throws IOException {
-		return new GZIPOutputStream(os) {
-			@Override /* OutputStream */
-			public final void close() throws IOException {
-				finish();
-				super.close();
-			}
-		};
-	}
-
-	@Override /* Encoder */
-	public InputStream getInputStream(InputStream is) throws IOException {
-		return new GZIPInputStream(is);
-	}
-
-	/**
-	 * Returns <code>[<js>"gzip"</js>]</code>.
-	 */
-	@Override /* Encoder */
-	public String[] getCodings() {
-		return new String[]{"gzip"};
-	}
-}
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.
 The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance            *
+// * with the License.  You may obtain a copy of the License at                         
                                    * 
+// *                                                                                    
                                    *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                        
                                    *
+// *                                                                                    
                                    *
+// * Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the        *
+// * specific language governing permissions and limitations under the License.         
                                    *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import java.io.*;
+
+import org.apache.juneau.encoders.*;
+
+/**
+ * A wrapped {@link PrintWriter} with an added <code>finish()</code> method.
+ */
+public class FinishablePrintWriter extends PrintWriter implements Finishable {
+
+	final Finishable f;
+
+	FinishablePrintWriter(OutputStream out, String characterEncoding) throws IOException {
+		super(new OutputStreamWriter(out, characterEncoding));
+		f = (out instanceof Finishable ? (Finishable)out : null);
+	}
+
+
+	/**
+	 * Calls {@link Finishable#finish()} on the underlying output stream.
+	 * 
+	 * <p>
+	 * A no-op if the underlying output stream does not implement the {@link Finishable} interface.
+	 */
+	@Override /* Finishable */
+	public void finish() throws IOException {
+		if (f != null)
+			f.finish();
+	}
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/FinishableServletOutputStream.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/FinishableServletOutputStream.java
new file mode 100644
index 0000000..87e2044
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/FinishableServletOutputStream.java
@@ -0,0 +1,78 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.
 The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance            *
+// * with the License.  You may obtain a copy of the License at                         
                                    * 
+// *                                                                                    
                                    *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                        
                                    *
+// *                                                                                    
                                    *
+// * Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the        *
+// * specific language governing permissions and limitations under the License.         
                                    *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import java.io.*;
+
+import javax.servlet.*;
+
+import org.apache.juneau.encoders.*;
+
+/**
+ * A wrapped {@link ServletOutputStream} with an added <code>finish()</code>
method.
+ */
+public class FinishableServletOutputStream extends ServletOutputStream implements Finishable
{
+
+	final OutputStream os;
+	final ServletOutputStream sos;
+	final Finishable f;
+	
+	FinishableServletOutputStream(OutputStream os) {
+		this.os = os;
+		this.sos = (os instanceof ServletOutputStream ? (ServletOutputStream)os : null);
+		this.f = (os instanceof Finishable ? (Finishable)os : null);
+	}
+	
+	@Override /* OutputStream */
+	public final void write(byte[] b, int off, int len) throws IOException {
+		os.write(b, off, len);
+	}
+	
+	@Override /* OutputStream */
+	public final void write(int b) throws IOException {
+		os.write(b);
+	}
+	
+	@Override /* OutputStream */
+	public final void flush() throws IOException {
+		os.flush();
+	}
+	
+	@Override /* OutputStream */
+	public final void close() throws IOException {
+		os.close();
+	}
+	
+	@Override /* ServletOutputStream */
+	public boolean isReady() {
+		return sos == null ? true : sos.isReady();
+	}
+	
+	@Override /* ServletOutputStream */
+	public void setWriteListener(WriteListener arg0) {
+		if (sos != null)
+			sos.setWriteListener(arg0);
+	}
+
+	/**
+	 * Calls {@link Finishable#finish()} on the underlying output stream.
+	 * 
+	 * <p>
+	 * A no-op if the underlying output stream does not implement the {@link Finishable} interface.
+	 */
+	@Override /* Finishable */
+	public void finish() throws IOException {
+		if (f != null)
+			f.finish();
+	}
+}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
index 21f196b..1228145 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java
@@ -58,8 +58,9 @@ public final class RestResponse extends HttpServletResponseWrapper {
 	private Object output;                       // The POJO being sent to the output.
 	private boolean isNullOutput;                // The output is null (as opposed to not being
set at all)
 	private RequestProperties properties;                // Response properties
-	private ServletOutputStream os;
-	private PrintWriter w;
+	private ServletOutputStream sos;
+	private FinishableServletOutputStream os;
+	private FinishablePrintWriter w;
 	private HtmlDocBuilder htmlDocBuilder;
 
 	/**
@@ -347,7 +348,7 @@ public final class RestResponse extends HttpServletResponseWrapper {
 	 * @return A negotiated output stream.
 	 * @throws IOException
 	 */
-	public ServletOutputStream getNegotiatedOutputStream() throws IOException {
+	public FinishableServletOutputStream getNegotiatedOutputStream() throws IOException {
 		if (os == null) {
 			Encoder encoder = null;
 			EncoderGroup encoders = restJavaMethod.encoders;
@@ -372,46 +373,18 @@ public final class RestResponse extends HttpServletResponseWrapper {
 						setHeader("content-encoding", encoding);
 				}
 			}
-			os = getOutputStream();
-			if (encoder != null) {
-				@SuppressWarnings("resource")
-				final OutputStream os2 = encoder.getOutputStream(os);
-				os = new ServletOutputStream(){
-					@Override /* OutputStream */
-					public final void write(byte[] b, int off, int len) throws IOException {
-						os2.write(b, off, len);
-					}
-					@Override /* OutputStream */
-					public final void write(int b) throws IOException {
-						os2.write(b);
-					}
-					@Override /* OutputStream */
-					public final void flush() throws IOException {
-						os2.flush();
-					}
-					@Override /* OutputStream */
-					public final void close() throws IOException {
-						os2.close();
-					}
-					@Override /* ServletOutputStream */
-					public boolean isReady() {
-						return true;
-					}
-					@Override /* ServletOutputStream */
-					public void setWriteListener(WriteListener arg0) {
-						throw new NoSuchMethodError();
-					}
-				};
-			}
+			@SuppressWarnings("resource")
+			ServletOutputStream sos = getOutputStream();
+			os = new FinishableServletOutputStream(encoder == null ? sos : encoder.getOutputStream(sos));

 		}
 		return os;
 	}
 
 	@Override /* ServletResponse */
 	public ServletOutputStream getOutputStream() throws IOException {
-		if (os == null)
-			os = super.getOutputStream();
-		return os;
+		if (sos == null)
+			sos = super.getOutputStream();
+		return sos;
 	}
 
 	/**
@@ -420,7 +393,7 @@ public final class RestResponse extends HttpServletResponseWrapper {
 	 * @return <jk>true</jk> if {@link #getOutputStream()} has been called.
 	 */
 	public boolean getOutputStreamCalled() {
-		return os != null;
+		return sos != null;
 	}
 
 	/**
@@ -463,11 +436,12 @@ public final class RestResponse extends HttpServletResponseWrapper {
 	 * @return The negotiated writer.
 	 * @throws IOException
 	 */
-	public PrintWriter getNegotiatedWriter() throws IOException {
+	public FinishablePrintWriter getNegotiatedWriter() throws IOException {
 		return getWriter(false);
 	}
 
-	private PrintWriter getWriter(boolean raw) throws IOException {
+	@SuppressWarnings("resource")
+	private FinishablePrintWriter getWriter(boolean raw) throws IOException {
 		if (w != null)
 			return w;
 
@@ -477,7 +451,7 @@ public final class RestResponse extends HttpServletResponseWrapper {
 
 		try {
 			OutputStream out = (raw ? getOutputStream() : getNegotiatedOutputStream());
-			w = new PrintWriter(new OutputStreamWriter(out, getCharacterEncoding()));
+			w = new FinishablePrintWriter(out, getCharacterEncoding());
 			return w;
 		} catch (UnsupportedEncodingException e) {
 			String ce = getCharacterEncoding();
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/StreamResource.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/StreamResource.java
index e8ba790..a62cb17 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/StreamResource.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/StreamResource.java
@@ -114,6 +114,7 @@ public class StreamResource implements Streamable {
 	public void streamTo(OutputStream os) throws IOException {
 		for (byte[] b : contents)
 			os.write(b);
+		os.flush();
 	}
 
 	@Override /* Streamable */
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
index 609a862..96a5ba1 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
@@ -69,20 +69,23 @@ public class DefaultHandler implements ResponseHandler {
 
 				if (! session.isWriterSerializer()) {
 					if (req.isPlainText()) {
-						Writer w = res.getNegotiatedWriter();
+						FinishablePrintWriter w = res.getNegotiatedWriter();
 						ByteArrayOutputStream baos = new ByteArrayOutputStream();
 						session.serialize(output, baos);
 						w.write(StringUtils.toSpacedHex(baos.toByteArray()));
-						w.close();  // Leave open if exception occurs.
+						w.flush();
+						w.finish();
 					} else {
-						OutputStream os = res.getNegotiatedOutputStream();
+						FinishableServletOutputStream os = res.getNegotiatedOutputStream();
 						session.serialize(output, os);
-						os.close();  // Leave open if exception occurs.
+						os.flush();
+						os.finish();
 					}
 				} else {
-					Writer w = res.getNegotiatedWriter();
+					FinishablePrintWriter w = res.getNegotiatedWriter();
 					session.serialize(output, w);
-					w.close();  // Leave open if exception occurs.
+					w.flush();
+					w.finish();
 				}
 			} catch (SerializeException e) {
 				throw new RestException(SC_INTERNAL_SERVER_ERROR, e);

-- 
To stop receiving notification emails like this one, please contact
jamesbognar@apache.org.

Mime
View raw message