61 * |
61 * |
62 * @author Joshua Bloch |
62 * @author Joshua Bloch |
63 * @author Gadi Guy |
63 * @author Gadi Guy |
64 */ |
64 */ |
65 |
65 |
|
66 import java.lang.reflect.Method; |
|
67 import java.lang.reflect.InvocationTargetException; |
66 import java.security.*; |
68 import java.security.*; |
67 import java.io.*; |
69 import java.io.*; |
68 import java.util.Properties; |
70 import java.util.Properties; |
69 import java.util.Enumeration; |
71 import java.util.Enumeration; |
70 import java.net.*; |
72 import java.net.*; |
71 import java.nio.file.DirectoryStream; |
|
72 import java.nio.file.Path; |
|
73 import java.util.Random; |
73 import java.util.Random; |
74 import sun.security.util.Debug; |
74 import sun.security.util.Debug; |
75 |
75 |
76 abstract class SeedGenerator { |
76 abstract class SeedGenerator { |
77 |
77 |
181 md.update |
181 md.update |
182 (InetAddress.getLocalHost().toString().getBytes()); |
182 (InetAddress.getLocalHost().toString().getBytes()); |
183 |
183 |
184 // The temporary dir |
184 // The temporary dir |
185 File f = new File(p.getProperty("java.io.tmpdir")); |
185 File f = new File(p.getProperty("java.io.tmpdir")); |
186 int count = 0; |
186 |
187 DirectoryStream<Path> ds |
187 // Go thru files in the tmp dir using NIO's |
188 = f.toPath().newDirectoryStream(); |
188 // DirectoryStream. Fallback to File.list() |
189 try { |
189 // if NIO is not available. |
|
190 if (NIODirectoryStream.isAvailable()) { |
|
191 int count = 0; |
|
192 Iterable<?> stream = |
|
193 NIODirectoryStream.newDirectoryStream(f); |
190 // We use a Random object to choose what file names |
194 // We use a Random object to choose what file names |
191 // should be used. Otherwise on a machine with too |
195 // should be used. Otherwise on a machine with too |
192 // many files, the same first 1024 files always get |
196 // many files, the same first 1024 files always get |
193 // used. Any, We make sure the first 512 files are |
197 // used. Any, We make sure the first 512 files are |
194 // always used. |
198 // always used. |
195 Random r = new Random(); |
199 Random r = new Random(); |
196 for (Path path: ds) { |
200 try { |
197 if (count < 512 || r.nextBoolean()) { |
201 for (Object entry: stream) { |
198 md.update(path.getName().toString().getBytes()); |
202 if (count < 512 || r.nextBoolean()) { |
|
203 md.update(NIODirectoryStream.getName( |
|
204 entry).getBytes()); |
|
205 } |
|
206 if (count++ > 1024) { |
|
207 break; |
|
208 } |
199 } |
209 } |
200 if (count++ > 1024) { |
210 } finally { |
201 break; |
211 ((Closeable)stream).close(); |
202 } |
|
203 } |
212 } |
204 } finally { |
213 } else { |
205 ds.close(); |
214 String[] sa = f.list(); |
|
215 for(int i = 0; i < sa.length; i++) { |
|
216 md.update(sa[i].getBytes()); |
|
217 } |
206 } |
218 } |
207 } catch (Exception ex) { |
219 } catch (Exception ex) { |
208 md.update((byte)ex.hashCode()); |
220 md.update((byte)ex.hashCode()); |
209 } |
221 } |
210 |
222 |
503 } |
515 } |
504 } |
516 } |
505 |
517 |
506 } |
518 } |
507 |
519 |
|
520 /** |
|
521 * A wrapper of NIO DirectoryStream using reflection. |
|
522 */ |
|
523 private static class NIODirectoryStream { |
|
524 private static final Class<?> pathClass = |
|
525 getClass("java.nio.file.Path"); |
|
526 |
|
527 private static final Method toPathMethod = |
|
528 (pathClass == null) ? null : getMethod(File.class, "toPath"); |
|
529 private static final Method getNameMethod = |
|
530 getMethod(pathClass, "getName"); |
|
531 private static final Method newDirectoryStreamMethod = |
|
532 getMethod(pathClass, "newDirectoryStream"); |
|
533 |
|
534 private static Class<?> getClass(String name) { |
|
535 try { |
|
536 return Class.forName(name, true, null); |
|
537 } catch (ClassNotFoundException e) { |
|
538 return null; |
|
539 } |
|
540 } |
|
541 |
|
542 private static Method getMethod(Class<?> clazz, |
|
543 String name, |
|
544 Class<?>... paramTypes) { |
|
545 if (clazz != null) { |
|
546 try { |
|
547 return clazz.getMethod(name, paramTypes); |
|
548 } catch (NoSuchMethodException e) { |
|
549 throw new AssertionError(e); |
|
550 } |
|
551 } else { |
|
552 return null; |
|
553 } |
|
554 } |
|
555 |
|
556 static boolean isAvailable() { |
|
557 return pathClass != null; |
|
558 } |
|
559 |
|
560 static Iterable<?> newDirectoryStream(File dir) throws IOException { |
|
561 assert pathClass != null; |
|
562 try { |
|
563 Object path = toPathMethod.invoke(dir); |
|
564 return (Iterable<?>)newDirectoryStreamMethod.invoke(path); |
|
565 } catch (InvocationTargetException e) { |
|
566 Throwable cause = e.getCause(); |
|
567 if (cause instanceof IOException) |
|
568 throw (IOException)cause; |
|
569 if (cause instanceof RuntimeException) |
|
570 throw (RuntimeException)cause; |
|
571 if (cause instanceof Error) |
|
572 throw (Error)cause; |
|
573 throw new AssertionError(e); |
|
574 } catch (IllegalAccessException iae) { |
|
575 throw new AssertionError(iae); |
|
576 } |
|
577 } |
|
578 |
|
579 static String getName(Object path) { |
|
580 assert pathClass != null; |
|
581 try { |
|
582 Object name = getNameMethod.invoke(path); |
|
583 return name.toString(); |
|
584 } catch (InvocationTargetException e) { |
|
585 throw new AssertionError(e); |
|
586 } catch (IllegalAccessException iae) { |
|
587 throw new AssertionError(iae); |
|
588 } |
|
589 } |
|
590 } |
508 } |
591 } |
|
592 |