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

hazendaz / httpunit / 389

12 Aug 2025 11:17PM UTC coverage: 80.48% (-0.02%) from 80.503%
389

push

github

hazendaz
Merge branch 'master' into javax

3216 of 4105 branches covered (78.34%)

Branch coverage included in aggregate %.

238 of 258 new or added lines in 68 files covered. (92.25%)

2 existing lines in 2 files now uncovered.

8254 of 10147 relevant lines covered (81.34%)

0.81 hits per line

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

73.96
/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
import java.util.Vector;
43

44
import javax.servlet.ServletOutputStream;
45
import javax.servlet.WriteListener;
46
import javax.servlet.http.Cookie;
47
import javax.servlet.http.HttpServletResponse;
48

49
class ServletUnitHttpResponse implements HttpServletResponse {
1✔
50

51
    // rfc1123-date is "Sun, 06 Nov 1994 08:49:37 GMT"
52
    private static final String RFC1123_DATE_SPEC = "EEE, dd MMM yyyy HH:mm:ss z";
53
    private boolean _committed;
54
    private Locale _locale = Locale.getDefault();
1✔
55

56
    private static final Hashtable ENCODING_MAP = new Hashtable<>();
1✔
57

58
    /**
59
     * @deprecated Use encodeURL(String url)
60
     */
61
    @Deprecated
62
    @Override
63
    public String encodeUrl(String url) {
64
        return encodeURL(url);
×
65
    }
66

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

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

83
    /**
84
     * @deprecated Use encodeRedirectURL(String url)
85
     **/
86
    @Deprecated
87
    @Override
88
    public String encodeRedirectUrl(String url) {
89
        return encodeRedirectURL(url);
×
90
    }
91

92
    /**
93
     * Encodes the specified URL by including the session ID in it, or, if encoding is not needed, returns the URL
94
     * unchanged. The implementation of this method should include the logic to determine whether the session ID needs
95
     * to be encoded in the URL. For example, if the browser supports cookies, or session tracking is turned off, URL
96
     * encoding is unnecessary.
97
     **/
98
    @Override
99
    public String encodeURL(String url) {
100
        return url;
×
101
    }
102

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

114
    /**
115
     * Sends a temporary redirect response to the client using the specified redirect location URL. The URL must be
116
     * absolute (for example, <code><em>https://hostname/path/file.html</em></code>). Relative URLs are not permitted
117
     * here.
118
     */
119
    @Override
120
    public void sendRedirect(String location) throws IOException {
121
        setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
1✔
122
        setHeader("Location", location);
1✔
123
    }
1✔
124

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

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

147
        _writer = null;
×
148
        _servletStream = null;
×
149

150
        setContentType("text/html");
×
151
        getWriter().println("<html><head><title>" + msg + "</title></head><body>" + msg + "</body></html>");
×
152
    }
×
153

154
    /**
155
     * Sets the status code for this response. This method is used to set the return status code when there is no error
156
     * (for example, for the status codes SC_OK or SC_MOVED_TEMPORARILY). If there is an error, the
157
     * <code>sendError</code> method should be used instead.
158
     **/
159
    @Override
160
    public void setStatus(int sc) {
161
        _status = sc;
1✔
162
    }
1✔
163

164
    /**
165
     * @deprecated As of version 2.1, due to ambiguous meaning of the message parameter. To set a status code use
166
     *             setStatus(int), to send an error with a description use sendError(int, String). Sets the status code
167
     *             and message for this response.
168
     **/
169
    @Deprecated
170
    @Override
171
    public void setStatus(int sc, String msg) {
172
        setStatus(sc);
×
173
    }
×
174

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

189
    /**
190
     * Adds a field to the response header with the given name and integer value. If the field had already been set, the
191
     * new value overwrites the previous one. The <code>containsHeader</code> method can be used to test for the
192
     * presence of a header before setting its value.
193
     **/
194
    @Override
195
    public void setIntHeader(String name, int value) {
196
        setHeader(name, asHeaderValue(value));
1✔
197
    }
1✔
198

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

208
    private String asHeaderValue(int value) {
209
        return Integer.toString(value);
1✔
210
    }
211

212
    private String asHeaderLongValue(long value) {
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
    private String asDateHeaderValue(long date) {
227
        Date value = new Date(date);
1✔
228
        SimpleDateFormat formatter = new SimpleDateFormat(RFC1123_DATE_SPEC, Locale.US);
1✔
229
        formatter.setTimeZone(TimeZone.getTimeZone("Greenwich Mean Time"));
1✔
230
        return formatter.format(value);
1✔
231
    }
232

233
    /**
234
     * Returns the name of the character set encoding used for the MIME body sent by this response.
235
     **/
236
    @Override
237
    public String getCharacterEncoding() {
238
        return _encoding == null ? StandardCharsets.ISO_8859_1.name() : _encoding;
1✔
239
    }
240

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

252
        _contentType = typeAndEncoding[0];
1✔
253
        if (typeAndEncoding[1] != null) {
1✔
254
            _encoding = typeAndEncoding[1];
1✔
255
        }
256
    }
1✔
257

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

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

303
    /**
304
     * Sets the length of the content the server returns to the client. In HTTP servlets, this method sets the HTTP
305
     * Content-Length header.
306
     **/
307
    @Override
308
    public void setContentLength(int len) {
309
        setIntHeader("Content-Length", len);
1✔
310
    }
1✔
311

312
    // ------------------------------- the following methods are new in JSDK 2.2 ----------------------
313

314
    /**
315
     * Adds a response header with the given name and value. This method allows response headers to have multiple
316
     * values.
317
     **/
318
    @Override
319
    public void addHeader(String name, String value) {
320
        synchronized (_headers) {
1✔
321
            String key = name.toUpperCase();
1✔
322
            List values = (ArrayList) _headers.get(key);
1✔
323
            if (values == null) {
1✔
324
                values = new ArrayList<>();
1✔
325
                _headers.put(key, values);
1✔
326
            }
327
            values.add(value);
1✔
328
        }
1✔
329
    }
1✔
330

331
    /**
332
     * Adds a response header with the given name and value. This method allows response headers to have multiple
333
     * values.
334
     **/
335
    @Override
336
    public void addIntHeader(String name, int value) {
337
        addHeader(name, asHeaderValue(value));
1✔
338
    }
1✔
339

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

349
    /**
350
     * Sets the preferred buffer size for the body of the response. The servlet container will use a buffer at least as
351
     * large as the size requested. The actual buffer size used can be found using getBufferSize.
352
     **/
353
    @Override
354
    public void setBufferSize(int size) {
355
        if (getContents().length != 0) {
1✔
356
            throw new IllegalStateException("May not set buffer size after data is written");
1✔
357
        }
358
    }
1✔
359

360
    /**
361
     * Returns the actual buffer size used for the response. If no buffering is used, this method returns 0.
362
     **/
363
    @Override
364
    public int getBufferSize() {
365
        return 0;
×
366
    }
367

368
    /**
369
     * Returns a boolean indicating if the response has been committed. A committed response has already had its status
370
     * code and headers written.
371
     **/
372
    @Override
373
    public boolean isCommitted() {
374
        return _committed;
1✔
375
    }
376

377
    /**
378
     * Forces any content in the buffer to be written to the client. A call to this method automatically commits the
379
     * response, meaning the status code and headers will be written.
380
     **/
381
    @Override
382
    public void flushBuffer() throws IOException {
383
        _committed = true;
1✔
384
    }
1✔
385

386
    /**
387
     * Clears any data that exists in the buffer as well as the status code and headers. If the response has been
388
     * committed, this method throws an IllegalStateException.
389
     **/
390
    @Override
391
    public void reset() {
392
        resetBuffer();
1✔
393
        _headers.clear();
1✔
394
        _headersComplete = false;
1✔
395
        _status = SC_OK;
1✔
396
    }
1✔
397

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

418
    /**
419
     * Returns the locale assigned to the response.
420
     **/
421
    @Override
422
    public Locale getLocale() {
423
        return _locale;
1✔
424
    }
425

426
    // ----------------------------- methods added to ServletResponse in JSDK 2.3 --------------------------------------
427

428
    /**
429
     * Clears the content of the underlying buffer in the response without clearing headers or status code. If the
430
     * response has been committed, this method throws an IllegalStateException.
431
     *
432
     * @since 1.3
433
     */
434
    @Override
435
    public void resetBuffer() {
436
        if (_committed) {
1✔
437
            throw new IllegalStateException("May not resetBuffer after response is committed");
1✔
438
        }
439
        _outputStream = null;
1✔
440
        _servletStream = null;
1✔
441
        _writer = null;
1✔
442
    }
1✔
443

444
    // ---------------------------------------------- package methods --------------------------------------------------
445

446
    /**
447
     * Returns the contents of this response.
448
     **/
449
    byte[] getContents() {
450
        if (_outputStream == null) {
1✔
451
            return new byte[0];
1✔
452
        }
453
        if (_writer != null) {
1✔
454
            _writer.flush();
1✔
455
        }
456
        return _outputStream.toByteArray();
1✔
457
    }
458

459
    /**
460
     * Returns the status of this response.
461
     **/
462
    @Override
463
    public int getStatus() {
464
        return _status;
1✔
465
    }
466

467
    /**
468
     * Returns the message associated with this response's status.
469
     **/
470
    String getMessage() {
471
        return _statusMessage;
×
472
    }
473

474
    public String[] getHeaderFieldNames() {
475
        if (!_headersComplete) {
×
476
            completeHeaders();
×
477
        }
NEW
478
        Vector names = new Vector<>();
×
479
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
×
480
            names.addElement(e.nextElement());
×
481
        }
482
        String[] result = new String[names.size()];
×
483
        names.copyInto(result);
×
484
        return result;
×
485
    }
486

487
    /**
488
     * Returns the headers defined for this response.
489
     *
490
     * @param name
491
     *            - the name of the field to get
492
     **/
493
    String getHeaderFieldDirect(String name) {
494
        ArrayList values;
495
        synchronized (_headers) {
1✔
496
            values = (ArrayList) _headers.get(name.toUpperCase());
1✔
497
        }
1✔
498

499
        return values == null ? null : (String) values.get(0);
1✔
500
    }
501

502
    /**
503
     * Returns the headers defined for this response.
504
     *
505
     * @param name
506
     **/
507
    String getHeaderField(String name) {
508
        if (!_headersComplete) {
1✔
509
            completeHeaders();
1✔
510
        }
511
        return getHeaderFieldDirect(name);
1✔
512
    }
513

514
    /**
515
     * Return an array of all the header values associated with the specified header name, or an zero-length array if
516
     * there are no such header values.
517
     *
518
     * @param name
519
     *            Header name to look up
520
     */
521
    public String[] getHeaderFields(String name) {
522
        if (!_headersComplete) {
1✔
523
            completeHeaders();
1✔
524
        }
525
        ArrayList values;
526
        synchronized (_headers) {
1✔
527
            values = (ArrayList) _headers.get(name.toUpperCase());
1✔
528
        }
1✔
529
        if (values == null) {
1✔
530
            return new String[0];
1✔
531
        }
532
        String[] results = new String[values.size()];
1✔
533
        return (String[]) values.toArray(results);
1✔
534

535
    }
536

537
    // --------------------------------------- methods added to ServletRequest in Servlet API 2.4
538
    // ----------------------------
539

540
    @Override
541
    public void setCharacterEncoding(String string) {
542
        _encoding = string;
×
543
    }
×
544

545
    /**
546
     * Returns the content type defined for this response.
547
     **/
548
    @Override
549
    public String getContentType() {
550
        return _contentType;
×
551
    }
552

553
    // ------------------------------------------- private members ------------------------------------
554

555
    private String _contentType = "text/plain";
1✔
556

557
    private String _encoding;
558

559
    private PrintWriter _writer;
560

561
    private ServletOutputStream _servletStream;
562

563
    private ByteArrayOutputStream _outputStream;
564

565
    private int _status = SC_OK;
1✔
566

567
    private String _statusMessage = "OK";
1✔
568

569
    private final Hashtable _headers = new Hashtable<>();
1✔
570

571
    private boolean _headersComplete;
572

573
    private Vector _cookies = new Vector<>();
1✔
574

575
    private void completeHeaders() {
576
        if (_headersComplete) {
1!
577
            return;
×
578
        }
579
        addCookieHeader();
1✔
580
        // BR 3301056 ServletUnit handling Content-Type incorrectly
581
        if (getHeaderFieldDirect("Content-Type") == null) {
1✔
582
            setHeader("Content-Type", _contentType + "; charset=" + getCharacterEncoding());
1✔
583
        }
584
        _headersComplete = true;
1✔
585
    }
1✔
586

587
    private void addCookieHeader() {
588
        if (_cookies.isEmpty()) {
1✔
589
            return;
1✔
590
        }
591

592
        StringBuilder sb = new StringBuilder();
1✔
593
        for (Enumeration e = _cookies.elements(); e.hasMoreElements();) {
1✔
594
            Cookie cookie = (Cookie) e.nextElement();
1✔
595
            sb.append(cookie.getName()).append('=').append(cookie.getValue());
1✔
596
            if (cookie.getPath() != null) {
1!
597
                sb.append(";path=").append(cookie.getPath());
1✔
598
            }
599
            if (cookie.getDomain() != null) {
1!
600
                sb.append(";domain=").append(cookie.getDomain());
×
601
            }
602
            if (e.hasMoreElements()) {
1!
603
                sb.append(',');
×
604
            }
605
        }
1✔
606
        setHeader("Set-Cookie", sb.toString());
1✔
607
    }
1✔
608

609
    static {
610
        ENCODING_MAP.put("ISO-8859-1", "ca da de en es fi fr is it nl no pt sv ");
1✔
611
        ENCODING_MAP.put("ISO-8859-2", "cs hr hu pl ro sh sk sl sq ");
1✔
612
        ENCODING_MAP.put("ISO-8859-4", "et lt lv ");
1✔
613
        ENCODING_MAP.put("ISO-8859-5", "be bg mk ru sr uk ");
1✔
614
        ENCODING_MAP.put("ISO-8859-6", "ar ");
1✔
615
        ENCODING_MAP.put("ISO-8859-7", "el ");
1✔
616
        ENCODING_MAP.put("ISO-8859-8", "iw he ");
1✔
617
        ENCODING_MAP.put("ISO-8859-9", "tr ");
1✔
618

619
        ENCODING_MAP.put("Shift_JIS", "ja ");
1✔
620
        ENCODING_MAP.put("EUC-KR", "ko ");
1✔
621
        ENCODING_MAP.put("TIS-620", "th ");
1✔
622
        ENCODING_MAP.put("GB2312", "zh ");
1✔
623
        ENCODING_MAP.put("Big5", "zh_TW zh_HK ");
1✔
624
    }
1✔
625

626
    @Override
627
    public String getHeader(String name) {
628
        return (String) _headers.get(name.toUpperCase());
×
629
    }
630

631
    @Override
632
    public Collection<String> getHeaders(String name) {
633
        List values;
634
        synchronized (_headers) {
×
635
            values = (ArrayList) _headers.get(name.toUpperCase());
×
636
        }
×
637
        if (values == null) {
×
NEW
638
            return Collections.emptyList();
×
639
        }
640
        return values;
×
641
    }
642

643
    @Override
644
    public Collection<String> getHeaderNames() {
645
        if (!_headersComplete) {
×
646
            completeHeaders();
×
647
        }
NEW
648
        Vector names = new Vector<>();
×
649
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
×
650
            names.addElement(e.nextElement());
×
651
        }
652
        return names;
×
653
    }
654

655
    @Override
656
    public void setContentLengthLong(long len) {
657
        setLongHeader("Content-Length", len);
×
658
    }
×
659

660
}
661

662
class ServletUnitOutputStream extends ServletOutputStream {
663

664
    ServletUnitOutputStream(ByteArrayOutputStream stream) {
1✔
665
        _stream = stream;
1✔
666
    }
1✔
667

668
    @Override
669
    public void write(int aByte) throws IOException {
670
        _stream.write(aByte);
1✔
671
    }
1✔
672

673
    private ByteArrayOutputStream _stream;
674

675
    @Override
676
    public boolean isReady() {
677
        return false;
×
678
    }
679

680
    @Override
681
    public void setWriteListener(WriteListener writeListener) {
682
        // Do nothing
683
    }
×
684
}
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