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

hazendaz / httpunit / 636

05 Dec 2025 03:27AM UTC coverage: 80.509%. Remained the same
636

push

github

hazendaz
Cleanup more old since tags

you guessed it, at this point going to jautodoc the rest so the warnings on builds go away ;)

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8249 of 10132 relevant lines covered (81.42%)

0.81 hits per line

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

86.65
/src/main/java/com/meterware/httpunit/FormControl.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.controls.SelectionFormControl;
23
import com.meterware.httpunit.dom.HTMLControl;
24
import com.meterware.httpunit.dom.HTMLInputElementImpl;
25
import com.meterware.httpunit.dom.HTMLSelectElementImpl;
26
import com.meterware.httpunit.dom.HTMLTextAreaElementImpl;
27
import com.meterware.httpunit.protocol.ParameterProcessor;
28
import com.meterware.httpunit.protocol.UploadFileSpec;
29
import com.meterware.httpunit.scripting.Input;
30
import com.meterware.httpunit.scripting.ScriptableDelegate;
31

32
import java.io.IOException;
33
import java.util.Iterator;
34
import java.util.List;
35
import java.util.Set;
36

37
import org.w3c.dom.Node;
38
import org.xml.sax.SAXException;
39

40
/**
41
 * Represents a control in an HTML form.
42
 **/
43
public abstract class FormControl extends HTMLElementBase {
44

45
    static final String[] NO_VALUE = {};
1✔
46

47
    private final WebForm _form;
48
    private HTMLControl _control;
49

50
    public static final String UNDEFINED_TYPE = "undefined";
51
    public static final String BUTTON_TYPE = "button";
52
    public static final String RESET_BUTTON_TYPE = "reset";
53
    public static final String SUBMIT_BUTTON_TYPE = "submit";
54
    public static final String IMAGE_BUTTON_TYPE = "image";
55
    public static final String RADIO_BUTTON_TYPE = "radio";
56
    public static final String CHECKBOX_TYPE = "checkbox";
57
    public static final String TEXT_TYPE = "text";
58
    public static final String PASSWORD_TYPE = "password";
59
    public static final String HIDDEN_TYPE = "hidden";
60
    public static final String TEXTAREA_TYPE = "textarea";
61
    public static final String FILE_TYPE = "file";
62
    public static final String SINGLE_TYPE = "select-one";
63
    public static final String MULTIPLE_TYPE = "select-multiple";
64

65
    /**
66
     * Return the type of the control, as seen from JavaScript.
67
     */
68
    public abstract String getType();
69

70
    static ScriptableDelegate newSelectionOption() {
71
        return new SelectionFormControl.Option();
1✔
72
    }
73

74
    FormControl(WebForm form) {
75
        this(form, newEmptyControlElement(form));
1✔
76
    }
1✔
77

78
    private static HTMLControl newEmptyControlElement(WebForm form) {
79
        return (HTMLControl) form.getElement().getOwnerDocument().createElement("input");
1✔
80
    }
81

82
    /**
83
     * initialize the given form control from a Webform and a HTMLControl
84
     *
85
     * @param form
86
     * @param control
87
     */
88
    protected FormControl(WebForm form, HTMLControl control) {
89
        super(control);
1✔
90
        _control = control;
1✔
91
        _form = form;
1✔
92
        supportAttribute("tabindex");
1✔
93
        supportAttribute("disabled");
1✔
94
        // Add all custom attributes
95
        Set customAttributes = HttpUnitOptions.getCustomAttributes();
1✔
96
        if (customAttributes != null) {
1✔
97
            for (Iterator iter = customAttributes.iterator(); iter.hasNext();) {
1✔
98
                supportAttribute((String) iter.next());
1✔
99
            }
100
        }
101
    }
1✔
102

103
    /**
104
     * Returns the current value(s) associated with this control. These values will be transmitted to the server if the
105
     * control is 'successful'.
106
     **/
107
    protected abstract String[] getValues();
108

109
    /**
110
     * Returns either a single delegate object or potentially an array of delegates as needed, given the form control.
111
     * This default implementation returns the scriptable delegate for the control.
112
     */
113
    Object getDelegate() {
114
        return getScriptingHandler();
1✔
115
    }
116

117
    protected final WebForm getForm() {
118
        return _form;
1✔
119
    }
120

121
    @Override
122
    public ScriptableDelegate getParentDelegate() {
123
        return (ScriptableDelegate) getForm().getScriptingHandler();
1✔
124
    }
125

126
    /**
127
     * Returns the values permitted in this control. Does not apply to text or file controls.
128
     **/
129
    public String[] getOptionValues() {
130
        return NO_VALUE;
×
131
    }
132

133
    /**
134
     * Returns the list of values displayed by this control, if any.
135
     **/
136
    protected String[] getDisplayedOptions() {
137
        return NO_VALUE;
×
138
    }
139

140
    /**
141
     * Returns true if this control is read-only.
142
     **/
143
    protected boolean isReadOnly() {
144
        return isDisabled() || _control.getReadOnly();
1✔
145
    }
146

147
    /**
148
     * Returns true if this control is hidden.
149
     **/
150
    public boolean isHidden() {
151
        return false;
1✔
152
    }
153

154
    void setDisabled(boolean disabled) {
155
        _control.setDisabled(disabled);
1✔
156
    }
1✔
157

158
    /**
159
     * Returns true if this control is disabled, meaning that it will not send a value to the server as part of a
160
     * request.
161
     **/
162
    public boolean isDisabled() {
163
        return _control.getDisabled();
1✔
164
    }
165

166
    /**
167
     * Returns true if this control accepts free-form text.
168
     **/
169
    boolean isTextControl() {
170
        return false;
×
171
    }
172

173
    /**
174
     * Returns true if only one control of this kind with this name can have a value. This is true for radio buttons.
175
     **/
176
    boolean isExclusive() {
177
        return false;
1✔
178
    }
179

180
    /**
181
     * Returns true if a single control can have multiple values.
182
     **/
183
    protected boolean isMultiValued() {
184
        return false;
×
185
    }
186

187
    /**
188
     * Returns true if this control accepts a file for upload.
189
     **/
190
    boolean isFileParameter() {
191
        return false;
1✔
192
    }
193

194
    protected abstract void addValues(ParameterProcessor processor, String characterSet) throws IOException;
195

196
    /**
197
     * Remove any required values for this control from the list, throwing an exception if they are missing.
198
     **/
199
    void claimRequiredValues(List values) {
200
    }
1✔
201

202
    /**
203
     * Sets this control to the next compatible value from the list, removing it from the list.
204
     **/
205
    void claimValue(List values) {
206
    }
1✔
207

208
    /**
209
     * Sets this control to the next compatible value from the list, removing it from the list.
210
     **/
211
    protected void claimUniqueValue(List values) {
212
    }
1✔
213

214
    /**
215
     * Specifies a file to be uploaded via this control.
216
     **/
217
    void claimUploadSpecification(List files) {
218
    }
×
219

220
    /**
221
     * Resets this control to its initial value.
222
     **/
223
    protected void reset() {
224
        _control.reset();
1✔
225
    }
1✔
226

227
    /**
228
     * Toggles the value of this control.
229
     */
230
    public void toggle() {
231
        throw new FormParameter.IllegalCheckboxParameterException(getName(), "toggleCheckbox");
1✔
232
    }
233

234
    /**
235
     * Sets the state of this boolean control.
236
     */
237
    public void setState(boolean state) {
238
        throw new FormParameter.IllegalCheckboxParameterException(getName(), "setCheckbox");
×
239
    }
240

241
    /**
242
     * Performs the 'onChange' event defined for this control.
243
     *
244
     * @deprecated since 1.7 use doOnChangeEvent instead
245
     */
246
    @Deprecated
247
    protected void sendOnChangeEvent() {
248
        doOnChangeEvent();
1✔
249
    }
1✔
250

251
    /**
252
     * Performs the 'onchange' event defined for this control.
253
     */
254
    protected boolean doOnChangeEvent() {
255
        return handleEvent("onchange");
1✔
256
    }
257

258
    /**
259
     * Performs the 'onClick' event defined for this control.
260
     *
261
     * @deprecated since 1.7 use doOnClickEvent instead
262
     */
263
    @Deprecated
264
    protected void sendOnClickEvent() {
265
        doOnClickEvent();
1✔
266
    }
1✔
267

268
    /**
269
     * Performs the 'onClick' event defined for this control.
270
     */
271
    protected boolean doOnClickEvent() {
272
        return handleEvent("onclick");
1✔
273
    }
274

275
    /**
276
     * Performs the 'onMouseUp' event defined for this control.
277
     *
278
     * @deprecated since 1.7 use doOnMouseUpEvent instead
279
     */
280
    @Deprecated
281
    protected void sendOnMouseUpEvent() {
282
        doOnMouseUpEvent();
×
283
    }
×
284

285
    /**
286
     * Performs the 'onMouseUp' event defined for this control.
287
     */
288
    protected boolean doOnMouseUpEvent() {
289
        return handleEvent("onmouseup");
×
290
    }
291

292
    /**
293
     * Performs the 'onMouseDown' event defined for this control.
294
     *
295
     * @deprecated since 1.7 use doOnMouseDownEvent instead
296
     */
297
    @Deprecated
298
    protected void sendOnMouseDownEvent() {
299
        doOnMouseDownEvent();
×
300
    }
×
301

302
    /**
303
     * Performs the 'onMouseDown' event defined for this control.
304
     */
305
    protected boolean doOnMouseDownEvent() {
306
        return handleEvent("onmousedown");
×
307
    }
308

309
    /**
310
     * Creates and returns a scriptable object for this control. Subclasses should override this if they use a different
311
     * implementation of Scriptable.
312
     */
313
    @Override
314
    public ScriptableDelegate newScriptable() {
315
        return new Scriptable();
×
316
    }
317

318
    /**
319
     * Returns the value of this control in the form. If no value is specified, defaults to the empty string.
320
     **/
321
    protected String getValueAttribute() {
322
        return "";
×
323
    }
324

325
    /**
326
     * Sets the value of this control in the form.
327
     */
328
    protected void setValueAttribute(String value) {
329
    }
×
330

331
    /**
332
     * Removes the specified required value from the list of values, throwing an exception if it is missing.
333
     **/
334
    protected final void claimValueIsRequired(List values, final String value) {
335
        if (!values.contains(value)) {
1✔
336
            throw new MissingParameterValueException(getName(), value,
1✔
337
                    (String[]) values.toArray(new String[values.size()]));
1✔
338
        }
339
        values.remove(value);
1✔
340
    }
1✔
341

342
    static String[] getControlElementTags() {
343
        return new String[] { "textarea", "select", "button", "input" };
1✔
344
    }
345

346
    /**
347
     * return the FormControl for the given parameter node in a form
348
     *
349
     * @param form
350
     *            - the form in which the parameter is defined
351
     * @param node
352
     *            - the node in which the parameter is defined
353
     *
354
     * @return the form control
355
     */
356
    static FormControl newFormParameter(WebForm form, Node node) {
357
        if (node.getNodeType() != Node.ELEMENT_NODE) {
1!
358
            return null;
×
359
        }
360
        if (node.getNodeName().equalsIgnoreCase("textarea")) {
1✔
361
            return new TextAreaFormControl(form, (HTMLTextAreaElementImpl) node);
1✔
362
        }
363
        if (node.getNodeName().equalsIgnoreCase("select")) {
1✔
364
            return new SelectionFormControl(form, (HTMLSelectElementImpl) node);
1✔
365
        }
366
        if (node.getNodeName().equalsIgnoreCase("button")) {
1✔
367
            HTMLControl control = (HTMLControl) node;
1✔
368
            final String type = control.getType();
1✔
369
            if (type.equalsIgnoreCase(SUBMIT_BUTTON_TYPE)) {
1✔
370
                return new SubmitButton(form, control);
1✔
371
            }
372
            if (type.equalsIgnoreCase(RESET_BUTTON_TYPE)) {
1✔
373
                return new ResetButton(form, control);
1✔
374
            }
375
            return new Button(form, control);
1✔
376
        }
377
        if (!node.getNodeName().equalsIgnoreCase("input")) {
1!
378
            return null;
×
379
        }
380
        HTMLInputElementImpl element = (HTMLInputElementImpl) node;
1✔
381
        final String type = element.getType();
1✔
382
        if (type.equalsIgnoreCase(TEXT_TYPE)) {
1✔
383
            return new TextFieldFormControl(form, element);
1✔
384
        }
385
        if (type.equalsIgnoreCase(PASSWORD_TYPE)) {
1✔
386
            return new PasswordFieldFormControl(form, element);
1✔
387
        }
388
        if (type.equalsIgnoreCase(HIDDEN_TYPE)) {
1✔
389
            return new HiddenFieldFormControl(form, element);
1✔
390
        }
391
        if (type.equalsIgnoreCase(RADIO_BUTTON_TYPE)) {
1✔
392
            return new RadioButtonFormControl(form, element);
1✔
393
        }
394
        if (type.equalsIgnoreCase(CHECKBOX_TYPE)) {
1✔
395
            return new CheckboxFormControl(form, element);
1✔
396
        }
397
        if (type.equalsIgnoreCase(SUBMIT_BUTTON_TYPE) || type.equalsIgnoreCase(IMAGE_BUTTON_TYPE)) {
1✔
398
            return new SubmitButton(form, element);
1✔
399
        }
400
        if (type.equalsIgnoreCase(BUTTON_TYPE)) {
1✔
401
            return new Button(form, (HTMLControl) node);
1✔
402
        }
403
        if (type.equalsIgnoreCase(RESET_BUTTON_TYPE)) {
1✔
404
            return new ResetButton(form, (HTMLControl) node);
1✔
405
        }
406
        if (type.equalsIgnoreCase(FILE_TYPE)) {
1✔
407
            return new FileSubmitFormControl(form, element);
1✔
408
        }
409
        return new TextFieldFormControl(form, element);
1✔
410
    }
411

412
    protected String emptyIfNull(String value) {
413
        return value == null ? "" : value;
1✔
414
    }
415

416
    /**
417
     * implementation of Scriptable input elements
418
     */
419
    public class Scriptable extends HTMLElementScriptable implements Input {
420

421
        /**
422
         * get my Name
423
         *
424
         * @return the name of this scriptable
425
         */
426
        @Override
427
        public String getName() {
428
            return FormControl.this.getName();
1✔
429
        }
430

431
        /**
432
         * get my ID
433
         *
434
         * @return the id of this scriptable
435
         */
436
        @Override
437
        public String getID() {
438
            return FormControl.this.getID();
1✔
439
        }
440

441
        /**
442
         * construct a Scriptable
443
         */
444
        public Scriptable() {
1✔
445
            super(FormControl.this);
1✔
446
        }
1✔
447

448
        /**
449
         * get the given property
450
         *
451
         * @param propertyName
452
         *            - the name of the property to get
453
         */
454
        @Override
455
        public Object get(String propertyName) {
456
            if (propertyName.equalsIgnoreCase("name")) {
1✔
457
                return FormControl.this.getName();
1✔
458
            }
459
            if (propertyName.equalsIgnoreCase("type")) {
1✔
460
                return FormControl.this.getType();
1✔
461
            }
462
            return super.get(propertyName);
1✔
463
        }
464

465
        /**
466
         * set the given property to the given value
467
         *
468
         * @param propertyName
469
         *            - the property to set
470
         * @param value
471
         *            - the value to use
472
         */
473
        @Override
474
        public void set(String propertyName, Object value) {
475
            if (propertyName.equalsIgnoreCase("value")) {
1✔
476
                setValueAttribute(value.toString());
1✔
477
            } else if (propertyName.equalsIgnoreCase("disabled")) {
1!
478
                setDisabled(value instanceof Boolean && ((Boolean) value).booleanValue());
1!
479
            } else {
480
                super.set(propertyName, value);
×
481
            }
482
        }
1✔
483

484
        /**
485
         * set the given attribute to the given value
486
         *
487
         * @param attributeName
488
         *            - the name of the attribute to set
489
         * @param value
490
         *            - the value to use
491
         */
492
        @Override
493
        public void setAttribute(String attributeName, Object value) {
494
            // Value set by JavaScript, make sure attribute is supported
495
            supportAttribute(attributeName);
1✔
496
            super.setAttribute(attributeName, value);
1✔
497
        }
1✔
498

499
        /**
500
         * allow calling click for this control
501
         */
502
        @Override
503
        public void click() throws IOException, SAXException {
504
            // TODO check whether the empty body of this method was correct
505
            // call onclick event handler
506
            HTMLElement element = this.get_element();
×
507
            if (element instanceof FormControl) {
×
508
                FormControl control = (FormControl) element;
×
509
                control.sendOnClickEvent();
×
510
            }
511
        }
×
512

513
        /**
514
         * simulate blur
515
         */
516
        public void blur() {
517
            handleEvent("onblur");
×
518
        }
×
519

520
        /**
521
         * simulate focus;
522
         */
523
        public void focus() {
524
            handleEvent("onfocus");
×
525
        }
×
526

527
        /**
528
         * allow firing a sendOnChangeEvent
529
         */
530
        @Override
531
        public void sendOnChangeEvent() {
532
            // TODO check why the test for this does not work although
533
            // the javascript function call is done in the corresponding testcase
534
            // testCallOnChange()
535
            HTMLElement element = this.get_element();
1✔
536
            if (element instanceof FormControl) {
1!
537
                FormControl control = (FormControl) element;
1✔
538
                control.sendOnChangeEvent();
1✔
539
            }
540
        }
1✔
541

542
    }
543

544
}
545

546
abstract class BooleanFormControl extends FormControl {
547

548
    private String[] _displayedValue;
549

550
    private HTMLInputElementImpl _element;
551

552
    @Override
553
    public ScriptableDelegate newScriptable() {
554
        return new Scriptable();
1✔
555
    }
556

557
    class Scriptable extends FormControl.Scriptable {
1✔
558

559
        @Override
560
        public Object get(String propertyName) {
561
            if (propertyName.equalsIgnoreCase("value")) {
1✔
562
                return getQueryValue();
1✔
563
            }
564
            if (propertyName.equalsIgnoreCase("checked")) {
1✔
565
                return isChecked() ? Boolean.TRUE : Boolean.FALSE;
1✔
566
            }
567
            if (propertyName.equalsIgnoreCase("defaultchecked")) {
1✔
568
                return _element.getDefaultChecked() ? Boolean.TRUE : Boolean.FALSE;
1✔
569
            }
570
            return super.get(propertyName);
1✔
571
        }
572

573
        @Override
574
        public void set(String propertyName, Object value) {
575
            if (propertyName.equalsIgnoreCase("checked")) {
1✔
576
                setChecked(value instanceof Boolean && ((Boolean) value).booleanValue());
1!
577
            } else {
578
                super.set(propertyName, value);
1✔
579
            }
580
        }
1✔
581
    }
582

583
    public BooleanFormControl(WebForm form, HTMLInputElementImpl element) {
584
        super(form, element);
1✔
585
        _element = element;
1✔
586
        _displayedValue = new String[] { readDisplayedValue(element) };
1✔
587
    }
1✔
588

589
    private String readDisplayedValue(Node node) {
590
        Node nextSibling = node.getNextSibling();
1✔
591
        while (nextSibling != null && nextSibling.getNodeType() != Node.TEXT_NODE
1✔
592
                && nextSibling.getNodeType() != Node.ELEMENT_NODE) {
1!
593
            nextSibling = nextSibling.getNextSibling();
×
594
        }
595
        if (nextSibling == null || nextSibling.getNodeType() != Node.TEXT_NODE) {
1✔
596
            return "";
1✔
597
        }
598
        return nextSibling.getNodeValue();
1✔
599
    }
600

601
    boolean isChecked() {
602
        return _element.getChecked();
1✔
603
    }
604

605
    @Override
606
    protected String getValueAttribute() {
607
        return emptyIfNull(_element.getValue());
1✔
608
    }
609

610
    @Override
611
    protected void setValueAttribute(String value) {
612
        _element.setValue(value);
1✔
613
    }
1✔
614

615
    public void setChecked(boolean checked) {
616
        _element.setChecked(checked);
1✔
617
    }
1✔
618

619
    /**
620
     * Returns the current value(s) associated with this control. These values will be transmitted to the server if the
621
     * control is 'successful'.
622
     **/
623
    @Override
624
    public String[] getValues() {
625
        return isChecked() ? toArray(getQueryValue()) : NO_VALUE;
1✔
626
    }
627

628
    /**
629
     * Returns the values permitted in this control.
630
     **/
631
    @Override
632
    public String[] getOptionValues() {
633
        return isReadOnly() && !isChecked() ? NO_VALUE : toArray(getQueryValue());
1✔
634
    }
635

636
    @Override
637
    protected String[] getDisplayedOptions() {
638
        return _displayedValue;
1✔
639
    }
640

641
    @Override
642
    protected void addValues(ParameterProcessor processor, String characterSet) throws IOException {
643
        if (isChecked() && !isDisabled()) {
1✔
644
            processor.addParameter(getName(), getQueryValue(), characterSet);
1✔
645
        }
646
    }
1✔
647

648
    /**
649
     * Remove any required values for this control from the list, throwing an exception if they are missing.
650
     **/
651
    @Override
652
    void claimRequiredValues(List values) {
653
        if (isValueRequired()) {
1✔
654
            claimValueIsRequired(values, getQueryValue());
1✔
655
        }
656
    }
1✔
657

658
    protected boolean isValueRequired() {
659
        return isReadOnly() && isChecked();
1✔
660
    }
661

662
    abstract String getQueryValue();
663

664
    private String[] toArray(String value) {
665
        return new String[] { value };
1✔
666
    }
667
}
668

669
class CheckboxFormControl extends BooleanFormControl {
670

671
    @Override
672
    public String getType() {
673
        return CHECKBOX_TYPE;
1✔
674
    }
675

676
    public CheckboxFormControl(WebForm form, HTMLInputElementImpl element) {
677
        super(form, element);
1✔
678
    }
1✔
679

680
    @Override
681
    protected void claimUniqueValue(List values) {
682
        if (isValueRequired()) {
1✔
683
            return;
1✔
684
        }
685
        setState(values.contains(getQueryValue()));
1✔
686
        if (isChecked()) {
1✔
687
            values.remove(getQueryValue());
1✔
688
        }
689
    }
1✔
690

691
    @Override
692
    String getQueryValue() {
693
        final String value = getValueAttribute();
1✔
694
        return value.isEmpty() ? "on" : value;
1✔
695
    }
696

697
    /**
698
     * Toggles the value of this control.
699
     */
700
    @Override
701
    public void toggle() {
702
        setState(!isChecked());
1!
703
    }
1✔
704

705
    /**
706
     * Sets the state of this boolean control. Triggers the 'onclick' event if the state has changed.
707
     */
708
    @Override
709
    public void setState(boolean state) {
710
        boolean wasChecked = isChecked();
1✔
711
        setChecked(state);
1✔
712
        if (isChecked() != wasChecked) {
1✔
713
            sendOnClickEvent();
1✔
714
        }
715
    }
1✔
716
}
717

718
abstract class TextFormControl extends FormControl {
719

720
    public TextFormControl(WebForm form, HTMLControl control) {
721
        super(form, control);
1✔
722
    }
1✔
723

724
    /**
725
     * Returns the current value(s) associated with this control. These values will be transmitted to the server if the
726
     * control is 'successful'.
727
     **/
728
    @Override
729
    public String[] getValues() {
730
        return new String[] { getValue() };
1✔
731
    }
732

733
    abstract protected String getDefaultValue();
734

735
    abstract protected String getValue();
736

737
    abstract protected void setValue(String value);
738

739
    /**
740
     * Returns true to indicate that this control accepts free-form text.
741
     **/
742
    @Override
743
    public boolean isTextControl() {
744
        return true;
1✔
745
    }
746

747
    @Override
748
    public ScriptableDelegate newScriptable() {
749
        return new Scriptable();
1✔
750
    }
751

752
    @Override
753
    protected void addValues(ParameterProcessor processor, String characterSet) throws IOException {
754
        if (!isDisabled() && getName().length() > 0) {
1✔
755
            processor.addParameter(getName(), getValues()[0], characterSet);
1✔
756
        }
757
    }
1✔
758

759
    /**
760
     * claim values and fire onChange Event if a change occured
761
     *
762
     * @param values
763
     *            - the list of values
764
     */
765
    @Override
766
    void claimValue(List values) {
767
        if (isReadOnly()) {
1✔
768
            return;
1✔
769
        }
770

771
        String oldValue = getValue();
1✔
772
        if (values.isEmpty()) {
1✔
773
            setValue("");
1✔
774
        } else {
775
            setValue((String) values.get(0));
1✔
776
            values.remove(0);
1✔
777
        }
778
        boolean same = oldValue == null && getValue() == null;
1!
779
        if (oldValue != null) {
1!
780
            same = oldValue.equals(getValue());
1✔
781
        }
782
        if (!same) {
1✔
783
            sendOnChangeEvent();
1✔
784
        }
785
    }
1✔
786

787
    @Override
788
    void claimRequiredValues(List values) {
789
        if (isReadOnly()) {
1✔
790
            claimValueIsRequired(values);
1✔
791
        }
792
    }
1✔
793

794
    protected void claimValueIsRequired(List values) {
795
        claimValueIsRequired(values, getDefaultValue());
1✔
796
    }
1✔
797

798
    class Scriptable extends FormControl.Scriptable {
1✔
799

800
        @Override
801
        public Object get(String propertyName) {
802
            if (propertyName.equalsIgnoreCase("value")) {
1✔
803
                return getValue();
1✔
804
            }
805
            if (propertyName.equalsIgnoreCase("defaultValue")) {
1✔
806
                return getDefaultValue();
1✔
807
            }
808
            return super.get(propertyName);
1✔
809
        }
810

811
        @Override
812
        public void set(String propertyName, Object value) {
813
            if (!propertyName.equalsIgnoreCase("value")) {
1!
814
                super.set(propertyName, value);
×
815
            } else if (value instanceof Number) {
1✔
816
                setValue(HttpUnitUtils.trimmedValue((Number) value));
1✔
817
            } else {
818
                setValue(value == null ? null : value.toString());
1✔
819
            }
820
        }
1✔
821
    }
822
}
823

824
class TextFieldFormControl extends TextFormControl {
825

826
    private HTMLInputElementImpl _element;
827

828
    @Override
829
    public String getType() {
830
        return TEXT_TYPE;
1✔
831
    }
832

833
    public TextFieldFormControl(WebForm form, HTMLInputElementImpl element) {
834
        super(form, element);
1✔
835
        _element = element;
1✔
836
        supportAttribute("maxlength");
1✔
837
    }
1✔
838

839
    @Override
840
    protected String getDefaultValue() {
841
        return _element.getDefaultValue();
1✔
842
    }
843

844
    @Override
845
    protected String getValue() {
846
        return emptyIfNull(_element.getValue());
1✔
847
    }
848

849
    @Override
850
    protected void setValue(String value) {
851
        _element.setValue(value);
1✔
852
    }
1✔
853
}
854

855
class PasswordFieldFormControl extends TextFieldFormControl {
856

857
    @Override
858
    public String getType() {
859
        return PASSWORD_TYPE;
1✔
860
    }
861

862
    public PasswordFieldFormControl(WebForm form, HTMLInputElementImpl element) {
863
        super(form, element);
1✔
864
    }
1✔
865
}
866

867
/**
868
 * a hidden text field
869
 */
870
class HiddenFieldFormControl extends TextFieldFormControl {
871

872
    @Override
873
    public String getType() {
874
        return HIDDEN_TYPE;
1✔
875
    }
876

877
    public HiddenFieldFormControl(WebForm form, HTMLInputElementImpl element) {
878
        super(form, element);
1✔
879
    }
1✔
880

881
    @Override
882
    void claimRequiredValues(List values) {
883
        claimValueIsRequired(values);
1✔
884
    }
1✔
885

886
    @Override
887
    void claimValue(List values) {
888
    }
1✔
889

890
    @Override
891
    public boolean isHidden() {
892
        return true;
1✔
893
    }
894
}
895

896
class TextAreaFormControl extends TextFormControl {
897

898
    private HTMLTextAreaElementImpl _element;
899

900
    public TextAreaFormControl(WebForm form, HTMLTextAreaElementImpl element) {
901
        super(form, element);
1✔
902
        _element = element;
1✔
903
    }
1✔
904

905
    @Override
906
    public String getType() {
907
        return TEXTAREA_TYPE;
1✔
908
    }
909

910
    @Override
911
    protected String getDefaultValue() {
912
        return _element.getDefaultValue();
1✔
913
    }
914

915
    @Override
916
    protected String getValue() {
917
        return _element.getValue();
1✔
918
    }
919

920
    @Override
921
    protected void setValue(String value) {
922
        _element.setValue(value);
1✔
923
    }
1✔
924

925
}
926

927
/**
928
 * a control for File submit
929
 */
930
class FileSubmitFormControl extends FormControl {
931

932
    /**
933
     * accessor for the type
934
     *
935
     * @return the constant FILE_TYPE
936
     */
937
    @Override
938
    public String getType() {
939
        return FILE_TYPE;
1✔
940
    }
941

942
    private UploadFileSpec _fileToUpload;
943

944
    @Override
945
    public ScriptableDelegate newScriptable() {
946
        return new Scriptable();
1✔
947
    }
948

949
    class Scriptable extends FormControl.Scriptable {
1✔
950

951
        @Override
952
        public Object get(String propertyName) {
953
            if (propertyName.equalsIgnoreCase("value")) {
1✔
954
                return getSelectedName();
1✔
955
            }
956
            return super.get(propertyName);
1✔
957
        }
958

959
    }
960

961
    public FileSubmitFormControl(WebForm form, HTMLInputElementImpl node) {
962
        super(form, node);
1✔
963
    }
1✔
964

965
    /**
966
     * Returns true if this control accepts a file for upload.
967
     **/
968
    @Override
969
    public boolean isFileParameter() {
970
        return true;
1✔
971
    }
972

973
    /**
974
     * Returns the name of the selected file, if any.
975
     */
976
    @Override
977
    public String[] getValues() {
978
        return new String[] { getSelectedName() };
1✔
979
    }
980

981
    private String getSelectedName() {
982
        return _fileToUpload == null ? "" : _fileToUpload.getFileName();
1✔
983
    }
984

985
    /**
986
     * Specifies a number of file upload specifications for this control.
987
     **/
988
    @Override
989
    void claimUploadSpecification(List files) {
990
        if (files.isEmpty()) {
1✔
991
            _fileToUpload = null;
1✔
992
        } else {
993
            _fileToUpload = (UploadFileSpec) files.get(0);
1✔
994
            files.remove(0);
1✔
995
        }
996
    }
1✔
997

998
    @Override
999
    protected void addValues(ParameterProcessor processor, String characterSet) throws IOException {
1000
        if (!isDisabled() && _fileToUpload != null) {
1!
1001
            processor.addFile(getName(), _fileToUpload);
1✔
1002
        }
1003
    }
1✔
1004
}
1005

1006
// ============================= exception class MissingParameterValueException ======================================
1007

1008
/**
1009
 * This exception is thrown on an attempt to remove a required value from a form parameter.
1010
 **/
1011
class MissingParameterValueException extends IllegalRequestParameterException {
1012

1013
    private static final long serialVersionUID = 1L;
1014

1015
    MissingParameterValueException(String parameterName, String missingValue, String[] proposed) {
1✔
1016
        _parameterName = parameterName;
1✔
1017
        _missingValue = missingValue;
1✔
1018
        _proposedValues = proposed;
1✔
1019
    }
1✔
1020

1021
    @Override
1022
    public String getMessage() {
1023
        StringBuilder sb = new StringBuilder(HttpUnitUtils.DEFAULT_TEXT_BUFFER_SIZE);
×
1024
        sb.append("Parameter '").append(_parameterName).append("' must have the value '");
×
1025
        sb.append(_missingValue).append("'. Attempted to set it to: { ");
×
1026
        for (int i = 0; i < _proposedValues.length; i++) {
×
1027
            if (i != 0) {
×
1028
                sb.append(", ");
×
1029
            }
1030
            sb.append(_proposedValues[i]);
×
1031
        }
1032
        sb.append(" }");
×
1033
        return sb.toString();
×
1034
    }
1035

1036
    private String _parameterName;
1037
    private String _missingValue;
1038
    private String[] _proposedValues;
1039
}
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