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.StringUtils.*; 016 017import java.io.*; 018import java.text.*; 019import java.util.*; 020import java.util.regex.*; 021 022import javax.servlet.*; 023import javax.servlet.http.*; 024 025import org.apache.juneau.internal.*; 026import org.apache.juneau.rest.util.*; 027import org.apache.juneau.utils.*; 028 029/** 030 * An implementation of {@link HttpServletResponse} for mocking purposes. 031 * 032 * @deprecated Use <c>org.apache.juneau.rest.mock2</c> 033*/ 034@Deprecated 035public class MockServletResponse implements HttpServletResponse, MockHttpResponse { 036 037 private String characterEncoding = "UTF-8"; 038 private ByteArrayOutputStream baos = new ByteArrayOutputStream(); 039 private long contentLength = 0; 040 private int bufferSize = 0; 041 private Locale locale; 042 private int sc; 043 private String msg; 044 private Map<String,String[]> headerMap = new LinkedHashMap<>(); 045 046 047 /** 048 * Creates a new servlet response. 049 * 050 * @return A new response. 051 */ 052 public static MockServletResponse create() { 053 return new MockServletResponse(); 054 } 055 056 /** 057 * Returns the content length. 058 * 059 * @return The content length. 060 */ 061 public long getContentLength() { 062 return contentLength; 063 } 064 065 /** 066 * Returns the response message. 067 * 068 * @return The response message. 069 */ 070 @Override /* MockHttpResponse */ 071 public String getMessage() { 072 return msg; 073 } 074 075 @Override /* HttpServletResponse */ 076 public String getCharacterEncoding() { 077 return characterEncoding ; 078 } 079 080 @Override /* HttpServletResponse */ 081 public String getContentType() { 082 return getHeader("Content-Type"); 083 } 084 085 @Override /* HttpServletResponse */ 086 public ServletOutputStream getOutputStream() throws IOException { 087 return new FinishableServletOutputStream(baos); 088 } 089 090 @Override /* HttpServletResponse */ 091 public PrintWriter getWriter() throws IOException { 092 return new PrintWriter(new OutputStreamWriter(getOutputStream(), characterEncoding)); 093 } 094 095 @Override /* HttpServletResponse */ 096 public void setCharacterEncoding(String charset) { 097 this.characterEncoding = charset; 098 } 099 100 @Override /* HttpServletResponse */ 101 public void setContentLength(int len) { 102 this.contentLength = len; 103 } 104 105 @Override /* HttpServletResponse */ 106 public void setContentLengthLong(long len) { 107 this.contentLength = len; 108 } 109 110 @Override /* HttpServletResponse */ 111 public void setContentType(String type) { 112 setHeader("Content-Type", type); 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 String encodeUrl(String url) { 173 return null; 174 } 175 176 @Override /* HttpServletResponse */ 177 public String encodeRedirectUrl(String url) { 178 return null; 179 } 180 181 @Override /* HttpServletResponse */ 182 public void sendError(int sc, String msg) throws IOException { 183 this.sc = sc; 184 this.msg = msg; 185 } 186 187 @Override /* HttpServletResponse */ 188 public void sendError(int sc) throws IOException { 189 this.sc = sc; 190 } 191 192 @Override /* HttpServletResponse */ 193 public void sendRedirect(String location) throws IOException { 194 this.sc = 302; 195 headerMap.put("Location", new String[] {location}); 196 } 197 198 @Override /* HttpServletResponse */ 199 public void setDateHeader(String name, long date) { 200 headerMap.put(name, new String[] {DateUtils.formatDate(new Date(date), DateUtils.PATTERN_RFC1123)}); 201 } 202 203 @Override /* HttpServletResponse */ 204 public void addDateHeader(String name, long date) { 205 headerMap.put(name, new String[] {DateUtils.formatDate(new Date(date), DateUtils.PATTERN_RFC1123)}); 206 } 207 208 @Override /* HttpServletResponse */ 209 public void setHeader(String name, String value) { 210 headerMap.put(name, new String[] {value}); 211 } 212 213 @Override /* HttpServletResponse */ 214 public void addHeader(String name, String value) { 215 headerMap.put(name, new String[] {value}); 216 } 217 218 @Override /* HttpServletResponse */ 219 public void setIntHeader(String name, int value) { 220 headerMap.put(name, new String[] {String.valueOf(value)}); 221 } 222 223 @Override /* HttpServletResponse */ 224 public void addIntHeader(String name, int value) { 225 headerMap.put(name, new String[] {String.valueOf(value)}); 226 } 227 228 @Override /* HttpServletResponse */ 229 public void setStatus(int sc) { 230 this.sc = sc; 231 } 232 233 @Override /* HttpServletResponse */ 234 public void setStatus(int sc, String sm) { 235 this.sc = sc; 236 this.msg = sm; 237 } 238 239 @Override /* HttpServletResponse */ 240 public int getStatus() { 241 return sc; 242 } 243 244 @Override /* HttpServletResponse */ 245 public String getHeader(String name) { 246 String[] s = headerMap.get(name); 247 return s == null || s.length == 0 ? null : s[0]; 248 } 249 250 @Override /* HttpServletResponse */ 251 public Collection<String> getHeaders(String name) { 252 String[] s = headerMap.get(name); 253 return s == null ? Collections.emptyList() : Arrays.asList(s); 254 } 255 256 @Override /* HttpServletResponse */ 257 public Collection<String> getHeaderNames() { 258 return headerMap.keySet(); 259 } 260 261 /** 262 * Returns the body of the request as a string. 263 * 264 * @return The body of the request as a string. 265 */ 266 public String getBodyAsString() { 267 try { 268 return baos.toString("UTF-8"); 269 } catch (UnsupportedEncodingException e) { 270 throw new RuntimeException(e); 271 } 272 } 273 274 /** 275 * Throws an {@link AssertionError} if the response status does not match the expected status. 276 * 277 * @param status The expected status. 278 * @return This object (for method chaining). 279 * @throws AssertionError Thrown if status does not match. 280 */ 281 public MockServletResponse assertStatus(int status) throws AssertionError { 282 if (getStatus() != status) 283 throw new MockAssertionError("Response did not have the expected status.\n\tExpected=[{0}]\n\tActual=[{1}]", status, getStatus()); 284 return this; 285 } 286 287 /** 288 * Throws an {@link AssertionError} if the response body does not contain the expected text. 289 * 290 * @param text The expected text of the body. 291 * @return This object (for method chaining). 292 * @throws AssertionError Thrown if the body does not contain the expected text. 293 */ 294 public MockServletResponse assertBody(String text) throws AssertionError { 295 if (! StringUtils.isEquals(text, getBodyAsString())) 296 throw new MockAssertionError("Response did not have the expected text.\n\tExpected=[{0}]\n\tActual=[{1}]", text, getBodyAsString()); 297 return this; 298 } 299 300 /** 301 * Throws an {@link AssertionError} if the response body does not contain all of the expected substrings. 302 * 303 * @param substrings The expected substrings. 304 * @return This object (for method chaining). 305 * @throws AssertionError Thrown if the body does not contain one or more of the expected substrings. 306 */ 307 public MockServletResponse assertBodyContains(String...substrings) throws AssertionError { 308 String text = getBodyAsString(); 309 for (String substring : substrings) 310 if (! contains(text, substring)) 311 throw new MockAssertionError("Response did not have the expected substring.\n\tExpected=[{0}]\n\tBody=[{1}]", substring, text); 312 return this; 313 } 314 315 /** 316 * Throws an {@link AssertionError} if the response body does not match the specified pattern. 317 * 318 * <p> 319 * A pattern is a simple string containing <js>"*"</js> to represent zero or more arbitrary characters. 320 * 321 * @param pattern The pattern to match against. 322 * @return This object (for method chaining). 323 * @throws AssertionError Thrown if the body does not match the specified pattern. 324 */ 325 public MockServletResponse assertBodyMatches(String pattern) throws AssertionError { 326 String text = getBodyAsString(); 327 if (! getMatchPattern(pattern).matcher(text).matches()) 328 throw new MockAssertionError("Response did not match expected pattern.\n\tPattern=[{0}]\n\tBody=[{1}]", pattern, text); 329 return this; 330 } 331 332 /** 333 * Throws an {@link AssertionError} if the response body does not match the specified regular expression. 334 * 335 * <p> 336 * A pattern is a simple string containing <js>"*"</js> to represent zero or more arbitrary characters. 337 * 338 * @param regExp The regular expression to match against. 339 * @return This object (for method chaining). 340 * @throws AssertionError Thrown if the body does not match the specified regular expression. 341 */ 342 public MockServletResponse assertBodyMatchesRE(String regExp) throws AssertionError { 343 String text = getBodyAsString(); 344 if (! Pattern.compile(regExp).matcher(text).matches()) 345 throw new MockAssertionError("Response did not match expected regular expression.\n\tRegExp=[{0}]\n\tBody=[{1}]", regExp, text); 346 return this; 347 } 348 349 /** 350 * Throws an {@link AssertionError} if the response does not contain the expected character encoding. 351 * 352 * @param value The expected character encoding. 353 * @return This object (for method chaining). 354 * @throws AssertionError Thrown if the response does not contain the expected character encoding. 355 */ 356 public MockServletResponse assertCharset(String value) { 357 if (! StringUtils.isEquals(value, getCharacterEncoding())) 358 throw new MockAssertionError("Response did not have the expected character encoding.\n\tExpected=[{0}]\n\tActual=[{1}]", value, getBodyAsString()); 359 return this; 360 } 361 362 /** 363 * Throws an {@link AssertionError} if the response does not contain the expected header value. 364 * 365 * @param name The header name. 366 * @param value The expected header value. 367 * @return This object (for method chaining). 368 * @throws AssertionError Thrown if the response does not contain the expected header value. 369 */ 370 public MockServletResponse assertHeader(String name, String value) { 371 if (! StringUtils.isEquals(value, getHeader(name))) 372 throw new MockAssertionError("Response did not have the expected value for header {0}.\n\tExpected=[{1}]\n\tActual=[{2}]", name, value, getHeader(name)); 373 return this; 374 } 375 376 /** 377 * Throws an {@link AssertionError} if the response header does not contain all of the expected substrings. 378 * 379 * @param name The header name. 380 * @param substrings The expected substrings. 381 * @return This object (for method chaining). 382 * @throws AssertionError Thrown if the header does not contain one or more of the expected substrings. 383 */ 384 public MockServletResponse assertHeaderContains(String name, String...substrings) { 385 String text = getHeader(name); 386 for (String substring : substrings) 387 if (! contains(text, substring)) 388 throw new MockAssertionError("Response did not have the expected substring in header {0}.\n\tExpected=[{1}]\n\tHeader=[{2}]", name, substring, text); 389 return this; 390 } 391 392 /** 393 * Returns the body of the request. 394 * 395 * @return The body of the request. 396 */ 397 @Override /* MockHttpResponse */ 398 public byte[] getBody() { 399 return baos.toByteArray(); 400 } 401 402 @Override /* MockHttpResponse */ 403 public Map<String,String[]> getHeaders() { 404 return headerMap; 405 } 406 407 private static class MockAssertionError extends AssertionError { 408 private static final long serialVersionUID = 1L; 409 410 MockAssertionError(String msg, Object...args) { 411 super(MessageFormat.format(msg, args)); 412 System.err.println(getMessage()); // NOT DEBUG 413 } 414 } 415}