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 <[email protected]>
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
[email protected].