Coverage report

  %line %branch
org.apache.jetspeed.resource.BufferedHttpServletResponse$1
0% 
0% 

 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.jetspeed.resource;
 18  
 
 19  
 import java.io.ByteArrayOutputStream;
 20  
 import java.io.CharArrayWriter;
 21  
 import java.io.IOException;
 22  
 import java.io.PrintWriter;
 23  
 import java.util.ArrayList;
 24  
 import java.util.HashMap;
 25  
 import java.util.Iterator;
 26  
 import java.util.Locale;
 27  
 import java.util.Map.Entry;
 28  
 
 29  
 import javax.servlet.ServletOutputStream;
 30  
 import javax.servlet.http.Cookie;
 31  
 import javax.servlet.http.HttpServletResponse;
 32  
 import javax.servlet.http.HttpServletResponseWrapper;
 33  
 
 34  
 /**
 35  
  * <p>
 36  
  * BufferedHttpServletResponse fully captures all HttpServletResponse interactions to be flushed out later.
 37  
  * This wrapper is specifically written to allow included servlets to set headers, cookies, encoding etc. which isn't allowed by
 38  
  * the servlet specification on included responses.
 39  
  * </p>
 40  
  * <p>
 41  
  * Call flush(HttpServletResponse) after the include has returned to flush out the buffered data, headers and state.
 42  
  * </p>
 43  
  * <p>
 44  
  * Note: the only method not fully supported by this buffered version is getCharacterEncoding(). Setting characterEncoding through
 45  
  * setContentType or setLocale on this class won't be reflected in the return value from getCharacterEncoding(), and calling getWriter()
 46  
  * won't set it either although calling setLocale, setContentType or setCharacterEncoding (servlet api 2.4+) after that will be ignored.
 47  
  * But, when this object is flused to a (real) response, the contentType, locale and/or characterEncoding recorded will be set on the
 48  
  * target response then.
 49  
  * </p>
 50  
  * 
 51  
  * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
 52  
  * @version $Id: BufferedHttpServletResponse.java 544024 2007-06-04 00:59:09Z ate $
 53  
  */
 54  
 public class BufferedHttpServletResponse extends HttpServletResponseWrapper
 55  
 {
 56  
     private static class CharArrayWriterBuffer extends CharArrayWriter
 57  
     {
 58  
         public char[] getBuffer()
 59  
         {
 60  
             return buf;
 61  
         }
 62  
         
 63  
         public int getCount()
 64  
         {
 65  
             return count;
 66  
         }
 67  
     }
 68  
     
 69  
     private ByteArrayOutputStream byteOutputBuffer;
 70  
     private CharArrayWriterBuffer charOutputBuffer;
 71  
     private ServletOutputStream outputStream;
 72  
     private PrintWriter printWriter;
 73  
     private HashMap headers;
 74  
     private ArrayList cookies;
 75  
     private int errorCode;
 76  
     private int statusCode;
 77  
     private String errorMessage;
 78  
     private String redirectLocation;
 79  
     private boolean committed;
 80  
     private boolean hasStatus;
 81  
     private boolean hasError;
 82  
     private Locale locale;
 83  
     private boolean closed;
 84  
     private String characterEncoding;
 85  
     private int contentLength = -1;
 86  
     private String contentType;
 87  
     private boolean flushed;
 88  
     
 89  
     public BufferedHttpServletResponse(HttpServletResponse response)
 90  
     {
 91  
         super(response);
 92  
     }
 93  
     
 94  
     public void flush(HttpServletResponse response) throws IOException
 95  
     {
 96  
         if (flushed)
 97  
         {
 98  
             throw new IllegalStateException("Already flushed");            
 99  
         }
 100  
         flushed = true;
 101  
         
 102  
         if (locale != null)
 103  
         {
 104  
             response.setLocale(locale);
 105  
         }        
 106  
         if (contentType != null)
 107  
         {
 108  
             response.setContentType(contentType);
 109  
         }
 110  
         if (characterEncoding != null)
 111  
         {
 112  
             // setCharacterEncoding only available on Servlet Spec 2.4+
 113  
             try
 114  
             {
 115  
                 response.getClass().getMethod("setCharacterEncoding", new Class[]{String.class}).invoke(response, class="keyword">new Object[]{characterEncoding});
 116  
             }
 117  
             catch (NoSuchMethodException nsme)
 118  
             {
 119  
                 // servlet spec 2.3
 120  
             }
 121  
             catch (Exception e)
 122  
             {
 123  
                 throw new RuntimeException(e);
 124  
             }
 125  
         }
 126  
         if (cookies != null)
 127  
         {
 128  
             for (int i=0,size=cookies.size(); i<size; i++)
 129  
             {
 130  
                 response.addCookie((Cookie)cookies.get(i));
 131  
             }
 132  
             cookies = null;
 133  
         }
 134  
         if (headers != null)
 135  
         {
 136  
             Iterator iter = headers.entrySet().iterator();
 137  
             while (iter.hasNext())
 138  
             {
 139  
                 Entry e = (Entry)iter.next();
 140  
                 String name = (String)e.getKey();
 141  
                 ArrayList values = (ArrayList)e.getValue();
 142  
                 for (int i=0, size=values.size(); i < size; i++ )
 143  
                 {
 144  
                     Object value = values.get(i);
 145  
                     if (value instanceof Integer)
 146  
                     {
 147  
                         response.addIntHeader(name, ((Integer)value).intValue());
 148  
                     }
 149  
                     else if (value instanceof Long)
 150  
                     {
 151  
                         response.addDateHeader(name, ((Long)value).longValue());
 152  
                     }
 153  
                     else
 154  
                     {
 155  
                         response.addHeader(name, (String)value);
 156  
                     }
 157  
                 }
 158  
             }
 159  
             headers = null;
 160  
         }
 161  
         if (contentLength > -1)
 162  
         {
 163  
             response.setContentLength(contentLength);
 164  
         }
 165  
         if (hasStatus)
 166  
         {
 167  
             response.setStatus(statusCode);
 168  
         }
 169  
         if (hasError)
 170  
         {
 171  
             response.sendError(errorCode, errorMessage);            
 172  
         }
 173  
         else if (redirectLocation != null)
 174  
         {
 175  
             response.sendRedirect(redirectLocation);
 176  
         }
 177  
         else
 178  
         {
 179  
             if (outputStream != null)
 180  
             {
 181  
                 if (!closed)
 182  
                 {
 183  
                     outputStream.flush();
 184  
                 }
 185  
                 ServletOutputStream realOutputStream = response.getOutputStream();
 186  
                 int len = byteOutputBuffer.size();
 187  
                 if (contentLength > -1 && contentLength < len)
 188  
                 {
 189  
                     len = contentLength;
 190  
                 }
 191  
                 if (len > 0)
 192  
                 {
 193  
                     realOutputStream.write(byteOutputBuffer.toByteArray(), 0, len);
 194  
                 }
 195  
                 outputStream.close();
 196  
                 outputStream = null;
 197  
                 byteOutputBuffer = null;
 198  
             }
 199  
             else if (printWriter != null)
 200  
             {
 201  
                 if (!closed)
 202  
                 {
 203  
                     printWriter.flush();
 204  
                     if ( charOutputBuffer.getCount() > 0)
 205  
                     {
 206  
                         response.getWriter().write(charOutputBuffer.getBuffer(), 0, charOutputBuffer.getCount());
 207  
                     }
 208  
                     printWriter.close();
 209  
                     
 210  
                     printWriter = null;
 211  
                     charOutputBuffer = null;
 212  
                 }
 213  
             }
 214  
             
 215  
         }
 216  
     }
 217  
     
 218  
     private ArrayList getHeaderList(String name, boolean create)
 219  
     {
 220  
         if ( headers == null )
 221  
         {
 222  
             headers = new HashMap();
 223  
         }
 224  
         ArrayList headerList = (ArrayList)headers.get(name);
 225  
         if ( headerList == null && create )
 226  
         {
 227  
             headerList = new ArrayList();
 228  
             headers.put(name,headerList);
 229  
         }
 230  
         return headerList;
 231  
     }
 232  
     
 233  
     private void failIfCommitted()
 234  
     {
 235  
         if (committed)
 236  
         {
 237  
             throw new IllegalStateException("Response is already committed");
 238  
         }
 239  
     }
 240  
     
 241  
     /* (non-Javadoc)
 242  
      * @see javax.servlet.http.HttpServletResponseWrapper#addCookie(javax.servlet.http.Cookie)
 243  
      */
 244  
     public void addCookie(Cookie cookie)
 245  
     {
 246  
         if ( !committed )
 247  
         {
 248  
             if ( cookies == null )
 249  
             {
 250  
                 cookies = new ArrayList();
 251  
             }
 252  
             cookies.add(cookie);
 253  
         }
 254  
     }
 255  
 
 256  
     /* (non-Javadoc)
 257  
      * @see javax.servlet.http.HttpServletResponseWrapper#addDateHeader(java.lang.String, long)
 258  
      */
 259  
     public void addDateHeader(String name, long date)
 260  
     {
 261  
         if (!committed)
 262  
         {
 263  
             ArrayList headerList = getHeaderList(name, true);
 264  
             headerList.add(new Long(date));
 265  
         }
 266  
     }
 267  
 
 268  
     /* (non-Javadoc)
 269  
      * @see javax.servlet.http.HttpServletResponseWrapper#addHeader(java.lang.String, java.lang.String)
 270  
      */
 271  
     public void addHeader(String name, String value)
 272  
     {
 273  
         if (!committed)
 274  
         {
 275  
             ArrayList headerList = getHeaderList(name, true);
 276  
             headerList.add(value);
 277  
         }
 278  
     }
 279  
 
 280  
     /* (non-Javadoc)
 281  
      * @see javax.servlet.http.HttpServletResponseWrapper#addIntHeader(java.lang.String, int)
 282  
      */
 283  
     public void addIntHeader(String name, int value)
 284  
     {
 285  
         if (!committed)
 286  
         {
 287  
             ArrayList headerList = getHeaderList(name, true);
 288  
             headerList.add(new Integer(value));
 289  
         }
 290  
     }
 291  
 
 292  
     /* (non-Javadoc)
 293  
      * @see javax.servlet.http.HttpServletResponseWrapper#containsHeader(java.lang.String)
 294  
      */
 295  
     public boolean containsHeader(String name)
 296  
     {
 297  
         return getHeaderList(name, false) != null;
 298  
     }
 299  
 
 300  
     /* (non-Javadoc)
 301  
      * @see javax.servlet.http.HttpServletResponseWrapper#sendError(int, java.lang.String)
 302  
      */
 303  
     public void sendError(int errorCode, String errorMessage) throws IOException
 304  
     {
 305  
         failIfCommitted();
 306  
         committed = true;
 307  
         closed = true;
 308  
         hasError = true;
 309  
         this.errorCode = errorCode;
 310  
         this.errorMessage = errorMessage;
 311  
     }
 312  
 
 313  
     /* (non-Javadoc)
 314  
      * @see javax.servlet.http.HttpServletResponseWrapper#sendError(int)
 315  
      */
 316  
     public void sendError(int errorCode) throws IOException
 317  
     {
 318  
         sendError(errorCode, null);
 319  
     }
 320  
 
 321  
     /* (non-Javadoc)
 322  
      * @see javax.servlet.http.HttpServletResponseWrapper#sendRedirect(java.lang.String)
 323  
      */
 324  
     public void sendRedirect(String redirectLocation) throws IOException
 325  
     {
 326  
         failIfCommitted();
 327  
         closed = true;
 328  
         committed = true;
 329  
         this.redirectLocation = redirectLocation;
 330  
     }
 331  
 
 332  
     /* (non-Javadoc)
 333  
      * @see javax.servlet.http.HttpServletResponseWrapper#setDateHeader(java.lang.String, long)
 334  
      */
 335  
     public void setDateHeader(String name, long date)
 336  
     {
 337  
         if (!committed)
 338  
         {
 339  
             ArrayList headerList = getHeaderList(name, true);
 340  
             headerList.clear();
 341  
             headerList.add(new Long(date));
 342  
         }
 343  
     }
 344  
 
 345  
     /* (non-Javadoc)
 346  
      * @see javax.servlet.http.HttpServletResponseWrapper#setHeader(java.lang.String, java.lang.String)
 347  
      */
 348  
     public void setHeader(String name, String value)
 349  
     {
 350  
         if (!committed)
 351  
         {
 352  
             ArrayList headerList = getHeaderList(name, true);
 353  
             headerList.clear();
 354  
             headerList.add(value);
 355  
         }
 356  
     }
 357  
 
 358  
     /* (non-Javadoc)
 359  
      * @see javax.servlet.http.HttpServletResponseWrapper#setIntHeader(java.lang.String, int)
 360  
      */
 361  
     public void setIntHeader(String name, int value)
 362  
     {
 363  
         if (!committed)
 364  
         {
 365  
             ArrayList headerList = getHeaderList(name, true);
 366  
             headerList.clear();
 367  
             headerList.add(new Integer(value));
 368  
         }
 369  
     }
 370  
 
 371  
     /* (non-Javadoc)
 372  
      * @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int, java.lang.String)
 373  
      */
 374  
     public void setStatus(int statusCode, String message)
 375  
     {
 376  
         throw new UnsupportedOperationException("This method is deprecated and no longer available");
 377  
     }
 378  
 
 379  
     /* (non-Javadoc)
 380  
      * @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int)
 381  
      */
 382  
     public void setStatus(int statusCode)
 383  
     {
 384  
         if (!committed)
 385  
         {
 386  
             this.statusCode = statusCode;
 387  
             this.hasStatus = true;
 388  
             resetBuffer();
 389  
         }
 390  
     }
 391  
 
 392  
     /* (non-Javadoc)
 393  
      * @see javax.servlet.ServletResponseWrapper#flushBuffer()
 394  
      */
 395  
     public void flushBuffer() throws IOException
 396  
     {
 397  
         if (!closed)
 398  
         {
 399  
             committed = true;
 400  
         }
 401  
     }
 402  
 
 403  
     /* (non-Javadoc)
 404  
      * @see javax.servlet.ServletResponseWrapper#getBufferSize()
 405  
      */
 406  
     public int getBufferSize()
 407  
     {
 408  
         return Integer.MAX_VALUE;
 409  
     }
 410  
 
 411  
     /* (non-Javadoc)
 412  
      * @see javax.servlet.ServletResponseWrapper#getCharacterEncoding()
 413  
      */
 414  
     public String getCharacterEncoding()
 415  
     {
 416  
         return characterEncoding != null ? characterEncoding : "ISO-8859-1";
 417  
     }
 418  
 
 419  
     /* (non-Javadoc)
 420  
      * @see javax.servlet.ServletResponseWrapper#getLocale()
 421  
      */
 422  
     public Locale getLocale()
 423  
     {
 424  
         return locale != null ? locale : super.getLocale();
 425  
     }
 426  
 
 427  
     /* (non-Javadoc)
 428  
      * @see javax.servlet.ServletResponseWrapper#getOutputStream()
 429  
      */
 430  
     public ServletOutputStream getOutputStream() throws IOException
 431  
     {
 432  
         if (outputStream == null)
 433  
         {
 434  
             if (printWriter != null)
 435  
             {
 436  
                 throw new IllegalStateException("getWriter() has already been called on this response");
 437  
             }
 438  
             byteOutputBuffer = new ByteArrayOutputStream();
 439  
             outputStream = new ServletOutputStream()
 440  
             {
 441  0
                 public void write(int b) throws IOException
 442  
                 {
 443  0
                     if (!closed)
 444  
                     {
 445  0
                         byteOutputBuffer.write(b);
 446  0
                         if (contentLength>-1 && byteOutputBuffer.size()>=contentLength)
 447  
                         {
 448  0
                             committed = true;
 449  0
                             closed = true;
 450  
                         }
 451  
                     }
 452  0
                 }
 453  
             };
 454  
         }
 455  
         return outputStream;
 456  
     }
 457  
 
 458  
     /* (non-Javadoc)
 459  
      * @see javax.servlet.ServletResponseWrapper#getWriter()
 460  
      */
 461  
     public PrintWriter getWriter() throws IOException
 462  
     {
 463  
         if (printWriter == null)
 464  
         {
 465  
             if (outputStream != null)
 466  
             {
 467  
                 throw new IllegalStateException("getOutputStream() has already been called on this response");
 468  
             }
 469  
             charOutputBuffer = new CharArrayWriterBuffer();
 470  
             printWriter = new PrintWriter(charOutputBuffer);
 471  
         }
 472  
         return printWriter;
 473  
     }
 474  
 
 475  
     /* (non-Javadoc)
 476  
      * @see javax.servlet.ServletResponseWrapper#isCommitted()
 477  
      */
 478  
     public boolean isCommitted()
 479  
     {
 480  
         return committed;
 481  
     }
 482  
 
 483  
     /* (non-Javadoc)
 484  
      * @see javax.servlet.ServletResponseWrapper#reset()
 485  
      */
 486  
     public void reset()
 487  
     {
 488  
         resetBuffer(); // fails if committed
 489  
         headers = null;
 490  
         cookies = null;
 491  
         hasStatus = false;
 492  
         contentLength = -1;
 493  
         if (printWriter == null)
 494  
         {
 495  
             contentType = null;
 496  
             characterEncoding = null;
 497  
             locale = null;
 498  
         }
 499  
     }
 500  
 
 501  
     /* (non-Javadoc)
 502  
      * @see javax.servlet.ServletResponseWrapper#resetBuffer()
 503  
      */
 504  
     public void resetBuffer()
 505  
     {
 506  
         failIfCommitted();
 507  
         if (outputStream != null)
 508  
         {
 509  
             try { outputStream.flush(); } catch (Exception e){}
 510  
             byteOutputBuffer.reset();
 511  
         }
 512  
         else if (printWriter != null)
 513  
         {
 514  
             printWriter.flush();
 515  
             charOutputBuffer.reset();
 516  
         }
 517  
     }
 518  
 
 519  
     /* (non-Javadoc)
 520  
      * @see javax.servlet.ServletResponseWrapper#setBufferSize(int)
 521  
      */
 522  
     public void setBufferSize(int size)
 523  
     {
 524  
         failIfCommitted();
 525  
         if ( (charOutputBuffer != null && charOutputBuffer.size() > 0)
 526  
                 || (byteOutputBuffer != null && byteOutputBuffer.size() > 0) )
 527  
         {
 528  
             throw new IllegalStateException("Content has already been written");
 529  
         }
 530  
     }
 531  
 
 532  
     /* (non-Javadoc)
 533  
      * @see javax.servlet.ServletResponseWrapper#setCharacterEncoding(java.lang.String)
 534  
      */
 535  
     public void setCharacterEncoding(String charset)
 536  
     {
 537  
         if (charset != null && !committed && printWriter == class="keyword">null)
 538  
         {
 539  
             characterEncoding = charset;
 540  
         }
 541  
     }
 542  
 
 543  
     /* (non-Javadoc)
 544  
      * @see javax.servlet.ServletResponseWrapper#setContentLength(int)
 545  
      */
 546  
     public void setContentLength(int len)
 547  
     {
 548  
         if (!committed && printWriter == null && len > 0)
 549  
         {
 550  
             contentLength = len;
 551  
             if (outputStream != null)
 552  
             {
 553  
                 try { outputStream.flush(); } catch (Exception e){}
 554  
             }
 555  
             if ( !closed && byteOutputBuffer != null && byteOutputBuffer.size() >= len )
 556  
             {
 557  
                 committed = true;
 558  
                 closed = true;
 559  
             }
 560  
         }
 561  
     }
 562  
 
 563  
     /* (non-Javadoc)
 564  
      * @see javax.servlet.ServletResponseWrapper#setContentType(java.lang.String)
 565  
      */
 566  
     public void setContentType(String type)
 567  
     {
 568  
         if (!committed)
 569  
         {
 570  
             contentType = type;
 571  
             if (printWriter == null)
 572  
             {
 573  
                 // TODO: parse possible encoding for better return value from getCharacterEncoding()
 574  
             }
 575  
         }
 576  
     }
 577  
 
 578  
     /* (non-Javadoc)
 579  
      * @see javax.servlet.ServletResponseWrapper#setLocale(java.util.Locale)
 580  
      */
 581  
     public void setLocale(Locale locale)
 582  
     {
 583  
         if (!committed)
 584  
         {
 585  
             this.locale = locale;
 586  
             /* NON-FIXABLE ISSUE: defaulting the characterEncoding from the Locale
 587  
                This feature cannot be implemented/wrapped as it might depend on web.xml locale settings
 588  
              */
 589  
         }
 590  
     }
 591  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.