src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java
author pliden
Wed, 20 Nov 2019 10:37:46 +0100
changeset 59152 59272e9e0635
parent 53720 3e451bff6f7f
permissions -rw-r--r--
8234383: Test TestBiasedLockRevocationEvents.java assumes -XX:UseBiasedLocking is enabled Reviewed-by: mgronlun, tschatzl
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
53720
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
     2
 * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5460
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5460
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5460
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5460
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 5460
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.net.httpserver;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.io.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.net.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import javax.net.ssl.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.util.*;
41592
855537e5ad9c 8157965: update httpserver logging to use java.lang.System.Logger
dfuchs
parents: 25859
diff changeset
    32
import java.lang.System.Logger;
855537e5ad9c 8157965: update httpserver logging to use java.lang.System.Logger
dfuchs
parents: 25859
diff changeset
    33
import java.lang.System.Logger.Level;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.text.*;
53720
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
    35
import java.util.stream.Stream;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import com.sun.net.httpserver.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
class ExchangeImpl {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
    Headers reqHdrs, rspHdrs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
    Request req;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
    String method;
7271
17d3fc18872d 6725892: Http server stability issues
michaelm
parents: 6003
diff changeset
    43
    boolean writefinished;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    URI uri;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    HttpConnection connection;
1511
65ddd8f149f3 6756771: com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig
chegar
parents: 2
diff changeset
    46
    long reqContentLen;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
    long rspContentLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
    /* raw streams which access the socket directly */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
    InputStream ris;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
    OutputStream ros;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
    Thread thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
    /* close the underlying connection when this exchange finished */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
    boolean close;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
    boolean closed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
    boolean http10 = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
    /* for formatting the Date: header */
6003
6aed6c9c974d 6967684: httpserver using a non thread-safe SimpleDateFormat
chegar
parents: 5506
diff changeset
    58
    private static final String pattern = "EEE, dd MMM yyyy HH:mm:ss zzz";
6aed6c9c974d 6967684: httpserver using a non thread-safe SimpleDateFormat
chegar
parents: 5506
diff changeset
    59
    private static final TimeZone gmtTZ = TimeZone.getTimeZone("GMT");
6aed6c9c974d 6967684: httpserver using a non thread-safe SimpleDateFormat
chegar
parents: 5506
diff changeset
    60
    private static final ThreadLocal<DateFormat> dateFormat =
6aed6c9c974d 6967684: httpserver using a non thread-safe SimpleDateFormat
chegar
parents: 5506
diff changeset
    61
         new ThreadLocal<DateFormat>() {
6aed6c9c974d 6967684: httpserver using a non thread-safe SimpleDateFormat
chegar
parents: 5506
diff changeset
    62
             @Override protected DateFormat initialValue() {
6aed6c9c974d 6967684: httpserver using a non thread-safe SimpleDateFormat
chegar
parents: 5506
diff changeset
    63
                 DateFormat df = new SimpleDateFormat(pattern, Locale.US);
6aed6c9c974d 6967684: httpserver using a non thread-safe SimpleDateFormat
chegar
parents: 5506
diff changeset
    64
                 df.setTimeZone(gmtTZ);
6aed6c9c974d 6967684: httpserver using a non thread-safe SimpleDateFormat
chegar
parents: 5506
diff changeset
    65
                 return df;
6aed6c9c974d 6967684: httpserver using a non thread-safe SimpleDateFormat
chegar
parents: 5506
diff changeset
    66
         }
6aed6c9c974d 6967684: httpserver using a non thread-safe SimpleDateFormat
chegar
parents: 5506
diff changeset
    67
     };
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
5460
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
    69
    private static final String HEAD = "HEAD";
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
    70
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    /* streams which take care of the HTTP protocol framing
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
     * and are passed up to higher layers
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    InputStream uis;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    OutputStream uos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    LeftOverInputStream uis_orig; // uis may have be a user supplied wrapper
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    PlaceholderOutputStream uos_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
    boolean sentHeaders; /* true after response headers sent */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    Map<String,Object> attributes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    int rcode = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    HttpPrincipal principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    ServerImpl server;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    ExchangeImpl (
1511
65ddd8f149f3 6756771: com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig
chegar
parents: 2
diff changeset
    86
        String m, URI u, Request req, long len, HttpConnection connection
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    ) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
        this.req = req;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
        this.reqHdrs = req.headers();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
        this.rspHdrs = new Headers();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        this.method = m;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
        this.uri = u;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
        this.connection = connection;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        this.reqContentLen = len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
        /* ros only used for headers, body written directly to stream */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        this.ros = req.outputStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
        this.ris = req.inputStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
        server = getServerImpl();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
        server.startExchange();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    public Headers getRequestHeaders () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
        return new UnmodifiableHeaders (reqHdrs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
    public Headers getResponseHeaders () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        return rspHdrs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    public URI getRequestURI () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
        return uri;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
    public String getRequestMethod (){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
        return method;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
    public HttpContextImpl getHttpContext (){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        return connection.getHttpContext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
5460
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   122
    private boolean isHeadRequest() {
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   123
        return HEAD.equals(getRequestMethod());
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   124
    }
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   125
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    public void close () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
        if (closed) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
        closed = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
        /* close the underlying connection if,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
         * a) the streams not set up yet, no response can be sent, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
         * b) if the wrapper output stream is not set up, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
         * c) if the close of the input/outpu stream fails
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
            if (uis_orig == null || uos == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
                connection.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
            if (!uos_orig.isWrapped()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
                connection.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
            if (!uis_orig.isClosed()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
                uis_orig.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
            uos.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
            connection.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
    public InputStream getRequestBody () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
        if (uis != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            return uis;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
        }
1511
65ddd8f149f3 6756771: com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig
chegar
parents: 2
diff changeset
   159
        if (reqContentLen == -1L) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
            uis_orig = new ChunkedInputStream (this, ris);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            uis = uis_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
            uis_orig = new FixedLengthInputStream (this, ris, reqContentLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
            uis = uis_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
        return uis;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
    LeftOverInputStream getOriginalInputStream () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        return uis_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
    public int getResponseCode () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
        return rcode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
    public OutputStream getResponseBody () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
        /* TODO. Change spec to remove restriction below. Filters
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
         * cannot work with this restriction
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
         * if (!sentHeaders) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
         *    throw new IllegalStateException ("headers not sent");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
         * }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
        if (uos == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
            uos_orig = new PlaceholderOutputStream (null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
            uos = uos_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
        return uos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
    /* returns the place holder stream, which is the stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
     * returned from the 1st call to getResponseBody()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
     * The "real" ouputstream is then placed inside this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    PlaceholderOutputStream getPlaceholderResponseBody () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        getResponseBody();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        return uos_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
    public void sendResponseHeaders (int rCode, long contentLen)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
    throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        if (sentHeaders) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
            throw new IOException ("headers already sent");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        this.rcode = rCode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        String statusLine = "HTTP/1.1 "+rCode+Code.msg(rCode)+"\r\n";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
        OutputStream tmpout = new BufferedOutputStream (ros);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
        PlaceholderOutputStream o = getPlaceholderResponseBody();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
        tmpout.write (bytes(statusLine, 0), 0, statusLine.length());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        boolean noContentToSend = false; // assume there is content
52023
d0c04d180a3b 8211420: com.sun.net.httpserver.HttpServer returns Content-length header for 204 response code
michaelm
parents: 50681
diff changeset
   214
        boolean noContentLengthHeader = false; // must not send Content-length is set
6003
6aed6c9c974d 6967684: httpserver using a non thread-safe SimpleDateFormat
chegar
parents: 5506
diff changeset
   215
        rspHdrs.set ("Date", dateFormat.get().format (new Date()));
4047
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   216
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   217
        /* check for response type that is not allowed to send a body */
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   218
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   219
        if ((rCode>=100 && rCode <200) /* informational */
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   220
            ||(rCode == 204)           /* no content */
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   221
            ||(rCode == 304))          /* not modified */
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   222
        {
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   223
            if (contentLen != -1) {
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   224
                Logger logger = server.getLogger();
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   225
                String msg = "sendResponseHeaders: rCode = "+ rCode
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   226
                    + ": forcing contentLen = -1";
41592
855537e5ad9c 8157965: update httpserver logging to use java.lang.System.Logger
dfuchs
parents: 25859
diff changeset
   227
                logger.log (Level.WARNING, msg);
4047
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   228
            }
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   229
            contentLen = -1;
52023
d0c04d180a3b 8211420: com.sun.net.httpserver.HttpServer returns Content-length header for 204 response code
michaelm
parents: 50681
diff changeset
   230
            noContentLengthHeader = (rCode != 304);
4047
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   231
        }
5460
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   232
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 47216
diff changeset
   233
        if (isHeadRequest() || rCode == 304) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 47216
diff changeset
   234
            /* HEAD requests or 304 responses should not set a content length by passing it
5460
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   235
             * through this API, but should instead manually set the required
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   236
             * headers.*/
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   237
            if (contentLen >= 0) {
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   238
                final Logger logger = server.getLogger();
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   239
                String msg =
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   240
                    "sendResponseHeaders: being invoked with a content length for a HEAD request";
41592
855537e5ad9c 8157965: update httpserver logging to use java.lang.System.Logger
dfuchs
parents: 25859
diff changeset
   241
                logger.log (Level.WARNING, msg);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
            }
5460
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   243
            noContentToSend = true;
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   244
            contentLen = 0;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 47216
diff changeset
   245
        } else { /* not a HEAD request or 304 response */
5460
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   246
            if (contentLen == 0) {
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   247
                if (http10) {
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   248
                    o.setWrappedStream (new UndefLengthOutputStream (this, ros));
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   249
                    close = true;
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   250
                } else {
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   251
                    rspHdrs.set ("Transfer-encoding", "chunked");
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   252
                    o.setWrappedStream (new ChunkedOutputStream (this, ros));
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   253
                }
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   254
            } else {
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   255
                if (contentLen == -1) {
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   256
                    noContentToSend = true;
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   257
                    contentLen = 0;
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   258
                }
52196
420445d16008 8211437: java.net.http.HttpClient hangs on 204 reply without Content-length 0
michaelm
parents: 52023
diff changeset
   259
                if (!noContentLengthHeader) {
52023
d0c04d180a3b 8211420: com.sun.net.httpserver.HttpServer returns Content-length header for 204 response code
michaelm
parents: 50681
diff changeset
   260
                    rspHdrs.set("Content-length", Long.toString(contentLen));
d0c04d180a3b 8211420: com.sun.net.httpserver.HttpServer returns Content-length header for 204 response code
michaelm
parents: 50681
diff changeset
   261
                }
5460
0682ab146d05 6886723: light weight http server doesn't return correct status code for HEAD requests
chegar
parents: 4047
diff changeset
   262
                o.setWrappedStream (new FixedLengthOutputStream (this, ros, contentLen));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        }
53720
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   265
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   266
        // A custom handler can request that the connection be
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   267
        // closed after the exchange by supplying Connection: close
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   268
        // to the response header. Nothing to do if the exchange is
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   269
        // already set up to be closed.
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   270
        if (!close) {
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   271
            Stream<String> conheader =
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   272
                    Optional.ofNullable(rspHdrs.get("Connection"))
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   273
                    .map(List::stream).orElse(Stream.empty());
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   274
            if (conheader.anyMatch("close"::equalsIgnoreCase)) {
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   275
                Logger logger = server.getLogger();
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   276
                logger.log (Level.DEBUG, "Connection: close requested by handler");
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   277
                close = true;
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   278
            }
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   279
        }
3e451bff6f7f 8218554: HttpServer: allow custom handlers to request that the connection be closed after the exchange.
dfuchs
parents: 52196
diff changeset
   280
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        write (rspHdrs, tmpout);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        this.rspContentLen = contentLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
        tmpout.flush() ;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        tmpout = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
        sentHeaders = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
        if (noContentToSend) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
            WriteFinishedEvent e = new WriteFinishedEvent (this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
            server.addEvent (e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
            closed = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        server.logReply (rCode, req.requestLine(), null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
    void write (Headers map, OutputStream os) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
        Set<Map.Entry<String,List<String>>> entries = map.entrySet();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        for (Map.Entry<String,List<String>> entry : entries) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            String key = entry.getKey();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
            byte[] buf;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
            List<String> values = entry.getValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
            for (String val : values) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
                int i = key.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
                buf = bytes (key, 2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
                buf[i++] = ':';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
                buf[i++] = ' ';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
                os.write (buf, 0, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
                buf = bytes (val, 2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
                i = val.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
                buf[i++] = '\r';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
                buf[i++] = '\n';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
                os.write (buf, 0, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        os.write ('\r');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        os.write ('\n');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
    private byte[] rspbuf = new byte [128]; // used by bytes()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
     * convert string to byte[], using rspbuf
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
     * Make sure that at least "extra" bytes are free at end
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
     * of rspbuf. Reallocate rspbuf if not big enough.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
     * caller must check return value to see if rspbuf moved
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
    private byte[] bytes (String s, int extra) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
        int slen = s.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
        if (slen+extra > rspbuf.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
            int diff = slen + extra - rspbuf.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
            rspbuf = new byte [2* (rspbuf.length + diff)];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
        char c[] = s.toCharArray();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        for (int i=0; i<c.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
            rspbuf[i] = (byte)c[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
        return rspbuf;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
    public InetSocketAddress getRemoteAddress (){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
        Socket s = connection.getChannel().socket();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
        InetAddress ia = s.getInetAddress();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
        int port = s.getPort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
        return new InetSocketAddress (ia, port);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
    public InetSocketAddress getLocalAddress (){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
        Socket s = connection.getChannel().socket();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
        InetAddress ia = s.getLocalAddress();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        int port = s.getLocalPort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
        return new InetSocketAddress (ia, port);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
    public String getProtocol (){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
        String reqline = req.requestLine();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
        int index = reqline.lastIndexOf (' ');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
        return reqline.substring (index+1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
    public SSLSession getSSLSession () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
        SSLEngine e = connection.getSSLEngine();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        if (e == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        return e.getSession();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
    public Object getAttribute (String name) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
        if (name == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
            throw new NullPointerException ("null name parameter");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
        if (attributes == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
            attributes = getHttpContext().getAttributes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        return attributes.get (name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
    public void setAttribute (String name, Object value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
        if (name == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            throw new NullPointerException ("null name parameter");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        if (attributes == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
            attributes = getHttpContext().getAttributes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
        attributes.put (name, value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
    public void setStreams (InputStream i, OutputStream o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        assert uis != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
        if (i != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
            uis = i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
        if (o != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
            uos = o;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
     * PP
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
    HttpConnection getConnection () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        return connection;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
    ServerImpl getServerImpl () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        return getHttpContext().getServerImpl();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
    public HttpPrincipal getPrincipal () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
        return principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
    void setPrincipal (HttpPrincipal principal) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
        this.principal = principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
    static ExchangeImpl get (HttpExchange t) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
        if (t instanceof HttpExchangeImpl) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
            return ((HttpExchangeImpl)t).getExchangeImpl();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
            assert t instanceof HttpsExchangeImpl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
            return ((HttpsExchangeImpl)t).getExchangeImpl();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
 * An OutputStream which wraps another stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
 * which is supplied either at creation time, or sometime later.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
 * If a caller/user tries to write to this stream before
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
 * the wrapped stream has been provided, then an IOException will
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
 * be thrown.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
class PlaceholderOutputStream extends java.io.OutputStream {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
    OutputStream wrapped;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
    PlaceholderOutputStream (OutputStream os) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        wrapped = os;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
    void setWrappedStream (OutputStream os) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
        wrapped = os;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
    boolean isWrapped () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
        return wrapped != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
    private void checkWrap () throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
        if (wrapped == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
            throw new IOException ("response headers not sent yet");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
    public void write(int b) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
        checkWrap();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
        wrapped.write (b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
    public void write(byte b[]) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
        checkWrap();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
        wrapped.write (b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
    public void write(byte b[], int off, int len) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
        checkWrap();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
        wrapped.write (b, off, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
    public void flush() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
        checkWrap();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
        wrapped.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
    public void close() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
        checkWrap();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
        wrapped.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
}