111111
112112import javax .servlet .http .HttpServletRequest ;
113113import javax .servlet .http .HttpServletResponse ;
114+
115+ import javax .annotation .Nullable ;
114116import javax .xml .XMLConstants ;
115117import javax .xml .parsers .ParserConfigurationException ;
116118import javax .xml .stream .XMLStreamException ;
@@ -1827,14 +1829,22 @@ private void writeResourceAs(final DocumentImpl resource, final DBBroker broker,
18271829 outputProperties .setProperty ("omit-xml-declaration" , "no" );
18281830 }
18291831
1830- final OutputStreamWriter writer = new OutputStreamWriter (response .getOutputStream (), encoding );
1831- sax .setOutput (writer , outputProperties );
1832- serializer .setSAXHandlers (sax , sax );
1832+ // 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
1833+ @ Nullable Writer writerToClose = null ;
1834+ try {
1835+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
1836+ sax .setOutput (writer , outputProperties );
1837+ serializer .setSAXHandlers (sax , sax );
18331838
1834- serializer .toSAX (resource );
1839+ serializer .toSAX (resource );
18351840
1836- writer .flush ();
1837- writer .close (); // DO NOT use in try-write-resources, otherwise ther response stream is always closed, and we can't report the errors
1841+ writer .flush ();
1842+ writerToClose = writer ;
1843+ } finally {
1844+ if (writerToClose != null ) {
1845+ writerToClose .close ();
1846+ }
1847+ }
18381848 } catch (final SAXException saxe ) {
18391849 LOG .warn (saxe );
18401850 throw new BadRequestException ("Error while serializing XML: " + saxe .getMessage ());
@@ -1870,28 +1880,36 @@ private void writeXPathExceptionHtml(final HttpServletResponse response,
18701880
18711881 response .setContentType (MimeType .HTML_TYPE .getName () + "; charset=" + encoding );
18721882
1873- final OutputStreamWriter writer = new OutputStreamWriter (response .getOutputStream (), encoding );
1874- writer .write (QUERY_ERROR_HEAD );
1875- writer .write ("<p class=\" path\" ><span class=\" high\" >Path</span>: " );
1876- writer .write ("<a href=\" " );
1877- writer .write (path );
1878- writer .write ("\" >" );
1879- writer .write (path );
1880- writer .write ("</a>" );
1881-
1882- writer .write ("<p class=\" errmsg\" >" );
1883- final String message = e .getMessage () == null ? e .toString () : e .getMessage ();
1884- writer .write (XMLUtil .encodeAttrMarkup (message ));
1885- writer .write ("" );
1886- if (query != null ) {
1887- writer .write ("<span class=\" high\" >Query</span>:<pre>" );
1888- writer .write (XMLUtil .encodeAttrMarkup (query ));
1889- writer .write ("</pre>" );
1890- }
1891- writer .write ("</body></html>" );
1883+ // 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
1884+ @ Nullable Writer writerToClose = null ;
1885+ try {
1886+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
1887+ writer .write (QUERY_ERROR_HEAD );
1888+ writer .write ("<p class=\" path\" ><span class=\" high\" >Path</span>: " );
1889+ writer .write ("<a href=\" " );
1890+ writer .write (path );
1891+ writer .write ("\" >" );
1892+ writer .write (path );
1893+ writer .write ("</a>" );
18921894
1893- writer .flush ();
1894- writer .close ();
1895+ writer .write ("<p class=\" errmsg\" >" );
1896+ final String message = e .getMessage () == null ? e .toString () : e .getMessage ();
1897+ writer .write (XMLUtil .encodeAttrMarkup (message ));
1898+ writer .write ("" );
1899+ if (query != null ) {
1900+ writer .write ("<span class=\" high\" >Query</span>:<pre>" );
1901+ writer .write (XMLUtil .encodeAttrMarkup (query ));
1902+ writer .write ("</pre>" );
1903+ }
1904+ writer .write ("</body></html>" );
1905+
1906+ writer .flush ();
1907+ writerToClose = writer ;
1908+ } finally {
1909+ if (writerToClose != null ) {
1910+ writerToClose .close ();
1911+ }
1912+ }
18951913 }
18961914
18971915 /**
@@ -1913,8 +1931,10 @@ private void writeXPathException(final HttpServletResponse response,
19131931
19141932 response .setContentType (MimeType .XML_TYPE .getName () + "; charset=" + encoding );
19151933
1916- try (final OutputStreamWriter writer =
1917- new OutputStreamWriter (response .getOutputStream (), encoding )) {
1934+ // 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
1935+ @ Nullable Writer writerToClose = null ;
1936+ try {
1937+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
19181938
19191939 writer .write ("<?xml version=\" 1.0\" ?>" );
19201940 writer .write ("<exception><path>" );
@@ -1930,6 +1950,13 @@ private void writeXPathException(final HttpServletResponse response,
19301950 writer .write ("</query>" );
19311951 }
19321952 writer .write ("</exception>" );
1953+
1954+ writer .flush ();
1955+ writerToClose = writer ;
1956+ } finally {
1957+ if (writerToClose != null ) {
1958+ writerToClose .close ();
1959+ }
19331960 }
19341961 }
19351962
@@ -1947,17 +1974,23 @@ private void writeXUpdateResult(final HttpServletResponse response,
19471974
19481975 response .setContentType (MimeType .XML_TYPE .getName () + "; charset=" + encoding );
19491976
1950- final OutputStreamWriter writer =
1951- new OutputStreamWriter (response .getOutputStream (), encoding );
1952-
1953- writer .write ("<?xml version=\" 1.0\" ?>" );
1954- writer .write ("<exist:modifications xmlns:exist=\" "
1977+ // 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
1978+ @ Nullable Writer writerToClose = null ;
1979+ try {
1980+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
1981+ writer .write ("<?xml version=\" 1.0\" ?>" );
1982+ writer .write ("<exist:modifications xmlns:exist=\" "
19551983 + Namespaces .EXIST_NS + "\" count=\" " + updateCount + "\" >" );
1956- writer .write (updateCount + " modifications processed." );
1957- writer .write ("</exist:modifications>" );
1984+ writer .write (updateCount + " modifications processed." );
1985+ writer .write ("</exist:modifications>" );
19581986
1959- writer .flush ();
1960- writer .close ();
1987+ writer .flush ();
1988+ writerToClose = writer ;
1989+ } finally {
1990+ if (writerToClose != null ) {
1991+ writerToClose .close ();
1992+ }
1993+ }
19611994 }
19621995
19631996 /**
@@ -1980,12 +2013,12 @@ protected void writeCollection(final HttpServletResponse response,
19802013
19812014 setCreatedAndLastModifiedHeaders (response , collection .getCreated (), collection .getCreated ());
19822015
1983- final OutputStreamWriter writer =
1984- new OutputStreamWriter (response .getOutputStream (), encoding );
1985-
19862016 SAXSerializer serializer = null ;
19872017
2018+ // 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
2019+ @ Nullable Writer writerToClose = null ;
19882020 try {
2021+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
19892022 serializer = (SAXSerializer ) SerializerPool .getInstance ().borrowObject (SAXSerializer .class );
19902023
19912024 serializer .setOutput (writer , defaultProperties );
@@ -2085,7 +2118,7 @@ protected void writeCollection(final HttpServletResponse response,
20852118 serializer .endDocument ();
20862119
20872120 writer .flush ();
2088- writer . close () ;
2121+ writerToClose = writer ;
20892122
20902123 } catch (final SAXException e ) {
20912124 // should never happen
@@ -2094,6 +2127,9 @@ protected void writeCollection(final HttpServletResponse response,
20942127 if (serializer != null ) {
20952128 SerializerPool .getInstance ().returnObject (serializer );
20962129 }
2130+ if (writerToClose != null ) {
2131+ writerToClose .close ();
2132+ }
20972133 }
20982134 }
20992135
@@ -2165,14 +2201,23 @@ private void writeResultXML(final HttpServletResponse response,
21652201 if (wrap ) {
21662202 outputProperties .setProperty ("method" , "xml" );
21672203 }
2168- final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
2169- final XQuerySerializer serializer = new XQuerySerializer (broker , outputProperties , writer );
21702204
2171- //Marshaller.marshall(broker, results, start, howmany, serializer.getContentHandler());
2172- serializer .serialize (results , start , howmany , wrap , typed , compilationTime , executionTime );
2205+ // 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
2206+ @ Nullable Writer writerToClose = null ;
2207+ try {
2208+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), encoding );
2209+ final XQuerySerializer serializer = new XQuerySerializer (broker , outputProperties , writer );
21732210
2174- writer .flush ();
2175- writer .close ();
2211+ //Marshaller.marshall(broker, results, start, howmany, serializer.getContentHandler());
2212+ serializer .serialize (results , start , howmany , wrap , typed , compilationTime , executionTime );
2213+
2214+ writer .flush ();
2215+ writerToClose = writer ;
2216+ } finally {
2217+ if (writerToClose != null ) {
2218+ writerToClose .close ();
2219+ }
2220+ }
21762221
21772222 } catch (final SAXException e ) {
21782223 LOG .warn (e );
@@ -2208,7 +2253,9 @@ private void writeResultJSON(final HttpServletResponse response,
22082253 outputProperties .setProperty (Serializer .GENERATE_DOC_EVENTS , "false" );
22092254 try {
22102255 serializer .setProperties (outputProperties );
2211- try (final Writer writer = new OutputStreamWriter (response .getOutputStream (), outputProperties .getProperty (OutputKeys .ENCODING ))) {
2256+ @ Nullable Writer writerToClose = null ;
2257+ try {
2258+ final Writer writer = new OutputStreamWriter (response .getOutputStream (), outputProperties .getProperty (OutputKeys .ENCODING ));
22122259 final JSONObject root = new JSONObject ();
22132260 root .addObject (new JSONSimpleProperty ("start" , Integer .toString (start ), true ));
22142261 root .addObject (new JSONSimpleProperty ("count" , Integer .toString (howmany ), true ));
@@ -2252,6 +2299,12 @@ private void writeResultJSON(final HttpServletResponse response,
22522299 root .serialize (writer , true );
22532300
22542301 writer .flush ();
2302+ writerToClose = writer ;
2303+
2304+ } finally {
2305+ if (writerToClose != null ) {
2306+ writerToClose .close ();
2307+ }
22552308 }
22562309 } catch (final IOException | XPathException | SAXException e ) {
22572310 throw new BadRequestException ("Error while serializing xml: " + e .toString (), e );
0 commit comments