111
111
112
112
import jakarta .servlet .http .HttpServletRequest ;
113
113
import jakarta .servlet .http .HttpServletResponse ;
114
+
115
+ import javax .annotation .Nullable ;
114
116
import javax .xml .XMLConstants ;
115
117
import javax .xml .parsers .ParserConfigurationException ;
116
118
import javax .xml .stream .XMLStreamException ;
@@ -1851,14 +1853,22 @@ private void writeResourceAs(final DocumentImpl resource, final DBBroker broker,
1851
1853
outputProperties .setProperty ("omit-xml-declaration" , "no" );
1852
1854
}
1853
1855
1854
- final OutputStreamWriter writer = new OutputStreamWriter (response .getOutputStream (), encoding );
1855
- sax .setOutput (writer , outputProperties );
1856
- serializer .setSAXHandlers (sax , sax );
1856
+ // NOTE(AR) we only close the OutputStreamWriter if serialization succeeds, otherwise we raise a BadRequestException below which needs the OutputStream to remain open so that it can report the issue via the HTTP response to the client
1857
+ @ Nullable Writer writerToClose = null ;
1858
+ try {
1859
+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
1860
+ sax .setOutput (writer , outputProperties );
1861
+ serializer .setSAXHandlers (sax , sax );
1857
1862
1858
- serializer .toSAX (resource );
1863
+ serializer .toSAX (resource );
1859
1864
1860
- writer .flush ();
1861
- writer .close (); // DO NOT use in try-write-resources, otherwise ther response stream is always closed, and we can't report the errors
1865
+ writer .flush ();
1866
+ writerToClose = writer ;
1867
+ } finally {
1868
+ if (writerToClose != null ) {
1869
+ writerToClose .close ();
1870
+ }
1871
+ }
1862
1872
} catch (final SAXException saxe ) {
1863
1873
LOG .warn (saxe );
1864
1874
throw new BadRequestException ("Error while serializing XML: " + saxe .getMessage ());
@@ -1894,28 +1904,36 @@ private void writeXPathExceptionHtml(final HttpServletResponse response,
1894
1904
1895
1905
response .setContentType (MimeType .HTML_TYPE .getName () + "; charset=" + encoding );
1896
1906
1897
- final OutputStreamWriter writer = new OutputStreamWriter (response .getOutputStream (), encoding );
1898
- writer .write (QUERY_ERROR_HEAD );
1899
- writer .write ("<p class=\" path\" ><span class=\" high\" >Path</span>: " );
1900
- writer .write ("<a href=\" " );
1901
- writer .write (path );
1902
- writer .write ("\" >" );
1903
- writer .write (path );
1904
- writer .write ("</a>" );
1905
-
1906
- writer .write ("<p class=\" errmsg\" >" );
1907
- final String message = e .getMessage () == null ? e .toString () : e .getMessage ();
1908
- writer .write (XMLUtil .encodeAttrMarkup (message ));
1909
- writer .write ("" );
1910
- if (query != null ) {
1911
- writer .write ("<span class=\" high\" >Query</span>:<pre>" );
1912
- writer .write (XMLUtil .encodeAttrMarkup (query ));
1913
- writer .write ("</pre>" );
1914
- }
1915
- writer .write ("</body></html>" );
1907
+ // NOTE(AR) we only close the OutputStreamWriter if serialization succeeds, otherwise we raise a BadRequestException below which needs the OutputStream to remain open so that it can report the issue via the HTTP response to the client
1908
+ @ Nullable Writer writerToClose = null ;
1909
+ try {
1910
+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
1911
+ writer .write (QUERY_ERROR_HEAD );
1912
+ writer .write ("<p class=\" path\" ><span class=\" high\" >Path</span>: " );
1913
+ writer .write ("<a href=\" " );
1914
+ writer .write (path );
1915
+ writer .write ("\" >" );
1916
+ writer .write (path );
1917
+ writer .write ("</a>" );
1916
1918
1917
- writer .flush ();
1918
- writer .close ();
1919
+ writer .write ("<p class=\" errmsg\" >" );
1920
+ final String message = e .getMessage () == null ? e .toString () : e .getMessage ();
1921
+ writer .write (XMLUtil .encodeAttrMarkup (message ));
1922
+ writer .write ("" );
1923
+ if (query != null ) {
1924
+ writer .write ("<span class=\" high\" >Query</span>:<pre>" );
1925
+ writer .write (XMLUtil .encodeAttrMarkup (query ));
1926
+ writer .write ("</pre>" );
1927
+ }
1928
+ writer .write ("</body></html>" );
1929
+
1930
+ writer .flush ();
1931
+ writerToClose = writer ;
1932
+ } finally {
1933
+ if (writerToClose != null ) {
1934
+ writerToClose .close ();
1935
+ }
1936
+ }
1919
1937
}
1920
1938
1921
1939
/**
@@ -1937,8 +1955,10 @@ private void writeXPathException(final HttpServletResponse response,
1937
1955
1938
1956
response .setContentType (MimeType .XML_TYPE .getName () + "; charset=" + encoding );
1939
1957
1940
- try (final OutputStreamWriter writer =
1941
- new OutputStreamWriter (response .getOutputStream (), encoding )) {
1958
+ // NOTE(AR) we only close the OutputStreamWriter if serialization succeeds, otherwise we raise a BadRequestException below which needs the OutputStream to remain open so that it can report the issue via the HTTP response to the client
1959
+ @ Nullable Writer writerToClose = null ;
1960
+ try {
1961
+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
1942
1962
1943
1963
writer .write ("<?xml version=\" 1.0\" ?>" );
1944
1964
writer .write ("<exception><path>" );
@@ -1954,6 +1974,13 @@ private void writeXPathException(final HttpServletResponse response,
1954
1974
writer .write ("</query>" );
1955
1975
}
1956
1976
writer .write ("</exception>" );
1977
+
1978
+ writer .flush ();
1979
+ writerToClose = writer ;
1980
+ } finally {
1981
+ if (writerToClose != null ) {
1982
+ writerToClose .close ();
1983
+ }
1957
1984
}
1958
1985
}
1959
1986
@@ -1971,17 +1998,23 @@ private void writeXUpdateResult(final HttpServletResponse response,
1971
1998
1972
1999
response .setContentType (MimeType .XML_TYPE .getName () + "; charset=" + encoding );
1973
2000
1974
- final OutputStreamWriter writer =
1975
- new OutputStreamWriter (response .getOutputStream (), encoding );
1976
-
1977
- writer .write ("<?xml version=\" 1.0\" ?>" );
1978
- writer .write ("<exist:modifications xmlns:exist=\" "
2001
+ // NOTE(AR) we only close the OutputStreamWriter if serialization succeeds, otherwise we raise a BadRequestException below which needs the OutputStream to remain open so that it can report the issue via the HTTP response to the client
2002
+ @ Nullable Writer writerToClose = null ;
2003
+ try {
2004
+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
2005
+ writer .write ("<?xml version=\" 1.0\" ?>" );
2006
+ writer .write ("<exist:modifications xmlns:exist=\" "
1979
2007
+ Namespaces .EXIST_NS + "\" count=\" " + updateCount + "\" >" );
1980
- writer .write (updateCount + " modifications processed." );
1981
- writer .write ("</exist:modifications>" );
2008
+ writer .write (updateCount + " modifications processed." );
2009
+ writer .write ("</exist:modifications>" );
1982
2010
1983
- writer .flush ();
1984
- writer .close ();
2011
+ writer .flush ();
2012
+ writerToClose = writer ;
2013
+ } finally {
2014
+ if (writerToClose != null ) {
2015
+ writerToClose .close ();
2016
+ }
2017
+ }
1985
2018
}
1986
2019
1987
2020
/**
@@ -2004,12 +2037,12 @@ protected void writeCollection(final HttpServletResponse response,
2004
2037
2005
2038
setCreatedAndLastModifiedHeaders (response , collection .getCreated (), collection .getCreated ());
2006
2039
2007
- final OutputStreamWriter writer =
2008
- new OutputStreamWriter (response .getOutputStream (), encoding );
2009
-
2010
2040
SAXSerializer serializer = null ;
2011
2041
2042
+ // NOTE(AR) we only close the OutputStreamWriter if serialization succeeds, otherwise we raise a BadRequestException below which needs the OutputStream to remain open so that it can report the issue via the HTTP response to the client
2043
+ @ Nullable Writer writerToClose = null ;
2012
2044
try {
2045
+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
2013
2046
serializer = (SAXSerializer ) SerializerPool .getInstance ().borrowObject (SAXSerializer .class );
2014
2047
2015
2048
serializer .setOutput (writer , defaultProperties );
@@ -2109,7 +2142,7 @@ protected void writeCollection(final HttpServletResponse response,
2109
2142
serializer .endDocument ();
2110
2143
2111
2144
writer .flush ();
2112
- writer . close () ;
2145
+ writerToClose = writer ;
2113
2146
2114
2147
} catch (final SAXException e ) {
2115
2148
// should never happen
@@ -2118,6 +2151,9 @@ protected void writeCollection(final HttpServletResponse response,
2118
2151
if (serializer != null ) {
2119
2152
SerializerPool .getInstance ().returnObject (serializer );
2120
2153
}
2154
+ if (writerToClose != null ) {
2155
+ writerToClose .close ();
2156
+ }
2121
2157
}
2122
2158
}
2123
2159
@@ -2193,14 +2229,23 @@ private void writeResultXML(final HttpServletResponse response,
2193
2229
if (wrap ) {
2194
2230
outputProperties .setProperty ("method" , "xml" );
2195
2231
}
2196
- final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
2197
- final XQuerySerializer serializer = new XQuerySerializer (broker , outputProperties , writer );
2198
2232
2199
- //Marshaller.marshall(broker, results, start, howmany, serializer.getContentHandler());
2200
- serializer .serialize (results , start , howmany , wrap , typed , compilationTime , executionTime );
2233
+ // NOTE(AR) we only close the OutputStreamWriter if serialization succeeds, otherwise we raise a BadRequestException below which needs the OutputStream to remain open so that it can report the issue via the HTTP response to the client
2234
+ @ Nullable Writer writerToClose = null ;
2235
+ try {
2236
+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
2237
+ final XQuerySerializer serializer = new XQuerySerializer (broker , outputProperties , writer );
2201
2238
2202
- writer .flush ();
2203
- writer .close ();
2239
+ //Marshaller.marshall(broker, results, start, howmany, serializer.getContentHandler());
2240
+ serializer .serialize (results , start , howmany , wrap , typed , compilationTime , executionTime );
2241
+
2242
+ writer .flush ();
2243
+ writerToClose = writer ;
2244
+ } finally {
2245
+ if (writerToClose != null ) {
2246
+ writerToClose .close ();
2247
+ }
2248
+ }
2204
2249
2205
2250
} catch (final SAXException e ) {
2206
2251
LOG .warn (e );
@@ -2236,7 +2281,9 @@ private void writeResultJSON(final HttpServletResponse response,
2236
2281
outputProperties .setProperty (Serializer .GENERATE_DOC_EVENTS , "false" );
2237
2282
try {
2238
2283
serializer .setProperties (outputProperties );
2239
- try (final Writer writer = new OutputStreamWriter (response .getOutputStream (), getEncoding (outputProperties ))) {
2284
+ @ Nullable Writer writerToClose = null ;
2285
+ try {
2286
+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), getEncoding (outputProperties ));
2240
2287
final JSONObject root = new JSONObject ();
2241
2288
root .addObject (new JSONSimpleProperty ("start" , Integer .toString (start ), true ));
2242
2289
root .addObject (new JSONSimpleProperty ("count" , Integer .toString (howmany ), true ));
@@ -2280,6 +2327,12 @@ private void writeResultJSON(final HttpServletResponse response,
2280
2327
root .serialize (writer , true );
2281
2328
2282
2329
writer .flush ();
2330
+ writerToClose = writer ;
2331
+
2332
+ } finally {
2333
+ if (writerToClose != null ) {
2334
+ writerToClose .close ();
2335
+ }
2283
2336
}
2284
2337
} catch (final IOException | XPathException | SAXException e ) {
2285
2338
throw new BadRequestException ("Error while serializing xml: " + e .toString (), e );
0 commit comments