001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. 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 distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.rest.mock; 014 015import static org.apache.juneau.internal.CollectionUtils.*; 016 017import java.io.*; 018import java.util.*; 019 020import jakarta.servlet.*; 021import jakarta.servlet.http.*; 022 023import org.apache.juneau.internal.*; 024import org.apache.juneau.rest.util.*; 025 026/** 027 * An implementation of {@link HttpServletResponse} for mocking purposes. 028 * 029 * <h5 class='section'>See Also:</h5><ul> 030 * <li class='link'><a class="doclink" href="../../../../../index.html#juneau-rest-mock">juneau-rest-mock</a> 031 * </ul> 032*/ 033public class MockServletResponse implements HttpServletResponse { 034 035 private String characterEncoding = "UTF-8"; 036 private ByteArrayOutputStream baos = new ByteArrayOutputStream(); 037 private int bufferSize = 0; 038 private Locale locale; 039 private int sc; 040 private String msg; 041 private Map<String,String[]> headerMap = map(); 042 043 /** 044 * Creates a new servlet response. 045 * 046 * @return A new response. 047 */ 048 public static MockServletResponse create() { 049 return new MockServletResponse(); 050 } 051 052 /** 053 * Returns the response message. 054 * 055 * @return The response message. 056 */ 057 public String getMessage() { 058 return msg; 059 } 060 061 @Override /* HttpServletResponse */ 062 public String getCharacterEncoding() { 063 return characterEncoding ; 064 } 065 066 @Override /* HttpServletResponse */ 067 public String getContentType() { 068 return getHeader("Content-Type"); 069 } 070 071 @Override /* HttpServletResponse */ 072 public ServletOutputStream getOutputStream() throws IOException { 073 return new FinishableServletOutputStream(baos); 074 } 075 076 @Override /* HttpServletResponse */ 077 public PrintWriter getWriter() throws IOException { 078 return new PrintWriter(new OutputStreamWriter(getOutputStream(), characterEncoding)); 079 } 080 081 @Override /* HttpServletResponse */ 082 public void setCharacterEncoding(String charset) { 083 this.characterEncoding = charset; 084 updateContentTypeHeader(); 085 } 086 087 private void updateContentTypeHeader() { 088 String contentType = getContentType(); 089 String charset = characterEncoding; 090 if (contentType != null && charset != null) { 091 if (contentType.indexOf("charset=") != -1) 092 contentType = contentType.replaceAll("\\;\\s*charset=.*", ""); 093 if (! "UTF-8".equalsIgnoreCase(charset)) 094 contentType = contentType + ";charset=" + charset; 095 header("Content-Type", contentType); 096 } 097 } 098 099 @Override /* HttpServletResponse */ 100 public void setContentLength(int len) { 101 header("Content-Length", String.valueOf(len)); 102 } 103 104 @Override /* HttpServletResponse */ 105 public void setContentLengthLong(long len) { 106 header("Content-Length", String.valueOf(len)); 107 } 108 109 @Override /* HttpServletResponse */ 110 public void setContentType(String type) { 111 setHeader("Content-Type", type); 112 updateContentTypeHeader(); 113 } 114 115 @Override /* HttpServletResponse */ 116 public void setBufferSize(int size) { 117 this.bufferSize = size; 118 } 119 120 @Override /* HttpServletResponse */ 121 public int getBufferSize() { 122 return bufferSize; 123 } 124 125 @Override /* HttpServletResponse */ 126 public void flushBuffer() throws IOException { 127 } 128 129 @Override /* HttpServletResponse */ 130 public void resetBuffer() { 131 } 132 133 @Override /* HttpServletResponse */ 134 public boolean isCommitted() { 135 return false; 136 } 137 138 @Override /* HttpServletResponse */ 139 public void reset() { 140 } 141 142 @Override /* HttpServletResponse */ 143 public void setLocale(Locale loc) { 144 this.locale = loc; 145 } 146 147 @Override /* HttpServletResponse */ 148 public Locale getLocale() { 149 return locale; 150 } 151 152 @Override /* HttpServletResponse */ 153 public void addCookie(Cookie cookie) { 154 } 155 156 @Override /* HttpServletResponse */ 157 public boolean containsHeader(String name) { 158 return getHeader(name) != null; 159 } 160 161 @Override /* HttpServletResponse */ 162 public String encodeURL(String url) { 163 return null; 164 } 165 166 @Override /* HttpServletResponse */ 167 public String encodeRedirectURL(String url) { 168 return null; 169 } 170 171 @Override /* HttpServletResponse */ 172 public void sendError(int sc, String msg) throws IOException { 173 this.sc = sc; 174 this.msg = msg; 175 } 176 177 @Override /* HttpServletResponse */ 178 public void sendError(int sc) throws IOException { 179 this.sc = sc; 180 } 181 182 @Override /* HttpServletResponse */ 183 public void sendRedirect(String location) throws IOException { 184 this.sc = 302; 185 headerMap.put("Location", new String[] {location}); 186 } 187 188 @Override /* HttpServletResponse */ 189 public void setDateHeader(String name, long date) { 190 headerMap.put(name, new String[] {DateUtils.formatDate(new Date(date), DateUtils.PATTERN_RFC1123)}); 191 } 192 193 @Override /* HttpServletResponse */ 194 public void addDateHeader(String name, long date) { 195 headerMap.put(name, new String[] {DateUtils.formatDate(new Date(date), DateUtils.PATTERN_RFC1123)}); 196 } 197 198 @Override /* HttpServletResponse */ 199 public void setHeader(String name, String value) { 200 headerMap.put(name, new String[] {value}); 201 } 202 203 @Override /* HttpServletResponse */ 204 public void addHeader(String name, String value) { 205 headerMap.put(name, new String[] {value}); 206 } 207 208 /** 209 * Fluent setter for {@link #setHeader(String,String)}. 210 * 211 * @param name The header name. 212 * @param value The new header value. 213 * @return This object. 214 */ 215 public MockServletResponse header(String name, String value) { 216 setHeader(name, value); 217 return this; 218 } 219 220 @Override /* HttpServletResponse */ 221 public void setIntHeader(String name, int value) { 222 headerMap.put(name, new String[] {String.valueOf(value)}); 223 } 224 225 @Override /* HttpServletResponse */ 226 public void addIntHeader(String name, int value) { 227 headerMap.put(name, new String[] {String.valueOf(value)}); 228 } 229 230 @Override /* HttpServletResponse */ 231 public void setStatus(int sc) { 232 this.sc = sc; 233 } 234 235 /** 236 * Fluent setter for {@link #setStatus(int)}. 237 * 238 * @param value The new property value. 239 * @return This object. 240 */ 241 public MockServletResponse status(int value) { 242 setStatus(value); 243 return this; 244 } 245 246 @Override /* HttpServletResponse */ 247 public int getStatus() { 248 return sc; 249 } 250 251 @Override /* HttpServletResponse */ 252 public String getHeader(String name) { 253 String[] s = headerMap.get(name); 254 return s == null || s.length == 0 ? null : s[0]; 255 } 256 257 @Override /* HttpServletResponse */ 258 public Collection<String> getHeaders(String name) { 259 String[] s = headerMap.get(name); 260 return s == null ? emptyList() : ulist(s); 261 } 262 263 @Override /* HttpServletResponse */ 264 public Collection<String> getHeaderNames() { 265 return headerMap.keySet(); 266 } 267 268 byte[] getContent() throws IOException { 269 baos.flush(); 270 return baos.toByteArray(); 271 } 272 273 Map<String,String[]> getHeaders() { 274 return headerMap; 275 } 276}