001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.mock; 018 019import java.io.ByteArrayOutputStream; 020import java.io.IOException; 021import java.time.Instant; 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.List; 025import java.util.Set; 026import javax.servlet.http.Cookie; 027import org.apache.wicket.WicketRuntimeException; 028import org.apache.wicket.request.HttpHeaderCollection; 029import org.apache.wicket.request.http.WebResponse; 030import org.apache.wicket.util.lang.Args; 031 032/** 033 * Mocked {@link WebResponse}. 034 * 035 * @author Matej Knopp 036 */ 037public class MockWebResponse extends WebResponse 038{ 039 /** response headers */ 040 private final HttpHeaderCollection headers = new HttpHeaderCollection(); 041 042 /** response cookies */ 043 private final List<Cookie> cookies = new ArrayList<Cookie>(); 044 045 /** url for redirection */ 046 private String redirectUrl; 047 048 /** content type of response */ 049 private String contentType; 050 051 /** content length of response in bytes */ 052 private Long contentLength; 053 054 /** current characters in response body */ 055 private StringBuilder textResponse; 056 057 /** current octets in response body */ 058 private ByteArrayOutputStream binaryResponse; 059 060 /** http response status */ 061 private Integer status; 062 063 /** response error message */ 064 private String errorMessage; 065 066 /** 067 * Construct. 068 */ 069 public MockWebResponse() 070 { 071 } 072 073 @Override 074 public void addCookie(Cookie cookie) 075 { 076 cookies.add(cookie); 077 } 078 079 @Override 080 public void clearCookie(Cookie cookie) 081 { 082 cookies.remove(cookie); 083 } 084 085 /** 086 * @return cookies set in this response 087 */ 088 public List<Cookie> getCookies() 089 { 090 return Collections.unmodifiableList(cookies); 091 } 092 093 @Override 094 public void sendRedirect(String url) 095 { 096 redirectUrl = url; 097 } 098 099 /** 100 * @return redirect URL or <code>null</code> if {@link #sendRedirect(String)} was not called. 101 */ 102 public String getRedirectUrl() 103 { 104 return redirectUrl; 105 } 106 107 /** 108 * @return <code>true</code> if redirect URL was set, <code>false</code> otherwise. 109 */ 110 @Override 111 public boolean isRedirect() 112 { 113 return redirectUrl != null; 114 } 115 116 @Override 117 public void setContentLength(long length) 118 { 119 contentLength = length; 120 setHeader("Content-Length", String.valueOf(length).intern()); 121 } 122 123 /** 124 * @return content length (set by {@link #setContentLength(long)}) 125 */ 126 public Long getContentLength() 127 { 128 return contentLength; 129 } 130 131 @Override 132 public void setContentType(String mimeType) 133 { 134 contentType = mimeType; 135 } 136 137 /** 138 * @return content mime type 139 */ 140 public String getContentType() 141 { 142 return contentType; 143 } 144 145 @Override 146 public void setDateHeader(String name, Instant date) 147 { 148 Args.notNull(date, "date"); 149 headers.setDateHeader(name, date); 150 } 151 152 /** 153 * @param name 154 * 155 * @return date header with specified name 156 */ 157 public Instant getDateHeader(String name) 158 { 159 final Instant time = headers.getDateHeader(name); 160 161 if (time == null) 162 { 163 throw new WicketRuntimeException("Date header '" + name + "' is not set."); 164 } 165 return time; 166 } 167 168 @Override 169 public boolean isHeaderSupported() 170 { 171 return true; 172 } 173 174 @Override 175 public void setHeader(String name, String value) 176 { 177 internalSetContentType(name, value); 178 headers.setHeader(name, value); 179 } 180 181 @Override 182 public void addHeader(String name, String value) 183 { 184 internalSetContentType(name, value); 185 headers.addHeader(name, value); 186 } 187 188 /** 189 * set content type if it is specified 190 * 191 * @param name 192 * header name 193 * @param value 194 * header value 195 */ 196 private void internalSetContentType(String name, String value) 197 { 198 if ("Content-Type".equalsIgnoreCase(name)) 199 { 200 if (headers.containsHeader(name) == false) 201 { 202 setContentType(value); 203 } 204 } 205 } 206 207 /** 208 * @param name 209 * 210 * @return header string with specified name 211 */ 212 public String getHeader(String name) 213 { 214 return headers.getHeader(name); 215 } 216 217 /** 218 * @param name 219 * 220 * @return <code>true</code> if the header was set, <code>false</code> otherwise 221 */ 222 public boolean hasHeader(String name) 223 { 224 return headers.containsHeader(name); 225 } 226 227 /** 228 * @return set of all header names 229 */ 230 public Set<String> getHeaderNames() 231 { 232 return headers.getHeaderNames(); 233 } 234 235 @Override 236 public void setStatus(int sc) 237 { 238 status = sc; 239 } 240 241 /** 242 * @return status code or <code>null</code> if status was not set 243 */ 244 public Integer getStatus() 245 { 246 return status; 247 } 248 249 @Override 250 public String encodeURL(CharSequence url) 251 { 252 return url.toString(); 253 } 254 255 @Override 256 public String encodeRedirectURL(CharSequence url) 257 { 258 return url.toString(); 259 } 260 261 @Override 262 public void write(CharSequence sequence) 263 { 264 if (binaryResponse != null) 265 { 266 throw new IllegalStateException("Binary response has already been initiated."); 267 } 268 if (textResponse == null) 269 { 270 textResponse = new StringBuilder(); 271 } 272 textResponse.append(sequence); 273 } 274 275 /** 276 * @return text response 277 */ 278 public CharSequence getTextResponse() 279 { 280 return textResponse; 281 } 282 283 @Override 284 public void write(byte[] array) 285 { 286 if (textResponse != null) 287 { 288 throw new IllegalStateException("Text response has already been initiated."); 289 } 290 if (binaryResponse == null) 291 { 292 binaryResponse = new ByteArrayOutputStream(); 293 } 294 try 295 { 296 binaryResponse.write(array); 297 } 298 catch (IOException ignored) 299 { 300 } 301 } 302 303 @Override 304 public void write(byte[] array, int offset, int length) 305 { 306 if (textResponse != null) 307 { 308 throw new IllegalStateException("Text response has already been initiated."); 309 } 310 if (binaryResponse == null) 311 { 312 binaryResponse = new ByteArrayOutputStream(); 313 } 314 315 binaryResponse.write(array, offset, length); 316 } 317 318 /** 319 * @return binary response 320 */ 321 public byte[] getBinaryResponse() 322 { 323 if (binaryResponse == null) 324 { 325 return null; 326 } 327 else 328 { 329 byte[] bytes = binaryResponse.toByteArray(); 330 if (getContentLength() != null) 331 { 332 byte[] trimmed = new byte[getContentLength().intValue()]; 333 System.arraycopy(bytes, 0, trimmed, 0, getContentLength().intValue()); 334 return trimmed; 335 } 336 return bytes; 337 } 338 } 339 340 @Override 341 public void sendError(int sc, String msg) 342 { 343 status = sc; 344 errorMessage = msg; 345 } 346 347 /** 348 * @return error message 349 */ 350 public String getErrorMessage() 351 { 352 return errorMessage; 353 } 354 355 @Override 356 public void flush() 357 { 358 } 359 360 @Override 361 public void reset() 362 { 363 super.reset(); 364 if (binaryResponse != null) 365 { 366 binaryResponse = new ByteArrayOutputStream(); 367 } 368 contentLength = null; 369 contentType = null; 370 if (cookies != null) 371 { 372 cookies.clear(); 373 } 374 errorMessage = null; 375 if (headers != null) 376 { 377 headers.clear(); 378 } 379 redirectUrl = null; 380 status = null; 381 if (textResponse != null) 382 { 383 textResponse.setLength(0); 384 } 385 386 } 387 388 @Override 389 public Object getContainerResponse() 390 { 391 return this; 392 } 393}