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

hazendaz / httpunit / 755

14 Feb 2026 07:14PM UTC coverage: 80.526%. Remained the same
755

push

github

hazendaz
[ci] Fix badge

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8245 of 10124 relevant lines covered (81.44%)

0.81 hits per line

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

82.76
/src/main/java/com/meterware/httpunit/WebRequestSource.java
1
/*
2
 * SPDX-License-Identifier: MIT
3
 * See LICENSE file for details.
4
 *
5
 * Copyright 2000-2026 Russell Gold
6
 * Copyright 2021-2000 hazendaz
7
 */
8
package com.meterware.httpunit;
9

10
import com.meterware.httpunit.scripting.ScriptableDelegate;
11
import com.meterware.httpunit.scripting.ScriptingHandler;
12

13
import java.io.IOException;
14
import java.net.URL;
15
import java.util.StringTokenizer;
16

17
import org.w3c.dom.Element;
18
import org.w3c.dom.Node;
19
import org.xml.sax.SAXException;
20

21
/**
22
 * Base class for objects which can be clicked to generate new web requests.
23
 */
24
public abstract class WebRequestSource extends ParameterHolder implements HTMLElement {
25

26
    /** The frame. */
27
    private FrameSelector _frame;
28

29
    /**
30
     * The name of the destination attribute used to create for the request, including anchors and parameters. *
31
     */
32
    private String _destinationAttribute;
33

34
    /** The scriptable. */
35
    private ScriptingHandler _scriptable;
36

37
    /**
38
     * Returns the ID associated with this request source.
39
     */
40
    @Override
41
    public String getID() {
42
        return getAttribute("id");
1✔
43
    }
44

45
    /**
46
     * Returns the class associated with this request source.
47
     */
48
    @Override
49
    public String getClassName() {
50
        return getAttribute("class");
1✔
51
    }
52

53
    /**
54
     * Returns the name associated with this request source.
55
     */
56
    @Override
57
    public String getName() {
58
        return getAttribute("name");
1✔
59
    }
60

61
    /**
62
     * Returns the title associated with this request source.
63
     */
64
    @Override
65
    public String getTitle() {
66
        return getAttribute("title");
1✔
67
    }
68

69
    /**
70
     * Returns the target for this request source.
71
     *
72
     * @return the target
73
     */
74
    public String getTarget() {
75
        if (getSpecifiedTarget().isEmpty()) {
1✔
76
            return _defaultTarget;
1✔
77
        }
78
        return getSpecifiedTarget();
1✔
79
    }
80

81
    /**
82
     * Returns the name of the frame containing this request source.
83
     *
84
     * @return the page frame
85
     *
86
     * @deprecated as of 1.6, use #getFrame
87
     */
88
    @Deprecated
89
    public String getPageFrame() {
90
        return _frame.getName();
×
91
    }
92

93
    /**
94
     * Returns the frame containing this request source.
95
     *
96
     * @return the frame
97
     */
98
    public FrameSelector getFrame() {
99
        return _frame;
1✔
100
    }
101

102
    /**
103
     * Returns the fragment identifier for this request source, used to identifier an element within an HTML document.
104
     *
105
     * @return the fragment identifier
106
     */
107
    public String getFragmentIdentifier() {
108
        final int hashIndex = getDestination().indexOf('#');
1✔
109
        if (hashIndex < 0) {
1✔
110
            return "";
1✔
111
        }
112
        return getDestination().substring(hashIndex + 1);
1✔
113
    }
114

115
    /**
116
     * Returns a copy of the domain object model subtree associated with this entity.
117
     *
118
     * @return the DOM subtree
119
     */
120
    public Node getDOMSubtree() {
121
        return _node.cloneNode( /* deep */true);
×
122
    }
123

124
    /**
125
     * Creates and returns a web request from this request source.
126
     *
127
     * @return the request
128
     */
129
    public abstract WebRequest getRequest();
130

131
    /**
132
     * Returns an array containing the names of any parameters to be sent on a request based on this request source.
133
     */
134
    @Override
135
    public abstract String[] getParameterNames();
136

137
    /**
138
     * Returns the values of the named parameter.
139
     */
140
    @Override
141
    public abstract String[] getParameterValues(String name);
142

143
    /**
144
     * Returns the URL relative to the current page which will handle the request.
145
     *
146
     * @return the relative page
147
     */
148
    String getRelativePage() {
149
        final String url = getRelativeURL();
1✔
150
        if (HttpUnitUtils.isJavaScriptURL(url)) {
1!
151
            return url;
×
152
        }
153
        final int questionMarkIndex = url.indexOf("?");
1✔
154
        if (questionMarkIndex >= 1 && questionMarkIndex < url.length() - 1) {
1!
155
            return url.substring(0, questionMarkIndex);
1✔
156
        }
157
        return url;
1✔
158
    }
159

160
    /**
161
     * get the relative URL for a weblink change spaces to %20.
162
     *
163
     * @return the relative URL as a string
164
     */
165
    protected String getRelativeURL() {
166
        String result = HttpUnitUtils.encodeSpaces(HttpUnitUtils.trimFragment(getDestination()));
1✔
167
        if (result.trim().isEmpty()) {
1✔
168
            result = getBaseURL().getFile();
1✔
169
        }
170
        return result;
1✔
171
    }
172

173
    // ----------------------------- protected members
174
    // ---------------------------------------------
175

176
    /**
177
     * Contructs a web request source.
178
     *
179
     * @param response
180
     *            the response from which this request source was extracted
181
     * @param node
182
     *            the DOM subtree defining this request source
183
     * @param baseURL
184
     *            the URL on which to base all releative URL requests
185
     * @param attribute
186
     *            the attribute which defines the relative URL to which requests will be directed
187
     * @param frame
188
     *            the frame
189
     * @param defaultTarget
190
     *            the default target
191
     */
192
    WebRequestSource(WebResponse response, Node node, URL baseURL, String attribute, FrameSelector frame,
193
            String defaultTarget) {
1✔
194
        if (node == null) {
1!
195
            throw new IllegalArgumentException("node must not be null");
×
196
        }
197
        _baseResponse = response;
1✔
198
        _node = node;
1✔
199
        _baseURL = baseURL;
1✔
200
        _destinationAttribute = attribute;
1✔
201
        _frame = frame;
1✔
202
        _defaultTarget = defaultTarget;
1✔
203
    }
1✔
204

205
    /**
206
     * Gets the base URL.
207
     *
208
     * @return the base URL
209
     */
210
    protected URL getBaseURL() {
211
        return _baseURL;
1✔
212
    }
213

214
    /**
215
     * get the Destination made public per FR 2836664 make WebRequestSource.getDestination() public by Dan Lipofsky
216
     *
217
     * @return the destination
218
     */
219
    public String getDestination() {
220
        return getElement().getAttribute(_destinationAttribute);
1✔
221
    }
222

223
    /**
224
     * Sets the destination.
225
     *
226
     * @param destination
227
     *            the new destination
228
     */
229
    protected void setDestination(String destination) {
230
        getElement().setAttribute(_destinationAttribute, destination);
1✔
231
    }
1✔
232

233
    /**
234
     * Returns the actual DOM for this request source, not a copy.
235
     *
236
     * @return the element
237
     */
238
    protected Element getElement() {
239
        return (Element) _node;
1✔
240
    }
241

242
    /**
243
     * Returns the HTMLPage associated with this request source.
244
     *
245
     * @return the HTML page
246
     *
247
     * @throws SAXException
248
     *             the SAX exception
249
     */
250
    protected HTMLPage getHTMLPage() throws SAXException {
251
        return _baseResponse.getReceivedPage();
1✔
252
    }
253

254
    /**
255
     * Extracts any parameters specified as part of the destination URL, calling addPresetParameter for each one in the
256
     * order in which they are found.
257
     */
258
    protected final void loadDestinationParameters() {
259
        StringTokenizer st = new StringTokenizer(getParametersString(), PARAM_DELIM);
1✔
260
        while (st.hasMoreTokens()) {
1✔
261
            stripOneParameter(st.nextToken());
1✔
262
        }
263
    }
1✔
264

265
    /**
266
     * submit the given event for the given request.
267
     *
268
     * @param event
269
     *            the event
270
     * @param request
271
     *            the request
272
     *
273
     * @return the response for the submitted Request
274
     *
275
     * @throws IOException
276
     *             Signals that an I/O exception has occurred.
277
     * @throws SAXException
278
     *             the SAX exception
279
     */
280
    protected WebResponse submitRequest(String event, final WebRequest request) throws IOException, SAXException {
281
        WebResponse response = null;
1✔
282
        if (doEventScript(event)) {
1✔
283
            response = submitRequest(request);
1✔
284
        }
285
        if (response == null) {
1✔
286
            response = getCurrentFrameContents();
1✔
287
        }
288
        return response;
1✔
289
    }
290

291
    /**
292
     * handle the event that has the given script attached by compiling the eventScript as a function and executing it
293
     *
294
     * @param eventScript
295
     *            - the script to use
296
     *
297
     * @deprecated since 1.7 - use doEventScript instead
298
     */
299
    @Deprecated
300
    @Override
301
    public boolean doEvent(String eventScript) {
302
        return doEventScript(eventScript);
×
303
    }
304

305
    /**
306
     * optional do the event if it's defined
307
     *
308
     * @param eventScript
309
     *            - the script to handle
310
     *
311
     * @return whether the script was handled
312
     */
313
    @Override
314
    public boolean doEventScript(String eventScript) {
315
        return this.getScriptingHandler().doEventScript(eventScript);
1✔
316
    }
317

318
    @Override
319
    public boolean handleEvent(String eventName) {
320
        return this.getScriptingHandler().handleEvent(eventName);
1✔
321
    }
322

323
    /**
324
     * Gets the current frame contents.
325
     *
326
     * @return the current frame contents
327
     */
328
    protected WebResponse getCurrentFrameContents() {
329
        return getCurrentFrame(getBaseResponse().getWindow(), _frame);
1✔
330
    }
331

332
    /**
333
     * Gets the current frame.
334
     *
335
     * @param window
336
     *            the window
337
     * @param pageFrame
338
     *            the page frame
339
     *
340
     * @return the current frame
341
     */
342
    private WebResponse getCurrentFrame(WebWindow window, FrameSelector pageFrame) {
343
        return window.hasFrame(pageFrame) ? window.getFrameContents(pageFrame) : window.getCurrentPage();
1✔
344
    }
345

346
    /**
347
     * Submits a request to the web client from which this request source was originally obtained.
348
     *
349
     * @param request
350
     *            the request
351
     *
352
     * @return the web response
353
     *
354
     * @throws IOException
355
     *             Signals that an I/O exception has occurred.
356
     * @throws SAXException
357
     *             the SAX exception
358
     */
359
    protected final WebResponse submitRequest(WebRequest request) throws IOException, SAXException {
360
        return getDestination().equals("#") ? _baseResponse : _baseResponse.getWindow().sendRequest(request);
1!
361
    }
362

363
    /**
364
     * Returns the web response containing this request source.
365
     *
366
     * @return the base response
367
     */
368
    protected final WebResponse getBaseResponse() {
369
        return _baseResponse;
1✔
370
    }
371

372
    /**
373
     * Records a parameter defined by including it in the destination URL. The value can be null, if the parameter name
374
     * was not specified with an equals sign.
375
     *
376
     * @param name
377
     *            the name
378
     * @param value
379
     *            the value
380
     */
381
    abstract protected void addPresetParameter(String name, String value);
382

383
    /**
384
     * get the attribute value for the given name
385
     *
386
     * @param name
387
     *            - the name of the attribute to get
388
     */
389
    @Override
390
    public String getAttribute(final String name) {
391
        return NodeUtils.getNodeAttribute(_node, name);
1✔
392
    }
393

394
    /**
395
     * set the attribute with the given name to the given value
396
     *
397
     * @param name
398
     *            - the name of the attribute
399
     * @param value
400
     *            - the value to use
401
     */
402
    @Override
403
    public void setAttribute(final String name, final Object value) {
404
        NodeUtils.setNodeAttribute(getNode(), name, value == null ? null : value.toString());
×
405
    }
×
406

407
    /**
408
     * remove the given attribute
409
     *
410
     * @param name
411
     *            - the name of the attribute to remove
412
     */
413
    @Override
414
    public void removeAttribute(final String name) {
415
        NodeUtils.removeNodeAttribute(getNode(), name);
×
416
    }
×
417

418
    @Override
419
    public boolean isSupportedAttribute(String name) {
420
        return false;
1✔
421
    }
422

423
    @Override
424
    public Node getNode() {
425
        return _node;
1✔
426
    }
427

428
    /**
429
     * Returns the text value of this block.
430
     */
431
    @Override
432
    public String getText() {
433
        if (_node == null) {
1!
434
            return "";
×
435
        }
436
        if (_node.getNodeType() == Node.TEXT_NODE) {
1!
437
            return _node.getNodeValue().trim();
×
438
        }
439
        if (!_node.hasChildNodes()) {
1!
440
            return "";
×
441
        }
442
        return NodeUtils.asText(_node.getChildNodes()).trim();
1✔
443
    }
444

445
    @Override
446
    public String getTagName() {
447
        return _node.getNodeName();
×
448
    }
449

450
    /**
451
     * Gets the attribute.
452
     *
453
     * @param name
454
     *            the name
455
     * @param defaultValue
456
     *            the default value
457
     *
458
     * @return the attribute
459
     */
460
    String getAttribute(final String name, String defaultValue) {
461
        return NodeUtils.getNodeAttribute(_node, name, defaultValue);
1✔
462
    }
463

464
    // ----------------------------- private members
465
    // -----------------------------------------------
466

467
    /**
468
     * parameter Delimiter for URL parameters bug report [ 1052037 ] Semicolon not supported as URL param delimiter asks
469
     * for this to be extended to &;.
470
     *
471
     * @see http://www.w3.org/TR/html4/appendix/notes.html#h-B.2 section B2.2
472
     */
473
    private static final String PARAM_DELIM = "&";
474

475
    /** The web response containing this request source. * */
476
    private WebResponse _baseResponse;
477

478
    /**
479
     * The name of the frame in which the response containing this request source is rendered. *
480
     */
481
    private String _defaultTarget;
482

483
    /** The URL of the page containing this entity. * */
484
    private URL _baseURL;
485

486
    /** The DOM node representing this entity. * */
487
    private Node _node;
488

489
    /**
490
     * Gets the specified target.
491
     *
492
     * @return the specified target
493
     */
494
    private String getSpecifiedTarget() {
495
        return getAttribute("target");
1✔
496
    }
497

498
    /**
499
     * Sets the target attribute.
500
     *
501
     * @param value
502
     *            the new target attribute
503
     */
504
    protected void setTargetAttribute(String value) {
505
        ((Element) _node).setAttribute("target", value);
1✔
506
    }
1✔
507

508
    /**
509
     * Gets all parameters from a URL.
510
     *
511
     * @return the parameters string
512
     */
513
    private String getParametersString() {
514
        String url = HttpUnitUtils.trimFragment(getDestination());
1✔
515
        if (url.trim().isEmpty()) {
1✔
516
            url = getBaseURL().toExternalForm();
1✔
517
        }
518
        if (HttpUnitUtils.isJavaScriptURL(url)) {
1!
519
            return "";
×
520
        }
521
        final int questionMarkIndex = url.indexOf("?");
1✔
522
        if (questionMarkIndex >= 1 && questionMarkIndex < url.length() - 1) {
1!
523
            return url.substring(questionMarkIndex + 1);
1✔
524
        }
525
        return "";
1✔
526
    }
527

528
    /**
529
     * Extracts a parameter of the form <name>[=[<value>]].
530
     *
531
     * @param param
532
     *            the param
533
     */
534
    private void stripOneParameter(String param) {
535
        final int index = param.indexOf("=");
1✔
536
        String value = index < 0 ? null
1✔
537
                : index == param.length() - 1 ? getEmptyParameterValue() : decode(param.substring(index + 1));
1✔
538
        String name = index < 0 ? decode(param) : decode(param.substring(0, index));
1✔
539
        addPresetParameter(name, value);
1✔
540
    }
1✔
541

542
    /**
543
     * Decode.
544
     *
545
     * @param string
546
     *            the string
547
     *
548
     * @return the string
549
     */
550
    private String decode(String string) {
551
        return HttpUnitUtils.decode(string, _baseResponse.getCharacterSet()).trim();
1✔
552
    }
553

554
    /**
555
     * Gets the empty parameter value.
556
     *
557
     * @return the empty parameter value
558
     */
559
    abstract protected String getEmptyParameterValue();
560

561
    /**
562
     * Returns the scriptable delegate.
563
     */
564
    @Override
565
    public ScriptingHandler getScriptingHandler() {
566
        if (_scriptable == null) {
1✔
567
            _scriptable = HttpUnitOptions.getScriptingEngine().createHandler(this);
1✔
568
        }
569
        return _scriptable;
1✔
570
    }
571

572
    @Override
573
    public ScriptableDelegate getParentDelegate() {
574
        return getBaseResponse().getDocumentScriptable();
1✔
575
    }
576

577
}
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