1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit;
16
17 import static java.nio.charset.StandardCharsets.ISO_8859_1;
18
19 import java.io.IOException;
20 import java.net.URL;
21 import java.nio.charset.Charset;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.htmlunit.util.MimeType;
31 import org.htmlunit.util.NameValuePair;
32
33
34
35
36
37
38
39
40
41
42
43 public class MockWebConnection implements WebConnection {
44
45 private static final Log LOG = LogFactory.getLog(MockWebConnection.class);
46
47 private final Map<String, IOException> throwableMap_ = new HashMap<>();
48 private final Map<String, RawResponseData> responseMap_ = new HashMap<>();
49 private RawResponseData defaultResponse_;
50 private WebRequest lastRequest_;
51 private int requestCount_;
52 private final List<URL> requestedUrls_ = Collections.synchronizedList(new ArrayList<>());
53
54
55
56
57 public static class RawResponseData {
58 private final List<NameValuePair> headers_;
59 private final byte[] byteContent_;
60 private final String stringContent_;
61 private final int statusCode_;
62 private final String statusMessage_;
63 private Charset charset_;
64
65 RawResponseData(final byte[] byteContent, final int statusCode, final String statusMessage,
66 final String contentType, final List<NameValuePair> headers) {
67 byteContent_ = byteContent;
68 stringContent_ = null;
69 statusCode_ = statusCode;
70 statusMessage_ = statusMessage;
71 headers_ = compileHeaders(headers, contentType);
72 }
73
74 RawResponseData(final String stringContent, final Charset charset, final int statusCode,
75 final String statusMessage, final String contentType, final List<NameValuePair> headers) {
76 byteContent_ = null;
77 charset_ = charset;
78 stringContent_ = stringContent;
79 statusCode_ = statusCode;
80 statusMessage_ = statusMessage;
81 headers_ = compileHeaders(headers, contentType);
82 }
83
84 private static List<NameValuePair> compileHeaders(final List<NameValuePair> headers, final String contentType) {
85 final List<NameValuePair> compiledHeaders = new ArrayList<>();
86 if (headers != null) {
87 compiledHeaders.addAll(headers);
88 }
89 if (contentType != null) {
90 compiledHeaders.add(new NameValuePair(HttpHeader.CONTENT_TYPE, contentType));
91 }
92 return compiledHeaders;
93 }
94
95 WebResponseData asWebResponseData() {
96 final byte[] content;
97 if (byteContent_ != null) {
98 content = byteContent_;
99 }
100 else if (stringContent_ == null) {
101 content = new byte[] {};
102 }
103 else {
104 content = stringContent_.getBytes(charset_);
105 }
106 return new WebResponseData(content, statusCode_, statusMessage_, headers_);
107 }
108
109
110
111
112
113 public List<NameValuePair> getHeaders() {
114 return headers_;
115 }
116
117
118
119
120
121 public byte[] getByteContent() {
122 return byteContent_;
123 }
124
125
126
127
128
129 public String getStringContent() {
130 return stringContent_;
131 }
132
133
134
135
136
137 public int getStatusCode() {
138 return statusCode_;
139 }
140
141
142
143
144
145 public String getStatusMessage() {
146 return statusMessage_;
147 }
148
149
150
151
152
153 public Charset getCharset() {
154 return charset_;
155 }
156 }
157
158
159
160
161 @Override
162 public WebResponse getResponse(final WebRequest request) throws IOException {
163 final RawResponseData rawResponse = getRawResponse(request);
164 return new WebResponse(rawResponse.asWebResponseData(), request, 0);
165 }
166
167
168
169
170
171
172
173 public RawResponseData getRawResponse(final WebRequest request) throws IOException {
174 final URL url = request.getUrl();
175
176 if (LOG.isDebugEnabled()) {
177 LOG.debug("Getting response for " + url.toExternalForm());
178 }
179
180 lastRequest_ = request;
181 requestCount_++;
182 requestedUrls_.add(url);
183
184 String urlString = url.toExternalForm();
185 final IOException throwable = throwableMap_.get(urlString);
186 if (throwable != null) {
187 throw throwable;
188 }
189
190 RawResponseData rawResponse = responseMap_.get(urlString);
191 if (rawResponse == null) {
192
193 final int queryStart = urlString.lastIndexOf('?');
194 if (queryStart > -1) {
195 urlString = urlString.substring(0, queryStart);
196 rawResponse = responseMap_.get(urlString);
197 }
198
199
200 if (rawResponse == null) {
201 rawResponse = defaultResponse_;
202 if (rawResponse == null) {
203 throw new IllegalStateException("No response specified that can handle URL "
204 + request.getHttpMethod()
205 + " [" + urlString + "]");
206 }
207 }
208 }
209
210 return rawResponse;
211 }
212
213
214
215
216
217 public List<URL> getRequestedUrls() {
218 return Collections.unmodifiableList(requestedUrls_);
219 }
220
221
222
223
224
225
226 public List<String> getRequestedUrls(final URL relativeTo) {
227 final String baseUrl = relativeTo.toString();
228 final List<String> response = new ArrayList<>();
229 for (final URL url : requestedUrls_) {
230 String s = url.toString();
231 if (s.startsWith(baseUrl)) {
232 s = s.substring(baseUrl.length());
233 }
234 response.add(s);
235 }
236
237 return Collections.unmodifiableList(response);
238 }
239
240
241
242
243
244
245 public HttpMethod getLastMethod() {
246 return lastRequest_.getHttpMethod();
247 }
248
249
250
251
252
253
254 public List<NameValuePair> getLastParameters() {
255 return lastRequest_.getRequestParameters();
256 }
257
258
259
260
261
262
263
264
265
266
267 public void setResponse(final URL url, final String content, final int statusCode,
268 final String statusMessage, final String contentType,
269 final List<NameValuePair> headers) {
270
271 setResponse(
272 url,
273 content,
274 statusCode,
275 statusMessage,
276 contentType,
277 ISO_8859_1,
278 headers);
279 }
280
281
282
283
284
285
286
287
288
289
290
291 public void setResponse(final URL url, final String content, final int statusCode,
292 final String statusMessage, final String contentType, final Charset charset,
293 final List<NameValuePair> headers) {
294
295 final RawResponseData responseEntry = buildRawResponseData(content, charset, statusCode, statusMessage,
296 contentType, headers);
297 responseMap_.put(url.toExternalForm(), responseEntry);
298 }
299
300
301
302
303
304
305 public void setThrowable(final URL url, final IOException throwable) {
306 throwableMap_.put(url.toExternalForm(), throwable);
307 }
308
309
310
311
312
313
314
315
316
317
318 public void setResponse(final URL url, final byte[] content, final int statusCode,
319 final String statusMessage, final String contentType,
320 final List<NameValuePair> headers) {
321
322 final RawResponseData responseEntry = buildRawResponseData(content, statusCode, statusMessage, contentType,
323 headers);
324 responseMap_.put(url.toExternalForm(), responseEntry);
325 }
326
327 private static RawResponseData buildRawResponseData(final byte[] content, final int statusCode,
328 final String statusMessage, final String contentType, final List<NameValuePair> headers) {
329 return new RawResponseData(content, statusCode, statusMessage, contentType, headers);
330 }
331
332 private static RawResponseData buildRawResponseData(final String content, Charset charset, final int statusCode,
333 final String statusMessage, final String contentType, final List<NameValuePair> headers) {
334
335 if (charset == null) {
336 charset = ISO_8859_1;
337 }
338 return new RawResponseData(content, charset, statusCode, statusMessage, contentType, headers);
339 }
340
341
342
343
344
345
346
347
348
349 public void setResponse(final URL url, final String content) {
350 setResponse(url, content, 200, "OK", MimeType.TEXT_HTML, null);
351 }
352
353
354
355
356
357
358
359
360
361
362 public void setResponse(final URL url, final String content, final String contentType) {
363 setResponse(url, content, 200, "OK", contentType, null);
364 }
365
366
367
368
369
370
371
372
373
374
375
376 public void setResponse(final URL url, final String content, final String contentType, final Charset charset) {
377 setResponse(url, content, 200, "OK", contentType, charset, null);
378 }
379
380
381
382
383
384
385
386
387
388 public void setResponseAsGenericHtml(final URL url, final String title) {
389 final String content = "<!DOCTYPE html><html><head><title>" + title + "</title></head><body></body></html>";
390 setResponse(url, content);
391 }
392
393
394
395
396
397
398
399
400
401
402 public void setDefaultResponse(final String content, final int statusCode,
403 final String statusMessage, final String contentType) {
404
405 defaultResponse_ = buildRawResponseData(content, null, statusCode, statusMessage, contentType, null);
406 }
407
408
409
410
411
412
413
414
415
416
417 public void setDefaultResponse(final byte[] content, final int statusCode,
418 final String statusMessage, final String contentType) {
419
420 defaultResponse_ = buildRawResponseData(content, statusCode, statusMessage, contentType, null);
421 }
422
423
424
425
426
427
428
429 public void setDefaultResponse(final String content) {
430 setDefaultResponse(content, 200, "OK", MimeType.TEXT_HTML);
431 }
432
433
434
435
436
437
438
439
440 public void setDefaultResponse(final String content, final String contentType) {
441 setDefaultResponse(content, 200, "OK", contentType, null);
442 }
443
444
445
446
447
448
449
450
451
452 public void setDefaultResponse(final String content, final String contentType, final Charset charset) {
453 setDefaultResponse(content, 200, "OK", contentType, charset, null);
454 }
455
456
457
458
459
460
461
462
463
464 public void setDefaultResponse(final String content, final int statusCode,
465 final String statusMessage, final String contentType,
466 final List<NameValuePair> headers) {
467
468 defaultResponse_ = buildRawResponseData(content, null, statusCode, statusMessage, contentType, headers);
469 }
470
471
472
473
474
475
476
477
478
479
480 public void setDefaultResponse(final String content, final int statusCode,
481 final String statusMessage, final String contentType, final Charset charset,
482 final List<NameValuePair> headers) {
483
484 defaultResponse_ = buildRawResponseData(content, charset, statusCode, statusMessage, contentType, headers);
485 }
486
487
488
489
490
491
492
493 public Map<String, String> getLastAdditionalHeaders() {
494 return lastRequest_.getAdditionalHeaders();
495 }
496
497
498
499
500
501
502
503 public WebRequest getLastWebRequest() {
504 return lastRequest_;
505 }
506
507
508
509
510
511 public int getRequestCount() {
512 return requestCount_;
513 }
514
515
516
517
518
519
520 public boolean hasResponse(final URL url) {
521 return responseMap_.containsKey(url.toExternalForm());
522 }
523
524
525
526
527 @Override
528 public void close() {
529 clear();
530 }
531
532
533
534
535 public void clear() {
536 throwableMap_.clear();
537 responseMap_.clear();
538 defaultResponse_ = null;
539 lastRequest_ = null;
540 requestCount_ = 0;
541 requestedUrls_.clear();
542 }
543 }