• 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

91.45
/src/main/java/com/meterware/servletunit/RequestContext.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.servletunit;
9

10
import com.meterware.httpunit.HttpUnitOptions;
11
import com.meterware.httpunit.HttpUnitUtils;
12

13
import jakarta.servlet.http.HttpServletRequest;
14

15
import java.net.URL;
16
import java.nio.charset.StandardCharsets;
17
import java.util.Enumeration;
18
import java.util.Hashtable;
19
import java.util.Map;
20
import java.util.StringTokenizer;
21

22
/**
23
 * The Class RequestContext.
24
 */
25
class RequestContext {
26

27
    /** The parameters. */
28
    private Hashtable _parameters = new Hashtable<>();
1✔
29

30
    /** The visible parameters. */
31
    private Hashtable _visibleParameters;
32

33
    /** The parent request. */
34
    private HttpServletRequest _parentRequest;
35

36
    /** The url. */
37
    private URL _url;
38

39
    /** The message body. */
40
    private byte[] _messageBody;
41

42
    /** The message encoding. */
43
    private String _messageEncoding;
44

45
    /**
46
     * Instantiates a new request context.
47
     *
48
     * @param url
49
     *            the url
50
     */
51
    RequestContext(URL url) {
1✔
52
        _url = url;
1✔
53
        String file = _url.getFile();
1✔
54
        if (file.indexOf('?') >= 0) {
1✔
55
            loadParameters(file.substring(file.indexOf('?') + 1) /* urlEncoded */ );
1✔
56
        }
57
    }
1✔
58

59
    /**
60
     * Sets the parent request.
61
     *
62
     * @param parentRequest
63
     *            the new parent request
64
     */
65
    void setParentRequest(HttpServletRequest parentRequest) {
66
        _parentRequest = parentRequest;
1✔
67
        _visibleParameters = null;
1✔
68
    }
1✔
69

70
    /**
71
     * Gets the request URI.
72
     *
73
     * @return the request URI
74
     */
75
    String getRequestURI() {
76
        return _url.getPath();
1✔
77
    }
78

79
    /**
80
     * Gets the parameter.
81
     *
82
     * @param name
83
     *            the name
84
     *
85
     * @return the parameter
86
     */
87
    String getParameter(String name) {
88
        String[] parameters = (String[]) getParameters().get(name);
1✔
89
        return parameters == null ? null : parameters[0];
1!
90
    }
91

92
    /**
93
     * Gets the parameter names.
94
     *
95
     * @return the parameter names
96
     */
97
    Enumeration getParameterNames() {
98
        return getParameters().keys();
1✔
99
    }
100

101
    /**
102
     * Gets the parameter map.
103
     *
104
     * @return the parameter map
105
     */
106
    Map getParameterMap() {
107
        return (Map) getParameters().clone();
1✔
108
    }
109

110
    /**
111
     * Gets the parameter values.
112
     *
113
     * @param name
114
     *            the name
115
     *
116
     * @return the parameter values
117
     */
118
    String[] getParameterValues(String name) {
119
        return (String[]) getParameters().get(name);
1✔
120
    }
121

122
    /** The Constant STATE_INITIAL. */
123
    static final private int STATE_INITIAL = 0;
124

125
    /** The Constant STATE_HAVE_NAME. */
126
    static final private int STATE_HAVE_NAME = 1;
127

128
    /** The Constant STATE_HAVE_EQUALS. */
129
    static final private int STATE_HAVE_EQUALS = 2;
130

131
    /** The Constant STATE_HAVE_VALUE. */
132
    static final private int STATE_HAVE_VALUE = 3;
133

134
    /**
135
     * This method employs a state machine to parse a parameter query string. The transition rules are as follows: State
136
     * \ text '=' '&' initial: have_name - initial have_name: - have_equals initial have_equals: have_value - initial
137
     * have_value: - initial initial actions occur on the following transitions: initial -> have_name: save token as
138
     * name have_equals -> initial: record parameter with null value have_value -> initial: record parameter with value
139
     *
140
     * @param queryString
141
     *            the query string
142
     */
143
    void loadParameters(String queryString) {
144
        if (queryString.isEmpty()) {
1✔
145
            return;
1✔
146
        }
147
        StringTokenizer st = new StringTokenizer(queryString, "&=", /* return tokens */ true);
1✔
148
        int state = STATE_INITIAL;
1✔
149
        String name = null;
1✔
150
        String value = null;
1✔
151

152
        while (st.hasMoreTokens()) {
1✔
153
            String token = st.nextToken();
1✔
154
            if (token.equals("&")) {
1✔
155
                state = STATE_INITIAL;
1✔
156
                if (name != null && value != null) {
1!
157
                    addParameter(name, value);
1✔
158
                }
159
                name = value = null;
1✔
160
            } else if (token.equals("=")) {
1✔
161
                if (state == STATE_HAVE_NAME) {
1!
162
                    state = STATE_HAVE_EQUALS;
1✔
163
                } else if (state == STATE_HAVE_VALUE) {
×
164
                    state = STATE_INITIAL;
×
165
                }
166
            } else if (state == STATE_INITIAL) {
1✔
167
                name = HttpUnitUtils.decode(token, getMessageEncoding());
1✔
168
                value = "";
1✔
169
                state = STATE_HAVE_NAME;
1✔
170
            } else {
171
                value = HttpUnitUtils.decode(token, getMessageEncoding());
1✔
172
                state = STATE_HAVE_VALUE;
1✔
173
            }
174
        }
1✔
175
        if (name != null && value != null) {
1!
176
            addParameter(name, value);
1✔
177
        }
178
    }
1✔
179

180
    /**
181
     * Adds the parameter.
182
     *
183
     * @param name
184
     *            the name
185
     * @param encodedValue
186
     *            the encoded value
187
     */
188
    private void addParameter(String name, String encodedValue) {
189
        String[] values = (String[]) _parameters.get(name);
1✔
190
        _visibleParameters = null;
1✔
191
        if (values == null) {
1✔
192
            _parameters.put(name, new String[] { encodedValue });
1✔
193
        } else {
194
            _parameters.put(name, extendedArray(values, encodedValue));
1✔
195
        }
196
    }
1✔
197

198
    /**
199
     * Extended array.
200
     *
201
     * @param baseArray
202
     *            the base array
203
     * @param newValue
204
     *            the new value
205
     *
206
     * @return the string[]
207
     */
208
    private static String[] extendedArray(String[] baseArray, String newValue) {
209
        String[] result = new String[baseArray.length + 1];
1✔
210
        System.arraycopy(baseArray, 0, result, 0, baseArray.length);
1✔
211
        result[baseArray.length] = newValue;
1✔
212
        return result;
1✔
213
    }
214

215
    /**
216
     * Gets the parameters.
217
     *
218
     * @return the parameters
219
     */
220
    private Hashtable getParameters() {
221
        if (_messageBody != null) {
1✔
222
            loadParameters(getMessageBodyAsString());
1✔
223
            _messageBody = null;
1✔
224
        }
225
        if (_visibleParameters == null) {
1✔
226
            if (_parentRequest == null) {
1✔
227
                _visibleParameters = _parameters;
1✔
228
            } else {
229
                _visibleParameters = new Hashtable<>();
1✔
230
                final Map parameterMap = _parentRequest.getParameterMap();
1✔
231
                for (Object key : parameterMap.keySet()) {
1✔
232
                    _visibleParameters.put(key, parameterMap.get(key));
1✔
233
                }
1✔
234
                for (Enumeration e = _parameters.keys(); e.hasMoreElements();) {
1✔
235
                    Object key = e.nextElement();
1✔
236
                    _visibleParameters.put(key, _parameters.get(key));
1✔
237
                }
1✔
238
            }
239
        }
240
        return _visibleParameters;
1✔
241
    }
242

243
    /**
244
     * Gets the message body as string.
245
     *
246
     * @return the message body as string
247
     */
248
    private String getMessageBodyAsString() {
249
        return new String(_messageBody, StandardCharsets.UTF_8);
1✔
250
    }
251

252
    /**
253
     * Sets the message body.
254
     *
255
     * @param bytes
256
     *            the new message body
257
     */
258
    void setMessageBody(byte[] bytes) {
259
        _messageBody = bytes;
1✔
260
    }
1✔
261

262
    /**
263
     * Sets the message encoding.
264
     *
265
     * @param messageEncoding
266
     *            the new message encoding
267
     */
268
    public void setMessageEncoding(String messageEncoding) {
269
        _messageEncoding = messageEncoding;
1✔
270
    }
1✔
271

272
    /**
273
     * Gets the message encoding.
274
     *
275
     * @return the message encoding
276
     */
277
    private String getMessageEncoding() {
278
        return _messageEncoding == null ?
1✔
279
        /* Fixing 1705925: StandardCharsets.ISO_8859_1.name() */
280
                HttpUnitOptions.getDefaultCharacterSet() : _messageEncoding;
1✔
281
    }
282

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