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

hazendaz / httpunit / 656

06 Dec 2025 09:11PM UTC coverage: 80.452% (+0.02%) from 80.435%
656

push

github

hazendaz
[maven-release-plugin] prepare for next development iteration

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8245 of 10137 relevant lines covered (81.34%)

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
 * 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.scripting.ScriptableDelegate;
23
import com.meterware.httpunit.scripting.ScriptingHandler;
24

25
import java.io.IOException;
26
import java.net.URL;
27
import java.util.StringTokenizer;
28

29
import org.w3c.dom.Element;
30
import org.w3c.dom.Node;
31
import org.xml.sax.SAXException;
32

33
/**
34
 * Base class for objects which can be clicked to generate new web requests.
35
 */
36
public abstract class WebRequestSource extends ParameterHolder implements HTMLElement {
37

38
    /** The frame. */
39
    private FrameSelector _frame;
40

41
    /**
42
     * The name of the destination attribute used to create for the request, including anchors and parameters. *
43
     */
44
    private String _destinationAttribute;
45

46
    /** The scriptable. */
47
    private ScriptingHandler _scriptable;
48

49
    /**
50
     * Returns the ID associated with this request source.
51
     */
52
    @Override
53
    public String getID() {
54
        return getAttribute("id");
1✔
55
    }
56

57
    /**
58
     * Returns the class associated with this request source.
59
     */
60
    @Override
61
    public String getClassName() {
62
        return getAttribute("class");
1✔
63
    }
64

65
    /**
66
     * Returns the name associated with this request source.
67
     */
68
    @Override
69
    public String getName() {
70
        return getAttribute("name");
1✔
71
    }
72

73
    /**
74
     * Returns the title associated with this request source.
75
     */
76
    @Override
77
    public String getTitle() {
78
        return getAttribute("title");
1✔
79
    }
80

81
    /**
82
     * Returns the target for this request source.
83
     *
84
     * @return the target
85
     */
86
    public String getTarget() {
87
        if (getSpecifiedTarget().isEmpty()) {
1✔
88
            return _defaultTarget;
1✔
89
        }
90
        return getSpecifiedTarget();
1✔
91
    }
92

93
    /**
94
     * Returns the name of the frame containing this request source.
95
     *
96
     * @return the page frame
97
     *
98
     * @deprecated as of 1.6, use #getFrame
99
     */
100
    @Deprecated
101
    public String getPageFrame() {
102
        return _frame.getName();
×
103
    }
104

105
    /**
106
     * Returns the frame containing this request source.
107
     *
108
     * @return the frame
109
     */
110
    public FrameSelector getFrame() {
111
        return _frame;
1✔
112
    }
113

114
    /**
115
     * Returns the fragment identifier for this request source, used to identifier an element within an HTML document.
116
     *
117
     * @return the fragment identifier
118
     */
119
    public String getFragmentIdentifier() {
120
        final int hashIndex = getDestination().indexOf('#');
1✔
121
        if (hashIndex < 0) {
1✔
122
            return "";
1✔
123
        }
124
        return getDestination().substring(hashIndex + 1);
1✔
125
    }
126

127
    /**
128
     * Returns a copy of the domain object model subtree associated with this entity.
129
     *
130
     * @return the DOM subtree
131
     */
132
    public Node getDOMSubtree() {
133
        return _node.cloneNode( /* deep */true);
×
134
    }
135

136
    /**
137
     * Creates and returns a web request from this request source.
138
     *
139
     * @return the request
140
     */
141
    public abstract WebRequest getRequest();
142

143
    /**
144
     * Returns an array containing the names of any parameters to be sent on a request based on this request source.
145
     */
146
    @Override
147
    public abstract String[] getParameterNames();
148

149
    /**
150
     * Returns the values of the named parameter.
151
     */
152
    @Override
153
    public abstract String[] getParameterValues(String name);
154

155
    /**
156
     * Returns the URL relative to the current page which will handle the request.
157
     *
158
     * @return the relative page
159
     */
160
    String getRelativePage() {
161
        final String url = getRelativeURL();
1✔
162
        if (HttpUnitUtils.isJavaScriptURL(url)) {
1!
163
            return url;
×
164
        }
165
        final int questionMarkIndex = url.indexOf("?");
1✔
166
        if (questionMarkIndex >= 1 && questionMarkIndex < url.length() - 1) {
1!
167
            return url.substring(0, questionMarkIndex);
1✔
168
        }
169
        return url;
1✔
170
    }
171

172
    /**
173
     * get the relative URL for a weblink change spaces to %20.
174
     *
175
     * @return the relative URL as a string
176
     */
177
    protected String getRelativeURL() {
178
        String result = HttpUnitUtils.encodeSpaces(HttpUnitUtils.trimFragment(getDestination()));
1✔
179
        if (result.trim().isEmpty()) {
1✔
180
            result = getBaseURL().getFile();
1✔
181
        }
182
        return result;
1✔
183
    }
184

185
    // ----------------------------- protected members
186
    // ---------------------------------------------
187

188
    /**
189
     * Contructs a web request source.
190
     *
191
     * @param response
192
     *            the response from which this request source was extracted
193
     * @param node
194
     *            the DOM subtree defining this request source
195
     * @param baseURL
196
     *            the URL on which to base all releative URL requests
197
     * @param attribute
198
     *            the attribute which defines the relative URL to which requests will be directed
199
     * @param frame
200
     *            the frame
201
     * @param defaultTarget
202
     *            the default target
203
     */
204
    WebRequestSource(WebResponse response, Node node, URL baseURL, String attribute, FrameSelector frame,
205
            String defaultTarget) {
1✔
206
        if (node == null) {
1!
207
            throw new IllegalArgumentException("node must not be null");
×
208
        }
209
        _baseResponse = response;
1✔
210
        _node = node;
1✔
211
        _baseURL = baseURL;
1✔
212
        _destinationAttribute = attribute;
1✔
213
        _frame = frame;
1✔
214
        _defaultTarget = defaultTarget;
1✔
215
    }
1✔
216

217
    /**
218
     * Gets the base URL.
219
     *
220
     * @return the base URL
221
     */
222
    protected URL getBaseURL() {
223
        return _baseURL;
1✔
224
    }
225

226
    /**
227
     * get the Destination made public per FR 2836664 make WebRequestSource.getDestination() public by Dan Lipofsky
228
     *
229
     * @return the destination
230
     */
231
    public String getDestination() {
232
        return getElement().getAttribute(_destinationAttribute);
1✔
233
    }
234

235
    /**
236
     * Sets the destination.
237
     *
238
     * @param destination
239
     *            the new destination
240
     */
241
    protected void setDestination(String destination) {
242
        getElement().setAttribute(_destinationAttribute, destination);
1✔
243
    }
1✔
244

245
    /**
246
     * Returns the actual DOM for this request source, not a copy.
247
     *
248
     * @return the element
249
     */
250
    protected Element getElement() {
251
        return (Element) _node;
1✔
252
    }
253

254
    /**
255
     * Returns the HTMLPage associated with this request source.
256
     *
257
     * @return the HTML page
258
     *
259
     * @throws SAXException
260
     *             the SAX exception
261
     */
262
    protected HTMLPage getHTMLPage() throws SAXException {
263
        return _baseResponse.getReceivedPage();
1✔
264
    }
265

266
    /**
267
     * Extracts any parameters specified as part of the destination URL, calling addPresetParameter for each one in the
268
     * order in which they are found.
269
     */
270
    protected final void loadDestinationParameters() {
271
        StringTokenizer st = new StringTokenizer(getParametersString(), PARAM_DELIM);
1✔
272
        while (st.hasMoreTokens()) {
1✔
273
            stripOneParameter(st.nextToken());
1✔
274
        }
275
    }
1✔
276

277
    /**
278
     * submit the given event for the given request.
279
     *
280
     * @param event
281
     *            the event
282
     * @param request
283
     *            the request
284
     *
285
     * @return the response for the submitted Request
286
     *
287
     * @throws IOException
288
     *             Signals that an I/O exception has occurred.
289
     * @throws SAXException
290
     *             the SAX exception
291
     */
292
    protected WebResponse submitRequest(String event, final WebRequest request) throws IOException, SAXException {
293
        WebResponse response = null;
1✔
294
        if (doEventScript(event)) {
1✔
295
            response = submitRequest(request);
1✔
296
        }
297
        if (response == null) {
1✔
298
            response = getCurrentFrameContents();
1✔
299
        }
300
        return response;
1✔
301
    }
302

303
    /**
304
     * handle the event that has the given script attached by compiling the eventScript as a function and executing it
305
     *
306
     * @param eventScript
307
     *            - the script to use
308
     *
309
     * @deprecated since 1.7 - use doEventScript instead
310
     */
311
    @Deprecated
312
    @Override
313
    public boolean doEvent(String eventScript) {
314
        return doEventScript(eventScript);
×
315
    }
316

317
    /**
318
     * optional do the event if it's defined
319
     *
320
     * @param eventScript
321
     *            - the script to handle
322
     *
323
     * @return whether the script was handled
324
     */
325
    @Override
326
    public boolean doEventScript(String eventScript) {
327
        return this.getScriptingHandler().doEventScript(eventScript);
1✔
328
    }
329

330
    @Override
331
    public boolean handleEvent(String eventName) {
332
        return this.getScriptingHandler().handleEvent(eventName);
1✔
333
    }
334

335
    /**
336
     * Gets the current frame contents.
337
     *
338
     * @return the current frame contents
339
     */
340
    protected WebResponse getCurrentFrameContents() {
341
        return getCurrentFrame(getBaseResponse().getWindow(), _frame);
1✔
342
    }
343

344
    /**
345
     * Gets the current frame.
346
     *
347
     * @param window
348
     *            the window
349
     * @param pageFrame
350
     *            the page frame
351
     *
352
     * @return the current frame
353
     */
354
    private WebResponse getCurrentFrame(WebWindow window, FrameSelector pageFrame) {
355
        return window.hasFrame(pageFrame) ? window.getFrameContents(pageFrame) : window.getCurrentPage();
1✔
356
    }
357

358
    /**
359
     * Submits a request to the web client from which this request source was originally obtained.
360
     *
361
     * @param request
362
     *            the request
363
     *
364
     * @return the web response
365
     *
366
     * @throws IOException
367
     *             Signals that an I/O exception has occurred.
368
     * @throws SAXException
369
     *             the SAX exception
370
     */
371
    protected final WebResponse submitRequest(WebRequest request) throws IOException, SAXException {
372
        return getDestination().equals("#") ? _baseResponse : _baseResponse.getWindow().sendRequest(request);
1!
373
    }
374

375
    /**
376
     * Returns the web response containing this request source.
377
     *
378
     * @return the base response
379
     */
380
    protected final WebResponse getBaseResponse() {
381
        return _baseResponse;
1✔
382
    }
383

384
    /**
385
     * Records a parameter defined by including it in the destination URL. The value can be null, if the parameter name
386
     * was not specified with an equals sign.
387
     *
388
     * @param name
389
     *            the name
390
     * @param value
391
     *            the value
392
     */
393
    abstract protected void addPresetParameter(String name, String value);
394

395
    /**
396
     * get the attribute value for the given name
397
     *
398
     * @param name
399
     *            - the name of the attribute to get
400
     */
401
    @Override
402
    public String getAttribute(final String name) {
403
        return NodeUtils.getNodeAttribute(_node, name);
1✔
404
    }
405

406
    /**
407
     * set the attribute with the given name to the given value
408
     *
409
     * @param name
410
     *            - the name of the attribute
411
     * @param value
412
     *            - the value to use
413
     */
414
    @Override
415
    public void setAttribute(final String name, final Object value) {
416
        NodeUtils.setNodeAttribute(getNode(), name, value == null ? null : value.toString());
×
417
    }
×
418

419
    /**
420
     * remove the given attribute
421
     *
422
     * @param name
423
     *            - the name of the attribute to remove
424
     */
425
    @Override
426
    public void removeAttribute(final String name) {
427
        NodeUtils.removeNodeAttribute(getNode(), name);
×
428
    }
×
429

430
    @Override
431
    public boolean isSupportedAttribute(String name) {
432
        return false;
1✔
433
    }
434

435
    @Override
436
    public Node getNode() {
437
        return _node;
1✔
438
    }
439

440
    /**
441
     * Returns the text value of this block.
442
     */
443
    @Override
444
    public String getText() {
445
        if (_node == null) {
1!
446
            return "";
×
447
        }
448
        if (_node.getNodeType() == Node.TEXT_NODE) {
1!
449
            return _node.getNodeValue().trim();
×
450
        }
451
        if (!_node.hasChildNodes()) {
1!
452
            return "";
×
453
        }
454
        return NodeUtils.asText(_node.getChildNodes()).trim();
1✔
455
    }
456

457
    @Override
458
    public String getTagName() {
459
        return _node.getNodeName();
×
460
    }
461

462
    /**
463
     * Gets the attribute.
464
     *
465
     * @param name
466
     *            the name
467
     * @param defaultValue
468
     *            the default value
469
     *
470
     * @return the attribute
471
     */
472
    String getAttribute(final String name, String defaultValue) {
473
        return NodeUtils.getNodeAttribute(_node, name, defaultValue);
1✔
474
    }
475

476
    // ----------------------------- private members
477
    // -----------------------------------------------
478

479
    /**
480
     * parameter Delimiter for URL parameters bug report [ 1052037 ] Semicolon not supported as URL param delimiter asks
481
     * for this to be extended to &;.
482
     *
483
     * @see http://www.w3.org/TR/html4/appendix/notes.html#h-B.2 section B2.2
484
     */
485
    private static final String PARAM_DELIM = "&";
486

487
    /** The web response containing this request source. * */
488
    private WebResponse _baseResponse;
489

490
    /**
491
     * The name of the frame in which the response containing this request source is rendered. *
492
     */
493
    private String _defaultTarget;
494

495
    /** The URL of the page containing this entity. * */
496
    private URL _baseURL;
497

498
    /** The DOM node representing this entity. * */
499
    private Node _node;
500

501
    /**
502
     * Gets the specified target.
503
     *
504
     * @return the specified target
505
     */
506
    private String getSpecifiedTarget() {
507
        return getAttribute("target");
1✔
508
    }
509

510
    /**
511
     * Sets the target attribute.
512
     *
513
     * @param value
514
     *            the new target attribute
515
     */
516
    protected void setTargetAttribute(String value) {
517
        ((Element) _node).setAttribute("target", value);
1✔
518
    }
1✔
519

520
    /**
521
     * Gets all parameters from a URL.
522
     *
523
     * @return the parameters string
524
     */
525
    private String getParametersString() {
526
        String url = HttpUnitUtils.trimFragment(getDestination());
1✔
527
        if (url.trim().isEmpty()) {
1✔
528
            url = getBaseURL().toExternalForm();
1✔
529
        }
530
        if (HttpUnitUtils.isJavaScriptURL(url)) {
1!
531
            return "";
×
532
        }
533
        final int questionMarkIndex = url.indexOf("?");
1✔
534
        if (questionMarkIndex >= 1 && questionMarkIndex < url.length() - 1) {
1!
535
            return url.substring(questionMarkIndex + 1);
1✔
536
        }
537
        return "";
1✔
538
    }
539

540
    /**
541
     * Extracts a parameter of the form <name>[=[<value>]].
542
     *
543
     * @param param
544
     *            the param
545
     */
546
    private void stripOneParameter(String param) {
547
        final int index = param.indexOf("=");
1✔
548
        String value = index < 0 ? null
1✔
549
                : index == param.length() - 1 ? getEmptyParameterValue() : decode(param.substring(index + 1));
1✔
550
        String name = index < 0 ? decode(param) : decode(param.substring(0, index));
1✔
551
        addPresetParameter(name, value);
1✔
552
    }
1✔
553

554
    /**
555
     * Decode.
556
     *
557
     * @param string
558
     *            the string
559
     *
560
     * @return the string
561
     */
562
    private String decode(String string) {
563
        return HttpUnitUtils.decode(string, _baseResponse.getCharacterSet()).trim();
1✔
564
    }
565

566
    /**
567
     * Gets the empty parameter value.
568
     *
569
     * @return the empty parameter value
570
     */
571
    abstract protected String getEmptyParameterValue();
572

573
    /**
574
     * Returns the scriptable delegate.
575
     */
576
    @Override
577
    public ScriptingHandler getScriptingHandler() {
578
        if (_scriptable == null) {
1✔
579
            _scriptable = HttpUnitOptions.getScriptingEngine().createHandler(this);
1✔
580
        }
581
        return _scriptable;
1✔
582
    }
583

584
    @Override
585
    public ScriptableDelegate getParentDelegate() {
586
        return getBaseResponse().getDocumentScriptable();
1✔
587
    }
588

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