< prev index next >

src/java.base/share/classes/sun/net/www/http/ChunkedInputStream.java

Print this page




  61     private MessageHeader responses;
  62 
  63     /**
  64      * The size, in bytes, of the chunk that is currently being read.
  65      * This size is only valid if the current position in the underlying
  66      * input stream is inside a chunk (ie: state == STATE_READING_CHUNK).
  67      */
  68     private int chunkSize;
  69 
  70     /**
  71      * The number of bytes read from the underlying stream for the current
  72      * chunk. This value is always in the range <code>0</code> through to
  73      * <code>chunkSize</code>
  74      */
  75     private int chunkRead;
  76 
  77     /**
  78      * The internal buffer array where chunk data is available for the
  79      * application to read.
  80      */
  81     private byte chunkData[] = new byte[4096];
  82 
  83     /**
  84      * The current position in the buffer. It contains the index
  85      * of the next byte to read from <code>chunkData</code>
  86      */
  87     private int chunkPos;
  88 
  89     /**
  90      * The index one greater than the index of the last valid byte in the
  91      * buffer. This value is always in the range <code>0</code> through
  92      * <code>chunkData.length</code>.
  93      */
  94     private int chunkCount;
  95 
  96     /**
  97      * The internal buffer where bytes from the underlying stream can be
  98      * read. It may contain bytes representing chunk-size, chunk-data, or
  99      * trailer fields.
 100      */
 101     private byte rawData[] = new byte[32];
 102 
 103     /**
 104      * The current position in the buffer. It contains the index
 105      * of the next byte to read from <code>rawData</code>
 106      */
 107     private int rawPos;
 108 
 109     /**
 110      * The index one greater than the index of the last valid byte in the
 111      * buffer. This value is always in the range <code>0</code> through
 112      * <code>rawData.length</code>.
 113      */
 114     private int rawCount;
 115 
 116     /**
 117      * Indicates if an error was encountered when processing the chunked
 118      * stream.
 119      */
 120     private boolean error;
 121 


 169     /**
 170      * Check to make sure that this stream has not been closed.
 171      */
 172     private void ensureOpen() throws IOException {
 173         if (closed) {
 174             throw new IOException("stream is closed");
 175         }
 176     }
 177 
 178 
 179     /**
 180      * Ensures there is <code>size</code> bytes available in
 181      * <code>rawData</code>. This requires that we either
 182      * shift the bytes in use to the begining of the buffer
 183      * or allocate a large buffer with sufficient space available.
 184      */
 185     private void ensureRawAvailable(int size) {
 186         if (rawCount + size > rawData.length) {
 187             int used = rawCount - rawPos;
 188             if (used + size > rawData.length) {
 189                 byte tmp[] = new byte[used + size];
 190                 if (used > 0) {
 191                     System.arraycopy(rawData, rawPos, tmp, 0, used);
 192                 }
 193                 rawData = tmp;
 194             } else {
 195                 if (used > 0) {
 196                     System.arraycopy(rawData, rawPos, rawData, 0, used);
 197                 }
 198             }
 199             rawCount = used;
 200             rawPos = 0;
 201         }
 202     }
 203 
 204 
 205     /**
 206      * Close the underlying input stream by either returning it to the
 207      * keep alive cache or closing the stream.
 208      * <p>
 209      * As a chunked stream is inheritly persistent (see HTTP 1.1 RFC) the


 343                  * total read from the underlying stream to date.
 344                  */
 345                 case STATE_READING_CHUNK :
 346                     /* no data available yet */
 347                     if (rawPos >= rawCount) {
 348                         return;
 349                     }
 350 
 351                     /*
 352                      * Compute the number of bytes of chunk data available in the
 353                      * raw buffer.
 354                      */
 355                     int copyLen = Math.min( chunkSize-chunkRead, rawCount-rawPos );
 356 
 357                     /*
 358                      * Expand or compact chunkData if needed.
 359                      */
 360                     if (chunkData.length < chunkCount + copyLen) {
 361                         int cnt = chunkCount - chunkPos;
 362                         if (chunkData.length < cnt + copyLen) {
 363                             byte tmp[] = new byte[cnt + copyLen];
 364                             System.arraycopy(chunkData, chunkPos, tmp, 0, cnt);
 365                             chunkData = tmp;
 366                         } else {
 367                             System.arraycopy(chunkData, chunkPos, chunkData, 0, cnt);
 368                         }
 369                         chunkPos = 0;
 370                         chunkCount = cnt;
 371                     }
 372 
 373                     /*
 374                      * Copy the chunk data into chunkData so that it's available
 375                      * to the read methods.
 376                      */
 377                     System.arraycopy(rawData, rawPos, chunkData, chunkCount, copyLen);
 378                     rawPos += copyLen;
 379                     chunkCount += copyLen;
 380                     chunkRead += copyLen;
 381 
 382                     /*
 383                      * If all the chunk has been copied into chunkData then the next


 650         if (chunkPos >= chunkCount) {
 651             if (readAhead(true) <= 0) {
 652                 return -1;
 653             }
 654         }
 655         return chunkData[chunkPos++] & 0xff;
 656     }
 657 
 658 
 659     /**
 660      * Reads bytes from this stream into the specified byte array, starting at
 661      * the given offset.
 662      *
 663      * @param      b     destination buffer.
 664      * @param      off   offset at which to start storing bytes.
 665      * @param      len   maximum number of bytes to read.
 666      * @return     the number of bytes read, or <code>-1</code> if the end of
 667      *             the stream has been reached.
 668      * @exception  IOException  if an I/O error occurs.
 669      */
 670     public synchronized int read(byte b[], int off, int len)
 671         throws IOException
 672     {
 673         ensureOpen();
 674         if ((off < 0) || (off > b.length) || (len < 0) ||
 675             ((off + len) > b.length) || ((off + len) < 0)) {
 676             throw new IndexOutOfBoundsException();
 677         } else if (len == 0) {
 678             return 0;
 679         }
 680 
 681         int avail = chunkCount - chunkPos;
 682         if (avail <= 0) {
 683             /*
 684              * Optimization: if we're in the middle of the chunk read
 685              * directly from the underlying stream into the caller's
 686              * buffer
 687              */
 688             if (state == STATE_READING_CHUNK) {
 689                 return fastRead( b, off, len );
 690             }




  61     private MessageHeader responses;
  62 
  63     /**
  64      * The size, in bytes, of the chunk that is currently being read.
  65      * This size is only valid if the current position in the underlying
  66      * input stream is inside a chunk (ie: state == STATE_READING_CHUNK).
  67      */
  68     private int chunkSize;
  69 
  70     /**
  71      * The number of bytes read from the underlying stream for the current
  72      * chunk. This value is always in the range <code>0</code> through to
  73      * <code>chunkSize</code>
  74      */
  75     private int chunkRead;
  76 
  77     /**
  78      * The internal buffer array where chunk data is available for the
  79      * application to read.
  80      */
  81     private byte[] chunkData = new byte[4096];
  82 
  83     /**
  84      * The current position in the buffer. It contains the index
  85      * of the next byte to read from <code>chunkData</code>
  86      */
  87     private int chunkPos;
  88 
  89     /**
  90      * The index one greater than the index of the last valid byte in the
  91      * buffer. This value is always in the range <code>0</code> through
  92      * <code>chunkData.length</code>.
  93      */
  94     private int chunkCount;
  95 
  96     /**
  97      * The internal buffer where bytes from the underlying stream can be
  98      * read. It may contain bytes representing chunk-size, chunk-data, or
  99      * trailer fields.
 100      */
 101     private byte[] rawData = new byte[32];
 102 
 103     /**
 104      * The current position in the buffer. It contains the index
 105      * of the next byte to read from <code>rawData</code>
 106      */
 107     private int rawPos;
 108 
 109     /**
 110      * The index one greater than the index of the last valid byte in the
 111      * buffer. This value is always in the range <code>0</code> through
 112      * <code>rawData.length</code>.
 113      */
 114     private int rawCount;
 115 
 116     /**
 117      * Indicates if an error was encountered when processing the chunked
 118      * stream.
 119      */
 120     private boolean error;
 121 


 169     /**
 170      * Check to make sure that this stream has not been closed.
 171      */
 172     private void ensureOpen() throws IOException {
 173         if (closed) {
 174             throw new IOException("stream is closed");
 175         }
 176     }
 177 
 178 
 179     /**
 180      * Ensures there is <code>size</code> bytes available in
 181      * <code>rawData</code>. This requires that we either
 182      * shift the bytes in use to the begining of the buffer
 183      * or allocate a large buffer with sufficient space available.
 184      */
 185     private void ensureRawAvailable(int size) {
 186         if (rawCount + size > rawData.length) {
 187             int used = rawCount - rawPos;
 188             if (used + size > rawData.length) {
 189                 byte[] tmp = new byte[used + size];
 190                 if (used > 0) {
 191                     System.arraycopy(rawData, rawPos, tmp, 0, used);
 192                 }
 193                 rawData = tmp;
 194             } else {
 195                 if (used > 0) {
 196                     System.arraycopy(rawData, rawPos, rawData, 0, used);
 197                 }
 198             }
 199             rawCount = used;
 200             rawPos = 0;
 201         }
 202     }
 203 
 204 
 205     /**
 206      * Close the underlying input stream by either returning it to the
 207      * keep alive cache or closing the stream.
 208      * <p>
 209      * As a chunked stream is inheritly persistent (see HTTP 1.1 RFC) the


 343                  * total read from the underlying stream to date.
 344                  */
 345                 case STATE_READING_CHUNK :
 346                     /* no data available yet */
 347                     if (rawPos >= rawCount) {
 348                         return;
 349                     }
 350 
 351                     /*
 352                      * Compute the number of bytes of chunk data available in the
 353                      * raw buffer.
 354                      */
 355                     int copyLen = Math.min( chunkSize-chunkRead, rawCount-rawPos );
 356 
 357                     /*
 358                      * Expand or compact chunkData if needed.
 359                      */
 360                     if (chunkData.length < chunkCount + copyLen) {
 361                         int cnt = chunkCount - chunkPos;
 362                         if (chunkData.length < cnt + copyLen) {
 363                             byte[] tmp = new byte[cnt + copyLen];
 364                             System.arraycopy(chunkData, chunkPos, tmp, 0, cnt);
 365                             chunkData = tmp;
 366                         } else {
 367                             System.arraycopy(chunkData, chunkPos, chunkData, 0, cnt);
 368                         }
 369                         chunkPos = 0;
 370                         chunkCount = cnt;
 371                     }
 372 
 373                     /*
 374                      * Copy the chunk data into chunkData so that it's available
 375                      * to the read methods.
 376                      */
 377                     System.arraycopy(rawData, rawPos, chunkData, chunkCount, copyLen);
 378                     rawPos += copyLen;
 379                     chunkCount += copyLen;
 380                     chunkRead += copyLen;
 381 
 382                     /*
 383                      * If all the chunk has been copied into chunkData then the next


 650         if (chunkPos >= chunkCount) {
 651             if (readAhead(true) <= 0) {
 652                 return -1;
 653             }
 654         }
 655         return chunkData[chunkPos++] & 0xff;
 656     }
 657 
 658 
 659     /**
 660      * Reads bytes from this stream into the specified byte array, starting at
 661      * the given offset.
 662      *
 663      * @param      b     destination buffer.
 664      * @param      off   offset at which to start storing bytes.
 665      * @param      len   maximum number of bytes to read.
 666      * @return     the number of bytes read, or <code>-1</code> if the end of
 667      *             the stream has been reached.
 668      * @exception  IOException  if an I/O error occurs.
 669      */
 670     public synchronized int read(byte[] b, int off, int len)
 671         throws IOException
 672     {
 673         ensureOpen();
 674         if ((off < 0) || (off > b.length) || (len < 0) ||
 675             ((off + len) > b.length) || ((off + len) < 0)) {
 676             throw new IndexOutOfBoundsException();
 677         } else if (len == 0) {
 678             return 0;
 679         }
 680 
 681         int avail = chunkCount - chunkPos;
 682         if (avail <= 0) {
 683             /*
 684              * Optimization: if we're in the middle of the chunk read
 685              * directly from the underlying stream into the caller's
 686              * buffer
 687              */
 688             if (state == STATE_READING_CHUNK) {
 689                 return fastRead( b, off, len );
 690             }


< prev index next >