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 org.apache.commons.logging.Log;
018 import org.apache.commons.logging.LogFactory;
019 import org.apache.hivemind.ApplicationRuntimeException;
020 import org.apache.hivemind.util.Defense;
021 import org.apache.tapestry.util.ContentType;
022
023 import javax.servlet.http.HttpServletResponse;
024 import java.io.IOException;
025 import java.io.OutputStream;
026 import java.io.PrintWriter;
027
028 /**
029 * Adapts {@link javax.servlet.http.HttpServletResponse} as
030 * {@link org.apache.tapestry.web.WebResponse}.
031 *
032 * @author Howard M. Lewis Ship
033 * @since 4.0
034 */
035 public class ServletWebResponse implements WebResponse
036 {
037 private static final Log DEFAULT_LOG = LogFactory.getLog(ServletWebResponse.class);
038
039 private final Log _log;
040
041 private final boolean _tomcatPatch;
042
043 private final HttpServletResponse _servletResponse;
044
045 private boolean _needsReset;
046
047 private ContentType _printWriterContentType;
048
049 public ServletWebResponse(HttpServletResponse response)
050 {
051 this(response, DEFAULT_LOG, Boolean.getBoolean("org.apache.tapestry.607-patch"));
052 }
053
054 /**
055 * Alternate constructor used by some tests.
056 *
057 * @param response
058 * The wrapped response.
059 * @param log
060 * Logger.
061 * @param tomcatPatch
062 * Whether or not to apply tomcat workaround.
063 */
064 ServletWebResponse(HttpServletResponse response, Log log, boolean tomcatPatch)
065 {
066 Defense.notNull(response, "response");
067 Defense.notNull(log, "log");
068
069 _servletResponse = response;
070 _log = log;
071 _tomcatPatch = tomcatPatch;
072 }
073
074 public OutputStream getOutputStream(ContentType contentType)
075 {
076 Defense.notNull(contentType, "contentType");
077
078 _servletResponse.setContentType(contentType.getMimeType());
079
080 try
081 {
082 return _servletResponse.getOutputStream();
083 }
084 catch (IOException ex)
085 {
086 throw new ApplicationRuntimeException(WebMessages.streamOpenError(contentType, ex),
087 null, ex);
088 }
089 }
090
091 public PrintWriter getPrintWriter(ContentType contentType) throws IOException
092 {
093 Defense.notNull(contentType, "contentType");
094
095 if (_needsReset)
096 reset();
097
098 _needsReset = true;
099
100 if (_printWriterContentType == null || ! _tomcatPatch)
101 {
102 _servletResponse.setContentType(contentType.toString());
103 _printWriterContentType = contentType;
104 }
105 else
106 {
107 // This is a workaround for a tomcat bug; it takes effect when a page is reset so that
108 // the exception page (typically) can be rendered. See TAPESTRY-607 for details.
109
110 if (!_printWriterContentType.equals(contentType))
111 _log.warn(WebMessages.contentTypeUnchanged(_printWriterContentType, contentType));
112 }
113
114 try
115 {
116 return _servletResponse.getWriter();
117 }
118 catch (IOException ex)
119 {
120 throw new ApplicationRuntimeException(WebMessages.writerOpenError(contentType, ex),
121 null, ex);
122 }
123 }
124
125 public String encodeURL(String url)
126 {
127 return _servletResponse.encodeURL(url);
128 }
129
130 public void reset()
131 {
132 try
133 {
134 _servletResponse.reset();
135 }
136 catch (IllegalStateException ex)
137 {
138 _log.error(WebMessages.resetFailed(ex), ex);
139 }
140 }
141
142 public void setContentLength(int length)
143 {
144 _servletResponse.setContentLength(length);
145 }
146
147 public String getNamespace()
148 {
149 return "";
150 }
151
152 public void setDateHeader(String name, long date)
153 {
154 _servletResponse.setDateHeader(name, date);
155 }
156
157 public void setStatus(int status)
158 {
159 _servletResponse.setStatus(status);
160 }
161
162 public void setHeader(String name, String value)
163 {
164 _servletResponse.setHeader(name, value);
165 }
166
167 public void setIntHeader(String name, int value)
168 {
169 _servletResponse.setIntHeader(name, value);
170 }
171
172 public void sendError(int statusCode, String message) throws IOException
173 {
174 _servletResponse.sendError(statusCode, message);
175 }
176
177 }