jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java
author michaelm
Thu, 15 Oct 2009 12:03:31 +0100
changeset 4047 f5dcf30f9206
parent 1639 a97859015238
child 5460 0682ab146d05
permissions -rw-r--r--
6886436: Lightwight HTTP Container (com.sun.* package) is unstable Reviewed-by: chegar
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
1639
a97859015238 6785258: Update copyright year
xdono
parents: 1511
diff changeset
     2
 * Copyright 2005-2008 Sun Microsystems, Inc.  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
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
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
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
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.nio.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.nio.channels.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.net.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import javax.net.ssl.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.util.*;
4047
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
    34
import java.util.logging.Logger;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.text.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import sun.net.www.MessageHeader;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import com.sun.net.httpserver.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import com.sun.net.httpserver.spi.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
class ExchangeImpl {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
    Headers reqHdrs, rspHdrs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
    Request req;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    String method;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    URI uri;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
    HttpConnection connection;
1511
65ddd8f149f3 6756771: com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig
chegar
parents: 2
diff changeset
    47
    long reqContentLen;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
    long rspContentLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
    /* raw streams which access the socket directly */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
    InputStream ris;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
    OutputStream ros;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
    Thread thread;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
    /* close the underlying connection when this exchange finished */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
    boolean close;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
    boolean closed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
    boolean http10 = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
    /* for formatting the Date: header */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
    static TimeZone tz;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
    static DateFormat df;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    static {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
        String pattern = "EEE, dd MMM yyyy HH:mm:ss zzz";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
        tz = TimeZone.getTimeZone ("GMT");
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
        df = new SimpleDateFormat (pattern, Locale.US);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
        df.setTimeZone (tz);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    /* streams which take care of the HTTP protocol framing
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
     * and are passed up to higher layers
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    InputStream uis;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    OutputStream uos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
    LeftOverInputStream uis_orig; // uis may have be a user supplied wrapper
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    PlaceholderOutputStream uos_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    boolean sentHeaders; /* true after response headers sent */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    Map<String,Object> attributes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    int rcode = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
    HttpPrincipal principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    ServerImpl server;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    ExchangeImpl (
1511
65ddd8f149f3 6756771: com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig
chegar
parents: 2
diff changeset
    83
        String m, URI u, Request req, long len, HttpConnection connection
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    ) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
        this.req = req;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
        this.reqHdrs = req.headers();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
        this.rspHdrs = new Headers();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
        this.method = m;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
        this.uri = u;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
        this.connection = connection;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        this.reqContentLen = len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
        /* ros only used for headers, body written directly to stream */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
        this.ros = req.outputStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        this.ris = req.inputStream();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
        server = getServerImpl();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        server.startExchange();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    public Headers getRequestHeaders () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
        return new UnmodifiableHeaders (reqHdrs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    public Headers getResponseHeaders () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        return rspHdrs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
    public URI getRequestURI () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
        return uri;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    public String getRequestMethod (){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
        return method;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    public HttpContextImpl getHttpContext (){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
        return connection.getHttpContext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
    public void close () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
        if (closed) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
        closed = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
        /* close the underlying connection if,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
         * a) the streams not set up yet, no response can be sent, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
         * b) if the wrapper output stream is not set up, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
         * c) if the close of the input/outpu stream fails
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
            if (uis_orig == null || uos == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
                connection.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
            if (!uos_orig.isWrapped()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
                connection.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
            if (!uis_orig.isClosed()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                uis_orig.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
            uos.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
            connection.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
    public InputStream getRequestBody () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
        if (uis != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
            return uis;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
        }
1511
65ddd8f149f3 6756771: com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig
chegar
parents: 2
diff changeset
   152
        if (reqContentLen == -1L) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
            uis_orig = new ChunkedInputStream (this, ris);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
            uis = uis_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
            uis_orig = new FixedLengthInputStream (this, ris, reqContentLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            uis = uis_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
        return uis;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
    LeftOverInputStream getOriginalInputStream () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        return uis_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
    public int getResponseCode () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
        return rcode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
    public OutputStream getResponseBody () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        /* TODO. Change spec to remove restriction below. Filters
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
         * cannot work with this restriction
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
         * if (!sentHeaders) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
         *    throw new IllegalStateException ("headers not sent");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
         * }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
        if (uos == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
            uos_orig = new PlaceholderOutputStream (null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
            uos = uos_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
        return uos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
    /* returns the place holder stream, which is the stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
     * returned from the 1st call to getResponseBody()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
     * The "real" ouputstream is then placed inside this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
    PlaceholderOutputStream getPlaceholderResponseBody () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
        getResponseBody();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        return uos_orig;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
    public void sendResponseHeaders (int rCode, long contentLen)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
    throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        if (sentHeaders) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
            throw new IOException ("headers already sent");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
        this.rcode = rCode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
        String statusLine = "HTTP/1.1 "+rCode+Code.msg(rCode)+"\r\n";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
        OutputStream tmpout = new BufferedOutputStream (ros);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
        PlaceholderOutputStream o = getPlaceholderResponseBody();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        tmpout.write (bytes(statusLine, 0), 0, statusLine.length());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        boolean noContentToSend = false; // assume there is content
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        rspHdrs.set ("Date", df.format (new Date()));
4047
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   208
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   209
        /* 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
   210
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   211
        if ((rCode>=100 && rCode <200) /* informational */
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   212
            ||(rCode == 204)           /* no content */
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   213
            ||(rCode == 304))          /* not modified */
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   214
        {
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   215
            if (contentLen != -1) {
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   216
                Logger logger = server.getLogger();
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   217
                String msg = "sendResponseHeaders: rCode = "+ rCode
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   218
                    + ": forcing contentLen = -1";
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   219
                logger.warning (msg);
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   220
            }
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   221
            contentLen = -1;
f5dcf30f9206 6886436: Lightwight HTTP Container (com.sun.* package) is unstable
michaelm
parents: 1639
diff changeset
   222
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
        if (contentLen == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
            if (http10) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                o.setWrappedStream (new UndefLengthOutputStream (this, ros));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                close = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
                rspHdrs.set ("Transfer-encoding", "chunked");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
                o.setWrappedStream (new ChunkedOutputStream (this, ros));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
            if (contentLen == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
                noContentToSend = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
                contentLen = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
            /* content len might already be set, eg to implement HEAD resp */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
            if (rspHdrs.getFirst ("Content-length") == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
                rspHdrs.set ("Content-length", Long.toString(contentLen));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
            o.setWrappedStream (new FixedLengthOutputStream (this, ros, contentLen));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        write (rspHdrs, tmpout);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
        this.rspContentLen = contentLen;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
        tmpout.flush() ;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
        tmpout = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
        sentHeaders = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
        if (noContentToSend) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
            WriteFinishedEvent e = new WriteFinishedEvent (this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
            server.addEvent (e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
            closed = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        server.logReply (rCode, req.requestLine(), null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    void write (Headers map, OutputStream os) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
        Set<Map.Entry<String,List<String>>> entries = map.entrySet();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        for (Map.Entry<String,List<String>> entry : entries) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
            String key = entry.getKey();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
            byte[] buf;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
            List<String> values = entry.getValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
            for (String val : values) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
                int i = key.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
                buf = bytes (key, 2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
                buf[i++] = ':';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
                buf[i++] = ' ';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
                os.write (buf, 0, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
                buf = bytes (val, 2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
                i = val.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
                buf[i++] = '\r';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
                buf[i++] = '\n';
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
                os.write (buf, 0, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
        os.write ('\r');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
        os.write ('\n');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
    private byte[] rspbuf = new byte [128]; // used by bytes()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
     * convert string to byte[], using rspbuf
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
     * Make sure that at least "extra" bytes are free at end
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
     * of rspbuf. Reallocate rspbuf if not big enough.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
     * caller must check return value to see if rspbuf moved
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
    private byte[] bytes (String s, int extra) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
        int slen = s.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
        if (slen+extra > rspbuf.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
            int diff = slen + extra - rspbuf.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
            rspbuf = new byte [2* (rspbuf.length + diff)];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        char c[] = s.toCharArray();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
        for (int i=0; i<c.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
            rspbuf[i] = (byte)c[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        return rspbuf;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
    public InetSocketAddress getRemoteAddress (){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
        Socket s = connection.getChannel().socket();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        InetAddress ia = s.getInetAddress();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
        int port = s.getPort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
        return new InetSocketAddress (ia, port);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
    public InetSocketAddress getLocalAddress (){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        Socket s = connection.getChannel().socket();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        InetAddress ia = s.getLocalAddress();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        int port = s.getLocalPort();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        return new InetSocketAddress (ia, port);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
    public String getProtocol (){
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        String reqline = req.requestLine();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        int index = reqline.lastIndexOf (' ');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        return reqline.substring (index+1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
    public SSLSession getSSLSession () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
        SSLEngine e = connection.getSSLEngine();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        if (e == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        return e.getSession();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
    public Object getAttribute (String name) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
        if (name == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
            throw new NullPointerException ("null name parameter");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
        if (attributes == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
            attributes = getHttpContext().getAttributes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        return attributes.get (name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
    public void setAttribute (String name, Object value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
        if (name == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
            throw new NullPointerException ("null name parameter");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
        if (attributes == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
            attributes = getHttpContext().getAttributes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
        attributes.put (name, value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
    public void setStreams (InputStream i, OutputStream o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        assert uis != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
        if (i != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
            uis = i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
        if (o != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
            uos = o;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
     * PP
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
    HttpConnection getConnection () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        return connection;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
    ServerImpl getServerImpl () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
        return getHttpContext().getServerImpl();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
    public HttpPrincipal getPrincipal () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        return principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
    void setPrincipal (HttpPrincipal principal) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        this.principal = principal;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
    static ExchangeImpl get (HttpExchange t) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
        if (t instanceof HttpExchangeImpl) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            return ((HttpExchangeImpl)t).getExchangeImpl();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
            assert t instanceof HttpsExchangeImpl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
            return ((HttpsExchangeImpl)t).getExchangeImpl();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
 * An OutputStream which wraps another stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
 * which is supplied either at creation time, or sometime later.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
 * If a caller/user tries to write to this stream before
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
 * the wrapped stream has been provided, then an IOException will
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
 * be thrown.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
class PlaceholderOutputStream extends java.io.OutputStream {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
    OutputStream wrapped;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
    PlaceholderOutputStream (OutputStream os) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        wrapped = os;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    void setWrappedStream (OutputStream os) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        wrapped = os;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
    boolean isWrapped () {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
        return wrapped != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
    private void checkWrap () throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
        if (wrapped == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
            throw new IOException ("response headers not sent yet");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
    public void write(int b) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
        checkWrap();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        wrapped.write (b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
    public void write(byte b[]) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
        checkWrap();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        wrapped.write (b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
    public void write(byte b[], int off, int len) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
        checkWrap();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
        wrapped.write (b, off, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
    public void flush() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
        checkWrap();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
        wrapped.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
    public void close() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
        checkWrap();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        wrapped.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
}