src/java.base/share/classes/sun/net/www/http/ChunkedOutputStream.java
author dfuchs
Fri, 30 Aug 2019 15:42:27 +0100
branchJDK-8229867-branch
changeset 57968 8595871a5446
parent 47216 71c04702a3d5
permissions -rw-r--r--
JDK-8229867: first prototype
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
     2
 * Copyright (c) 2004, 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: 1635
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: 1635
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: 1635
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1635
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1635
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
package sun.net.www.http;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
import java.io.*;
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
    28
import java.util.concurrent.locks.Lock;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
    29
import java.util.concurrent.locks.ReentrantLock;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
 * OutputStream that sends the output to the underlying stream using chunked
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
 * encoding as specified in RFC 2068.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
public class ChunkedOutputStream extends PrintStream {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
    /* Default chunk size (including chunk header) if not specified */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
    static final int DEFAULT_CHUNK_SIZE = 4096;
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    39
    private static final byte[] CRLF = {'\r', '\n'};
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    40
    private static final int CRLF_SIZE = CRLF.length;
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    41
    private static final byte[] FOOTER = CRLF;
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    42
    private static final int FOOTER_SIZE = CRLF_SIZE;
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    43
    private static final byte[] EMPTY_CHUNK_HEADER = getHeader(0);
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    44
    private static final int EMPTY_CHUNK_HEADER_SIZE = getHeaderSize(0);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
    /* internal buffer */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
    private byte buf[];
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    48
    /* size of data (excluding footers and headers) already stored in buf */
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    49
    private int size;
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    50
    /* current index in buf (i.e. buf[count] */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
    private int count;
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    52
    /* number of bytes to be filled up to complete a data chunk
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    53
     * currently being built */
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    54
    private int spaceInCurrentChunk;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
    /* underlying stream */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
    private PrintStream out;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
    /* the chunk size we use */
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    60
    private int preferredChunkDataSize;
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    61
    private int preferedHeaderSize;
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    62
    private int preferredChunkGrossSize;
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    63
    /* header for a complete Chunk */
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    64
    private byte[] completeHeader;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
    66
    private final Lock writeLock = new ReentrantLock();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
    67
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    /* return the size of the header for a particular chunk size */
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    69
    private static int getHeaderSize(int size) {
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    70
        return (Integer.toHexString(size)).length() + CRLF_SIZE;
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    71
    }
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    72
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    73
    /* return a header for a particular chunk size */
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    74
    private static byte[] getHeader(int size){
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    75
        try {
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    76
            String hexStr =  Integer.toHexString(size);
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    77
            byte[] hexBytes = hexStr.getBytes("US-ASCII");
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    78
            byte[] header = new byte[getHeaderSize(size)];
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    79
            for (int i=0; i<hexBytes.length; i++)
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    80
                header[i] = hexBytes[i];
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    81
            header[hexBytes.length] = CRLF[0];
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    82
            header[hexBytes.length+1] = CRLF[1];
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    83
            return header;
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    84
        } catch (java.io.UnsupportedEncodingException e) {
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    85
            /* This should never happen */
10419
12c063b39232 7084245: Update usages of InternalError to use exception chaining
sherman
parents: 5506
diff changeset
    86
            throw new InternalError(e.getMessage(), e);
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
    87
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    public ChunkedOutputStream(PrintStream o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        this(o, DEFAULT_CHUNK_SIZE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    public ChunkedOutputStream(PrintStream o, int size) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
        super(o);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        out = o;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
        if (size <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
            size = DEFAULT_CHUNK_SIZE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
        }
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   101
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
        /* Adjust the size to cater for the chunk header - eg: if the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
         * preferred chunk size is 1k this means the chunk size should
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   104
         * be 1017 bytes (differs by 7 from preferred size because of
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   105
         * 3 bytes for chunk size in hex and CRLF (header) and CRLF (footer)).
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   106
         *
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   107
         * If headerSize(adjusted_size) is shorter then headerSize(size)
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   108
         * then try to use the extra byte unless headerSize(adjusted_size+1)
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   109
         * increases back to headerSize(size)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
        if (size > 0) {
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   112
            int adjusted_size = size - getHeaderSize(size) - FOOTER_SIZE;
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   113
            if (getHeaderSize(adjusted_size+1) < getHeaderSize(size)){
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
                adjusted_size++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
            size = adjusted_size;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        if (size > 0) {
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   120
            preferredChunkDataSize = size;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
        } else {
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   122
            preferredChunkDataSize = DEFAULT_CHUNK_SIZE -
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   123
                    getHeaderSize(DEFAULT_CHUNK_SIZE) - FOOTER_SIZE;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   126
        preferedHeaderSize = getHeaderSize(preferredChunkDataSize);
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   127
        preferredChunkGrossSize = preferedHeaderSize + preferredChunkDataSize
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   128
                + FOOTER_SIZE;
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   129
        completeHeader = getHeader(preferredChunkDataSize);
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   130
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
        /* start with an initial buffer */
18173
cf70549231af 8015421: NegativeArraySizeException occurs in ChunkedOutputStream() with Integer.MAX_VALUE
khazra
parents: 14342
diff changeset
   132
        buf = new byte[preferredChunkGrossSize];
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   133
        reset();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
    /*
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   137
     * Flush a buffered, completed chunk to an underlying stream. If the data in
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   138
     * the buffer is insufficient to build up a chunk of "preferredChunkSize"
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   139
     * then the data do not get flushed unless flushAll is true. If flushAll is
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   140
     * true then the remaining data builds up a last chunk which size is smaller
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   141
     * than preferredChunkSize, and then the last chunk gets flushed to
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   142
     * underlying stream. If flushAll is true and there is no data in a buffer
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   143
     * at all then an empty chunk (containing a header only) gets flushed to
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   144
     * underlying stream.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
     */
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   146
     private void flush(boolean flushAll) {
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   147
        if (spaceInCurrentChunk == 0) {
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   148
            /* flush a completed chunk to underlying stream */
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   149
            out.write(buf, 0, preferredChunkGrossSize);
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   150
            out.flush();
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   151
            reset();
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   152
        } else if (flushAll){
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   153
            /* complete the last chunk and flush it to underlying stream */
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   154
            if (size > 0){
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   155
                /* adjust a header start index in case the header of the last
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   156
                 * chunk is shorter then preferedHeaderSize */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   158
                int adjustedHeaderStartIndex = preferedHeaderSize -
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   159
                        getHeaderSize(size);
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   160
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   161
                /* write header */
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   162
                System.arraycopy(getHeader(size), 0, buf,
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   163
                        adjustedHeaderStartIndex, getHeaderSize(size));
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   164
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   165
                /* write footer */
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   166
                buf[count++] = FOOTER[0];
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   167
                buf[count++] = FOOTER[1];
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   168
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   169
                //send the last chunk to underlying stream
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   170
                out.write(buf, adjustedHeaderStartIndex, count - adjustedHeaderStartIndex);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
            } else {
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   172
                //send an empty chunk (containing just a header) to underlying stream
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   173
                out.write(EMPTY_CHUNK_HEADER, 0, EMPTY_CHUNK_HEADER_SIZE);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
            out.flush();
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   177
            reset();
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   178
         }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   181
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
    public boolean checkError() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
        return out.checkError();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
    /* Check that the output stream is still open */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    private void ensureOpen() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        if (out == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
            setError();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   192
   /*
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   193
    * Writes data from b[] to an internal buffer and stores the data as data
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   194
    * chunks of a following format: {Data length in Hex}{CRLF}{data}{CRLF}
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   195
    * The size of the data is preferredChunkSize. As soon as a completed chunk
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   196
    * is read from b[] a process of reading from b[] suspends, the chunk gets
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   197
    * flushed to the underlying stream and then the reading process from b[]
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   198
    * continues. When there is no more sufficient data in b[] to build up a
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   199
    * chunk of preferredChunkSize size the data get stored as an incomplete
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   200
    * chunk of a following format: {space for data length}{CRLF}{data}
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   201
    * The size of the data is of course smaller than preferredChunkSize.
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   202
    */
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   203
    @Override
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   204
    public void write(byte b[], int off, int len) {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   205
        writeLock.lock();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   206
        try {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   207
            ensureOpen();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   208
            if ((off < 0) || (off > b.length) || (len < 0) ||
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   209
                    ((off + len) > b.length) || ((off + len) < 0)) {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   210
                throw new IndexOutOfBoundsException();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   211
            } else if (len == 0) {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   212
                return;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
            }
88
b2fea49cad6b 6631048: Problem when writing on output stream of HttpURLConnection
chegar
parents: 2
diff changeset
   214
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   215
            /* if b[] contains enough data then one loop cycle creates one complete
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   216
             * data chunk with a header, body and a footer, and then flushes the
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   217
             * chunk to the underlying stream. Otherwise, the last loop cycle
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   218
             * creates incomplete data chunk with empty header and with no footer
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   219
             * and stores this incomplete chunk in an internal buffer buf[]
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   220
             */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   221
            int bytesToWrite = len;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   222
            int inputIndex = off;  /* the index of the byte[] currently being written */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   223
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   224
            do {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   225
                /* enough data to complete a chunk */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   226
                if (bytesToWrite >= spaceInCurrentChunk) {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   227
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   228
                    /* header */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   229
                    for (int i = 0; i < completeHeader.length; i++)
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   230
                        buf[i] = completeHeader[i];
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   231
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   232
                    /* data */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   233
                    System.arraycopy(b, inputIndex, buf, count, spaceInCurrentChunk);
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   234
                    inputIndex += spaceInCurrentChunk;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   235
                    bytesToWrite -= spaceInCurrentChunk;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   236
                    count += spaceInCurrentChunk;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   238
                    /* footer */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   239
                    buf[count++] = FOOTER[0];
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   240
                    buf[count++] = FOOTER[1];
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   241
                    spaceInCurrentChunk = 0; //chunk is complete
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   242
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   243
                    flush(false);
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   244
                    if (checkError()) {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   245
                        break;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   246
                    }
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   247
                }
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   248
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   249
                /* not enough data to build a chunk */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   250
                else {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   251
                    /* header */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   252
                    /* do not write header if not enough bytes to build a chunk yet */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   253
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   254
                    /* data */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   255
                    System.arraycopy(b, inputIndex, buf, count, bytesToWrite);
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   256
                    count += bytesToWrite;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   257
                    size += bytesToWrite;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   258
                    spaceInCurrentChunk -= bytesToWrite;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   259
                    bytesToWrite = 0;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   260
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   261
                    /* footer */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   262
                    /* do not write header if not enough bytes to build a chunk yet */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   263
                }
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   264
            } while (bytesToWrite > 0);
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   265
        } finally {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   266
            writeLock.unlock();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   267
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   270
    @Override
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   271
    public void write(int _b) {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   272
        writeLock.lock();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   273
        try {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   274
            byte b[] = {(byte) _b};
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   275
            write(b, 0, 1);
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   276
        } finally {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   277
            writeLock.unlock();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   278
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   281
    public void reset() {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   282
        writeLock.lock();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   283
        try {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   284
            count = preferedHeaderSize;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   285
            size = 0;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   286
            spaceInCurrentChunk = preferredChunkDataSize;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   287
        } finally {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   288
            writeLock.unlock();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   289
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
    public int size() {
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   293
        return size;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   296
    @Override
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   297
    public void close() {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   298
        writeLock.lock();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   299
        try {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   300
            ensureOpen();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   302
            /* if we have buffer a chunked send it */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   303
            if (size > 0) {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   304
                flush(true);
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   305
            }
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   306
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   307
            /* send a zero length chunk */
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   308
            flush(true);
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   309
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   310
            /* don't close the underlying stream */
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   311
            out = null;
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   312
        } finally {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   313
            writeLock.unlock();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
1635
8ca7ecc0226d 6720866: Slow performance using HttpURLConnection for upload
chegar
parents: 715
diff changeset
   317
    @Override
57968
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   318
    public void flush() {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   319
        writeLock.lock();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   320
        try {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   321
            ensureOpen();
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   322
            if (size > 0) {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   323
                flush(true);
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   324
            }
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   325
        } finally {
8595871a5446 JDK-8229867: first prototype
dfuchs
parents: 47216
diff changeset
   326
            writeLock.unlock();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
}