src/java.base/share/classes/sun/net/www/MeteredStream.java
branchJDK-8229867-branch
changeset 57968 8595871a5446
parent 47216 71c04702a3d5
equal deleted inserted replaced
57966:e89c7aaf2906 57968:8595871a5446
     1 /*
     1 /*
     2  * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package sun.net.www;
    26 package sun.net.www;
    27 
    27 
    28 import java.net.URL;
       
    29 import java.util.*;
       
    30 import java.io.*;
    28 import java.io.*;
       
    29 import java.util.concurrent.locks.ReentrantLock;
    31 import sun.net.ProgressSource;
    30 import sun.net.ProgressSource;
    32 import sun.net.www.http.ChunkedInputStream;
    31 import sun.net.www.http.ChunkedInputStream;
    33 
    32 
    34 
    33 
    35 public class MeteredStream extends FilterInputStream {
    34 public class MeteredStream extends FilterInputStream {
    42     protected long expected;
    41     protected long expected;
    43     protected long count = 0;
    42     protected long count = 0;
    44     protected long markedCount = 0;
    43     protected long markedCount = 0;
    45     protected int markLimit = -1;
    44     protected int markLimit = -1;
    46     protected ProgressSource pi;
    45     protected ProgressSource pi;
       
    46     protected final ReentrantLock readLock = new ReentrantLock();
    47 
    47 
    48     public MeteredStream(InputStream is, ProgressSource pi, long expected)
    48     public MeteredStream(InputStream is, ProgressSource pi, long expected)
    49     {
    49     {
    50         super(is);
    50         super(is);
    51 
    51 
    55         if (pi != null) {
    55         if (pi != null) {
    56             pi.updateProgress(0, expected);
    56             pi.updateProgress(0, expected);
    57         }
    57         }
    58     }
    58     }
    59 
    59 
    60     private final void justRead(long n) throws IOException   {
    60     private final  void justRead(long n) throws IOException   {
       
    61         assert readLock.isHeldByCurrentThread();
       
    62 
    61         if (n == -1) {
    63         if (n == -1) {
    62 
    64 
    63             /*
    65             /*
    64              * don't close automatically when mark is set and is valid;
    66              * don't close automatically when mark is set and is valid;
    65              * cannot reset() after close()
    67              * cannot reset() after close()
    97 
    99 
    98     /**
   100     /**
    99      * Returns true if the mark is valid, false otherwise
   101      * Returns true if the mark is valid, false otherwise
   100      */
   102      */
   101     private boolean isMarked() {
   103     private boolean isMarked() {
       
   104         assert readLock.isHeldByCurrentThread();
   102 
   105 
   103         if (markLimit < 0) {
   106         if (markLimit < 0) {
   104             return false;
   107             return false;
   105         }
   108         }
   106 
   109 
   111 
   114 
   112         // mark still holds
   115         // mark still holds
   113         return true;
   116         return true;
   114     }
   117     }
   115 
   118 
   116     public synchronized int read() throws java.io.IOException {
   119     public int read() throws java.io.IOException {
   117         if (closed) {
   120         if (closed) return -1;
   118             return -1;
   121         readLock.lock();
   119         }
   122         try {
   120         int c = in.read();
   123             if (closed) return -1;
   121         if (c != -1) {
   124             int c = in.read();
   122             justRead(1);
   125             if (c != -1) {
   123         } else {
   126                 justRead(1);
   124             justRead(c);
   127             } else {
   125         }
   128                 justRead(c);
   126         return c;
   129             }
   127     }
   130             return c;
   128 
   131         } finally {
   129     public synchronized int read(byte b[], int off, int len)
   132             readLock.unlock();
       
   133         }
       
   134     }
       
   135 
       
   136     public int read(byte b[], int off, int len)
   130                 throws java.io.IOException {
   137                 throws java.io.IOException {
   131         if (closed) {
   138         if (closed) return -1;
   132             return -1;
   139         readLock.lock();
   133         }
   140         try {
   134         int n = in.read(b, off, len);
   141             if (closed) return -1;
   135         justRead(n);
   142 
   136         return n;
   143             int n = in.read(b, off, len);
   137     }
   144             justRead(n);
   138 
   145             return n;
   139     public synchronized long skip(long n) throws IOException {
   146         } finally {
   140 
   147             readLock.unlock();
   141         // REMIND: what does skip do on EOF????
   148         }
   142         if (closed) {
   149     }
   143             return 0;
   150 
   144         }
   151     public long skip(long n) throws IOException {
   145 
   152 
   146         if (in instanceof ChunkedInputStream) {
   153         if (closed) return 0;
   147             n = in.skip(n);
   154         readLock.lock();
   148         }
   155         try {
   149         else {
   156             // REMIND: what does skip do on EOF????
   150             // just skip min(n, num_bytes_left)
   157             if (closed) return 0;
   151             long min = (n > expected - count) ? expected - count: n;
   158 
   152             n = in.skip(min);
   159             if (in instanceof ChunkedInputStream) {
   153         }
   160                 n = in.skip(n);
   154         justRead(n);
   161             } else {
   155         return n;
   162                 // just skip min(n, num_bytes_left)
       
   163                 long min = (n > expected - count) ? expected - count : n;
       
   164                 n = in.skip(min);
       
   165             }
       
   166             justRead(n);
       
   167             return n;
       
   168         } finally {
       
   169             readLock.unlock();
       
   170         }
   156     }
   171     }
   157 
   172 
   158     public void close() throws IOException {
   173     public void close() throws IOException {
   159         if (closed) {
   174         if (closed) return;
   160             return;
   175         readLock.lock();
   161         }
   176         try {
   162         if (pi != null)
   177             if (closed) return;
   163             pi.finishTracking();
   178             if (pi != null)
   164 
   179                 pi.finishTracking();
   165         closed = true;
   180 
   166         in.close();
   181             closed = true;
   167     }
   182             in.close();
   168 
   183         } finally {
   169     public synchronized int available() throws IOException {
   184             readLock.unlock();
   170         return closed ? 0: in.available();
   185         }
   171     }
   186     }
   172 
   187 
   173     public synchronized void mark(int readLimit) {
   188     public int available() throws IOException {
   174         if (closed) {
   189         if (closed) return 0;
   175             return;
   190         readLock.lock();
   176         }
   191         try {
   177         super.mark(readLimit);
   192             return closed ? 0 : in.available();
   178 
   193         } finally {
   179         /*
   194             readLock.unlock();
   180          * mark the count to restore upon reset
   195         }
   181          */
   196     }
   182         markedCount = count;
   197 
   183         markLimit = readLimit;
   198     public void mark(int readLimit) {
   184     }
   199         if (closed) return;
   185 
   200         readLock.lock();
   186     public synchronized void reset() throws IOException {
   201         try {
   187         if (closed) {
   202             if (closed) return;
   188             return;
   203             super.mark(readLimit);
   189         }
   204 
   190 
   205             /*
   191         if (!isMarked()) {
   206              * mark the count to restore upon reset
   192             throw new IOException ("Resetting to an invalid mark");
   207              */
   193         }
   208             markedCount = count;
   194 
   209             markLimit = readLimit;
   195         count = markedCount;
   210         } finally {
   196         super.reset();
   211             readLock.unlock();
       
   212         }
       
   213     }
       
   214 
       
   215     public void reset() throws IOException {
       
   216         if (closed) return;
       
   217 
       
   218         readLock.lock();
       
   219         try {
       
   220             if (closed) return;
       
   221             if (!isMarked()) {
       
   222                 throw new IOException("Resetting to an invalid mark");
       
   223             }
       
   224 
       
   225             count = markedCount;
       
   226             super.reset();
       
   227         } finally {
       
   228             readLock.unlock();
       
   229         }
   197     }
   230     }
   198 
   231 
   199     public boolean markSupported() {
   232     public boolean markSupported() {
   200         if (closed) {
   233         if (closed) return false;
   201             return false;
   234         readLock.lock();
   202         }
   235         try {
   203         return super.markSupported();
   236             if (closed) return false;
       
   237             return super.markSupported();
       
   238         } finally {
       
   239             readLock.unlock();
       
   240         }
   204     }
   241     }
   205 
   242 
   206     @SuppressWarnings("deprecation")
   243     @SuppressWarnings("deprecation")
   207     protected void finalize() throws Throwable {
   244     protected void finalize() throws Throwable {
   208         try {
   245         try {