88package org .jruby .rack .servlet ;
99
1010import java .io .IOException ;
11- import java .io .OutputStream ;
1211import java .io .OutputStreamWriter ;
1312import java .io .PrintWriter ;
1413import java .lang .reflect .InvocationTargetException ;
@@ -65,11 +64,11 @@ public boolean isStatusSet() {
6564 *
6665 * @param status the new HTTP status
6766 * @param error whether the status comes from a {@code sendError}
68- * @see #isHandled()
67+ * @see #isHandled(HttpServletRequest )
6968 */
7069 protected boolean handleStatus (int status , boolean error ) {
7170 this .status = status ;
72- return isHandled ();
71+ return isHandled (null );
7372 }
7473
7574 @ Override
@@ -157,11 +156,9 @@ public void setIntHeader(String name, int value) {
157156 public ServletOutputStream getOutputStream () throws IOException {
158157 if ( output == null ) output = STREAM ;
159158
160- if ( isHandled () ) {
161- return super .getOutputStream ();
162- }
163- else {
164- // backwards compatibility with isError() then :
159+ if ( isHandled (null ) ) return super .getOutputStream ();
160+ else { // TODO get rid of this in 1.2.0
161+ // backwards compatibility with isError() :
165162 return new ServletOutputStream () {
166163 @ Override
167164 public void write (int b ) throws IOException {
@@ -175,43 +172,37 @@ public void write(int b) throws IOException {
175172 public PrintWriter getWriter () throws IOException {
176173 if ( output == null ) output = WRITER ;
177174
178- if ( isHandled () ) {
179- // we protect against API limitations as we depend on #getWriter
180- // being functional even if getOutputStream has been called ...
181- if ( output != WRITER ) {
182- String enc = getCharacterEncoding ();
183- if ( enc == null ) enc = "UTF-8" ;
184- return new PrintWriter (new OutputStreamWriter (getOutputStream (), enc ));
185- }
186- else {
187- return super .getWriter ();
188- }
175+ // we protect against API limitations as we depend on #getWriter
176+ // being functional even if getOutputStream has been called ...
177+ if ( output != WRITER ) {
178+ String enc = getCharacterEncoding ();
179+ if ( enc == null ) enc = "UTF-8" ;
180+ return new PrintWriter (new OutputStreamWriter (getOutputStream (), enc ));
189181 }
190182 else {
191- // backwards compatibility with isError() then :
192- return new PrintWriter (new OutputStream () {
193- @ Override
194- public void write (int b ) throws IOException {
195- // swallow output, because we're going to discard it
196- }
197- });
183+ return super .getWriter ();
198184 }
199185 }
200186
201187 @ Override
202188 public void flushBuffer () throws IOException {
203- if ( isHandled () ) super .flushBuffer ();
189+ if ( isHandled (null ) ) super .flushBuffer ();
204190 }
205191
206192 public boolean isError () {
207193 return getStatus () >= 400 ;
208194 }
209195
210- // NOTE: should probably deprecate this one
196+ /**
197+ * @deprecated no longer to be used from outside
198+ * @see #isHandled(HttpServletRequest)
199+ */
211200 public boolean isHandled () {
212201 return isHandled (null );
213202 }
214203
204+ private boolean handled ; // once handled - stays handled
205+
215206 /**
216207 * Response is considered to be handled if a status has been set
217208 * and it is (by default) not a HTTP NOT FOUND (404) status.
@@ -220,28 +211,36 @@ public boolean isHandled() {
220211 * @see #handleStatus(int, boolean)
221212 */
222213 public boolean isHandled (final HttpServletRequest request ) {
214+ if ( handled ) return true ; // ... once handled always handled !
215+
223216 // setting a header should consider the response to be handled
224217 if ( ! isStatusSet () ) {
225- if ( ! isHeaderSet () ) return false ;
218+ if ( ! isHeaderSet () ) {
219+ // true by default seems very weird but this is best to cover
220+ // "more" containers right out of the box ...
221+ // e.g. Jetty https://github.com/jruby/jruby-rack/issues/175
222+ return handled = true ; // return false;
223+ }
226224
227225 // consider HTTP OPTIONS with "Allow" header unhandled :
228226 if ( request != null && "OPTIONS" .equals ( request .getMethod () ) ) {
229- final Collection <String > headerNames = getHeaderNamesInternal ();
227+ final Collection <String > headerNames = getHeaderNamesOrNull ();
230228 if ( headerNames == null || headerNames .isEmpty () ) {
231229 // not to happen but there's all kind of beasts out there
232230 return false ;
233231 }
234232 for ( final String headerName : headerNames ) {
235233 if ( ! "Allow" .equals (headerName ) ) {
236- return true ; // not just Allow header - consider handled
234+ return handled = true ; // not just Allow header - consider handled
237235 }
238236 }
239237 return false ; // OPTIONS with only Allow header set - unhandled
240238 }
241- return true ;
239+ return handled = true ;
242240 }
241+
243242 if ( notHandledStatuses .contains ( getStatus () ) ) return false ;
244- return true ;
243+ return handled = true ;
245244 }
246245
247246 public Collection <Integer > getNotHandledStatuses () {
@@ -263,8 +262,8 @@ public boolean isOutputAccessed() {
263262 }
264263
265264 @ SuppressWarnings ("unchecked" )
266- private Collection <String > getHeaderNamesInternal () {
267- // NOTE: getHeaderNames available since 3.0 JRuby-Rack 1.1 still support 2.5
265+ private Collection <String > getHeaderNamesOrNull () {
266+ // NOTE: getHeaderNames since Servlet API 3.0 JRuby-Rack 1.1 still supports 2.5
268267 try {
269268 final Method getHeaderNames = HttpServletResponse .class .getMethod ("getHeaderNames" );
270269 return (Collection <String >) getHeaderNames .invoke (this );
0 commit comments