1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.io.File;
  25 import java.io.FileOutputStream;
  26 import java.io.IOException;
  27 import java.io.InputStream;
  28 import java.lang.reflect.InvocationTargetException;
  29 import java.lang.reflect.Method;
  30 import java.lang.reflect.UndeclaredThrowableException;
  31 import java.util.Arrays;
  32 
  33 import static jdk.testlibrary.Asserts.*;
  34 
  35 /**
  36  * @test a unit test for sun.security.provider.FileInputStreamPool
  37  * @bug 8047769
  38  * @summary test behaviour of sun.security.provider.FileInputStreamPool
  39  */
  40 
  41 public class FileInputStreamPoolTest {
  42 
  43     static final byte[] bytes = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
  44 
  45     static void testCaching(File file) throws IOException {
  46         InputStream in1 = FileInputStreamPoolProxy.getInputStream(file);
  47         InputStream in2 = FileInputStreamPoolProxy.getInputStream(file);
  48         assert in1 == in2;
  49 
  50         byte[] readBytes = new byte[bytes.length];
  51         int nread = in1.read(readBytes);
  52         assertEquals(bytes.length, nread, "short read");
  53         assertTrue(Arrays.equals(readBytes, bytes),
  54             "readBytes: " + Arrays.toString(readBytes) +
  55                 " not equal to expected: " + Arrays.toString(bytes));
  56     }
  57 
  58     public static void main(String[] args) throws Exception {
  59         // 1st create temporary file
  60         File file = File.createTempFile("test", ".dat");
  61         try {
  62             try (FileOutputStream out = new FileOutputStream(file)) {
  63                 out.write(bytes);
  64             }
  65 
  66             // test caching 1t time
  67             testCaching(file);
  68 
  69             // make GC process WeakReferences
  70             System.gc();
  71             // wait a while for ReferenceHandler to enqueue WeakReferences
  72             // if this fails on slow or busy machines, sleep should be
  73             // replaced with:
  74             //   while (java.lang.ref.Reference.tryHandlePending(false)) {}
  75             Thread.sleep(500L);
  76 
  77             // test caching 2nd time - this should only succeed if
  78             // the stream has been closed and re-opened as a consequence
  79             // of cleared WeakReference
  80             testCaching(file);
  81         } finally {
  82             file.delete();
  83         }
  84     }
  85 
  86     /**
  87      * A proxy for package-private sun.security.provider.FileInputStreamPool
  88      */
  89     static class FileInputStreamPoolProxy {
  90         private static final Method getInputStreamMethod;
  91 
  92         static {
  93             try {
  94                 Class<?> fileInputStreamPoolClass =
  95                     Class.forName("sun.security.provider.FileInputStreamPool");
  96                 getInputStreamMethod =
  97                     fileInputStreamPoolClass.getDeclaredMethod(
  98                         "getInputStream",   File.class);
  99                 getInputStreamMethod.setAccessible(true);
 100             } catch (Exception e) {
 101                 throw new Error(e);
 102             }
 103         }
 104 
 105         static InputStream getInputStream(File file) throws IOException {
 106             try {
 107                 return (InputStream) getInputStreamMethod.invoke(null, file);
 108             } catch (InvocationTargetException e) {
 109                 Throwable te = e.getTargetException();
 110                 if (te instanceof IOException) {
 111                     throw (IOException) te;
 112                 } else if (te instanceof RuntimeException) {
 113                     throw (RuntimeException) te;
 114                 } else if (te instanceof Error) {
 115                     throw (Error) te;
 116                 } else {
 117                     throw new UndeclaredThrowableException(te);
 118                 }
 119             } catch (IllegalAccessException e) {
 120                 throw new RuntimeException(e);
 121             }
 122         }
 123     }
 124 }