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 }