6894534: SeedGenerator shouldn't require java.nio.file to be present
authorweijun
Fri, 30 Oct 2009 11:28:42 +0800
changeset 4176 bf303f38f727
parent 4175 3bbed32a84ee
child 4177 208f8c11e7ba
child 4222 fbd90ce2c529
6894534: SeedGenerator shouldn't require java.nio.file to be present Reviewed-by: alanb
jdk/src/share/classes/sun/security/provider/SeedGenerator.java
--- a/jdk/src/share/classes/sun/security/provider/SeedGenerator.java	Thu Oct 29 19:55:52 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/SeedGenerator.java	Fri Oct 30 11:28:42 2009 +0800
@@ -63,13 +63,13 @@
  * @author Gadi Guy
  */
 
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
 import java.security.*;
 import java.io.*;
 import java.util.Properties;
 import java.util.Enumeration;
 import java.net.*;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Path;
 import java.util.Random;
 import sun.security.util.Debug;
 
@@ -183,26 +183,38 @@
 
                         // The temporary dir
                         File f = new File(p.getProperty("java.io.tmpdir"));
-                        int count = 0;
-                        DirectoryStream<Path> ds
-                                = f.toPath().newDirectoryStream();
-                        try {
+
+                        // Go thru files in the tmp dir using NIO's
+                        // DirectoryStream. Fallback to File.list()
+                        // if NIO is not available.
+                        if (NIODirectoryStream.isAvailable()) {
+                            int count = 0;
+                            Iterable<?> stream =
+                                    NIODirectoryStream.newDirectoryStream(f);
                             // We use a Random object to choose what file names
                             // should be used. Otherwise on a machine with too
                             // many files, the same first 1024 files always get
                             // used. Any, We make sure the first 512 files are
                             // always used.
                             Random r = new Random();
-                            for (Path path: ds) {
-                                if (count < 512 || r.nextBoolean()) {
-                                    md.update(path.getName().toString().getBytes());
+                            try {
+                                for (Object entry: stream) {
+                                    if (count < 512 || r.nextBoolean()) {
+                                        md.update(NIODirectoryStream.getName(
+                                                entry).getBytes());
+                                    }
+                                    if (count++ > 1024) {
+                                        break;
+                                    }
                                 }
-                                if (count++ > 1024) {
-                                    break;
-                                }
+                            } finally {
+                                ((Closeable)stream).close();
                             }
-                        } finally {
-                            ds.close();
+                        } else {
+                            String[] sa = f.list();
+                            for(int i = 0; i < sa.length; i++) {
+                                md.update(sa[i].getBytes());
+                            }
                         }
                     } catch (Exception ex) {
                         md.update((byte)ex.hashCode());
@@ -505,4 +517,76 @@
 
     }
 
+    /**
+     * A wrapper of NIO DirectoryStream using reflection.
+     */
+    private static class NIODirectoryStream {
+        private static final Class<?> pathClass =
+                getClass("java.nio.file.Path");
+
+        private static final Method toPathMethod =
+                (pathClass == null) ? null : getMethod(File.class, "toPath");
+        private static final Method getNameMethod =
+                getMethod(pathClass, "getName");
+        private static final Method newDirectoryStreamMethod =
+                getMethod(pathClass, "newDirectoryStream");
+
+        private static Class<?> getClass(String name) {
+            try {
+                return Class.forName(name, true, null);
+            } catch (ClassNotFoundException e) {
+                return null;
+            }
+        }
+
+        private static Method getMethod(Class<?> clazz,
+                                        String name,
+                                        Class<?>... paramTypes) {
+            if (clazz != null) {
+                try {
+                    return clazz.getMethod(name, paramTypes);
+                } catch (NoSuchMethodException e) {
+                    throw new AssertionError(e);
+                }
+            } else {
+                return null;
+            }
+        }
+
+        static boolean isAvailable() {
+            return pathClass != null;
+        }
+
+        static Iterable<?> newDirectoryStream(File dir) throws IOException {
+            assert pathClass != null;
+            try {
+                Object path = toPathMethod.invoke(dir);
+                return (Iterable<?>)newDirectoryStreamMethod.invoke(path);
+            } catch (InvocationTargetException e) {
+                Throwable cause = e.getCause();
+                if (cause instanceof IOException)
+                    throw (IOException)cause;
+                if (cause instanceof RuntimeException)
+                    throw (RuntimeException)cause;
+                if (cause instanceof Error)
+                    throw (Error)cause;
+                throw new AssertionError(e);
+            } catch (IllegalAccessException iae) {
+                throw new AssertionError(iae);
+            }
+        }
+
+        static String getName(Object path) {
+            assert pathClass != null;
+            try {
+                Object name = getNameMethod.invoke(path);
+                return name.toString();
+            } catch (InvocationTargetException e) {
+                throw new AssertionError(e);
+            } catch (IllegalAccessException iae) {
+                throw new AssertionError(iae);
+            }
+        }
+    }
 }
+