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

hazendaz / httpunit / 646

06 Dec 2025 08:11PM UTC coverage: 80.526% (+0.02%) from 80.509%
646

push

github

hazendaz
Cleanup array usage

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

4 of 4 new or added lines in 3 files covered. (100.0%)

532 existing lines in 26 files now uncovered.

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

73.68
/src/main/java/com/meterware/servletunit/ServletUnitHttpResponse.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.servletunit;
21

22
import com.meterware.httpunit.HttpUnitUtils;
23

24
import jakarta.servlet.ServletOutputStream;
25
import jakarta.servlet.WriteListener;
26
import jakarta.servlet.http.Cookie;
27
import jakarta.servlet.http.HttpServletResponse;
28

29
import java.io.ByteArrayOutputStream;
30
import java.io.IOException;
31
import java.io.OutputStreamWriter;
32
import java.io.PrintWriter;
33
import java.nio.charset.Charset;
34
import java.nio.charset.StandardCharsets;
35
import java.text.SimpleDateFormat;
36
import java.util.ArrayList;
37
import java.util.Collection;
38
import java.util.Collections;
39
import java.util.Date;
40
import java.util.Enumeration;
41
import java.util.Hashtable;
42
import java.util.Iterator;
43
import java.util.List;
44
import java.util.Locale;
45
import java.util.Map;
46
import java.util.TimeZone;
47

48
/**
49
 * The Class ServletUnitHttpResponse.
50
 */
51
class ServletUnitHttpResponse implements HttpServletResponse {
1✔
52

53
    /** The Constant RFC1123_DATE_SPEC. */
54
    // rfc1123-date is "Sun, 06 Nov 1994 08:49:37 GMT"
55
    private static final String RFC1123_DATE_SPEC = "EEE, dd MMM yyyy HH:mm:ss z";
56

57
    /** The committed. */
58
    private boolean _committed;
59

60
    /** The locale. */
61
    private Locale _locale = Locale.getDefault();
1✔
62

63
    /** The Constant ENCODING_MAP. */
64
    private static final Hashtable ENCODING_MAP = new Hashtable<>();
1✔
65

66
    /**
67
     * Adds the specified cookie to the response. It can be called multiple times to set more than one cookie.
68
     */
69
    @Override
70
    public void addCookie(Cookie cookie) {
71
        _cookies.add(cookie);
1✔
72
    }
1✔
73

74
    /**
75
     * Checks whether the response message header has a field with the specified name.
76
     */
77
    @Override
78
    public boolean containsHeader(String name) {
79
        return _headers.containsKey(name.toUpperCase());
1✔
80
    }
81

82
    /**
83
     * Encodes the specified URL by including the session ID in it, or, if encoding is not needed, returns the URL
84
     * unchanged. The implementation of this method should include the logic to determine whether the session ID needs
85
     * to be encoded in the URL. For example, if the browser supports cookies, or session tracking is turned off, URL
86
     * encoding is unnecessary.
87
     **/
88
    @Override
89
    public String encodeURL(String url) {
UNCOV
90
        return url;
×
91
    }
92

93
    /**
94
     * Encodes the specified URL for use in the <code>sendRedirect</code> method or, if encoding is not needed, returns
95
     * the URL unchanged. The implementation of this method should include the logic to determine whether the session ID
96
     * needs to be encoded in the URL. Because the rules for making this determination differ from those used to decide
97
     * whether to encode a normal link, this method is seperate from the <code>encodeUrl</code> method.
98
     **/
99
    @Override
100
    public String encodeRedirectURL(String url) {
UNCOV
101
        return url;
×
102
    }
103

104
    /**
105
     * Sends a temporary redirect response to the client using the specified redirect location URL. The URL must be
106
     * absolute (for example, <code><em>https://hostname/path/file.html</em></code>). Relative URLs are not permitted
107
     * here.
108
     */
109
    @Override
110
    public void sendRedirect(String location) throws IOException {
111
        setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
1✔
112
        setHeader("Location", location);
1✔
113
    }
1✔
114

115
    /**
116
     * Sends an error response to the client using the specified status code and descriptive message. If setStatus has
117
     * previously been called, it is reset to the error status code. The message is sent as the body of an HTML page,
118
     * which is returned to the user to describe the problem. The page is sent with a default HTML header; the message
119
     * is enclosed in simple body tags (&lt;body&gt;&lt;/body&gt;).
120
     **/
121
    @Override
122
    public void sendError(int sc) throws IOException {
UNCOV
123
        sendError(sc, "");
×
124
    }
×
125

126
    /**
127
     * Sends an error response to the client using the specified status code and descriptive message. If setStatus has
128
     * previously been called, it is reset to the error status code. The message is sent as the body of an HTML page,
129
     * which is returned to the user to describe the problem. The page is sent with a default HTML header; the message
130
     * is enclosed in simple body tags (&lt;body&gt;&lt;/body&gt;).
131
     **/
132
    @Override
133
    public void sendError(int sc, String msg) throws IOException {
UNCOV
134
        setStatus(sc);
×
135
        _statusMessage = msg;
×
136

UNCOV
137
        _writer = null;
×
138
        _servletStream = null;
×
139

UNCOV
140
        setContentType("text/html");
×
141
        getWriter().println("<html><head><title>" + msg + "</title></head><body>" + msg + "</body></html>");
×
142
    }
×
143

144
    /**
145
     * Sets the status code for this response. This method is used to set the return status code when there is no error
146
     * (for example, for the status codes SC_OK or SC_MOVED_TEMPORARILY). If there is an error, the
147
     * <code>sendError</code> method should be used instead.
148
     **/
149
    @Override
150
    public void setStatus(int sc) {
151
        _status = sc;
1✔
152
    }
1✔
153

154
    /**
155
     * Adds a field to the response header with the given name and value. If the field had already been set, the new
156
     * value overwrites the previous one. The <code>containsHeader</code> method can be used to test for the presence of
157
     * a header before setting its value.
158
     **/
159
    @Override
160
    public void setHeader(String name, String value) {
161
        ArrayList values = new ArrayList<>();
1✔
162
        values.add(value);
1✔
163
        synchronized (_headers) {
1✔
164
            _headers.put(name.toUpperCase(), values);
1✔
165
        }
1✔
166
    }
1✔
167

168
    /**
169
     * Adds a field to the response header with the given name and integer value. If the field had already been set, the
170
     * new value overwrites the previous one. The <code>containsHeader</code> method can be used to test for the
171
     * presence of a header before setting its value.
172
     **/
173
    @Override
174
    public void setIntHeader(String name, int value) {
175
        setHeader(name, asHeaderValue(value));
1✔
176
    }
1✔
177

178
    /**
179
     * Adds a field to the response header with the given name and integer value. If the field had already been set, the
180
     * new value overwrites the previous one. The <code>containsHeader</code> method can be used to test for the
181
     * presence of a header before setting its value.
182
     *
183
     * @param name
184
     *            the name
185
     * @param value
186
     *            the value
187
     */
188
    public void setLongHeader(String name, long value) {
UNCOV
189
        setHeader(name, asHeaderLongValue(value));
×
190
    }
×
191

192
    /**
193
     * As header value.
194
     *
195
     * @param value
196
     *            the value
197
     *
198
     * @return the string
199
     */
200
    private String asHeaderValue(int value) {
201
        return Integer.toString(value);
1✔
202
    }
203

204
    /**
205
     * As header long value.
206
     *
207
     * @param value
208
     *            the value
209
     *
210
     * @return the string
211
     */
212
    private String asHeaderLongValue(long value) {
UNCOV
213
        return Long.toString(value);
×
214
    }
215

216
    /**
217
     * Adds a field to the response header with the given name and date-valued field. The date is specified in terms of
218
     * milliseconds since the epoch. If the date field had already been set, the new value overwrites the previous one.
219
     * The <code>containsHeader</code> method can be used to test for the presence of a header before setting its value.
220
     **/
221
    @Override
222
    public void setDateHeader(String name, long date) {
223
        setHeader(name, asDateHeaderValue(date));
1✔
224
    }
1✔
225

226
    /**
227
     * As date header value.
228
     *
229
     * @param date
230
     *            the date
231
     *
232
     * @return the string
233
     */
234
    private String asDateHeaderValue(long date) {
235
        Date value = new Date(date);
1✔
236
        SimpleDateFormat formatter = new SimpleDateFormat(RFC1123_DATE_SPEC, Locale.US);
1✔
237
        formatter.setTimeZone(TimeZone.getTimeZone("Greenwich Mean Time"));
1✔
238
        return formatter.format(value);
1✔
239
    }
240

241
    /**
242
     * Returns the name of the character set encoding used for the MIME body sent by this response.
243
     **/
244
    @Override
245
    public String getCharacterEncoding() {
246
        return _encoding == null ? StandardCharsets.ISO_8859_1.name() : _encoding;
1✔
247
    }
248

249
    /**
250
     * Sets the content type of the response the server sends to the client. The content type may include the type of
251
     * character encoding used, for example, <code>text/html; charset=ISO-8859-4</code>.
252
     * <p>
253
     * You can only use this method once, and you should call it before you obtain a <code>PrintWriter</code> or
254
     * {@link ServletOutputStream} object to return a response.
255
     **/
256
    @Override
257
    public void setContentType(String type) {
258
        String[] typeAndEncoding = HttpUnitUtils.parseContentTypeHeader(type);
1✔
259

260
        _contentType = typeAndEncoding[0];
1✔
261
        if (typeAndEncoding[1] != null) {
1✔
262
            _encoding = typeAndEncoding[1];
1✔
263
        }
264
    }
1✔
265

266
    /**
267
     * Returns a {@link ServletOutputStream} suitable for writing binary data in the response. The servlet engine does
268
     * not encode the binary data.
269
     *
270
     * @exception IllegalStateException
271
     *                if you have already called the <code>getWriter</code> method
272
     **/
273
    @Override
274
    public ServletOutputStream getOutputStream() throws IOException {
275
        if (_writer != null) {
1✔
276
            throw new IllegalStateException("Tried to create output stream; writer already exists");
1✔
277
        }
278
        if (_servletStream == null) {
1✔
279
            _outputStream = new ByteArrayOutputStream();
1✔
280
            _servletStream = new ServletUnitOutputStream(_outputStream);
1✔
281
        }
282
        return _servletStream;
1✔
283
    }
284

285
    /**
286
     * Returns a <code>PrintWriter</code> object that you can use to send character text to the client. The character
287
     * encoding used is the one specified in the <code>charset=</code> property of the {@link #setContentType} method,
288
     * which you must call <i>before</i> you call this method.
289
     * <p>
290
     * If necessary, the MIME type of the response is modified to reflect the character encoding used.
291
     * <p>
292
     * You cannot use this method if you have already called {@link #getOutputStream} for this
293
     * <code>ServletResponse</code> object.
294
     *
295
     * @exception IllegalStateException
296
     *                if the <code>getOutputStream</code> method has already been called for this response object; in
297
     *                that case, you can't use this method
298
     **/
299
    @Override
300
    public PrintWriter getWriter() {
301
        if (_servletStream != null) {
1✔
302
            throw new IllegalStateException("Tried to create writer; output stream already exists");
1✔
303
        }
304
        if (_writer == null) {
1✔
305
            _outputStream = new ByteArrayOutputStream();
1✔
306
            _writer = new PrintWriter(new OutputStreamWriter(_outputStream, Charset.forName(getCharacterEncoding())));
1✔
307
        }
308
        return _writer;
1✔
309
    }
310

311
    /**
312
     * Sets the length of the content the server returns to the client. In HTTP servlets, this method sets the HTTP
313
     * Content-Length header.
314
     **/
315
    @Override
316
    public void setContentLength(int len) {
317
        setIntHeader("Content-Length", len);
1✔
318
    }
1✔
319

320
    // ------------------------------- the following methods are new in JSDK 2.2 ----------------------
321

322
    /**
323
     * Adds a response header with the given name and value. This method allows response headers to have multiple
324
     * values.
325
     **/
326
    @Override
327
    public void addHeader(String name, String value) {
328
        synchronized (_headers) {
1✔
329
            String key = name.toUpperCase();
1✔
330
            List values = (ArrayList) _headers.get(key);
1✔
331
            if (values == null) {
1✔
332
                values = new ArrayList<>();
1✔
333
                _headers.put(key, values);
1✔
334
            }
335
            values.add(value);
1✔
336
        }
1✔
337
    }
1✔
338

339
    /**
340
     * Adds a response header with the given name and value. This method allows response headers to have multiple
341
     * values.
342
     **/
343
    @Override
344
    public void addIntHeader(String name, int value) {
345
        addHeader(name, asHeaderValue(value));
1✔
346
    }
1✔
347

348
    /**
349
     * Adds a response header with the given name and value. This method allows response headers to have multiple
350
     * values.
351
     **/
352
    @Override
353
    public void addDateHeader(String name, long value) {
354
        addHeader(name, asDateHeaderValue(value));
1✔
355
    }
1✔
356

357
    /**
358
     * Sets the preferred buffer size for the body of the response. The servlet container will use a buffer at least as
359
     * large as the size requested. The actual buffer size used can be found using getBufferSize.
360
     **/
361
    @Override
362
    public void setBufferSize(int size) {
363
        if (getContents().length != 0) {
1✔
364
            throw new IllegalStateException("May not set buffer size after data is written");
1✔
365
        }
366
    }
1✔
367

368
    /**
369
     * Returns the actual buffer size used for the response. If no buffering is used, this method returns 0.
370
     **/
371
    @Override
372
    public int getBufferSize() {
UNCOV
373
        return 0;
×
374
    }
375

376
    /**
377
     * Returns a boolean indicating if the response has been committed. A committed response has already had its status
378
     * code and headers written.
379
     **/
380
    @Override
381
    public boolean isCommitted() {
382
        return _committed;
1✔
383
    }
384

385
    /**
386
     * Forces any content in the buffer to be written to the client. A call to this method automatically commits the
387
     * response, meaning the status code and headers will be written.
388
     **/
389
    @Override
390
    public void flushBuffer() throws IOException {
391
        _committed = true;
1✔
392
    }
1✔
393

394
    /**
395
     * Clears any data that exists in the buffer as well as the status code and headers. If the response has been
396
     * committed, this method throws an IllegalStateException.
397
     **/
398
    @Override
399
    public void reset() {
400
        resetBuffer();
1✔
401
        _headers.clear();
1✔
402
        _headersComplete = false;
1✔
403
        _status = SC_OK;
1✔
404
    }
1✔
405

406
    /**
407
     * Sets the locale of the response, setting the headers (including the Content-Type's charset) as appropriate. This
408
     * method should be called before a call to getWriter(). By default, the response locale is the default locale for
409
     * the server.
410
     **/
411
    @Override
412
    public void setLocale(Locale locale) {
413
        _locale = locale;
1✔
414
        if (_encoding == null) {
1!
415
            for (Iterator it = ENCODING_MAP.entrySet().iterator(); it.hasNext();) {
1!
416
                Map.Entry entry = (Map.Entry) it.next();
1✔
417
                String locales = (String) entry.getValue();
1✔
418
                if (locales.indexOf(locale.getLanguage()) >= 0 || locales.indexOf(locale.toString()) >= 0) {
1!
419
                    _encoding = (String) entry.getKey();
1✔
420
                    return;
1✔
421
                }
422
            }
1✔
423
        }
UNCOV
424
    }
×
425

426
    /**
427
     * Returns the locale assigned to the response.
428
     **/
429
    @Override
430
    public Locale getLocale() {
431
        return _locale;
1✔
432
    }
433

434
    // ----------------------------- methods added to ServletResponse in JSDK 2.3 --------------------------------------
435

436
    /**
437
     * Clears the content of the underlying buffer in the response without clearing headers or status code. If the
438
     * response has been committed, this method throws an IllegalStateException.
439
     */
440
    @Override
441
    public void resetBuffer() {
442
        if (_committed) {
1✔
443
            throw new IllegalStateException("May not resetBuffer after response is committed");
1✔
444
        }
445
        _outputStream = null;
1✔
446
        _servletStream = null;
1✔
447
        _writer = null;
1✔
448
    }
1✔
449

450
    // ---------------------------------------------- package methods --------------------------------------------------
451

452
    /**
453
     * Returns the contents of this response.
454
     *
455
     * @return the contents
456
     */
457
    byte[] getContents() {
458
        if (_outputStream == null) {
1✔
459
            return new byte[0];
1✔
460
        }
461
        if (_writer != null) {
1✔
462
            _writer.flush();
1✔
463
        }
464
        return _outputStream.toByteArray();
1✔
465
    }
466

467
    /**
468
     * Returns the status of this response.
469
     **/
470
    @Override
471
    public int getStatus() {
472
        return _status;
1✔
473
    }
474

475
    /**
476
     * Returns the message associated with this response's status.
477
     *
478
     * @return the message
479
     */
480
    String getMessage() {
UNCOV
481
        return _statusMessage;
×
482
    }
483

484
    /**
485
     * Gets the header field names.
486
     *
487
     * @return the header field names
488
     */
489
    public String[] getHeaderFieldNames() {
UNCOV
490
        if (!_headersComplete) {
×
491
            completeHeaders();
×
492
        }
UNCOV
493
        List<String> names = new ArrayList<>();
×
494
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
×
495
            names.add((String) e.nextElement());
×
496
        }
UNCOV
497
        return names.toArray(new String[0]);
×
498
    }
499

500
    /**
501
     * Returns the headers defined for this response.
502
     *
503
     * @param name
504
     *            - the name of the field to get
505
     *
506
     * @return the header field direct
507
     */
508
    String getHeaderFieldDirect(String name) {
509
        ArrayList values;
510
        synchronized (_headers) {
1✔
511
            values = (ArrayList) _headers.get(name.toUpperCase());
1✔
512
        }
1✔
513

514
        return values == null ? null : (String) values.get(0);
1✔
515
    }
516

517
    /**
518
     * Returns the headers defined for this response.
519
     *
520
     * @param name
521
     *            the name
522
     *
523
     * @return the header field
524
     */
525
    String getHeaderField(String name) {
526
        if (!_headersComplete) {
1✔
527
            completeHeaders();
1✔
528
        }
529
        return getHeaderFieldDirect(name);
1✔
530
    }
531

532
    /**
533
     * Return an array of all the header values associated with the specified header name, or an zero-length array if
534
     * there are no such header values.
535
     *
536
     * @param name
537
     *            Header name to look up
538
     *
539
     * @return the header fields
540
     */
541
    public String[] getHeaderFields(String name) {
542
        if (!_headersComplete) {
1✔
543
            completeHeaders();
1✔
544
        }
545
        ArrayList values;
546
        synchronized (_headers) {
1✔
547
            values = (ArrayList) _headers.get(name.toUpperCase());
1✔
548
        }
1✔
549
        if (values == null) {
1✔
550
            return new String[0];
1✔
551
        }
552
        String[] results = new String[values.size()];
1✔
553
        return (String[]) values.toArray(results);
1✔
554

555
    }
556

557
    // --------------------------------------- methods added to ServletRequest in Servlet API 2.4
558
    // ----------------------------
559

560
    @Override
561
    public void setCharacterEncoding(String string) {
UNCOV
562
        _encoding = string;
×
UNCOV
563
    }
×
564

565
    /**
566
     * Returns the content type defined for this response.
567
     **/
568
    @Override
569
    public String getContentType() {
UNCOV
570
        return _contentType;
×
571
    }
572

573
    // ------------------------------------------- private members ------------------------------------
574

575
    /** The content type. */
576
    private String _contentType = "text/plain";
1✔
577

578
    /** The encoding. */
579
    private String _encoding;
580

581
    /** The writer. */
582
    private PrintWriter _writer;
583

584
    /** The servlet stream. */
585
    private ServletOutputStream _servletStream;
586

587
    /** The output stream. */
588
    private ByteArrayOutputStream _outputStream;
589

590
    /** The status. */
591
    private int _status = SC_OK;
1✔
592

593
    /** The status message. */
594
    private String _statusMessage = "OK";
1✔
595

596
    /** The headers. */
597
    private final Hashtable _headers = new Hashtable<>();
1✔
598

599
    /** The headers complete. */
600
    private boolean _headersComplete;
601

602
    /** The cookies. */
603
    private List<Cookie> _cookies = new ArrayList<>();
1✔
604

605
    /**
606
     * Complete headers.
607
     */
608
    private void completeHeaders() {
609
        if (_headersComplete) {
1!
UNCOV
610
            return;
×
611
        }
612
        addCookieHeader();
1✔
613
        // BR 3301056 ServletUnit handling Content-Type incorrectly
614
        if (getHeaderFieldDirect("Content-Type") == null) {
1✔
615
            setHeader("Content-Type", _contentType + "; charset=" + getCharacterEncoding());
1✔
616
        }
617
        _headersComplete = true;
1✔
618
    }
1✔
619

620
    /**
621
     * Adds the cookie header.
622
     */
623
    private void addCookieHeader() {
624
        if (_cookies.isEmpty()) {
1✔
625
            return;
1✔
626
        }
627

628
        StringBuilder sb = new StringBuilder();
1✔
629
        for (Enumeration e = Collections.enumeration(_cookies); e.hasMoreElements();) {
1✔
630
            Cookie cookie = (Cookie) e.nextElement();
1✔
631
            sb.append(cookie.getName()).append('=').append(cookie.getValue());
1✔
632
            if (cookie.getPath() != null) {
1!
633
                sb.append(";path=").append(cookie.getPath());
1✔
634
            }
635
            if (cookie.getDomain() != null) {
1!
UNCOV
636
                sb.append(";domain=").append(cookie.getDomain());
×
637
            }
638
            if (e.hasMoreElements()) {
1!
639
                sb.append(',');
×
640
            }
641
        }
1✔
642
        setHeader("Set-Cookie", sb.toString());
1✔
643
    }
1✔
644

645
    static {
646
        ENCODING_MAP.put("ISO-8859-1", "ca da de en es fi fr is it nl no pt sv ");
1✔
647
        ENCODING_MAP.put("ISO-8859-2", "cs hr hu pl ro sh sk sl sq ");
1✔
648
        ENCODING_MAP.put("ISO-8859-4", "et lt lv ");
1✔
649
        ENCODING_MAP.put("ISO-8859-5", "be bg mk ru sr uk ");
1✔
650
        ENCODING_MAP.put("ISO-8859-6", "ar ");
1✔
651
        ENCODING_MAP.put("ISO-8859-7", "el ");
1✔
652
        ENCODING_MAP.put("ISO-8859-8", "iw he ");
1✔
653
        ENCODING_MAP.put("ISO-8859-9", "tr ");
1✔
654

655
        ENCODING_MAP.put("Shift_JIS", "ja ");
1✔
656
        ENCODING_MAP.put("EUC-KR", "ko ");
1✔
657
        ENCODING_MAP.put("TIS-620", "th ");
1✔
658
        ENCODING_MAP.put("GB2312", "zh ");
1✔
659
        ENCODING_MAP.put("Big5", "zh_TW zh_HK ");
1✔
660
    }
1✔
661

662
    @Override
663
    public String getHeader(String name) {
UNCOV
664
        return (String) _headers.get(name.toUpperCase());
×
665
    }
666

667
    @Override
668
    public Collection<String> getHeaders(String name) {
669
        List values;
UNCOV
670
        synchronized (_headers) {
×
UNCOV
671
            values = (ArrayList) _headers.get(name.toUpperCase());
×
UNCOV
672
        }
×
673
        if (values == null) {
×
674
            return Collections.emptyList();
×
675
        }
676
        return values;
×
677
    }
678

679
    @Override
680
    public Collection<String> getHeaderNames() {
UNCOV
681
        if (!_headersComplete) {
×
UNCOV
682
            completeHeaders();
×
683
        }
684
        List names = new ArrayList<>();
×
685
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
×
UNCOV
686
            names.add(e.nextElement());
×
687
        }
688
        return names;
×
689
    }
690

691
    @Override
692
    public void setContentLengthLong(long len) {
UNCOV
693
        setLongHeader("Content-Length", len);
×
UNCOV
694
    }
×
695

696
    public void sendRedirect(String location, int sc, boolean clearBuffer) throws IOException {
697
        setStatus(sc);
×
UNCOV
698
        setHeader("Location", location);
×
UNCOV
699
        if (clearBuffer) {
×
700
            resetBuffer();
×
701
        }
702
    }
×
703

704
}
705

706
class ServletUnitOutputStream extends ServletOutputStream {
707

708
    ServletUnitOutputStream(ByteArrayOutputStream stream) {
1✔
709
        _stream = stream;
1✔
710
    }
1✔
711

712
    @Override
713
    public void write(int aByte) throws IOException {
714
        _stream.write(aByte);
1✔
715
    }
1✔
716

717
    private ByteArrayOutputStream _stream;
718

719
    @Override
720
    public boolean isReady() {
UNCOV
721
        return false;
×
722
    }
723

724
    @Override
725
    public void setWriteListener(WriteListener writeListener) {
726
        // Do nothing
UNCOV
727
    }
×
728
}
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