You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rave.apache.org by at...@apache.org on 2012/08/07 15:07:30 UTC

svn commit: r1370236 - in /rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc: servlet/HmvcDispatcherServlet.java support/HmvcServletResponse.java support/ResponseHolder.java

Author: ate
Date: Tue Aug  7 13:07:30 2012
New Revision: 1370236

URL: http://svn.apache.org/viewvc?rev=1370236&view=rev
Log:
RAVE-698: wrapping and buffering nested hmvc view rendering

Modified:
    rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/servlet/HmvcDispatcherServlet.java
    rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/support/HmvcServletResponse.java
    rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/support/ResponseHolder.java

Modified: rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/servlet/HmvcDispatcherServlet.java
URL: http://svn.apache.org/viewvc/rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/servlet/HmvcDispatcherServlet.java?rev=1370236&r1=1370235&r2=1370236&view=diff
==============================================================================
--- rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/servlet/HmvcDispatcherServlet.java (original)
+++ rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/servlet/HmvcDispatcherServlet.java Tue Aug  7 13:07:30 2012
@@ -38,24 +38,37 @@ public class HmvcDispatcherServlet exten
 
     @Override
     protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        HmvcServletRequest hmvcRequest = new HmvcServletRequest(request);
+        HmvcServletResponse hmvcResponse = new HmvcServletResponse(response);
+        
+        renderChildren(mv, hmvcRequest, hmvcResponse);
+        render(mv, hmvcRequest, hmvcResponse);
+        hmvcResponse.getResponseHolder().flush();
+    }
+
+    protected void renderChildren(ModelAndView mv, HmvcServletRequest hmvcRequest, HmvcServletResponse hvmcResponse) throws Exception {
         @SuppressWarnings("unchecked")
         Map<String, ModelAndView> ccmvMap = (Map<String, ModelAndView>) mv.getModelMap().get(HmvcHandlerMethod.MODEL_AND_VIEW);
         if (ccmvMap != null) {
             Map<String, Object> ccvrMap = new LinkedHashMap<String, Object>();
             mv.getModelMap().addAttribute(HmvcHandlerMethod.VIEW_RESPONSE_STATE, ccvrMap);
             for (Map.Entry<String, ModelAndView> entry : ccmvMap.entrySet()) {
-                HttpServletRequest servletRequest = new HmvcServletRequest(request);
-                HmvcServletResponse servletResponse = new HmvcServletResponse(response);
-                render(entry.getValue(), servletRequest, servletResponse);
-                ccvrMap.put(entry.getKey(), servletResponse.getResponseHolder());
+                HmvcServletResponse childHmvcResponse = new HmvcServletResponse(hvmcResponse);
+                renderChildren(entry.getValue(), hmvcRequest, childHmvcResponse);
+                render(entry.getValue(), hmvcRequest, childHmvcResponse);
+                ccvrMap.put(entry.getKey(), childHmvcResponse.getResponseHolder());
             }
         }
+    }
+    
+    protected void render(ModelAndView mv, HmvcServletRequest hmvcRequest, HmvcServletResponse hmvcResponse) throws Exception {
+        
         if (!mv.isReference()) {
             setInternalResourceViewIncludeAlways(mv.getView());
         }
-        super.render(mv, request, response);
+        super.render(mv, hmvcRequest, hmvcResponse);
     }
-    
+
     protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
             HttpServletRequest request) throws Exception {
         View view = super.resolveViewName(viewName, model, locale, request);

Modified: rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/support/HmvcServletResponse.java
URL: http://svn.apache.org/viewvc/rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/support/HmvcServletResponse.java?rev=1370236&r1=1370235&r2=1370236&view=diff
==============================================================================
--- rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/support/HmvcServletResponse.java (original)
+++ rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/support/HmvcServletResponse.java Tue Aug  7 13:07:30 2012
@@ -21,8 +21,10 @@ package org.apache.rave.portal.web.hmvc.
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.Locale;
 
 import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponseWrapper;
 
@@ -36,9 +38,8 @@ public class HmvcServletResponse extends
 
     private static Logger log = LoggerFactory.getLogger(HmvcServletResponse.class);
 
-
     private final ResponseHolder responseHolder;
-
+    private String redirectLocation;
 
     /**
      * Constructs a response adaptor wrapping the given response.
@@ -49,29 +50,207 @@ public class HmvcServletResponse extends
         super(response);
         responseHolder = new ResponseHolder(response);
     }
+    
+    public void setResponse(HttpServletResponse response) {
+        super.setResponse(response);
+    }
+    
+    public String getRedirectLocation() {
+        return this.redirectLocation;
+    }
+    
+    @Override
+    public void addCookie(Cookie cookie)
+    {
+        responseHolder.addCookie(cookie);
+    }
 
+    @Override
+    public void addDateHeader(String name, long date)
+    {
+        responseHolder.addDateHeader(name, date);
+    }
 
-    public ResponseHolder getResponseHolder() {
-        return responseHolder;
+    @Override
+    public void addHeader(String name, String value)
+    {
+        responseHolder.addHeader(name, value);
     }
 
+    @Override
+    public void addIntHeader(String name, int value)
+    {
+        responseHolder.addIntHeader(name, value);
+    }
+
+    @Override
+    public boolean containsHeader(String name)
+    {
+        return responseHolder.containsHeader(name);
+    }
 
     @Override
-    public void flushBuffer() throws IOException {
+    public void flushBuffer() throws IOException
+    {
         responseHolder.flushBuffer();
     }
 
     @Override
-    public ServletOutputStream getOutputStream() throws IOException {
-        ServletOutputStream outputStream = responseHolder.getOutputStream();
-        return outputStream != null ? outputStream : super.getOutputStream();
+    public int getBufferSize()
+    {
+        return responseHolder.getBufferSize();
+    }
+
+    @Override
+    public String getCharacterEncoding()
+    {
+        return responseHolder.getCharacterEncoding();
+    }
+
+    @Override
+    public String getContentType()
+    {
+        return responseHolder.getContentType();
+    }
+
+    @Override
+    public Locale getLocale()
+    {
+        return responseHolder.getLocale();
+    }
+
+    @Override
+    public ServletOutputStream getOutputStream() throws IOException
+    {
+        ServletOutputStream os = responseHolder.getOutputStream();
+        return os != null ? os : super.getOutputStream();
+    }
+
+    @Override
+    public PrintWriter getWriter() throws IOException
+    {
+        PrintWriter pw = responseHolder.getWriter();
+        return pw != null ? pw : super.getWriter();
+    }
+
+    @Override
+    public boolean isCommitted()
+    {
+        return responseHolder.isCommitted();
+    }
+
+    @Override
+    public void reset()
+    {
+        responseHolder.reset();
+    }
+
+    @Override
+    public void resetBuffer()
+    {
+        responseHolder.resetBuffer();
+    }
+
+    @Override
+    public void sendError(int errorCode, String errorMessage) throws IOException
+    {
+        responseHolder.sendError(errorCode, errorMessage);
+    }
+
+    @Override
+    public void sendError(int errorCode) throws IOException
+    {
+        responseHolder.sendError(errorCode);
+    }
+
+    @Override
+    public void sendRedirect(String redirectLocation) throws IOException
+    {
+        responseHolder.sendRedirect(redirectLocation);
+    }
+
+    @Override
+    public void setBufferSize(int size)
+    {
+        responseHolder.setBufferSize(size);
+    }
+
+    public void setCharacterEncoding(String charset)
+    {
+        responseHolder.setCharacterEncoding(charset);
+    }
+
+    @Override
+    public void setContentLength(int len)
+    {
+        responseHolder.setContentLength(len);
+    }
+
+    @Override
+    public void setContentType(String type)
+    {
+        responseHolder.setContentType(type);
+    }
+
+    @Override
+    public void setDateHeader(String name, long date)
+    {
+        responseHolder.setDateHeader(name, date);
+    }
+
+    @Override
+    public void setHeader(String name, String value)
+    {
+        responseHolder.setHeader(name, value);
     }
 
     @Override
-    public PrintWriter getWriter() throws IOException {
-        PrintWriter writer = responseHolder.getWriter();
-        return writer != null ? writer : super.getWriter();
+    public void setIntHeader(String name, int value)
+    {
+        responseHolder.setIntHeader(name, value);
     }
 
+    @Override
+    public void setLocale(Locale locale)
+    {
+        responseHolder.setLocale(locale);
+    }
+
+    @Override
+    public void setStatus(int statusCode, String message)
+    {
+        responseHolder.setStatus(statusCode, message);
+    }
+
+    @Override
+    public void setStatus(int statusCode)
+    {
+        responseHolder.setStatus(statusCode);
+    }
+
+    @Override
+    public String encodeRedirectUrl(String url)
+    {
+        return encodeRedirectURL(url);
+    }
 
+    @Override
+    public String encodeRedirectURL(String url)
+    {
+        return url;
+    }
+
+    @Override
+    public String encodeUrl(String url)
+    {
+        return encodeURL(url);
+    }
+
+    public void forward(String pathInfo) throws IOException {
+        this.responseHolder.forward(pathInfo);
+    }
+
+    public ResponseHolder getResponseHolder() {
+        return responseHolder;
+    }
 }

Modified: rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/support/ResponseHolder.java
URL: http://svn.apache.org/viewvc/rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/support/ResponseHolder.java?rev=1370236&r1=1370235&r2=1370236&view=diff
==============================================================================
--- rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/support/ResponseHolder.java (original)
+++ rave/sandbox/content-services/rave-web-hmvc/src/main/java/org/apache/rave/portal/web/hmvc/support/ResponseHolder.java Tue Aug  7 13:07:30 2012
@@ -22,9 +22,20 @@ package org.apache.rave.portal.web.hmvc.
 import java.io.ByteArrayOutputStream;
 import java.io.CharArrayWriter;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
 
 import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletResponse;
 
 import org.slf4j.Logger;
@@ -37,44 +48,310 @@ public class ResponseHolder {
 
     private static Logger log = LoggerFactory.getLogger(ResponseHolder.class);
 
-    /**
-     * Flag which indicates response is flushed
-     */
-    private boolean responseFlushed;
-
-    protected ByteArrayOutputStream byteOutputBuffer;
-    private CharArrayWriterBuffer charBuffer;
+    private Locale defaultLocale;
+    private boolean flushed;
+    
+    private ByteArrayOutputStream byteOutputBuffer;
+    private CharArrayWriterBuffer charOutputBuffer;
     private ServletOutputStream outputStream;
     private PrintWriter printWriter;
+    
+    private Map<String, List<String>> addedHeaders;
+    private Map<String, List<String>> setHeaders;
+    private List<Cookie> cookies;
+
+    private boolean committed;
+    private boolean hasStatus;
+    private boolean hasError;
+    private Locale locale;
+    private boolean setContentTypeAfterEncoding;
     private boolean closed;
-    private boolean commited;
-    private int contentLength;
-    private final HttpServletResponse response;
-
+    private String characterEncoding;
+    private int contentLength = -1;
+    private String contentType;
+    private int errorCode;
+    private String errorMessage;
+    private int statusCode;
 
+    private final HttpServletResponse response;
+    
+    private String redirectLocation;
+    
+    private String forwardPathInfo;
+
+    private String formatDateHeaderValue(long date) {
+        DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); 
+        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); 
+        return dateFormat.format(new Date(date)); 
+    }
+    
     public ResponseHolder(HttpServletResponse response) {
         this.response = response;
+        this.defaultLocale = null;
+    }
+
+    protected List<String> getAddedHeaderList(String name, boolean create) {
+        if (addedHeaders == null) {
+            addedHeaders = new HashMap<String, List<String>>();
+        }
+        
+        List<String> headerList = addedHeaders.get(name);
+        
+        if (headerList == null && create) {
+            headerList = new ArrayList<String>();
+            addedHeaders.put(name, headerList);
+        }
+        
+        return headerList;
+    }
+
+    protected List<String> getSetHeaderList(String name, boolean create) {
+        if (setHeaders == null) {
+            setHeaders = new HashMap<String, List<String>>();
+        }
+        
+        List<String> headerList = setHeaders.get(name);
+        
+        if (headerList == null && create) {
+            headerList = new ArrayList<String>();
+            setHeaders.put(name, headerList);
+        }
+        
+        return headerList;
     }
 
+    protected void failIfCommitted() {
+        if (committed) {
+            throw new IllegalStateException("Response is already committed");
+        }
+    }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#addCookie(javax.servlet.http.Cookie)
+     */
+    public void addCookie(Cookie cookie) {
+        if (!committed) {
+            if (cookies == null) {
+                cookies = new ArrayList<Cookie>();
+            }
+            cookies.add(cookie);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#addDateHeader(java.lang.String, long)
+     */
+    public void addDateHeader(String name, long date) {
+        addHeader(name, formatDateHeaderValue(date));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#addHeader(java.lang.String,
+     * java.lang.String)
+     */
+    public void addHeader(String name, String value) {
+        if (!committed) {
+            getAddedHeaderList(name, true).add(value);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#addIntHeader(java.lang.String, int)
+     */
+    public void addIntHeader(String name, int value) {
+        addHeader(name, Integer.toString(value));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#containsHeader(java.lang.String)
+     */
+    public boolean containsHeader(String name) {
+        return getAddedHeaderList(name, false) != null || getSetHeaderList(name, false) != null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#sendError(int, java.lang.String)
+     */
+    public void sendError(int errorCode, String errorMessage) throws IOException {
+        failIfCommitted();
+        committed = true;
+        closed = true;
+        hasError = true;
+        this.errorCode = errorCode;
+        this.errorMessage = errorMessage;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#sendError(int)
+     */
+    public void sendError(int errorCode) throws IOException {
+        sendError(errorCode, null);
+    }
+
+    public int getErrorCode() {
+        return this.errorCode;
+    }
+    
+    public String getErrorMessage() {
+        return this.errorMessage;
+    }
+    
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#sendRedirect(java.lang.String)
+     */
+    public void sendRedirect(String redirectLocation) throws IOException {
+        failIfCommitted();
+        closed = true;
+        committed = true;
+
+        this.redirectLocation = redirectLocation;
+    }
+    
+    public String getRedirectLocation() {
+        return redirectLocation;
+    }
+
+    public void forward(String pathInfo) throws IOException {
+        if (response instanceof HmvcServletResponse) {
+            ((HmvcServletResponse)response).forward(pathInfo);
+        }
+        failIfCommitted();
+        closed = true;
+        committed = true;
+        forwardPathInfo = pathInfo;
+    }
+    
+    public String getForwardPathInfo() {
+        return forwardPathInfo;
+    }
+    
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#setDateHeader(java.lang.String, long)
+     */
+    public void setDateHeader(String name, long date) {
+        setHeader(name, formatDateHeaderValue(date));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#setHeader(java.lang.String,
+     * java.lang.String)
+     */
+    public void setHeader(String name, String value) {
+        if (!committed) {
+            List<String> headerList = getSetHeaderList(name, true);
+            headerList.clear();
+            headerList.add(value);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#setIntHeader(java.lang.String, int)
+     */
+    public void setIntHeader(String name, int value) {
+        setHeader(name, Integer.toString(value));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int, java.lang.String)
+     */
+    public void setStatus(int statusCode, String message) {
+        throw new UnsupportedOperationException("This method is deprecated and no longer supported");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int)
+     */
+    public void setStatus(int statusCode) {
+        if (!committed) {
+            if (response instanceof HmvcServletResponse) {
+                ((HmvcServletResponse)response).setStatus(statusCode);
+            } else {
+                this.statusCode = statusCode;
+                hasStatus = true;
+                resetBuffer();
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#flushBuffer()
+     */
     public void flushBuffer() throws IOException {
         if (!closed) {
-            responseFlushed = true;
+            committed = true;
         }
+    }
 
-
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#getBufferSize()
+     */
+    public int getBufferSize() {
+        return Integer.MAX_VALUE;
     }
 
-    public PrintWriter getWriter() throws IOException {
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#getCharacterEncoding()
+     */
+    public String getCharacterEncoding() {
+        return characterEncoding != null ? characterEncoding : "ISO-8859-1";
+    }
 
-        charBuffer = new CharArrayWriterBuffer();
-        printWriter = new PrintWriter(charBuffer);
-        return printWriter;
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#getContentType()
+     */
+    public String getContentType() {
+        return contentType;
     }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#getLocale()
+     */
+    public Locale getLocale() {
+        return locale != null ? locale : defaultLocale;
+    }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#getOutputStream()
+     */
     public ServletOutputStream getOutputStream() throws IOException {
-
         if (outputStream == null) {
             if (printWriter != null) {
                 throw new IllegalStateException("getWriter() has already been called on this response");
@@ -86,7 +363,7 @@ public class ResponseHolder {
                     if (!closed) {
                         byteOutputBuffer.write(b);
                         if (contentLength > -1 && byteOutputBuffer.size() >= contentLength) {
-                            commited = true;
+                            committed = true;
                             closed = true;
                         }
                     }
@@ -96,7 +373,299 @@ public class ResponseHolder {
         return outputStream;
     }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#getWriter()
+     */
+    public PrintWriter getWriter() throws IOException {
+        if (printWriter == null) {
+            if (outputStream != null) {
+                throw new IllegalStateException("getOutputStream() has already been called on this response");
+            }
+            charOutputBuffer = new CharArrayWriterBuffer();
+            printWriter = new PrintWriter(charOutputBuffer);
+        }
+        return printWriter;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#isCommitted()
+     */
+    public boolean isCommitted() {
+        return committed;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#reset()
+     */
+    public void reset() {
+        resetBuffer(); // fails if committed
+        addedHeaders = null;
+        setHeaders = null;
+        cookies = null;
+        hasStatus = false;
+        contentLength = -1;
+        if (printWriter == null) {
+            contentType = null;
+            characterEncoding = null;
+            locale = null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#resetBuffer()
+     */
+    public void resetBuffer() {
+        failIfCommitted();
+        if (outputStream != null) {
+            try {
+                outputStream.flush();
+            } catch (Exception e) {
+            }
+            byteOutputBuffer.reset();
+        } else if (printWriter != null) {
+            printWriter.flush();
+            charOutputBuffer.reset();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#setBufferSize(int)
+     */
+    public void setBufferSize(int size) {
+        // ignore
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#setCharacterEncoding(java.lang.String)
+     */
+    public void setCharacterEncoding(String charset) {
+        // TODO: check if allowed and/or needed
+        if (charset != null && !committed && printWriter == null) {
+            characterEncoding = charset;
+            setContentTypeAfterEncoding = false;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#setContentLength(int)
+     */
+    public void setContentLength(int len) {
+        // TODO: check if allowed and/or needed
+        if (!committed && printWriter == null && len > 0) {
+            contentLength = len;
+            if (outputStream != null) {
+                try {
+                    outputStream.flush();
+                } catch (Exception e) {
+                }
+            }
+            if (!closed && byteOutputBuffer != null && byteOutputBuffer.size() >= len) {
+                committed = true;
+                closed = true;
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#setContentType(java.lang.String)
+     */
+    public void setContentType(String type) {
+        if (!committed) {
+            contentType = type;
+            setContentTypeAfterEncoding = false;
+            if (printWriter == null) {
+                // TODO: parse possible encoding for better return value from getCharacterEncoding()
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.ServletResponseWrapper#setLocale(java.util.Locale)
+     */
+    public void setLocale(Locale locale) {
+        // TODO: check if allowed and/or needed
+        if (!committed) {
+            this.locale = locale;
+        }
+    }
+
+    public void clear() {
+        printWriter = null;
+        byteOutputBuffer = null;
+        charOutputBuffer = null;
+        outputStream = null;
+        printWriter = null;
+        addedHeaders = null;
+        setHeaders = null;
+        cookies = null;
+        committed = false;
+        hasStatus = false;
+        hasError = false;
+        locale = null;
+        setContentTypeAfterEncoding = false;
+        closed = false;
+        characterEncoding = null;
+        contentLength = -1;
+        contentType = null;
+        errorCode = 0;
+        errorMessage = null;
+        statusCode = 0;
+        redirectLocation = null;
+    }
+    
+    public void flush() throws IOException {
+        if (flushed) {
+            //throw new IllegalStateException("Already flushed");
+            // Just ignore...
+            return;
+        }
+
+        flushed = true;
+
+        if (cookies != null) {
+            for (Cookie cookie : cookies) {
+                addResponseCookie(cookie);
+            }
+            cookies = null;
+        }
+
+        if (locale != null) {
+            try {
+                setResponseLocale(locale);
+            } catch (UnsupportedOperationException usoe) {
+            }
+        }
+
+        if (contentType != null) {
+            if (characterEncoding != null) {
+                if (setContentTypeAfterEncoding) {
+                    setResponseCharacterEncoding(characterEncoding);
+                    setResponseContentType(contentType);
+                } else {
+                    setResponseContentType(contentType);
+                    setResponseCharacterEncoding(characterEncoding);
+                }
+            } else {
+                setResponseContentType(contentType);
+            }
+        } else if (characterEncoding != null) {
+            setResponseCharacterEncoding(characterEncoding);
+        }
+
+        if (addedHeaders != null) {
+            for (Map.Entry<String, List<String>> entry : addedHeaders.entrySet()) {
+                for (String value : entry.getValue()) {
+                    addResponseHeader(entry.getKey(), value);
+                }
+            }
+            addedHeaders = null;
+        }
+
+        if (setHeaders != null) {
+            for (Map.Entry<String, List<String>> entry : setHeaders.entrySet()) {
+                for (String value : entry.getValue()) {
+                    setResponseHeader(entry.getKey(), value);
+                }
+            }
+            setHeaders = null;
+        }
+
+        // NOTE: To allow setting status code from each component.
+        //if (isResourceResponse && hasStatus) {
+        if (hasStatus) {
+            setResponseStatus(statusCode);
+        }
+
+        if (!hasError && redirectLocation == null) {
+            if (outputStream != null) {
+                if (!closed) {
+                    outputStream.flush();
+                }
 
+                OutputStream realOutputStream = getResponseOutputStream();
+                int len = byteOutputBuffer.size();
+                if (contentLength > -1 && contentLength < len) {
+                    len = contentLength;
+                }
+                if (len > 0) {
+                    realOutputStream.write(byteOutputBuffer.toByteArray(), 0, len);
+                }
+                outputStream.close();
+                outputStream = null;
+                byteOutputBuffer = null;
+            } else if (printWriter != null) {
+                if (!closed) {
+                    printWriter.flush();
+                    if (charOutputBuffer.getCount() > 0) {
+                        getResponseWriter().write(charOutputBuffer.getBuffer(), 0, charOutputBuffer.getCount());
+                    }
+                    printWriter.close();
+
+                    printWriter = null;
+                    charOutputBuffer = null;
+                }
+            }
+        }
+    }
+
+    protected void setResponseLocale(Locale locale) {
+        this.response.setLocale(locale);
+    }
+    
+    protected void addResponseCookie(Cookie cookie) {
+        this.response.addCookie(cookie);
+    }
+    
+    protected void setResponseCharacterEncoding(String characterEncoding) {
+        this.response.setCharacterEncoding(characterEncoding);
+    }
+    
+    protected void setResponseContentType(String contentType) {
+        this.response.setContentType(contentType);
+    }
+    
+    protected void addResponseHeader(String name, String value) {
+        this.response.addHeader(name, value);
+    }
+    
+    protected void setResponseHeader(String name, String value) {
+        this.response.setHeader(name, value);
+    }
+    
+    protected void setResponseStatus(int status) {
+        this.response.setStatus(status);
+    }
+    
+    protected void setResponseContentLength(int len) {
+        this.response.setContentLength(len);
+    }
+    
+    protected OutputStream getResponseOutputStream() throws IOException {
+        return this.response.getOutputStream();
+    }
+    
+    protected PrintWriter getResponseWriter() throws IOException {
+        return this.response.getWriter();
+    }
+    
     //*************************************************************************************
     // HELP CLASSES
     //*************************************************************************************
@@ -110,6 +679,4 @@ public class ResponseHolder {
             return count;
         }
     }
-
-
 }