• 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

74.52
/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 java.io.ByteArrayOutputStream;
25
import java.io.IOException;
26
import java.io.OutputStreamWriter;
27
import java.io.PrintWriter;
28
import java.nio.charset.Charset;
29
import java.nio.charset.StandardCharsets;
30
import java.text.SimpleDateFormat;
31
import java.util.ArrayList;
32
import java.util.Collection;
33
import java.util.Collections;
34
import java.util.Date;
35
import java.util.Enumeration;
36
import java.util.Hashtable;
37
import java.util.Iterator;
38
import java.util.List;
39
import java.util.Locale;
40
import java.util.Map;
41
import java.util.TimeZone;
42

43
import javax.servlet.ServletOutputStream;
44
import javax.servlet.WriteListener;
45
import javax.servlet.http.Cookie;
46
import javax.servlet.http.HttpServletResponse;
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
     * @deprecated Use encodeURL(String url)
68
     */
69
    @Deprecated
70
    @Override
71
    public String encodeUrl(String url) {
72
        return encodeURL(url);
×
73
    }
74

75
    /**
76
     * Adds the specified cookie to the response. It can be called multiple times to set more than one cookie.
77
     */
78
    @Override
79
    public void addCookie(Cookie cookie) {
80
        _cookies.add(cookie);
1✔
81
    }
1✔
82

83
    /**
84
     * Checks whether the response message header has a field with the specified name.
85
     */
86
    @Override
87
    public boolean containsHeader(String name) {
88
        return _headers.containsKey(name.toUpperCase());
1✔
89
    }
90

91
    /**
92
     * @deprecated Use encodeRedirectURL(String url)
93
     **/
94
    @Deprecated
95
    @Override
96
    public String encodeRedirectUrl(String url) {
97
        return encodeRedirectURL(url);
×
98
    }
99

100
    /**
101
     * Encodes the specified URL by including the session ID in it, or, if encoding is not needed, returns the URL
102
     * unchanged. The implementation of this method should include the logic to determine whether the session ID needs
103
     * to be encoded in the URL. For example, if the browser supports cookies, or session tracking is turned off, URL
104
     * encoding is unnecessary.
105
     **/
106
    @Override
107
    public String encodeURL(String url) {
108
        return url;
×
109
    }
110

111
    /**
112
     * Encodes the specified URL for use in the <code>sendRedirect</code> method or, if encoding is not needed, returns
113
     * the URL unchanged. The implementation of this method should include the logic to determine whether the session ID
114
     * needs to be encoded in the URL. Because the rules for making this determination differ from those used to decide
115
     * whether to encode a normal link, this method is seperate from the <code>encodeUrl</code> method.
116
     **/
117
    @Override
118
    public String encodeRedirectURL(String url) {
119
        return url;
×
120
    }
121

122
    /**
123
     * Sends a temporary redirect response to the client using the specified redirect location URL. The URL must be
124
     * absolute (for example, <code><em>https://hostname/path/file.html</em></code>). Relative URLs are not permitted
125
     * here.
126
     */
127
    @Override
128
    public void sendRedirect(String location) throws IOException {
129
        setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
1✔
130
        setHeader("Location", location);
1✔
131
    }
1✔
132

133
    /**
134
     * Sends an error response to the client using the specified status code and descriptive message. If setStatus has
135
     * previously been called, it is reset to the error status code. The message is sent as the body of an HTML page,
136
     * which is returned to the user to describe the problem. The page is sent with a default HTML header; the message
137
     * is enclosed in simple body tags (&lt;body&gt;&lt;/body&gt;).
138
     **/
139
    @Override
140
    public void sendError(int sc) throws IOException {
141
        sendError(sc, "");
×
142
    }
×
143

144
    /**
145
     * Sends an error response to the client using the specified status code and descriptive message. If setStatus has
146
     * previously been called, it is reset to the error status code. The message is sent as the body of an HTML page,
147
     * which is returned to the user to describe the problem. The page is sent with a default HTML header; the message
148
     * is enclosed in simple body tags (&lt;body&gt;&lt;/body&gt;).
149
     **/
150
    @Override
151
    public void sendError(int sc, String msg) throws IOException {
152
        setStatus(sc);
×
153
        _statusMessage = msg;
×
154

155
        _writer = null;
×
156
        _servletStream = null;
×
157

158
        setContentType("text/html");
×
159
        getWriter().println("<html><head><title>" + msg + "</title></head><body>" + msg + "</body></html>");
×
160
    }
×
161

162
    /**
163
     * Sets the status code for this response. This method is used to set the return status code when there is no error
164
     * (for example, for the status codes SC_OK or SC_MOVED_TEMPORARILY). If there is an error, the
165
     * <code>sendError</code> method should be used instead.
166
     **/
167
    @Override
168
    public void setStatus(int sc) {
169
        _status = sc;
1✔
170
    }
1✔
171

172
    /**
173
     * @deprecated As of version 2.1, due to ambiguous meaning of the message parameter. To set a status code use
174
     *             setStatus(int), to send an error with a description use sendError(int, String). Sets the status code
175
     *             and message for this response.
176
     **/
177
    @Deprecated
178
    @Override
179
    public void setStatus(int sc, String msg) {
180
        setStatus(sc);
×
181
    }
×
182

183
    /**
184
     * Adds a field to the response header with the given name and value. If the field had already been set, the new
185
     * value overwrites the previous one. The <code>containsHeader</code> method can be used to test for the presence of
186
     * a header before setting its value.
187
     **/
188
    @Override
189
    public void setHeader(String name, String value) {
190
        ArrayList values = new ArrayList<>();
1✔
191
        values.add(value);
1✔
192
        synchronized (_headers) {
1✔
193
            _headers.put(name.toUpperCase(), values);
1✔
194
        }
1✔
195
    }
1✔
196

197
    /**
198
     * Adds a field to the response header with the given name and integer value. If the field had already been set, the
199
     * new value overwrites the previous one. The <code>containsHeader</code> method can be used to test for the
200
     * presence of a header before setting its value.
201
     **/
202
    @Override
203
    public void setIntHeader(String name, int value) {
204
        setHeader(name, asHeaderValue(value));
1✔
205
    }
1✔
206

207
    /**
208
     * Adds a field to the response header with the given name and integer value. If the field had already been set, the
209
     * new value overwrites the previous one. The <code>containsHeader</code> method can be used to test for the
210
     * presence of a header before setting its value.
211
     *
212
     * @param name
213
     *            the name
214
     * @param value
215
     *            the value
216
     */
217
    public void setLongHeader(String name, long value) {
218
        setHeader(name, asHeaderLongValue(value));
×
219
    }
×
220

221
    /**
222
     * As header value.
223
     *
224
     * @param value
225
     *            the value
226
     *
227
     * @return the string
228
     */
229
    private String asHeaderValue(int value) {
230
        return Integer.toString(value);
1✔
231
    }
232

233
    /**
234
     * As header long value.
235
     *
236
     * @param value
237
     *            the value
238
     *
239
     * @return the string
240
     */
241
    private String asHeaderLongValue(long value) {
242
        return Long.toString(value);
×
243
    }
244

245
    /**
246
     * Adds a field to the response header with the given name and date-valued field. The date is specified in terms of
247
     * milliseconds since the epoch. If the date field had already been set, the new value overwrites the previous one.
248
     * The <code>containsHeader</code> method can be used to test for the presence of a header before setting its value.
249
     **/
250
    @Override
251
    public void setDateHeader(String name, long date) {
252
        setHeader(name, asDateHeaderValue(date));
1✔
253
    }
1✔
254

255
    /**
256
     * As date header value.
257
     *
258
     * @param date
259
     *            the date
260
     *
261
     * @return the string
262
     */
263
    private String asDateHeaderValue(long date) {
264
        Date value = new Date(date);
1✔
265
        SimpleDateFormat formatter = new SimpleDateFormat(RFC1123_DATE_SPEC, Locale.US);
1✔
266
        formatter.setTimeZone(TimeZone.getTimeZone("Greenwich Mean Time"));
1✔
267
        return formatter.format(value);
1✔
268
    }
269

270
    /**
271
     * Returns the name of the character set encoding used for the MIME body sent by this response.
272
     **/
273
    @Override
274
    public String getCharacterEncoding() {
275
        return _encoding == null ? StandardCharsets.ISO_8859_1.name() : _encoding;
1✔
276
    }
277

278
    /**
279
     * Sets the content type of the response the server sends to the client. The content type may include the type of
280
     * character encoding used, for example, <code>text/html; charset=ISO-8859-4</code>.
281
     * <p>
282
     * You can only use this method once, and you should call it before you obtain a <code>PrintWriter</code> or
283
     * {@link ServletOutputStream} object to return a response.
284
     **/
285
    @Override
286
    public void setContentType(String type) {
287
        String[] typeAndEncoding = HttpUnitUtils.parseContentTypeHeader(type);
1✔
288

289
        _contentType = typeAndEncoding[0];
1✔
290
        if (typeAndEncoding[1] != null) {
1✔
291
            _encoding = typeAndEncoding[1];
1✔
292
        }
293
    }
1✔
294

295
    /**
296
     * Returns a {@link ServletOutputStream} suitable for writing binary data in the response. The servlet engine does
297
     * not encode the binary data.
298
     *
299
     * @exception IllegalStateException
300
     *                if you have already called the <code>getWriter</code> method
301
     **/
302
    @Override
303
    public ServletOutputStream getOutputStream() throws IOException {
304
        if (_writer != null) {
1✔
305
            throw new IllegalStateException("Tried to create output stream; writer already exists");
1✔
306
        }
307
        if (_servletStream == null) {
1✔
308
            _outputStream = new ByteArrayOutputStream();
1✔
309
            _servletStream = new ServletUnitOutputStream(_outputStream);
1✔
310
        }
311
        return _servletStream;
1✔
312
    }
313

314
    /**
315
     * Returns a <code>PrintWriter</code> object that you can use to send character text to the client. The character
316
     * encoding used is the one specified in the <code>charset=</code> property of the {@link #setContentType} method,
317
     * which you must call <i>before</i> you call this method.
318
     * <p>
319
     * If necessary, the MIME type of the response is modified to reflect the character encoding used.
320
     * <p>
321
     * You cannot use this method if you have already called {@link #getOutputStream} for this
322
     * <code>ServletResponse</code> object.
323
     *
324
     * @exception IllegalStateException
325
     *                if the <code>getOutputStream</code> method has already been called for this response object; in
326
     *                that case, you can't use this method
327
     **/
328
    @Override
329
    public PrintWriter getWriter() {
330
        if (_servletStream != null) {
1✔
331
            throw new IllegalStateException("Tried to create writer; output stream already exists");
1✔
332
        }
333
        if (_writer == null) {
1✔
334
            _outputStream = new ByteArrayOutputStream();
1✔
335
            _writer = new PrintWriter(new OutputStreamWriter(_outputStream, Charset.forName(getCharacterEncoding())));
1✔
336
        }
337
        return _writer;
1✔
338
    }
339

340
    /**
341
     * Sets the length of the content the server returns to the client. In HTTP servlets, this method sets the HTTP
342
     * Content-Length header.
343
     **/
344
    @Override
345
    public void setContentLength(int len) {
346
        setIntHeader("Content-Length", len);
1✔
347
    }
1✔
348

349
    // ------------------------------- the following methods are new in JSDK 2.2 ----------------------
350

351
    /**
352
     * Adds a response header with the given name and value. This method allows response headers to have multiple
353
     * values.
354
     **/
355
    @Override
356
    public void addHeader(String name, String value) {
357
        synchronized (_headers) {
1✔
358
            String key = name.toUpperCase();
1✔
359
            List values = (ArrayList) _headers.get(key);
1✔
360
            if (values == null) {
1✔
361
                values = new ArrayList<>();
1✔
362
                _headers.put(key, values);
1✔
363
            }
364
            values.add(value);
1✔
365
        }
1✔
366
    }
1✔
367

368
    /**
369
     * Adds a response header with the given name and value. This method allows response headers to have multiple
370
     * values.
371
     **/
372
    @Override
373
    public void addIntHeader(String name, int value) {
374
        addHeader(name, asHeaderValue(value));
1✔
375
    }
1✔
376

377
    /**
378
     * Adds a response header with the given name and value. This method allows response headers to have multiple
379
     * values.
380
     **/
381
    @Override
382
    public void addDateHeader(String name, long value) {
383
        addHeader(name, asDateHeaderValue(value));
1✔
384
    }
1✔
385

386
    /**
387
     * Sets the preferred buffer size for the body of the response. The servlet container will use a buffer at least as
388
     * large as the size requested. The actual buffer size used can be found using getBufferSize.
389
     **/
390
    @Override
391
    public void setBufferSize(int size) {
392
        if (getContents().length != 0) {
1✔
393
            throw new IllegalStateException("May not set buffer size after data is written");
1✔
394
        }
395
    }
1✔
396

397
    /**
398
     * Returns the actual buffer size used for the response. If no buffering is used, this method returns 0.
399
     **/
400
    @Override
401
    public int getBufferSize() {
402
        return 0;
×
403
    }
404

405
    /**
406
     * Returns a boolean indicating if the response has been committed. A committed response has already had its status
407
     * code and headers written.
408
     **/
409
    @Override
410
    public boolean isCommitted() {
411
        return _committed;
1✔
412
    }
413

414
    /**
415
     * Forces any content in the buffer to be written to the client. A call to this method automatically commits the
416
     * response, meaning the status code and headers will be written.
417
     **/
418
    @Override
419
    public void flushBuffer() throws IOException {
420
        _committed = true;
1✔
421
    }
1✔
422

423
    /**
424
     * Clears any data that exists in the buffer as well as the status code and headers. If the response has been
425
     * committed, this method throws an IllegalStateException.
426
     **/
427
    @Override
428
    public void reset() {
429
        resetBuffer();
1✔
430
        _headers.clear();
1✔
431
        _headersComplete = false;
1✔
432
        _status = SC_OK;
1✔
433
    }
1✔
434

435
    /**
436
     * Sets the locale of the response, setting the headers (including the Content-Type's charset) as appropriate. This
437
     * method should be called before a call to getWriter(). By default, the response locale is the default locale for
438
     * the server.
439
     **/
440
    @Override
441
    public void setLocale(Locale locale) {
442
        _locale = locale;
1✔
443
        if (_encoding == null) {
1!
444
            for (Iterator it = ENCODING_MAP.entrySet().iterator(); it.hasNext();) {
1!
445
                Map.Entry entry = (Map.Entry) it.next();
1✔
446
                String locales = (String) entry.getValue();
1✔
447
                if (locales.indexOf(locale.getLanguage()) >= 0 || locales.indexOf(locale.toString()) >= 0) {
1!
448
                    _encoding = (String) entry.getKey();
1✔
449
                    return;
1✔
450
                }
451
            }
1✔
452
        }
453
    }
×
454

455
    /**
456
     * Returns the locale assigned to the response.
457
     **/
458
    @Override
459
    public Locale getLocale() {
460
        return _locale;
1✔
461
    }
462

463
    // ----------------------------- methods added to ServletResponse in JSDK 2.3 --------------------------------------
464

465
    /**
466
     * Clears the content of the underlying buffer in the response without clearing headers or status code. If the
467
     * response has been committed, this method throws an IllegalStateException.
468
     */
469
    @Override
470
    public void resetBuffer() {
471
        if (_committed) {
1✔
472
            throw new IllegalStateException("May not resetBuffer after response is committed");
1✔
473
        }
474
        _outputStream = null;
1✔
475
        _servletStream = null;
1✔
476
        _writer = null;
1✔
477
    }
1✔
478

479
    // ---------------------------------------------- package methods --------------------------------------------------
480

481
    /**
482
     * Returns the contents of this response.
483
     *
484
     * @return the contents
485
     */
486
    byte[] getContents() {
487
        if (_outputStream == null) {
1✔
488
            return new byte[0];
1✔
489
        }
490
        if (_writer != null) {
1✔
491
            _writer.flush();
1✔
492
        }
493
        return _outputStream.toByteArray();
1✔
494
    }
495

496
    /**
497
     * Returns the status of this response.
498
     **/
499
    @Override
500
    public int getStatus() {
501
        return _status;
1✔
502
    }
503

504
    /**
505
     * Returns the message associated with this response's status.
506
     *
507
     * @return the message
508
     */
509
    String getMessage() {
510
        return _statusMessage;
×
511
    }
512

513
    /**
514
     * Gets the header field names.
515
     *
516
     * @return the header field names
517
     */
518
    public String[] getHeaderFieldNames() {
519
        if (!_headersComplete) {
×
520
            completeHeaders();
×
521
        }
522
        List<String> names = new ArrayList<>();
×
523
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
×
524
            names.add((String) e.nextElement());
×
525
        }
526
        return names.toArray(new String[0]);
×
527
    }
528

529
    /**
530
     * Returns the headers defined for this response.
531
     *
532
     * @param name
533
     *            - the name of the field to get
534
     *
535
     * @return the header field direct
536
     */
537
    String getHeaderFieldDirect(String name) {
538
        ArrayList values;
539
        synchronized (_headers) {
1✔
540
            values = (ArrayList) _headers.get(name.toUpperCase());
1✔
541
        }
1✔
542

543
        return values == null ? null : (String) values.get(0);
1✔
544
    }
545

546
    /**
547
     * Returns the headers defined for this response.
548
     *
549
     * @param name
550
     *            the name
551
     *
552
     * @return the header field
553
     */
554
    String getHeaderField(String name) {
555
        if (!_headersComplete) {
1✔
556
            completeHeaders();
1✔
557
        }
558
        return getHeaderFieldDirect(name);
1✔
559
    }
560

561
    /**
562
     * Return an array of all the header values associated with the specified header name, or an zero-length array if
563
     * there are no such header values.
564
     *
565
     * @param name
566
     *            Header name to look up
567
     *
568
     * @return the header fields
569
     */
570
    public String[] getHeaderFields(String name) {
571
        if (!_headersComplete) {
1✔
572
            completeHeaders();
1✔
573
        }
574
        ArrayList values;
575
        synchronized (_headers) {
1✔
576
            values = (ArrayList) _headers.get(name.toUpperCase());
1✔
577
        }
1✔
578
        if (values == null) {
1✔
579
            return new String[0];
1✔
580
        }
581
        String[] results = new String[values.size()];
1✔
582
        return (String[]) values.toArray(results);
1✔
583

584
    }
585

586
    // --------------------------------------- methods added to ServletRequest in Servlet API 2.4
587
    // ----------------------------
588

589
    @Override
590
    public void setCharacterEncoding(String string) {
591
        _encoding = string;
×
592
    }
×
593

594
    /**
595
     * Returns the content type defined for this response.
596
     **/
597
    @Override
598
    public String getContentType() {
599
        return _contentType;
×
600
    }
601

602
    // ------------------------------------------- private members ------------------------------------
603

604
    /** The content type. */
605
    private String _contentType = "text/plain";
1✔
606

607
    /** The encoding. */
608
    private String _encoding;
609

610
    /** The writer. */
611
    private PrintWriter _writer;
612

613
    /** The servlet stream. */
614
    private ServletOutputStream _servletStream;
615

616
    /** The output stream. */
617
    private ByteArrayOutputStream _outputStream;
618

619
    /** The status. */
620
    private int _status = SC_OK;
1✔
621

622
    /** The status message. */
623
    private String _statusMessage = "OK";
1✔
624

625
    /** The headers. */
626
    private final Hashtable _headers = new Hashtable<>();
1✔
627

628
    /** The headers complete. */
629
    private boolean _headersComplete;
630

631
    /** The cookies. */
632
    private List<Cookie> _cookies = new ArrayList<>();
1✔
633

634
    /**
635
     * Complete headers.
636
     */
637
    private void completeHeaders() {
638
        if (_headersComplete) {
1!
639
            return;
×
640
        }
641
        addCookieHeader();
1✔
642
        // BR 3301056 ServletUnit handling Content-Type incorrectly
643
        if (getHeaderFieldDirect("Content-Type") == null) {
1✔
644
            setHeader("Content-Type", _contentType + "; charset=" + getCharacterEncoding());
1✔
645
        }
646
        _headersComplete = true;
1✔
647
    }
1✔
648

649
    /**
650
     * Adds the cookie header.
651
     */
652
    private void addCookieHeader() {
653
        if (_cookies.isEmpty()) {
1✔
654
            return;
1✔
655
        }
656

657
        StringBuilder sb = new StringBuilder();
1✔
658
        for (Enumeration e = Collections.enumeration(_cookies); e.hasMoreElements();) {
1✔
659
            Cookie cookie = (Cookie) e.nextElement();
1✔
660
            sb.append(cookie.getName()).append('=').append(cookie.getValue());
1✔
661
            if (cookie.getPath() != null) {
1!
662
                sb.append(";path=").append(cookie.getPath());
1✔
663
            }
664
            if (cookie.getDomain() != null) {
1!
665
                sb.append(";domain=").append(cookie.getDomain());
×
666
            }
667
            if (e.hasMoreElements()) {
1!
668
                sb.append(',');
×
669
            }
670
        }
1✔
671
        setHeader("Set-Cookie", sb.toString());
1✔
672
    }
1✔
673

674
    static {
675
        ENCODING_MAP.put("ISO-8859-1", "ca da de en es fi fr is it nl no pt sv ");
1✔
676
        ENCODING_MAP.put("ISO-8859-2", "cs hr hu pl ro sh sk sl sq ");
1✔
677
        ENCODING_MAP.put("ISO-8859-4", "et lt lv ");
1✔
678
        ENCODING_MAP.put("ISO-8859-5", "be bg mk ru sr uk ");
1✔
679
        ENCODING_MAP.put("ISO-8859-6", "ar ");
1✔
680
        ENCODING_MAP.put("ISO-8859-7", "el ");
1✔
681
        ENCODING_MAP.put("ISO-8859-8", "iw he ");
1✔
682
        ENCODING_MAP.put("ISO-8859-9", "tr ");
1✔
683

684
        ENCODING_MAP.put("Shift_JIS", "ja ");
1✔
685
        ENCODING_MAP.put("EUC-KR", "ko ");
1✔
686
        ENCODING_MAP.put("TIS-620", "th ");
1✔
687
        ENCODING_MAP.put("GB2312", "zh ");
1✔
688
        ENCODING_MAP.put("Big5", "zh_TW zh_HK ");
1✔
689
    }
1✔
690

691
    @Override
692
    public String getHeader(String name) {
693
        return (String) _headers.get(name.toUpperCase());
×
694
    }
695

696
    @Override
697
    public Collection<String> getHeaders(String name) {
698
        List values;
699
        synchronized (_headers) {
×
700
            values = (ArrayList) _headers.get(name.toUpperCase());
×
701
        }
×
702
        if (values == null) {
×
703
            return Collections.emptyList();
×
704
        }
705
        return values;
×
706
    }
707

708
    @Override
709
    public Collection<String> getHeaderNames() {
710
        if (!_headersComplete) {
×
711
            completeHeaders();
×
712
        }
713
        List names = new ArrayList<>();
×
714
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
×
715
            names.add(e.nextElement());
×
716
        }
717
        return names;
×
718
    }
719

720
    @Override
721
    public void setContentLengthLong(long len) {
722
        setLongHeader("Content-Length", len);
×
723
    }
×
724

725
}
726

727
class ServletUnitOutputStream extends ServletOutputStream {
728

729
    ServletUnitOutputStream(ByteArrayOutputStream stream) {
1✔
730
        _stream = stream;
1✔
731
    }
1✔
732

733
    @Override
734
    public void write(int aByte) throws IOException {
735
        _stream.write(aByte);
1✔
736
    }
1✔
737

738
    private ByteArrayOutputStream _stream;
739

740
    @Override
741
    public boolean isReady() {
742
        return false;
×
743
    }
744

745
    @Override
746
    public void setWriteListener(WriteListener writeListener) {
747
        // Do nothing
748
    }
×
749
}
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