• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / httpunit / 389

12 Aug 2025 11:17PM UTC coverage: 80.48% (-0.02%) from 80.503%
389

push

github

hazendaz
Merge branch 'master' into javax

3216 of 4105 branches covered (78.34%)

Branch coverage included in aggregate %.

238 of 258 new or added lines in 68 files covered. (92.25%)

2 existing lines in 2 files now uncovered.

8254 of 10147 relevant lines covered (81.34%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.3
/src/main/java/com/meterware/httpunit/WebClient.java
1
/*
2
 * MIT License
3
 *
4
 * Copyright 2011-2025 Russell Gold
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
7
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
9
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions
12
 * of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
15
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
17
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18
 * DEALINGS IN THE SOFTWARE.
19
 */
20
package com.meterware.httpunit;
21

22
import com.meterware.httpunit.cookies.Cookie;
23
import com.meterware.httpunit.cookies.CookieJar;
24

25
import java.io.IOException;
26
import java.io.OutputStream;
27
import java.net.HttpURLConnection;
28
import java.net.PasswordAuthentication;
29
import java.net.URL;
30
import java.nio.charset.StandardCharsets;
31
import java.util.ArrayList;
32
import java.util.Base64;
33
import java.util.Dictionary;
34
import java.util.Enumeration;
35
import java.util.Hashtable;
36
import java.util.Iterator;
37
import java.util.LinkedList;
38
import java.util.List;
39

40
import org.xml.sax.SAXException;
41

42
/**
43
 * The context for a series of web requests. This class manages cookies used to maintain session context, computes
44
 * relative URLs, and generally emulates the browser behavior needed to build an automated test of a web site.
45
 *
46
 * @author <a href="mailto:russgold@httpunit.org">Russell Gold</a>
47
 * @author Jan Ohrstrom
48
 * @author Seth Ladd
49
 * @author Oliver Imbusch
50
 **/
51
public abstract class WebClient {
52

53
    private ArrayList _openWindows = new ArrayList<>();
1✔
54

55
    /** The current main window. **/
56
    private WebWindow _mainWindow = new WebWindow(this);
1✔
57

58
    /** An authorization string to be sent with every request, whether challenged or not. May be null. **/
59
    private String _fixedAuthorizationString;
60

61
    /** An authorization string to be sent with the next request only. May be null. **/
62
    private String _authorizationString;
63

64
    private String _proxyAuthorizationString;
65
    private Hashtable _credentials = new Hashtable<>();
1✔
66

67
    public WebWindow getMainWindow() {
68
        return _mainWindow;
1✔
69
    }
70

71
    public void setMainWindow(WebWindow mainWindow) {
72
        if (!_openWindows.contains(mainWindow)) {
×
73
            throw new IllegalArgumentException("May only select an open window owned by this client");
×
74
        }
75
        _mainWindow = mainWindow;
×
76
    }
×
77

78
    public WebWindow[] getOpenWindows() {
79
        return (WebWindow[]) _openWindows.toArray(new WebWindow[_openWindows.size()]);
1✔
80
    }
81

82
    public WebWindow getOpenWindow(String name) {
83
        if (name == null || name.isEmpty()) {
1!
84
            return null;
×
85
        }
86
        for (Iterator i = _openWindows.iterator(); i.hasNext();) {
1!
87
            WebWindow window = (WebWindow) i.next();
1✔
88
            if (name.equals(window.getName())) {
1✔
89
                return window;
1✔
90
            }
91
        }
1✔
92
        return null;
×
93
    }
94

95
    /**
96
     * Submits a GET method request and returns a response.
97
     *
98
     * @exception SAXException
99
     *                thrown if there is an error parsing the retrieved page
100
     **/
101
    public WebResponse getResponse(String urlString) throws IOException, SAXException {
102
        return _mainWindow.getResponse(urlString);
1✔
103
    }
104

105
    /**
106
     * Submits a web request and returns a response. This is an alternate name for the getResponse method.
107
     */
108
    public WebResponse sendRequest(WebRequest request) throws IOException, SAXException {
109
        return _mainWindow.sendRequest(request);
1✔
110
    }
111

112
    /**
113
     * Returns the response representing the current top page in the main window.
114
     */
115
    public WebResponse getCurrentPage() {
116
        return _mainWindow.getCurrentPage();
1✔
117
    }
118

119
    /**
120
     * Submits a web request and returns a response, using all state developed so far as stored in cookies as requested
121
     * by the server.
122
     *
123
     * @exception SAXException
124
     *                thrown if there is an error parsing the retrieved page
125
     **/
126
    public WebResponse getResponse(WebRequest request) throws IOException, SAXException {
127
        return _mainWindow.getResponse(request);
1✔
128
    }
129

130
    /**
131
     * Returns the name of the currently active frames in the main window.
132
     **/
133
    public String[] getFrameNames() {
134
        return _mainWindow.getFrameNames();
1✔
135
    }
136

137
    /**
138
     * Returns the response associated with the specified frame name in the main window. Throws a runtime exception if
139
     * no matching frame is defined.
140
     **/
141
    public WebResponse getFrameContents(String frameName) {
142
        return _mainWindow.getFrameContents(frameName);
1✔
143
    }
144

145
    /**
146
     * Returns the response associated with the specified frame name in the main window. Throws a runtime exception if
147
     * no matching frame is defined.
148
     *
149
     * @since 1.6
150
     **/
151
    public WebResponse getFrameContents(FrameSelector targetFrame) {
152
        return _mainWindow.getFrameContents(targetFrame);
1✔
153
    }
154

155
    /**
156
     * Returns the resource specified by the request. Does not update the client or load included framesets or scripts.
157
     * May return null if the resource is a JavaScript URL which would normally leave the client unchanged.
158
     */
159
    public WebResponse getResource(WebRequest request) throws IOException {
160
        return _mainWindow.getResource(request);
×
161
    }
162

163
    /**
164
     * Resets the state of this client, removing all cookies, frames, and per-client headers. This does not affect any
165
     * listeners or preferences which may have been set.
166
     **/
167
    public void clearContents() {
168
        _mainWindow = new WebWindow(this);
×
169
        _cookieJar.clear();
×
170
        _headers = new HeaderDictionary();
×
171
    }
×
172

173
    /**
174
     * Defines a cookie to be sent to the server on every request.
175
     *
176
     * @deprecated as of 1.6, use #putCookie instead.
177
     **/
178
    @Deprecated
179
    public void addCookie(String name, String value) {
180
        _cookieJar.addCookie(name, value);
×
181
    }
×
182

183
    /**
184
     * Defines a cookie to be sent to the server on every request. This overrides any previous setting for this cookie
185
     * name.
186
     **/
187
    public void putCookie(String name, String value) {
188
        _cookieJar.putCookie(name, value);
1✔
189
    }
1✔
190

191
    /**
192
     * Returns the name of all the active cookies which will be sent to the server.
193
     **/
194
    public String[] getCookieNames() {
195
        return _cookieJar.getCookieNames();
1✔
196
    }
197

198
    /**
199
     * Returns an object containing the details of the named cookie
200
     *
201
     * @since [ 1488617 ] alternate patch for cookie bug #1371204
202
     */
203
    public Cookie getCookieDetails(String name) {
204
        return _cookieJar.getCookie(name);
1✔
205
    }
206

207
    /**
208
     * Returns the value of the specified cookie.
209
     **/
210
    public String getCookieValue(String name) {
211
        return _cookieJar.getCookieValue(name);
1✔
212
    }
213

214
    /**
215
     * Returns the properties associated with this client.
216
     */
217
    public ClientProperties getClientProperties() {
218
        if (_clientProperties == null) {
1✔
219
            _clientProperties = ClientProperties.getDefaultProperties().cloneProperties();
1✔
220
        }
221
        return _clientProperties;
1✔
222
    }
223

224
    /**
225
     * Specifies the user agent identification. Used to trigger browser-specific server behavior.
226
     *
227
     * @deprecated as of 1.4.6. Use ClientProperties#setUserAgent instead.
228
     **/
229
    @Deprecated
230
    public void setUserAgent(String userAgent) {
231
        getClientProperties().setUserAgent(userAgent);
×
232
    }
×
233

234
    /**
235
     * Returns the current user agent setting.
236
     *
237
     * @deprecated as of 1.4.6. Use ClientProperties#getUserAgent instead.
238
     **/
239
    @Deprecated
240
    public String getUserAgent() {
241
        return getClientProperties().getUserAgent();
×
242
    }
243

244
    /**
245
     * Sets a username and password for a basic authentication scheme. Use #setAuthentication for more accurate
246
     * emulation of browser behavior.
247
     **/
248
    public void setAuthorization(String userName, String password) {
249
        _fixedAuthorizationString = "Basic "
1✔
250
                + Base64.getEncoder().encodeToString((userName + ':' + password).getBytes(StandardCharsets.UTF_8));
1✔
251
    }
1✔
252

253
    /**
254
     * Specifies a username and password for on-demand authentication. Will only send the authorization header when
255
     * challenged for the specified realm.
256
     *
257
     * @param realm
258
     *            the realm for which the credentials apply.
259
     * @param username
260
     *            the user to authenticate
261
     * @param password
262
     *            the credentials for the user
263
     */
264
    public void setAuthentication(String realm, String username, String password) {
265
        _credentials.put(realm, new PasswordAuthentication(username, password.toCharArray()));
1✔
266
    }
1✔
267

268
    /**
269
     * get the credentials for the given realm
270
     *
271
     * @param realm
272
     *
273
     * @return
274
     */
275
    PasswordAuthentication getCredentialsForRealm(String realm) {
276
        if (_credentials == null) {
1!
277
            throw new Error("null _credentials while calling getCredentialsForRealm");
×
278
        }
279
        if (realm == null) {
1!
280
            throw new Error("null realm while calling getCredentialsForRealm");
×
281
        }
282
        return (PasswordAuthentication) _credentials.get(realm);
1✔
283
    }
284

285
    /**
286
     * Specifies a proxy server to use for requests from this client.
287
     */
288
    public abstract void setProxyServer(String proxyHost, int proxyPort);
289

290
    /**
291
     * Specifies a proxy server to use, along with a user and password for authentication.
292
     *
293
     * @since 1.6
294
     */
295
    public void setProxyServer(String proxyHost, int proxyPort, String userName, String password) {
296
        setProxyServer(proxyHost, proxyPort);
×
NEW
297
        _proxyAuthorizationString = "Basic "
×
NEW
298
                + Base64.getEncoder().encodeToString((userName + ':' + password).getBytes(StandardCharsets.UTF_8));
×
UNCOV
299
    }
×
300

301
    /**
302
     * Clears the proxy server settings.
303
     */
304
    public void clearProxyServer() {
305
    }
×
306

307
    /**
308
     * Returns the name of the active proxy server.
309
     */
310
    public String getProxyHost() {
311
        return System.getProperty("proxyHost");
×
312
    }
313

314
    /**
315
     * Returns the number of the active proxy port, or 0 is none is specified.
316
     */
317
    public int getProxyPort() {
318
        try {
319
            return Integer.getInteger("proxyPort");
×
320
        } catch (NumberFormatException e) {
×
321
            return 0;
×
322
        }
323
    }
324

325
    /**
326
     * Sets the value for a header field to be sent with all requests. If the value set is null, removes the header from
327
     * those to be sent.
328
     **/
329
    public void setHeaderField(String fieldName, String fieldValue) {
330
        _headers.put(fieldName, fieldValue);
1✔
331
    }
1✔
332

333
    /**
334
     * Returns the value for the header field with the specified name. This method will ignore the case of the field
335
     * name.
336
     */
337
    public String getHeaderField(String fieldName) {
338
        return (String) _headers.get(fieldName);
×
339
    }
340

341
    /**
342
     * Specifies whether an exception will be thrown when an error status (4xx or 5xx) is detected on a response.
343
     * Defaults to the value returned by HttpUnitOptions.getExceptionsThrownOnErrorStatus.
344
     **/
345
    public void setExceptionsThrownOnErrorStatus(boolean throwExceptions) {
346
        _exceptionsThrownOnErrorStatus = throwExceptions;
1✔
347
    }
1✔
348

349
    /**
350
     * Returns true if an exception will be thrown when an error status (4xx or 5xx) is detected on a response.
351
     **/
352
    public boolean getExceptionsThrownOnErrorStatus() {
353
        return _exceptionsThrownOnErrorStatus;
1✔
354
    }
355

356
    /**
357
     * Adds a listener to watch for requests and responses.
358
     */
359
    public void addClientListener(WebClientListener listener) {
360
        synchronized (_clientListeners) {
1✔
361
            if (listener != null && !_clientListeners.contains(listener)) {
1!
362
                _clientListeners.add(listener);
1✔
363
            }
364
        }
1✔
365
    }
1✔
366

367
    /**
368
     * Removes a listener to watch for requests and responses.
369
     */
370
    public void removeClientListener(WebClientListener listener) {
371
        synchronized (_clientListeners) {
×
372
            _clientListeners.remove(listener);
×
373
        }
×
374
    }
×
375

376
    /**
377
     * Adds a listener to watch for window openings and closings.
378
     */
379
    public void addWindowListener(WebWindowListener listener) {
380
        synchronized (_windowListeners) {
1✔
381
            if (listener != null && !_windowListeners.contains(listener)) {
1!
382
                _windowListeners.add(listener);
1✔
383
            }
384
        }
1✔
385
    }
1✔
386

387
    /**
388
     * Removes a listener to watch for window openings and closings.
389
     */
390
    public void removeWindowListener(WebWindowListener listener) {
391
        synchronized (_windowListeners) {
×
392
            _windowListeners.remove(listener);
×
393
        }
×
394
    }
×
395

396
    /**
397
     * Returns the next javascript alert without removing it from the queue.
398
     */
399
    public String getNextAlert() {
400
        return _alerts.isEmpty() ? null : (String) _alerts.getFirst();
1✔
401
    }
402

403
    /**
404
     * Returns the next javascript alert and removes it from the queue. If the queue is empty, will return an empty
405
     * string.
406
     */
407
    public String popNextAlert() {
408
        if (_alerts.isEmpty()) {
1✔
409
            return "";
1✔
410
        }
411
        return (String) _alerts.removeFirst();
1✔
412
    }
413

414
    /**
415
     * Specifies the object which will respond to all dialogs.
416
     **/
417
    public void setDialogResponder(DialogResponder responder) {
418
        _dialogResponder = responder;
1✔
419
    }
1✔
420

421
    // ------------------------------------------ protected members -----------------------------------
422

423
    protected WebClient() {
1✔
424
        _openWindows.add(_mainWindow);
1✔
425
    }
1✔
426

427
    /**
428
     * Creates a web response object which represents the response to the specified web request.
429
     *
430
     * @param request
431
     *            the request to which the response should be generated
432
     * @param targetFrame
433
     *            the frame in which the response should be stored
434
     **/
435
    abstract protected WebResponse newResponse(WebRequest request, FrameSelector targetFrame) throws IOException;
436

437
    /**
438
     * Writes the message body for the request.
439
     **/
440
    protected final void writeMessageBody(WebRequest request, OutputStream stream) throws IOException {
441
        request.writeMessageBody(stream);
1✔
442
    }
1✔
443

444
    /**
445
     * Returns the value of all current header fields.
446
     **/
447
    protected Dictionary getHeaderFields(URL targetURL) {
448
        Hashtable result = (Hashtable) _headers.clone();
1✔
449
        result.put("User-Agent", getClientProperties().getUserAgent());
1✔
450
        if (getClientProperties().isAcceptGzip()) {
1✔
451
            result.put("Accept-Encoding", "gzip");
1✔
452
        }
453
        AddHeaderIfNotNull(result, "Cookie", _cookieJar.getCookieHeaderField(targetURL));
1✔
454
        if (_authorizationString == null) {
1✔
455
            _authorizationString = _fixedAuthorizationString;
1✔
456
        }
457
        AddHeaderIfNotNull(result, "Authorization", _authorizationString);
1✔
458
        AddHeaderIfNotNull(result, "Proxy-Authorization", _proxyAuthorizationString);
1✔
459
        _authorizationString = null;
1✔
460
        return result;
1✔
461
    }
462

463
    private void AddHeaderIfNotNull(Hashtable result, final String headerName, final String headerValue) {
464
        if (headerValue != null) {
1✔
465
            result.put(headerName, headerValue);
1✔
466
        }
467
    }
1✔
468

469
    /**
470
     * Updates this web client based on a received response. This includes updating cookies and frames. This method is
471
     * required by ServletUnit, which cannot call the updateWindow method directly.
472
     **/
473
    protected final void updateMainWindow(FrameSelector frame, WebResponse response) throws IOException, SAXException {
474
        getMainWindow().updateWindow(frame.getName(), response, new RequestContext());
1✔
475
    }
1✔
476

477
    // ------------------------------------------------- package members
478
    // ----------------------------------------------------
479

480
    void tellListeners(WebRequest request) {
481
        List listeners;
482

483
        synchronized (_clientListeners) {
1✔
484
            listeners = new ArrayList(_clientListeners);
1✔
485
        }
1✔
486

487
        for (Iterator i = listeners.iterator(); i.hasNext();) {
1✔
488
            ((WebClientListener) i.next()).requestSent(this, request);
1✔
489
        }
490
    }
1✔
491

492
    void tellListeners(WebResponse response) {
493
        List listeners;
494

495
        synchronized (_clientListeners) {
1✔
496
            listeners = new ArrayList(_clientListeners);
1✔
497
        }
1✔
498

499
        for (Iterator i = listeners.iterator(); i.hasNext();) {
1✔
500
            ((WebClientListener) i.next()).responseReceived(this, response);
1✔
501
        }
502
    }
1✔
503

504
    void updateClient(WebResponse response) throws IOException {
505
        if (getClientProperties().isAcceptCookies()) {
1✔
506
            _cookieJar.updateCookies(response.getCookieJar());
1✔
507
        }
508
        validateHeaders(response);
1✔
509
    }
1✔
510

511
    /**
512
     * Support Request [ 1288796 ] getCookieJar() in WebClient
513
     *
514
     * @deprecated - use with care - was not public in the past
515
     *
516
     * @return the cookie jar
517
     */
518
    @Deprecated
519
    public CookieJar getCookieJar() {
520
        return _cookieJar;
1✔
521
    }
522

523
    void updateFrameContents(WebWindow requestWindow, String requestTarget, WebResponse response,
524
            RequestContext requestContext) throws IOException, SAXException {
525
        if (response.getFrame() == FrameSelector.NEW_FRAME) {
1✔
526
            WebWindow window = new WebWindow(this, requestWindow.getCurrentPage());
1✔
527
            if (!WebRequest.NEW_WINDOW.equalsIgnoreCase(requestTarget)) {
1✔
528
                window.setName(requestTarget);
1✔
529
            }
530
            response.setFrame(window.getTopFrame());
1✔
531
            window.updateFrameContents(response, requestContext);
1✔
532
            _openWindows.add(window);
1✔
533
            reportWindowOpened(window);
1✔
534
        } else if (response.getFrame().getWindow() != null && response.getFrame().getWindow() != requestWindow) {
1✔
535
            response.getFrame().getWindow().updateFrameContents(response, requestContext);
1✔
536
        } else {
537
            if (response.getFrame() == FrameSelector.TOP_FRAME) {
1✔
538
                response.setFrame(requestWindow.getTopFrame());
1✔
539
            }
540
            requestWindow.updateFrameContents(response, requestContext);
1✔
541
        }
542
    }
1✔
543

544
    void close(WebWindow window) {
545
        if (!_openWindows.contains(window)) {
1!
546
            throw new IllegalStateException("Window is already closed");
×
547
        }
548
        _openWindows.remove(window);
1✔
549
        if (_openWindows.isEmpty()) {
1✔
550
            _openWindows.add(new WebWindow(this));
1✔
551
        }
552
        if (window.equals(_mainWindow)) {
1✔
553
            _mainWindow = (WebWindow) _openWindows.get(0);
1✔
554
        }
555
        reportWindowClosed(window);
1✔
556
    }
1✔
557

558
    private void reportWindowOpened(WebWindow window) {
559
        List listeners;
560

561
        synchronized (_windowListeners) {
1✔
562
            listeners = new ArrayList(_windowListeners);
1✔
563
        }
1✔
564

565
        for (Iterator i = listeners.iterator(); i.hasNext();) {
1✔
566
            ((WebWindowListener) i.next()).windowOpened(this, window);
1✔
567
        }
568
    }
1✔
569

570
    private void reportWindowClosed(WebWindow window) {
571
        List listeners;
572

573
        synchronized (_windowListeners) {
1✔
574
            listeners = new ArrayList(_windowListeners);
1✔
575
        }
1✔
576

577
        for (Iterator i = listeners.iterator(); i.hasNext();) {
1✔
578
            ((WebWindowListener) i.next()).windowClosed(this, window);
1✔
579
        }
580
    }
1✔
581

582
    // ------------------------------------------ package members ------------------------------------
583

584
    boolean getConfirmationResponse(String message) {
585
        return _dialogResponder.getConfirmation(message);
1✔
586
    }
587

588
    String getUserResponse(String message, String defaultResponse) {
589
        return _dialogResponder.getUserResponse(message, defaultResponse);
1✔
590
    }
591

592
    /**
593
     * simulate an alert by remembering the alert message on a Stack
594
     *
595
     * @param message
596
     *            - the alert message to post
597
     */
598
    void postAlert(String message) {
599
        _alerts.addLast(message);
1✔
600
    }
1✔
601

602
    // ------------------------------------------ private members -------------------------------------
603

604
    /** The list of alerts generated by JavaScript. **/
605
    private LinkedList _alerts = new LinkedList();
1✔
606

607
    /** The currently defined cookies. **/
608
    private CookieJar _cookieJar = new CookieJar();
1✔
609

610
    /** A map of header names to values. **/
611
    private HeaderDictionary _headers = new HeaderDictionary();
1✔
612

613
    private boolean _exceptionsThrownOnErrorStatus = HttpUnitOptions.getExceptionsThrownOnErrorStatus();
1✔
614

615
    private final List _clientListeners = new ArrayList<>();
1✔
616

617
    private final List _windowListeners = new ArrayList<>();
1✔
618

619
    private DialogResponder _dialogResponder = new DialogAdapter();
1✔
620

621
    private ClientProperties _clientProperties;
622

623
    /**
624
     * Examines the headers in the response and throws an exception if appropriate.
625
     *
626
     * @parm response - the response to validate
627
     **/
628
    private void validateHeaders(WebResponse response) throws HttpException {
629
        HttpException exception = null;
1✔
630
        if (response.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) {
1!
631
            exception = new HttpInternalErrorException(response.getURL());
×
632
        } else if (response.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
1✔
633
            exception = new HttpNotFoundException(response.getResponseMessage(), response.getURL());
1✔
634
        } else if (response.getResponseCode() >= HttpURLConnection.HTTP_BAD_REQUEST) {
1✔
635
            exception = new HttpException(response.getResponseCode(), response.getResponseMessage(), response.getURL());
1✔
636
        }
637
        // is there an exception?
638
        if (exception != null) {
1✔
639
            // see feature request [ 914314 ] Add HttpException.getResponse for better reporting
640
            exception.setResponse(response);
1✔
641
            // shall we ignore errors?
642
            if (!getExceptionsThrownOnErrorStatus()) {
1✔
643
                return;
1✔
644
            }
645
            throw exception;
1✔
646
        }
647
    }
1✔
648

649
    FrameSelector findFrame(String target) {
650
        for (Object _openWindow : _openWindows) {
1✔
651
            WebWindow webWindow = (WebWindow) _openWindow;
1✔
652
            FrameSelector frame = webWindow.getFrame(target);
1✔
653
            if (frame != null) {
1✔
654
                return frame;
1✔
655
            }
656
        }
1✔
657
        return null;
1✔
658
    }
659

660
    /**
661
     * Sends a request and returns a response after dealing with any authentication challenge. If challenged and able to
662
     * respond, resends the request after setting the authentication header (which will apply only for the that
663
     * request).
664
     *
665
     * @param request
666
     *            the original request
667
     * @param targetFrame
668
     *            the frame into which the result will be stored
669
     *
670
     * @return a response from the server
671
     *
672
     * @throws IOException
673
     *             if an exception (including authorization failure) occurs
674
     */
675
    WebResponse createResponse(WebRequest request, FrameSelector targetFrame) throws IOException {
676
        WebResponse response = newResponse(request, targetFrame);
1✔
677
        AuthenticationChallenge challenge = new AuthenticationChallenge(this, request,
1✔
678
                response.getHeaderField("WWW-Authenticate"));
1✔
679
        if (!challenge.needToAuthenticate()) {
1✔
680
            return response;
1✔
681
        }
682
        setOnetimeAuthenticationHeader(challenge.createAuthenticationHeader());
1✔
683
        WebResponse response2 = newResponse(request, targetFrame);
1✔
684
        if (response2.getHeaderField("WWW-Authenticate") != null && getExceptionsThrownOnErrorStatus()) {
1!
685
            throw AuthenticationChallenge.createException(response2.getHeaderField("WWW-Authenticate"));
×
686
        }
687
        return response2;
1✔
688
    }
689

690
    private void setOnetimeAuthenticationHeader(String authorizationHeader) {
691
        _authorizationString = authorizationHeader;
1✔
692
    }
1✔
693

694
    // ==================================================================================================
695

696
    static public class HeaderDictionary extends Hashtable {
1✔
697

698
        private static final long serialVersionUID = 1L;
699

700
        public void addEntries(Dictionary source) {
701
            for (Enumeration e = source.keys(); e.hasMoreElements();) {
1✔
702
                Object key = e.nextElement();
1✔
703
                put(key, source.get(key));
1✔
704
            }
1✔
705
        }
1✔
706

707
        @Override
708
        public boolean containsKey(Object key) {
709
            return super.containsKey(matchPreviousFieldName(key.toString()));
1✔
710
        }
711

712
        @Override
713
        public Object get(Object fieldName) {
714
            return super.get(matchPreviousFieldName(fieldName.toString()));
1✔
715
        }
716

717
        @Override
718
        public Object put(Object fieldName, Object fieldValue) {
719
            fieldName = matchPreviousFieldName(fieldName.toString());
1✔
720
            Object oldValue = super.get(fieldName);
1✔
721
            if (fieldValue == null) {
1!
722
                remove(fieldName);
×
723
            } else {
724
                super.put(fieldName, fieldValue);
1✔
725
            }
726
            return oldValue;
1✔
727
        }
728

729
        /**
730
         * If a matching field name with different case is already known, returns the older name. Otherwise, returns the
731
         * specified name.
732
         **/
733
        private String matchPreviousFieldName(String fieldName) {
734
            for (Enumeration e = keys(); e.hasMoreElements();) {
1✔
735
                String key = (String) e.nextElement();
1✔
736
                if (key.equalsIgnoreCase(fieldName)) {
1✔
737
                    return key;
1✔
738
                }
739
            }
1✔
740
            return fieldName;
1✔
741
        }
742

743
    }
744

745
}
746

747
// ==================================================================================================
748

749
class RedirectWebRequest extends WebRequest {
750

751
    RedirectWebRequest(WebResponse response) {
752
        super(response.getURL(), response.getHeaderField("Location"), response.getFrame(), response.getFrameName());
1✔
753
        if (response.getReferer() != null) {
1✔
754
            setHeaderField("Referer", response.getReferer());
1✔
755
        }
756
    }
1✔
757

758
    /**
759
     * Returns the HTTP method defined for this request.
760
     **/
761
    @Override
762
    public String getMethod() {
763
        return "GET";
1✔
764
    }
765
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc