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 }