src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java
branchhttp-client-branch
changeset 56257 82a9340bdda6
parent 56138 4f92b988600e
child 56451 9585061fdb04
equal deleted inserted replaced
56256:0fe17c3f9b4f 56257:82a9340bdda6
    25 
    25 
    26 package jdk.internal.net.http;
    26 package jdk.internal.net.http;
    27 
    27 
    28 import java.io.File;
    28 import java.io.File;
    29 import java.io.FileInputStream;
    29 import java.io.FileInputStream;
       
    30 import java.io.FileNotFoundException;
       
    31 import java.io.FilePermission;
    30 import java.io.IOException;
    32 import java.io.IOException;
    31 import java.io.InputStream;
    33 import java.io.InputStream;
    32 import java.io.UncheckedIOException;
    34 import java.io.UncheckedIOException;
    33 import java.nio.ByteBuffer;
    35 import java.nio.ByteBuffer;
    34 import java.nio.charset.Charset;
    36 import java.nio.charset.Charset;
       
    37 import java.nio.file.Files;
    35 import java.nio.file.Path;
    38 import java.nio.file.Path;
    36 import java.security.AccessControlContext;
    39 import java.security.AccessControlContext;
    37 import java.security.AccessController;
    40 import java.security.AccessController;
    38 import java.security.PrivilegedAction;
    41 import java.security.PrivilegedAction;
    39 import java.security.PrivilegedActionException;
    42 import java.security.PrivilegedActionException;
   215         public void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
   218         public void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
   216             delegate.subscribe(subscriber);
   219             delegate.subscribe(subscriber);
   217         }
   220         }
   218     }
   221     }
   219 
   222 
       
   223     /**
       
   224      * Publishes the content of a given file.
       
   225      *
       
   226      * Privileged actions are performed within a limited doPrivileged that only
       
   227      * asserts the specific, read, file permission that was checked during the
       
   228      * construction of this FilePublisher.
       
   229      */
   220     public static class FilePublisher implements BodyPublisher  {
   230     public static class FilePublisher implements BodyPublisher  {
       
   231 
       
   232         private static final FilePermission[] EMPTY_FILE_PERMISSIONS = new FilePermission[0];
       
   233 
   221         private final File file;
   234         private final File file;
   222 
   235         private final FilePermission[] filePermissions;
   223         public FilePublisher(Path name) {
   236 
       
   237         private static String pathForSecurityCheck(Path path) {
       
   238             return path.toFile().getPath();
       
   239         }
       
   240 
       
   241         /**
       
   242          * Factory for creating FilePublisher.
       
   243          *
       
   244          * Permission checks are performed here before construction of the
       
   245          * FilePublisher. Permission checking and construction are deliberately
       
   246          * and tightly co-located.
       
   247          */
       
   248         public static FilePublisher create(Path path) throws FileNotFoundException {
       
   249             FilePermission filePermission = null;
       
   250             SecurityManager sm = System.getSecurityManager();
       
   251             if (sm != null) {
       
   252                 String fn = pathForSecurityCheck(path);
       
   253                 FilePermission readPermission = new FilePermission(fn, "read");
       
   254                 sm.checkPermission(readPermission);
       
   255                 filePermission = readPermission;
       
   256             }
       
   257 
       
   258             // existence check must be after permission checks
       
   259             if (Files.notExists(path))
       
   260                 throw new FileNotFoundException(path + " not found");
       
   261 
       
   262             return new FilePublisher(path, filePermission);
       
   263         }
       
   264 
       
   265         private FilePublisher(Path name, FilePermission filePermission) {
       
   266             assert filePermission != null ? filePermission.getActions().equals("read") : true;
   224             file = name.toFile();
   267             file = name.toFile();
       
   268             this.filePermissions = filePermission == null ? EMPTY_FILE_PERMISSIONS
       
   269                     : new FilePermission[] { filePermission };
   225         }
   270         }
   226 
   271 
   227         @Override
   272         @Override
   228         public void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
   273         public void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
   229             InputStream is;
   274             InputStream is;
   230             try {
   275             if (System.getSecurityManager() == null) {
   231                 PrivilegedExceptionAction<FileInputStream> pa =
   276                 try {
   232                         () -> new FileInputStream(file);
   277                     is = new FileInputStream(file);
   233                 is = AccessController.doPrivileged(pa);
   278                 } catch (IOException ioe) {
   234             } catch (PrivilegedActionException pae) {
   279                     throw new UncheckedIOException(ioe);
   235                 throw new UncheckedIOException((IOException)pae.getCause());
   280                 }
       
   281             } else {
       
   282                 try {
       
   283                     PrivilegedExceptionAction<FileInputStream> pa =
       
   284                             () -> new FileInputStream(file);
       
   285                     is = AccessController.doPrivileged(pa, null, filePermissions);
       
   286                 } catch (PrivilegedActionException pae) {
       
   287                     throw new UncheckedIOException((IOException) pae.getCause());
       
   288                 }
   236             }
   289             }
   237             PullPublisher<ByteBuffer> publisher =
   290             PullPublisher<ByteBuffer> publisher =
   238                     new PullPublisher<>(() -> new StreamIterator(is));
   291                     new PullPublisher<>(() -> new StreamIterator(is));
   239             publisher.subscribe(subscriber);
   292             publisher.subscribe(subscriber);
   240         }
   293         }
   241 
   294 
   242         @Override
   295         @Override
   243         public long contentLength() {
   296         public long contentLength() {
   244             PrivilegedAction<Long> pa = () -> file.length();
   297             if (System.getSecurityManager() == null) {
   245             return AccessController.doPrivileged(pa);
   298                 return file.length();
       
   299             } else {
       
   300                 PrivilegedAction<Long> pa = () -> file.length();
       
   301                 return AccessController.doPrivileged(pa, null, filePermissions);
       
   302             }
   246         }
   303         }
   247     }
   304     }
   248 
   305 
   249     /**
   306     /**
   250      * Reads one buffer ahead all the time, blocking in hasNext()
   307      * Reads one buffer ahead all the time, blocking in hasNext()