1010 *******************************************************************************/
1111package org .eclipse .rdf4j .common .webapp .filters ;
1212
13- import java .io .CharArrayWriter ;
13+ import java .io .ByteArrayOutputStream ;
1414import java .io .IOException ;
15+ import java .io .OutputStreamWriter ;
1516import java .io .PrintWriter ;
17+ import java .nio .charset .Charset ;
18+ import java .nio .charset .StandardCharsets ;
1619
1720import javax .servlet .Filter ;
1821import javax .servlet .FilterChain ;
1922import javax .servlet .FilterConfig ;
2023import javax .servlet .ServletException ;
24+ import javax .servlet .ServletOutputStream ;
2125import javax .servlet .ServletRequest ;
2226import javax .servlet .ServletResponse ;
27+ import javax .servlet .WriteListener ;
2328import javax .servlet .http .HttpServletRequest ;
2429import javax .servlet .http .HttpServletResponse ;
2530import javax .servlet .http .HttpServletResponseWrapper ;
@@ -42,39 +47,91 @@ public void destroy() {
4247 @ Override
4348 public void doFilter (ServletRequest req , ServletResponse res , FilterChain filterChain )
4449 throws IOException , ServletException {
45- if (req instanceof HttpServletRequest ) {
50+ if (req instanceof HttpServletRequest && res instanceof HttpServletResponse ) {
4651 HttpServletRequest request = (HttpServletRequest ) req ;
4752 HttpServletResponse response = (HttpServletResponse ) res ;
4853 String path = request .getContextPath ();
4954
50- PrintWriter out = response .getWriter ();
51- CharResponseWrapper wrapper = new CharResponseWrapper ((HttpServletResponse ) response );
55+ ContentCapturingResponseWrapper wrapper = new ContentCapturingResponseWrapper (response );
5256 filterChain .doFilter (request , wrapper );
53- CharArrayWriter caw = new CharArrayWriter ();
54- caw .write (wrapper .toString ().replace ("${path}" , path ));
55- String result = caw .toString ();
56- response .setContentLength (result .length ());
57- out .write (result );
57+
58+ String replaced = wrapper .getCapturedAsString ().replace ("${path}" , path );
59+ byte [] body = replaced .getBytes (wrapper .getEncoding ());
60+
61+ response .resetBuffer ();
62+ response .setContentLength (body .length );
63+ response .getOutputStream ().write (body );
64+ } else {
65+ filterChain .doFilter (req , res );
5866 }
5967 }
6068
61- private static class CharResponseWrapper extends HttpServletResponseWrapper {
69+ private static class ContentCapturingResponseWrapper extends HttpServletResponseWrapper {
6270
63- private final CharArrayWriter output ;
71+ private final ByteArrayOutputStream content = new ByteArrayOutputStream ();
72+ private final Charset encoding ;
73+ private ServletOutputStream outputStream ;
74+ private PrintWriter writer ;
6475
65- @ Override
66- public String toString () {
67- return output .toString ();
76+ ContentCapturingResponseWrapper (HttpServletResponse response ) {
77+ super (response );
78+ String characterEncoding = response .getCharacterEncoding ();
79+ if (characterEncoding == null ) {
80+ encoding = StandardCharsets .ISO_8859_1 ;
81+ } else {
82+ encoding = Charset .forName (characterEncoding );
83+ }
6884 }
6985
70- public CharResponseWrapper (HttpServletResponse response ) {
71- super (response );
72- output = new CharArrayWriter ();
86+ @ Override
87+ public ServletOutputStream getOutputStream () throws IOException {
88+ if (writer != null ) {
89+ throw new IllegalStateException ("getWriter() has already been called on this response." );
90+ }
91+ if (outputStream == null ) {
92+ outputStream = new ServletOutputStream () {
93+ @ Override
94+ public boolean isReady () {
95+ return true ;
96+ }
97+
98+ @ Override
99+ public void setWriteListener (WriteListener writeListener ) {
100+ // no-op
101+ }
102+
103+ @ Override
104+ public void write (int b ) throws IOException {
105+ content .write (b );
106+ }
107+ };
108+ }
109+ return outputStream ;
73110 }
74111
75112 @ Override
76- public PrintWriter getWriter () {
77- return new PrintWriter (output );
113+ public PrintWriter getWriter () throws IOException {
114+ if (outputStream != null ) {
115+ throw new IllegalStateException ("getOutputStream() has already been called on this response." );
116+ }
117+ if (writer == null ) {
118+ writer = new PrintWriter (new OutputStreamWriter (content , encoding ), true );
119+ }
120+ return writer ;
121+ }
122+
123+ String getCapturedAsString () throws IOException {
124+ if (writer != null ) {
125+ writer .flush ();
126+ }
127+ if (outputStream != null ) {
128+ outputStream .flush ();
129+ }
130+ return content .toString (encoding .name ());
131+ }
132+
133+ Charset getEncoding () {
134+ return encoding ;
78135 }
79136 }
80137}
0 commit comments