001 // Copyright 2005 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry.web;
016
017 import java.io.IOException;
018 import java.io.OutputStream;
019 import java.io.PrintWriter;
020
021 import javax.servlet.http.HttpServletResponse;
022
023 import org.apache.commons.logging.Log;
024 import org.apache.commons.logging.LogFactory;
025 import org.apache.hivemind.ApplicationRuntimeException;
026 import org.apache.hivemind.util.Defense;
027 import org.apache.tapestry.util.ContentType;
028
029 /**
030 * Adapts {@link javax.servlet.http.HttpServletResponse} as
031 * {@link org.apache.tapestry.web.WebResponse}.
032 *
033 * @author Howard M. Lewis Ship
034 * @since 4.0
035 */
036 public class ServletWebResponse implements WebResponse
037 {
038 private static final Log DEFAULT_LOG = LogFactory.getLog(ServletWebResponse.class);
039
040 private final Log _log;
041
042 private final boolean _tomcatPatch;
043
044 private final HttpServletResponse _servletResponse;
045
046 private boolean _needsReset;
047
048 private ContentType _printWriterContentType;
049
050 public ServletWebResponse(HttpServletResponse response)
051 {
052 this(response, DEFAULT_LOG, Boolean.getBoolean("org.apache.tapestry.607-patch"));
053 }
054
055 /**
056 * Alternate constructor used by some tests.
057 */
058 ServletWebResponse(HttpServletResponse response, Log log, boolean tomcatPatch)
059 {
060 Defense.notNull(response, "response");
061 Defense.notNull(log, "log");
062
063 _servletResponse = response;
064 _log = log;
065 _tomcatPatch = tomcatPatch;
066 }
067
068 public OutputStream getOutputStream(ContentType contentType)
069 {
070 Defense.notNull(contentType, "contentType");
071
072 _servletResponse.setContentType(contentType.getMimeType());
073
074 try
075 {
076 return _servletResponse.getOutputStream();
077 }
078 catch (IOException ex)
079 {
080 throw new ApplicationRuntimeException(WebMessages.streamOpenError(contentType, ex),
081 null, ex);
082 }
083 }
084
085 public PrintWriter getPrintWriter(ContentType contentType) throws IOException
086 {
087 Defense.notNull(contentType, "contentType");
088
089 if (_needsReset)
090 reset();
091
092 _needsReset = true;
093
094 if (_printWriterContentType == null || ! _tomcatPatch)
095 {
096 _servletResponse.setContentType(contentType.toString());
097 _printWriterContentType = contentType;
098 }
099 else
100 {
101 // This is a workaround for a tomcat bug; it takes effect when a page is reset so that
102 // the exception page (typically) can be rendered. See TAPESTRY-607 for details.
103
104 if (!_printWriterContentType.equals(contentType))
105 _log.warn(WebMessages.contentTypeUnchanged(_printWriterContentType, contentType));
106 }
107
108 try
109 {
110 return _servletResponse.getWriter();
111 }
112 catch (IOException ex)
113 {
114 throw new ApplicationRuntimeException(WebMessages.writerOpenError(contentType, ex),
115 null, ex);
116 }
117 }
118
119 public String encodeURL(String url)
120 {
121 return _servletResponse.encodeURL(url);
122 }
123
124 public void reset()
125 {
126 try
127 {
128 _servletResponse.reset();
129 }
130 catch (IllegalStateException ex)
131 {
132 _log.error(WebMessages.resetFailed(ex), ex);
133 }
134 }
135
136 public void setContentLength(int length)
137 {
138 _servletResponse.setContentLength(length);
139 }
140
141 public String getNamespace()
142 {
143 return "";
144 }
145
146 public void setDateHeader(String name, long date)
147 {
148 _servletResponse.setDateHeader(name, date);
149 }
150
151 public void setStatus(int status)
152 {
153 _servletResponse.setStatus(status);
154 }
155
156 public void setHeader(String name, String value)
157 {
158 _servletResponse.setHeader(name, value);
159 }
160
161 public void setIntHeader(String name, int value)
162 {
163 _servletResponse.setIntHeader(name, value);
164 }
165
166 public void sendError(int statusCode, String message) throws IOException
167 {
168 _servletResponse.sendError(statusCode, message);
169 }
170
171 }