diff --git a/jdk/.hgtags b/jdk/.hgtags index c73326b379e..684719db0b2 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -102,3 +102,4 @@ ac311eb325bfc763698219252bf3cee9e091f3af jdk7-b122 0a56bdd709d01c1663047e55201d19152ffd3d69 jdk7-b125 8361ef97a0f90086c9048beaf7cea1a37216c4cd jdk7-b126 29e09de1d0b4f84faea114cf10b3ec08b59acc4e jdk7-b127 +f08682e23279d6cccbdcafda1eb0647ba4900874 jdk7-b128 diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk index 47179069c17..fdd4b551912 100644 --- a/jdk/make/java/java/FILES_java.gmk +++ b/jdk/make/java/java/FILES_java.gmk @@ -443,7 +443,6 @@ JAVA_JAVA_java = \ java/io/FileReader.java \ java/io/PipedReader.java \ java/io/StringReader.java \ - java/io/TempFileHelper.java \ java/io/Writer.java \ java/io/BufferedWriter.java \ java/io/PrintWriter.java \ diff --git a/jdk/make/java/nio/FILES_java.gmk b/jdk/make/java/nio/FILES_java.gmk index cb416fe0932..9fbeafb48a3 100644 --- a/jdk/make/java/nio/FILES_java.gmk +++ b/jdk/make/java/nio/FILES_java.gmk @@ -81,12 +81,12 @@ FILES_src = \ java/nio/file/ClosedDirectoryStreamException.java \ java/nio/file/ClosedFileSystemException.java \ java/nio/file/ClosedWatchServiceException.java \ + java/nio/file/CopyMoveHelper.java \ java/nio/file/CopyOption.java \ java/nio/file/DirectoryIteratorException.java \ java/nio/file/DirectoryNotEmptyException.java \ java/nio/file/DirectoryStream.java \ java/nio/file/FileAlreadyExistsException.java \ - java/nio/file/FileRef.java \ java/nio/file/FileStore.java \ java/nio/file/FileSystem.java \ java/nio/file/FileSystemAlreadyExistsException.java \ @@ -116,6 +116,7 @@ FILES_src = \ java/nio/file/StandardCopyOption.java \ java/nio/file/StandardOpenOption.java \ java/nio/file/StandardWatchEventKind.java \ + java/nio/file/TempFileHelper.java \ java/nio/file/WatchEvent.java \ java/nio/file/WatchKey.java \ java/nio/file/WatchService.java \ @@ -127,7 +128,6 @@ FILES_src = \ java/nio/file/attribute/AclEntryType.java \ java/nio/file/attribute/AclFileAttributeView.java \ java/nio/file/attribute/AttributeView.java \ - java/nio/file/attribute/Attributes.java \ java/nio/file/attribute/BasicFileAttributeView.java \ java/nio/file/attribute/BasicFileAttributes.java \ java/nio/file/attribute/DosFileAttributeView.java \ @@ -136,8 +136,6 @@ FILES_src = \ java/nio/file/attribute/FileAttributeView.java \ java/nio/file/attribute/FileOwnerAttributeView.java \ java/nio/file/attribute/FileStoreAttributeView.java \ - java/nio/file/attribute/FileStoreSpaceAttributeView.java \ - java/nio/file/attribute/FileStoreSpaceAttributes.java \ java/nio/file/attribute/FileTime.java \ java/nio/file/attribute/GroupPrincipal.java \ java/nio/file/attribute/UserDefinedFileAttributeView.java \ @@ -246,6 +244,7 @@ FILES_src = \ sun/nio/fs/AbstractAclFileAttributeView.java \ sun/nio/fs/AbstractBasicFileAttributeView.java \ sun/nio/fs/AbstractFileTypeDetector.java \ + sun/nio/fs/AbstractFileSystemProvider.java \ sun/nio/fs/AbstractPath.java \ sun/nio/fs/AbstractPoller.java \ sun/nio/fs/AbstractUserDefinedFileAttributeView.java \ diff --git a/jdk/make/netbeans/common/java-data-native.ent b/jdk/make/netbeans/common/java-data-native.ent index c968584892b..831bf255245 100644 --- a/jdk/make/netbeans/common/java-data-native.ent +++ b/jdk/make/netbeans/common/java-data-native.ent @@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + ${root}/src/share/classes ${root}/src/windows/classes @@ -39,6 +39,6 @@ ${bootstrap.jdk}/jre/lib/rt.jar ${root}/build/${platform}-${arch}/classes ${root}/build/javadoc/${name} - 1.5 + 1.7 diff --git a/jdk/make/netbeans/common/java-data-no-native.ent b/jdk/make/netbeans/common/java-data-no-native.ent index e7717f2d398..fdc06cfca34 100644 --- a/jdk/make/netbeans/common/java-data-no-native.ent +++ b/jdk/make/netbeans/common/java-data-no-native.ent @@ -31,12 +31,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + ${root}/src/share/classes ${bootstrap.jdk}/jre/lib/rt.jar ${root}/build/${platform}-${arch}/classes ${root}/build/javadoc/${name} - 1.5 + 1.7 diff --git a/jdk/src/share/bin/java.c b/jdk/src/share/bin/java.c index c2a6ab99249..2d339547761 100644 --- a/jdk/src/share/bin/java.c +++ b/jdk/src/share/bin/java.c @@ -244,6 +244,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ for (i = 0; i < argc ; i++) { printf("argv[%d] = %s\n", i, argv[i]); } + AddOption("-Dsun.java.launcher.diag=true", NULL); } CreateExecutionEnvironment(&argc, &argv, @@ -1009,6 +1010,8 @@ ParseArguments(int *pargc, char ***pargv, } else if (JLI_StrCmp(arg, "-XshowSettings") == 0 || JLI_StrCCmp(arg, "-XshowSettings:") == 0) { showSettings = arg; + } else if (JLI_StrCmp(arg, "-Xdiag") == 0) { + AddOption("-Dsun.java.launcher.diag=true", NULL); /* * The following case provide backward compatibility with old-style * command line options. diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/Connection.java b/jdk/src/share/classes/com/sun/jndi/ldap/Connection.java index dec38eb752d..94067617ae1 100644 --- a/jdk/src/share/classes/com/sun/jndi/ldap/Connection.java +++ b/jdk/src/share/classes/com/sun/jndi/ldap/Connection.java @@ -656,14 +656,17 @@ public final class Connection implements Runnable { } nparent = notifyParent; } - } - if (nparent) { - LdapRequest ldr = pendingRequests; - while (ldr != null) { - ldr.notify(); - ldr = ldr.next; + if (nparent) { + LdapRequest ldr = pendingRequests; + while (ldr != null) { + + synchronized (ldr) { + ldr.notify(); + ldr = ldr.next; + } + } + parent.processConnectionClosure(); } - parent.processConnectionClosure(); } } diff --git a/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java b/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java index bd3dc18fc24..7ecd4d75aea 100644 --- a/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java +++ b/jdk/src/share/classes/com/sun/jndi/toolkit/ctx/Continuation.java @@ -143,7 +143,7 @@ public class Continuation extends ResolveResult { e.setRemainingName(remainingName); e.setResolvedObj(resolvedObj); - if (starter == null) + if (starter == null || starter.isEmpty()) e.setResolvedName(null); else if (remainingName == null) e.setResolvedName(starter); diff --git a/jdk/src/share/classes/java/io/BufferedReader.java b/jdk/src/share/classes/java/io/BufferedReader.java index b12eaa0d0b5..e8583e046f0 100644 --- a/jdk/src/share/classes/java/io/BufferedReader.java +++ b/jdk/src/share/classes/java/io/BufferedReader.java @@ -54,6 +54,7 @@ package java.io; * * @see FileReader * @see InputStreamReader + * @see java.nio.file.Files#newBufferedReader * * @author Mark Reinhold * @since JDK1.1 @@ -374,6 +375,8 @@ public class BufferedReader extends Reader { * stream has been reached * * @exception IOException If an I/O error occurs + * + * @see java.nio.file.Files#readAllLines */ public String readLine() throws IOException { return readLine(false); diff --git a/jdk/src/share/classes/java/io/BufferedWriter.java b/jdk/src/share/classes/java/io/BufferedWriter.java index 457c73f512d..4322683d367 100644 --- a/jdk/src/share/classes/java/io/BufferedWriter.java +++ b/jdk/src/share/classes/java/io/BufferedWriter.java @@ -57,6 +57,7 @@ package java.io; * @see PrintWriter * @see FileWriter * @see OutputStreamWriter + * @see java.nio.file.Files#newBufferedWriter * * @author Mark Reinhold * @since JDK1.1 diff --git a/jdk/src/share/classes/java/io/File.java b/jdk/src/share/classes/java/io/File.java index 1ff3e936bae..cde70d0b977 100644 --- a/jdk/src/share/classes/java/io/File.java +++ b/jdk/src/share/classes/java/io/File.java @@ -35,8 +35,7 @@ import java.util.ArrayList; import java.security.AccessController; import java.security.SecureRandom; import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.FileAttribute; +import java.nio.file.FileSystems; import sun.security.action.GetPropertyAction; /** @@ -139,9 +138,10 @@ import sun.security.action.GetPropertyAction; * many of the limitations of the {@code java.io.File} class. * The {@link #toPath toPath} method may be used to obtain a {@link * Path} that uses the abstract path represented by a {@code File} object to - * locate a file. The resulting {@code Path} provides more efficient and - * extensive access to file attributes, additional file operations, and I/O - * exceptions to help diagnose errors when an operation on a file fails. + * locate a file. The resulting {@code Path} may be used with the {@link + * java.nio.file.Files} class to provide more efficient and extensive access to + * additional file operations, file attributes, and I/O exceptions to help + * diagnose errors when an operation on a file fails. * * @author unascribed * @since JDK1.0 @@ -778,6 +778,12 @@ public class File * Tests whether the file denoted by this abstract pathname is a * directory. * + *

Where it is required to distinguish an I/O exception from the case + * that the file is not a directory, or where several attributes of the + * same file are required at the same time, then the {@link + * java.nio.file.Files#readAttributes(Path,Class,LinkOption[]) + * Files.readAttributes} method may be used. + * * @return true if and only if the file denoted by this * abstract pathname exists and is a directory; * false otherwise @@ -786,8 +792,6 @@ public class File * If a security manager exists and its {@link * java.lang.SecurityManager#checkRead(java.lang.String)} * method denies read access to the file - * - * @see java.nio.file.attribute.Attributes#readBasicFileAttributes */ public boolean isDirectory() { SecurityManager security = System.getSecurityManager(); @@ -804,6 +808,12 @@ public class File * addition, satisfies other system-dependent criteria. Any non-directory * file created by a Java application is guaranteed to be a normal file. * + *

Where it is required to distinguish an I/O exception from the case + * that the file is not a normal file, or where several attributes of the + * same file are required at the same time, then the {@link + * java.nio.file.Files#readAttributes(Path,Class,LinkOption[]) + * Files.readAttributes} method may be used. + * * @return true if and only if the file denoted by this * abstract pathname exists and is a normal file; * false otherwise @@ -812,8 +822,6 @@ public class File * If a security manager exists and its {@link * java.lang.SecurityManager#checkRead(java.lang.String)} * method denies read access to the file - * - * @see java.nio.file.attribute.Attributes#readBasicFileAttributes */ public boolean isFile() { SecurityManager security = System.getSecurityManager(); @@ -853,6 +861,13 @@ public class File * Returns the time that the file denoted by this abstract pathname was * last modified. * + *

Where it is required to distinguish an I/O exception from the case + * where {@code 0L} is returned, or where several attributes of the + * same file are required at the same time, or where the time of last + * access or the creation time are required, then the {@link + * java.nio.file.Files#readAttributes(Path,Class,LinkOption[]) + * Files.readAttributes} method may be used. + * * @return A long value representing the time the file was * last modified, measured in milliseconds since the epoch * (00:00:00 GMT, January 1, 1970), or 0L if the @@ -862,8 +877,6 @@ public class File * If a security manager exists and its {@link * java.lang.SecurityManager#checkRead(java.lang.String)} * method denies read access to the file - * - * @see java.nio.file.attribute.Attributes#readBasicFileAttributes */ public long lastModified() { SecurityManager security = System.getSecurityManager(); @@ -877,6 +890,12 @@ public class File * Returns the length of the file denoted by this abstract pathname. * The return value is unspecified if this pathname denotes a directory. * + *

Where it is required to distinguish an I/O exception from the case + * that {@code 0L} is returned, or where several attributes of the same file + * are required at the same time, then the {@link + * java.nio.file.Files#readAttributes(Path,Class,LinkOption[]) + * Files.readAttributes} method may be used. + * * @return The length, in bytes, of the file denoted by this abstract * pathname, or 0L if the file does not exist. Some * operating systems may return 0L for pathnames @@ -886,8 +905,6 @@ public class File * If a security manager exists and its {@link * java.lang.SecurityManager#checkRead(java.lang.String)} * method denies read access to the file - * - * @see java.nio.file.attribute.Attributes#readBasicFileAttributes */ public long length() { SecurityManager security = System.getSecurityManager(); @@ -937,11 +954,10 @@ public class File * this pathname denotes a directory, then the directory must be empty in * order to be deleted. * - *

Note that the {@link Path} class defines the {@link Path#delete - * delete} method to throw an {@link IOException} when a file cannot be - * deleted. This is useful for error reporting and to diagnose why a file - * cannot be deleted. The {@link #toPath toPath} method may be used to - * obtain a {@code Path} representing this abstract pathname. + *

Note that the {@link java.nio.file.Files} class defines the {@link + * java.nio.file.Files#delete(Path) delete} method to throw an {@link IOException} + * when a file cannot be deleted. This is useful for error reporting and to + * diagnose why a file cannot be deleted. * * @return true if and only if the file or directory is * successfully deleted; false otherwise @@ -1009,12 +1025,11 @@ public class File * will appear in any specific order; they are not, in particular, * guaranteed to appear in alphabetical order. * - *

Note that the {@link Path} class defines the {@link - * Path#newDirectoryStream newDirectoryStream} method to open a directory - * and iterate over the names of the files in the directory. This may use - * less resources when working with very large directories. The {@link - * #toPath toPath} method may be used to obtain a {@code Path} representing - * this abstract pathname. + *

Note that the {@link java.nio.file.Files} class defines the {@link + * java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method to + * open a directory and iterate over the names of the files in the directory. + * This may use less resources when working with very large directories, and + * may be more responsive when working with remote directories. * * @return An array of strings naming the files and directories in the * directory denoted by this abstract pathname. The array will be @@ -1061,6 +1076,8 @@ public class File * If a security manager exists and its {@link * SecurityManager#checkRead(String)} method denies read access to * the directory + * + * @see java.nio.file.Files#newDirectoryStream(Path,String) */ public String[] list(FilenameFilter filter) { String names[] = list(); @@ -1095,12 +1112,11 @@ public class File * will appear in any specific order; they are not, in particular, * guaranteed to appear in alphabetical order. * - *

Note that the {@link Path} class defines the {@link - * Path#newDirectoryStream newDirectoryStream} method to open a directory - * and iterate over the names of the files in the directory. This may use - * less resources when working with very large directories. The {@link - * #toPath toPath} method may be used to obtain a {@code Path} representing - * this abstract pathname. + *

Note that the {@link java.nio.file.Files} class defines the {@link + * java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method + * to open a directory and iterate over the names of the files in the + * directory. This may use less resources when working with very large + * directories. * * @return An array of abstract pathnames denoting the files and * directories in the directory denoted by this abstract pathname. @@ -1154,6 +1170,7 @@ public class File * the directory * * @since 1.2 + * @see java.nio.file.Files#newDirectoryStream(Path,String) */ public File[] listFiles(FilenameFilter filter) { String ss[] = list(); @@ -1191,6 +1208,7 @@ public class File * the directory * * @since 1.2 + * @see java.nio.file.Files#newDirectoryStream(Path,java.nio.file.DirectoryStream.Filter) */ public File[] listFiles(FileFilter filter) { String ss[] = list(); @@ -1207,12 +1225,6 @@ public class File /** * Creates the directory named by this abstract pathname. * - *

Note that the {@link Path} class defines the {@link Path#createDirectory - * createDirectory} method to throw an {@link IOException} when a directory - * cannot be created. This is useful for error reporting and to diagnose why - * a directory cannot be created. The {@link #toPath toPath} method may be - * used to obtain a {@code Path} representing this abstract pathname. - * * @return true if and only if the directory was * created; false otherwise * @@ -1278,10 +1290,9 @@ public class File * already exists. The return value should always be checked to make sure * that the rename operation was successful. * - *

Note that the {@link Path} class defines the {@link Path#moveTo - * moveTo} method to move or rename a file in a platform independent manner. - * The {@link #toPath toPath} method may be used to obtain a {@code Path} - * representing this abstract pathname. + *

Note that the {@link java.nio.file.Files} class defines the {@link + * java.nio.file.Files#move move} method to move or rename a file in a + * platform independent manner. * * @param dest The new abstract pathname for the named file * @@ -1369,10 +1380,9 @@ public class File * Sets the owner's or everybody's write permission for this abstract * pathname. * - *

The {@link java.nio.file.attribute.Attributes Attributes} class - * defines methods that operate on file attributes including file - * permissions. This may be used when finer manipulation of file permissions - * is required. + *

The {@link java.nio.file.Files} class defines methods that operate on + * file attributes including file permissions. This may be used when finer + * manipulation of file permissions is required. * * @param writable * If true, sets the access permission to allow write @@ -1437,10 +1447,9 @@ public class File * Sets the owner's or everybody's read permission for this abstract * pathname. * - *

The {@link java.nio.file.attribute.Attributes Attributes} class - * defines methods that operate on file attributes including file - * permissions. This may be used when finer manipulation of file permissions - * is required. + *

The {@link java.nio.file.Files} class defines methods that operate on + * file attributes including file permissions. This may be used when finer + * manipulation of file permissions is required. * * @param readable * If true, sets the access permission to allow read @@ -1511,10 +1520,9 @@ public class File * Sets the owner's or everybody's execute permission for this abstract * pathname. * - *

The {@link java.nio.file.attribute.Attributes Attributes} class - * defines methods that operate on file attributes including file - * permissions. This may be used when finer manipulation of file permissions - * is required. + *

The {@link java.nio.file.Files} class defines methods that operate on + * file attributes including file permissions. This may be used when finer + * manipulation of file permissions is required. * * @param executable * If true, sets the access permission to allow execute @@ -1646,6 +1654,7 @@ public class File * filesystem roots. * * @since 1.2 + * @see java.nio.file.FileStore */ public static File[] listRoots() { return fs.listRoots(); @@ -1753,7 +1762,7 @@ public class File /* -- Temporary files -- */ - static class TempDirectory { + private static class TempDirectory { private TempDirectory() { } // temporary directory location @@ -1880,11 +1889,12 @@ public class File * java.lang.String, java.io.File) * createTempFile(prefix, suffix, null)}. * - *

The {@link #createTemporaryFile(String,String,FileAttribute[])} method - * provides an alternative method to create an empty file in the - * temporary-file directory. Files created by that method may have more - * restrictive access permissions to files created by this method and so - * may be more suited to security-sensitive applications. + *

The {@link + * java.nio.file.Files#createTempFile(String,String,java.nio.file.attribute.FileAttribute[]) + * Files.createTempFile} method provides an alternative method to create an + * empty file in the temporary-file directory. Files created by that method + * may have more restrictive access permissions to files created by this + * method and so may be more suited to security-sensitive applications. * * @param prefix The prefix string to be used in generating the file's * name; must be at least three characters long @@ -1907,6 +1917,7 @@ public class File * method does not allow a file to be created * * @since 1.2 + * @see java.nio.file.Files#createTempDirectory(String,FileAttribute[]) */ public static File createTempFile(String prefix, String suffix) throws IOException @@ -1914,61 +1925,6 @@ public class File return createTempFile(prefix, suffix, null); } - /** - * Creates an empty file in the default temporary-file directory, using - * the given prefix and suffix to generate its name. - * - *

The {@code attrs} parameter is an optional array of {@link FileAttribute - * attributes} to set atomically when creating the file. Each attribute is - * identified by its {@link FileAttribute#name name}. If more than one attribute - * of the same name is included in the array then all but the last occurrence - * is ignored. - * - *

Where the {@code attrs} parameter does not specify access - * permissions to set atomically when creating the file, then the - * resulting file may have more restrictive access permissions than files - * created by the {@link #createTempFile(java.lang.String, java.lang.String)} - * method. - * - * @param prefix - * The prefix string to be used in generating the file's - * name; must be at least three characters long - * @param suffix - * The suffix string to be used in generating the file's - * name; may be {@code null}, in which case the suffix - * {@code ".tmp"} will be used - * @param attrs - * An optional list of file attributes to set atomically when creating - * the file - * - * @return An abstract pathname denoting a newly-created empty file - * - * @throws IllegalArgumentException - * If the {@code prefix} argument contains fewer than three - * characters - * @throws UnsupportedOperationException - * If the array contains an attribute that cannot be set atomically - * when creating the file - * @throws IOException - * If a file could not be created - * @throws SecurityException - * If a security manager exists and its {@link - * java.lang.SecurityManager#checkWrite(java.lang.String)} - * method does not allow a file to be created. - * - * @since 1.7 - */ - public static File createTemporaryFile(String prefix, - String suffix, - FileAttribute... attrs) - throws IOException - { - if (prefix.length() < 3) - throw new IllegalArgumentException("Prefix string too short"); - suffix = (suffix == null) ? ".tmp" : suffix; - return TempFileHelper.createFile(prefix, suffix, attrs); - } - /* -- Basic infrastructure -- */ /** @@ -2104,6 +2060,7 @@ public class File * path (see {@link java.nio.file.FileSystem#getPath FileSystem.getPath}) * * @since 1.7 + * @see Path#toFile */ public Path toPath() { Path result = filePath; @@ -2111,12 +2068,7 @@ public class File synchronized (this) { result = filePath; if (result == null) { - if (path.length() == 0) { - // assume default file system treats "." as current directory - result = Paths.get("."); - } else { - result = Paths.get(path); - } + result = FileSystems.getDefault().getPath(path); filePath = result; } } diff --git a/jdk/src/share/classes/java/io/FileInputStream.java b/jdk/src/share/classes/java/io/FileInputStream.java index 23530c19e1f..da7ad18a532 100644 --- a/jdk/src/share/classes/java/io/FileInputStream.java +++ b/jdk/src/share/classes/java/io/FileInputStream.java @@ -42,6 +42,7 @@ import sun.nio.ch.FileChannelImpl; * @see java.io.File * @see java.io.FileDescriptor * @see java.io.FileOutputStream + * @see java.nio.file.Files#newInputStream * @since JDK1.0 */ public diff --git a/jdk/src/share/classes/java/io/FileOutputStream.java b/jdk/src/share/classes/java/io/FileOutputStream.java index 3fe3a594fd2..d714679164a 100644 --- a/jdk/src/share/classes/java/io/FileOutputStream.java +++ b/jdk/src/share/classes/java/io/FileOutputStream.java @@ -46,6 +46,7 @@ import sun.nio.ch.FileChannelImpl; * @see java.io.File * @see java.io.FileDescriptor * @see java.io.FileInputStream + * @see java.nio.file.Files#newOutputStream * @since JDK1.0 */ public diff --git a/jdk/src/share/classes/java/io/FilePermission.java b/jdk/src/share/classes/java/io/FilePermission.java index 06b4f3bb267..b5feb367e13 100644 --- a/jdk/src/share/classes/java/io/FilePermission.java +++ b/jdk/src/share/classes/java/io/FilePermission.java @@ -72,7 +72,7 @@ import sun.security.util.SecurityConstants; *

readlink *
read link permission. Allows the target of a * symbolic link - * to be read by invoking the {@link java.nio.file.Path#readSymbolicLink + * to be read by invoking the {@link java.nio.file.Files#readSymbolicLink * readSymbolicLink } method. * *

diff --git a/jdk/src/share/classes/java/io/PrintStream.java b/jdk/src/share/classes/java/io/PrintStream.java index 9ed3ff6f910..f29b5407abf 100644 --- a/jdk/src/share/classes/java/io/PrintStream.java +++ b/jdk/src/share/classes/java/io/PrintStream.java @@ -70,11 +70,11 @@ public class PrintStream extends FilterOutputStream private OutputStreamWriter charOut; /** - * nonNull is explicitly declared here so as not to create an extra - * dependency on java.util.Objects.nonNull. PrintStream is loaded + * requireNonNull is explicitly declared here so as not to create an extra + * dependency on java.util.Objects.requireNonNull. PrintStream is loaded * early during system initialization. */ - private static T nonNull(T obj, String message) { + private static T requireNonNull(T obj, String message) { if (obj == null) throw new NullPointerException(message); return obj; @@ -88,7 +88,7 @@ public class PrintStream extends FilterOutputStream private static Charset toCharset(String csn) throws UnsupportedEncodingException { - nonNull(csn, "charsetName"); + requireNonNull(csn, "charsetName"); try { return Charset.forName(csn); } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { @@ -148,7 +148,7 @@ public class PrintStream extends FilterOutputStream * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream, boolean) */ public PrintStream(OutputStream out, boolean autoFlush) { - this(autoFlush, nonNull(out, "Null output stream")); + this(autoFlush, requireNonNull(out, "Null output stream")); } /** @@ -173,7 +173,7 @@ public class PrintStream extends FilterOutputStream throws UnsupportedEncodingException { this(autoFlush, - nonNull(out, "Null output stream"), + requireNonNull(out, "Null output stream"), toCharset(encoding)); } diff --git a/jdk/src/share/classes/java/io/PrintWriter.java b/jdk/src/share/classes/java/io/PrintWriter.java index 16044567065..0e9ea8f5688 100644 --- a/jdk/src/share/classes/java/io/PrintWriter.java +++ b/jdk/src/share/classes/java/io/PrintWriter.java @@ -82,7 +82,7 @@ public class PrintWriter extends Writer { private static Charset toCharset(String csn) throws UnsupportedEncodingException { - Objects.nonNull(csn, "charsetName"); + Objects.requireNonNull(csn, "charsetName"); try { return Charset.forName(csn); } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { diff --git a/jdk/src/share/classes/java/io/SerialCallbackContext.java b/jdk/src/share/classes/java/io/SerialCallbackContext.java index 90d022e53ea..f62bdbf9a3e 100644 --- a/jdk/src/share/classes/java/io/SerialCallbackContext.java +++ b/jdk/src/share/classes/java/io/SerialCallbackContext.java @@ -54,5 +54,3 @@ thread = null; } } - - diff --git a/jdk/src/share/classes/java/lang/StackTraceElement.java b/jdk/src/share/classes/java/lang/StackTraceElement.java index b95587d7185..3bd8ed433c0 100644 --- a/jdk/src/share/classes/java/lang/StackTraceElement.java +++ b/jdk/src/share/classes/java/lang/StackTraceElement.java @@ -68,8 +68,8 @@ public final class StackTraceElement implements java.io.Serializable { */ public StackTraceElement(String declaringClass, String methodName, String fileName, int lineNumber) { - this.declaringClass = Objects.nonNull(declaringClass, "Declaring class is null"); - this.methodName = Objects.nonNull(methodName, "Method name is null"); + this.declaringClass = Objects.requireNonNull(declaringClass, "Declaring class is null"); + this.methodName = Objects.requireNonNull(methodName, "Method name is null"); this.fileName = fileName; this.lineNumber = lineNumber; } diff --git a/jdk/src/share/classes/java/lang/SuppressWarnings.java b/jdk/src/share/classes/java/lang/SuppressWarnings.java index 6989c4023dd..babb060396a 100644 --- a/jdk/src/share/classes/java/lang/SuppressWarnings.java +++ b/jdk/src/share/classes/java/lang/SuppressWarnings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ import static java.lang.annotation.ElementType.*; * @since 1.5 * @author Josh Bloch */ -@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, TYPE_PARAMETER}) +@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { /** diff --git a/jdk/src/share/classes/java/lang/Thread.java b/jdk/src/share/classes/java/lang/Thread.java index 3e258e6cdf0..d35e082b844 100644 --- a/jdk/src/share/classes/java/lang/Thread.java +++ b/jdk/src/share/classes/java/lang/Thread.java @@ -690,7 +690,7 @@ class Thread implements Runnable { /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ - group.threadStarting(this); + group.add(this); boolean started = false; try { diff --git a/jdk/src/share/classes/java/lang/ThreadGroup.java b/jdk/src/share/classes/java/lang/ThreadGroup.java index 945dfe20175..e27f17550a0 100644 --- a/jdk/src/share/classes/java/lang/ThreadGroup.java +++ b/jdk/src/share/classes/java/lang/ThreadGroup.java @@ -867,21 +867,6 @@ class ThreadGroup implements Thread.UncaughtExceptionHandler { } } - /** - * Notifies the group that the thread {@code t} is about to be - * started and adds the thread to this thread group. - * - * The thread is now a fully fledged member of the group, even though - * it hasn't been started yet. It will prevent the group from being - * destroyed so the unstarted Threads count is decremented. - */ - void threadStarting(Thread t) { - synchronized (this) { - add(t); - nUnstartedThreads--; - } - } - /** * Adds the specified thread to this thread group. * @@ -910,6 +895,12 @@ class ThreadGroup implements Thread.UncaughtExceptionHandler { // This is done last so it doesn't matter in case the // thread is killed nthreads++; + + // The thread is now a fully fledged member of the group, even + // though it may, or may not, have been started yet. It will prevent + // the group from being destroyed so the unstarted Threads count is + // decremented. + nUnstartedThreads--; } } diff --git a/jdk/src/share/classes/java/lang/annotation/ElementType.java b/jdk/src/share/classes/java/lang/annotation/ElementType.java index 3ca2c7a4372..917054991dd 100644 --- a/jdk/src/share/classes/java/lang/annotation/ElementType.java +++ b/jdk/src/share/classes/java/lang/annotation/ElementType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,12 +40,6 @@ public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, - /** Uses of a type */ - TYPE_USE, - - /** type parameters */ - TYPE_PARAMETER, - /** Field declaration (includes enum constants) */ FIELD, diff --git a/jdk/src/share/classes/java/math/BigDecimal.java b/jdk/src/share/classes/java/math/BigDecimal.java index 578c2c1159c..0d695f3bda5 100644 --- a/jdk/src/share/classes/java/math/BigDecimal.java +++ b/jdk/src/share/classes/java/math/BigDecimal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -121,8 +121,8 @@ import static java.math.BigInteger.LONG_MASK; * scale for each operation is listed in the table below. * * - * + * * * * @@ -661,25 +661,25 @@ public class BigDecimal extends Number implements Comparable { *
{@code .} FractionPart *
IntegerPart *

- *

IntegerPart: - *
Digits + *
IntegerPart: + *
Digits *

- *

FractionPart: - *
Digits + *
FractionPart: + *
Digits *

- *

Exponent: - *
ExponentIndicator SignedInteger + *
Exponent: + *
ExponentIndicator SignedInteger *

*

ExponentIndicator: *
{@code e} *
{@code E} *

- *

SignedInteger: - *
Signopt Digits + *
SignedInteger: + *
Signopt Digits *

- *

Digits: - *
Digit - *
Digits Digit + *
Digits: + *
Digit + *
Digits Digit *

*

Digit: *
any character for which {@link Character#isDigit} diff --git a/jdk/src/share/classes/java/math/RoundingMode.java b/jdk/src/share/classes/java/math/RoundingMode.java index 91c25a73510..69994a4c316 100644 --- a/jdk/src/share/classes/java/math/RoundingMode.java +++ b/jdk/src/share/classes/java/math/RoundingMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ package java.math; * *

*

Preferred Scales for Results of Arithmetic Operations - *

Preferred Scales for Results of Arithmetic Operations + *
OperationPreferred Scale of Result
Addmax(addend.scale(), augend.scale())
Subtractmax(minuend.scale(), subtrahend.scale())
- * + * * * diff --git a/jdk/src/share/classes/java/nio/channels/FileChannel.java b/jdk/src/share/classes/java/nio/channels/FileChannel.java index 8dff4bfc316..80961dd3f8e 100644 --- a/jdk/src/share/classes/java/nio/channels/FileChannel.java +++ b/jdk/src/share/classes/java/nio/channels/FileChannel.java @@ -248,7 +248,7 @@ public abstract class FileChannel * FileSystemProvider#newFileChannel newFileChannel} method on the * provider that created the {@code Path}. * - * @param file + * @param path * The path of the file to open or create * @param options * Options specifying how the file is opened @@ -261,7 +261,7 @@ public abstract class FileChannel * @throws IllegalArgumentException * If the set contains an invalid combination of options * @throws UnsupportedOperationException - * If the {@code file} is associated with a provider that does not + * If the {@code path} is associated with a provider that does not * support creating file channels, or an unsupported open option is * specified, or the array contains an attribute that cannot be set * atomically when creating the file @@ -278,13 +278,13 @@ public abstract class FileChannel * * @since 1.7 */ - public static FileChannel open(Path file, + public static FileChannel open(Path path, Set options, FileAttribute... attrs) throws IOException { - FileSystemProvider provider = file.getFileSystem().provider(); - return provider.newFileChannel(file, options, attrs); + FileSystemProvider provider = path.getFileSystem().provider(); + return provider.newFileChannel(path, options, attrs); } private static final FileAttribute[] NO_ATTRIBUTES = new FileAttribute[0]; @@ -295,10 +295,12 @@ public abstract class FileChannel *

An invocation of this method behaves in exactly the same way as the * invocation *

-     *     fc.{@link #open(Path,Set,FileAttribute[]) open}(file, options, new FileAttribute<?>[0]);
+     *     fc.{@link #open(Path,Set,FileAttribute[]) open}(file, opts, new FileAttribute<?>[0]);
      * 
+ * where {@code opts} is a set of the options specified in the {@code + * options} array. * - * @param file + * @param path * The path of the file to open or create * @param options * Options specifying how the file is opened @@ -308,7 +310,7 @@ public abstract class FileChannel * @throws IllegalArgumentException * If the set contains an invalid combination of options * @throws UnsupportedOperationException - * If the {@code file} is associated with a provider that does not + * If the {@code path} is associated with a provider that does not * support creating file channels, or an unsupported open option is * specified * @throws IOException @@ -324,12 +326,12 @@ public abstract class FileChannel * * @since 1.7 */ - public static FileChannel open(Path file, OpenOption... options) + public static FileChannel open(Path path, OpenOption... options) throws IOException { Set set = new HashSet(options.length); Collections.addAll(set, options); - return open(file, set, NO_ATTRIBUTES); + return open(path, set, NO_ATTRIBUTES); } // -- Channel operations -- diff --git a/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java b/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java index 4e75723b261..c2378546370 100644 --- a/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java +++ b/jdk/src/share/classes/java/nio/channels/SeekableByteChannel.java @@ -47,7 +47,7 @@ import java.io.IOException; * so that method invocations on the implementation class can be chained. * * @since 1.7 - * @see java.nio.file.Path#newByteChannel + * @see java.nio.file.Files#newByteChannel */ public interface SeekableByteChannel diff --git a/jdk/src/share/classes/java/nio/file/AccessMode.java b/jdk/src/share/classes/java/nio/file/AccessMode.java index c040bec01c8..43b06c25a64 100644 --- a/jdk/src/share/classes/java/nio/file/AccessMode.java +++ b/jdk/src/share/classes/java/nio/file/AccessMode.java @@ -29,8 +29,6 @@ package java.nio.file; * Defines access modes used to test the accessibility of a file. * * @since 1.7 - * - * @see Path#checkAccess */ public enum AccessMode { diff --git a/jdk/src/share/classes/java/nio/file/CopyMoveHelper.java b/jdk/src/share/classes/java/nio/file/CopyMoveHelper.java new file mode 100644 index 00000000000..70ca6ee50ad --- /dev/null +++ b/jdk/src/share/classes/java/nio/file/CopyMoveHelper.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.nio.file; + +import java.nio.file.attribute.*; +import java.io.InputStream; +import java.io.IOException; + +/** + * Helper class to support copying or moving files when the source and target + * are associated with different providers. + */ + +class CopyMoveHelper { + private CopyMoveHelper() { } + + /** + * Parses the arguments for a file copy operation. + */ + private static class CopyOptions { + boolean replaceExisting = false; + boolean copyAttributes = false; + boolean followLinks = true; + + private CopyOptions() { } + + static CopyOptions parse(CopyOption... options) { + CopyOptions result = new CopyOptions(); + for (CopyOption option: options) { + if (option == StandardCopyOption.REPLACE_EXISTING) { + result.replaceExisting = true; + continue; + } + if (option == LinkOption.NOFOLLOW_LINKS) { + result.followLinks = false; + continue; + } + if (option == StandardCopyOption.COPY_ATTRIBUTES) { + result.copyAttributes = true; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new UnsupportedOperationException("'" + option + + "' is not a recognized copy option"); + } + return result; + } + } + + /** + * Converts the given array of options for moving a file to options suitable + * for copying the file when a move is implemented as copy + delete. + */ + private static CopyOption[] convertMoveToCopyOptions(CopyOption... options) + throws AtomicMoveNotSupportedException + { + int len = options.length; + CopyOption[] newOptions = new CopyOption[len+2]; + for (int i=0; i Objects of this type may be used with the {@link Path#copyTo copyTo} and - * {@link Path#moveTo moveTo} methods to configure how a file is copied or moved. + *

Objects of this type may be used with the {@link + * Files#copy(Path,Path,CopyOption[]) Files.copy(Path,Path,CopyOption...)}, + * {@link Files#copy(java.io.InputStream,Path,CopyOption[]) + * Files.copy(InputStream,Path,CopyOption...)} and {@link Files#move + * Files.move(Path,Path,CopyOption...)} methods to configure how a file is + * copied or moved. * *

The {@link StandardCopyOption} enumeration type defines the * standard options. diff --git a/jdk/src/share/classes/java/nio/file/DirectoryIteratorException.java b/jdk/src/share/classes/java/nio/file/DirectoryIteratorException.java index 729c84a77cd..a74369c5a22 100644 --- a/jdk/src/share/classes/java/nio/file/DirectoryIteratorException.java +++ b/jdk/src/share/classes/java/nio/file/DirectoryIteratorException.java @@ -56,7 +56,7 @@ public final class DirectoryIteratorException * if the cause is {@code null} */ public DirectoryIteratorException(IOException cause) { - super(Objects.nonNull(cause)); + super(Objects.requireNonNull(cause)); } /** diff --git a/jdk/src/share/classes/java/nio/file/DirectoryStream.java b/jdk/src/share/classes/java/nio/file/DirectoryStream.java index 5601c9d99a8..d34f8dbd450 100644 --- a/jdk/src/share/classes/java/nio/file/DirectoryStream.java +++ b/jdk/src/share/classes/java/nio/file/DirectoryStream.java @@ -54,7 +54,7 @@ import java.io.IOException; * construct to ensure that the stream is closed: *

  *   Path dir = ...
- *   try (DirectoryStream<Path> stream = dir.newDirectoryStream()) {
+ *   try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
  *       for (Path entry: stream) {
  *           ...
  *       }
@@ -97,8 +97,8 @@ import java.io.IOException;
  * both the for-each and try-with-resources constructs.
  * 
  *   List<Path> listSourceFiles(Path dir) throws IOException {
- *       List<Path> result = new ArrayList<Path>();
- *       try (DirectoryStream<Path> stream = dir.newDirectoryStream("*.{c,h,cpp,hpp,java}")) {
+ *       List<Path> result = new ArrayList<>();
+ *       try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{c,h,cpp,hpp,java}")) {
  *           for (Path entry: stream) {
  *               result.add(entry);
  *           }
@@ -113,7 +113,7 @@ import java.io.IOException;
  *
  * @since 1.7
  *
- * @see Path#newDirectoryStream
+ * @see Files#newDirectoryStream(Path)
  */
 
 public interface DirectoryStream
@@ -122,9 +122,9 @@ public interface DirectoryStream
     /**
      * An interface that is implemented by objects that decide if a directory
      * entry should be accepted or filtered. A {@code Filter} is passed as the
-     * parameter to the {@link Path#newDirectoryStream(DirectoryStream.Filter)
-     * newDirectoryStream} method when opening a directory to iterate over the
-     * entries in the directory.
+     * parameter to the {@link Files#newDirectoryStream(Path,DirectoryStream.Filter)}
+     * method when opening a directory to iterate over the entries in the
+     * directory.
      *
      * @param        the type of the directory entry
      *
diff --git a/jdk/src/share/classes/java/nio/file/FileRef.java b/jdk/src/share/classes/java/nio/file/FileRef.java
deleted file mode 100644
index fea3b7c3dfe..00000000000
--- a/jdk/src/share/classes/java/nio/file/FileRef.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.nio.file;
-
-import java.nio.file.attribute.*;
-import java.util.Map;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-
-/**
- * A reference to a file.
- *
- * 

A {@code FileRef} is an object that locates a file and defines methods to - * open the file for reading or writing. It also provides access to associated - * metadata or file attributes. - * - * @since 1.7 - * @see java.nio.file.attribute.Attributes - * @see java.io.File#toPath - */ - -public interface FileRef { - - /** - * Opens the file referenced by this object, returning an input stream to - * read from the file. The stream will not be buffered, and is not required - * to support the {@link InputStream#mark mark} or {@link InputStream#reset - * reset} methods. The stream will be safe for access by multiple concurrent - * threads. Reading commences at the beginning of the file. - * - *

The {@code options} parameter determines how the file is opened. - * If no options are present then it is equivalent to opening the file with - * the {@link StandardOpenOption#READ READ} option. In addition to the {@code - * READ} option, an implementation may also support additional implementation - * specific options. - * - * @return an input stream to read bytes from the file - * - * @throws IllegalArgumentException - * if an invalid combination of options is specified - * @throws UnsupportedOperationException - * if an unsupported option is specified - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the file. - */ - InputStream newInputStream(OpenOption... options) throws IOException; - - /** - * Opens or creates the file located by this object for writing, returning - * an output stream to write bytes to the file. - * - *

The {@code options} parameter determines how the file is opened. - * If no options are present then this method creates a new file for writing - * or truncates an existing file. In addition to the {@link StandardOpenOption - * standard} options, an implementation may also support additional - * implementation specific options. - * - *

The resulting stream will not be buffered. The stream will be safe - * for access by multiple concurrent threads. - * - * @param options - * options specifying how the file is opened - * - * @return a new output stream - * - * @throws IllegalArgumentException - * if {@code options} contains an invalid combination of options - * @throws UnsupportedOperationException - * if an unsupported option is specified - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkWrite(String) checkWrite} - * method is invoked to check write access to the file. - */ - OutputStream newOutputStream(OpenOption... options) throws IOException; - - /** - * Returns a file attribute view of a given type. - * - *

A file attribute view provides a read-only or updatable view of a - * set of file attributes. This method is intended to be used where the file - * attribute view defines type-safe methods to read or update the file - * attributes. The {@code type} parameter is the type of the attribute view - * required and the method returns an instance of that type if supported. - * The {@link BasicFileAttributeView} type supports access to the basic - * attributes of a file. Invoking this method to select a file attribute - * view of that type will always return an instance of that class. - * - *

The {@code options} array may be used to indicate how symbolic links - * are handled by the resulting file attribute view for the case that the - * file is a symbolic link. By default, symbolic links are followed. If the - * option {@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} is present then - * symbolic links are not followed. This option is ignored by implementations - * that do not support symbolic links. - * - * @param type - * the {@code Class} object corresponding to the file attribute view - * @param options - * options indicating how symbolic links are handled - * - * @return a file attribute view of the specified type, or {@code null} if - * the attribute view type is not available - * - * @throws UnsupportedOperationException - * If options contains an unsupported option. This exception is - * specified to allow the {@code LinkOption} enum be extended - * in future releases. - * - * @see Attributes#readBasicFileAttributes - */ - V getFileAttributeView(Class type, - LinkOption... options); - - /** - * Sets the value of a file attribute. - * - *

The {@code attribute} parameter identifies the attribute to be set - * and takes the form: - *

- * [view-name:]attribute-name - *
- * where square brackets [...] delineate an optional component and the - * character {@code ':'} stands for itself. - * - *

view-name is the {@link FileAttributeView#name name} of a {@link - * FileAttributeView} that identifies a set of file attributes. If not - * specified then it defaults to {@code "basic"}, the name of the file - * attribute view that identifies the basic set of file attributes common to - * many file systems. attribute-name is the name of the attribute - * within the set. - * - *

Usage Example: - * Suppose we want to set the DOS "hidden" attribute: - *

-     *    file.setAttribute("dos:hidden", true);
-     * 
- * - * @param attribute - * the attribute to set - * @param value - * the attribute value - * @param options - * options indicating how symbolic links are handled - * - * @throws UnsupportedOperationException - * if the attribute view is not available or it does not support - * updating the attribute - * @throws IllegalArgumentException - * if the attribute value is of the correct type but has an - * inappropriate value - * @throws ClassCastException - * If the attribute value is not of the expected type or is a - * collection containing elements that are not of the expected - * type - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, its {@link SecurityManager#checkWrite(String) checkWrite} - * method denies write access to the file. If this method is invoked - * to set security sensitive attributes then the security manager - * may be invoked to check for additional permissions. - */ - void setAttribute(String attribute, Object value, LinkOption... options) - throws IOException; - - /** - * Reads the value of a file attribute. - * - *

The {@code attribute} parameter identifies the attribute to be read - * and takes the form: - *

- * [view-name:]attribute-name - *
- * where square brackets [...] delineate an optional component and the - * character {@code ':'} stands for itself. - * - *

view-name is the {@link FileAttributeView#name name} of a {@link - * FileAttributeView} that identifies a set of file attributes. If not - * specified then it defaults to {@code "basic"}, the name of the file - * attribute view that identifies the basic set of file attributes common to - * many file systems. attribute-name is the name of the attribute. - * - *

The {@code options} array may be used to indicate how symbolic links - * are handled for the case that the file is a symbolic link. By default, - * symbolic links are followed and the file attribute of the final target - * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS - * NOFOLLOW_LINKS} is present then symbolic links are not followed and so - * the method returns the file attribute of the symbolic link. - * - *

Usage Example: - * Suppose we require the user ID of the file owner on a system that - * supports a "{@code unix}" view: - *

-     *    int uid = (Integer)file.getAttribute("unix:uid");
-     * 
- * - * @param attribute - * the attribute to read - * @param options - * options indicating how symbolic links are handled - * @return the attribute value or {@code null} if the attribute view - * is not available or it does not support reading the attribute - * - * reading the attribute - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, its {@link SecurityManager#checkRead(String) checkRead} - * method denies read access to the file. If this method is invoked - * to read security sensitive attributes then the security manager - * may be invoked to check for additional permissions. - */ - Object getAttribute(String attribute, LinkOption... options) throws IOException; - - /** - * Reads a set of file attributes as a bulk operation. - * - *

The {@code attributes} parameter identifies the attributes to be read - * and takes the form: - *

- * [view-name:]attribute-list - *
- * where square brackets [...] delineate an optional component and the - * character {@code ':'} stands for itself. - * - *

view-name is the {@link FileAttributeView#name name} of a {@link - * FileAttributeView} that identifies a set of file attributes. If not - * specified then it defaults to {@code "basic"}, the name of the file - * attribute view that identifies the basic set of file attributes common to - * many file systems. - * - *

The attribute-list component is a comma separated list of - * zero or more names of attributes to read. If the list contains the value - * {@code "*"} then all attributes are read. Attributes that are not supported - * are ignored and will not be present in the returned map. It is - * implementation specific if all attributes are read as an atomic operation - * with respect to other file system operations. - * - *

The following examples demonstrate possible values for the {@code - * attributes} parameter: - * - *

- *

Summary of Rounding Operations Under Different Rounding Modes

Summary of Rounding Operations Under Different Rounding Modes
Result of rounding input to one digit with the given * rounding mode
- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
{@code "*"} Read all {@link BasicFileAttributes basic-file-attributes}.
{@code "size,lastModifiedTime,lastAccessTime"} Reads the file size, last modified time, and last access time - * attributes.
{@code "posix:*"} Read all {@link PosixFileAttributes POSIX-file-attributes}..
{@code "posix:permissions,owner,size"} Reads the POSX file permissions, owner, and file size.
- * - * - *

The {@code options} array may be used to indicate how symbolic links - * are handled for the case that the file is a symbolic link. By default, - * symbolic links are followed and the file attribute of the final target - * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS - * NOFOLLOW_LINKS} is present then symbolic links are not followed and so - * the method returns the file attribute of the symbolic link. - * - * @param attributes - * The attributes to read - * @param options - * Options indicating how symbolic links are handled - * - * @return A map of the attributes returned; may be empty. The map's keys - * are the attribute names, its values are the attribute values - * - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, its {@link SecurityManager#checkRead(String) checkRead} - * method denies read access to the file. If this method is invoked - * to read security sensitive attributes then the security manager - * may be invoke to check for additional permissions. - */ - Map readAttributes(String attributes, LinkOption... options) - throws IOException; -} diff --git a/jdk/src/share/classes/java/nio/file/FileStore.java b/jdk/src/share/classes/java/nio/file/FileStore.java index 4a79cccdff5..4284a8ad5e9 100644 --- a/jdk/src/share/classes/java/nio/file/FileStore.java +++ b/jdk/src/share/classes/java/nio/file/FileStore.java @@ -32,16 +32,13 @@ import java.io.IOException; * Storage for files. A {@code FileStore} represents a storage pool, device, * partition, volume, concrete file system or other implementation specific means * of file storage. The {@code FileStore} for where a file is stored is obtained - * by invoking the {@link Path#getFileStore getFileStore} method, or all file + * by invoking the {@link Files#getFileStore getFileStore} method, or all file * stores can be enumerated by invoking the {@link FileSystem#getFileStores * getFileStores} method. * *

In addition to the methods defined by this class, a file store may support * one or more {@link FileStoreAttributeView FileStoreAttributeView} classes * that provide a read-only or updatable view of a set of file store attributes. - * File stores associated with the default provider support the {@link - * FileStoreSpaceAttributeView} to read the space related attributes of the - * file store. * * @since 1.7 */ @@ -86,6 +83,51 @@ public abstract class FileStore { */ public abstract boolean isReadOnly(); + /** + * Returns the size, in bytes, of the file store. + * + * @return the size of the file store, in bytes + * + * @throws IOException + * if an I/O error occurs + */ + public abstract long getTotalSpace() throws IOException; + + /** + * Returns the number of bytes available to this Java virtual machine on the + * file store. + * + *

The returned number of available bytes is a hint, but not a + * guarantee, that it is possible to use most or any of these bytes. The + * number of usable bytes is most likely to be accurate immediately + * after the space attributes are obtained. It is likely to be made inaccurate + * by any external I/O operations including those made on the system outside + * of this Java virtual machine. + * + * @return the number of bytes available + * + * @throws IOException + * if an I/O error occurs + */ + public abstract long getUsableSpace() throws IOException; + + /** + * Returns the number of unallocated bytes in the file store. + * + *

The returned number of unallocated bytes is a hint, but not a + * guarantee, that it is possible to use most or any of these bytes. The + * number of unallocated bytes is most likely to be accurate immediately + * after the space attributes are obtained. It is likely to be + * made inaccurate by any external I/O operations including those made on + * the system outside of this virtual machine. + * + * @return the number of unallocated bytes + * + * @throws IOException + * if an I/O error occurs + */ + public abstract long getUnallocatedSpace() throws IOException; + /** * Tells whether or not this file store supports the file attributes * identified by the given file attribute view. @@ -131,12 +173,6 @@ public abstract class FileStore { * The {@code type} parameter is the type of the attribute view required and * the method returns an instance of that type if supported. * - *

For {@code FileStore} objects created by the default provider, then - * the file stores support the {@link FileStoreSpaceAttributeView} that - * provides access to space attributes. In that case invoking this method - * with a parameter value of {@code FileStoreSpaceAttributeView.class} will - * always return an instance of that class. - * * @param type * the {@code Class} object corresponding to the attribute view * @@ -160,10 +196,6 @@ public abstract class FileStore { * a {@link FileStore AttributeView} that identifies a set of file attributes. * attribute-name is the name of the attribute. * - *

For {@code FileStore} objects created by the default provider, then - * the file stores support the {@link FileStoreSpaceAttributeView} that - * provides access to space attributes. - * *

Usage Example: * Suppose we want to know if ZFS compression is enabled (assuming the "zfs" * view is supported): diff --git a/jdk/src/share/classes/java/nio/file/FileSystem.java b/jdk/src/share/classes/java/nio/file/FileSystem.java index 8c7637a3947..15b6ca2cd0f 100644 --- a/jdk/src/share/classes/java/nio/file/FileSystem.java +++ b/jdk/src/share/classes/java/nio/file/FileSystem.java @@ -38,8 +38,8 @@ import java.io.IOException; *

The default file system, obtained by invoking the {@link FileSystems#getDefault * FileSystems.getDefault} method, provides access to the file system that is * accessible to the Java virtual machine. The {@link FileSystems} class defines - * methods to create file systems that provide access to other types of file - * systems. + * methods to create file systems that provide access to other types of (custom) + * file systems. * *

A file system is the factory for several types of objects: * @@ -214,10 +214,9 @@ public abstract class FileSystem * Suppose we want to print the space usage for all file stores: *

      *     for (FileStore store: FileSystems.getDefault().getFileStores()) {
-     *         FileStoreSpaceAttributes attrs = Attributes.readFileStoreSpaceAttributes(store);
-     *         long total = attrs.totalSpace() / 1024;
-     *         long used = (attrs.totalSpace() - attrs.unallocatedSpace()) / 1024;
-     *         long avail = attrs.usableSpace() / 1024;
+     *         long total = store.getTotalSpace() / 1024;
+     *         long used = (store.getTotalSpace() - store.getUnallocatedSpace()) / 1024;
+     *         long avail = store.getUsableSpace() / 1024;
      *         System.out.format("%-20s %12d %12d %12d%n", store, total, used, avail);
      *     }
      * 
@@ -244,7 +243,20 @@ public abstract class FileSystem public abstract Set supportedFileAttributeViews(); /** - * Converts a path string to a {@code Path}. + * Converts a path string, or a sequence of strings that when joined form + * a path string, to a {@code Path}. If {@code more} does not specify any + * elements then the value of the {@code first} parameter is the path string + * to convert. If {@code more} specifies one or more elements then each + * non-empty string, including {@code first}, is considered to be a sequence + * of name elements (see {@link Path}) and is joined to form a path string. + * The details as to how the Strings are joined is provider specific but + * typically they will be joined using the {@link #getSeparator + * name-separator} as the separator. For example, if the name separator is + * "{@code /}" and {@code getPath("/foo","bar","gus")} is invoked, then the + * path string {@code "/foo/bar/gus"} is converted to a {@code Path}. + * A {@code Path} representing an empty path is returned if {@code first} + * is the empty string and {@code more} does not contain any non-empty + * strings. * *

The parsing and conversion to a path object is inherently * implementation dependent. In the simplest case, the path string is rejected, @@ -270,18 +282,17 @@ public abstract class FileSystem * index} value indicating the first position in the {@code path} parameter * that caused the path string to be rejected. * - *

Invoking this method with an empty path string throws - * {@code InvalidPathException}. + * @param first + * the path string or initial part of the path string + * @param more + * additional strings to be joined to form the path string * - * @param path - * The path string - * - * @return A {@code Path} object + * @return the resulting {@code Path} * * @throws InvalidPathException * If the path string cannot be converted */ - public abstract Path getPath(String path); + public abstract Path getPath(String first, String... more); /** * Returns a {@code PathMatcher} that performs match operations on the @@ -290,9 +301,9 @@ public abstract class FileSystem * * The {@code syntaxAndPattern} parameter identifies the syntax and the * pattern and takes the form: - *

+ *
      * syntax:pattern
-     * 
+ *
* where {@code ':'} stands for itself. * *

A {@code FileSystem} implementation supports the "{@code glob}" and @@ -409,7 +420,7 @@ public abstract class FileSystem * @throws UnsupportedOperationException * If the pattern syntax is not known to the implementation * - * @see Path#newDirectoryStream(String) + * @see Files#newDirectoryStream(Path,String) */ public abstract PathMatcher getPathMatcher(String syntaxAndPattern); @@ -421,10 +432,8 @@ public abstract class FileSystem *

Usage Example: * Suppose we want to make "joe" the owner of a file: *

-     *     Path file = ...
-     *     UserPrincipal joe = file.getFileSystem().getUserPrincipalLookupService()
-     *         .lookupPrincipalByName("joe");
-     *     Attributes.setOwner(file, joe);
+     *     UserPrincipalLookupService lookupService = FileSystems.getDefault().getUserPrincipalLookupService();
+     *     Files.setOwner(path, lookupService.lookupPrincipalByName("joe"));
      * 
* * @throws UnsupportedOperationException diff --git a/jdk/src/share/classes/java/nio/file/FileSystems.java b/jdk/src/share/classes/java/nio/file/FileSystems.java index 3fc348b09f4..3d7ab7a20f1 100644 --- a/jdk/src/share/classes/java/nio/file/FileSystems.java +++ b/jdk/src/share/classes/java/nio/file/FileSystems.java @@ -164,8 +164,8 @@ public final class FileSystems { * to the first provider instance. The third provider class is instantiated * by invoking it with a reference to the second instance, and so on. The * last provider to be instantiated becomes the default provider; its {@code - * getFileSystem} method is invoked with the URI {@code "file:///"} to create - * the default file system. + * getFileSystem} method is invoked with the URI {@code "file:///"} to + * get a reference to the default file system. * *

Subsequent invocations of this method return the file system that was * returned by the first invocation. @@ -238,7 +238,7 @@ public final class FileSystems { * Suppose there is a provider identified by the scheme {@code "memory"} * installed: *

-     *   Map<String,String> env = new HashMap<String,String>();
+     *   Map<String,String> env = new HashMap<>();
      *   env.put("capacity", "16G");
      *   env.put("blockSize", "4k");
      *   FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"), env);
@@ -343,33 +343,25 @@ public final class FileSystems {
      *
      * 

This method makes use of specialized providers that create pseudo file * systems where the contents of one or more files is treated as a file - * system. The {@code file} parameter is a reference to an existing file - * and the {@code env} parameter is a map of provider specific properties to - * configure the file system. + * system. * *

This method iterates over the {@link FileSystemProvider#installedProviders() * installed} providers. It invokes, in turn, each provider's {@link - * FileSystemProvider#newFileSystem(FileRef,Map) newFileSystem(FileRef,Map)} method. - * If a provider returns a file system then the iteration terminates - * and the file system is returned. If none of the installed providers return - * a {@code FileSystem} then an attempt is made to locate the provider using - * the given class loader. If a provider returns a file system then the lookup - * terminates and the file system is returned. + * FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)} method + * with an empty map. If a provider returns a file system then the iteration + * terminates and the file system is returned. If none of the installed + * providers return a {@code FileSystem} then an attempt is made to locate + * the provider using the given class loader. If a provider returns a file + * system then the lookup terminates and the file system is returned. * - * @param file - * a reference to a file - * @param env - * a map of provider specific properties to configure the file system; - * may be empty + * @param path + * the path to the file * @param loader * the class loader to locate the provider or {@code null} to only * attempt to locate an installed provider * * @return a new file system * - * @throws IllegalArgumentException - * if the {@code env} parameter does not contain properties required - * by the provider, or a property value is invalid * @throws ProviderNotFoundException * if a provider supporting this file type cannot be located * @throws ServiceConfigurationError @@ -380,18 +372,18 @@ public final class FileSystems { * if a security manager is installed and it denies an unspecified * permission */ - public static FileSystem newFileSystem(FileRef file, - Map env, + public static FileSystem newFileSystem(Path path, ClassLoader loader) throws IOException { - if (file == null) + if (path == null) throw new NullPointerException(); + Map env = Collections.emptyMap(); // check installed providers for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { try { - return provider.newFileSystem(file, env); + return provider.newFileSystem(path, env); } catch (UnsupportedOperationException uoe) { } } @@ -402,7 +394,7 @@ public final class FileSystems { .load(FileSystemProvider.class, loader); for (FileSystemProvider provider: sl) { try { - return provider.newFileSystem(file, env); + return provider.newFileSystem(path, env); } catch (UnsupportedOperationException uoe) { } } diff --git a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java index b3f422e6ac0..4c0896f70c1 100644 --- a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java +++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java @@ -69,7 +69,7 @@ class FileTreeWalker { FileVisitResult result = walk(start, 0, new ArrayList()); - Objects.nonNull(result, "FileVisitor returned null"); + Objects.requireNonNull(result, "FileVisitor returned null"); } /** @@ -102,12 +102,13 @@ class FileTreeWalker { if (attrs == null) { try { try { - attrs = Attributes.readBasicFileAttributes(file, linkOptions); + attrs = Files.readAttributes(file, BasicFileAttributes.class, linkOptions); } catch (IOException x1) { if (followLinks) { try { - attrs = Attributes - .readBasicFileAttributes(file, LinkOption.NOFOLLOW_LINKS); + attrs = Files.readAttributes(file, + BasicFileAttributes.class, + LinkOption.NOFOLLOW_LINKS); } catch (IOException x2) { exc = x2; } @@ -151,7 +152,7 @@ class FileTreeWalker { } else { boolean isSameFile = false; try { - isSameFile = file.isSameFile(ancestor.file()); + isSameFile = Files.isSameFile(file, ancestor.file()); } catch (IOException x) { // ignore } catch (SecurityException x) { @@ -175,7 +176,7 @@ class FileTreeWalker { // open the directory try { - stream = file.newDirectoryStream(); + stream = Files.newDirectoryStream(file); } catch (IOException x) { return visitor.visitFileFailed(file, x); } catch (SecurityException x) { @@ -212,7 +213,11 @@ class FileTreeWalker { } finally { try { stream.close(); - } catch (IOException x) { } + } catch (IOException e) { + // IOException will be notified to postVisitDirectory + if (ioe == null) + ioe = e; + } } // invoke postVisitDirectory last diff --git a/jdk/src/share/classes/java/nio/file/FileVisitor.java b/jdk/src/share/classes/java/nio/file/FileVisitor.java index bd6bac15d59..3c507a8d443 100644 --- a/jdk/src/share/classes/java/nio/file/FileVisitor.java +++ b/jdk/src/share/classes/java/nio/file/FileVisitor.java @@ -30,8 +30,8 @@ import java.io.IOException; /** * A visitor of files. An implementation of this interface is provided to the - * {@link Files#walkFileTree walkFileTree} utility method to visit each file - * in a tree. + * {@link Files#walkFileTree Files.walkFileTree} methods to visit each file in + * a file tree. * *

Usage Examples: * Suppose we want to delete a file tree. In that case, each directory should @@ -43,19 +43,20 @@ import java.io.IOException; * public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) * throws IOException * { - * file.delete(); + * Files.delete(file); * return FileVisitResult.CONTINUE; * } * @Override * public FileVisitResult postVisitDirectory(Path dir, IOException e) * throws IOException * { - * if (e != null) { + * if (e == null) { + * Files.delete(dir); + * return FileVisitResult.CONTINUE; + * } else { * // directory iteration failed * throw e; * } - * dir.delete(); - * return FileVisitResult.CONTINUE; * } * }); *

@@ -72,10 +73,12 @@ import java.io.IOException; * public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) * throws IOException * { + * Path targetdir = target.resolve(source.relativize(dir)); * try { - * dir.copyTo(target.resolve(source.relativize(dir))); + * Files.copy(dir, targetdir); * } catch (FileAlreadyExistsException e) { - * // ignore + * if (!Files.isDirectory(targetdir)) + * throw e; * } * return CONTINUE; * } @@ -83,7 +86,7 @@ import java.io.IOException; * public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) * throws IOException * { - * file.copyTo(target.resolve(source.relativize(file))); + * Files.copy(file, target.resolve(source.relativize(file))); * return CONTINUE; * } * }); diff --git a/jdk/src/share/classes/java/nio/file/Files.java b/jdk/src/share/classes/java/nio/file/Files.java index a0f00855b74..357529ac9cf 100644 --- a/jdk/src/share/classes/java/nio/file/Files.java +++ b/jdk/src/share/classes/java/nio/file/Files.java @@ -25,16 +25,32 @@ package java.nio.file; -import java.nio.file.spi.FileTypeDetector; import java.nio.file.attribute.*; +import java.nio.file.spi.FileSystemProvider; +import java.nio.file.spi.FileTypeDetector; +import java.nio.channels.SeekableByteChannel; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; import java.io.IOException; import java.util.*; import java.security.AccessController; import java.security.PrivilegedAction; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; /** - * This class consists exclusively of static methods that operate on files or - * directories. + * This class consists exclusively of static methods that operate on files, + * directories, or other types of files. + * + *

In most cases, the methods defined here will delegate to the associated + * file system provider to perform the file operations. * * @since 1.7 */ @@ -42,8 +58,1422 @@ import java.security.PrivilegedAction; public final class Files { private Files() { } + /** + * Returns the {@code FileSystemProvider} to delegate to. + */ + private static FileSystemProvider provider(Path path) { + return path.getFileSystem().provider(); + } + + // -- File contents -- + + /** + * Opens a file, returning an input stream to read from the file. The stream + * will not be buffered, and is not required to support the {@link + * InputStream#mark mark} or {@link InputStream#reset reset} methods. The + * stream will be safe for access by multiple concurrent threads. Reading + * commences at the beginning of the file. Whether the returned stream is + * asynchronously closeable and/or interruptible is highly + * file system provider specific and therefore not specified. + * + *

The {@code options} parameter determines how the file is opened. + * If no options are present then it is equivalent to opening the file with + * the {@link StandardOpenOption#READ READ} option. In addition to the {@code + * READ} option, an implementation may also support additional implementation + * specific options. + * + * @param path + * the path to the file to open + * @param options + * options specifying how the file is opened + * + * @return a new input stream + * + * @throws IllegalArgumentException + * if an invalid combination of options is specified + * @throws UnsupportedOperationException + * if an unsupported option is specified + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file. + */ + public static InputStream newInputStream(Path path, OpenOption... options) + throws IOException + { + return provider(path).newInputStream(path, options); + } + + /** + * Opens or creates a file, returning an output stream that may be used to + * write bytes to the file. The resulting stream will not be buffered. The + * stream will be safe for access by multiple concurrent threads. Whether + * the returned stream is asynchronously closeable and/or + * interruptible is highly file system provider specific and + * therefore not specified. + * + *

This method opens or creates a file in exactly the manner specified + * by the {@link #newByteChannel(Path,Set,FileAttribute[]) newByteChannel} + * method with the exception that the {@link StandardOpenOption#READ READ} + * option may not be present in the array of options. If no options are + * present then this method works as if the {@link StandardOpenOption#CREATE + * CREATE}, {@link StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING}, + * and {@link StandardOpenOption#WRITE WRITE} options are present. In other + * words, it opens the file for writing, creating the file if it doesn't + * exist, or initially truncating an existing {@link #isRegularFile + * regular-file} to a size of {@code 0} if it exists. + * + *

Usage Examples: + *

+     *     Path path = ...
+     *
+     *     // replace an existing file or create the file if it doesn't initially exist
+     *     OutputStream out = Files.newOutputStream(path);
+     *
+     *     // append to an existing file, fail if the file does not exist
+     *     out = Files.newOutputStream(path, APPEND);
+     *
+     *     // append to an existing file, create file if it doesn't initially exist
+     *     out = Files.newOutputStream(CREATE, APPEND);
+     *
+     *     // always create new file, failing if it already exists
+     *     out = Files.newOutputStream(CREATE_NEW);
+     * 
+ * + * @param path + * the path to the file to open or create + * @param options + * options specifying how the file is opened + * + * @return a new output stream + * + * @throws IllegalArgumentException + * if {@code options} contains an invalid combination of options + * @throws UnsupportedOperationException + * if an unsupported option is specified + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to the file. The {@link + * SecurityManager#checkDelete(String) checkDelete} method is + * invoked to check delete access if the file is opened with the + * {@code DELETE_ON_CLOSE} option. + */ + public static OutputStream newOutputStream(Path path, OpenOption... options) + throws IOException + { + return provider(path).newOutputStream(path, options); + } + + /** + * Opens or creates a file, returning a seekable byte channel to access the + * file. + * + *

The {@code options} parameter determines how the file is opened. + * The {@link StandardOpenOption#READ READ} and {@link + * StandardOpenOption#WRITE WRITE} options determine if the file should be + * opened for reading and/or writing. If neither option (or the {@link + * StandardOpenOption#APPEND APPEND} option) is present then the file is + * opened for reading. By default reading or writing commence at the + * beginning of the file. + * + *

In the addition to {@code READ} and {@code WRITE}, the following + * options may be present: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Option Description
{@link StandardOpenOption#APPEND APPEND} If this option is present then the file is opened for writing and + * each invocation of the channel's {@code write} method first advances + * the position to the end of the file and then writes the requested + * data. Whether the advancement of the position and the writing of the + * data are done in a single atomic operation is system-dependent and + * therefore unspecified. This option may not be used in conjunction + * with the {@code READ} or {@code TRUNCATE_EXISTING} options.
{@link StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING} If this option is present then the existing file is truncated to + * a size of 0 bytes. This option is ignored when the file is opened only + * for reading.
{@link StandardOpenOption#CREATE_NEW CREATE_NEW} If this option is present then a new file is created, failing if + * the file already exists or is a symbolic link. When creating a file the + * check for the existence of the file and the creation of the file if it + * does not exist is atomic with respect to other file system operations. + * This option is ignored when the file is opened only for reading.
{@link StandardOpenOption#CREATE CREATE} If this option is present then an existing file is opened if it + * exists, otherwise a new file is created. This option is ignored if the + * {@code CREATE_NEW} option is also present or the file is opened only + * for reading.
{@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} When this option is present then the implementation makes a + * best effort attempt to delete the file when closed by the + * {@link SeekableByteChannel#close close} method. If the {@code close} + * method is not invoked then a best effort attempt is made to + * delete the file when the Java virtual machine terminates.
{@link StandardOpenOption#SPARSE SPARSE} When creating a new file this option is a hint that the + * new file will be sparse. This option is ignored when not creating + * a new file.
{@link StandardOpenOption#SYNC SYNC} Requires that every update to the file's content or metadata be + * written synchronously to the underlying storage device. (see Synchronized I/O file + * integrity).
{@link StandardOpenOption#DSYNC DSYNC} Requires that every update to the file's content be written + * synchronously to the underlying storage device. (see Synchronized I/O file + * integrity).
+ * + *

An implementation may also support additional implementation specific + * options. + * + *

The {@code attrs} parameter is optional {@link FileAttribute + * file-attributes} to set atomically when a new file is created. + * + *

In the case of the default provider, the returned seekable byte channel + * is a {@link java.nio.channels.FileChannel}. + * + *

Usage Examples: + *

+     *     Path path = ...
+     *
+     *     // open file for reading
+     *     ReadableByteChannel rbc = Files.newByteChannel(path, EnumSet.of(READ)));
+     *
+     *     // open file for writing to the end of an existing file, creating
+     *     // the file if it doesn't already exist
+     *     WritableByteChannel wbc = Files.newByteChannel(path, EnumSet.of(CREATE,APPEND));
+     *
+     *     // create file with initial permissions, opening it for both reading and writing
+     *     {@code FileAttribute<> perms = ...}
+     *     SeekableByteChannel sbc = Files.newByteChannel(path, EnumSet.of(CREATE_NEW,READ,WRITE), perms);
+     * 
+ * + * @param path + * the path to the file to open or create + * @param options + * options specifying how the file is opened + * @param attrs + * an optional list of file attributes to set atomically when + * creating the file + * + * @return a new seekable byte channel + * + * @throws IllegalArgumentException + * if the set contains an invalid combination of options + * @throws UnsupportedOperationException + * if an unsupported open option is specified or the array contains + * attributes that cannot be set atomically when creating the file + * @throws FileAlreadyExistsException + * if a file of that name already exists and the {@link + * StandardOpenOption#CREATE_NEW CREATE_NEW} option is specified + * (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the path if the file is + * opened for reading. The {@link SecurityManager#checkWrite(String) + * checkWrite} method is invoked to check write access to the path + * if the file is opened for writing. The {@link + * SecurityManager#checkDelete(String) checkDelete} method is + * invoked to check delete access if the file is opened with the + * {@code DELETE_ON_CLOSE} option. + * + * @see java.nio.channels.FileChannel#open(Path,Set,FileAttribute[]) + */ + public static SeekableByteChannel newByteChannel(Path path, + Set options, + FileAttribute... attrs) + throws IOException + { + return provider(path).newByteChannel(path, options, attrs); + } + + /** + * Opens or creates a file, returning a seekable byte channel to access the + * file. + * + *

This method opens or creates a file in exactly the manner specified + * by the {@link #newByteChannel(Path,Set,FileAttribute[]) newByteChannel} + * method. + * + * @param path + * the path to the file to open or create + * @param options + * options specifying how the file is opened + * + * @return a new seekable byte channel + * + * @throws IllegalArgumentException + * if the set contains an invalid combination of options + * @throws UnsupportedOperationException + * if an unsupported open option is specified + * @throws FileAlreadyExistsException + * if a file of that name already exists and the {@link + * StandardOpenOption#CREATE_NEW CREATE_NEW} option is specified + * (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the path if the file is + * opened for reading. The {@link SecurityManager#checkWrite(String) + * checkWrite} method is invoked to check write access to the path + * if the file is opened for writing. The {@link + * SecurityManager#checkDelete(String) checkDelete} method is + * invoked to check delete access if the file is opened with the + * {@code DELETE_ON_CLOSE} option. + * + * @see java.nio.channels.FileChannel#open(Path,OpenOption[]) + */ + public static SeekableByteChannel newByteChannel(Path path, OpenOption... options) + throws IOException + { + Set set = new HashSet(options.length); + Collections.addAll(set, options); + return newByteChannel(path, set); + } + + // -- Directories -- + + /** + * Opens a directory, returning a {@link DirectoryStream} to iterate over + * all entries in the directory. The elements returned by the directory + * stream's {@link DirectoryStream#iterator iterator} are of type {@code + * Path}, each one representing an entry in the directory. The {@code Path} + * objects are obtained as if by {@link Path#resolve(Path) resolving} the + * name of the directory entry against {@code dir}. + * + *

When not using the try-with-resources construct, then directory + * stream's {@code close} method should be invoked after iteration is + * completed so as to free any resources held for the open directory. + * + *

When an implementation supports operations on entries in the + * directory that execute in a race-free manner then the returned directory + * stream is a {@link SecureDirectoryStream}. + * + * @param dir + * the path to the directory + * + * @return a new and open {@code DirectoryStream} object + * + * @throws NotDirectoryException + * if the file could not otherwise be opened because it is not + * a directory (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the directory. + */ + public static DirectoryStream newDirectoryStream(Path dir) + throws IOException + { + return provider(dir).newDirectoryStream(dir, new DirectoryStream.Filter() { + @Override + public boolean accept(Path entry) { + return true; + } + }); + } + + /** + * Opens a directory, returning a {@link DirectoryStream} to iterate over + * the entries in the directory. The elements returned by the directory + * stream's {@link DirectoryStream#iterator iterator} are of type {@code + * Path}, each one representing an entry in the directory. The {@code Path} + * objects are obtained as if by {@link Path#resolve(Path) resolving} the + * name of the directory entry against {@code dir}. The entries returned by + * the iterator are filtered by matching the {@code String} representation + * of their file names against the given globbing pattern. + * + *

For example, suppose we want to iterate over the files ending with + * ".java" in a directory: + *

+     *     Path dir = ...
+     *     try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.java")) {
+     *         :
+     *     }
+     * 
+ * + *

The globbing pattern is specified by the {@link + * FileSystem#getPathMatcher getPathMatcher} method. + * + *

When not using the try-with-resources construct, then directory + * stream's {@code close} method should be invoked after iteration is + * completed so as to free any resources held for the open directory. + * + *

When an implementation supports operations on entries in the + * directory that execute in a race-free manner then the returned directory + * stream is a {@link SecureDirectoryStream}. + * + * @param dir + * the path to the directory + * @param glob + * the glob pattern + * + * @return a new and open {@code DirectoryStream} object + * + * @throws java.util.regex.PatternSyntaxException + * if the pattern is invalid + * @throws NotDirectoryException + * if the file could not otherwise be opened because it is not + * a directory (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the directory. + */ + public static DirectoryStream newDirectoryStream(Path dir, String glob) + throws IOException + { + // avoid creating a matcher if all entries are required. + if (glob.equals("*")) + return newDirectoryStream(dir); + + // create a matcher and return a filter that uses it. + FileSystem fs = dir.getFileSystem(); + final PathMatcher matcher = fs.getPathMatcher("glob:" + glob); + DirectoryStream.Filter filter = new DirectoryStream.Filter() { + @Override + public boolean accept(Path entry) { + return matcher.matches(entry.getFileName()); + } + }; + return fs.provider().newDirectoryStream(dir, filter); + } + + /** + * Opens a directory, returning a {@link DirectoryStream} to iterate over + * the entries in the directory. The elements returned by the directory + * stream's {@link DirectoryStream#iterator iterator} are of type {@code + * Path}, each one representing an entry in the directory. The {@code Path} + * objects are obtained as if by {@link Path#resolve(Path) resolving} the + * name of the directory entry against {@code dir}. The entries returned by + * the iterator are filtered by the given {@link DirectoryStream.Filter + * filter}. + * + *

When not using the try-with-resources construct, then directory + * stream's {@code close} method should be invoked after iteration is + * completed so as to free any resources held for the open directory. + * + *

Where the filter terminates due to an uncaught error or runtime + * exception then it is propagated to the {@link Iterator#hasNext() + * hasNext} or {@link Iterator#next() next} method. Where an {@code + * IOException} is thrown, it results in the {@code hasNext} or {@code + * next} method throwing a {@link DirectoryIteratorException} with the + * {@code IOException} as the cause. + * + *

When an implementation supports operations on entries in the + * directory that execute in a race-free manner then the returned directory + * stream is a {@link SecureDirectoryStream}. + * + *

Usage Example: + * Suppose we want to iterate over the files in a directory that are + * larger than 8K. + *

+     *     DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
+     *         public boolean accept(Path file) throws IOException {
+     *             return (Files.size(file) > 8192L);
+     *         }
+     *     };
+     *     Path dir = ...
+     *     try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, filter)) {
+     *         :
+     *     }
+     * 
+ * + * @param dir + * the path to the directory + * @param filter + * the directory stream filter + * + * @return a new and open {@code DirectoryStream} object + * + * @throws NotDirectoryException + * if the file could not otherwise be opened because it is not + * a directory (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the directory. + */ + public static DirectoryStream newDirectoryStream(Path dir, + DirectoryStream.Filter filter) + throws IOException + { + return provider(dir).newDirectoryStream(dir, filter); + } + + // -- Creation and deletion -- + + /** + * Creates a new and empty file, failing if the file already exists. The + * check for the existence of the file and the creation of the new file if + * it does not exist are a single operation that is atomic with respect to + * all other filesystem activities that might affect the directory. + * + *

The {@code attrs} parameter is optional {@link FileAttribute + * file-attributes} to set atomically when creating the file. Each attribute + * is identified by its {@link FileAttribute#name name}. If more than one + * attribute of the same name is included in the array then all but the last + * occurrence is ignored. + * + * @param path + * the path to the file to create + * @param attrs + * an optional list of file attributes to set atomically when + * creating the file + * + * @return the file + * + * @throws UnsupportedOperationException + * if the array contains an attribute that cannot be set atomically + * when creating the file + * @throws FileAlreadyExistsException + * if a file of that name already exists + * (optional specific exception) + * @throws IOException + * if an I/O error occurs or the parent directory does not exist + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to the new file. + */ + public static Path createFile(Path path, FileAttribute... attrs) + throws IOException + { + EnumSet options = + EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE); + newByteChannel(path, options, attrs).close(); + return path; + } + + /** + * Creates a new directory. The check for the existence of the file and the + * creation of the directory if it does not exist are a single operation + * that is atomic with respect to all other filesystem activities that might + * affect the directory. The {@link #createDirectories createDirectories} + * method should be used where it is required to create all nonexistent + * parent directories first. + * + *

The {@code attrs} parameter is optional {@link FileAttribute + * file-attributes} to set atomically when creating the directory. Each + * attribute is identified by its {@link FileAttribute#name name}. If more + * than one attribute of the same name is included in the array then all but + * the last occurrence is ignored. + * + * @param dir + * the directory to create + * @param attrs + * an optional list of file attributes to set atomically when + * creating the directory + * + * @return the directory + * + * @throws UnsupportedOperationException + * if the array contains an attribute that cannot be set atomically + * when creating the directory + * @throws FileAlreadyExistsException + * if a directory could not otherwise be created because a file of + * that name already exists (optional specific exception) + * @throws IOException + * if an I/O error occurs or the parent directory does not exist + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to the new directory. + */ + public static Path createDirectory(Path dir, FileAttribute... attrs) + throws IOException + { + provider(dir).createDirectory(dir, attrs); + return dir; + } + + /** + * Creates a directory by creating all nonexistent parent directories first. + * Unlike the {@link #createDirectory createDirectory} method, an exception + * is not thrown if the directory could not be created because it already + * exists. + * + *

The {@code attrs} parameter is optional {@link FileAttribute + * file-attributes} to set atomically when creating the nonexistent + * directories. Each file attribute is identified by its {@link + * FileAttribute#name name}. If more than one attribute of the same name is + * included in the array then all but the last occurrence is ignored. + * + *

If this method fails, then it may do so after creating some, but not + * all, of the parent directories. + * + * @param dir + * the directory to create + * + * @param attrs + * an optional list of file attributes to set atomically when + * creating the directory + * + * @return the directory + * + * @throws UnsupportedOperationException + * if the array contains an attribute that cannot be set atomically + * when creating the directory + * @throws FileAlreadyExistsException + * if {@code dir} exists but is not a directory (optional specific + * exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * in the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked prior to attempting to create a directory and + * its {@link SecurityManager#checkRead(String) checkRead} is + * invoked for each parent directory that is checked. If {@code + * dir} is not an absolute path then its {@link Path#toAbsolutePath + * toAbsolutePath} may need to be invoked to get its absolute path. + * This may invoke the security manager's {@link + * SecurityManager#checkPropertyAccess(String) checkPropertyAccess} + * method to check access to the system property {@code user.dir} + */ + public static Path createDirectories(Path dir, FileAttribute... attrs) + throws IOException + { + // attempt to create the directory + try { + createAndCheckIsDirectory(dir, attrs); + return dir; + } catch (FileAlreadyExistsException x) { + // file exists and is not a directory + throw x; + } catch (IOException x) { + // parent may not exist or other reason + } + SecurityException se = null; + try { + dir = dir.toAbsolutePath(); + } catch (SecurityException x) { + // don't have permission to get absolute path + se = x; + } + // find a decendent that exists + Path parent = dir.getParent(); + while (parent != null) { + try { + provider(parent).checkAccess(parent); + break; + } catch (NoSuchFileException x) { + // does not exist + } + parent = parent.getParent(); + } + if (parent == null) { + // unable to find existing parent + if (se != null) + throw se; + throw new IOException("Root directory does not exist"); + } + + // create directories + Path child = parent; + for (Path name: parent.relativize(dir)) { + child = child.resolve(name); + createAndCheckIsDirectory(child, attrs); + } + return dir; + } + + /** + * Used by createDirectories to attempt to create a directory. A no-op + * if the directory already exists. + */ + private static void createAndCheckIsDirectory(Path dir, + FileAttribute... attrs) + throws IOException + { + try { + createDirectory(dir, attrs); + } catch (FileAlreadyExistsException x) { + if (!isDirectory(dir, LinkOption.NOFOLLOW_LINKS)) + throw x; + } + } + + /** + * Creates a new empty file in the specified directory, using the given + * prefix and suffix strings to generate its name. The resulting + * {@code Path} is associated with the same {@code FileSystem} as the given + * directory. + * + *

The details as to how the name of the file is constructed is + * implementation dependent and therefore not specified. Where possible + * the {@code prefix} and {@code suffix} are used to construct candidate + * names in the same manner as the {@link + * java.io.File#createTempFile(String,String,File)} method. + * + *

As with the {@code File.createTempFile} methods, this method is only + * part of a temporary-file facility. Where used as a work files, + * the resulting file may be opened using the {@link + * StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} option so that the + * file is deleted when the appropriate {@code close} method is invoked. + * Alternatively, a {@link Runtime#addShutdownHook shutdown-hook}, or the + * {@link java.io.File#deleteOnExit} mechanism may be used to delete the + * file automatically. + * + *

The {@code attrs} parameter is optional {@link FileAttribute + * file-attributes} to set atomically when creating the file. Each attribute + * is identified by its {@link FileAttribute#name name}. If more than one + * attribute of the same name is included in the array then all but the last + * occurrence is ignored. When no file attributes are specified, then the + * resulting file may have more restrictive access permissions to files + * created by the {@link java.io.File#createTempFile(String,String,File)} + * method. + * + * @param dir + * the path to directory in which to create the file + * @param prefix + * the prefix string to be used in generating the file's name; + * may be {@code null} + * @param suffix + * the suffix string to be used in generating the file's name; + * may be {@code null}, in which case "{@code .tmp}" is used + * @param attrs + * an optional list of file attributes to set atomically when + * creating the file + * + * @return the path to the newly created file that did not exist before + * this method was invoked + * + * @throws IllegalArgumentException + * if the prefix or suffix parameters cannot be used to generate + * a candidate file name + * @throws UnsupportedOperationException + * if the array contains an attribute that cannot be set atomically + * when creating the directory + * @throws IOException + * if an I/O error occurs or {@code dir} does not exist + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to the file. + */ + public static Path createTempFile(Path dir, + String prefix, + String suffix, + FileAttribute... attrs) + throws IOException + { + return TempFileHelper.createTempFile(dir, prefix, suffix, attrs); + } + + /** + * Creates an empty file in the default temporary-file directory, using + * the given prefix and suffix to generate its name. The resulting {@code + * Path} is associated with the default {@code FileSystem}. + * + *

This method works in exactly the manner specified by the + * {@link #createTempFile(Path,String,String,FileAttribute[])} method for + * the case that the {@code dir} parameter is the temporary-file directory. + * + * @param prefix + * the prefix string to be used in generating the file's name; + * may be {@code null} + * @param suffix + * the suffix string to be used in generating the file's name; + * may be {@code null}, in which case "{@code .tmp}" is used + * @param attrs + * an optional list of file attributes to set atomically when + * creating the file + * + * @return the path to the newly created file that did not exist before + * this method was invoked + * + * @throws IllegalArgumentException + * if the prefix or suffix parameters cannot be used to generate + * a candidate file name + * @throws UnsupportedOperationException + * if the array contains an attribute that cannot be set atomically + * when creating the directory + * @throws IOException + * if an I/O error occurs or the temporary-file directory does not + * exist + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to the file. + */ + public static Path createTempFile(String prefix, + String suffix, + FileAttribute... attrs) + throws IOException + { + return TempFileHelper.createTempFile(null, prefix, suffix, attrs); + } + + /** + * Creates a new directory in the specified directory, using the given + * prefix to generate its name. The resulting {@code Path} is associated + * with the same {@code FileSystem} as the given directory. + * + *

The details as to how the name of the directory is constructed is + * implementation dependent and therefore not specified. Where possible + * the {@code prefix} is used to construct candidate names. + * + *

As with the {@code createTempFile} methods, this method is only + * part of a temporary-file facility. A {@link Runtime#addShutdownHook + * shutdown-hook}, or the {@link java.io.File#deleteOnExit} mechanism may be + * used to delete the directory automatically. + * + *

The {@code attrs} parameter is optional {@link FileAttribute + * file-attributes} to set atomically when creating the directory. Each + * attribute is identified by its {@link FileAttribute#name name}. If more + * than one attribute of the same name is included in the array then all but + * the last occurrence is ignored. + * + * @param dir + * the path to directory in which to create the directory + * @param prefix + * the prefix string to be used in generating the directory's name; + * may be {@code null} + * @param attrs + * an optional list of file attributes to set atomically when + * creating the directory + * + * @return the path to the newly created directory that did not exist before + * this method was invoked + * + * @throws IllegalArgumentException + * if the prefix cannot be used to generate a candidate directory name + * @throws UnsupportedOperationException + * if the array contains an attribute that cannot be set atomically + * when creating the directory + * @throws IOException + * if an I/O error occurs or {@code dir} does not exist + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access when creating the + * directory. + */ + public static Path createTempDirectory(Path dir, + String prefix, + FileAttribute... attrs) + throws IOException + { + return TempFileHelper.createTempDirectory(dir, prefix, attrs); + } + + /** + * Creates a new directory in the default temporary-file directory, using + * the given prefix and suffix to generate its name. The resulting {@code + * Path} is associated with the default {@code FileSystem}. + * + *

This method works in exactly the manner specified by {@link + * #createTempDirectory(Path,String,FileAttribute[])} method for the case + * that the {@code dir} parameter is the temporary-file directory. + * + * @param prefix + * the prefix string to be used in generating the directory's name; + * may be {@code null} + * @param attrs + * an optional list of file attributes to set atomically when + * creating the directory + * + * @return the path to the newly created directory that did not exist before + * this method was invoked + * + * @throws IllegalArgumentException + * if the prefix cannot be used to generate a candidate directory name + * @throws UnsupportedOperationException + * if the array contains an attribute that cannot be set atomically + * when creating the directory + * @throws IOException + * if an I/O error occurs or the temporary-file directory does not + * exist + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access when creating the + * directory. + */ + public static Path createTempDirectory(String prefix, + FileAttribute... attrs) + throws IOException + { + return TempFileHelper.createTempDirectory(null, prefix, attrs); + } + + /** + * Creates a symbolic link to a target (optional operation). + * + *

The {@code target} parameter is the target of the link. It may be an + * {@link Path#isAbsolute absolute} or relative path and may not exist. When + * the target is a relative path then file system operations on the resulting + * link are relative to the path of the link. + * + *

The {@code attrs} parameter is optional {@link FileAttribute + * attributes} to set atomically when creating the link. Each attribute is + * identified by its {@link FileAttribute#name name}. If more than one attribute + * of the same name is included in the array then all but the last occurrence + * is ignored. + * + *

Where symbolic links are supported, but the underlying {@link FileStore} + * does not support symbolic links, then this may fail with an {@link + * IOException}. Additionally, some operating systems may require that the + * Java virtual machine be started with implementation specific privileges to + * create symbolic links, in which case this method may throw {@code IOException}. + * + * @param link + * the path of the symbolic link to create + * @param target + * the target of the symbolic link + * @param attrs + * the array of attributes to set atomically when creating the + * symbolic link + * + * @return the path to the symbolic link + * + * @throws UnsupportedOperationException + * if the implementation does not support symbolic links or the + * array contains an attribute that cannot be set atomically when + * creating the symbolic link + * @throws FileAlreadyExistsException + * if a file with the name already exists (optional specific + * exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager + * is installed, it denies {@link LinkPermission}("symbolic") + * or its {@link SecurityManager#checkWrite(String) checkWrite} + * method denies write access to the path of the symbolic link. + */ + public static Path createSymbolicLink(Path link, Path target, + FileAttribute... attrs) + throws IOException + { + provider(link).createSymbolicLink(link, target, attrs); + return link; + } + + /** + * Creates a new link (directory entry) for an existing file (optional + * operation). + * + *

The {@code link} parameter locates the directory entry to create. + * The {@code existing} parameter is the path to an existing file. This + * method creates a new directory entry for the file so that it can be + * accessed using {@code link} as the path. On some file systems this is + * known as creating a "hard link". Whether the file attributes are + * maintained for the file or for each directory entry is file system + * specific and therefore not specified. Typically, a file system requires + * that all links (directory entries) for a file be on the same file system. + * Furthermore, on some platforms, the Java virtual machine may require to + * be started with implementation specific privileges to create hard links + * or to create links to directories. + * + * @param link + * the link (directory entry) to create + * @param existing + * a path to an existing file + * + * @return the path to the link (directory entry) + * + * @throws UnsupportedOperationException + * if the implementation does not support adding an existing file + * to a directory + * @throws FileAlreadyExistsException + * if the entry could not otherwise be created because a file of + * that name already exists (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager + * is installed, it denies {@link LinkPermission}("hard") + * or its {@link SecurityManager#checkWrite(String) checkWrite} + * method denies write access to either the link or the + * existing file. + */ + public static Path createLink(Path link, Path existing) throws IOException { + provider(link).createLink(link, existing); + return link; + } + + /** + * Deletes a file. + * + *

An implementation may require to examine the file to determine if the + * file is a directory. Consequently this method may not be atomic with respect + * to other file system operations. If the file is a symbolic link then the + * symbolic link itself, not the final target of the link, is deleted. + * + *

If the file is a directory then the directory must be empty. In some + * implementations a directory has entries for special files or links that + * are created when the directory is created. In such implementations a + * directory is considered empty when only the special entries exist. + * This method can be used with the {@link #walkFileTree walkFileTree} + * method to delete a directory and all entries in the directory, or an + * entire file-tree where required. + * + *

On some operating systems it may not be possible to remove a file when + * it is open and in use by this Java virtual machine or other programs. + * + * @param path + * the path to the file to delete + * + * @throws NoSuchFileException + * if the file does not exist (optional specific exception) + * @throws DirectoryNotEmptyException + * if the file is a directory and could not otherwise be deleted + * because the directory is not empty (optional specific + * exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkDelete(String)} method + * is invoked to check delete access to the file + */ + public static void delete(Path path) throws IOException { + provider(path).delete(path); + } + + /** + * Deletes a file if it exists. + * + *

As with the {@link #delete(Path) delete(Path)} method, an + * implementation may need to examine the file to determine if the file is a + * directory. Consequently this method may not be atomic with respect to + * other file system operations. If the file is a symbolic link, then the + * symbolic link itself, not the final target of the link, is deleted. + * + *

If the file is a directory then the directory must be empty. In some + * implementations a directory has entries for special files or links that + * are created when the directory is created. In such implementations a + * directory is considered empty when only the special entries exist. + * + *

On some operating systems it may not be possible to remove a file when + * it is open and in use by this Java virtual machine or other programs. + * + * @param path + * the path to the file to delete + * + * @return {@code true} if the file was deleted by this method; {@code + * false} if the file could not be deleted because it did not + * exist + * + * @throws DirectoryNotEmptyException + * if the file is a directory and could not otherwise be deleted + * because the directory is not empty (optional specific + * exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkDelete(String)} method + * is invoked to check delete access to the file. + */ + public static boolean deleteIfExists(Path path) throws IOException { + return provider(path).deleteIfExists(path); + } + + // -- Copying and moving files -- + + /** + * Copy a file to a target file. + * + *

This method copies a file to the target file with the {@code + * options} parameter specifying how the copy is performed. By default, the + * copy fails if the target file already exists or is a symbolic link, + * except if the source and target are the {@link #isSameFile same} file, in + * which case the method completes without copying the file. File attributes + * are not required to be copied to the target file. If symbolic links are + * supported, and the file is a symbolic link, then the final target of the + * link is copied. If the file is a directory then it creates an empty + * directory in the target location (entries in the directory are not + * copied). This method can be used with the {@link #walkFileTree + * walkFileTree} method to copy a directory and all entries in the directory, + * or an entire file-tree where required. + * + *

The {@code options} parameter may include any of the following: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Option Description
{@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} If the target file exists, then the target file is replaced if it + * is not a non-empty directory. If the target file exists and is a + * symbolic link, then the symbolic link itself, not the target of + * the link, is replaced.
{@link StandardCopyOption#COPY_ATTRIBUTES COPY_ATTRIBUTES} Attempts to copy the file attributes associated with this file to + * the target file. The exact file attributes that are copied is platform + * and file system dependent and therefore unspecified. Minimally, the + * {@link BasicFileAttributes#lastModifiedTime last-modified-time} is + * copied to the target file if supported by both the source and target + * file store. Copying of file timestamps may result in precision + * loss.
{@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} Symbolic links are not followed. If the file is a symbolic link, + * then the symbolic link itself, not the target of the link, is copied. + * It is implementation specific if file attributes can be copied to the + * new link. In other words, the {@code COPY_ATTRIBUTES} option may be + * ignored when copying a symbolic link.
+ * + *

An implementation of this interface may support additional + * implementation specific options. + * + *

Copying a file is not an atomic operation. If an {@link IOException} + * is thrown then it possible that the target file is incomplete or some of + * its file attributes have not been copied from the source file. When the + * {@code REPLACE_EXISTING} option is specified and the target file exists, + * then the target file is replaced. The check for the existence of the file + * and the creation of the new file may not be atomic with respect to other + * file system activities. + * + *

Usage Example: + * Suppose we want to copy a file into a directory, giving it the same file + * name as the source file: + *

+     *     Path source = ...
+     *     Path newdir = ...
+     *     Files.copy(source, newdir.resolve(source.getFileName());
+     * 
+ * + * @param source + * the path to the file to copy + * @param target + * the path to the target file (may be associated with a different + * provider to the source path) + * @param options + * options specifying how the copy should be done + * + * @return the path to the target file + * + * @throws UnsupportedOperationException + * if the array contains a copy option that is not supported + * @throws FileAlreadyExistsException + * if the target file exists but cannot be replaced because the + * {@code REPLACE_EXISTING} option is not specified (optional + * specific exception) + * @throws DirectoryNotEmptyException + * the {@code REPLACE_EXISTING} option is specified but the file + * cannot be replaced because it is a non-empty directory + * (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the source file, the + * {@link SecurityManager#checkWrite(String) checkWrite} is invoked + * to check write access to the target file. If a symbolic link is + * copied the security manager is invoked to check {@link + * LinkPermission}{@code ("symbolic")}. + */ + public static Path copy(Path source, Path target, CopyOption... options) + throws IOException + { + FileSystemProvider provider = provider(source); + if (provider(target) == provider) { + // same provider + provider.copy(source, target, options); + } else { + // different providers + CopyMoveHelper.copyToForeignTarget(source, target, options); + } + return target; + } + + /** + * Move or rename a file to a target file. + * + *

By default, this method attempts to move the file to the target + * file, failing if the target file exists except if the source and + * target are the {@link #isSameFile same} file, in which case this method + * has no effect. If the file is a symbolic link then the symbolic link + * itself, not the target of the link, is moved. This method may be + * invoked to move an empty directory. In some implementations a directory + * has entries for special files or links that are created when the + * directory is created. In such implementations a directory is considered + * empty when only the special entries exist. When invoked to move a + * directory that is not empty then the directory is moved if it does not + * require moving the entries in the directory. For example, renaming a + * directory on the same {@link FileStore} will usually not require moving + * the entries in the directory. When moving a directory requires that its + * entries be moved then this method fails (by throwing an {@code + * IOException}). To move a file tree may involve copying rather + * than moving directories and this can be done using the {@link + * #copy copy} method in conjunction with the {@link + * #walkFileTree Files.walkFileTree} utility method. + * + *

The {@code options} parameter may include any of the following: + * + * + * + * + * + * + * + * + * + * + *
Option Description
{@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} If the target file exists, then the target file is replaced if it + * is not a non-empty directory. If the target file exists and is a + * symbolic link, then the symbolic link itself, not the target of + * the link, is replaced.
{@link StandardCopyOption#ATOMIC_MOVE ATOMIC_MOVE} The move is performed as an atomic file system operation and all + * other options are ignored. If the target file exists then it is + * implementation specific if the existing file is replaced or this method + * fails by throwing an {@link IOException}. If the move cannot be + * performed as an atomic file system operation then {@link + * AtomicMoveNotSupportedException} is thrown. This can arise, for + * example, when the target location is on a different {@code FileStore} + * and would require that the file be copied, or target location is + * associated with a different provider to this object.
+ * + *

An implementation of this interface may support additional + * implementation specific options. + * + *

Where the move requires that the file be copied then the {@link + * BasicFileAttributes#lastModifiedTime last-modified-time} is copied to the + * new file. An implementation may also attempt to copy other file + * attributes but is not required to fail if the file attributes cannot be + * copied. When the move is performed as a non-atomic operation, and a {@code + * IOException} is thrown, then the state of the files is not defined. The + * original file and the target file may both exist, the target file may be + * incomplete or some of its file attributes may not been copied from the + * original file. + * + *

Usage Examples: + * Suppose we want to rename a file to "newname", keeping the file in the + * same directory: + *

+     *     Path source = ...
+     *     Files.move(source, source.resolveSibling("newname"));
+     * 
+ * Alternatively, suppose we want to move a file to new directory, keeping + * the same file name, and replacing any existing file of that name in the + * directory: + *
+     *     Path source = ...
+     *     Path newdir = ...
+     *     Files.move(source, newdir.resolve(source.getFileName()), REPLACE_EXISTING);
+     * 
+ * + * @param source + * the path to the file to move + * @param target + * the path to the target file (may be associated with a different + * provider to the source path) + * @param options + * options specifying how the move should be done + * + * @return the path to the target file + * + * @throws UnsupportedOperationException + * if the array contains a copy option that is not supported + * @throws FileAlreadyExistsException + * if the target file exists but cannot be replaced because the + * {@code REPLACE_EXISTING} option is not specified (optional + * specific exception) + * @throws DirectoryNotEmptyException + * the {@code REPLACE_EXISTING} option is specified but the file + * cannot be replaced because it is a non-empty directory + * (optional specific exception) + * @throws AtomicMoveNotSupportedException + * if the options array contains the {@code ATOMIC_MOVE} option but + * the file cannot be moved as an atomic file system operation. + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to both the source and + * target file. + */ + public static Path move(Path source, Path target, CopyOption... options) + throws IOException + { + FileSystemProvider provider = provider(source); + if (provider(target) == provider) { + // same provider + provider.move(source, target, options); + } else { + // different providers + CopyMoveHelper.moveToForeignTarget(source, target, options); + } + return target; + } + + // -- Miscellenous -- + + /** + * Reads the target of a symbolic link (optional operation). + * + *

If the file system supports symbolic + * links then this method is used to read the target of the link, failing + * if the file is not a symbolic link. The target of the link need not exist. + * The returned {@code Path} object will be associated with the same file + * system as {@code link}. + * + * @param link + * the path to the symbolic link + * + * @return a {@code Path} object representing the target of the link + * + * @throws UnsupportedOperationException + * if the implementation does not support symbolic links + * @throws NotLinkException + * if the target could otherwise not be read because the file + * is not a symbolic link (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager + * is installed, it checks that {@code FilePermission} has been + * granted with the "{@code readlink}" action to read the link. + */ + public static Path readSymbolicLink(Path link) throws IOException { + return provider(link).readSymbolicLink(link); + } + + /** + * Returns the {@link FileStore} representing the file store where a file + * is located. + * + *

Once a reference to the {@code FileStore} is obtained it is + * implementation specific if operations on the returned {@code FileStore}, + * or {@link FileStoreAttributeView} objects obtained from it, continue + * to depend on the existence of the file. In particular the behavior is not + * defined for the case that the file is deleted or moved to a different + * file store. + * + * @param path + * the path to the file + * + * @return the file store where the file is stored + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file, and in + * addition it checks {@link RuntimePermission} + * ("getFileStoreAttributes") + */ + public static FileStore getFileStore(Path path) throws IOException { + return provider(path).getFileStore(path); + } + + /** + * Tests if two paths locate the same file. + * + *

If both {@code Path} objects are {@link Path#equals(Object) equal} + * then this method returns {@code true} without checking if the file exists. + * If the two {@code Path} objects are associated with different providers + * then this method returns {@code false}. Otherwise, this method checks if + * both {@code Path} objects locate the same file, and depending on the + * implementation, may require to open or access both files. + * + *

If the file system and files remain static, then this method implements + * an equivalence relation for non-null {@code Paths}. + *

    + *
  • It is reflexive: for {@code Path} {@code f}, + * {@code isSameFile(f,f)} should return {@code true}. + *
  • It is symmetric: for two {@code Paths} {@code f} and {@code g}, + * {@code isSameFile(f,g)} will equal {@code isSameFile(g,f)}. + *
  • It is transitive: for three {@code Paths} + * {@code f}, {@code g}, and {@code h}, if {@code isSameFile(f,g)} returns + * {@code true} and {@code isSameFile(g,h)} returns {@code true}, then + * {@code isSameFile(g,h)} will return return {@code true}. + *
+ * + * @param path + * one path to the file + * @param path2 + * the other path + * + * @return {@code true} if, and only if, the two paths locate the same file + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to both files. + * + * @see java.nio.file.attribute.BasicFileAttributes#fileKey + */ + public static boolean isSameFile(Path path, Path path2) throws IOException { + return provider(path).isSameFile(path, path2); + } + + /** + * Tells whether or not a file is considered hidden. The exact + * definition of hidden is platform or provider dependent. On UNIX for + * example a file is considered to be hidden if its name begins with a + * period character ('.'). On Windows a file is considered hidden if it + * isn't a directory and the DOS {@link DosFileAttributes#isHidden hidden} + * attribute is set. + * + *

Depending on the implementation this method may require to access + * the file system to determine if the file is considered hidden. + * + * @param path + * the path to the file to test + * + * @return {@code true} if the file is considered hidden + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file. + */ + public static boolean isHidden(Path path) throws IOException { + return provider(path).isHidden(path); + } + // lazy loading of default and installed file type detectors - private static class DefaultFileTypeDetectorHolder { + private static class FileTypeDetectors{ static final FileTypeDetector defaultFileTypeDetector = sun.nio.fs.DefaultFileTypeDetector.create(); static final List installeDetectors = @@ -54,7 +1484,7 @@ public final class Files { return AccessController .doPrivileged(new PrivilegedAction>() { @Override public List run() { - List list = new ArrayList(); + List list = new ArrayList<>(); ServiceLoader loader = ServiceLoader .load(FileTypeDetector.class, ClassLoader.getSystemClassLoader()); for (FileTypeDetector detector: loader) { @@ -100,33 +1530,948 @@ public final class Files { * Message Bodies. The string is guaranteed to be parsable according * to the grammar in the RFC. * - * @param file - * The file reference + * @param path + * the path to the file to probe * * @return The content type of the file, or {@code null} if the content * type cannot be determined * * @throws IOException - * If an I/O error occurs + * if an I/O error occurs * @throws SecurityException * If a security manager is installed and it denies an unspecified * permission required by a file type detector implementation. */ - public static String probeContentType(FileRef file) + public static String probeContentType(Path path) throws IOException { // try installed file type detectors - for (FileTypeDetector detector: DefaultFileTypeDetectorHolder.installeDetectors) { - String result = detector.probeContentType(file); + for (FileTypeDetector detector: FileTypeDetectors.installeDetectors) { + String result = detector.probeContentType(path); if (result != null) return result; } // fallback to default - return DefaultFileTypeDetectorHolder.defaultFileTypeDetector - .probeContentType(file); + return FileTypeDetectors.defaultFileTypeDetector.probeContentType(path); } + // -- File Attributes -- + + /** + * Returns a file attribute view of a given type. + * + *

A file attribute view provides a read-only or updatable view of a + * set of file attributes. This method is intended to be used where the file + * attribute view defines type-safe methods to read or update the file + * attributes. The {@code type} parameter is the type of the attribute view + * required and the method returns an instance of that type if supported. + * The {@link BasicFileAttributeView} type supports access to the basic + * attributes of a file. Invoking this method to select a file attribute + * view of that type will always return an instance of that class. + * + *

The {@code options} array may be used to indicate how symbolic links + * are handled by the resulting file attribute view for the case that the + * file is a symbolic link. By default, symbolic links are followed. If the + * option {@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} is present then + * symbolic links are not followed. This option is ignored by implementations + * that do not support symbolic links. + * + *

Usage Example: + * Suppose we want read or set a file's ACL, if supported: + *

+     *     Path path = ...
+     *     AclFileAttributeView view = Files.getFileAttributeView(path, AclFileAttributeView.class);
+     *     if (view != null) {
+     *         List<AclEntry> acl = view.getAcl();
+     *         :
+     *     }
+     * 
+ * + * + * @param path + * the path to the file + * @param type + * the {@code Class} object corresponding to the file attribute view + * @param options + * options indicating how symbolic links are handled + * + * @return a file attribute view of the specified type, or {@code null} if + * the attribute view type is not available + */ + public static V getFileAttributeView(Path path, + Class type, + LinkOption... options) + { + return provider(path).getFileAttributeView(path, type, options); + } + + /** + * Reads a file's attributes as a bulk operation. + * + *

The {@code type} parameter is the type of the attributes required + * and this method returns an instance of that type if supported. All + * implementations support a basic set of file attributes and so invoking + * this method with a {@code type} parameter of {@code + * BasicFileAttributes.class} will not throw {@code + * UnsupportedOperationException}. + * + *

The {@code options} array may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed and the file attribute of the final target + * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed. + * + *

It is implementation specific if all file attributes are read as an + * atomic operation with respect to other file system operations. + * + *

Usage Example: + * Suppose we want to read a file's attributes in bulk: + *

+     *    Path path = ...
+     *    BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
+     * 
+ * Alternatively, suppose we want to read file's POSIX attributes without + * following symbolic links: + *
+     *    PosixFileAttributes attrs = Files.readAttributes(path, PosixFileAttributes.class, NOFOLLOW_LINKS);
+     * 
+ * + * @param path + * the path to the file + * @param type + * the {@code Class} of the file attributes required + * to read + * @param options + * options indicating how symbolic links are handled + * + * @return the file attributes + * + * @throws UnsupportedOperationException + * if an attributes of the given type are not supported + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file. If this + * method is invoked to read security sensitive attributes then the + * security manager may be invoke to check for additional permissions. + */ + public static A readAttributes(Path path, + Class type, + LinkOption... options) + throws IOException + { + return provider(path).readAttributes(path, type, options); + } + + /** + * Sets the value of a file attribute. + * + *

The {@code attribute} parameter identifies the attribute to be set + * and takes the form: + *

+ * [view-name:]attribute-name + *
+ * where square brackets [...] delineate an optional component and the + * character {@code ':'} stands for itself. + * + *

view-name is the {@link FileAttributeView#name name} of a {@link + * FileAttributeView} that identifies a set of file attributes. If not + * specified then it defaults to {@code "basic"}, the name of the file + * attribute view that identifies the basic set of file attributes common to + * many file systems. attribute-name is the name of the attribute + * within the set. + * + *

The {@code options} array may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed and the file attribute of the final target + * of the link is set. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed. + * + *

Usage Example: + * Suppose we want to set the DOS "hidden" attribute: + *

+     *    Path path = ...
+     *    Files.setAttribute(path, "dos:hidden", true);
+     * 
+ * + * @param path + * the path to the file + * @param attribute + * the attribute to set + * @param value + * the attribute value + * @param options + * options indicating how symbolic links are handled + * + * @return the {@code path} parameter + * + * @throws UnsupportedOperationException + * if the attribute view is not available or it does not support + * updating the attribute + * @throws IllegalArgumentException + * if the attribute value is of the correct type but has an + * inappropriate value + * @throws ClassCastException + * if the attribute value is not of the expected type or is a + * collection containing elements that are not of the expected + * type + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkWrite(String) checkWrite} + * method denies write access to the file. If this method is invoked + * to set security sensitive attributes then the security manager + * may be invoked to check for additional permissions. + */ + public static Path setAttribute(Path path, String attribute, Object value, + LinkOption... options) + throws IOException + { + provider(path).setAttribute(path, attribute, value, options); + return path; + } + + /** + * Reads the value of a file attribute. + * + *

The {@code attribute} parameter identifies the attribute to be read + * and takes the form: + *

+ * [view-name:]attribute-name + *
+ * where square brackets [...] delineate an optional component and the + * character {@code ':'} stands for itself. + * + *

view-name is the {@link FileAttributeView#name name} of a {@link + * FileAttributeView} that identifies a set of file attributes. If not + * specified then it defaults to {@code "basic"}, the name of the file + * attribute view that identifies the basic set of file attributes common to + * many file systems. attribute-name is the name of the attribute. + * + *

The {@code options} array may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed and the file attribute of the final target + * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed. + * + *

Usage Example: + * Suppose we require the user ID of the file owner on a system that + * supports a "{@code unix}" view: + *

+     *    Path path = ...
+     *    int uid = (Integer)Files.getAttribute(path, "unix:uid");
+     * 
+ * + * @param path + * the path to the file + * @param attribute + * the attribute to read + * @param options + * options indicating how symbolic links are handled + * + * @return the attribute value or {@code null} if the attribute view + * is not available or it does not support reading the attribute + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method denies read access to the file. If this method is invoked + * to read security sensitive attributes then the security manager + * may be invoked to check for additional permissions. + */ + public static Object getAttribute(Path path, String attribute, + LinkOption... options) + throws IOException + { + // only one attribute should be read + if (attribute.indexOf('*') >= 0 || attribute.indexOf(',') >= 0) + return null; + Map map = readAttributes(path, attribute, options); + String name; + int pos = attribute.indexOf(':'); + if (pos == -1) { + name = attribute; + } else { + name = (pos == attribute.length()) ? "" : attribute.substring(pos+1); + } + return map.get(name); + } + + /** + * Reads a set of file attributes as a bulk operation. + * + *

The {@code attributes} parameter identifies the attributes to be read + * and takes the form: + *

+ * [view-name:]attribute-list + *
+ * where square brackets [...] delineate an optional component and the + * character {@code ':'} stands for itself. + * + *

view-name is the {@link FileAttributeView#name name} of a {@link + * FileAttributeView} that identifies a set of file attributes. If not + * specified then it defaults to {@code "basic"}, the name of the file + * attribute view that identifies the basic set of file attributes common to + * many file systems. + * + *

The attribute-list component is a comma separated list of + * zero or more names of attributes to read. If the list contains the value + * {@code "*"} then all attributes are read. Attributes that are not supported + * are ignored and will not be present in the returned map. It is + * implementation specific if all attributes are read as an atomic operation + * with respect to other file system operations. + * + *

The following examples demonstrate possible values for the {@code + * attributes} parameter: + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
{@code "*"} Read all {@link BasicFileAttributes basic-file-attributes}.
{@code "size,lastModifiedTime,lastAccessTime"} Reads the file size, last modified time, and last access time + * attributes.
{@code "posix:*"} Read all {@link PosixFileAttributes POSIX-file-attributes}.
{@code "posix:permissions,owner,size"} Reads the POSX file permissions, owner, and file size.
+ *
+ * + *

The {@code options} array may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed and the file attribute of the final target + * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed. + * + * @param path + * the path to the file + * @param attributes + * the attributes to read + * @param options + * options indicating how symbolic links are handled + * + * @return a map of the attributes returned; may be empty. The map's keys + * are the attribute names, its values are the attribute values + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method denies read access to the file. If this method is invoked + * to read security sensitive attributes then the security manager + * may be invoke to check for additional permissions. + */ + public static Map readAttributes(Path path, String attributes, + LinkOption... options) + throws IOException + { + return provider(path).readAttributes(path, attributes, options); + } + + /** + * Returns a file's POSIX file permissions. + * + *

The {@code path} parameter is associated with a {@code FileSystem} + * that supports the {@link PosixFileAttributeView}. This attribute view + * provides access to file attributes commonly associated with files on file + * systems used by operating systems that implement the Portable Operating + * System Interface (POSIX) family of standards. + * + *

The {@code options} array may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed and the file attribute of the final target + * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed. + * + * @param path + * the path to the file + * @param options + * options indicating how symbolic links are handled + * + * @return the file permissions + * + * @throws UnsupportedOperationException + * if the associated file system does not support the {@code + * PosixFileAttributeView} + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, a security manager is + * installed, and it denies {@link RuntimePermission}("accessUserInformation") + * or its {@link SecurityManager#checkRead(String) checkRead} method + * denies read access to the file. + */ + public static Set getPosixFilePermissions(Path path, + LinkOption... options) + throws IOException + { + return readAttributes(path, PosixFileAttributes.class, options).permissions(); + } + + /** + * Sets a file's POSIX permissions. + * + *

The {@code path} parameter is associated with a {@code FileSystem} + * that supports the {@link PosixFileAttributeView}. This attribute view + * provides access to file attributes commonly associated with files on file + * systems used by operating systems that implement the Portable Operating + * System Interface (POSIX) family of standards. + * + * @param path + * A file reference that locates the file + * @param perms + * The new set of permissions + * + * @throws UnsupportedOperationException + * if the associated file system does not support the {@code + * PosixFileAttributeView} + * @throws ClassCastException + * if the sets contains elements that are not of type {@code + * PosixFilePermission} + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, it denies {@link RuntimePermission}("accessUserInformation") + * or its {@link SecurityManager#checkWrite(String) checkWrite} + * method denies write access to the file. + */ + public static Path setPosixFilePermissions(Path path, + Set perms) + throws IOException + { + PosixFileAttributeView view = + getFileAttributeView(path, PosixFileAttributeView.class); + if (view == null) + throw new UnsupportedOperationException(); + view.setPermissions(perms); + return path; + } + + /** + * Returns the owner of a file. + * + *

The {@code path} parameter is associated with a file system that + * supports {@link FileOwnerAttributeView}. This file attribute view provides + * access to a file attribute that is the owner of the file. + * + * @param path + * A file reference that locates the file + * @param options + * options indicating how symbolic links are handled + * + * @return A user principal representing the owner of the file + * + * @throws UnsupportedOperationException + * if the associated file system does not support the {@code + * FileOwnerAttributeView} + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, it denies {@link RuntimePermission}("accessUserInformation") + * or its {@link SecurityManager#checkRead(String) checkRead} method + * denies read access to the file. + */ + public static UserPrincipal getOwner(Path path, LinkOption... options) throws IOException { + FileOwnerAttributeView view = + getFileAttributeView(path, FileOwnerAttributeView.class, options); + if (view == null) + throw new UnsupportedOperationException(); + return view.getOwner(); + } + + /** + * Updates the file owner. + * + *

The {@code path} parameter is associated with a file system that + * supports {@link FileOwnerAttributeView}. This file attribute view provides + * access to a file attribute that is the owner of the file. + * + *

Usage Example: + * Suppose we want to make "joe" the owner of a file: + *

+     *     Path path = ...
+     *     UserPrincipalLookupService lookupService =
+     *         provider(path).getUserPrincipalLookupService();
+     *     UserPrincipal joe = lookupService.lookupPrincipalByName("joe");
+     *     Files.setOwner(path, joe);
+     * 
+ * + * @param path + * A file reference that locates the file + * @param owner + * The new file owner + * + * @throws UnsupportedOperationException + * if the associated file system does not support the {@code + * FileOwnerAttributeView} + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, it denies {@link RuntimePermission}("accessUserInformation") + * or its {@link SecurityManager#checkWrite(String) checkWrite} + * method denies write access to the file. + * + * @see FileSystem#getUserPrincipalLookupService + * @see java.nio.file.attribute.UserPrincipalLookupService + */ + public static Path setOwner(Path path, UserPrincipal owner) + throws IOException + { + FileOwnerAttributeView view = + getFileAttributeView(path, FileOwnerAttributeView.class); + if (view == null) + throw new UnsupportedOperationException(); + view.setOwner(owner); + return path; + } + + /** + * Tests whether a file is a symbolic link. + * + *

Where is it required to distinguish an I/O exception from the case + * that the file is not a symbolic link then the file attributes can be + * read with the {@link #readAttributes(Path,Class,LinkOption[]) + * readAttributes} method and the file type tested with the {@link + * BasicFileAttributes#isSymbolicLink} method. + * + * @return {@code true} if the file is a symbolic link; {@code false} if + * the file does not exist, is not a symbolic link, or it cannot + * be determined if the file is symbolic link or not. + * + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method denies read access to the file. + */ + public static boolean isSymbolicLink(Path path) { + try { + return readAttributes(path, + BasicFileAttributes.class, + LinkOption.NOFOLLOW_LINKS).isSymbolicLink(); + } catch (IOException ioe) { + return false; + } + } + + /** + * Tests whether a file is a directory. + * + *

The {@code options} array may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed and the file attribute of the final target + * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed. + * + *

Where is it required to distinguish an I/O exception from the case + * that the file is not a directory then the file attributes can be + * read with the {@link #readAttributes(Path,Class,LinkOption[]) + * readAttributes} method and the file type tested with the {@link + * BasicFileAttributes#isDirectory} method. + * + * @param path + * the path to the file to test + * @param options + * options indicating how symbolic links are handled + * + * @return {@code true} if the file is a directory; {@code false} if + * the file does not exist, is not a directory, or it cannot + * be determined if the file is directory or not. + * + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method denies read access to the file. + */ + public static boolean isDirectory(Path path, LinkOption... options) { + try { + return readAttributes(path, BasicFileAttributes.class, options).isDirectory(); + } catch (IOException ioe) { + return false; + } + } + + /** + * Tests whether a file is a regular file with opaque content. + * + *

The {@code options} array may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed and the file attribute of the final target + * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed. + * + *

Where is it required to distinguish an I/O exception from the case + * that the file is not a regular file then the file attributes can be + * read with the {@link #readAttributes(Path,Class,LinkOption[]) + * readAttributes} method and the file type tested with the {@link + * BasicFileAttributes#isRegularFile} method. + * + * @param path + * the path to the file + * @param options + * options indicating how symbolic links are handled + * + * @return {@code true} if the file is a regular file; {@code false} if + * the file does not exist, is not a direcregular filetory, or it + * cannot be determined if the file is regular file or not. + * + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method denies read access to the file. + */ + public static boolean isRegularFile(Path path, LinkOption... options) { + try { + return readAttributes(path, BasicFileAttributes.class, options).isRegularFile(); + } catch (IOException ioe) { + return false; + } + } + + /** + * Returns a file's last modified time. + * + *

The {@code options} array may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed and the file attribute of the final target + * of the link is read. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed. + * + * @param path + * the path to the file + * @param options + * options indicating how symbolic links are handled + * + * @return a {@code FileTime} representing the time the file was last + * modified, or an implementation specific default when a time + * stamp to indicate the time of last modification is not supported + * by the file system + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method denies read access to the file. + * + * @see BasicFileAttributes#lastModifiedTime + */ + public static FileTime getLastModifiedTime(Path path, LinkOption... options) + throws IOException + { + return readAttributes(path, BasicFileAttributes.class, options).lastModifiedTime(); + } + + /** + * Updates a file's last modified time attribute. The file time is converted + * to the epoch and precision supported by the file system. Converting from + * finer to coarser granularities result in precision loss. The behavior of + * this method when attempting to set the last modified time when it is not + * supported by the file system or is outside the range supported by the + * underlying file store is not defined. It may or not fail by throwing an + * {@code IOException}. + * + *

Usage Example: + * Suppose we want to set the last modified time to the current time: + *

+     *    Path path = ...
+     *    FileTime now = FileTime.fromMillis(System.currentTimeMillis());
+     *    Files.setLastModifiedTime(path, now);
+     * 
+ * + * @param path + * the path to the file + * @param time + * the new last modified time + * + * @return the file + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, the security manager's {@link + * SecurityManager#checkWrite(String) checkWrite} method is invoked + * to check write access to file + * + * @see BasicFileAttributeView#setTimes + */ + public static Path setLastModifiedTime(Path path, FileTime time) + throws IOException + { + getFileAttributeView(path, BasicFileAttributeView.class) + .setTimes(time, null, null); + return path; + } + + /** + * Returns the size of a file (in bytes). The size may differ from the + * actual size on the file system due to compression, support for sparse + * files, or other reasons. The size of files that are not {@link + * #isRegularFile regular} files is implementation specific and + * therefore unspecified. + * + * @param path + * the path to the file + * + * @return the file size, in bytes + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method denies read access to the file. + * + * @see BasicFileAttributes#size + */ + public static long size(Path path) throws IOException { + return readAttributes(path, BasicFileAttributes.class).size(); + } + + // -- Accessibility -- + + /** + * Returns {@code false} if NOFOLLOW_LINKS is present. + */ + private static boolean followLinks(LinkOption... options) { + boolean followLinks = true; + for (LinkOption opt: options) { + if (opt == LinkOption.NOFOLLOW_LINKS) { + followLinks = false; + continue; + } + if (opt == null) + throw new NullPointerException(); + throw new AssertionError("Should not get here"); + } + return followLinks; + } + + /** + * Tests whether a file exists. + * + *

The {@code options} parameter may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed. + * + *

Note that the result of this method is immediately outdated. If this + * method indicates the file exists then there is no guarantee that a + * subsequence access will succeed. Care should be taken when using this + * method in security sensitive applications. + * + * @param path + * the path to the file to test + * @param options + * options indicating how symbolic links are handled + * . + * @return {@code true} if the file exists; {@code false} if the file does + * not exist or its existence cannot be determined. + * + * @throws SecurityException + * In the case of the default provider, the {@link + * SecurityManager#checkRead(String)} is invoked to check + * read access to the file. + * + * @see #notExists + */ + public static boolean exists(Path path, LinkOption... options) { + try { + if (followLinks(options)) { + provider(path).checkAccess(path); + } else { + // attempt to read attributes without following links + readAttributes(path, BasicFileAttributes.class, + LinkOption.NOFOLLOW_LINKS); + } + // file exists + return true; + } catch (IOException x) { + // does not exist or unable to determine if file exists + return false; + } + + } + + /** + * Tests whether the file located by this path does not exist. This method + * is intended for cases where it is required to take action when it can be + * confirmed that a file does not exist. + * + *

The {@code options} parameter may be used to indicate how symbolic links + * are handled for the case that the file is a symbolic link. By default, + * symbolic links are followed. If the option {@link LinkOption#NOFOLLOW_LINKS + * NOFOLLOW_LINKS} is present then symbolic links are not followed. + * + *

Note that this method is not the complement of the {@link #exists + * exists} method. Where it is not possible to determine if a file exists + * or not then both methods return {@code false}. As with the {@code exists} + * method, the result of this method is immediately outdated. If this + * method indicates the file does exist then there is no guarantee that a + * subsequence attempt to create the file will succeed. Care should be taken + * when using this method in security sensitive applications. + * + * @param path + * the path to the file to test + * @param options + * options indicating how symbolic links are handled + * + * @return {@code true} if the file does not exist; {@code false} if the + * file exists or its existence cannot be determined + * + * @throws SecurityException + * In the case of the default provider, the {@link + * SecurityManager#checkRead(String)} is invoked to check + * read access to the file. + */ + public static boolean notExists(Path path, LinkOption... options) { + try { + if (followLinks(options)) { + provider(path).checkAccess(path); + } else { + // attempt to read attributes without following links + readAttributes(path, BasicFileAttributes.class, + LinkOption.NOFOLLOW_LINKS); + } + // file exists + return false; + } catch (NoSuchFileException x) { + // file confirmed not to exist + return true; + } catch (IOException x) { + return false; + } + } + + /** + * Used by isReadbale, isWritable, isExecutable to test access to a file. + */ + private static boolean isAccessible(Path path, AccessMode... modes) { + try { + provider(path).checkAccess(path, modes); + return true; + } catch (IOException x) { + return false; + } + } + + /** + * Tests whether a file is readable. This method checks that a file exists + * and that this Java virtual machine has appropriate privileges that would + * allow it open the file for reading. Depending on the implementation, this + * method may require to read file permissions, access control lists, or + * other file attributes in order to check the effective access to the file. + * Consequently, this method may not be atomic with respect to other file + * system operations. + * + *

Note that the result of this method is immediately outdated, there is + * no guarantee that a subsequent attempt to open the file for reading will + * succeed (or even that it will access the same file). Care should be taken + * when using this method in security sensitive applications. + * + * @param path + * the path to the file to check + * + * @return {@code true} if the file exists and is readable; {@code false} + * if the file does not exist, read access would be denied because + * the Java virtual machine has insufficient privileges, or access + * cannot be determined + * + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * is invoked to check read access to the file. + */ + public static boolean isReadable(Path path) { + return isAccessible(path, AccessMode.READ); + } + + /** + * Tests whether a file is writable. This method checks that a file exists + * and that this Java virtual machine has appropriate privileges that would + * allow it open the file for writing. Depending on the implementation, this + * method may require to read file permissions, access control lists, or + * other file attributes in order to check the effective access to the file. + * Consequently, this method may not be atomic with respect to other file + * system operations. + * + *

Note that result of this method is immediately outdated, there is no + * guarantee that a subsequent attempt to open the file for writing will + * succeed (or even that it will access the same file). Care should be taken + * when using this method in security sensitive applications. + * + * @param path + * the path to the file to check + * + * @return {@code true} if the file exists and is writable; {@code false} + * if the file does not exist, write access would be denied because + * the Java virtual machine has insufficient privileges, or access + * cannot be determined + * + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * is invoked to check write access to the file. + */ + public static boolean isWritable(Path path) { + return isAccessible(path, AccessMode.WRITE); + } + + /** + * Tests whether a file is executable. This method checks that a file exists + * and that this Java virtual machine has appropriate privileges to {@link + * Runtime#exec execute} the file. The semantics may differ when checking + * access to a directory. For example, on UNIX systems, checking for + * execute access checks that the Java virtual machine has permission to + * search the directory in order to access file or subdirectories. + * + *

Depending on the implementation, this method may require to read file + * permissions, access control lists, or other file attributes in order to + * check the effective access to the file. Consequently, this method may not + * be atomic with respect to other file system operations. + * + *

Note that the result of this method is immediately outdated, there is + * no guarantee that a subsequent attempt to execute the file will succeed + * (or even that it will access the same file). Care should be taken when + * using this method in security sensitive applications. + * + * @param path + * the path to the file to check + * + * @return {@code true} if the file exists and is executable; {@code false} + * if the file does not exist, execute access would be denied because + * the Java virtual machine has insufficient privileges, or access + * cannot be determined + * + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkExec(String) + * checkExec} is invoked to check execute access to the file. + */ + public static boolean isExecutable(Path path) { + return isAccessible(path, AccessMode.EXECUTE); + } + + // -- Recursive operations -- + /** * Walks a file tree. * @@ -139,7 +2484,7 @@ public final class Files { * an uncaught error, or runtime exception, then the traversal is terminated * and the error or exception is propagated to the caller of this method. * - *

For each file encountered this method attempts to gets its {@link + *

For each file encountered this method attempts to read its {@link * java.nio.file.attribute.BasicFileAttributes}. If the file is not a * directory then the {@link FileVisitor#visitFile visitFile} method is * invoked with the file attributes. If the file attributes cannot be read, @@ -174,7 +2519,7 @@ public final class Files { * arises when there is an entry in a directory that is an ancestor of the * directory. Cycle detection is done by recording the {@link * java.nio.file.attribute.BasicFileAttributes#fileKey file-key} of directories, - * or if file keys are not available, by invoking the {@link Path#isSameFile + * or if file keys are not available, by invoking the {@link #isSameFile * isSameFile} method to test if a directory is the same file as an * ancestor. When a cycle is detected it is treated as an I/O error, and the * {@link FileVisitor#visitFileFailed visitFileFailed} method is invoked with @@ -197,25 +2542,27 @@ public final class Files { * that file (or directory). * * @param start - * The starting file + * the starting file * @param options - * Options to configure the traversal + * options to configure the traversal * @param maxDepth - * The maximum number of directory levels to visit + * the maximum number of directory levels to visit * @param visitor - * The file visitor to invoke for each file + * the file visitor to invoke for each file + * + * @return the starting file * * @throws IllegalArgumentException - * If the {@code maxDepth} parameter is negative + * if the {@code maxDepth} parameter is negative * @throws SecurityException * If the security manager denies access to the starting file. * In the case of the default provider, the {@link * SecurityManager#checkRead(String) checkRead} method is invoked * to check read access to the directory. * @throws IOException - * If an I/O error is thrown by a visitor method + * if an I/O error is thrown by a visitor method */ - public static void walkFileTree(Path start, + public static Path walkFileTree(Path start, Set options, int maxDepth, FileVisitor visitor) @@ -224,6 +2571,7 @@ public final class Files { if (maxDepth < 0) throw new IllegalArgumentException("'maxDepth' is negative"); new FileTreeWalker(options, visitor, maxDepth).walk(start); + return start; } /** @@ -234,11 +2582,15 @@ public final class Files { *

      * walkFileTree(start, EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE, visitor)
      * 
+ * In other words, it does not follow symbolic links, and visits all levels + * of the file level. * * @param start - * The starting file + * the starting file * @param visitor - * The file visitor to invoke for each file + * the file visitor to invoke for each file + * + * @return the starting file * * @throws SecurityException * If the security manager denies access to the starting file. @@ -246,118 +2598,511 @@ public final class Files { * SecurityManager#checkRead(String) checkRead} method is invoked * to check read access to the directory. * @throws IOException - * If an I/O error is thrown by a visitor method + * if an I/O error is thrown by a visitor method */ - public static void walkFileTree(Path start, FileVisitor visitor) + public static Path walkFileTree(Path start, FileVisitor visitor) throws IOException { - walkFileTree(start, - EnumSet.noneOf(FileVisitOption.class), - Integer.MAX_VALUE, - visitor); + return walkFileTree(start, + EnumSet.noneOf(FileVisitOption.class), + Integer.MAX_VALUE, + visitor); + } + + + // -- Utility methods for simple usages -- + + // buffer size used for reading and writing + private static final int BUFFER_SIZE = 8192; + + /** + * Opens a file for reading, returning a {@code BufferedReader} that may be + * used to read text from the file in an efficient manner. Bytes from the + * file are decoded into characters using the specified charset. Reading + * commences at the beginning of the file. + * + *

The {@code Reader} methods that read from the file throw {@code + * IOException} if a malformed or unmappable byte sequence is read. + * + * @param path + * the path to the file + * @param cs + * the charset to use for decoding + * + * @return a new buffered reader, with default buffer size, to read text + * from the file + * + * @throws IOException + * if an I/O error occurs opening the file + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file. + * + * @see #readAllLines + */ + public static BufferedReader newBufferedReader(Path path, Charset cs) + throws IOException + { + CharsetDecoder decoder = cs.newDecoder(); + Reader reader = new InputStreamReader(newInputStream(path), decoder); + return new BufferedReader(reader); } /** - * Creates a directory by creating all nonexistent parent directories first. + * Opens or creates a file for writing, returning a {@code BufferedWriter} + * that may be used to write text to the file in an efficient manner. + * The {@code options} parameter specifies how the the file is created or + * opened. If no options are present then this method works as if the {@link + * StandardOpenOption#CREATE CREATE}, {@link + * StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING}, and {@link + * StandardOpenOption#WRITE WRITE} options are present. In other words, it + * opens the file for writing, creating the file if it doesn't exist, or + * initially truncating an existing {@link #isRegularFile regular-file} to + * a size of {@code 0} if it exists. * - *

The {@code attrs} parameter is an optional array of {@link FileAttribute - * file-attributes} to set atomically when creating the nonexistent - * directories. Each file attribute is identified by its {@link - * FileAttribute#name name}. If more than one attribute of the same name is - * included in the array then all but the last occurrence is ignored. + *

The {@code Writer} methods to write text throw {@code IOException} + * if the text cannot be encoded using the specified charset. * - *

If this method fails, then it may do so after creating some, but not - * all, of the parent directories. + * @param path + * the path to the file + * @param cs + * the charset to use for encoding + * @param options + * options specifying how the file is opened * - * @param dir - * the directory to create + * @return a new buffered writer, with default buffer size, to write text + * to the file * - * @param attrs - * an optional list of file attributes to set atomically when - * creating the directory - * - * @throws UnsupportedOperationException - * if the array contains an attribute that cannot be set atomically - * when creating the directory - * @throws FileAlreadyExistsException - * if {@code dir} exists but is not a directory (optional specific - * exception) * @throws IOException - * if an I/O error occurs + * if an I/O error occurs opening or creating the file + * @throws UnsupportedOperationException + * if an unsupported option is specified * @throws SecurityException - * in the case of the default provider, and a security manager is + * In the case of the default provider, and a security manager is * installed, the {@link SecurityManager#checkWrite(String) checkWrite} - * method is invoked prior to attempting to create a directory and - * its {@link SecurityManager#checkRead(String) checkRead} is - * invoked for each parent directory that is checked. If {@code - * dir} is not an absolute path then its {@link Path#toAbsolutePath - * toAbsolutePath} may need to be invoked to get its absolute path. - * This may invoke the security manager's {@link - * SecurityManager#checkPropertyAccess(String) checkPropertyAccess} - * method to check access to the system property {@code user.dir} + * method is invoked to check write access to the file. * + * @see #write(Path,Iterable,Charset,OpenOption[]) */ - public static void createDirectories(Path dir, FileAttribute... attrs) + public static BufferedWriter newBufferedWriter(Path path, Charset cs, + OpenOption... options) throws IOException { - // attempt to create the directory - try { - createAndCheckIsDirectory(dir, attrs); - return; - } catch (FileAlreadyExistsException x) { - // file exists and is not a directory - throw x; - } catch (IOException x) { - // parent may not exist or other reason + CharsetEncoder encoder = cs.newEncoder(); + Writer writer = new OutputStreamWriter(newOutputStream(path, options), encoder); + return new BufferedWriter(writer); + } + + /** + * Reads all bytes from an input stream and writes them to an output stream. + */ + private static long copy(InputStream source, OutputStream sink) + throws IOException + { + long nread = 0L; + byte[] buf = new byte[BUFFER_SIZE]; + int n; + while ((n = source.read(buf)) > 0) { + sink.write(buf, 0, n); + nread += n; + } + return nread; + } + + /** + * Copies all bytes from an input stream to a file. On return, the input + * stream will be at end of stream. + * + *

By default, the copy fails if the target file already exists or is a + * symbolic link. If the {@link StandardCopyOption#REPLACE_EXISTING + * REPLACE_EXISTING} option is specified, and the target file already exists, + * then it is replaced if it is not a non-empty directory. If the target + * file exists and is a symbolic link, then the symbolic link is replaced. + * In this release, the {@code REPLACE_EXISTING} option is the only option + * required to be supported by this method. Additional options may be + * supported in future releases. + * + *

If an I/O error occurs reading from the input stream or writing to + * the file, then it may do so after the target file has been created and + * after some bytes have been read or written. Consequently the input + * stream may not be at end of stream and may be in an inconsistent state. + * It is strongly recommended that the input stream be promptly closed if an + * I/O error occurs. + * + *

This method may block indefinitely reading from the input stream (or + * writing to the file). The behavior for the case that the input stream is + * asynchronously closed or the thread interrupted during the copy is + * highly input stream and file system provider specific and therefore not + * specified. + * + *

Usage example: Suppose we want to capture a web page and save + * it to a file: + *

+     *     Path path = ...
+     *     URI u = URI.create("http://java.sun.com/");
+     *     try (InputStream in = u.toURL().openStream()) {
+     *         Files.copy(in, path);
+     *     }
+     * 
+ * + * @param in + * the input stream to read from + * @param target + * the path to the file + * @param options + * options specifying how the copy should be done + * + * @return the number of bytes read or written + * + * @throws IOException + * if an I/O error occurs when reading or writing + * @throws FileAlreadyExistsException + * if the target file exists but cannot be replaced because the + * {@code REPLACE_EXISTING} option is not specified (optional + * specific exception) + * @throws DirectoryNotEmptyException + * the {@code REPLACE_EXISTING} option is specified but the file + * cannot be replaced because it is a non-empty directory + * (optional specific exception) * + * @throws UnsupportedOperationException + * if {@code options} contains a copy option that is not supported + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to the file. Where the + * {@code REPLACE_EXISTING} option is specified, the security + * manager's {@link SecurityManager#checkDelete(String) checkDelete} + * method is invoked to check that an existing file can be deleted. + */ + public static long copy(InputStream in, Path target, CopyOption... options) + throws IOException + { + // ensure not null before opening file + Objects.requireNonNull(in); + + // check for REPLACE_EXISTING + boolean replaceExisting = false; + for (CopyOption opt: options) { + if (opt == StandardCopyOption.REPLACE_EXISTING) { + replaceExisting = true; + } else { + if (opt == null) { + throw new NullPointerException("options contains 'null'"); + } else { + throw new UnsupportedOperationException(opt + " not supported"); + } + } } - // find existing parent (may require absolute path) + // attempt to delete an existing file SecurityException se = null; - try { - dir = dir.toAbsolutePath(); - } catch (SecurityException x) { - // don't have permission to get absolute path - se = x; - } - Path parent = dir.getParent(); - while (parent != null) { + if (replaceExisting) { try { - parent.checkAccess(); - break; - } catch (NoSuchFileException x) { - // does not exist + deleteIfExists(target); + } catch (SecurityException x) { + se = x; } - parent = parent.getParent(); } - if (parent == null) { - // unable to find existing parent + + // attempt to create target file. If it fails with + // FileAlreadyExistsException then it may be because the security + // manager prevented us from deleting the file, in which case we just + // throw the SecurityException. + OutputStream ostream; + try { + ostream = newOutputStream(target, StandardOpenOption.CREATE_NEW, + StandardOpenOption.WRITE); + } catch (FileAlreadyExistsException x) { if (se != null) throw se; - throw new IOException("Root directory does not exist"); + // someone else won the race and created the file + throw x; } - // create directories - Path child = parent; - for (Path name: parent.relativize(dir)) { - child = child.resolve(name); - createAndCheckIsDirectory(child, attrs); + // do the copy + try (OutputStream out = ostream) { + return copy(in, out); } } /** - * Attempts to create a directory. Does nothing if the directory already - * exists. + * Copies all bytes from a file to an output stream. + * + *

If an I/O error occurs reading from the file or writing to the output + * stream, then it may do so after some bytes have been read or written. + * Consequently the output stream may be in an inconsistent state. It is + * strongly recommended that the output stream be promptly closed if an I/O + * error occurs. + * + *

This method may block indefinitely writing to the output stream (or + * reading from the file). The behavior for the case that the output stream + * is asynchronously closed or the thread interrupted during the copy + * is highly output stream and file system provider specific and therefore + * not specified. + * + *

Note that if the given output stream is {@link java.io.Flushable} + * then its {@link java.io.Flushable#flush flush} method may need to invoked + * after this method completes so as to flush any buffered output. + * + * @param source + * the path to the file + * @param out + * the output stream to write to + * + * @return the number of bytes read or written + * + * @throws IOException + * if an I/O error occurs when reading or writing + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file. */ - private static void createAndCheckIsDirectory(Path dir, FileAttribute... attrs) - throws IOException - { - try { - dir.createDirectory(attrs); - } catch (FileAlreadyExistsException x) { - boolean isDirectory = Attributes - .readBasicFileAttributes(dir, LinkOption.NOFOLLOW_LINKS).isDirectory(); - if (!isDirectory) - throw x; + public static long copy(Path source, OutputStream out) throws IOException { + // ensure not null before opening file + Objects.requireNonNull(out); + + try (InputStream in = newInputStream(source)) { + return copy(in, out); } } + + /** + * Read all the bytes from an input stream. The {@code initialSize} + * parameter indicates the initial size of the byte[] to allocate. + */ + private static byte[] read(InputStream source, int initialSize) + throws IOException + { + int capacity = initialSize; + byte[] buf = new byte[capacity]; + int nread = 0; + int rem = buf.length; + int n; + // read to EOF which may read more or less than initialSize (eg: file + // is truncated while we are reading) + while ((n = source.read(buf, nread, rem)) > 0) { + nread += n; + rem -= n; + assert rem >= 0; + if (rem == 0) { + // need larger buffer + int newCapacity = capacity << 1; + if (newCapacity < 0) { + if (capacity == Integer.MAX_VALUE) + throw new OutOfMemoryError("Required array size too large"); + newCapacity = Integer.MAX_VALUE; + } + rem = newCapacity - capacity; + buf = Arrays.copyOf(buf, newCapacity); + capacity = newCapacity; + } + } + return (capacity == nread) ? buf : Arrays.copyOf(buf, nread); + } + + /** + * Read all the bytes from a file. The method ensures that the file is + * closed when all bytes have been read or an I/O error, or other runtime + * exception, is thrown. + * + *

Note that this method is intended for simple cases where it is + * convenient to read all bytes into a byte array. It is not intended for + * reading in large files. + * + * @param path + * the path to the file + * + * @return a byte array containing the bytes read from the file + * + * @throws IOException + * if an I/O error occurs reading from the stream + * @throws OutOfMemoryError + * if an array of the required size cannot be allocated, for + * example the file is larger that {@code 2GB} + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file. + */ + public static byte[] readAllBytes(Path path) throws IOException { + long size = size(path); + if (size > (long)Integer.MAX_VALUE) + throw new OutOfMemoryError("Required array size too large"); + + try (InputStream in = newInputStream(path)) { + return read(in, (int)size); + } + } + + /** + * Read all lines from a file. This method ensures that the file is + * closed when all bytes have been read or an I/O error, or other runtime + * exception, is thrown. Bytes from the file are decoded into characters + * using the specified charset. + * + *

This method recognizes the following as line terminators: + *

    + *
  • \u000D followed by \u000A, + * CARRIAGE RETURN followed by LINE FEED
  • + *
  • \u000A, LINE FEED
  • + *
  • \u000D, CARRIAGE RETURN
  • + *
+ *

Additional Unicode line terminators may be recognized in future + * releases. + * + *

Note that this method is intended for simple cases where it is + * convenient to read all lines in a single operation. It is not intended + * for reading in large files. + * + * @param path + * the path to the file + * @param cs + * the charset to use for decoding + * + * @return the lines from the file as a {@code List}; whether the {@code + * List} is modifiable or not is implementation dependent and + * therefore not specified + * + * @throws IOException + * if an I/O error occurs reading from the file or a malformed or + * unmappable byte sequence is read + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file. + * + * @see #newBufferedReader + */ + public static List readAllLines(Path path, Charset cs) + throws IOException + { + try (BufferedReader reader = newBufferedReader(path, cs)) { + List result = new ArrayList<>(); + for (;;) { + String line = reader.readLine(); + if (line == null) + break; + result.add(line); + } + return result; + } + } + + /** + * Writes bytes to a file. The {@code options} parameter specifies how the + * the file is created or opened. If no options are present then this method + * works as if the {@link StandardOpenOption#CREATE CREATE}, {@link + * StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING}, and {@link + * StandardOpenOption#WRITE WRITE} options are present. In other words, it + * opens the file for writing, creating the file if it doesn't exist, or + * initially truncating an existing {@link #isRegularFile regular-file} to + * a size of {@code 0}. All bytes in the byte array are written to the file. + * The method ensures that the file is closed when all bytes have been + * written (or an I/O error or other runtime exception is thrown). If an I/O + * error occurs then it may do so after the file has created or truncated, + * or after some bytes have been written to the file. + * + *

Usage example: By default the method creates a new file or + * overrides an existing file. Suppose you instead want to append bytes + * to an existing file: + *

+     *     Path path = ...
+     *     byte[] bytes = ...
+     *     Files.write(path, bytes, StandardOpenOption.APPEND);
+     * 
+ * + * @param path + * the path to the file + * @param bytes + * the byte array with the bytes to write + * @param options + * options specifying how the file is opened + * + * @return the path + * + * @throws IOException + * if an I/O error occurs writing to or creating the file + * @throws UnsupportedOperationException + * if an unsupported option is specified + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to the file. + */ + public static Path write(Path path, byte[] bytes, OpenOption... options) + throws IOException + { + // ensure bytes is not null before opening file + Objects.requireNonNull(bytes); + + try (OutputStream out = Files.newOutputStream(path, options)) { + int len = bytes.length; + int rem = len; + while (rem > 0) { + int n = Math.min(rem, BUFFER_SIZE); + out.write(bytes, (len-rem), n); + rem -= n; + } + } + return path; + } + + /** + * Write lines of text to a file. Each line is a char sequence and is + * written to the file in sequence with each line terminated by the + * platform's line separator, as defined by the system property {@code + * line.separator}. Characters are encoded into bytes using the specified + * charset. + * + *

The {@code options} parameter specifies how the the file is created + * or opened. If no options are present then this method works as if the + * {@link StandardOpenOption#CREATE CREATE}, {@link + * StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING}, and {@link + * StandardOpenOption#WRITE WRITE} options are present. In other words, it + * opens the file for writing, creating the file if it doesn't exist, or + * initially truncating an existing {@link #isRegularFile regular-file} to + * a size of {@code 0}. The method ensures that the file is closed when all + * lines have been written (or an I/O error or other runtime exception is + * thrown). If an I/O error occurs then it may do so after the file has + * created or truncated, or after some bytes have been written to the file. + * + * @param path + * the path to the file + * @param lines + * an object to iterate over the char sequences + * @param cs + * the charset to use for encoding + * @param options + * options specifying how the file is opened + * + * @return the path + * + * @throws IOException + * if an I/O error occurs writing to or creating the file, or the + * text cannot be encoded using the specified charset + * @throws UnsupportedOperationException + * if an unsupported option is specified + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to the file. + */ + public static Path write(Path path, Iterable lines, + Charset cs, OpenOption... options) + throws IOException + { + // ensure lines is not null before opening file + Objects.requireNonNull(lines); + CharsetEncoder encoder = cs.newEncoder(); + OutputStream out = newOutputStream(path, options); + try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder))) { + for (CharSequence line: lines) { + writer.append(line); + writer.newLine(); + } + } + return path; + } } diff --git a/jdk/src/share/classes/java/nio/file/LinkOption.java b/jdk/src/share/classes/java/nio/file/LinkOption.java index 7c8d97d4c3f..13a42ef7143 100644 --- a/jdk/src/share/classes/java/nio/file/LinkOption.java +++ b/jdk/src/share/classes/java/nio/file/LinkOption.java @@ -35,8 +35,8 @@ public enum LinkOption implements OpenOption, CopyOption { /** * Do not follow symbolic links. * - * @see FileRef#getFileAttributeView(Class,LinkOption[]) - * @see Path#copyTo + * @see Files#getFileAttributeView(Path,Class,LinkOption[]) + * @see Files#copy * @see SecureDirectoryStream#newByteChannel */ NOFOLLOW_LINKS; diff --git a/jdk/src/share/classes/java/nio/file/LinkPermission.java b/jdk/src/share/classes/java/nio/file/LinkPermission.java index 25d799f8c74..161d1b9d7af 100644 --- a/jdk/src/share/classes/java/nio/file/LinkPermission.java +++ b/jdk/src/share/classes/java/nio/file/LinkPermission.java @@ -59,8 +59,8 @@ import java.security.BasicPermission; * * @since 1.7 * - * @see Path#createLink - * @see Path#createSymbolicLink + * @see Files#createLink + * @see Files#createSymbolicLink */ public final class LinkPermission extends BasicPermission { static final long serialVersionUID = -1441492453772213220L; diff --git a/jdk/src/share/classes/java/nio/file/OpenOption.java b/jdk/src/share/classes/java/nio/file/OpenOption.java index aae5e27911d..522d5ddc4f0 100644 --- a/jdk/src/share/classes/java/nio/file/OpenOption.java +++ b/jdk/src/share/classes/java/nio/file/OpenOption.java @@ -29,8 +29,8 @@ package java.nio.file; * An object that configures how to open or create a file. * *

Objects of this type are used by methods such as {@link - * Path#newOutputStream(OpenOption[]) newOutputStream}, {@link - * Path#newByteChannel newByteChannel}, {@link + * Files#newOutputStream(Path,OpenOption[]) newOutputStream}, {@link + * Files#newByteChannel newByteChannel}, {@link * java.nio.channels.FileChannel#open FileChannel.open}, and {@link * java.nio.channels.AsynchronousFileChannel#open AsynchronousFileChannel.open} * when opening or creating a file. diff --git a/jdk/src/share/classes/java/nio/file/Path.java b/jdk/src/share/classes/java/nio/file/Path.java index b41e03f91be..85436b01d9a 100644 --- a/jdk/src/share/classes/java/nio/file/Path.java +++ b/jdk/src/share/classes/java/nio/file/Path.java @@ -25,147 +25,95 @@ package java.nio.file; -import java.nio.file.attribute.*; -import java.nio.channels.SeekableByteChannel; +import java.io.File; import java.io.IOException; -import java.io.OutputStream; import java.net.URI; import java.util.Iterator; -import java.util.Set; /** - * A file reference that locates a file using a system dependent path. The file - * is not required to exist. + * An object that may be used to locate a file in a file system. It will + * typically represent a system dependent file path. * - *

On many platforms a path is the means to locate and access files - * in a file system. A path is hierarchical and composed of a sequence of - * directory and file name elements separated by a special separator or - * delimiter. - * - *

Path operations

- * - *

A system dependent path represented by this class is conceptually a - * sequence of name elements and optionally a root component. The name - * that is farthest from the root of the directory hierarchy is the - * name of a file or directory. The other elements are directory names. The root - * component typically identifies a file system hierarchy. A {@code Path} can - * represent a root, a root and a sequence of names, or simply one or more name - * elements. It defines the {@link #getName() getName}, {@link #getParent - * getParent}, {@link #getRoot getRoot}, and {@link #subpath subpath} methods - * to access the components or a subsequence of its name elements. + *

A {@code Path} represents a path that is hierarchical and composed of a + * sequence of directory and file name elements separated by a special separator + * or delimiter. A root component, that identifies a file system + * hierarchy, may also be present. The name element that is farthest + * from the root of the directory hierarchy is the name of a file or directory. + * The other name elements are directory names. A {@code Path} can represent a + * root, a root and a sequence of names, or simply one or more name elements. + * A {@code Path} is considered to be an empty path if it consists + * solely of one name element that is empty. Accessing a file using an + * empty path is equivalent to accessing the default directory of the + * file system. {@code Path} defines the {@link #getFileName() getFileName}, + * {@link #getParent getParent}, {@link #getRoot getRoot}, and {@link #subpath + * subpath} methods to access the path components or a subsequence of its name + * elements. * *

In addition to accessing the components of a path, a {@code Path} also - * defines {@link #resolve(Path) resolve} and {@link #relativize relativize} - * operations. Paths can also be {@link #compareTo compared}, and tested - * against each other using using the {@link #startsWith startsWith} and {@link - * #endsWith endWith} methods. + * defines the {@link #resolve(Path) resolve} and {@link #resolveSibling(Path) + * resolveSibling} methods to combine paths. The {@link #relativize relativize} + * method that can be used to construct a relative path between two paths. + * Paths can be {@link #compareTo compared}, and tested against each other using + * the {@link #startsWith startsWith} and {@link #endsWith endWith} methods. * - *

File operations

+ *

This interface extends {@link Watchable} interface so that a directory + * located by a path can be {@link #register registered} with a {@link + * WatchService} and entries in the directory watched.

* - *

A {@code Path} is either absolute or relative. An - * absolute path is complete in that does not need to be combined with another - * path in order to locate a file. All operations on relative paths are first - * resolved against a file system's default directory as if by invoking the - * {@link #toAbsolutePath toAbsolutePath} method. + *

WARNING: This interface is only intended to be implemented by + * those developing custom file system implementations. Methods may be added to + * this interface in future releases.

* - *

In addition to the operations defined by the {@link FileRef} interface, - * this class defines the following operations: - * - *

    - *
  • The {@link #newByteChannel newByteChannel} method - * may be used to open a file and obtain a byte channel for reading or - * writing.

  • - *
  • Files may be {@link #createFile(FileAttribute[]) created}, or - * directories may be {@link #createDirectory(FileAttribute[]) created}. - *

  • - *
  • The {@link #delete delete} method may be used to delete a file. - *

  • - *
  • The {@link #checkAccess checkAccess} method may be used to check - * the existence or accessibility of a file.

  • - *
  • The {@link #isSameFile isSameFile} method may be used to test if - * two file references locate the same file.

  • - *
  • The {@link #getFileStore getFileStore} method may be used to - * obtain the {@link FileStore} representing the storage where a file is - * located.

  • - *
  • Directories can be {@link #newDirectoryStream opened} so as to - * iterate over the entries in the directory.

  • - *
  • Files can be {@link #copyTo(Path,CopyOption[]) copied} or - * {@link #moveTo(Path,CopyOption[]) moved}.

  • - *
  • Symbolic links may be {@link #createSymbolicLink created}, or the - * target of a symbolic link may be {@link #readSymbolicLink read}.

  • - *
  • The {@link #toRealPath real} path of an existing file may be - * obtained.

  • - *
- * - *

This class implements {@link Watchable} interface so that a directory - * located by a path can be {@link #register registered} with a {@link WatchService}. - * and entries in the directory watched. - * - *

File attributes

- * - * In addition to the {@link #setAttribute setAttribute} and {@link #getAttribute - * getAttribute} methods, the
{@code - * java.nio.file.attribute} package provides type-safe and efficient access - * to file attributes or meta-data associated with files. The {@link - * Attributes Attributes} class defines methods that operate on or return file - * attributes. For example, the file type, size, timestamps, and other - * basic meta-data are obtained, in bulk, by invoking the {@link - * Attributes#readBasicFileAttributes Attributes.readBasicFileAttributes} method: + *

Accessing Files

+ *

Paths may be used with the {@link Files} class to operate on files, + * directories, and other types of files. For example, suppose we want a {@link + * java.io.BufferedReader} to read text from a file "{@code access.log}". The + * file is located in a directory "{@code logs}" relative to the current working + * directory and is UTF-8 encoded. *

- *     Path file = ...
- *     BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file);
+ *     Path path = FileSystems.getDefault().getPath("logs", "access.log");
+ *     BufferReader reader = Files.newBufferedReader(path, Charset.forName("UTF-8"));
  * 
* *

Interoperability

- * - *

Paths created by file systems associated with the default {@link + *

Paths associated with the default {@link * java.nio.file.spi.FileSystemProvider provider} are generally interoperable * with the {@link java.io.File java.io.File} class. Paths created by other * providers are unlikely to be interoperable with the abstract path names - * represented by {@code java.io.File}. The {@link java.io.File#toPath - * File.toPath} method may be used to obtain a {@code Path} from the abstract - * path name represented by a {@code java.io.File java.io.File} object. The - * resulting {@code Path} can be used to operate on the same file as the {@code - * java.io.File} object. - * - *

Path objects created by file systems associated with the default - * provider are interoperable with objects created by other file systems created - * by the same provider. Path objects created by file systems associated with - * other providers may not be interoperable with other file systems created by - * the same provider. The reasons for this are provider specific. + * represented by {@code java.io.File}. The {@link java.io.File#toPath toPath} + * method may be used to obtain a {@code Path} from the abstract path name + * represented by a {@code java.io.File} object. The resulting {@code Path} can + * be used to operate on the same file as the {@code java.io.File} object. In + * addition, the {@link #toFile toFile} method is useful to construct a {@code + * File} from the {@code String} representation of a {@code Path}. * *

Concurrency

- * - *

Instances of this class are immutable and safe for use by multiple concurrent - * threads. + *

Implementations of this interface are immutable and safe for use by + * multiple concurrent threads. * * @since 1.7 + * @see Paths */ -public abstract class Path - implements FileRef, Comparable, Iterable, Watchable +public interface Path + extends Comparable, Iterable, Watchable { - /** - * Initializes a new instance of this class. - */ - protected Path() { } - /** * Returns the file system that created this object. * * @return the file system that created this object */ - public abstract FileSystem getFileSystem(); + FileSystem getFileSystem(); /** * Tells whether or not this path is absolute. * - *

An absolute path is complete in that it doesn't need to be - * combined with other path information in order to locate a file. + *

An absolute path is complete in that it doesn't need to be combined + * with other path information in order to locate a file. * * @return {@code true} if, and only if, this path is absolute */ - public abstract boolean isAbsolute(); + boolean isAbsolute(); /** * Returns the root component of this path as a {@code Path} object, @@ -174,17 +122,17 @@ public abstract class Path * @return a path representing the root component of this path, * or {@code null} */ - public abstract Path getRoot(); + Path getRoot(); /** - * Returns the name of the file or directory denoted by this path. The - * file name is the farthest element from the root in the directory - * hierarchy. + * Returns the name of the file or directory denoted by this path as a + * {@code Path} object. The file name is the farthest element from + * the root in the directory hierarchy. * * @return a path representing the name of the file or directory, or * {@code null} if this path has zero elements */ - public abstract Path getName(); + Path getFileName(); /** * Returns the parent path, or {@code null} if this path does not @@ -209,7 +157,7 @@ public abstract class Path * * @return a path representing the path's parent */ - public abstract Path getParent(); + Path getParent(); /** * Returns the number of name elements in the path. @@ -217,10 +165,10 @@ public abstract class Path * @return the number of elements in the path, or {@code 0} if this path * only represents a root component */ - public abstract int getNameCount(); + int getNameCount(); - /** - * Returns a name element of this path. + /** + * Returns a name element of this path as a {@code Path} object. * *

The {@code index} parameter is the index of the name element to return. * The element that is closest to the root in the directory hierarchy @@ -237,7 +185,7 @@ public abstract class Path * equal to the number of elements, or this path has zero name * elements */ - public abstract Path getName(int index); + Path getName(int index); /** * Returns a relative {@code Path} that is a subsequence of the name @@ -264,7 +212,7 @@ public abstract class Path * the number of elements. If {@code endIndex} is less than or * equal to {@code beginIndex}, or larger than the number of elements. */ - public abstract Path subpath(int beginIndex, int endIndex); + Path subpath(int beginIndex, int endIndex); /** * Tests if this path starts with the given path. @@ -286,7 +234,25 @@ public abstract class Path * @return {@code true} if this path starts with the given path; otherwise * {@code false} */ - public abstract boolean startsWith(Path other); + boolean startsWith(Path other); + + /** + * Tests if this path starts with a {@code Path}, constructed by converting + * the given path string, in exactly the manner specified by the {@link + * #startsWith(Path) startsWith(Path)} method. On UNIX for example, the path + * "{@code foo/bar}" starts with "{@code foo}" and "{@code foo/bar}". It + * does not start with "{@code f}" or "{@code fo}". + * + * @param other + * the given path string + * + * @return {@code true} if this path starts with the given path; otherwise + * {@code false} + * + * @throws InvalidPathException + * If the path string cannot be converted to a Path. + */ + boolean startsWith(String other); /** * Tests if this path ends with the given path. @@ -310,7 +276,25 @@ public abstract class Path * @return {@code true} if this path ends with the given path; otherwise * {@code false} */ - public abstract boolean endsWith(Path other); + boolean endsWith(Path other); + + /** + * Tests if this path ends with a {@code Path}, constructed by converting + * the given path string, in exactly the manner specified by the {@link + * #endsWith(Path) endsWith(Path)} method. On UNIX for example, the path + * "{@code foo/bar}" ends with "{@code foo/bar}" and "{@code bar}". It does + * not end with "{@code r}" or "{@code /bar}". + * + * @param other + * the given path string + * + * @return {@code true} if this path starts with the given path; otherwise + * {@code false} + * + * @throws InvalidPathException + * If the path string cannot be converted to a Path. + */ + boolean endsWith(String other); /** * Returns a path that is this path with redundant name elements eliminated. @@ -330,14 +314,14 @@ public abstract class Path * path may result in the path that locates a different file than the original * path. This can arise when the preceding name is a symbolic link. * - * @return the resulting path, or this path if it does not contain - * redundant name elements, or {@code null} if this path does not - * have a root component and all name elements are redundant + * @return the resulting path or this path if it does not contain + * redundant name elements; an empty path is returned if this path + * does have a root component and all name elements are redundant * * @see #getParent * @see #toRealPath */ - public abstract Path normalize(); + Path normalize(); // -- resolution and relativization -- @@ -346,28 +330,31 @@ public abstract class Path * *

If the {@code other} parameter is an {@link #isAbsolute() absolute} * path then this method trivially returns {@code other}. If {@code other} - * is {@code null} then this path is returned. Otherwise this method - * considers this path to be a directory and resolves the given path - * against this path. In the simplest case, the given path does not have - * a {@link #getRoot root} component, in which case this method joins - * the given path to this path and returns a resulting path that {@link - * #endsWith ends} with the given path. Where the given path has a root - * component then resolution is highly implementation dependent and therefore - * unspecified. + * is an empty path then this method trivially returns this path. + * Otherwise this method considers this path to be a directory and resolves + * the given path against this path. In the simplest case, the given path + * does not have a {@link #getRoot root} component, in which case this method + * joins the given path to this path and returns a resulting path + * that {@link #endsWith ends} with the given path. Where the given path has + * a root component then resolution is highly implementation dependent and + * therefore unspecified. * * @param other - * the path to resolve against this path; can be {@code null} + * the path to resolve against this path * * @return the resulting path * * @see #relativize */ - public abstract Path resolve(Path other); + Path resolve(Path other); /** * Converts a given path string to a {@code Path} and resolves it against * this {@code Path} in exactly the manner specified by the {@link - * #resolve(Path) resolve} method. + * #resolve(Path) resolve} method. For example, suppose that the name + * separator is "{@code /}" and a path represents "{@code foo/bar}", then + * invoking this method with the path string "{@code gus}" will result in + * the {@code Path} "{@code foo/bar/gus}". * * @param other * the path string to resolve against this path @@ -375,11 +362,49 @@ public abstract class Path * @return the resulting path * * @throws InvalidPathException - * If the path string cannot be converted to a Path. + * if the path string cannot be converted to a Path. * * @see FileSystem#getPath */ - public abstract Path resolve(String other); + Path resolve(String other); + + /** + * Resolves the given path against this path's {@link #getParent parent} + * path. This is useful where a file name needs to be replaced with + * another file name. For example, suppose that the name separator is + * "{@code /}" and a path represents "{@code dir1/dir2/foo}", then invoking + * this method with the {@code Path} "{@code bar}" will result in the {@code + * Path} "{@code dir1/dir2/bar}". If this path does not have a parent path, + * or {@code other} is {@link #isAbsolute() absolute}, then this method + * returns {@code other}. If {@code other} is an empty path then this method + * returns this path's parent, or where this path doesn't have a parent, the + * empty path. + * + * @param other + * the path to resolve against this path's parent + * + * @return the resulting path + * + * @see #resolve(Path) + */ + Path resolveSibling(Path other); + + /** + * Converts a given path string to a {@code Path} and resolves it against + * this path's {@link #getParent parent} path in exactly the manner + * specified by the {@link #resolveSibling(Path) resolveSibling} method. + * + * @param other + * the path string to resolve against this path's parent + * + * @return the resulting path + * + * @throws InvalidPathException + * if the path string cannot be converted to a Path. + * + * @see FileSystem#getPath + */ + Path resolveSibling(String other); /** * Constructs a relative path between this path and a given path. @@ -395,17 +420,17 @@ public abstract class Path * constructed if only one of the paths have a root component. Where both * paths have a root component then it is implementation dependent if a * relative path can be constructed. If this path and the given path are - * {@link #equals equal} then {@code null} is returned. + * {@link #equals equal} then an empty path is returned. * - *

For any two paths p and q, where q does not have - * a root component, + *

For any two {@link #normalize normalized} paths p and + * q, where q does not have a root component, *

* p.relativize(p.resolve(q)).equals(q) *
* *

When symbolic links are supported, then whether the resulting path, * when resolved against this path, yields a path that can be used to locate - * the {@link #isSameFile same} file as {@code other} is implementation + * the {@link Files#isSameFile same} file as {@code other} is implementation * dependent. For example, if this path is {@code "/a/b"} and the given * path is {@code "/a/x"} then the resulting relative path may be {@code * "../x"}. If {@code "b"} is a symbolic link then is implementation @@ -414,185 +439,14 @@ public abstract class Path * @param other * the path to relativize against this path * - * @return the resulting relative path, or {@code null} if both paths are + * @return the resulting relative path, or an empty path if both paths are * equal * * @throws IllegalArgumentException * if {@code other} is not a {@code Path} that can be relativized * against this path */ - public abstract Path relativize(Path other); - - // -- file operations -- - - /** - * Deletes the file located by this path. - * - *

An implementation may require to examine the file to determine if the - * file is a directory. Consequently this method may not be atomic with respect - * to other file system operations. If the file is a symbolic link then the - * symbolic link itself, not the final target of the link, is deleted. - * - *

If the file is a directory then the directory must be empty. In some - * implementations a directory has entries for special files or links that - * are created when the directory is created. In such implementations a - * directory is considered empty when only the special entries exist. - * - *

On some operating systems it may not be possible to remove a file when - * it is open and in use by this Java virtual machine or other programs. - * - * @throws NoSuchFileException - * if the file does not exist (optional specific exception) - * @throws DirectoryNotEmptyException - * if the file is a directory and could not otherwise be deleted - * because the directory is not empty (optional specific - * exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkDelete(String)} method - * is invoked to check delete access to the file - */ - public abstract void delete() throws IOException; - - /** - * Deletes the file located by this path, if it exists. - * - *

As with the {@link #delete delete()} method, an implementation may - * need to examine the file to determine if the file is a directory. - * Consequently this method may not be atomic with respect to other file - * system operations. If the file is a symbolic link, then the symbolic - * link itself, not the final target of the link, is deleted. - * - *

If the file is a directory then the directory must be empty. In some - * implementations a directory has entries for special files or links that - * are created when the directory is created. In such implementations a - * directory is considered empty when only the special entries exist. - * - *

On some operating systems it may not be possible to remove a file when - * it is open and in use by this Java virtual machine or other programs. - * - * @throws DirectoryNotEmptyException - * if the file is a directory and could not otherwise be deleted - * because the directory is not empty (optional specific - * exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkDelete(String)} method - * is invoked to check delete access to the file. - */ - public abstract void deleteIfExists() throws IOException; - - /** - * Creates a symbolic link to a target (optional operation). - * - *

The {@code target} parameter is the target of the link. It may be an - * {@link Path#isAbsolute absolute} or relative path and may not exist. When - * the target is a relative path then file system operations on the resulting - * link are relative to the path of the link. - * - *

The {@code attrs} parameter is an optional array of {@link FileAttribute - * attributes} to set atomically when creating the link. Each attribute is - * identified by its {@link FileAttribute#name name}. If more than one attribute - * of the same name is included in the array then all but the last occurrence - * is ignored. - * - *

Where symbolic links are supported, but the underlying {@link FileStore} - * does not support symbolic links, then this may fail with an {@link - * IOException}. Additionally, some operating systems may require that the - * Java virtual machine be started with implementation specific privileges to - * create symbolic links, in which case this method may throw {@code IOException}. - * - * @param target - * the target of the symbolic link - * @param attrs - * the array of attributes to set atomically when creating the - * symbolic link - * - * @return this path - * - * @throws UnsupportedOperationException - * if the implementation does not support symbolic links or the - * array contains an attribute that cannot be set atomically when - * creating the symbolic link - * @throws FileAlreadyExistsException - * if a file with the name already exists (optional specific - * exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager - * is installed, it denies {@link LinkPermission}("symbolic") - * or its {@link SecurityManager#checkWrite(String) checkWrite} - * method denies write access to the path of the symbolic link. - */ - public abstract Path createSymbolicLink(Path target, FileAttribute... attrs) - throws IOException; - - /** - * Creates a new link (directory entry) for an existing file (optional - * operation). - * - *

This path locates the directory entry to create. The {@code existing} - * parameter is the path to an existing file. This method creates a new - * directory entry for the file so that it can be accessed using this path. - * On some file systems this is known as creating a "hard link". Whether the - * file attributes are maintained for the file or for each directory entry - * is file system specific and therefore not specified. Typically, a file - * system requires that all links (directory entries) for a file be on the - * same file system. Furthermore, on some platforms, the Java virtual machine - * may require to be started with implementation specific privileges to - * create hard links or to create links to directories. - * - * @param existing - * a reference to an existing file - * - * @return this path - * - * @throws UnsupportedOperationException - * if the implementation does not support adding an existing file - * to a directory - * @throws FileAlreadyExistsException - * if the entry could not otherwise be created because a file of - * that name already exists (optional specific exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager - * is installed, it denies {@link LinkPermission}("hard") - * or its {@link SecurityManager#checkWrite(String) checkWrite} - * method denies write access to both this path and the path of the - * existing file. - */ - public abstract Path createLink(Path existing) throws IOException; - - /** - * Reads the target of a symbolic link (optional operation). - * - *

If the file system supports symbolic - * links then this method is used to read the target of the link, failing - * if the file is not a symbolic link. The target of the link need not exist. - * The returned {@code Path} object will be associated with the same file - * system as this {@code Path}. - * - * @return a {@code Path} object representing the target of the link - * - * @throws UnsupportedOperationException - * if the implementation does not support symbolic links - * @throws NotLinkException - * if the target could otherwise not be read because the file - * is not a symbolic link (optional specific exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager - * is installed, it checks that {@code FilePermission} has been - * granted with the "{@code readlink}" action to read the link. - */ - public abstract Path readSymbolicLink() throws IOException; + Path relativize(Path other); /** * Returns a URI to represent this path. @@ -647,7 +501,7 @@ public abstract class Path * is installed, the {@link #toAbsolutePath toAbsolutePath} method * throws a security exception. */ - public abstract URI toUri(); + URI toUri(); /** * Returns a {@code Path} object representing the absolute path of this @@ -670,14 +524,14 @@ public abstract class Path * checkPropertyAccess} method is invoked to check access to the * system property {@code user.dir} */ - public abstract Path toAbsolutePath(); + Path toAbsolutePath(); /** * Returns the real path of an existing file. * *

The precise definition of this method is implementation dependent but * in general it derives from this path, an {@link #isAbsolute absolute} - * path that locates the {@link #isSameFile same} file as this path, but + * path that locates the {@link Files#isSameFile same} file as this path, but * with name elements that represent the actual name of the directories * and the file. For example, where filename comparisons on a file system * are case insensitive then the name elements represent the names in their @@ -713,756 +567,25 @@ public abstract class Path * checkPropertyAccess} method is invoked to check access to the * system property {@code user.dir} */ - public abstract Path toRealPath(boolean resolveLinks) throws IOException; + Path toRealPath(boolean resolveLinks) throws IOException; /** - * Copy the file located by this path to a target location. + * Returns a {@link File} object representing this path. Where this {@code + * Path} is associated with the default provider, then this method is + * equivalent to returning a {@code File} object constructed with the + * {@code String} representation of this path. * - *

This method copies the file located by this {@code Path} to the - * target location with the {@code options} parameter specifying how the - * copy is performed. By default, the copy fails if the target file already - * exists, except if the source and target are the {@link #isSameFile same} - * file, in which case this method has no effect. File attributes are not - * required to be copied to the target file. If symbolic links are supported, - * and the file is a symbolic link, then the final target of the link is copied. - * If the file is a directory then it creates an empty directory in the target - * location (entries in the directory are not copied). This method can be - * used with the {@link Files#walkFileTree Files.walkFileTree} utility - * method to copy a directory and all entries in the directory, or an entire - * file-tree where required. + *

If this path was created by invoking the {@code File} {@link + * File#toPath toPath} method then there is no guarantee that the {@code + * File} object returned by this method is {@link #equals equal} to the + * original {@code File}. * - *

The {@code options} parameter is an array of options and may contain - * any of the following: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Option Description
{@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} If the target file exists, then the target file is replaced if it - * is not a non-empty directory. If the target file exists and is a - * symbolic link, then the symbolic link itself, not the target of - * the link, is replaced.
{@link StandardCopyOption#COPY_ATTRIBUTES COPY_ATTRIBUTES} Attempts to copy the file attributes associated with this file to - * the target file. The exact file attributes that are copied is platform - * and file system dependent and therefore unspecified. Minimally, the - * {@link BasicFileAttributes#lastModifiedTime last-modified-time} is - * copied to the target file if supported by both the source and target - * file store. Copying of file timestamps may result in precision - * loss.
{@link LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} Symbolic links are not followed. If the file, located by this path, - * is a symbolic link, then the symbolic link itself, not the target of - * the link, is copied. It is implementation specific if file attributes - * can be copied to the new link. In other words, the {@code - * COPY_ATTRIBUTES} option may be ignored when copying a symbolic link.
- * - *

An implementation of this interface may support additional - * implementation specific options. - * - *

Copying a file is not an atomic operation. If an {@link IOException} - * is thrown then it possible that the target file is incomplete or some of - * its file attributes have not been copied from the source file. When the - * {@code REPLACE_EXISTING} option is specified and the target file exists, - * then the target file is replaced. The check for the existence of the file - * and the creation of the new file may not be atomic with respect to other - * file system activities. - * - * @param target - * the target location - * @param options - * options specifying how the copy should be done - * - * @return the target + * @return a {@code File} object representing this path * * @throws UnsupportedOperationException - * if the array contains a copy option that is not supported - * @throws FileAlreadyExistsException - * if the target file exists and cannot be replaced because the - * {@code REPLACE_EXISTING} option is not specified, or the target - * file is a non-empty directory (optional specific exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the source file, the - * {@link SecurityManager#checkWrite(String) checkWrite} is invoked - * to check write access to the target file. If a symbolic link is - * copied the security manager is invoked to check {@link - * LinkPermission}{@code ("symbolic")}. + * if this {@code Path} is not associated with the default provider */ - public abstract Path copyTo(Path target, CopyOption... options) - throws IOException; - - /** - * Move or rename the file located by this path to a target location. - * - *

By default, this method attempts to move the file to the target - * location, failing if the target file exists except if the source and - * target are the {@link #isSameFile same} file, in which case this method - * has no effect. If the file is a symbolic link then the symbolic link - * itself, not the target of the link, is moved. This method may be - * invoked to move an empty directory. In some implementations a directory - * has entries for special files or links that are created when the - * directory is created. In such implementations a directory is considered - * empty when only the special entries exist. When invoked to move a - * directory that is not empty then the directory is moved if it does not - * require moving the entries in the directory. For example, renaming a - * directory on the same {@link FileStore} will usually not require moving - * the entries in the directory. When moving a directory requires that its - * entries be moved then this method fails (by throwing an {@code - * IOException}). To move a file tree may involve copying rather - * than moving directories and this can be done using the {@link - * #copyTo copyTo} method in conjunction with the {@link - * Files#walkFileTree Files.walkFileTree} utility method. - * - *

The {@code options} parameter is an array of options and may contain - * any of the following: - * - * - * - * - * - * - * - * - * - * - *
Option Description
{@link StandardCopyOption#REPLACE_EXISTING REPLACE_EXISTING} If the target file exists, then the target file is replaced if it - * is not a non-empty directory. If the target file exists and is a - * symbolic link, then the symbolic link itself, not the target of - * the link, is replaced.
{@link StandardCopyOption#ATOMIC_MOVE ATOMIC_MOVE} The move is performed as an atomic file system operation and all - * other options are ignored. If the target file exists then it is - * implementation specific if the existing file is replaced or this method - * fails by throwing an {@link IOException}. If the move cannot be - * performed as an atomic file system operation then {@link - * AtomicMoveNotSupportedException} is thrown. This can arise, for - * example, when the target location is on a different {@code FileStore} - * and would require that the file be copied, or target location is - * associated with a different provider to this object.
- * - *

An implementation of this interface may support additional - * implementation specific options. - * - *

Where the move requires that the file be copied then the {@link - * BasicFileAttributes#lastModifiedTime last-modified-time} is copied to the - * new file. An implementation may also attempt to copy other file - * attributes but is not required to fail if the file attributes cannot be - * copied. When the move is performed as a non-atomic operation, and a {@code - * IOException} is thrown, then the state of the files is not defined. The - * original file and the target file may both exist, the target file may be - * incomplete or some of its file attributes may not been copied from the - * original file. - * - * @param target - * the target location - * @param options - * options specifying how the move should be done - * - * @return the target - * - * @throws UnsupportedOperationException - * if the array contains a copy option that is not supported - * @throws FileAlreadyExistsException - * if the target file exists and cannot be replaced because the - * {@code REPLACE_EXISTING} option is not specified, or the target - * file is a non-empty directory - * @throws AtomicMoveNotSupportedException - * if the options array contains the {@code ATOMIC_MOVE} option but - * the file cannot be moved as an atomic file system operation. - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkWrite(String) checkWrite} - * method is invoked to check write access to both the source and - * target file. - */ - public abstract Path moveTo(Path target, CopyOption... options) - throws IOException; - - /** - * Opens the directory referenced by this object, returning a {@code - * DirectoryStream} to iterate over all entries in the directory. The - * elements returned by the directory stream's {@link DirectoryStream#iterator - * iterator} are of type {@code Path}, each one representing an entry in the - * directory. The {@code Path} objects are obtained as if by {@link - * #resolve(Path) resolving} the name of the directory entry against this - * path. - * - *

The directory stream's {@code close} method should be invoked after - * iteration is completed so as to free any resources held for the open - * directory. - * - *

When an implementation supports operations on entries in the - * directory that execute in a race-free manner then the returned directory - * stream is a {@link SecureDirectoryStream}. - * - * @return a new and open {@code DirectoryStream} object - * - * @throws NotDirectoryException - * if the file could not otherwise be opened because it is not - * a directory (optional specific exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the directory. - */ - public abstract DirectoryStream newDirectoryStream() - throws IOException; - - /** - * Opens the directory referenced by this object, returning a {@code - * DirectoryStream} to iterate over the entries in the directory. The - * elements returned by the directory stream's {@link DirectoryStream#iterator - * iterator} are of type {@code Path}, each one representing an entry in the - * directory. The {@code Path} objects are obtained as if by {@link - * #resolve(Path) resolving} the name of the directory entry against this - * path. The entries returned by the iterator are filtered by matching the - * {@code String} representation of their file names against the given - * globbing pattern. - * - *

For example, suppose we want to iterate over the files ending with - * ".java" in a directory: - *

-     *     Path dir = ...
-     *     DirectoryStream<Path> stream = dir.newDirectoryStream("*.java");
-     * 
- * - *

The globbing pattern is specified by the {@link - * FileSystem#getPathMatcher getPathMatcher} method. - * - *

The directory stream's {@code close} method should be invoked after - * iteration is completed so as to free any resources held for the open - * directory. - * - *

When an implementation supports operations on entries in the - * directory that execute in a race-free manner then the returned directory - * stream is a {@link SecureDirectoryStream}. - * - * @param glob - * the glob pattern - * - * @return a new and open {@code DirectoryStream} object - * - * @throws java.util.regex.PatternSyntaxException - * if the pattern is invalid - * @throws NotDirectoryException - * if the file could not otherwise be opened because it is not - * a directory (optional specific exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the directory. - */ - public abstract DirectoryStream newDirectoryStream(String glob) - throws IOException; - - /** - * Opens the directory referenced by this object, returning a {@code - * DirectoryStream} to iterate over the entries in the directory. The - * elements returned by the directory stream's {@link DirectoryStream#iterator - * iterator} are of type {@code Path}, each one representing an entry in the - * directory. The {@code Path} objects are obtained as if by {@link - * #resolve(Path) resolving} the name of the directory entry against this - * path. The entries returned by the iterator are filtered by the given - * {@link DirectoryStream.Filter filter}. - * - *

The directory stream's {@code close} method should be invoked after - * iteration is completed so as to free any resources held for the open - * directory. - * - *

Where the filter terminates due to an uncaught error or runtime - * exception then it is propagated to the {@link Iterator#hasNext() - * hasNext} or {@link Iterator#next() next} method. Where an {@code - * IOException} is thrown, it results in the {@code hasNext} or {@code - * next} method throwing a {@link DirectoryIteratorException} with the - * {@code IOException} as the cause. - * - *

When an implementation supports operations on entries in the - * directory that execute in a race-free manner then the returned directory - * stream is a {@link SecureDirectoryStream}. - * - *

Usage Example: - * Suppose we want to iterate over the files in a directory that are - * larger than 8K. - *

-     *     DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
-     *         public boolean accept(Path file) throws IOException {
-     *             long size = Attributes.readBasicFileAttributes(file).size();
-     *             return (size > 8192L);
-     *         }
-     *     };
-     *     Path dir = ...
-     *     DirectoryStream<Path> stream = dir.newDirectoryStream(filter);
-     * 
- * @param filter - * the directory stream filter - * - * @return a new and open {@code DirectoryStream} object - * - * @throws NotDirectoryException - * if the file could not otherwise be opened because it is not - * a directory (optional specific exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the directory. - */ - public abstract DirectoryStream newDirectoryStream(DirectoryStream.Filter filter) - throws IOException; - - /** - * Creates a new and empty file, failing if the file already exists. - * - *

This {@code Path} locates the file to create. The check for the - * existence of the file and the creation of the new file if it does not - * exist are a single operation that is atomic with respect to all other - * filesystem activities that might affect the directory. - * - *

The {@code attrs} parameter is an optional array of {@link FileAttribute - * file-attributes} to set atomically when creating the file. Each attribute - * is identified by its {@link FileAttribute#name name}. If more than one - * attribute of the same name is included in the array then all but the last - * occurrence is ignored. - * - * @param attrs - * an optional list of file attributes to set atomically when - * creating the file - * - * @return this path - * - * @throws UnsupportedOperationException - * if the array contains an attribute that cannot be set atomically - * when creating the file - * @throws FileAlreadyExistsException - * if a file of that name already exists - * (optional specific exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkWrite(String) checkWrite} - * method is invoked to check write access to the new file. - */ - public abstract Path createFile(FileAttribute... attrs) throws IOException; - - /** - * Creates a new directory. - * - *

This {@code Path} locates the directory to create. The check for the - * existence of the file and the creation of the directory if it does not - * exist are a single operation that is atomic with respect to all other - * filesystem activities that might affect the directory. - * - *

The {@code attrs} parameter is an optional array of {@link FileAttribute - * file-attributes} to set atomically when creating the directory. Each - * file attribute is identified by its {@link FileAttribute#name name}. If - * more than one attribute of the same name is included in the array then all - * but the last occurrence is ignored. - * - * @param attrs - * an optional list of file attributes to set atomically when - * creating the directory - * - * @return this path - * - * @throws UnsupportedOperationException - * if the array contains an attribute that cannot be set atomically - * when creating the directory - * @throws FileAlreadyExistsException - * if a directory could not otherwise be created because a file of - * that name already exists (optional specific exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkWrite(String) checkWrite} - * method is invoked to check write access to the new directory. - * - * @see Files#createDirectories - */ - public abstract Path createDirectory(FileAttribute... attrs) - throws IOException; - - /** - * Opens or creates a file, returning a seekable byte channel to access the - * file. - * - *

The {@code options} parameter determines how the file is opened. - * The {@link StandardOpenOption#READ READ} and {@link StandardOpenOption#WRITE WRITE} - * options determine if the file should be opened for reading and/or writing. - * If neither option (or the {@link StandardOpenOption#APPEND APPEND} - * option) is contained in the array then the file is opened for reading. - * By default reading or writing commences at the beginning of the file. - * - *

In the addition to {@code READ} and {@code WRITE}, the following - * options may be present: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Option Description
{@link StandardOpenOption#APPEND APPEND} If this option is present then the file is opened for writing and - * each invocation of the channel's {@code write} method first advances - * the position to the end of the file and then writes the requested - * data. Whether the advancement of the position and the writing of the - * data are done in a single atomic operation is system-dependent and - * therefore unspecified. This option may not be used in conjunction - * with the {@code READ} or {@code TRUNCATE_EXISTING} options.
{@link StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING} If this option is present then the existing file is truncated to - * a size of 0 bytes. This option is ignored when the file is opened only - * for reading.
{@link StandardOpenOption#CREATE_NEW CREATE_NEW} If this option is present then a new file is created, failing if - * the file already exists or is a symbolic link. When creating a file the - * check for the existence of the file and the creation of the file if it - * does not exist is atomic with respect to other file system operations. - * This option is ignored when the file is opened only for reading.
{@link StandardOpenOption#CREATE CREATE} If this option is present then an existing file is opened if it - * exists, otherwise a new file is created. This option is ignored if the - * {@code CREATE_NEW} option is also present or the file is opened only - * for reading.
{@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} When this option is present then the implementation makes a - * best effort attempt to delete the file when closed by the - * {@link SeekableByteChannel#close close} method. If the {@code close} - * method is not invoked then a best effort attempt is made to - * delete the file when the Java virtual machine terminates.
{@link StandardOpenOption#SPARSE SPARSE} When creating a new file this option is a hint that the - * new file will be sparse. This option is ignored when not creating - * a new file.
{@link StandardOpenOption#SYNC SYNC} Requires that every update to the file's content or metadata be - * written synchronously to the underlying storage device. (see Synchronized I/O file - * integrity).
{@link StandardOpenOption#DSYNC DSYNC} Requires that every update to the file's content be written - * synchronously to the underlying storage device. (see Synchronized I/O file - * integrity).
- * - *

An implementation may also support additional implementation specific - * options. - * - *

The {@code attrs} parameter is an optional array of file {@link - * FileAttribute file-attributes} to set atomically when a new file is created. - * - *

In the case of the default provider, the returned seekable byte channel - * is a {@link java.nio.channels.FileChannel}. - * - *

Usage Examples: - *

-     *     Path file = ...
-     *
-     *     // open file for reading
-     *     ReadableByteChannel rbc = file.newByteChannel(EnumSet.of(READ)));
-     *
-     *     // open file for writing to the end of an existing file, creating
-     *     // the file if it doesn't already exist
-     *     WritableByteChannel wbc = file.newByteChannel(EnumSet.of(CREATE,APPEND));
-     *
-     *     // create file with initial permissions, opening it for both reading and writing
-     *     FileAttribute<Set<PosixFilePermission>> perms = ...
-     *     SeekableByteChannel sbc = file.newByteChannel(EnumSet.of(CREATE_NEW,READ,WRITE), perms);
-     * 
- * - * @param options - * Options specifying how the file is opened - * @param attrs - * An optional list of file attributes to set atomically when - * creating the file - * - * @return a new seekable byte channel - * - * @throws IllegalArgumentException - * if the set contains an invalid combination of options - * @throws UnsupportedOperationException - * if an unsupported open option is specified or the array contains - * attributes that cannot be set atomically when creating the file - * @throws FileAlreadyExistsException - * if a file of that name already exists and the {@link - * StandardOpenOption#CREATE_NEW CREATE_NEW} option is specified - * (optional specific exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the path if the file is - * opened for reading. The {@link SecurityManager#checkWrite(String) - * checkWrite} method is invoked to check write access to the path - * if the file is opened for writing. - */ - public abstract SeekableByteChannel newByteChannel(Set options, - FileAttribute... attrs) - throws IOException; - - /** - * Opens or creates a file, returning a seekable byte channel to access the - * file. - * - *

This method opens or creates a file in exactly the manner specified - * by the {@link Path#newByteChannel(Set,FileAttribute[]) newByteChannel} - * method. - * - * @param options - * options specifying how the file is opened - * - * @return a new seekable byte channel - * - * @throws IllegalArgumentException - * if the set contains an invalid combination of options - * @throws UnsupportedOperationException - * if an unsupported open option is specified - * @throws FileAlreadyExistsException - * if a file of that name already exists and the {@link - * StandardOpenOption#CREATE_NEW CREATE_NEW} option is specified - * (optional specific exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the path if the file is - * opened for reading. The {@link SecurityManager#checkWrite(String) - * checkWrite} method is invoked to check write access to the path - * if the file is opened for writing. - */ - public abstract SeekableByteChannel newByteChannel(OpenOption... options) - throws IOException; - - /** - * Opens or creates the file located by this object for writing, returning - * an output stream to write bytes to the file. - * - *

This method opens or creates a file in exactly the manner specified - * by the {@link Path#newByteChannel(Set,FileAttribute[]) newByteChannel} - * method except that the {@link StandardOpenOption#READ READ} option may not - * be present in the array of open options. - * - * @param options - * options specifying how the file is opened - * - * @return a new output stream - * - * @throws IllegalArgumentException {@inheritDoc} - * @throws UnsupportedOperationException {@inheritDoc} - * @throws IOException {@inheritDoc} - * @throws SecurityException {@inheritDoc} - */ - @Override - public abstract OutputStream newOutputStream(OpenOption... options) - throws IOException; - - /** - * Tells whether or not the file located by this object is considered - * hidden. The exact definition of hidden is platform or provider - * dependent. On UNIX for example a file is considered to be hidden if its - * name begins with a period character ('.'). On Windows a file is - * considered hidden if it isn't a directory and the DOS {@link - * DosFileAttributes#isHidden hidden} attribute is set. - * - *

Depending on the implementation this method may require to access - * the file system to determine if the file is considered hidden. - * - * @return {@code true} if the file is considered hidden - * - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the file. - */ - public abstract boolean isHidden() throws IOException; - - /** - * Checks the existence and optionally the accessibility of the file - * located by this path. - * - *

This method checks the existence of a file and that this Java virtual - * machine has appropriate privileges that would allow it access the file - * according to all of access modes specified in the {@code modes} parameter - * as follows: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Value Description
{@link AccessMode#READ READ} Checks that the file exists and that the Java virtual machine has - * permission to read the file.
{@link AccessMode#WRITE WRITE} Checks that the file exists and that the Java virtual machine has - * permission to write to the file,
{@link AccessMode#EXECUTE EXECUTE} Checks that the file exists and that the Java virtual machine has - * permission to {@link Runtime#exec execute} the file. The semantics - * may differ when checking access to a directory. For example, on UNIX - * systems, checking for {@code EXECUTE} access checks that the Java - * virtual machine has permission to search the directory in order to - * access file or subdirectories.
- * - *

If the {@code modes} parameter is of length zero, then the existence - * of the file is checked. - * - *

This method follows symbolic links if the file referenced by this - * object is a symbolic link. Depending on the implementation, this method - * may require to read file permissions, access control lists, or other - * file attributes in order to check the effective access to the file. To - * determine the effective access to a file may require access to several - * attributes and so in some implementations this method may not be atomic - * with respect to other file system operations. Furthermore, as the result - * of this method is immediately outdated, there is no guarantee that a - * subsequence access will succeed (or even that it will access the same - * file). Care should be taken when using this method in security sensitive - * applications. - * - * @param modes - * The access modes to check; may have zero elements - * - * @throws UnsupportedOperationException - * an implementation is required to support checking for - * {@code READ}, {@code WRITE}, and {@code EXECUTE} access. This - * exception is specified to allow for the {@code Access} enum to - * be extended in future releases. - * @throws NoSuchFileException - * if a file does not exist (optional specific exception) - * @throws AccessDeniedException - * the requested access would be denied or the access cannot be - * determined because the Java virtual machine has insufficient - * privileges or other reasons. (optional specific exception) - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * is invoked when checking read access to the file or only the - * existence of the file, the {@link SecurityManager#checkWrite(String) - * checkWrite} is invoked when checking write access to the file, - * and {@link SecurityManager#checkExec(String) checkExec} is invoked - * when checking execute access. - */ - public abstract void checkAccess(AccessMode... modes) throws IOException; - - /** - * Tests whether the file located by this path exists. - * - *

This convenience method is intended for cases where it is required to - * take action when it can be confirmed that a file exists. This method simply - * invokes the {@link #checkAccess checkAccess} method to check if the file - * exists. If the {@code checkAccess} method succeeds then this method returns - * {@code true}, otherwise if an {@code IOException} is thrown (because the - * file doesn't exist or cannot be accessed by this Java virtual machine) - * then {@code false} is returned. - * - *

Note that the result of this method is immediately outdated. If this - * method indicates the file exists then there is no guarantee that a - * subsequence access will succeed. Care should be taken when using this - * method in security sensitive applications. - * - * @return {@code true} if the file exists; {@code false} if the file does - * not exist or its existence cannot be determined. - * - * @throws SecurityException - * In the case of the default provider, the {@link - * SecurityManager#checkRead(String)} is invoked to check - * read access to the file. - * - * @see #notExists - */ - public abstract boolean exists(); - - /** - * Tests whether the file located by this path does not exist. - * - *

This convenience method is intended for cases where it is required to - * take action when it can be confirmed that a file does not exist. This - * method invokes the {@link #checkAccess checkAccess} method to check if the - * file exists. If the file does not exist then {@code true} is returned, - * otherwise the file exists or cannot be accessed by this Java virtual - * machine and {@code false} is returned. - * - *

Note that this method is not the complement of the {@link #exists - * exists} method. Where it is not possible to determine if a file exists - * or not then both methods return {@code false}. As with the {@code exists} - * method, the result of this method is immediately outdated. If this - * method indicates the file does exist then there is no guarantee that a - * subsequence attempt to create the file will succeed. Care should be taken - * when using this method in security sensitive applications. - * - * @return {@code true} if the file does not exist; {@code false} if the - * file exists or its existence cannot be determined. - * - * @throws SecurityException - * In the case of the default provider, the {@link - * SecurityManager#checkRead(String)} is invoked to check - * read access to the file. - */ - public abstract boolean notExists(); - - /** - * Returns the {@link FileStore} representing the file store where an - * existing file, located by this path, is stored. - * - *

Once a reference to the {@code FileStore} is obtained it is - * implementation specific if operations on the returned {@code FileStore}, - * or {@link FileStoreAttributeView} objects obtained from it, continue - * to depend on the existence of the file. In particular the behavior is not - * defined for the case that the file is deleted or moved to a different - * file store. - * - * @return the file store where the file is stored - * - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to the file, and in - * addition it checks {@link RuntimePermission} - * ("getFileStoreAttributes") - */ - public abstract FileStore getFileStore() throws IOException; + File toFile(); // -- watchable -- @@ -1471,8 +594,8 @@ public abstract class Path * *

In this release, this path locates a directory that exists. The * directory is registered with the watch service so that entries in the - * directory can be watched. The {@code events} parameter is an array of - * events to register and may contain the following events: + * directory can be watched. The {@code events} parameter is the events to + * register and may contain the following events: *

    *
  • {@link StandardWatchEventKind#ENTRY_CREATE ENTRY_CREATE} - * entry created or moved into the directory
  • @@ -1489,10 +612,10 @@ public abstract class Path *

    The set of events may include additional implementation specific * event that are not defined by the enum {@link StandardWatchEventKind} * - *

    The {@code modifiers} parameter is an array of modifiers - * that qualify how the directory is registered. This release does not - * define any standard modifiers. The array may contain - * implementation specific modifiers. + *

    The {@code modifiers} parameter specifies modifiers that + * qualify how the directory is registered. This release does not define any + * standard modifiers. It may contain implementation specific + * modifiers. * *

    Where a file is registered with a watch service by means of a symbolic * link then it is implementation specific if the watch continues to depend @@ -1525,9 +648,9 @@ public abstract class Path * method is invoked to check read access to the file. */ @Override - public abstract WatchKey register(WatchService watcher, - WatchEvent.Kind[] events, - WatchEvent.Modifier... modifiers) + WatchKey register(WatchService watcher, + WatchEvent.Kind[] events, + WatchEvent.Modifier... modifiers) throws IOException; /** @@ -1573,8 +696,8 @@ public abstract class Path * method is invoked to check read access to the file. */ @Override - public abstract WatchKey register(WatchService watcher, - WatchEvent.Kind... events) + WatchKey register(WatchService watcher, + WatchEvent.Kind... events) throws IOException; // -- Iterable -- @@ -1591,7 +714,7 @@ public abstract class Path * @return an iterator over the name elements of this path. */ @Override - public abstract Iterator iterator(); + Iterator iterator(); // -- compareTo/equals/hashCode -- @@ -1609,50 +732,7 @@ public abstract class Path * lexicographically greater than the argument */ @Override - public abstract int compareTo(Path other); - - /** - * Tests if the file referenced by this object is the same file referenced - * by another object. - * - *

    If this {@code Path} and the given {@code Path} are {@link - * #equals(Object) equal} then this method returns {@code true} without checking - * if the file exists. If the {@code Path} and the given {@code Path} - * are associated with different providers, or the given {@code Path} is - * {@code null} then this method returns {@code false}. Otherwise, this method - * checks if both {@code Paths} locate the same file, and depending on the - * implementation, may require to open or access both files. - * - *

    If the file system and files remain static, then this method implements - * an equivalence relation for non-null {@code Paths}. - *

      - *
    • It is reflexive: for a non-null {@code Path} {@code f}, - * {@code f.isSameFile(f)} should return {@code true}. - *
    • It is symmetric: for two non-null {@code Path} - * {@code f} and {@code g}, {@code f.isSameFile(g)} will equal - * {@code g.isSameFile(f)}. - *
    • It is transitive: for three {@code Paths} - * {@code f}, {@code g}, and {@code h}, if {@code f.isSameFile(g)} returns - * {@code true} and {@code g.isSameFile(h)} returns {@code true}, then - * {@code f.isSameFile(h)} will return return {@code true}. - *
    - * - * @param other - * the other file reference - * - * @return {@code true} if, and only if, this object and the given object - * locate the same file - * - * @throws IOException - * if an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, the {@link SecurityManager#checkRead(String) checkRead} - * method is invoked to check read access to both files. - * - * @see java.nio.file.attribute.BasicFileAttributes#fileKey - */ - public abstract boolean isSameFile(Path other) throws IOException; + int compareTo(Path other); /** * Tests this path for equality with the given object. @@ -1663,7 +743,9 @@ public abstract class Path *

    Whether or not two path are equal depends on the file system * implementation. In some cases the paths are compared without regard * to case, and others are case sensitive. This method does not access the - * file system and the file is not required to exist. + * file system and the file is not required to exist. Where required, the + * {@link Files#isSameFile isSameFile} method may be used to check if two + * paths locate the same file. * *

    This method satisfies the general contract of the {@link * java.lang.Object#equals(Object) Object.equals} method.

    @@ -1674,8 +756,7 @@ public abstract class Path * @return {@code true} if, and only if, the given object is a {@code Path} * that is identical to this {@code Path} */ - @Override - public abstract boolean equals(Object other); + boolean equals(Object other); /** * Computes a hash code for this path. @@ -1686,8 +767,7 @@ public abstract class Path * * @return the hash-code value for this path */ - @Override - public abstract int hashCode(); + int hashCode(); /** * Returns the string representation of this path. @@ -1701,6 +781,5 @@ public abstract class Path * * @return the string representation of this path */ - @Override - public abstract String toString(); + String toString(); } diff --git a/jdk/src/share/classes/java/nio/file/PathMatcher.java b/jdk/src/share/classes/java/nio/file/PathMatcher.java index 39af77d6b06..952f18f17f9 100644 --- a/jdk/src/share/classes/java/nio/file/PathMatcher.java +++ b/jdk/src/share/classes/java/nio/file/PathMatcher.java @@ -32,7 +32,7 @@ package java.nio.file; * @since 1.7 * * @see FileSystem#getPathMatcher - * @see Path#newDirectoryStream(String) + * @see Files#newDirectoryStream(Path,String) */ public interface PathMatcher { diff --git a/jdk/src/share/classes/java/nio/file/Paths.java b/jdk/src/share/classes/java/nio/file/Paths.java index be51761c486..d0906d4443f 100644 --- a/jdk/src/share/classes/java/nio/file/Paths.java +++ b/jdk/src/share/classes/java/nio/file/Paths.java @@ -39,14 +39,27 @@ public final class Paths { private Paths() { } /** - * Constructs a {@code Path} by converting the given path string. + * Converts a path string, or a sequence of strings that when joined form + * a path string, to a {@code Path}. If {@code more} does not specify any + * elements then the value of the {@code first} parameter is the path string + * to convert. If {@code more} specifies one or more elements then each + * non-empty string, including {@code first}, is considered to be a sequence + * of name elements (see {@link Path}) and is joined to form a path string. + * The details as to how the Strings are joined is provider specific but + * typically they will be joined using the {@link FileSystem#getSeparator + * name-separator} as the separator. For example, if the name separator is + * "{@code /}" and {@code getPath("/foo","bar","gus")} is invoked, then the + * path string {@code "/foo/bar/gus"} is converted to a {@code Path}. + * A {@code Path} representing an empty path is returned if {@code first} + * is the empty string and {@code more} does not contain any non-empty + * strings. * *

    The {@code Path} is obtained by invoking the {@link FileSystem#getPath * getPath} method of the {@link FileSystems#getDefault default} {@link * FileSystem}. * - *

    Note that while this method is very convenient, using it will - * imply an assumed reference to the default FileSystem and limit the + *

    Note that while this method is very convenient, using it will imply + * an assumed reference to the default {@code FileSystem} and limit the * utility of the calling code. Hence it should not be used in library code * intended for flexible reuse. A more flexible alternative is to use an * existing {@code Path} instance as an anchor, such as: @@ -55,8 +68,10 @@ public final class Paths { * Path path = dir.resolve("file"); * * - * @param path - * the path string to convert + * @param first + * the path string or initial part of the path string + * @param more + * additional strings to be joined to form the path string * * @return the resulting {@code Path} * @@ -65,8 +80,8 @@ public final class Paths { * * @see FileSystem#getPath */ - public static Path get(String path) { - return FileSystems.getDefault().getPath(path); + public static Path get(String first, String... more) { + return FileSystems.getDefault().getPath(first, more); } /** diff --git a/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java b/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java index 319237bfe96..fa26e513fd9 100644 --- a/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java +++ b/jdk/src/share/classes/java/nio/file/SecureDirectoryStream.java @@ -43,7 +43,7 @@ import java.io.IOException; * *

    A {@code SecureDirectoryStream} requires corresponding support from the * underlying operating system. Where an implementation supports this features - * then the {@code DirectoryStream} returned by the {@link Path#newDirectoryStream + * then the {@code DirectoryStream} returned by the {@link Files#newDirectoryStream * newDirectoryStream} method will be a {@code SecureDirectoryStream} and must * be cast to that type in order to invoke the methods defined by this interface. * @@ -56,20 +56,15 @@ import java.io.IOException; * @since 1.7 */ -public abstract class SecureDirectoryStream - implements DirectoryStream +public interface SecureDirectoryStream + extends DirectoryStream { - /** - * Initialize a new instance of this class. - */ - protected SecureDirectoryStream() { } - /** * Opens the directory identified by the given path, returning a {@code * SecureDirectoryStream} to iterate over the entries in the directory. * *

    This method works in exactly the manner specified by the {@link - * Path#newDirectoryStream() newDirectoryStream} method for the case that + * Files#newDirectoryStream(Path) newDirectoryStream} method for the case that * the {@code path} parameter is an {@link Path#isAbsolute absolute} path. * When the parameter is a relative path then the directory to open is * relative to this open directory. The {@link @@ -99,8 +94,7 @@ public abstract class SecureDirectoryStream * installed, the {@link SecurityManager#checkRead(String) checkRead} * method is invoked to check read access to the directory. */ - public abstract SecureDirectoryStream newDirectoryStream(T path, - LinkOption... options) + SecureDirectoryStream newDirectoryStream(T path, LinkOption... options) throws IOException; /** @@ -108,11 +102,11 @@ public abstract class SecureDirectoryStream * channel to access the file. * *

    This method works in exactly the manner specified by the {@link - * Path#newByteChannel Path.newByteChannel} method for the + * Files#newByteChannel Files.newByteChannel} method for the * case that the {@code path} parameter is an {@link Path#isAbsolute absolute} * path. When the parameter is a relative path then the file to open or * create is relative to this open directory. In addition to the options - * defined by the {@code Path.newByteChannel} method, the {@link + * defined by the {@code Files.newByteChannel} method, the {@link * LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} option may be used to * ensure that this method fails if the file is a symbolic link. * @@ -149,15 +143,15 @@ public abstract class SecureDirectoryStream * checkWrite} method is invoked to check write access to the path * if the file is opened for writing. */ - public abstract SeekableByteChannel newByteChannel(T path, - Set options, - FileAttribute... attrs) + SeekableByteChannel newByteChannel(T path, + Set options, + FileAttribute... attrs) throws IOException; /** * Deletes a file. * - *

    Unlike the {@link Path#delete delete()} method, this method does + *

    Unlike the {@link Files#delete delete()} method, this method does * not first examine the file to determine if the file is a directory. * Whether a directory is deleted by this method is system dependent and * therefore not specified. If the file is a symbolic link, then the link @@ -179,12 +173,12 @@ public abstract class SecureDirectoryStream * installed, the {@link SecurityManager#checkDelete(String) checkDelete} * method is invoked to check delete access to the file */ - public abstract void deleteFile(T path) throws IOException; + void deleteFile(T path) throws IOException; /** * Deletes a directory. * - *

    Unlike the {@link Path#delete delete()} method, this method + *

    Unlike the {@link Files#delete delete()} method, this method * does not first examine the file to determine if the file is a directory. * Whether non-directories are deleted by this method is system dependent and * therefore not specified. When the parameter is a relative path then the @@ -207,12 +201,12 @@ public abstract class SecureDirectoryStream * installed, the {@link SecurityManager#checkDelete(String) checkDelete} * method is invoked to check delete access to the directory */ - public abstract void deleteDirectory(T path) throws IOException; + void deleteDirectory(T path) throws IOException; /** * Move a file from this directory to another directory. * - *

    This method works in a similar manner to {@link Path#moveTo moveTo} + *

    This method works in a similar manner to {@link Files#move move} * method when the {@link StandardCopyOption#ATOMIC_MOVE ATOMIC_MOVE} option * is specified. That is, this method moves a file as an atomic file system * operation. If the {@code srcpath} parameter is an {@link Path#isAbsolute @@ -247,7 +241,7 @@ public abstract class SecureDirectoryStream * method is invoked to check write access to both the source and * target file. */ - public abstract void move(T srcpath, SecureDirectoryStream targetdir, T targetpath) + void move(T srcpath, SecureDirectoryStream targetdir, T targetpath) throws IOException; /** @@ -273,7 +267,7 @@ public abstract class SecureDirectoryStream * this directory stream, or {@code null} if the attribute view * type is not available */ - public abstract V getFileAttributeView(Class type); + V getFileAttributeView(Class type); /** * Returns a new file attribute view to access the file attributes of a file @@ -306,7 +300,7 @@ public abstract class SecureDirectoryStream * type is not available * */ - public abstract V getFileAttributeView(T path, - Class type, - LinkOption... options); + V getFileAttributeView(T path, + Class type, + LinkOption... options); } diff --git a/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java b/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java index 5b0a4602b4e..8bedbd4c9b3 100644 --- a/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java +++ b/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java @@ -57,8 +57,8 @@ public class SimpleFileVisitor implements FileVisitor { public FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs) throws IOException { - Objects.nonNull(dir); - Objects.nonNull(attrs); + Objects.requireNonNull(dir); + Objects.requireNonNull(attrs); return FileVisitResult.CONTINUE; } @@ -72,8 +72,8 @@ public class SimpleFileVisitor implements FileVisitor { public FileVisitResult visitFile(T file, BasicFileAttributes attrs) throws IOException { - Objects.nonNull(file); - Objects.nonNull(attrs); + Objects.requireNonNull(file); + Objects.requireNonNull(attrs); return FileVisitResult.CONTINUE; } @@ -87,7 +87,7 @@ public class SimpleFileVisitor implements FileVisitor { public FileVisitResult visitFileFailed(T file, IOException exc) throws IOException { - Objects.nonNull(file); + Objects.requireNonNull(file); throw exc; } @@ -104,7 +104,7 @@ public class SimpleFileVisitor implements FileVisitor { public FileVisitResult postVisitDirectory(T dir, IOException exc) throws IOException { - Objects.nonNull(dir); + Objects.requireNonNull(dir); if (exc != null) throw exc; return FileVisitResult.CONTINUE; diff --git a/jdk/src/share/classes/java/io/TempFileHelper.java b/jdk/src/share/classes/java/nio/file/TempFileHelper.java similarity index 56% rename from jdk/src/share/classes/java/io/TempFileHelper.java rename to jdk/src/share/classes/java/nio/file/TempFileHelper.java index 19852f32d1a..377730b4455 100644 --- a/jdk/src/share/classes/java/io/TempFileHelper.java +++ b/jdk/src/share/classes/java/nio/file/TempFileHelper.java @@ -23,54 +23,82 @@ * questions. */ -package java.io; +package java.nio.file; -import java.nio.file.FileSystems; -import java.nio.file.InvalidPathException; -import java.nio.file.FileAlreadyExistsException; +import java.util.Set; +import java.util.EnumSet; +import java.security.SecureRandom; +import static java.security.AccessController.*; +import java.io.IOException; import java.nio.file.attribute.FileAttribute; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import static java.nio.file.attribute.PosixFilePermission.*; -import java.util.Set; -import java.util.EnumSet; +import sun.security.action.GetPropertyAction; + /** - * Helper class to support creation of temporary files and directory with + * Helper class to support creation of temporary files and directories with * initial attributes. */ class TempFileHelper { private TempFileHelper() { } + // temporary directory location + private static final Path tmpdir = + Paths.get(doPrivileged(new GetPropertyAction("java.io.tmpdir"))); + + private static final boolean isPosix = + FileSystems.getDefault().supportedFileAttributeViews().contains("posix"); + + // file name generation, same as java.io.File for now + private static final SecureRandom random = new SecureRandom(); + private static Path generatePath(String prefix, String suffix, Path dir) { + long n = random.nextLong(); + n = (n == Long.MIN_VALUE) ? 0 : Math.abs(n); + Path name = dir.getFileSystem().getPath(prefix + Long.toString(n) + suffix); + // the generated name should be a simple file name + if (name.getParent() != null) + throw new IllegalArgumentException("Invalid prefix or suffix"); + return dir.resolve(name); + } + // default file and directory permissions (lazily initialized) - private static class PermissionsHolder { - static final boolean hasPosixPermissions = FileSystems.getDefault() - .supportedFileAttributeViews().contains("posix"); + private static class PosixPermissions { static final FileAttribute> filePermissions = PosixFilePermissions.asFileAttribute(EnumSet.of(OWNER_READ, OWNER_WRITE)); - static final FileAttribute> directoryPermissions = + static final FileAttribute> dirPermissions = PosixFilePermissions.asFileAttribute(EnumSet .of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE)); } /** - * Creates a file or directory in the temporary directory. + * Creates a file or directory in in the given given directory (or in the + * temporary directory if dir is {@code null}). */ - private static File create(String prefix, + private static Path create(Path dir, + String prefix, String suffix, - FileAttribute[] attrs, - boolean isDirectory) + boolean createDirectory, + FileAttribute[] attrs) throws IOException { + if (prefix == null) + prefix = ""; + if (suffix == null) + suffix = (createDirectory) ? "" : ".tmp"; + if (dir == null) + dir = tmpdir; + // in POSIX environments use default file and directory permissions // if initial permissions not given by caller. - if (PermissionsHolder.hasPosixPermissions) { + if (isPosix && (dir.getFileSystem() == FileSystems.getDefault())) { if (attrs.length == 0) { // no attributes so use default permissions attrs = new FileAttribute[1]; - attrs[0] = (isDirectory) ? PermissionsHolder.directoryPermissions : - PermissionsHolder.filePermissions; + attrs[0] = (createDirectory) ? PosixPermissions.dirPermissions : + PosixPermissions.filePermissions; } else { // check if posix permissions given; if not use default boolean hasPermissions = false; @@ -84,9 +112,9 @@ class TempFileHelper { FileAttribute[] copy = new FileAttribute[attrs.length+1]; System.arraycopy(attrs, 0, copy, 0, attrs.length); attrs = copy; - attrs[attrs.length-1] = (isDirectory) ? - PermissionsHolder.directoryPermissions : - PermissionsHolder.filePermissions; + attrs[attrs.length-1] = (createDirectory) ? + PosixPermissions.dirPermissions : + PosixPermissions.filePermissions; } } } @@ -94,24 +122,25 @@ class TempFileHelper { // loop generating random names until file or directory can be created SecurityManager sm = System.getSecurityManager(); for (;;) { - File tmpdir = File.TempDirectory.location(); - File f = File.TempDirectory.generateFile(prefix, suffix, tmpdir); + Path f; try { - if (isDirectory) { - f.toPath().createDirectory(attrs); - } else { - f.toPath().createFile(attrs); - } - return f; + f = generatePath(prefix, suffix, dir); } catch (InvalidPathException e) { // don't reveal temporary directory location if (sm != null) throw new IllegalArgumentException("Invalid prefix or suffix"); throw e; + } + try { + if (createDirectory) { + return Files.createDirectory(f, attrs); + } else { + return Files.createFile(f, attrs); + } } catch (SecurityException e) { // don't reveal temporary directory location - if (sm != null) - throw new SecurityException("Unable to create temporary file"); + if (dir == tmpdir && sm != null) + throw new SecurityException("Unable to create temporary file or directory"); throw e; } catch (FileAlreadyExistsException e) { // ignore @@ -120,20 +149,27 @@ class TempFileHelper { } /** - * Creates a file in the temporary directory. + * Creates a temporary file in the given directory, or in in the + * temporary directory if dir is {@code null}. */ - static File createFile(String prefix, String suffix, FileAttribute[] attrs) + static Path createTempFile(Path dir, + String prefix, + String suffix, + FileAttribute[] attrs) throws IOException { - return create(prefix, suffix, attrs, false); + return create(dir, prefix, suffix, false, attrs); } /** - * Creates a directory in the temporary directory. + * Creates a temporary directory in the given directory, or in in the + * temporary directory if dir is {@code null}. */ - static File createDirectory(String prefix, FileAttribute[] attrs) + static Path createTempDirectory(Path dir, + String prefix, + FileAttribute[] attrs) throws IOException { - return create(prefix, "", attrs, true); + return create(dir, prefix, null, true, attrs); } } diff --git a/jdk/src/share/classes/java/nio/file/WatchEvent.java b/jdk/src/share/classes/java/nio/file/WatchEvent.java index 68c93a117a4..2753fb2c3ac 100644 --- a/jdk/src/share/classes/java/nio/file/WatchEvent.java +++ b/jdk/src/share/classes/java/nio/file/WatchEvent.java @@ -44,7 +44,7 @@ package java.nio.file; * @since 1.7 */ -public abstract class WatchEvent { +public interface WatchEvent { /** * An event kind, for the purposes of identification. @@ -64,11 +64,6 @@ public abstract class WatchEvent { Class type(); } - /** - * Initializes a new instance of this class. - */ - protected WatchEvent() { } - /** * An event modifier that qualifies how a {@link Watchable} is registered * with a {@link WatchService}. @@ -90,7 +85,7 @@ public abstract class WatchEvent { * * @return the event kind */ - public abstract Kind kind(); + Kind kind(); /** * Returns the event count. If the event count is greater than {@code 1} @@ -98,7 +93,7 @@ public abstract class WatchEvent { * * @return the event count */ - public abstract int count(); + int count(); /** * Returns the context for the event. @@ -112,5 +107,5 @@ public abstract class WatchEvent { * * @return the event context; may be {@code null} */ - public abstract T context(); + T context(); } diff --git a/jdk/src/share/classes/java/nio/file/WatchKey.java b/jdk/src/share/classes/java/nio/file/WatchKey.java index 72997866b20..23897dba454 100644 --- a/jdk/src/share/classes/java/nio/file/WatchKey.java +++ b/jdk/src/share/classes/java/nio/file/WatchKey.java @@ -81,11 +81,7 @@ import java.util.List; * @since 1.7 */ -public abstract class WatchKey { - /** - * Initializes a new instance of this class. - */ - protected WatchKey() { } +public interface WatchKey { /** * Tells whether or not this watch key is valid. @@ -95,7 +91,7 @@ public abstract class WatchKey { * * @return {@code true} if, and only if, this watch key is valid */ - public abstract boolean isValid(); + boolean isValid(); /** * Retrieves and removes all pending events for this watch key, returning @@ -105,7 +101,7 @@ public abstract class WatchKey { * * @return the list of the events retrieved; may be empty */ - public abstract List> pollEvents(); + List> pollEvents(); /** * Resets this watch key. @@ -121,7 +117,7 @@ public abstract class WatchKey { * {@code false} if the watch key could not be reset because it is * no longer {@link #isValid valid} */ - public abstract boolean reset(); + boolean reset(); /** * Cancels the registration with the watch service. Upon return the watch key @@ -134,5 +130,21 @@ public abstract class WatchKey { *

    If this watch key has already been cancelled then invoking this * method has no effect. Once cancelled, a watch key remains forever invalid. */ - public abstract void cancel(); + void cancel(); + + /** + * Returns the object for which this watch key was created. This method will + * continue to return the object even after the key is cancelled. + * + *

    As the {@code WatchService} is intended to map directly on to the + * native file event notification facility (where available) then many of + * details on how registered objects are watched is highly implementation + * specific. When watching a directory for changes for example, and the + * directory is moved or renamed in the file system, there is no guarantee + * that the watch key will be cancelled and so the object returned by this + * method may no longer be a valid path to the directory. + * + * @return the object for which this watch key was created + */ + //T watchable(); } diff --git a/jdk/src/share/classes/java/nio/file/WatchService.java b/jdk/src/share/classes/java/nio/file/WatchService.java index 048472b6cdb..255e03fe518 100644 --- a/jdk/src/share/classes/java/nio/file/WatchService.java +++ b/jdk/src/share/classes/java/nio/file/WatchService.java @@ -103,13 +103,9 @@ import java.util.concurrent.TimeUnit; * @see FileSystem#newWatchService */ -public abstract class WatchService - implements Closeable +public interface WatchService + extends Closeable { - /** - * Initializes a new instance of this class. - */ - protected WatchService() { } /** * Closes this watch service. @@ -129,7 +125,7 @@ public abstract class WatchService * if an I/O error occurs */ @Override - public abstract void close() throws IOException; + void close() throws IOException; /** * Retrieves and removes the next watch key, or {@code null} if none are @@ -140,7 +136,7 @@ public abstract class WatchService * @throws ClosedWatchServiceException * if this watch service is closed */ - public abstract WatchKey poll(); + WatchKey poll(); /** * Retrieves and removes the next watch key, waiting if necessary up to the @@ -160,7 +156,7 @@ public abstract class WatchService * @throws InterruptedException * if interrupted while waiting */ - public abstract WatchKey poll(long timeout, TimeUnit unit) + WatchKey poll(long timeout, TimeUnit unit) throws InterruptedException; /** @@ -174,5 +170,5 @@ public abstract class WatchService * @throws InterruptedException * if interrupted while waiting */ - public abstract WatchKey take() throws InterruptedException; + WatchKey take() throws InterruptedException; } diff --git a/jdk/src/share/classes/java/nio/file/attribute/AclEntry.java b/jdk/src/share/classes/java/nio/file/attribute/AclEntry.java index b49944c1894..a0ea1fd16d5 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/AclEntry.java +++ b/jdk/src/share/classes/java/nio/file/attribute/AclEntry.java @@ -176,7 +176,7 @@ public final class AclEntry { */ public Builder setPermissions(Set perms) { // copy and check for erroneous elements - perms = new HashSet(perms); + perms = EnumSet.copyOf(perms); checkSet(perms, AclEntryPermission.class); this.perms = perms; return this; @@ -190,8 +190,7 @@ public final class AclEntry { * @return this builder */ public Builder setPermissions(AclEntryPermission... perms) { - Set set = - new HashSet(perms.length); + Set set = EnumSet.noneOf(AclEntryPermission.class); // copy and check for null elements for (AclEntryPermission p: perms) { if (p == null) @@ -214,7 +213,7 @@ public final class AclEntry { */ public Builder setFlags(Set flags) { // copy and check for erroneous elements - flags = new HashSet(flags); + flags = EnumSet.copyOf(flags); checkSet(flags, AclEntryFlag.class); this.flags = flags; return this; @@ -228,7 +227,7 @@ public final class AclEntry { * @return this builder */ public Builder setFlags(AclEntryFlag... flags) { - Set set = new HashSet(flags.length); + Set set = EnumSet.noneOf(AclEntryFlag.class); // copy and check for null elements for (AclEntryFlag f: flags) { if (f == null) diff --git a/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java index 13673116623..d4a8ba8b27e 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java @@ -65,7 +65,7 @@ import java.io.IOException; * UserPrincipalLookupService} may be used to obtain a {@link UserPrincipal} * to represent these special identities by invoking the {@link * UserPrincipalLookupService#lookupPrincipalByName lookupPrincipalByName} - * method. + * method.

    * *

    Usage Example: * Suppose we wish to add an entry to an existing ACL to grant "joe" access: @@ -75,7 +75,7 @@ import java.io.IOException; * .lookupPrincipalByName("joe"); * * // get view - * AclFileAttributeView view = file.getFileAttributeView(AclFileAttributeView.class); + * AclFileAttributeView view = Files.getFileAttributeView(file, AclFileAttributeView.class); * * // create ACE to give "joe" read access * AclEntry entry = AclEntry.newBuilder() @@ -110,11 +110,11 @@ import java.io.IOException; * * * - *

    The {@link FileRef#getAttribute getAttribute} method may be used to read + *

    The {@link Files#getAttribute getAttribute} method may be used to read * the ACL or owner attributes as if by invoking the {@link #getAcl getAcl} or * {@link #getOwner getOwner} methods. * - *

    The {@link FileRef#setAttribute setAttribute} method may be used to + *

    The {@link Files#setAttribute setAttribute} method may be used to * update the ACL or owner attributes as if by invoking the {@link #setAcl setAcl} * or {@link #setOwner setOwner} methods. * @@ -122,8 +122,8 @@ import java.io.IOException; * *

    Implementations supporting this attribute view may also support setting * the initial ACL when creating a file or directory. The initial ACL - * may be provided to methods such as {@link Path#createFile createFile} or {@link - * Path#createDirectory createDirectory} as an {@link FileAttribute} with {@link + * may be provided to methods such as {@link Files#createFile createFile} or {@link + * Files#createDirectory createDirectory} as an {@link FileAttribute} with {@link * FileAttribute#name name} {@code "acl:acl"} and a {@link FileAttribute#value * value} that is the list of {@code AclEntry} objects. * @@ -135,8 +135,6 @@ import java.io.IOException; * translation. * * @since 1.7 - * @see Attributes#getAcl - * @see Attributes#setAcl */ public interface AclFileAttributeView diff --git a/jdk/src/share/classes/java/nio/file/attribute/Attributes.java b/jdk/src/share/classes/java/nio/file/attribute/Attributes.java deleted file mode 100644 index 32dbec38ee6..00000000000 --- a/jdk/src/share/classes/java/nio/file/attribute/Attributes.java +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.nio.file.attribute; - -import java.nio.file.*; -import java.io.IOException; -import java.util.*; - -/** - * This class consists exclusively of static methods that operate on or return - * the attributes of files or file stores. These methods provide for convenient - * use of the {@link AttributeView attribute-views} defined in this package. - * - * @since 1.7 - */ - -public final class Attributes { - private Attributes() { } - - /** - * Reads the basic file attributes of a file. - * - *

    The {@code options} array may be used to indicate how symbolic links - * are handled for the case that the file is a symbolic link. By default, - * symbolic links are followed and the file attributes of the final target - * of the link are read. If the option {@link LinkOption#NOFOLLOW_LINKS - * NOFOLLOW_LINKS} is present then symbolic links are not followed and so - * the method returns the file attributes of the symbolic link itself. - * This option should be used where there is a need to determine if a - * file is a symbolic link: - *

    -     *    boolean isSymbolicLink = Attributes.readBasicFileAttributes(file, NOFOLLOW_LINKS).isSymbolicLink();
    -     * 
    - * - *

    It is implementation specific if all file attributes are read as an - * atomic operation with respect to other file system operations. - * - * @param file - * A file reference that locates the file - * @param options - * Options indicating how symbolic links are handled - * - * @return The basic file attributes - * - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, the security manager's {@link - * SecurityManager#checkRead(String) checkRead} method is invoked - * to check read access to file - * - * @see BasicFileAttributeView#readAttributes - */ - public static BasicFileAttributes readBasicFileAttributes(FileRef file, - LinkOption... options) - throws IOException - { - return file.getFileAttributeView(BasicFileAttributeView.class, options) - .readAttributes(); - } - - /** - * Reads the POSIX file attributes of a file. - * - *

    The {@code file} parameter locates a file that supports the {@link - * PosixFileAttributeView}. This file attribute view provides access to a - * subset of the file attributes commonly associated with files on file - * systems used by operating systems that implement the Portable Operating - * System Interface (POSIX) family of standards. It is implementation - * specific if all file attributes are read as an atomic operation with - * respect to other file system operations. - * - *

    The {@code options} array may be used to indicate how symbolic links - * are handled for the case that the file is a symbolic link. By default, - * symbolic links are followed and the file attributes of the final target - * of the link are read. If the option {@link LinkOption#NOFOLLOW_LINKS - * NOFOLLOW_LINKS} is present then symbolic links are not followed and so - * the method returns the file attributes of the symbolic link itself. - * - * @param file - * A file reference that locates the file - * @param options - * Options indicating how symbolic links are handled - * - * @return The POSIX file attributes - * - * @throws UnsupportedOperationException - * If the {@code PosixFileAttributeView} is not available - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, it denies {@link RuntimePermission}("accessUserInformation") - * or its {@link SecurityManager#checkRead(String) checkRead} method - * denies read access to the file. - * - * @see PosixFileAttributeView#readAttributes - */ - public static PosixFileAttributes readPosixFileAttributes(FileRef file, - LinkOption... options) - throws IOException - { - PosixFileAttributeView view = - file.getFileAttributeView(PosixFileAttributeView.class, options); - if (view == null) - throw new UnsupportedOperationException(); - return view.readAttributes(); - } - - /** - * Reads the DOS file attributes of a file. - * - *

    The {@code file} parameter locates a file that supports the {@link - * DosFileAttributeView}. This file attribute view provides access to - * legacy "DOS" attributes supported by the file systems such as File - * Allocation Table (FAT), commonly used in consumer devices. It is - * implementation specific if all file attributes are read as an atomic - * operation with respect to other file system operations. - * - *

    The {@code options} array may be used to indicate how symbolic links - * are handled for the case that the file is a symbolic link. By default, - * symbolic links are followed and the file attributes of the final target - * of the link are read. If the option {@link LinkOption#NOFOLLOW_LINKS - * NOFOLLOW_LINKS} is present then symbolic links are not followed and so - * the method returns the file attributes of the symbolic link itself. - * - * @param file - * A file reference that locates the file - * @param options - * Options indicating how symbolic links are handled - * - * @return The DOS file attributes - * - * @throws UnsupportedOperationException - * If the {@code DosFileAttributeView} is not available - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, the security manager's {@link - * SecurityManager#checkRead(String) checkRead} method is invoked - * to check read access to file - * - * @see DosFileAttributeView#readAttributes - */ - public static DosFileAttributes readDosFileAttributes(FileRef file, - LinkOption... options) - throws IOException - { - DosFileAttributeView view = - file.getFileAttributeView(DosFileAttributeView.class, options); - if (view == null) - throw new UnsupportedOperationException(); - return view.readAttributes(); - } - - /** - * Returns the owner of a file. - * - *

    The {@code file} parameter locates a file that supports the {@link - * FileOwnerAttributeView}. This file attribute view provides access to - * a file attribute that is the owner of the file. - * - * @param file - * A file reference that locates the file - * - * @return A user principal representing the owner of the file - * - * @throws UnsupportedOperationException - * If the {@code FileOwnerAttributeView} is not available - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, it denies {@link RuntimePermission}("accessUserInformation") - * or its {@link SecurityManager#checkRead(String) checkRead} method - * denies read access to the file. - * - * @see FileOwnerAttributeView#getOwner - */ - public static UserPrincipal getOwner(FileRef file) throws IOException { - FileOwnerAttributeView view = - file.getFileAttributeView(FileOwnerAttributeView.class); - if (view == null) - throw new UnsupportedOperationException(); - return view.getOwner(); - } - - /** - * Updates the file owner. - * - *

    The {@code file} parameter locates a file that supports the {@link - * FileOwnerAttributeView}. This file attribute view provides access to - * a file attribute that is the owner of the file. - * - * @param file - * A file reference that locates the file - * @param owner - * The new file owner - * - * @throws UnsupportedOperationException - * If the {@code FileOwnerAttributeView} is not available - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, it denies {@link RuntimePermission}("accessUserInformation") - * or its {@link SecurityManager#checkWrite(String) checkWrite} - * method denies write access to the file. - * - * @see FileOwnerAttributeView#setOwner - */ - public static void setOwner(FileRef file, UserPrincipal owner) - throws IOException - { - FileOwnerAttributeView view = - file.getFileAttributeView(FileOwnerAttributeView.class); - if (view == null) - throw new UnsupportedOperationException(); - view.setOwner(owner); - } - - /** - * Reads a file's Access Control List (ACL). - * - *

    The {@code file} parameter locates a file that supports the {@link - * AclFileAttributeView}. This file attribute view provides access to ACLs - * based on the ACL model specified in - * RFC 3530. - * - * @param file - * A file reference that locates the file - * - * @return An ordered list of {@link AclEntry entries} representing the - * ACL. The returned list is modifiable. - * - * @throws UnsupportedOperationException - * If the {@code AclAttributeView} is not available - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, it denies {@link RuntimePermission}("accessUserInformation") - * or its {@link SecurityManager#checkRead(String) checkRead} method - * denies read access to the file. - * - * @see AclFileAttributeView#getAcl - */ - public static List getAcl(FileRef file) throws IOException { - AclFileAttributeView view = - file.getFileAttributeView(AclFileAttributeView.class); - if (view == null) - throw new UnsupportedOperationException(); - return view.getAcl(); - } - - /** - * Updates a file's Access Control List (ACL). - * - *

    The {@code file} parameter locates a file that supports the {@link - * AclFileAttributeView}. This file attribute view provides access to ACLs - * based on the ACL model specified in - * RFC 3530. - * - * @param file - * A file reference that locates the file - * @param acl - * The new file ACL - * - * @throws UnsupportedOperationException - * If the {@code AclFileAttributeView} is not available - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, it denies {@link RuntimePermission}("accessUserInformation") - * or its {@link SecurityManager#checkWrite(String) checkWrite} - * method denies write access to the file. - * - * @see AclFileAttributeView#setAcl - */ - public static void setAcl(FileRef file, List acl) - throws IOException - { - AclFileAttributeView view = - file.getFileAttributeView(AclFileAttributeView.class); - if (view == null) - throw new UnsupportedOperationException(); - view.setAcl(acl); - } - - /** - * Updates a file's last modified time attribute. The file time is converted - * to the epoch and precision supported by the file system. Converting from - * finer to coarser granularities result in precision loss. The behavior of - * this method when attempting to set a timestamp to a value that is outside - * the range supported by the underlying file store is not defined. It may - * or not fail by throwing an {@code IOException}. - * - *

    If the file system does not support a last modified time attribute - * then this method has no effect. - * - *

    Usage Example: - * Suppose we want to set the last modified time to the current time: - *

    -     *    FileTime now = FileTime.fromMillis(System.currentTimeMillis());
    -     *    Attributes.setLastModifiedTime(file, now);
    -     * 
    - * - * @param file - * A file reference that locates the file - * @param lastModifiedTime - * The new last modified time - * - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, the security manager's {@link - * SecurityManager#checkWrite(String) checkWrite} method is invoked - * to check write access to file - * - * @see BasicFileAttributeView#setTimes - */ - public static void setLastModifiedTime(FileRef file, - FileTime lastModifiedTime) - throws IOException - { - if (lastModifiedTime == null) - throw new NullPointerException("'lastModifiedTime' is null"); - file.getFileAttributeView(BasicFileAttributeView.class) - .setTimes(lastModifiedTime, null, null); - } - - /** - * Updates a file's last access time attribute. The file time is converted - * to the epoch and precision supported by the file system. Converting from - * finer to coarser granularities result in precision loss. The behavior of - * this method when attempting to set a timestamp to a value that is outside - * the range supported by the underlying file store is not defined. It may - * or not fail by throwing an {@code IOException}. - * - *

    If the file system does not support a last access time attribute then - * this method has no effect. - * - * @param file - * A file reference that locates the file - * @param lastAccessTime - * The new last access time - * - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, the security manager's {@link - * SecurityManager#checkWrite(String) checkWrite} method is invoked - * to check write access to file - * - * @see BasicFileAttributeView#setTimes - */ - public static void setLastAccessTime(FileRef file, - FileTime lastAccessTime) - throws IOException - { - if (lastAccessTime == null) - throw new NullPointerException("'lastAccessTime' is null"); - file.getFileAttributeView(BasicFileAttributeView.class) - .setTimes(null, lastAccessTime, null); - } - - /** - * Sets a file's POSIX permissions. - * - *

    The {@code file} parameter is a reference to an existing file. It - * supports the {@link PosixFileAttributeView} that provides access to file - * attributes commonly associated with files on file systems used by - * operating systems that implement the Portable Operating System Interface - * (POSIX) family of standards. - * - * @param file - * A file reference that locates the file - * @param perms - * The new set of permissions - * - * @throws UnsupportedOperationException - * If {@code PosixFileAttributeView} is not available - * @throws ClassCastException - * If the sets contains elements that are not of type {@code - * PosixFilePermission} - * @throws IOException - * If an I/O error occurs - * @throws SecurityException - * In the case of the default provider, and a security manager is - * installed, it denies {@link RuntimePermission}("accessUserInformation") - * or its {@link SecurityManager#checkWrite(String) checkWrite} - * method denies write access to the file. - * - * @see PosixFileAttributeView#setPermissions - */ - public static void setPosixFilePermissions(FileRef file, - Set perms) - throws IOException - { - PosixFileAttributeView view = - file.getFileAttributeView(PosixFileAttributeView.class); - if (view == null) - throw new UnsupportedOperationException(); - view.setPermissions(perms); - } - - /** - * Reads the space attributes of a file store. - * - *

    The {@code store} parameter is a file store that supports the - * {@link FileStoreSpaceAttributeView} providing access to the space related - * attributes of the file store. It is implementation specific if all attributes - * are read as an atomic operation with respect to other file system operations. - * - * @param store - * The file store - * - * @return The file store space attributes - * - * @throws UnsupportedOperationException - * If the file store space attribute view is not supported - * @throws IOException - * If an I/O error occurs - * - * @see FileStoreSpaceAttributeView#readAttributes() - */ - public static FileStoreSpaceAttributes readFileStoreSpaceAttributes(FileStore store) - throws IOException - { - FileStoreSpaceAttributeView view = - store.getFileStoreAttributeView(FileStoreSpaceAttributeView.class); - if (view == null) - throw new UnsupportedOperationException(); - return view.readAttributes(); - } -} diff --git a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java index e2534812e99..4c50f82e952 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributeView.java @@ -85,16 +85,15 @@ import java.io.IOException; * * * - *

    The {@link java.nio.file.FileRef#getAttribute getAttribute} method may be + *

    The {@link java.nio.file.Files#getAttribute getAttribute} method may be * used to read any of these attributes as if by invoking the {@link * #readAttributes() readAttributes()} method. * - *

    The {@link java.nio.file.FileRef#setAttribute setAttribute} method may be + *

    The {@link java.nio.file.Files#setAttribute setAttribute} method may be * used to update the file's last modified time, last access time or create time * attributes as if by invoking the {@link #setTimes setTimes} method. * * @since 1.7 - * @see Attributes */ public interface BasicFileAttributeView @@ -131,9 +130,10 @@ public interface BasicFileAttributeView *

    This method updates the file's timestamp attributes. The values are * converted to the epoch and precision supported by the file system. * Converting from finer to coarser granularities result in precision loss. - * The behavior of this method when attempting to set a timestamp to a value - * that is outside the range supported by the underlying file store is not - * defined. It may or not fail by throwing an {@code IOException}. + * The behavior of this method when attempting to set a timestamp that is + * not supported or to a value that is outside the range supported by the + * underlying file store is not defined. It may or not fail by throwing an + * {@code IOException}. * *

    If any of the {@code lastModifiedTime}, {@code lastAccessTime}, * or {@code createTime} parameters has the value {@code null} then the @@ -146,6 +146,14 @@ public interface BasicFileAttributeView * lastAccessTime} and {@code createTime} parameters are {@code null} then * this method has no effect. * + *

    Usage Example: + * Suppose we want to change a file's creation time. + *

    +     *    Path path = ...
    +     *    FileTime time = ...
    +     *    Files.getFileAttributeView(path, BasicFileAttributeView.class).setTimes(null, null, time);
    +     * 
    + * * @param lastModifiedTime * the new last modified time, or {@code null} to not change the * value @@ -160,6 +168,8 @@ public interface BasicFileAttributeView * In the case of the default provider, a security manager is * installed, its {@link SecurityManager#checkWrite(String) checkWrite} * method is invoked to check write access to the file + * + * @see java.nio.file.Files#setLastModifiedTime */ void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, diff --git a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java index 31e076b9286..aa5d2f56156 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java +++ b/jdk/src/share/classes/java/nio/file/attribute/BasicFileAttributes.java @@ -34,8 +34,8 @@ package java.nio.file.attribute; * *

    Usage Example: *

    - *    FileRef file = ...
    - *    BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file);
    + *    Path file = ...
    + *    BasicFileAttributes attrs = Files.readAttributes(file, BasicFileAttributes.class);
      * 
    * * @since 1.7 @@ -48,25 +48,40 @@ public interface BasicFileAttributes { /** * Returns the time of last modification. * + *

    If the file system implementation does not support a time stamp + * to indicate the time of last modification then this method returns an + * implementation specific default value, typically a {@code FileTime} + * representing the epoch (1970-01-01T00:00:00Z). + * * @return a {@code FileTime} representing the time the file was last - * modified or {@code null} if the attribute is not supported. + * modified */ FileTime lastModifiedTime(); /** - * Returns the time of last access if supported. + * Returns the time of last access. * - * @return a {@code FileTime} representing the time of last access or - * {@code null} if the attribute is not supported. + *

    If the file system implementation does not support a time stamp + * to indicate the time of last access then this method returns + * an implementation specific default value, typically the {@link + * #lastModifiedTime() last-modified-time} or a {@code FileTime} + * representing the epoch (1970-01-01T00:00:00Z). + * + * @return a {@code FileTime} representing the time of last access */ FileTime lastAccessTime(); /** - * Returns the creation time if supported. The creation time is the time - * that the file was created. + * Returns the creation time. The creation time is the time that the file + * was created. * - * @return a {@code FileTime} representing the time the file was created - * or {@code null} if the attribute is not supported. + *

    If the file system implementation does not support a time stamp + * to indicate the time when the file was created then this method returns + * an implementation specific default value, typically the {@link + * #lastModifiedTime() last-modified-time} or a {@code FileTime} + * representing the epoch (1970-01-01T00:00:00Z). + * + * @return a {@code FileTime} representing the time the file was created */ FileTime creationTime(); @@ -120,7 +135,7 @@ public interface BasicFileAttributes { * *

    File keys returned by this method can be compared for equality and are * suitable for use in collections. If the file system and files remain static, - * and two files are the {@link java.nio.file.Path#isSameFile same} with + * and two files are the {@link java.nio.file.Files#isSameFile same} with * non-{@code null} file keys, then their file keys are equal. * * @see java.nio.file.Files#walkFileTree diff --git a/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java index def09013e78..7a21bae5fec 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributeView.java @@ -65,12 +65,12 @@ import java.io.IOException; * * * - *

    The {@link java.nio.file.FileRef#getAttribute getAttribute} method may + *

    The {@link java.nio.file.Files#getAttribute getAttribute} method may * be used to read any of these attributes, or any of the attributes defined by * {@link BasicFileAttributeView} as if by invoking the {@link #readAttributes * readAttributes()} method. * - *

    The {@link java.nio.file.FileRef#setAttribute setAttribute} method may + *

    The {@link java.nio.file.Files#setAttribute setAttribute} method may * be used to update the file's last modified time, last access time or create * time attributes as defined by {@link BasicFileAttributeView}. It may also be * used to update the DOS attributes as if by invoking the {@link #setReadOnly diff --git a/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributes.java b/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributes.java index d8d22174e84..d095d213358 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributes.java +++ b/jdk/src/share/classes/java/nio/file/attribute/DosFileAttributes.java @@ -29,13 +29,13 @@ package java.nio.file.attribute; * File attributes associated with a file in a file system that supports * legacy "DOS" attributes. * - *

    The DOS attributes of a file are retrieved using a {@link - * DosFileAttributeView} by invoking its {@link DosFileAttributeView#readAttributes - * readAttributes} method. + *

    Usage Example: + *

    + *    Path file = ...
    + *    DosFileAttributes attrs = Files.readAttributes(file, DosFileAttributes.class);
    + * 
    * * @since 1.7 - * - * @see Attributes#readDosFileAttributes */ public interface DosFileAttributes diff --git a/jdk/src/share/classes/java/nio/file/attribute/FileAttribute.java b/jdk/src/share/classes/java/nio/file/attribute/FileAttribute.java index d8c32fd7bbe..cd11d43dde8 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/FileAttribute.java +++ b/jdk/src/share/classes/java/nio/file/attribute/FileAttribute.java @@ -28,8 +28,8 @@ package java.nio.file.attribute; /** * An object that encapsulates the value of a file attribute that can be set * atomically when creating a new file or directory by invoking the {@link - * java.nio.file.Path#createFile createFile} or {@link - * java.nio.file.Path#createDirectory createDirectory} methods. + * java.nio.file.Files#createFile createFile} or {@link + * java.nio.file.Files#createDirectory createDirectory} methods. * * @param The type of the file attribute value * diff --git a/jdk/src/share/classes/java/nio/file/attribute/FileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/FileAttributeView.java index c9d7327494e..ee90ba07dba 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/FileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/FileAttributeView.java @@ -33,7 +33,7 @@ package java.nio.file.attribute; * * @since 1.7 * - * @see java.nio.file.FileRef#getFileAttributeView(Class,java.nio.file.LinkOption[]) + * @see java.nio.file.Files#getFileAttributeView(Path,Class,java.nio.file.LinkOption[]) */ public interface FileAttributeView diff --git a/jdk/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java index 8bf3a0932eb..09bc7ca02d6 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java @@ -37,8 +37,8 @@ import java.io.IOException; *

    The {@link #getOwner getOwner} or {@link #setOwner setOwner} methods may * be used to read or update the owner of the file. * - *

    The {@link java.nio.file.FileRef#getAttribute getAttribute} and - * {@link java.nio.file.FileRef#setAttribute setAttribute} methods may also be + *

    The {@link java.nio.file.Files#getAttribute getAttribute} and + * {@link java.nio.file.Files#setAttribute setAttribute} methods may also be * used to read or update the owner. In that case, the owner attribute is * identified by the name {@code "owner"}, and the value of the attribute is * a {@link UserPrincipal}. diff --git a/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java deleted file mode 100644 index dca8d4f010c..00000000000 --- a/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributeView.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.nio.file.attribute; - -import java.io.IOException; - -/** - * A file store attribute view that supports reading of space attributes. - * - *

    Where dynamic access to file attributes is required, the attributes - * supported by this attribute view have the following names and types: - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Name Type
    "totalSpace" {@link Long}
    "usableSpace" {@link Long}
    "unallocatedSpace" {@link Long}
    - *
    - *

    The {@link java.nio.file.FileStore#getAttribute getAttribute} method may - * be used to read any of these attributes. - * - * @since 1.7 - */ - -public interface FileStoreSpaceAttributeView - extends FileStoreAttributeView -{ - /** - * Returns the name of the attribute view. Attribute views of this type - * have the name {@code "space"}. - */ - @Override - String name(); - - /** - * Reads the disk space attributes as a bulk operation. - * - *

    It is file system specific if all attributes are read as an - * atomic operation with respect to other file system operations. - * - * @return The disk space attributes - * - * @throws IOException - * If an I/O error occurs - */ - FileStoreSpaceAttributes readAttributes() throws IOException; -} diff --git a/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributes.java b/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributes.java deleted file mode 100644 index ff2bfb66f61..00000000000 --- a/jdk/src/share/classes/java/nio/file/attribute/FileStoreSpaceAttributes.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.nio.file.attribute; - -/** - * Space related attributes of a file store. - * - * @since 1.7 - * - * @see Attributes#readFileStoreSpaceAttributes - */ - -public interface FileStoreSpaceAttributes { - /** - * Returns the size, in bytes, of the file store. - */ - long totalSpace(); - - /** - * Returns the number of bytes available to this Java virtual machine on the - * file store. - * - *

    The returned number of available bytes is a hint, but not a - * guarantee, that it is possible to use most or any of these bytes. The - * number of usable bytes is most likely to be accurate immediately - * after the space attributes are obtained. It is likely to be made inaccurate - * by any external I/O operations including those made on the system outside - * of this Java virtual machine. - */ - long usableSpace(); - - /** - * Returns the number of unallocated bytes in the file store. - * - *

    The returned number of unallocated bytes is a hint, but not a - * guarantee, that it is possible to use most or any of these bytes. The - * number of unallocated bytes is most likely to be accurate immediately - * after the space attributes are obtained. It is likely to be - * made inaccurate by any external I/O operations including those made on - * the system outside of this virtual machine. - */ - long unallocatedSpace(); -} diff --git a/jdk/src/share/classes/java/nio/file/attribute/FileTime.java b/jdk/src/share/classes/java/nio/file/attribute/FileTime.java index 1b3d2ff2f84..6cac437cdce 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/FileTime.java +++ b/jdk/src/share/classes/java/nio/file/attribute/FileTime.java @@ -35,20 +35,53 @@ import java.util.concurrent.TimeUnit; /** * Represents the value of a file's time stamp attribute. For example, it may - * represent the time that the file was last modified, accessed, or created. + * represent the time that the file was last + * {@link BasicFileAttributes#lastModifiedTime() modified}, + * {@link BasicFileAttributes#lastAccessTime() accessed}, + * or {@link BasicFileAttributes#creationTime() created}. * *

    Instances of this class are immutable. * * @since 1.7 - * @see BasicFileAttributes - * @see Attributes#setLastModifiedTime + * @see java.nio.file.Files#setLastModifiedTime + * @see java.nio.file.Files#getLastModifiedTime */ -public final class FileTime implements Comparable { +public final class FileTime + implements Comparable +{ + /** + * The value since the epoch; can be negative. + */ private final long value; - private final TimeUnit unit; - private String valueAsString; // created lazily + /** + * The unit of granularity to interpret the value. + */ + private final TimeUnit unit; + + /** + * The value return by toString (created lazily) + */ + private String valueAsString; + + /** + * The value in days and excess nanos (created lazily) + */ + private DaysAndNanos daysAndNanos; + + /** + * Returns a DaysAndNanos object representing the value. + */ + private DaysAndNanos asDaysAndNanos() { + if (daysAndNanos == null) + daysAndNanos = new DaysAndNanos(value, unit); + return daysAndNanos; + } + + /** + * Initializes a new instance of this class. + */ private FileTime(long value, TimeUnit unit) { if (unit == null) throw new NullPointerException(); @@ -143,9 +176,8 @@ public final class FileTime implements Comparable { */ @Override public int hashCode() { - // hash value for fixed granularity to satisfy contract with equals - long ms = toMillis(); - return (int)(ms ^ (ms >>> 32)); + // hashcode of days/nanos representation to satisfy contract with equals + return asDaysAndNanos().hashCode(); } /** @@ -162,46 +194,12 @@ public final class FileTime implements Comparable { @Override public int compareTo(FileTime other) { // same granularity - if (unit == other.unit) + if (unit == other.unit) { return (value < other.value) ? -1 : (value == other.value ? 0 : 1); - - // compare in days - long thisValueInDays = unit.toDays(value); - long otherValueInDays = other.unit.toDays(other.value); - if (thisValueInDays != otherValueInDays) - return (thisValueInDays < otherValueInDays) ? -1 : 1; - - // compare remainder in nanoseconds - long thisRemainder = remainderInNanos(thisValueInDays); - long otherRemainder = other.remainderInNanos(otherValueInDays); - return (thisRemainder < otherRemainder) ? -1 : - (thisRemainder == otherRemainder) ? 0 : 1; - } - - private long remainderInNanos(long days) { - // constants for conversion - final long C0 = 1L; - final long C1 = C0 * 24L; - final long C2 = C1 * 60L; - final long C3 = C2 * 60L; - final long C4 = C3 * 1000L; - final long C5 = C4 * 1000L; - final long C6 = C5 * 1000L; - - long scale; - switch (unit) { - case DAYS : scale = C0; break; - case HOURS : scale = C1; break; - case MINUTES : scale = C2; break; - case SECONDS : scale = C3; break; - case MILLISECONDS : scale = C4; break; - case MICROSECONDS : scale = C5; break; - case NANOSECONDS : scale = C6; break; - default: - throw new AssertionError("Unit not handled"); + } else { + // compare using days/nanos representation when unit differs + return asDaysAndNanos().compareTo(other.asDaysAndNanos()); } - long rem = value - (days * scale); - return unit.toNanos(rem); } /** @@ -239,26 +237,12 @@ public final class FileTime implements Comparable { // nothing to do when seconds/minutes/hours/days String fractionAsString = ""; if (unit.compareTo(TimeUnit.SECONDS) < 0) { - // constants for conversion - final long C0 = 1L; - final long C1 = C0 * 1000L; - final long C2 = C1 * 1000L; - final long C3 = C2 * 1000L; - - long scale; - int width; - switch (unit) { - case MILLISECONDS : scale = C1; width = 3; break; - case MICROSECONDS : scale = C2; width = 6; break; - case NANOSECONDS : scale = C3; width = 9; break; - default: - throw new AssertionError("Unit not handled"); - } - long fraction = value % scale; + long fraction = asDaysAndNanos().fractionOfSecondInNanos(); if (fraction != 0L) { // fraction must be positive if (fraction < 0L) { - fraction += scale; + final long MAX_FRACTION_PLUS_1 = 1000L * 1000L * 1000L; + fraction += MAX_FRACTION_PLUS_1; if (ms != Long.MIN_VALUE) ms--; } @@ -266,7 +250,7 @@ public final class FileTime implements Comparable { // stripping any trailing zeros String s = Long.toString(fraction); int len = s.length(); - width -= len; + int width = 9 - len; StringBuilder sb = new StringBuilder("."); while (width-- > 0) { sb.append('0'); @@ -302,4 +286,76 @@ public final class FileTime implements Comparable { } return v; } + + /** + * Represents a FileTime's value as two longs: the number of days since + * the epoch, and the excess (in nanoseconds). This is used for comparing + * values with different units of granularity. + */ + private static class DaysAndNanos implements Comparable { + // constants for conversion + private static final long C0 = 1L; + private static final long C1 = C0 * 24L; + private static final long C2 = C1 * 60L; + private static final long C3 = C2 * 60L; + private static final long C4 = C3 * 1000L; + private static final long C5 = C4 * 1000L; + private static final long C6 = C5 * 1000L; + + /** + * The value (in days) since the epoch; can be negative. + */ + private final long days; + + /** + * The excess (in nanoseconds); can be negative if days <= 0. + */ + private final long excessNanos; + + /** + * Initializes a new instance of this class. + */ + DaysAndNanos(long value, TimeUnit unit) { + long scale; + switch (unit) { + case DAYS : scale = C0; break; + case HOURS : scale = C1; break; + case MINUTES : scale = C2; break; + case SECONDS : scale = C3; break; + case MILLISECONDS : scale = C4; break; + case MICROSECONDS : scale = C5; break; + case NANOSECONDS : scale = C6; break; + default : throw new AssertionError("Unit not handled"); + } + this.days = unit.toDays(value); + this.excessNanos = unit.toNanos(value - (this.days * scale)); + } + + /** + * Returns the fraction of a second, in nanoseconds. + */ + long fractionOfSecondInNanos() { + return excessNanos % (1000L * 1000L * 1000L); + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof DaysAndNanos) ? + compareTo((DaysAndNanos)obj) == 0 : false; + } + + @Override + public int hashCode() { + return (int)(days ^ (days >>> 32) ^ + excessNanos ^ (excessNanos >>> 32)); + } + + @Override + public int compareTo(DaysAndNanos other) { + if (this.days != other.days) + return (this.days < other.days) ? -1 : 1; + return (this.excessNanos < other.excessNanos) ? -1 : + (this.excessNanos == other.excessNanos) ? 0 : 1; + } + } } diff --git a/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java index 2ec2008d382..9f1a668a8c6 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java @@ -60,8 +60,8 @@ import java.io.IOException; *

    Usage Example: * Suppose we need to print out the owner and access permissions of a file: *

    - *     FileRef file = ...
    - *     PosixFileAttributes attrs = file.getFileAttributeView(PosixFileAttributeView.class)
    + *     Path file = ...
    + *     PosixFileAttributes attrs = Files.getFileAttributeView(file, PosixFileAttributeView.class)
      *         .readAttributes();
      *     System.out.format("%s %s%n",
      *         attrs.owner().getName(),
    @@ -90,12 +90,12 @@ import java.io.IOException;
      * 
      * 
      *
    - * 

    The {@link FileRef#getAttribute getAttribute} method may be used to read + *

    The {@link Files#getAttribute getAttribute} method may be used to read * any of these attributes, or any of the attributes defined by {@link * BasicFileAttributeView} as if by invoking the {@link #readAttributes * readAttributes()} method. * - *

    The {@link FileRef#setAttribute setAttribute} method may be used to update + *

    The {@link Files#setAttribute setAttribute} method may be used to update * the file's last modified time, last access time or create time attributes as * defined by {@link BasicFileAttributeView}. It may also be used to update * the permissions, owner, or group-owner as if by invoking the {@link @@ -105,8 +105,8 @@ import java.io.IOException; *

    Setting Initial Permissions

    *

    Implementations supporting this attribute view may also support setting * the initial permissions when creating a file or directory. The - * initial permissions are provided to the {@link Path#createFile createFile} - * or {@link Path#createDirectory createDirectory} methods as a {@link + * initial permissions are provided to the {@link Files#createFile createFile} + * or {@link Files#createDirectory createDirectory} methods as a {@link * FileAttribute} with {@link FileAttribute#name name} {@code "posix:permissions"} * and a {@link FileAttribute#value value} that is the set of permissions. The * following example uses the {@link PosixFilePermissions#asFileAttribute @@ -117,7 +117,7 @@ import java.io.IOException; * Path path = ... * Set<PosixFilePermission> perms = * EnumSet.of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ); - * path.createFile(PosixFilePermissions.asFileAttribute(perms)); + * Files.createFile(path, PosixFilePermissions.asFileAttribute(perms)); *

    * *

    When the access permissions are set at file creation time then the actual @@ -128,13 +128,11 @@ import java.io.IOException; * the access permissions, and the underlying file system supports access * permissions, then it is required that the value of the actual access * permissions will be equal or less than the value of the attribute - * provided to the {@link java.nio.file.Path#createFile createFile} or - * {@link java.nio.file.Path#createDirectory createDirectory} methods. In - * other words, the file may be more secure than requested. + * provided to the {@link Files#createFile createFile} or {@link + * Files#createDirectory createDirectory} methods. In other words, the file may + * be more secure than requested. * * @since 1.7 - * - * @see Attributes#readPosixFileAttributes */ public interface PosixFileAttributeView diff --git a/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributes.java b/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributes.java index 6dfd650c327..361d4c2cc6e 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributes.java +++ b/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributes.java @@ -37,8 +37,6 @@ import java.util.Set; * PosixFileAttributeView#readAttributes readAttributes} method. * * @since 1.7 - * - * @see Attributes#readPosixFileAttributes */ public interface PosixFileAttributes diff --git a/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermission.java b/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermission.java index 3c5f33f86c7..52419b7b0aa 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermission.java +++ b/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermission.java @@ -25,14 +25,12 @@ package java.nio.file.attribute; -import java.util.*; - /** * Defines the bits for use with the {@link PosixFileAttributes#permissions() * permissions} attribute. * - *

    The {@link PosixFileAttributes} class defines method methods for - * manipulating {@link Set sets} of permissions. + *

    The {@link PosixFilePermissions} class defines methods for manipulating + * set of permissions. * * @since 1.7 */ diff --git a/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java b/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java index b3903957ef3..7499fa9498f 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java +++ b/jdk/src/share/classes/java/nio/file/attribute/PosixFilePermissions.java @@ -126,7 +126,7 @@ public final class PosixFilePermissions { public static Set fromString(String perms) { if (perms.length() != 9) throw new IllegalArgumentException("Invalid mode"); - Set result = new HashSet(); + Set result = EnumSet.noneOf(PosixFilePermission.class); if (isR(perms.charAt(0))) result.add(OWNER_READ); if (isW(perms.charAt(1))) result.add(OWNER_WRITE); if (isX(perms.charAt(2))) result.add(OWNER_EXECUTE); @@ -141,8 +141,8 @@ public final class PosixFilePermissions { /** * Creates a {@link FileAttribute}, encapsulating a copy of the given file - * permissions, suitable for passing to the {@link java.nio.file.Path#createFile - * createFile} or {@link java.nio.file.Path#createDirectory createDirectory} + * permissions, suitable for passing to the {@link java.nio.file.Files#createFile + * createFile} or {@link java.nio.file.Files#createDirectory createDirectory} * methods. * * @param perms diff --git a/jdk/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java index 04493e39369..41aaf2f107d 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java @@ -59,9 +59,9 @@ import java.io.IOException; * attributes. * *

    Where dynamic access to file attributes is required, the {@link - * java.nio.file.FileRef#getAttribute getAttribute} method may be used to read + * java.nio.file.Files#getAttribute getAttribute} method may be used to read * the attribute value. The attribute value is returned as a byte array (byte[]). - * The {@link java.nio.file.FileRef#setAttribute setAttribute} method may be used + * The {@link java.nio.file.Files#setAttribute setAttribute} method may be used * to write the value of a user-defined attribute from a buffer (as if by * invoking the {@link #write write} method), or byte array (byte[]). * @@ -132,8 +132,8 @@ public interface UserDefinedFileAttributeView * Suppose we want to read a file's MIME type that is stored as a user-defined * attribute with the name "{@code user.mimetype}". *

    -     *    UserDefinedFileAttributeView view = file
    -     *        .getFileAttributeView(UserDefinedFileAttributeView.class);
    +     *    UserDefinedFileAttributeView view =
    +     *        Files.getFileAttributeView(path, UserDefinedFileAttributeView.class);
          *    String name = "user.mimetype";
          *    ByteBuffer buf = ByteBuffer.allocate(view.size(name));
          *    view.read(name, buf);
    @@ -189,8 +189,8 @@ public interface UserDefinedFileAttributeView
          * 

    Usage Example: * Suppose we want to write a file's MIME type as a user-defined attribute: *

    -     *    UserDefinedFileAttributeView view = file
    -     *        .getFileAttributeView(UserDefinedFileAttributeView.class);
    +     *    UserDefinedFileAttributeView view =
    +     *        FIles.getFileAttributeView(path, UserDefinedFileAttributeView.class);
          *    view.write("user.mimetype", Charset.defaultCharset().encode("text/html"));
          * 
    * diff --git a/jdk/src/share/classes/java/nio/file/attribute/package-info.java b/jdk/src/share/classes/java/nio/file/attribute/package-info.java index a82881176df..0f06fded673 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/package-info.java +++ b/jdk/src/share/classes/java/nio/file/attribute/package-info.java @@ -46,8 +46,6 @@ * Can read or update user-defined file attributes *   {@link java.nio.file.attribute.FileStoreAttributeView} * Can read or update file system attributes - *     {@link java.nio.file.attribute.FileStoreSpaceAttributeView}   - * Can read file system space usage related attributes * * *

    An attribute view provides a read-only or updatable view of the non-opaque @@ -55,7 +53,7 @@ * The {@link java.nio.file.attribute.FileAttributeView} interface is * extended by several other interfaces that that views to specific sets of file * attributes. {@code FileAttributeViews} are selected by invoking the {@link - * java.nio.file.FileRef#getFileAttributeView} method with a + * java.nio.file.Files#getFileAttributeView} method with a * type-token to identify the required view. Views can also be identified * by name. The {@link java.nio.file.attribute.FileStoreAttributeView} interface * provides access to file store attributes. A {@code FileStoreAttributeView} of @@ -83,13 +81,6 @@ * on the model defined by * RFC 3530: Network File System (NFS) version 4 Protocol. * - *

    The {@link java.nio.file.attribute.FileStoreSpaceAttributeView} class - * defines methods to read file system space usage related attributes of a file system. - * - *

    The {@link java.nio.file.attribute.Attributes} utility class defines - * static methods to access file or file system attribute using the above - * attribute views. - * *

    In addition to attribute views, this package also defines classes and * interfaces that are used when accessing attributes: * diff --git a/jdk/src/share/classes/java/nio/file/package-info.java b/jdk/src/share/classes/java/nio/file/package-info.java index d5fa4d6bbd7..5a687774aef 100644 --- a/jdk/src/share/classes/java/nio/file/package-info.java +++ b/jdk/src/share/classes/java/nio/file/package-info.java @@ -31,7 +31,7 @@ * systems. The API to access file and file system attributes is defined in the * {@link java.nio.file.attribute} package. The {@link java.nio.file.spi} * package is used by service provider implementors wishing to extend the - * platform default provider, or to construct other provider implementations. + * platform default provider, or to construct other provider implementations.

    * *

    Symbolic Links

    * Many operating systems and file systems support for symbolic links. @@ -43,7 +43,7 @@ * target of the link. This package includes support for symbolic links where * implementations provide these semantics. File systems may support other types * that are semantically close but support for these other types of links is - * not included in this package. + * not included in this package.

    * *

    Interoperability

    * The {@link java.io.File} class defines the {@link java.io.File#toPath @@ -52,7 +52,7 @@ * {@code Path} can be used to operate on the same file as the {@code File} * object. The {@code Path} specification provides further information * on the interoperability between {@code Path} - * and {@code java.io.File} objects. + * and {@code java.io.File} objects.

    * *

    Visibility

    * The view of the files and file system provided by classes in this package are @@ -63,7 +63,7 @@ * network-filesystem protocols. This is true regardless of the language in which * these other programs are written, and whether they are running on the same machine * or on some other machine. The exact nature of any such inconsistencies are - * system-dependent and are therefore unspecified. + * system-dependent and are therefore unspecified.

    * *

    Synchronized I/O File Integrity

    * The {@link java.nio.file.StandardOpenOption#SYNC SYNC} and {@link @@ -80,14 +80,14 @@ * crash. If the file does not reside on a local device then no such guarantee * is made. Whether this guarantee is possible with other {@link * java.nio.file.spi.FileSystemProvider provider} implementations is provider - * specific. + * specific.

    * *

    General Exceptions

    * Unless otherwise noted, passing a {@code null} argument to a constructor * or method of any class or interface in this package will cause a {@link * java.lang.NullPointerException NullPointerException} to be thrown. Additionally, * invoking a method with a collection containing a {@code null} element will - * cause a {@code NullPointerException}, unless otherwise specified. + * cause a {@code NullPointerException}, unless otherwise specified.

    * *

    Unless otherwise noted, methods that attempt to access the file system * will throw {@link java.nio.file.ClosedFileSystemException} when invoked on @@ -95,12 +95,13 @@ * {@link java.nio.file.FileSystem#close closed}. Additionally, any methods * that attempt write access to a file system will throw {@link * java.nio.file.ReadOnlyFileSystemException} when invoked on an object associated - * with a {@link java.nio.file.FileSystem} that only provides read-only access. + * with a {@link java.nio.file.FileSystem} that only provides read-only + * access.

    * *

    Unless otherwise noted, invoking a method of any class or interface in * this package created by one {@link java.nio.file.spi.FileSystemProvider * provider} with a parameter that is an object created by another provider, - * will throw {@link java.nio.file.ProviderMismatchException}. + * will throw {@link java.nio.file.ProviderMismatchException}.

    * *

    Optional Specific Exceptions

    * Most of the methods defined by classes in this package that access the diff --git a/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java b/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java index a267ad11bba..ad285bd6ddb 100644 --- a/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java +++ b/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java @@ -26,17 +26,21 @@ package java.nio.file.spi; import java.nio.file.*; -import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.*; import java.nio.channels.*; import java.net.URI; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; import java.util.*; import java.util.concurrent.ExecutorService; import java.security.AccessController; import java.security.PrivilegedAction; -import java.io.IOException; /** - * Service-provider class for file systems. + * Service-provider class for file systems. The methods defined by the {@link + * java.nio.file.Files} class will typically delegate to an instance of this + * class. * *

    A file system provider is a concrete implementation of this class that * implements the abstract methods defined by this class. A provider is @@ -64,13 +68,6 @@ import java.io.IOException; * the {@code newFileSystem} method is invoked. In the case of the default * provider, the {@code FileSystem} is created when the provider is initialized. * - *

    In addition to file systems, a provider is also a factory for {@link - * FileChannel} and {@link AsynchronousFileChannel} channels. The {@link - * #newFileChannel newFileChannel} and {@link #newAsynchronousFileChannel - * AsynchronousFileChannel} methods are defined to open or create files, returning - * a channel to access the file. These methods are invoked by static factory - * methods defined in the {@link java.nio.channels} package. - * *

    All of the methods in this class are safe for use by multiple concurrent * threads. * @@ -202,9 +199,10 @@ public abstract class FileSystemProvider { * *

    This method throws {@link FileSystemAlreadyExistsException} if the * file system already exists because it was previously created by an - * invocation of this method. Once a file system is {@link FileSystem#close - * closed} it is provider-dependent if the provider allows a new file system - * to be created with the same URI as a file system it previously created. + * invocation of this method. Once a file system is {@link + * java.nio.file.FileSystem#close closed} it is provider-dependent if the + * provider allows a new file system to be created with the same URI as a + * file system it previously created. * * @param uri * URI reference @@ -234,20 +232,21 @@ public abstract class FileSystemProvider { * *

    This method returns a reference to a {@code FileSystem} that was * created by invoking the {@link #newFileSystem(URI,Map) newFileSystem(URI,Map)} - * method. File systems created the {@link #newFileSystem(FileRef,Map) - * newFileSystem(FileRef,Map)} method are not returned by this method. + * method. File systems created the {@link #newFileSystem(Path,Map) + * newFileSystem(Path,Map)} method are not returned by this method. * The file system is identified by its {@code URI}. Its exact form * is highly provider dependent. In the case of the default provider the URI's * path component is {@code "/"} and the authority, query and fragment components * are undefined (Undefined components are represented by {@code null}). * - *

    Once a file system created by this provider is {@link FileSystem#close - * closed} it is provider-dependent if this method returns a reference to - * the closed file system or throws {@link FileSystemNotFoundException}. - * If the provider allows a new file system to be created with the same URI - * as a file system it previously created then this method throws the - * exception if invoked after the file system is closed (and before a new - * instance is created by the {@link #newFileSystem newFileSystem} method). + *

    Once a file system created by this provider is {@link + * java.nio.file.FileSystem#close closed} it is provider-dependent if this + * method returns a reference to the closed file system or throws {@link + * FileSystemNotFoundException}. If the provider allows a new file system to + * be created with the same URI as a file system it previously created then + * this method throws the exception if invoked after the file system is + * closed (and before a new instance is created by the {@link #newFileSystem + * newFileSystem} method). * *

    If a security manager is installed then a provider implementation * may require to check a permission before returning a reference to an @@ -306,17 +305,16 @@ public abstract class FileSystemProvider { * *

    This method is intended for specialized providers of pseudo file * systems where the contents of one or more files is treated as a file - * system. The {@code file} parameter is a reference to an existing file - * and the {@code env} parameter is a map of provider specific properties to - * configure the file system. + * system. The {@code env} parameter is a map of provider specific properties + * to configure the file system. * *

    If this provider does not support the creation of such file systems * or if the provider does not recognize the file type of the given file then * it throws {@code UnsupportedOperationException}. The default implementation * of this method throws {@code UnsupportedOperationException}. * - * @param file - * The file + * @param path + * The path to the file * @param env * A map of provider specific properties to configure the file system; * may be empty @@ -336,32 +334,121 @@ public abstract class FileSystemProvider { * If a security manager is installed and it denies an unspecified * permission. */ - public FileSystem newFileSystem(FileRef file, Map env) + public FileSystem newFileSystem(Path path, Map env) throws IOException { throw new UnsupportedOperationException(); } /** - * Opens or creates a file for reading and/or writing, returning a file - * channel to access the file. + * Opens a file, returning an input stream to read from the file. This + * method works in exactly the manner specified by the {@link + * Files#newInputStream} method. * - *

    This method is invoked by the {@link FileChannel#open(Path,Set,FileAttribute[]) - * FileChannel.open} method to open a file channel. A provider that does not - * support all the features required to construct a file channel throws - * {@code UnsupportedOperationException}. The default provider is required - * to support the creation of file channels. When not overridden, the - * default implementation throws {@code UnsupportedOperationException}. + *

    The default implementation of this method opens a channel to the file + * as if by invoking the {@link #newByteChannel} method and constructs a + * stream that reads bytes from the channel. This method should be overridden + * where appropriate. * * @param path - * The path of the file to open or create + * the path to the file to open * @param options - * Options specifying how the file is opened + * options specifying how the file is opened + * + * @return a new input stream + * + * @throws IllegalArgumentException + * if an invalid combination of options is specified + * @throws UnsupportedOperationException + * if an unsupported option is specified + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file. + */ + public InputStream newInputStream(Path path, OpenOption... options) + throws IOException + { + if (options.length > 0) { + for (OpenOption opt: options) { + if (opt != StandardOpenOption.READ) + throw new UnsupportedOperationException("'" + opt + "' not allowed"); + } + } + return Channels.newInputStream(Files.newByteChannel(path)); + } + + /** + * Opens or creates a file, returning an output stream that may be used to + * write bytes to the file. This method works in exactly the manner + * specified by the {@link Files#newOutputStream} method. + * + *

    The default implementation of this method opens a channel to the file + * as if by invoking the {@link #newByteChannel} method and constructs a + * stream that writes bytes to the channel. This method should be overridden + * where appropriate. + * + * @param path + * the path to the file to open or create + * @param options + * options specifying how the file is opened + * + * @return a new output stream + * + * @throws IllegalArgumentException + * if {@code options} contains an invalid combination of options + * @throws UnsupportedOperationException + * if an unsupported option is specified + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to the file. The {@link + * SecurityManager#checkDelete(String) checkDelete} method is + * invoked to check delete access if the file is opened with the + * {@code DELETE_ON_CLOSE} option. + */ + public OutputStream newOutputStream(Path path, OpenOption... options) + throws IOException + { + int len = options.length; + Set opts = new HashSet(len + 3); + if (len == 0) { + opts.add(StandardOpenOption.CREATE); + opts.add(StandardOpenOption.TRUNCATE_EXISTING); + } else { + for (OpenOption opt: options) { + if (opt == StandardOpenOption.READ) + throw new IllegalArgumentException("READ not allowed"); + opts.add(opt); + } + } + opts.add(StandardOpenOption.WRITE); + return Channels.newOutputStream(newByteChannel(path, opts)); + } + + /** + * Opens or creates a file for reading and/or writing, returning a file + * channel to access the file. This method works in exactly the manner + * specified by the {@link FileChannel#open(Path,Set,FileAttribute[]) + * FileChannel.open} method. A provider that does not support all the + * features required to construct a file channel throws {@code + * UnsupportedOperationException}. The default provider is required to + * support the creation of file channels. When not overridden, the default + * implementation throws {@code UnsupportedOperationException}. + * + * @param path + * the path of the file to open or create + * @param options + * options specifying how the file is opened * @param attrs - * An optional list of file attributes to set atomically when + * an optional list of file attributes to set atomically when * creating the file * - * @return A new file channel + * @return a new file channel * * @throws IllegalArgumentException * If the set contains an invalid combination of options @@ -387,11 +474,10 @@ public abstract class FileSystemProvider { /** * Opens or creates a file for reading and/or writing, returning an - * asynchronous file channel to access the file. - * - *

    This method is invoked by the {@link + * asynchronous file channel to access the file. This method works in + * exactly the manner specified by the {@link * AsynchronousFileChannel#open(Path,Set,ExecutorService,FileAttribute[]) - * AsynchronousFileChannel.open} method to open an asynchronous file channel. + * AsynchronousFileChannel.open} method. * A provider that does not support all the features required to construct * an asynchronous file channel throws {@code UnsupportedOperationException}. * The default provider is required to support the creation of asynchronous @@ -399,17 +485,17 @@ public abstract class FileSystemProvider { * method throws {@code UnsupportedOperationException}. * * @param path - * The path of the file to open or create + * the path of the file to open or create * @param options - * Options specifying how the file is opened + * options specifying how the file is opened * @param executor - * The thread pool or {@code null} to associate the channel with + * the thread pool or {@code null} to associate the channel with * the default thread pool * @param attrs - * An optional list of file attributes to set atomically when + * an optional list of file attributes to set atomically when * creating the file * - * @return A new asynchronous file channel + * @return a new asynchronous file channel * * @throws IllegalArgumentException * If the set contains an invalid combination of options @@ -434,4 +520,569 @@ public abstract class FileSystemProvider { { throw new UnsupportedOperationException(); } + + /** + * Opens or creates a file, returning a seekable byte channel to access the + * file. This method works in exactly the manner specified by the {@link + * Files#newByteChannel(Path,Set,FileAttribute[])} method. + * + * @param path + * the path to the file to open or create + * @param options + * options specifying how the file is opened + * @param attrs + * an optional list of file attributes to set atomically when + * creating the file + * + * @return a new seekable byte channel + * + * @throws IllegalArgumentException + * if the set contains an invalid combination of options + * @throws UnsupportedOperationException + * if an unsupported open option is specified or the array contains + * attributes that cannot be set atomically when creating the file + * @throws FileAlreadyExistsException + * if a file of that name already exists and the {@link + * StandardOpenOption#CREATE_NEW CREATE_NEW} option is specified + * (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the path if the file is + * opened for reading. The {@link SecurityManager#checkWrite(String) + * checkWrite} method is invoked to check write access to the path + * if the file is opened for writing. The {@link + * SecurityManager#checkDelete(String) checkDelete} method is + * invoked to check delete access if the file is opened with the + * {@code DELETE_ON_CLOSE} option. + */ + public abstract SeekableByteChannel newByteChannel(Path path, + Set options, FileAttribute... attrs) throws IOException; + + /** + * Opens a directory, returning a {@code DirectoryStream} to iterate over + * the entries in the directory. This method works in exactly the manner + * specified by the {@link + * Files#newDirectoryStream(java.nio.file.Path, java.nio.file.DirectoryStream.Filter)} + * method. + * + * @param dir + * the path to the directory + * @param filter + * the directory stream filter + * + * @return a new and open {@code DirectoryStream} object + * + * @throws NotDirectoryException + * if the file could not otherwise be opened because it is not + * a directory (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the directory. + */ + public abstract DirectoryStream newDirectoryStream(Path dir, + DirectoryStream.Filter filter) throws IOException; + + /** + * Creates a new directory. This method works in exactly the manner + * specified by the {@link Files#createDirectory} method. + * + * @param dir + * the directory to create + * @param attrs + * an optional list of file attributes to set atomically when + * creating the directory + * + * @throws UnsupportedOperationException + * if the array contains an attribute that cannot be set atomically + * when creating the directory + * @throws FileAlreadyExistsException + * if a directory could not otherwise be created because a file of + * that name already exists (optional specific exception) + * @throws IOException + * if an I/O error occurs or the parent directory does not exist + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to the new directory. + */ + public abstract void createDirectory(Path dir, FileAttribute... attrs) + throws IOException; + + /** + * Creates a symbolic link to a target. This method works in exactly the + * manner specified by the {@link Files#createSymbolicLink} method. + * + *

    The default implementation of this method throws {@code + * UnsupportedOperationException}. + * + * @param link + * the path of the symbolic link to create + * @param target + * the target of the symbolic link + * @param attrs + * the array of attributes to set atomically when creating the + * symbolic link + * + * @throws UnsupportedOperationException + * if the implementation does not support symbolic links or the + * array contains an attribute that cannot be set atomically when + * creating the symbolic link + * @throws FileAlreadyExistsException + * if a file with the name already exists (optional specific + * exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager + * is installed, it denies {@link LinkPermission}("symbolic") + * or its {@link SecurityManager#checkWrite(String) checkWrite} + * method denies write access to the path of the symbolic link. + */ + public void createSymbolicLink(Path link, Path target, FileAttribute... attrs) + throws IOException + { + throw new UnsupportedOperationException(); + } + + /** + * Creates a new link (directory entry) for an existing file. This method + * works in exactly the manner specified by the {@link Files#createLink} + * method. + * + *

    The default implementation of this method throws {@code + * UnsupportedOperationException}. + * + * @param link + * the link (directory entry) to create + * @param existing + * a path to an existing file + * + * @throws UnsupportedOperationException + * if the implementation does not support adding an existing file + * to a directory + * @throws FileAlreadyExistsException + * if the entry could not otherwise be created because a file of + * that name already exists (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager + * is installed, it denies {@link LinkPermission}("hard") + * or its {@link SecurityManager#checkWrite(String) checkWrite} + * method denies write access to either the link or the + * existing file. + */ + public void createLink(Path link, Path existing) throws IOException { + throw new UnsupportedOperationException(); + } + + /** + * Deletes a file. This method works in exactly the manner specified by the + * {@link Files#delete} method. + * + * @param path + * the path to the file to delete + * + * @throws NoSuchFileException + * if the file does not exist (optional specific exception) + * @throws DirectoryNotEmptyException + * if the file is a directory and could not otherwise be deleted + * because the directory is not empty (optional specific + * exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkDelete(String)} method + * is invoked to check delete access to the file + */ + public abstract void delete(Path path) throws IOException; + + /** + * Deletes a file if it exists. This method works in exactly the manner + * specified by the {@link Files#deleteIfExists} method. + * + *

    The default implementation of this method simply invokes {@link + * #delete} ignoring the {@code NoSuchFileException} when the file does not + * exist. It may be overridden where appropriate. + * + * @param path + * the path to the file to delete + * + * @return {@code true} if the file was deleted by this method; {@code + * false} if the file could not be deleted because it did not + * exist + * + * @throws DirectoryNotEmptyException + * if the file is a directory and could not otherwise be deleted + * because the directory is not empty (optional specific + * exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkDelete(String)} method + * is invoked to check delete access to the file + */ + public boolean deleteIfExists(Path path) throws IOException { + try { + delete(path); + return true; + } catch (NoSuchFileException ignore) { + return false; + } + } + + /** + * Reads the target of a symbolic link. This method works in exactly the + * manner specified by the {@link Files#readSymbolicLink} method. + * + *

    The default implementation of this method throws {@code + * UnsupportedOperationException}. + * + * @param link + * the path to the symbolic link + * + * @throws UnsupportedOperationException + * if the implementation does not support symbolic links + * @throws NotLinkException + * if the target could otherwise not be read because the file + * is not a symbolic link (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager + * is installed, it checks that {@code FilePermission} has been + * granted with the "{@code readlink}" action to read the link. + */ + public Path readSymbolicLink(Path link) throws IOException { + throw new UnsupportedOperationException(); + } + + /** + * Copy a file to a target file. This method works in exactly the manner + * specified by the {@link Files#copy(Path,Path,CopyOption[])} method + * except that both the source and target paths must be associated with + * this provider. + * + * @param source + * the path to the file to copy + * @param target + * the path to the target file + * @param options + * options specifying how the copy should be done + * + * @throws UnsupportedOperationException + * if the array contains a copy option that is not supported + * @throws FileAlreadyExistsException + * if the target file exists but cannot be replaced because the + * {@code REPLACE_EXISTING} option is not specified (optional + * specific exception) + * @throws DirectoryNotEmptyException + * the {@code REPLACE_EXISTING} option is specified but the file + * cannot be replaced because it is a non-empty directory + * (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the source file, the + * {@link SecurityManager#checkWrite(String) checkWrite} is invoked + * to check write access to the target file. If a symbolic link is + * copied the security manager is invoked to check {@link + * LinkPermission}{@code ("symbolic")}. + */ + public abstract void copy(Path source, Path target, CopyOption... options) + throws IOException; + + /** + * Move or rename a file to a target file. This method works in exactly the + * manner specified by the {@link Files#move} method except that both the + * source and target paths must be associated with this provider. + * + * @param source + * the path to the file to move + * @param target + * the path to the target file + * @param options + * options specifying how the move should be done + * + * @throws UnsupportedOperationException + * if the array contains a copy option that is not supported + * @throws FileAlreadyExistsException + * if the target file exists but cannot be replaced because the + * {@code REPLACE_EXISTING} option is not specified (optional + * specific exception) + * @throws DirectoryNotEmptyException + * the {@code REPLACE_EXISTING} option is specified but the file + * cannot be replaced because it is a non-empty directory + * (optional specific exception) + * @throws AtomicMoveNotSupportedException + * if the options array contains the {@code ATOMIC_MOVE} option but + * the file cannot be moved as an atomic file system operation. + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkWrite(String) checkWrite} + * method is invoked to check write access to both the source and + * target file. + */ + public abstract void move(Path source, Path target, CopyOption... options) + throws IOException; + + /** + * Tests if two paths locate the same file. This method works in exactly the + * manner specified by the {@link Files#isSameFile} method. + * + * @param path + * one path to the file + * @param path2 + * the other path + * + * @return {@code true} if, and only if, the two paths locate the same file + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to both files. + */ + public abstract boolean isSameFile(Path path, Path path2) + throws IOException; + + /** + * Tells whether or not a file is considered hidden. This method + * works in exactly the manner specified by the {@link Files#isHidden} + * method. + * + *

    This method is invoked by the {@link Files#isHidden isHidden} method. + * + * @param path + * the path to the file to test + * + * @return {@code true} if the file is considered hidden + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file. + */ + public abstract boolean isHidden(Path path) throws IOException; + + /** + * Returns the {@link FileStore} representing the file store where a file + * is located. This method works in exactly the manner specified by the + * {@link Files#getFileStore} method. + * + * @param path + * the path to the file + * + * @return the file store where the file is stored + * + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file, and in + * addition it checks {@link RuntimePermission} + * ("getFileStoreAttributes") + */ + public abstract FileStore getFileStore(Path path) throws IOException; + + /** + * Checks the existence, and optionally the accessibility, of a file. + * + *

    This method may be used by the {@link Files#isReadable isReadable}, + * {@link Files#isWritable isWritable} and {@link Files#isExecutable + * isExecutable} methods to check the accessibility of a file. + * + *

    This method checks the existence of a file and that this Java virtual + * machine has appropriate privileges that would allow it access the file + * according to all of access modes specified in the {@code modes} parameter + * as follows: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Value Description
    {@link AccessMode#READ READ} Checks that the file exists and that the Java virtual machine has + * permission to read the file.
    {@link AccessMode#WRITE WRITE} Checks that the file exists and that the Java virtual machine has + * permission to write to the file,
    {@link AccessMode#EXECUTE EXECUTE} Checks that the file exists and that the Java virtual machine has + * permission to {@link Runtime#exec execute} the file. The semantics + * may differ when checking access to a directory. For example, on UNIX + * systems, checking for {@code EXECUTE} access checks that the Java + * virtual machine has permission to search the directory in order to + * access file or subdirectories.
    + * + *

    If the {@code modes} parameter is of length zero, then the existence + * of the file is checked. + * + *

    This method follows symbolic links if the file referenced by this + * object is a symbolic link. Depending on the implementation, this method + * may require to read file permissions, access control lists, or other + * file attributes in order to check the effective access to the file. To + * determine the effective access to a file may require access to several + * attributes and so in some implementations this method may not be atomic + * with respect to other file system operations. + * + * @param path + * the path to the file to check + * @param modes + * The access modes to check; may have zero elements + * + * @throws UnsupportedOperationException + * an implementation is required to support checking for + * {@code READ}, {@code WRITE}, and {@code EXECUTE} access. This + * exception is specified to allow for the {@code Access} enum to + * be extended in future releases. + * @throws NoSuchFileException + * if a file does not exist (optional specific exception) + * @throws AccessDeniedException + * the requested access would be denied or the access cannot be + * determined because the Java virtual machine has insufficient + * privileges or other reasons. (optional specific exception) + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, the {@link SecurityManager#checkRead(String) checkRead} + * is invoked when checking read access to the file or only the + * existence of the file, the {@link SecurityManager#checkWrite(String) + * checkWrite} is invoked when checking write access to the file, + * and {@link SecurityManager#checkExec(String) checkExec} is invoked + * when checking execute access. + */ + public abstract void checkAccess(Path path, AccessMode... modes) + throws IOException; + + /** + * Returns a file attribute view of a given type. This method works in + * exactly the manner specified by the {@link Files#getFileAttributeView} + * method. + * + * @param path + * the path to the file + * @param type + * the {@code Class} object corresponding to the file attribute view + * @param options + * options indicating how symbolic links are handled + * + * @return a file attribute view of the specified type, or {@code null} if + * the attribute view type is not available + */ + public abstract V + getFileAttributeView(Path path, Class type, LinkOption... options); + + /** + * Reads a file's attributes as a bulk operation. This method works in + * exactly the manner specified by the {@link + * Files#readAttributes(Path,Class,LinkOption[])} method. + * + * @param path + * the path to the file + * @param type + * the {@code Class} of the file attributes required + * to read + * @param options + * options indicating how symbolic links are handled + * + * @return the file attributes + * + * @throws UnsupportedOperationException + * if an attributes of the given type are not supported + * @throws IOException + * if an I/O error occurs + * @throws SecurityException + * In the case of the default provider, a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method is invoked to check read access to the file + */ + public abstract A + readAttributes(Path path, Class type, LinkOption... options) throws IOException; + + /** + * Reads a set of file attributes as a bulk operation. This method works in + * exactly the manner specified by the {@link + * Files#readAttributes(Path,String,LinkOption[])} method. + * + * @param path + * the path to the file + * @param attributes + * the attributes to read + * @param options + * options indicating how symbolic links are handled + * + * @return a map of the attributes returned; may be empty. The map's keys + * are the attribute names, its values are the attribute values + * + * @throws IOException + * If an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkRead(String) checkRead} + * method denies read access to the file. If this method is invoked + * to read security sensitive attributes then the security manager + * may be invoke to check for additional permissions. + */ + public abstract Map readAttributes(Path path, String attributes, + LinkOption... options) + throws IOException; + + /** + * Sets the value of a file attribute. This method works in exactly the + * manner specified by the {@link Files#setAttribute} method. + * + * @param path + * the path to the file + * @param attribute + * the attribute to set + * @param value + * the attribute value + * @param options + * options indicating how symbolic links are handled + * + * @throws UnsupportedOperationException + * if the attribute view is not available or it does not support + * updating the attribute + * @throws IllegalArgumentException + * if the attribute value is of the correct type but has an + * inappropriate value + * @throws ClassCastException + * If the attribute value is not of the expected type or is a + * collection containing elements that are not of the expected + * type + * @throws IOException + * If an I/O error occurs + * @throws SecurityException + * In the case of the default provider, and a security manager is + * installed, its {@link SecurityManager#checkWrite(String) checkWrite} + * method denies write access to the file. If this method is invoked + * to set security sensitive attributes then the security manager + * may be invoked to check for additional permissions. + */ + public abstract void setAttribute(Path path, String attribute, + Object value, LinkOption... options) + throws IOException; } diff --git a/jdk/src/share/classes/java/nio/file/spi/FileTypeDetector.java b/jdk/src/share/classes/java/nio/file/spi/FileTypeDetector.java index 21c130188fb..fd062804d6a 100644 --- a/jdk/src/share/classes/java/nio/file/spi/FileTypeDetector.java +++ b/jdk/src/share/classes/java/nio/file/spi/FileTypeDetector.java @@ -25,7 +25,7 @@ package java.nio.file.spi; -import java.nio.file.FileRef; +import java.nio.file.Path; import java.io.IOException; /** @@ -42,7 +42,7 @@ import java.io.IOException; * href="../attribute/package-summary.html"> attribute or the bytes in a * file may be examined to guess its file type. * - * @see java.nio.file.Files#probeContentType(FileRef) + * @see java.nio.file.Files#probeContentType(Path) * * @since 1.7 */ @@ -83,8 +83,8 @@ public abstract class FileTypeDetector { * Message Bodies. The string must be parsable according to the * grammar in the RFC 2045. * - * @param file - * The file to probe + * @param path + * the path to the file to probe * * @return The content type or {@code null} if the file type is not * recognized @@ -101,6 +101,6 @@ public abstract class FileTypeDetector { * * @see java.nio.file.Files#probeContentType */ - public abstract String probeContentType(FileRef file) + public abstract String probeContentType(Path path) throws IOException; } diff --git a/jdk/src/share/classes/java/security/AlgorithmParameterGenerator.java b/jdk/src/share/classes/java/security/AlgorithmParameterGenerator.java index 95268601653..f5ece273052 100644 --- a/jdk/src/share/classes/java/security/AlgorithmParameterGenerator.java +++ b/jdk/src/share/classes/java/security/AlgorithmParameterGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,6 +66,20 @@ import java.security.spec.AlgorithmParameterSpec; * default modulus prime size of 1024 bits for the generation of DSA * parameters. * + *

    Every implementation of the Java platform is required to support the + * following standard AlgorithmParameterGenerator algorithms and + * keysizes in parentheses: + *

      + *
    • DiffieHellman (1024)
    • + *
    • DSA (1024)
    • + *
    + * These algorithms are described in the + * AlgorithmParameterGenerator section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other algorithms are supported. + * * @author Jan Luehe * * @@ -126,9 +140,9 @@ public class AlgorithmParameterGenerator { * * @param algorithm the name of the algorithm this * parameter generator is associated with. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the AlgorithmParameterGenerator section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the new AlgorithmParameterGenerator object. @@ -168,9 +182,9 @@ public class AlgorithmParameterGenerator { * * @param algorithm the name of the algorithm this * parameter generator is associated with. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the AlgorithmParameterGenerator section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the string name of the Provider. @@ -214,9 +228,9 @@ public class AlgorithmParameterGenerator { * * @param algorithm the string name of the algorithm this * parameter generator is associated with. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the AlgorithmParameterGenerator section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the Provider object. diff --git a/jdk/src/share/classes/java/security/AlgorithmParameters.java b/jdk/src/share/classes/java/security/AlgorithmParameters.java index 7dee113a215..a17e8487b72 100644 --- a/jdk/src/share/classes/java/security/AlgorithmParameters.java +++ b/jdk/src/share/classes/java/security/AlgorithmParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,22 @@ import java.security.spec.InvalidParameterSpecException; * getParameterSpec, and a byte encoding of the parameters is * obtained via a call to getEncoded. * + *

    Every implementation of the Java platform is required to support the + * following standard AlgorithmParameters algorithms: + *

      + *
    • AES
    • + *
    • DES
    • + *
    • DESede
    • + *
    • DiffieHellman
    • + *
    • DSA
    • + *
    + * These algorithms are described in the + * AlgorithmParameters section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other algorithms are supported. + * * @author Jan Luehe * * @@ -111,9 +127,9 @@ public class AlgorithmParameters { * parameter encoding. * * @param algorithm the name of the algorithm requested. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the AlgorithmParameters section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the new parameter object. @@ -153,9 +169,9 @@ public class AlgorithmParameters { * parameter encoding. * * @param algorithm the name of the algorithm requested. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the AlgorithmParameters section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the name of the provider. @@ -200,9 +216,9 @@ public class AlgorithmParameters { * parameter encoding. * * @param algorithm the name of the algorithm requested. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the AlgorithmParameters section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the name of the provider. diff --git a/jdk/src/share/classes/java/security/KeyFactory.java b/jdk/src/share/classes/java/security/KeyFactory.java index f47f88b07ee..edc9724daf2 100644 --- a/jdk/src/share/classes/java/security/KeyFactory.java +++ b/jdk/src/share/classes/java/security/KeyFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,8 +67,21 @@ import sun.security.jca.GetInstance.Instance; * sig.verify(signature); *
    * - * @author Jan Luehe + *

    Every implementation of the Java platform is required to support the + * following standard KeyFactory algorithms: + *

      + *
    • DiffieHellman
    • + *
    • DSA
    • + *
    • RSA
    • + *
    + * These algorithms are described in the + * KeyFactory section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other algorithms are supported. * + * @author Jan Luehe * * @see Key * @see PublicKey @@ -141,9 +154,9 @@ public class KeyFactory { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the requested key algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the KeyFactory section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the new KeyFactory object. @@ -172,9 +185,9 @@ public class KeyFactory { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the requested key algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the KeyFactory section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the name of the provider. @@ -211,9 +224,9 @@ public class KeyFactory { * does not have to be registered in the provider list. * * @param algorithm the name of the requested key algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the KeyFactory section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the provider. diff --git a/jdk/src/share/classes/java/security/KeyPairGenerator.java b/jdk/src/share/classes/java/security/KeyPairGenerator.java index 37f922af6ed..66e7e2ce7f9 100644 --- a/jdk/src/share/classes/java/security/KeyPairGenerator.java +++ b/jdk/src/share/classes/java/security/KeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,8 +105,22 @@ import sun.security.jca.GetInstance.Instance; * the superclass are intended for cryptographic service providers who wish to * supply their own implementations of key pair generators. * - * @author Benjamin Renaud + *

    Every implementation of the Java platform is required to support the + * following standard KeyPairGenerator algorithms and keysizes in + * parentheses: + *

      + *
    • DiffieHellman (1024)
    • + *
    • DSA (1024)
    • + *
    • RSA (1024, 2048)
    • + *
    + * These algorithms are described in the + * KeyPairGenerator section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other algorithms are supported. * + * @author Benjamin Renaud * * @see java.security.spec.AlgorithmParameterSpec */ @@ -122,9 +136,9 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { * Creates a KeyPairGenerator object for the specified algorithm. * * @param algorithm the standard string name of the algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the KeyPairGenerator section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. */ protected KeyPairGenerator(String algorithm) { @@ -133,9 +147,9 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { /** * Returns the standard name of the algorithm for this key pair generator. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the KeyPairGenerator section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the standard string name of the algorithm. @@ -171,9 +185,9 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard string name of the algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the KeyPairGenerator section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the new KeyPairGenerator object. @@ -227,9 +241,9 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard string name of the algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the KeyPairGenerator section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the string name of the provider. @@ -266,9 +280,9 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi { * does not have to be registered in the provider list. * * @param algorithm the standard string name of the algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the KeyPairGenerator section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the provider. diff --git a/jdk/src/share/classes/java/security/KeyStore.java b/jdk/src/share/classes/java/security/KeyStore.java index c1e2e4649e7..743f3593f31 100644 --- a/jdk/src/share/classes/java/security/KeyStore.java +++ b/jdk/src/share/classes/java/security/KeyStore.java @@ -164,8 +164,19 @@ import javax.security.auth.callback.*; * different passwords or other protection parameters * may also be used. * - * @author Jan Luehe + *

    Every implementation of the Java platform is required to support + * the following standard KeyStore type: + *

      + *
    • PKCS12
    • + *
    + * This type is described in the + * KeyStore section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other types are supported. * + * @author Jan Luehe * * @see java.security.PrivateKey * @see javax.crypto.SecretKey @@ -582,9 +593,9 @@ public class KeyStore { * the {@link Security#getProviders() Security.getProviders()} method. * * @param type the type of keystore. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the KeyStore section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard keystore types. * * @return a keystore object of the specified type. @@ -620,9 +631,9 @@ public class KeyStore { * the {@link Security#getProviders() Security.getProviders()} method. * * @param type the type of keystore. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the KeyStore section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard keystore types. * * @param provider the name of the provider. @@ -663,9 +674,9 @@ public class KeyStore { * does not have to be registered in the provider list. * * @param type the type of keystore. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the KeyStore section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard keystore types. * * @param provider the provider. diff --git a/jdk/src/share/classes/java/security/MessageDigest.java b/jdk/src/share/classes/java/security/MessageDigest.java index 5173ed97836..ce920fffbc0 100644 --- a/jdk/src/share/classes/java/security/MessageDigest.java +++ b/jdk/src/share/classes/java/security/MessageDigest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ import java.nio.ByteBuffer; /** * This MessageDigest class provides applications the functionality of a - * message digest algorithm, such as MD5 or SHA. + * message digest algorithm, such as SHA-1 or SHA-256. * Message digests are secure one-way hash functions that take arbitrary-sized * data and output a fixed-length hash value. * @@ -81,8 +81,21 @@ import java.nio.ByteBuffer; * the superclass are intended for cryptographic service providers who wish to * supply their own implementations of message digest algorithms. * - * @author Benjamin Renaud + *

    Every implementation of the Java platform is required to support + * the following standard MessageDigest algorithms: + *

      + *
    • MD5
    • + *
    • SHA-1
    • + *
    • SHA-256
    • + *
    + * These algorithms are described in the + * MessageDigest section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other algorithms are supported. * + * @author Benjamin Renaud * * @see DigestInputStream * @see DigestOutputStream @@ -104,9 +117,9 @@ public abstract class MessageDigest extends MessageDigestSpi { * Creates a message digest with the specified algorithm name. * * @param algorithm the standard name of the digest algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the MessageDigest section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. */ protected MessageDigest(String algorithm) { @@ -127,9 +140,9 @@ public abstract class MessageDigest extends MessageDigestSpi { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm requested. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the MessageDigest section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return a Message Digest object that implements the specified algorithm. @@ -173,9 +186,9 @@ public abstract class MessageDigest extends MessageDigestSpi { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm requested. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the MessageDigest section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the name of the provider. @@ -222,9 +235,9 @@ public abstract class MessageDigest extends MessageDigestSpi { * does not have to be registered in the provider list. * * @param algorithm the name of the algorithm requested. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the MessageDigest section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the provider. @@ -439,9 +452,9 @@ public abstract class MessageDigest extends MessageDigestSpi { * Returns a string that identifies the algorithm, independent of * implementation details. The name should be a standard * Java Security name (such as "SHA", "MD5", and so on). - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the MessageDigest section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the name of the algorithm diff --git a/jdk/src/share/classes/java/security/Policy.java b/jdk/src/share/classes/java/security/Policy.java index 8ae6d6c0eaf..b92d0625261 100644 --- a/jdk/src/share/classes/java/security/Policy.java +++ b/jdk/src/share/classes/java/security/Policy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,9 +67,6 @@ import sun.security.util.SecurityConstants; * implementation. In addition, an instance of a Policy object can be * constructed by invoking one of the getInstance factory methods * with a standard type. The default policy type is "JavaPolicy". - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference - * for a list of standard Policy types. * *

    Once a Policy instance has been installed (either by default, or by * calling setPolicy), @@ -133,7 +130,7 @@ public abstract class Policy { * This method first calls * SecurityManager.checkPermission with a * SecurityPermission("getPolicy") permission - * to ensure it's ok to get the Policy object.. + * to ensure it's ok to get the Policy object. * * @return the installed Policy. * @@ -340,9 +337,10 @@ public abstract class Policy { *

    Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * - * @param type the specified Policy type. See Appendix A in the - * - * Java Cryptography Architecture API Specification & Reference + * @param type the specified Policy type. See the Policy section in the + * + * Java Cryptography Architecture Standard Algorithm Name Documentation * for a list of standard Policy types. * * @param params parameters for the Policy, which may be null. @@ -393,9 +391,10 @@ public abstract class Policy { *

    Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * - * @param type the specified Policy type. See Appendix A in the - * - * Java Cryptography Architecture API Specification & Reference + * @param type the specified Policy type. See the Policy section in the + * + * Java Cryptography Architecture Standard Algorithm Name Documentation * for a list of standard Policy types. * * @param params parameters for the Policy, which may be null. @@ -456,9 +455,10 @@ public abstract class Policy { * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * - * @param type the specified Policy type. See Appendix A in the - * - * Java Cryptography Architecture API Specification & Reference + * @param type the specified Policy type. See the Policy section in the + * + * Java Cryptography Architecture Standard Algorithm Name Documentation * for a list of standard Policy types. * * @param params parameters for the Policy, which may be null. diff --git a/jdk/src/share/classes/java/security/SecureRandom.java b/jdk/src/share/classes/java/security/SecureRandom.java index 4243a778940..e51b6098558 100644 --- a/jdk/src/share/classes/java/security/SecureRandom.java +++ b/jdk/src/share/classes/java/security/SecureRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -133,9 +133,9 @@ public class SecureRandom extends java.util.Random { *

    Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * - *

    See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + *

    See the SecureRandom section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard RNG algorithm names. * *

    The returned SecureRandom object has not been seeded. To seed the @@ -171,9 +171,9 @@ public class SecureRandom extends java.util.Random { *

    Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * - *

    See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + *

    See the SecureRandom section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard RNG algorithm names. * * @param seed the seed. @@ -256,9 +256,9 @@ public class SecureRandom extends java.util.Random { * previously called. * * @param algorithm the name of the RNG algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the SecureRandom section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard RNG algorithm names. * * @return the new SecureRandom object. @@ -299,9 +299,9 @@ public class SecureRandom extends java.util.Random { * previously called. * * @param algorithm the name of the RNG algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the SecureRandom section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard RNG algorithm names. * * @param provider the name of the provider. @@ -347,9 +347,9 @@ public class SecureRandom extends java.util.Random { * previously called. * * @param algorithm the name of the RNG algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the SecureRandom section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard RNG algorithm names. * * @param provider the provider. diff --git a/jdk/src/share/classes/java/security/Security.java b/jdk/src/share/classes/java/security/Security.java index 55816d9aefd..156e60b5ea0 100644 --- a/jdk/src/share/classes/java/security/Security.java +++ b/jdk/src/share/classes/java/security/Security.java @@ -277,10 +277,11 @@ public final class Security { /** * Gets a specified property for an algorithm. The algorithm name - * should be a standard name. See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * should be a standard name. See the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. + * * One possible use is by specialized algorithm parsers, which may map * classes to algorithms which they understand (much like Key parsers * do). @@ -513,9 +514,9 @@ public final class Security { * *

* - *

See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + *

See the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard cryptographic service names, standard * algorithm names and standard attribute names. * @@ -581,9 +582,9 @@ public final class Security { * constraint expressed by the specified attribute name/value pair. * * - *

See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + *

See the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard cryptographic service names, standard * algorithm names and standard attribute names. * diff --git a/jdk/src/share/classes/java/security/Signature.java b/jdk/src/share/classes/java/security/Signature.java index d303193a6f5..8e321f8946e 100644 --- a/jdk/src/share/classes/java/security/Signature.java +++ b/jdk/src/share/classes/java/security/Signature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; /** - * This Signature class is used to provide applications the functionality + * The Signature class is used to provide applications the functionality * of a digital signature algorithm. Digital signatures are used for * authentication and integrity assurance of digital data. * @@ -98,6 +98,20 @@ import sun.security.jca.GetInstance.Instance; * the superclass are intended for cryptographic service providers who wish to * supply their own implementations of digital signature algorithms. * + *

Every implementation of the Java platform is required to support the + * following standard Signature algorithms: + *

    + *
  • SHA1withDSA
  • + *
  • SHA1withRSA
  • + *
  • SHA256withRSA
  • + *
+ * These algorithms are described in the + * Signature section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other algorithms are supported. + * * @author Benjamin Renaud * */ @@ -144,9 +158,9 @@ public abstract class Signature extends SignatureSpi { * Creates a Signature object for the specified algorithm. * * @param algorithm the standard string name of the algorithm. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the Signature section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. */ protected Signature(String algorithm) { @@ -184,9 +198,9 @@ public abstract class Signature extends SignatureSpi { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the algorithm requested. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the Signature section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @return the new Signature object. @@ -303,9 +317,9 @@ public abstract class Signature extends SignatureSpi { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the algorithm requested. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the Signature section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the name of the provider. @@ -353,9 +367,9 @@ public abstract class Signature extends SignatureSpi { * does not have to be registered in the provider list. * * @param algorithm the name of the algorithm requested. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the Signature section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard algorithm names. * * @param provider the provider. diff --git a/jdk/src/share/classes/java/security/cert/CertPath.java b/jdk/src/share/classes/java/security/cert/CertPath.java index 67e294dfd64..786360aa20f 100644 --- a/jdk/src/share/classes/java/security/cert/CertPath.java +++ b/jdk/src/share/classes/java/security/cert/CertPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,6 +83,19 @@ import java.util.List; * may not follow these conventions. PKIX CertPathValidators will * detect any departure from these conventions that cause the certification * path to be invalid and throw a CertPathValidatorException. + * + *

Every implementation of the Java platform is required to support the + * following standard CertPath encodings: + *

    + *
  • PKCS7
  • + *
  • PkiPath
  • + *
+ * These encodings are described in the + * CertPath Encodings section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other encodings are supported. *

* Concurrent Access *

diff --git a/jdk/src/share/classes/java/security/cert/CertPathBuilder.java b/jdk/src/share/classes/java/security/cert/CertPathBuilder.java index 76210ff0984..99035c36af9 100644 --- a/jdk/src/share/classes/java/security/cert/CertPathBuilder.java +++ b/jdk/src/share/classes/java/security/cert/CertPathBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,19 @@ import sun.security.jca.GetInstance.Instance; * result (including the CertPath that was built) is returned * in an object that implements the CertPathBuilderResult * interface. + * + *

Every implementation of the Java platform is required to support the + * following standard CertPathBuilder algorithm: + *

    + *
  • PKIX
  • + *
+ * This algorithm is described in the + * CertPathBuilder section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other algorithms are supported. + * *

* Concurrent Access *

@@ -118,10 +131,10 @@ public class CertPathBuilder { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the requested CertPathBuilder - * algorithm. See Appendix A in the - * Java Certification Path API Programmer's Guide - * for information about standard algorithm names. + * algorithm. See the CertPathBuilder section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation + * for information about standard algorithm names. * * @return a CertPathBuilder object that implements the * specified algorithm. @@ -153,10 +166,10 @@ public class CertPathBuilder { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the requested CertPathBuilder - * algorithm. See Appendix A in the - * Java Certification Path API Programmer's Guide - * for information about standard algorithm names. + * algorithm. See the CertPathBuilder section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation + * for information about standard algorithm names. * * @param provider the name of the provider. * @@ -193,10 +206,10 @@ public class CertPathBuilder { * does not have to be registered in the provider list. * * @param algorithm the name of the requested CertPathBuilder - * algorithm. See Appendix A in the - * Java Certification Path API Programmer's Guide - * for information about standard algorithm names. + * algorithm. See the CertPathBuilder section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation + * for information about standard algorithm names. * * @param provider the provider. * diff --git a/jdk/src/share/classes/java/security/cert/CertPathValidator.java b/jdk/src/share/classes/java/security/cert/CertPathValidator.java index e7b95602923..22cbb59b85d 100644 --- a/jdk/src/share/classes/java/security/cert/CertPathValidator.java +++ b/jdk/src/share/classes/java/security/cert/CertPathValidator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,6 +53,19 @@ import sun.security.jca.GetInstance.Instance; * and an algorithm-specific set of parameters. If successful, the result is * returned in an object that implements the * CertPathValidatorResult interface. + * + *

Every implementation of the Java platform is required to support the + * following standard CertPathValidator algorithm: + *

    + *
  • PKIX
  • + *
+ * This algorithm is described in the + * CertPathValidator section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other algorithms are supported. + * *

* Concurrent Access *

@@ -118,10 +131,10 @@ public class CertPathValidator { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the requested CertPathValidator - * algorithm. See Appendix A in the - * Java Certification Path API Programmer's Guide - * for information about standard algorithm names. + * algorithm. See the CertPathValidator section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation + * for information about standard algorithm names. * * @return a CertPathValidator object that implements the * specified algorithm. @@ -153,10 +166,10 @@ public class CertPathValidator { * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the name of the requested CertPathValidator - * algorithm. See Appendix A in the - * Java Certification Path API Programmer's Guide - * for information about standard algorithm names. + * algorithm. See the CertPathValidator section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation + * for information about standard algorithm names. * * @param provider the name of the provider. * @@ -193,12 +206,11 @@ public class CertPathValidator { * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * - * @param algorithm the name of the requested - * CertPathValidator algorithm. - * See Appendix A in the - * Java Certification Path API Programmer's Guide - * for information about standard algorithm names. + * @param algorithm the name of the requested CertPathValidator + * algorithm. See the CertPathValidator section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation + * for information about standard algorithm names. * * @param provider the provider. * diff --git a/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java b/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java index b58b202cb5f..9eedb620d9a 100644 --- a/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java +++ b/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -286,6 +286,11 @@ public class CertPathValidatorException extends GeneralSecurityException { /** * The signature is invalid. */ - INVALID_SIGNATURE + INVALID_SIGNATURE, + + /** + * The public key or the signature algorithm has been constrained. + */ + ALGORITHM_CONSTRAINED } } diff --git a/jdk/src/share/classes/java/security/cert/CertStore.java b/jdk/src/share/classes/java/security/cert/CertStore.java index 0d8de632ba9..325b715ed77 100644 --- a/jdk/src/share/classes/java/security/cert/CertStore.java +++ b/jdk/src/share/classes/java/security/cert/CertStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,10 +58,20 @@ import sun.security.jca.GetInstance.Instance; * vast repository of untrusted certificates and CRLs. For example, an LDAP * implementation of CertStore provides access to certificates * and CRLs stored in one or more directories using the LDAP protocol and the - * schema as defined in the RFC service attribute. See Appendix A in the - * - * Java Certification Path API Programmer's Guide for more information about - * standard CertStore types. + * schema as defined in the RFC service attribute. + * + *

Every implementation of the Java platform is required to support the + * following standard CertStore type: + *

    + *
  • Collection
  • + *
+ * This type is described in the + * CertStore section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other types are supported. + * *

* Concurrent Access *

@@ -192,10 +202,10 @@ public class CertStore { * cloned. * * @param type the name of the requested CertStore type. - * See Appendix A in the - * Java Certification Path API Programmer's Guide - * for information about standard types. + * See the CertStore section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation + * for information about standard types. * * @param params the initialization parameters (may be null). * @@ -252,10 +262,10 @@ public class CertStore { * cloned. * * @param type the requested CertStore type. - * See Appendix A in the - * Java Certification Path API Programmer's Guide - * for information about standard types. + * See the CertStore section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation + * for information about standard types. * * @param params the initialization parameters (may be null). * @@ -310,10 +320,10 @@ public class CertStore { * cloned. * * @param type the requested CertStore type. - * See Appendix A in the - * Java Certification Path API Programmer's Guide - * for information about standard types. + * See the CertStore section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation + * for information about standard types. * * @param params the initialization parameters (may be null). * diff --git a/jdk/src/share/classes/java/security/cert/Certificate.java b/jdk/src/share/classes/java/security/cert/Certificate.java index be350f326bd..efe37ac7e34 100644 --- a/jdk/src/share/classes/java/security/cert/Certificate.java +++ b/jdk/src/share/classes/java/security/cert/Certificate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,9 +69,9 @@ public abstract class Certificate implements java.io.Serializable { * Creates a certificate of the specified type. * * @param type the standard name of the certificate type. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the CertificateFactory section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard certificate types. */ protected Certificate(String type) { diff --git a/jdk/src/share/classes/java/security/cert/CertificateFactory.java b/jdk/src/share/classes/java/security/cert/CertificateFactory.java index 6b2528b0a44..4cd81f43d81 100644 --- a/jdk/src/share/classes/java/security/cert/CertificateFactory.java +++ b/jdk/src/share/classes/java/security/cert/CertificateFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,11 +91,29 @@ import sun.security.jca.GetInstance.Instance; * } * * + *

Every implementation of the Java platform is required to support the + * following standard CertificateFactory type: + *

    + *
  • X.509
  • + *
+ * and the following standard CertPath encodings: + *
    + *
  • PKCS7
  • + *
  • PkiPath
  • + *
+ * The type and encodings are described in the + * CertificateFactory section and the + * CertPath Encodings section of the + * Java Cryptography Architecture Standard Algorithm Name Documentation. + * Consult the release documentation for your implementation to see if any + * other types or encodings are supported. + * * @author Hemma Prafullchandra * @author Jan Luehe * @author Sean Mullan * - * * @see Certificate * @see X509Certificate * @see CertPath @@ -146,9 +164,9 @@ public class CertificateFactory { * the {@link Security#getProviders() Security.getProviders()} method. * * @param type the name of the requested certificate type. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the CertificateFactory section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard certificate types. * * @return a certificate factory object for the specified type. @@ -184,9 +202,9 @@ public class CertificateFactory { * the {@link Security#getProviders() Security.getProviders()} method. * * @param type the certificate type. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the CertificateFactory section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard certificate types. * * @param provider the name of the provider. @@ -228,11 +246,10 @@ public class CertificateFactory { * does not have to be registered in the provider list. * * @param type the certificate type. - * See Appendix A in the - * Java Cryptography Architecture API Specification & Reference + * See the CertificateFactory section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard certificate types. - * @param provider the provider. * * @return a certificate factory object for the specified type. @@ -325,10 +342,10 @@ public class CertificateFactory { /** * Returns an iteration of the CertPath encodings supported * by this certificate factory, with the default encoding first. See - * Appendix A in the - * - * Java Certification Path API Programmer's Guide for information about - * standard encoding names and their formats. + * the CertPath Encodings section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation + * for information about standard encoding names and their formats. *

* Attempts to modify the returned Iterator via its * remove method result in an @@ -364,9 +381,10 @@ public class CertificateFactory { /** * Generates a CertPath object and initializes it with * the data read from the InputStream inStream. The data - * is assumed to be in the specified encoding. See Appendix A in the - * - * Java Certification Path API Programmer's Guide + * is assumed to be in the specified encoding. See + * the CertPath Encodings section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard encoding names and their formats. * * @param inStream an InputStream containing the data diff --git a/jdk/src/share/classes/java/security/cert/CertificateFactorySpi.java b/jdk/src/share/classes/java/security/cert/CertificateFactorySpi.java index a9dbae734fa..b7a3c55f8ab 100644 --- a/jdk/src/share/classes/java/security/cert/CertificateFactorySpi.java +++ b/jdk/src/share/classes/java/security/cert/CertificateFactorySpi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -182,9 +182,9 @@ public abstract class CertificateFactorySpi { /** * Returns an iteration of the CertPath encodings supported * by this certificate factory, with the default encoding first. See - * Appendix A in the - * - * Java Certification Path API Programmer's Guide + * the CertPath Encodings section in the + * Java Cryptography Architecture Standard Algorithm Name Documentation * for information about standard encoding names. *

* Attempts to modify the returned Iterator via its diff --git a/jdk/src/share/classes/java/security/cert/package.html b/jdk/src/share/classes/java/security/cert/package.html index 55109aaf3d4..0851accc6c5 100644 --- a/jdk/src/share/classes/java/security/cert/package.html +++ b/jdk/src/share/classes/java/security/cert/package.html @@ -1,5 +1,5 @@ -@since JDK1.4 +@since 1.4 diff --git a/jdk/src/share/classes/javax/swing/JComponent.java b/jdk/src/share/classes/javax/swing/JComponent.java index 9ef57bacadd..7bed584dca6 100644 --- a/jdk/src/share/classes/javax/swing/JComponent.java +++ b/jdk/src/share/classes/javax/swing/JComponent.java @@ -4911,7 +4911,7 @@ public abstract class JComponent extends Container implements Serializable, * painting to originate from this Component, or one of its ancestors. *

* Calling {@link JComponent#repaint} on a Swing component will be delegated to - * the first ancestor which {@code isPaintingOrigin()} returns {@true}, + * the first ancestor which {@code isPaintingOrigin()} returns {@code true}, * if there are any. *

* {@code JComponent} subclasses that need to be repainted when any of their diff --git a/jdk/src/share/classes/javax/swing/SwingWorker.java b/jdk/src/share/classes/javax/swing/SwingWorker.java index 48f2d56bd2b..413f81f9376 100644 --- a/jdk/src/share/classes/javax/swing/SwingWorker.java +++ b/jdk/src/share/classes/javax/swing/SwingWorker.java @@ -404,6 +404,7 @@ public abstract class SwingWorker implements RunnableFuture { * @see #process * */ + @SafeVarargs protected final void publish(V... chunks) { synchronized (this) { if (doProcess == null) { diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextPaneUI.java b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextPaneUI.java index eb7b2959151..aaade50df3d 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextPaneUI.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTextPaneUI.java @@ -92,7 +92,7 @@ public class SynthTextPaneUI extends SynthEditorPaneUI { * * * @param c the editor component - * @see BasicTextUI#installUI + * @see javax.swing.plaf.basic.BasicTextUI#installUI * @see ComponentUI#installUI */ @Override diff --git a/jdk/src/share/classes/sun/launcher/LauncherHelper.java b/jdk/src/share/classes/sun/launcher/LauncherHelper.java index 870ed30e9f0..ff71e8908b1 100644 --- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java +++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java @@ -63,8 +63,6 @@ import java.util.jar.Manifest; public enum LauncherHelper { INSTANCE; - private static final String defaultBundleName = - "sun.launcher.resources.launcher"; private static final String MAIN_CLASS = "Main-Class"; private static StringBuilder outBuf = new StringBuilder(); @@ -76,11 +74,14 @@ public enum LauncherHelper { private static final String PROP_SETTINGS = "Property settings:"; private static final String LOCALE_SETTINGS = "Locale settings:"; - private static synchronized ResourceBundle getLauncherResourceBundle() { - if (javarb == null) { - javarb = ResourceBundle.getBundle(defaultBundleName); - } - return javarb; + // sync with java.c and sun.misc.VM + private static final String diagprop = "sun.java.launcher.diag"; + + private static final String defaultBundleName = + "sun.launcher.resources.launcher"; + private static class ResourceBundleHolder { + private static final ResourceBundle RB = + ResourceBundle.getBundle(defaultBundleName); } /* @@ -308,7 +309,7 @@ public enum LauncherHelper { * apply any arguments that we might pass. */ private static String getLocalizedMessage(String key, Object... args) { - String msg = getLauncherResourceBundle().getString(key); + String msg = ResourceBundleHolder.RB.getString(key); return (args != null) ? MessageFormat.format(msg, args) : msg; } @@ -380,25 +381,29 @@ public enum LauncherHelper { File.pathSeparator)); } - static String getMainClassFromJar(String jarname) throws IOException { - JarFile jarFile = null; + static String getMainClassFromJar(PrintStream ostream, String jarname) { try { - jarFile = new JarFile(jarname); - Manifest manifest = jarFile.getManifest(); - if (manifest == null) { - throw new IOException("manifest not found in " + jarname); - } - Attributes mainAttrs = manifest.getMainAttributes(); - if (mainAttrs == null) { - throw new IOException("no main mainifest attributes, in " + - jarname); - } - return mainAttrs.getValue(MAIN_CLASS).trim(); - } finally { - if (jarFile != null) { - jarFile.close(); + JarFile jarFile = null; + try { + jarFile = new JarFile(jarname); + Manifest manifest = jarFile.getManifest(); + if (manifest == null) { + abort(ostream, null, "java.launcher.jar.error2", jarname); + } + Attributes mainAttrs = manifest.getMainAttributes(); + if (mainAttrs == null) { + abort(ostream, null, "java.launcher.jar.error3", jarname); + } + return mainAttrs.getValue(MAIN_CLASS).trim(); + } finally { + if (jarFile != null) { + jarFile.close(); + } } + } catch (IOException ioe) { + abort(ostream, ioe, "java.launcher.jar.error1", jarname); } + return null; } @@ -409,6 +414,20 @@ public enum LauncherHelper { private static final int LM_CLASS = 1; private static final int LM_JAR = 2; + static void abort(PrintStream ostream, Throwable t, String msgKey, Object... args) { + if (msgKey != null) { + ostream.println(getLocalizedMessage(msgKey, args)); + } + if (sun.misc.VM.getSavedProperty(diagprop) != null) { + if (t != null) { + t.printStackTrace(); + } else { + Thread.currentThread().dumpStack(); + } + } + System.exit(1); + } + /** * This method does the following: * 1. gets the classname from a Jar's manifest, if necessary @@ -426,39 +445,31 @@ public enum LauncherHelper { * @param isJar * @param name * @return - * @throws java.io.IOException */ public static Class checkAndLoadMain(boolean printToStderr, int mode, - String what) throws IOException - { - - ClassLoader ld = ClassLoader.getSystemClassLoader(); - + String what) { + final PrintStream ostream = (printToStderr) ? System.err : System.out; + final ClassLoader ld = ClassLoader.getSystemClassLoader(); // get the class name String cn = null; switch (mode) { - case LM_CLASS: - cn = what; - break; - case LM_JAR: - cn = getMainClassFromJar(what); - break; - default: - throw new InternalError("" + mode + ": Unknown launch mode"); + case LM_CLASS: + cn = what; + break; + case LM_JAR: + cn = getMainClassFromJar(ostream, what); + break; + default: + // should never happen + throw new InternalError("" + mode + ": Unknown launch mode"); } cn = cn.replace('/', '.'); - - PrintStream ostream = (printToStderr) ? System.err : System.out; Class c = null; try { c = ld.loadClass(cn); } catch (ClassNotFoundException cnfe) { - ostream.println(getLocalizedMessage("java.launcher.cls.error1", - cn)); - NoClassDefFoundError ncdfe = new NoClassDefFoundError(cn); - ncdfe.initCause(cnfe); - throw ncdfe; + abort(ostream, cnfe, "java.launcher.cls.error1", cn); } signatureDiagnostic(ostream, c); return c; @@ -470,9 +481,7 @@ public enum LauncherHelper { try { method = clazz.getMethod("main", String[].class); } catch (NoSuchMethodException nsme) { - ostream.println(getLocalizedMessage("java.launcher.cls.error4", - classname)); - throw new RuntimeException("Main method not found in " + classname); + abort(ostream, null, "java.launcher.cls.error4", classname); } /* * getMethod (above) will choose the correct method, based @@ -481,17 +490,10 @@ public enum LauncherHelper { */ int mod = method.getModifiers(); if (!Modifier.isStatic(mod)) { - ostream.println(getLocalizedMessage("java.launcher.cls.error2", - "static", classname)); - throw new RuntimeException("Main method is not static in class " + - classname); + abort(ostream, null, "java.launcher.cls.error2", "static", classname); } if (method.getReturnType() != java.lang.Void.TYPE) { - ostream.println(getLocalizedMessage("java.launcher.cls.error3", - classname)); - throw new RuntimeException("Main method must return a value" + - " of type void in class " + - classname); + abort(ostream, null, "java.launcher.cls.error3", classname); } return; } diff --git a/jdk/src/share/classes/sun/launcher/resources/launcher.properties b/jdk/src/share/classes/sun/launcher/resources/launcher.properties index 17ba48a1384..f508e9f49fc 100644 --- a/jdk/src/share/classes/sun/launcher/resources/launcher.properties +++ b/jdk/src/share/classes/sun/launcher/resources/launcher.properties @@ -84,6 +84,7 @@ java.launcher.X.usage=\ \ append to end of bootstrap class path\n\ \ -Xbootclasspath/p:\n\ \ prepend in front of bootstrap class path\n\ +\ -Xdiag show additional diagnostic messages\n\ \ -Xnoclassgc disable class garbage collection\n\ \ -Xincgc enable incremental garbage collection\n\ \ -Xloggc: log GC status to a file with time stamps\n\ @@ -109,7 +110,7 @@ java.launcher.X.usage=\ The -X options are non-standard and subject to change without notice.\n java.launcher.cls.error1=\ - Error: Could not find main class {0} + Error: Could not find or load main class {0} java.launcher.cls.error2=\ Error: Main method is not {0} in class {1}, please define the main method as:\n\ \ public static void main(String[] args) @@ -120,5 +121,7 @@ java.launcher.cls.error3=\ java.launcher.cls.error4=\ Error: Main method not found in class {0}, please define the main method as:\n\ \ public static void main(String[] args) - - +java.launcher.jar.error1=\ + Error: An unexpected error occurred while trying to open file {0} +java.launcher.jar.error2=manifest not found in {0} +java.launcher.jar.error3=no main manifest attribute, in {0} diff --git a/jdk/src/share/classes/sun/misc/FloatingDecimal.java b/jdk/src/share/classes/sun/misc/FloatingDecimal.java index 3ef35ed3edc..fedca65e760 100644 --- a/jdk/src/share/classes/sun/misc/FloatingDecimal.java +++ b/jdk/src/share/classes/sun/misc/FloatingDecimal.java @@ -1547,7 +1547,7 @@ public class FloatingDecimal{ if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){ overvalue = true; // our candidate is too big. diff = bigB.sub( bigD ); - if ( (bigIntNBits == 1) && (bigIntExp > -expBias) ){ + if ( (bigIntNBits == 1) && (bigIntExp > -expBias+1) ){ // candidate is a normalized exact power of 2 and // is too big. We will be subtracting. // For our purposes, ulp is the ulp of the diff --git a/jdk/src/share/classes/sun/misc/JarIndex.java b/jdk/src/share/classes/sun/misc/JarIndex.java index 0418befce12..39e2eca91d8 100644 --- a/jdk/src/share/classes/sun/misc/JarIndex.java +++ b/jdk/src/share/classes/sun/misc/JarIndex.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,6 +66,14 @@ public class JarIndex { */ public static final String INDEX_NAME = "META-INF/INDEX.LIST"; + /** + * true if, and only if, sun.misc.JarIndex.metaInfFilenames is set to true. + * If true, the names of the files in META-INF, and its subdirectories, will + * be added to the index. Otherwise, just the directory names are added. + */ + private static final boolean metaInfFilenames = + "true".equals(System.getProperty("sun.misc.JarIndex.metaInfFilenames")); + /** * Constructs a new, empty jar index. */ @@ -186,6 +194,18 @@ public class JarIndex { addToList(jarName, packageName, jarMap); } + /** + * Same as add(String,String) except that it doesn't strip off from the + * last index of '/'. It just adds the filename. + */ + private void addExplicit(String fileName, String jarName) { + // add the mapping to indexMap + addToList(fileName, jarName, indexMap); + + // add the mapping to jarMap + addToList(jarName, fileName, jarMap); + } + /** * Go through all the jar files and construct the * index table. @@ -204,15 +224,31 @@ public class JarIndex { Enumeration entries = zrf.entries(); while(entries.hasMoreElements()) { - String fileName = ((ZipEntry)(entries.nextElement())).getName(); - // Index the META-INF directory, but not the index or manifest. - if (!fileName.startsWith("META-INF/") || - !(fileName.equals("META-INF/") || - fileName.equals(INDEX_NAME) || - fileName.equals(JarFile.MANIFEST_NAME))) { + ZipEntry entry = (ZipEntry) entries.nextElement(); + String fileName = entry.getName(); + + // Skip the META-INF directory, the index, and manifest. + // Any files in META-INF/ will be indexed explicitly + if (fileName.equals("META-INF/") || + fileName.equals(INDEX_NAME) || + fileName.equals(JarFile.MANIFEST_NAME)) + continue; + + if (!metaInfFilenames) { add(fileName, currentJar); + } else { + if (!fileName.startsWith("META-INF/")) { + add(fileName, currentJar); + } else if (!entry.isDirectory()) { + // Add files under META-INF explicitly so that certain + // services, like ServiceLoader, etc, can be located + // with greater accuracy. Directories can be skipped + // since each file will be added explicitly. + addExplicit(fileName, currentJar); + } } } + zrf.close(); } } diff --git a/jdk/src/share/classes/sun/misc/VM.java b/jdk/src/share/classes/sun/misc/VM.java index 0d8369a9d01..e3dc5efd64e 100644 --- a/jdk/src/share/classes/sun/misc/VM.java +++ b/jdk/src/share/classes/sun/misc/VM.java @@ -235,6 +235,9 @@ public class VM { return savedProps.getProperty(key); } + // TODO: the Property Management needs to be refactored and + // the appropriate prop keys need to be accessible to the + // calling classes to avoid duplication of keys. private static final Properties savedProps = new Properties(); // Save a private copy of the system properties and remove @@ -283,6 +286,9 @@ public class VM { // used by java.util.zip.ZipFile props.remove("sun.zip.disableMemoryMapping"); + + // used by sun.launcher.LauncherHelper + props.remove("sun.java.launcher.diag"); } // Initialize any miscellenous operating system settings that need to be diff --git a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java index e75e294c1e2..7c09e3965fa 100644 --- a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java +++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java @@ -106,6 +106,9 @@ public class KeepAliveCache keepAliveTimer = new Thread(grp, cache, "Keep-Alive-Timer"); keepAliveTimer.setDaemon(true); keepAliveTimer.setPriority(Thread.MAX_PRIORITY - 2); + // Set the context class loader to null in order to avoid + // keeping a strong reference to an application classloader. + keepAliveTimer.setContextClassLoader(null); keepAliveTimer.start(); return null; } diff --git a/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java b/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java index c430ae3518b..b3d3b607066 100644 --- a/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java +++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java @@ -185,6 +185,9 @@ class KeepAliveStream extends MeteredStream implements Hurryable { cleanerThread = new Thread(grp, queue, "Keep-Alive-SocketCleaner"); cleanerThread.setDaemon(true); cleanerThread.setPriority(Thread.MAX_PRIORITY - 2); + // Set the context class loader to null in order to avoid + // keeping a strong reference to an application classloader. + cleanerThread.setContextClassLoader(null); cleanerThread.start(); return null; } diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java index 65b965bb32b..cd1e6c26b8d 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java @@ -44,15 +44,6 @@ abstract class AbstractAclFileAttributeView return "acl"; } - @Override - public final Object getAttribute(String attribute) throws IOException { - if (attribute.equals(OWNER_NAME)) - return getOwner(); - if (attribute.equals(ACL_NAME)) - return getAcl(); - return null; - } - @Override @SuppressWarnings("unchecked") public final void setAttribute(String attribute, Object value) @@ -71,7 +62,7 @@ abstract class AbstractAclFileAttributeView } @Override - public final Map readAttributes(String[] attributes) + public final Map readAttributes(String[] attributes) throws IOException { boolean acl = false; @@ -91,7 +82,7 @@ abstract class AbstractAclFileAttributeView continue; } } - Map result = new HashMap(2); + Map result = new HashMap<>(2); if (acl) result.put(ACL_NAME, getAcl()); if (owner) diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java index de84499cb78..6383c08edf1 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java @@ -53,30 +53,6 @@ abstract class AbstractBasicFileAttributeView return "basic"; } - @Override - public Object getAttribute(String attribute) throws IOException { - BasicFileAttributes attrs = readAttributes(); - if (attribute.equals(SIZE_NAME)) - return attrs.size(); - if (attribute.equals(CREATION_TIME_NAME)) - return attrs.creationTime(); - if (attribute.equals(LAST_ACCESS_TIME_NAME)) - return attrs.lastAccessTime(); - if (attribute.equals(LAST_MODIFIED_TIME_NAME)) - return attrs.lastModifiedTime(); - if (attribute.equals(FILE_KEY_NAME)) - return attrs.fileKey(); - if (attribute.equals(IS_DIRECTORY_NAME)) - return attrs.isDirectory(); - if (attribute.equals(IS_REGULAR_FILE_NAME)) - return attrs.isRegularFile(); - if (attribute.equals(IS_SYMBOLIC_LINK_NAME)) - return attrs.isSymbolicLink(); - if (attribute.equals(IS_OTHER_NAME)) - return attrs.isOther(); - return null; - } - @Override public void setAttribute(String attribute, Object value) throws IOException @@ -101,8 +77,8 @@ abstract class AbstractBasicFileAttributeView * Used to build a map of attribute name/values. */ static class AttributesBuilder { - private Set set = new HashSet(); - private Map map = new HashMap(); + private Set set = new HashSet<>(); + private Map map = new HashMap<>(); private boolean copyAll; private AttributesBuilder(String[] attributes) { @@ -172,7 +148,7 @@ abstract class AbstractBasicFileAttributeView } @Override - public Map readAttributes(String[] attributes) throws IOException { + public Map readAttributes(String[] attributes) throws IOException { AttributesBuilder builder = AttributesBuilder.create(attributes); addBasicAttributesToBuilder(readAttributes(), builder); return builder.unmodifiableMap(); diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java b/jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java new file mode 100644 index 00000000000..95d1cb30931 --- /dev/null +++ b/jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.nio.fs; + +import java.nio.file.*; +import java.nio.file.spi.FileSystemProvider; +import java.io.IOException; +import java.util.Map; +import java.util.Collections; + +/** + * Base implementation class of FileSystemProvider + */ + +abstract class AbstractFileSystemProvider extends FileSystemProvider { + protected AbstractFileSystemProvider() { } + + /** + * Splits the given attribute name into the name of an attribute view and + * the attribute. If the attribute view is not identified then it assumed + * to be "basic". + */ + private static String[] split(String attribute) { + String[] s = new String[2]; + int pos = attribute.indexOf(':'); + if (pos == -1) { + s[0] = "basic"; + s[1] = attribute; + } else { + s[0] = attribute.substring(0, pos++); + s[1] = (pos == attribute.length()) ? "" : attribute.substring(pos); + } + return s; + } + + /** + * Gets a DynamicFileAttributeView by name. Returns {@code null} if the + * view is not available. + */ + abstract DynamicFileAttributeView getFileAttributeView(Path file, + String name, + LinkOption... options); + + @Override + public final void setAttribute(Path file, + String attribute, + Object value, + LinkOption... options) + throws IOException + { + String[] s = split(attribute); + DynamicFileAttributeView view = getFileAttributeView(file, s[0], options); + if (view == null) + throw new UnsupportedOperationException("View '" + s[0] + "' not available"); + view.setAttribute(s[1], value); + } + + @Override + public final Map readAttributes(Path file, String attributes, LinkOption... options) + throws IOException + { + String[] s = split(attributes); + DynamicFileAttributeView view = getFileAttributeView(file, s[0], options); + if (view == null) + return Collections.emptyMap(); + return view.readAttributes(s[1].split(",")); + } + + /** + * Deletes a file. The {@code failIfNotExists} parameters determines if an + * {@code IOException} is thrown when the file does not exist. + */ + abstract boolean implDelete(Path file, boolean failIfNotExists) throws IOException; + + @Override + public final void delete(Path file) throws IOException { + implDelete(file, true); + } + + @Override + public final boolean deleteIfExists(Path file) throws IOException { + return implDelete(file, false); + } +} diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java b/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java index 612e8e36f59..2ab2961561c 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java @@ -25,7 +25,7 @@ package sun.nio.fs; -import java.nio.file.FileRef; +import java.nio.file.Path; import java.nio.file.spi.FileTypeDetector; import java.util.Locale; import java.io.IOException; @@ -46,7 +46,7 @@ public abstract class AbstractFileTypeDetector * and checks that the content type's syntax is valid. */ @Override - public final String probeContentType(FileRef file) throws IOException { + public final String probeContentType(Path file) throws IOException { if (file == null) throw new NullPointerException("'file' is null"); String result = implProbeContentType(file); @@ -56,7 +56,7 @@ public abstract class AbstractFileTypeDetector /** * Probes the given file to guess its content type. */ - protected abstract String implProbeContentType(FileRef file) + protected abstract String implProbeContentType(Path file) throws IOException; /** diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractPath.java b/jdk/src/share/classes/sun/nio/fs/AbstractPath.java index 17262b68c04..eae2ac96483 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractPath.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractPath.java @@ -26,391 +26,81 @@ package sun.nio.fs; import java.nio.file.*; -import static java.nio.file.StandardOpenOption.*; -import java.nio.file.attribute.*; -import java.nio.channels.*; -import java.nio.ByteBuffer; -import java.io.*; -import java.util.*; +import java.io.File; +import java.io.IOException; +import java.util.Iterator; +import java.util.NoSuchElementException; /** - * Base implementation class for a {@code Path}. + * Base implementation class of {@code Path}. */ -abstract class AbstractPath extends Path { +abstract class AbstractPath implements Path { protected AbstractPath() { } @Override - public final Path createFile(FileAttribute... attrs) - throws IOException - { - EnumSet options = EnumSet.of(CREATE_NEW, WRITE); - SeekableByteChannel sbc = newByteChannel(options, attrs); - try { - sbc.close(); - } catch (IOException x) { - // ignore - } - return this; - } - - /** - * Deletes a file. The {@code failIfNotExists} parameters determines if an - * {@code IOException} is thrown when the file does not exist. - */ - abstract void implDelete(boolean failIfNotExists) throws IOException; - - @Override - public final void delete() throws IOException { - implDelete(true); + public final boolean startsWith(String other) { + return startsWith(getFileSystem().getPath(other)); } @Override - public final void deleteIfExists() throws IOException { - implDelete(false); + public final boolean endsWith(String other) { + return endsWith(getFileSystem().getPath(other)); } @Override - public final InputStream newInputStream(OpenOption... options) - throws IOException - { - if (options.length > 0) { - for (OpenOption opt: options) { - if (opt != READ) - throw new UnsupportedOperationException("'" + opt + "' not allowed"); - } - } - return Channels.newInputStream(newByteChannel()); + public final Path resolve(String other) { + return resolve(getFileSystem().getPath(other)); } @Override - public final OutputStream newOutputStream(OpenOption... options) - throws IOException - { - int len = options.length; - Set opts = new HashSet(len + 3); - if (len == 0) { - opts.add(CREATE); - opts.add(TRUNCATE_EXISTING); - } else { - for (OpenOption opt: options) { - if (opt == READ) - throw new IllegalArgumentException("READ not allowed"); - opts.add(opt); - } - } - opts.add(WRITE); - return Channels.newOutputStream(newByteChannel(opts)); + public final Path resolveSibling(Path other) { + if (other == null) + throw new NullPointerException(); + Path parent = getParent(); + return (parent == null) ? other : parent.resolve(other); } @Override - public final SeekableByteChannel newByteChannel(OpenOption... options) - throws IOException - { - Set set = new HashSet(options.length); - Collections.addAll(set, options); - return newByteChannel(set); - } - - private static final DirectoryStream.Filter acceptAllFilter = - new DirectoryStream.Filter() { - @Override public boolean accept(Path entry) { return true; } - }; - - @Override - public final DirectoryStream newDirectoryStream() throws IOException { - return newDirectoryStream(acceptAllFilter); + public final Path resolveSibling(String other) { + return resolveSibling(getFileSystem().getPath(other)); } @Override - public final DirectoryStream newDirectoryStream(String glob) - throws IOException - { - // avoid creating a matcher if all entries are required. - if (glob.equals("*")) - return newDirectoryStream(); - - // create a matcher and return a filter that uses it. - final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob); - DirectoryStream.Filter filter = new DirectoryStream.Filter() { + public final Iterator iterator() { + return new Iterator() { + private int i = 0; @Override - public boolean accept(Path entry) { - return matcher.matches(entry.getName()); + public boolean hasNext() { + return (i < getNameCount()); + } + @Override + public Path next() { + if (i < getNameCount()) { + Path result = getName(i); + i++; + return result; + } else { + throw new NoSuchElementException(); + } + } + @Override + public void remove() { + throw new UnsupportedOperationException(); } }; - return newDirectoryStream(filter); } @Override - public final boolean exists() { - try { - checkAccess(); - return true; - } catch (IOException x) { - // unable to determine if file exists - } - return false; + public final File toFile() { + return new File(toString()); } - @Override - public final boolean notExists() { - try { - checkAccess(); - return false; - } catch (NoSuchFileException x) { - // file confirmed not to exist - return true; - } catch (IOException x) { - return false; - } - } - - private static final WatchEvent.Modifier[] NO_MODIFIERS = new WatchEvent.Modifier[0]; - @Override public final WatchKey register(WatchService watcher, WatchEvent.Kind... events) throws IOException { - return register(watcher, events, NO_MODIFIERS); - } - - abstract void implCopyTo(Path target, CopyOption... options) - throws IOException; - - @Override - public final Path copyTo(Path target, CopyOption... options) - throws IOException - { - if ((getFileSystem().provider() == target.getFileSystem().provider())) { - implCopyTo(target, options); - } else { - copyToForeignTarget(target, options); - } - return target; - } - - abstract void implMoveTo(Path target, CopyOption... options) - throws IOException; - - @Override - public final Path moveTo(Path target, CopyOption... options) - throws IOException - { - if ((getFileSystem().provider() == target.getFileSystem().provider())) { - implMoveTo(target, options); - } else { - // different providers so copy + delete - copyToForeignTarget(target, convertMoveToCopyOptions(options)); - delete(); - } - return target; - } - - /** - * Converts the given array of options for moving a file to options suitable - * for copying the file when a move is implemented as copy + delete. - */ - private static CopyOption[] convertMoveToCopyOptions(CopyOption... options) - throws AtomicMoveNotSupportedException - { - int len = options.length; - CopyOption[] newOptions = new CopyOption[len+2]; - for (int i=0; i 0; - buf.flip(); - while (buf.hasRemaining()) { - sbc.write(buf); - } - buf.rewind(); - } - - } finally { - sbc.close(); - } - } finally { - rbc.close(); - } - } - - /** - * Splits the given attribute name into the name of an attribute view and - * the attribute. If the attribute view is not identified then it assumed - * to be "basic". - */ - private static String[] split(String attribute) { - String[] s = new String[2]; - int pos = attribute.indexOf(':'); - if (pos == -1) { - s[0] = "basic"; - s[1] = attribute; - } else { - s[0] = attribute.substring(0, pos++); - s[1] = (pos == attribute.length()) ? "" : attribute.substring(pos); - } - return s; - } - - /** - * Gets a DynamicFileAttributeView by name. Returns {@code null} if the - * view is not available. - */ - abstract DynamicFileAttributeView getFileAttributeView(String name, - LinkOption... options); - - @Override - public final void setAttribute(String attribute, - Object value, - LinkOption... options) - throws IOException - { - String[] s = split(attribute); - DynamicFileAttributeView view = getFileAttributeView(s[0], options); - if (view == null) - throw new UnsupportedOperationException("View '" + s[0] + "' not available"); - view.setAttribute(s[1], value); - } - - @Override - public final Object getAttribute(String attribute, LinkOption... options) - throws IOException - { - String[] s = split(attribute); - DynamicFileAttributeView view = getFileAttributeView(s[0], options); - return (view == null) ? null : view.getAttribute(s[1]); - } - - @Override - public final Map readAttributes(String attributes, LinkOption... options) - throws IOException - { - String[] s = split(attributes); - DynamicFileAttributeView view = getFileAttributeView(s[0], options); - if (view == null) - return Collections.emptyMap(); - return view.readAttributes(s[1].split(",")); + return register(watcher, events, new WatchEvent.Modifier[0]); } } diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java b/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java index 25567f3ce30..4bc4ecc29df 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractPoller.java @@ -92,7 +92,7 @@ abstract class AbstractPoller implements Runnable { /** * Requests, and waits on, poller thread to register given file. */ - final WatchKey register(FileRef dir, + final WatchKey register(Path dir, WatchEvent.Kind[] events, WatchEvent.Modifier... modifiers) throws IOException @@ -102,7 +102,7 @@ abstract class AbstractPoller implements Runnable { throw new NullPointerException(); if (events.length == 0) throw new IllegalArgumentException("No events to register"); - Set> eventSet = new HashSet>(events.length); + Set> eventSet = new HashSet<>(events.length); for (WatchEvent.Kind event: events) { // standard events if (event == StandardWatchEventKind.ENTRY_CREATE || diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java index 2f60db3f547..cf36a09ff0a 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java @@ -59,8 +59,7 @@ abstract class AbstractUserDefinedFileAttributeView return "user"; } - @Override - public final Object getAttribute(String attribute) throws IOException { + private Object getAttribute(String attribute) throws IOException { int size; try { size = size(attribute); @@ -90,11 +89,11 @@ abstract class AbstractUserDefinedFileAttributeView } @Override - public final Map readAttributes(String[] attributes) + public final Map readAttributes(String[] attributes) throws IOException { // names of attributes to return - List names = new ArrayList(); + List names = new ArrayList<>(); for (String name: attributes) { if (name.equals("*")) { @@ -106,7 +105,7 @@ abstract class AbstractUserDefinedFileAttributeView } // read each value and return in map - Map result = new HashMap(); + Map result = new HashMap<>(); for (String name: names) { Object value = getAttribute(name); if (value != null) diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java b/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java index c3970d86c05..55234ba6528 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java @@ -32,7 +32,7 @@ import java.util.*; * Base implementation class for watch keys. */ -abstract class AbstractWatchKey extends WatchKey { +abstract class AbstractWatchKey implements WatchKey { /** * Maximum size of event list (in the future this may be tunable) @@ -53,6 +53,9 @@ abstract class AbstractWatchKey extends WatchKey { // reference to watcher private final AbstractWatchService watcher; + // reference to the original directory + private final Path dir; + // key state private State state; @@ -63,8 +66,9 @@ abstract class AbstractWatchKey extends WatchKey { // event for the context is an ENTRY_MODIFY event). private Map> lastModifyEvents; - protected AbstractWatchKey(AbstractWatchService watcher) { + protected AbstractWatchKey(Path dir, AbstractWatchService watcher) { this.watcher = watcher; + this.dir = dir; this.state = State.READY; this.events = new ArrayList>(); this.lastModifyEvents = new HashMap>(); @@ -74,6 +78,13 @@ abstract class AbstractWatchKey extends WatchKey { return watcher; } + /** + * Return the original watchable (Path) + */ + Path watchable() { + return dir; + } + /** * Enqueues this key to the watch service */ @@ -175,7 +186,7 @@ abstract class AbstractWatchKey extends WatchKey { /** * WatchEvent implementation */ - private static class Event extends WatchEvent { + private static class Event implements WatchEvent { private final WatchEvent.Kind kind; private final T context; diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java b/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java index ffab46fd645..c35e15f4158 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractWatchService.java @@ -33,7 +33,7 @@ import java.io.IOException; * Base implementation class for watch services. */ -abstract class AbstractWatchService extends WatchService { +abstract class AbstractWatchService implements WatchService { // signaled keys waiting to be dequeued private final LinkedBlockingDeque pendingKeys = @@ -41,7 +41,7 @@ abstract class AbstractWatchService extends WatchService { // special key to indicate that watch service is closed private final WatchKey CLOSE_KEY = - new AbstractWatchKey(null) { + new AbstractWatchKey(null, null) { @Override public boolean isValid() { return true; @@ -54,7 +54,7 @@ abstract class AbstractWatchService extends WatchService { // used when closing watch service private volatile boolean closed; - private Object closeLock = new Object(); + private final Object closeLock = new Object(); protected AbstractWatchService() { } @@ -93,7 +93,7 @@ abstract class AbstractWatchService extends WatchService { } @Override - public final WatchKey poll() { + public final WatchKey poll() { checkOpen(); WatchKey key = pendingKeys.poll(); checkKey(key); diff --git a/jdk/src/share/classes/sun/nio/fs/DynamicFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/DynamicFileAttributeView.java index 963a741b525..f91b8539e9c 100644 --- a/jdk/src/share/classes/sun/nio/fs/DynamicFileAttributeView.java +++ b/jdk/src/share/classes/sun/nio/fs/DynamicFileAttributeView.java @@ -34,11 +34,6 @@ import java.io.IOException; */ interface DynamicFileAttributeView { - /** - * Reads the value of an attribute. - */ - Object getAttribute(String attribute) throws IOException; - /** * Sets/updates the value of an attribute. */ @@ -47,5 +42,5 @@ interface DynamicFileAttributeView { /** * Reads a set of file attributes as a bulk operation. */ - Map readAttributes(String[] attributes) throws IOException; + Map readAttributes(String[] attributes) throws IOException; } diff --git a/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java b/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java index 977b81f4cfa..aae9bd318c1 100644 --- a/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java +++ b/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java @@ -57,13 +57,6 @@ final class FileOwnerAttributeViewImpl return "owner"; } - @Override - public Object getAttribute(String attribute) throws IOException { - if (attribute.equals(OWNER_NAME)) - return getOwner(); - return null; - } - @Override public void setAttribute(String attribute, Object value) throws IOException @@ -77,8 +70,8 @@ final class FileOwnerAttributeViewImpl } @Override - public Map readAttributes(String[] attributes) throws IOException { - Map result = new HashMap(); + public Map readAttributes(String[] attributes) throws IOException { + Map result = new HashMap<>(); for (String attribute: attributes) { if (attribute.equals("*") || attribute.equals(OWNER_NAME)) { result.put(OWNER_NAME, getOwner()); diff --git a/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java b/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java index e2b2078bd99..7cd923842b5 100644 --- a/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java +++ b/jdk/src/share/classes/sun/nio/fs/PollingWatchService.java @@ -146,7 +146,7 @@ class PollingWatchService throws IOException { // check file is a directory and get its file key if possible - BasicFileAttributes attrs = Attributes.readBasicFileAttributes(path); + BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class); if (!attrs.isDirectory()) { throw new NotDirectoryException(path.toString()); } @@ -164,7 +164,7 @@ class PollingWatchService watchKey = map.get(fileKey); if (watchKey == null) { // new registration - watchKey = new PollingWatchKey(this, path, fileKey); + watchKey = new PollingWatchKey(path, this, fileKey); map.put(fileKey, watchKey); } else { // update to existing registration @@ -228,7 +228,6 @@ class PollingWatchService * directory and queue keys when entries are added, modified, or deleted. */ private class PollingWatchKey extends AbstractWatchKey { - private final Path dir; private final Object fileKey; // current event set @@ -246,44 +245,28 @@ class PollingWatchService // map of entries in directory private Map entries; - PollingWatchKey(PollingWatchService watcher, - Path dir, - Object fileKey) + PollingWatchKey(Path dir, PollingWatchService watcher, Object fileKey) throws IOException { - super(watcher); - this.dir = dir; + super(dir, watcher); this.fileKey = fileKey; this.valid = true; this.tickCount = 0; this.entries = new HashMap(); // get the initial entries in the directory - DirectoryStream stream = dir.newDirectoryStream(); - try { + try (DirectoryStream stream = Files.newDirectoryStream(dir)) { for (Path entry: stream) { // don't follow links - long lastModified = Attributes - .readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS) - .lastModifiedTime().toMillis(); - entries.put(entry.getName(), - new CacheEntry(lastModified, tickCount)); + long lastModified = + Files.getLastModifiedTime(entry, LinkOption.NOFOLLOW_LINKS).toMillis(); + entries.put(entry.getFileName(), new CacheEntry(lastModified, tickCount)); } - } catch (ConcurrentModificationException cme) { - // thrown if directory iteration fails - Throwable cause = cme.getCause(); - if (cause != null && cause instanceof IOException) - throw (IOException)cause; - throw new AssertionError(cme); - } finally { - stream.close(); + } catch (DirectoryIteratorException e) { + throw e.getCause(); } } - FileRef directory() { - return dir; - } - Object fileKey() { return fileKey; } @@ -342,7 +325,7 @@ class PollingWatchService // open directory DirectoryStream stream = null; try { - stream = dir.newDirectoryStream(); + stream = Files.newDirectoryStream(watchable()); } catch (IOException x) { // directory is no longer accessible so cancel key cancel(); @@ -355,9 +338,8 @@ class PollingWatchService for (Path entry: stream) { long lastModified = 0L; try { - lastModified = Attributes - .readBasicFileAttributes(entry, LinkOption.NOFOLLOW_LINKS) - .lastModifiedTime().toMillis(); + lastModified = + Files.getLastModifiedTime(entry, LinkOption.NOFOLLOW_LINKS).toMillis(); } catch (IOException x) { // unable to get attributes of entry. If file has just // been deleted then we'll report it as deleted on the @@ -366,15 +348,15 @@ class PollingWatchService } // lookup cache - CacheEntry e = entries.get(entry.getName()); + CacheEntry e = entries.get(entry.getFileName()); if (e == null) { // new file found - entries.put(entry.getName(), + entries.put(entry.getFileName(), new CacheEntry(lastModified, tickCount)); // queue ENTRY_CREATE if event enabled if (events.contains(StandardWatchEventKind.ENTRY_CREATE)) { - signalEvent(StandardWatchEventKind.ENTRY_CREATE, entry.getName()); + signalEvent(StandardWatchEventKind.ENTRY_CREATE, entry.getFileName()); continue; } else { // if ENTRY_CREATE is not enabled and ENTRY_MODIFY is @@ -382,7 +364,7 @@ class PollingWatchService // modifications to the file immediately after it is // created. if (events.contains(StandardWatchEventKind.ENTRY_MODIFY)) { - signalEvent(StandardWatchEventKind.ENTRY_MODIFY, entry.getName()); + signalEvent(StandardWatchEventKind.ENTRY_MODIFY, entry.getFileName()); } } continue; @@ -391,15 +373,17 @@ class PollingWatchService // check if file has changed if (e.lastModified != lastModified) { if (events.contains(StandardWatchEventKind.ENTRY_MODIFY)) { - signalEvent(StandardWatchEventKind.ENTRY_MODIFY, entry.getName()); + signalEvent(StandardWatchEventKind.ENTRY_MODIFY, + entry.getFileName()); } } // entry in cache so update poll time e.update(lastModified, tickCount); } - } catch (ConcurrentModificationException x) { - // FIXME - should handle this + } catch (DirectoryIteratorException e) { + // ignore for now; if the directory is no longer accessible + // then the key will be cancelled on the next poll } finally { // close directory stream diff --git a/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java b/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java index c05d8bd08bf..140d5981b5e 100644 --- a/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java +++ b/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java @@ -173,7 +173,7 @@ class KrbAsRep extends KrbKdcRep { } Credentials getCreds() { - return Objects.nonNull(creds, "Creds not available yet."); + return Objects.requireNonNull(creds, "Creds not available yet."); } sun.security.krb5.internal.ccache.Credentials getCCreds() { diff --git a/jdk/src/share/classes/sun/security/provider/SeedGenerator.java b/jdk/src/share/classes/sun/security/provider/SeedGenerator.java index d66181a6149..cb778055b35 100644 --- a/jdk/src/share/classes/sun/security/provider/SeedGenerator.java +++ b/jdk/src/share/classes/sun/security/provider/SeedGenerator.java @@ -63,13 +63,14 @@ package sun.security.provider; * @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.Files; +import java.nio.file.Path; import java.util.Random; import sun.security.util.Debug; @@ -177,37 +178,21 @@ abstract class SeedGenerator { // The temporary dir File f = new File(p.getProperty("java.io.tmpdir")); - - // 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); + int count = 0; + try (DirectoryStream stream = Files.newDirectoryStream(f.toPath())) { // 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(); - try { - for (Object entry: stream) { - if (count < 512 || r.nextBoolean()) { - md.update(NIODirectoryStream.getName( - entry).getBytes()); - } - if (count++ > 1024) { - break; - } + for (Path entry: stream) { + if (count < 512 || r.nextBoolean()) { + md.update(entry.getFileName().toString().getBytes()); + } + if (count++ > 1024) { + break; } - } finally { - ((Closeable)stream).close(); - } - } else { - String[] sa = f.list(); - for(int i = 0; i < sa.length; i++) { - md.update(sa[i].getBytes()); } } } catch (Exception ex) { @@ -553,77 +538,4 @@ abstract class SeedGenerator { } } - - /** - * 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); - } - } - } } - diff --git a/jdk/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java b/jdk/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java new file mode 100644 index 00000000000..1b14bf8fa66 --- /dev/null +++ b/jdk/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.provider.certpath; + +import java.io.IOException; +import java.util.Date; + +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.security.cert.X509CertSelector; +import java.security.cert.CertificateException; + +import sun.security.util.DerOutputStream; +import sun.security.x509.SerialNumber; +import sun.security.x509.KeyIdentifier; +import sun.security.x509.AuthorityKeyIdentifierExtension; + +/** + * An adaptable X509 certificate selector for forward certification path + * building. + * + * @since 1.7 + */ +class AdaptableX509CertSelector extends X509CertSelector { + // The start date of a validity period. + private Date startDate = null; + + // The end date of a validity period. + private Date endDate = null; + + AdaptableX509CertSelector() { + super(); + } + + /** + * Sets the criterion of the X509Certificate validity period. + * + * Normally, we may not have to check that a certificate validity period + * must fall within its issuer's certificate validity period. However, + * when we face root CA key updates for version 1 certificates, according + * to scheme of RFC 4210 or 2510, the validity periods should be checked + * to determine the right issuer's certificate. + * + * Conservatively, we will only check the validity periods for version + * 1 and version 2 certificates. For version 3 certificates, we can + * determine the right issuer by authority and subject key identifier + * extensions. + * + * @param startDate the start date of a validity period that must fall + * within the certificate validity period for the X509Certificate + * @param endDate the end date of a validity period that must fall + * within the certificate validity period for the X509Certificate + */ + void setValidityPeriod(Date startDate, Date endDate) { + this.startDate = startDate; + this.endDate = endDate; + } + + /** + * Parse the authority key identifier extension. + * + * If the keyIdentifier field of the extension is non-null, set the + * subjectKeyIdentifier criterion. If the authorityCertSerialNumber + * field is non-null, set the serialNumber criterion. + * + * Note that we will not set the subject criterion according to the + * authorityCertIssuer field of the extension. The caller MUST set + * the subject criterion before call match(). + * + * @param akidext the authorityKeyIdentifier extension + */ + void parseAuthorityKeyIdentifierExtension( + AuthorityKeyIdentifierExtension akidext) throws IOException { + if (akidext != null) { + KeyIdentifier akid = (KeyIdentifier)akidext.get(akidext.KEY_ID); + if (akid != null) { + DerOutputStream derout = new DerOutputStream(); + derout.putOctetString(akid.getIdentifier()); + super.setSubjectKeyIdentifier(derout.toByteArray()); + } + + SerialNumber asn = + (SerialNumber)akidext.get(akidext.SERIAL_NUMBER); + if (asn != null) { + super.setSerialNumber(asn.getNumber()); + } + + // the subject criterion should be set by the caller. + } + } + + /** + * Decides whether a Certificate should be selected. + * + * For the purpose of compatibility, when a certificate is of + * version 1 and version 2, or the certificate does not include + * a subject key identifier extension, the selection criterion + * of subjectKeyIdentifier will be disabled. + */ + @Override + public boolean match(Certificate cert) { + if (!(cert instanceof X509Certificate)) { + return false; + } + + X509Certificate xcert = (X509Certificate)cert; + int version = xcert.getVersion(); + + // Check the validity period for version 1 and 2 certificate. + if (version < 3) { + if (startDate != null) { + try { + xcert.checkValidity(startDate); + } catch (CertificateException ce) { + return false; + } + } + + if (endDate != null) { + try { + xcert.checkValidity(endDate); + } catch (CertificateException ce) { + return false; + } + } + } + + if (version < 3 || xcert.getExtensionValue("2.5.29.14") == null) { + // If no SubjectKeyIdentifier extension, don't bother to check it. + setSubjectKeyIdentifier(null); + } + + return super.match(cert); + } + + @Override + public Object clone() { + AdaptableX509CertSelector copy = + (AdaptableX509CertSelector)super.clone(); + if (startDate != null) { + copy.startDate = (Date)startDate.clone(); + } + + if (endDate != null) { + copy.endDate = (Date)endDate.clone(); + } + + return copy; + } +} diff --git a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java index 69e560ed4bf..27a9caa8c87 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,8 @@ import java.security.cert.TrustAnchor; import java.security.cert.CRLException; import java.security.cert.CertificateException; import java.security.cert.CertPathValidatorException; +import java.security.cert.CertPathValidatorException.BasicReason; +import java.security.cert.PKIXReason; import java.io.IOException; import java.security.interfaces.*; import java.security.spec.*; @@ -196,14 +198,16 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { SIGNATURE_PRIMITIVE_SET, currSigAlg, currSigAlgParams)) { throw new CertPathValidatorException( - "Algorithm constraints check failed: " + currSigAlg); + "Algorithm constraints check failed: " + currSigAlg, + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } // check the key usage and key size boolean[] keyUsage = x509Cert.getKeyUsage(); if (keyUsage != null && keyUsage.length < 9) { throw new CertPathValidatorException( - "incorrect KeyUsage extension"); + "incorrect KeyUsage extension", + null, null, -1, PKIXReason.INVALID_KEY_USAGE); } if (keyUsage != null) { @@ -236,7 +240,8 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { if (!primitives.isEmpty()) { if (!constraints.permits(primitives, currPubKey)) { throw new CertPathValidatorException( - "algorithm constraints check failed"); + "algorithm constraints check failed", + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } } } @@ -248,7 +253,8 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { SIGNATURE_PRIMITIVE_SET, currSigAlg, prevPubKey, currSigAlgParams)) { throw new CertPathValidatorException( - "Algorithm constraints check failed: " + currSigAlg); + "Algorithm constraints check failed: " + currSigAlg, + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } } @@ -258,7 +264,7 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { // Inherit DSA parameters from previous key if (!(prevPubKey instanceof DSAPublicKey)) { throw new CertPathValidatorException("Input key is not " + - "of a appropriate type for inheriting parameters"); + "of a appropriate type for inheriting parameters"); } DSAParams params = ((DSAPublicKey)prevPubKey).getParams(); @@ -352,7 +358,8 @@ final public class AlgorithmChecker extends PKIXCertPathChecker { if (!certPathDefaultConstraints.permits( SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) { throw new CertPathValidatorException( - "algorithm check failed: " + sigAlgName + " is disabled"); + "algorithm check failed: " + sigAlgName + " is disabled", + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } } diff --git a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java index a980e7d1657..e367a1faef4 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -317,7 +317,7 @@ class DistributionPointFetcher { // we accept the case that a CRL issuer provide status // information for itself. - if (ForwardBuilder.issues(certImpl, crlImpl, provider)) { + if (issues(certImpl, crlImpl, provider)) { // reset the public key used to verify the CRL's signature prevKey = certImpl.getPublicKey(); } else { @@ -338,7 +338,7 @@ class DistributionPointFetcher { if (!Arrays.equals(certAKID, crlAKID)) { // we accept the case that a CRL issuer provide status // information for itself. - if (ForwardBuilder.issues(certImpl, crlImpl, provider)) { + if (issues(certImpl, crlImpl, provider)) { // reset the public key used to verify the CRL's signature prevKey = certImpl.getPublicKey(); } else { @@ -687,4 +687,41 @@ class DistributionPointFetcher { fullNames.add(new GeneralName(fullName)); return fullNames; } + + /** Verifies whether a CRL is issued by a certain certificate + * + * @param cert the certificate + * @param crl the CRL to be verified + * @param provider the name of the signature provider + */ + private static boolean issues(X509CertImpl cert, X509CRLImpl crl, + String provider) throws IOException { + + AdaptableX509CertSelector issuerSelector = + new AdaptableX509CertSelector(); + + // check certificate's key usage + boolean[] usages = cert.getKeyUsage(); + if (usages != null) { + usages[6] = true; // cRLSign + issuerSelector.setKeyUsage(usages); + } + + // check certificate's subject + X500Principal crlIssuer = crl.getIssuerX500Principal(); + issuerSelector.setSubject(crlIssuer); + + /* + * Facilitate certification path construction with authority + * key identifier and subject key identifier. + * + * In practice, conforming CAs MUST use the key identifier method, + * and MUST include authority key identifier extension in all CRLs + * issued. [section 5.2.1, RFC 2459] + */ + issuerSelector.parseAuthorityKeyIdentifierExtension( + crl.getAuthKeyIdExtension()); + + return issuerSelector.match(cert); + } } diff --git a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java index 7e828884940..e9c0ca77879 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,7 +77,7 @@ class ForwardBuilder extends Builder { private final Set trustedSubjectDNs; private final Set trustAnchors; private X509CertSelector eeSelector; - private X509CertSelector caSelector; + private AdaptableX509CertSelector caSelector; private X509CertSelector caTargetSelector; TrustAnchor trustAnchor; private Comparator comparator; @@ -230,9 +230,11 @@ class ForwardBuilder extends Builder { targetCertConstraints.clone(); /* - * Match on certificate validity date + * Since we don't check the validity period of trusted + * certificates, please don't set the certificate valid + * criterion unless the trusted certificate matching is + * completed. */ - caTargetSelector.setCertificateValid(date); /* * Policy processing optimizations @@ -246,17 +248,19 @@ class ForwardBuilder extends Builder { * at least as many CA certs that have already been traversed */ caTargetSelector.setBasicConstraints(currentState.traversedCACerts); - sel = caTargetSelector; + sel = caTargetSelector; } else { if (caSelector == null) { caSelector = new AdaptableX509CertSelector(); /* - * Match on certificate validity date. + * Since we don't check the validity period of trusted + * certificates, please don't set the certificate valid + * criterion unless the trusted certificate matching is + * completed. */ - caSelector.setCertificateValid(date); /* * Policy processing optimizations @@ -290,42 +294,19 @@ class ForwardBuilder extends Builder { */ AuthorityKeyIdentifierExtension akidext = currentState.cert.getAuthorityKeyIdentifierExtension(); - if (akidext != null) { - KeyIdentifier akid = (KeyIdentifier)akidext.get(akidext.KEY_ID); - if (akid != null) { - DerOutputStream derout = new DerOutputStream(); - derout.putOctetString(akid.getIdentifier()); - caSelector.setSubjectKeyIdentifier(derout.toByteArray()); - } + caSelector.parseAuthorityKeyIdentifierExtension(akidext); - SerialNumber asn = - (SerialNumber)akidext.get(akidext.SERIAL_NUMBER); - if (asn != null) { - caSelector.setSerialNumber(asn.getNumber()); - } - // the subject criterion was set previously. - } + /* + * check the validity period + */ + caSelector.setValidityPeriod(currentState.cert.getNotBefore(), + currentState.cert.getNotAfter()); sel = caSelector; } - /* - * Check if any of the trusted certs could be a match. - * Since we are not validating the trusted cert, we can't - * re-use the selector we've built up (sel) - we need - * to use a new selector (trustedSel) - */ - X509CertSelector trustedSel = null; - if (currentState.isInitial()) { - trustedSel = targetCertConstraints; - } else { - trustedSel = new X509CertSelector(); - trustedSel.setSubject(currentState.issuerDN); - } - - boolean foundMatchingCert = false; for (X509Certificate trustedCert : trustedCerts) { - if (trustedSel.match(trustedCert)) { + if (sel.match(trustedCert)) { if (debug != null) { debug.println("ForwardBuilder.getMatchingCACerts: " + "found matching trust anchor"); @@ -336,6 +317,11 @@ class ForwardBuilder extends Builder { } } + /* + * The trusted certificate matching is completed. We need to match + * on certificate validity date. + */ + sel.setCertificateValid(date); /* * If we have already traversed as many CA certs as the maxPathLength @@ -348,8 +334,8 @@ class ForwardBuilder extends Builder { (buildParams.getMaxPathLength() == -1) || (buildParams.getMaxPathLength() > currentState.traversedCACerts)) { - if (addMatchingCerts(sel, certStores, caCerts, searchAllCertStores) - && !searchAllCertStores) { + if (addMatchingCerts(sel, certStores, + caCerts, searchAllCertStores) && !searchAllCertStores) { return; } } @@ -939,120 +925,4 @@ class ForwardBuilder extends Builder { void removeFinalCertFromPath(LinkedList certPathList) { certPathList.removeFirst(); } - - /** Verifies whether a CRL is issued by a certain certificate - * - * @param cert the certificate - * @param crl the CRL to be verified - * @param provider the name of the signature provider - */ - static boolean issues(X509CertImpl cert, X509CRLImpl crl, String provider) - throws IOException { - - boolean kidmatched = false; - - // check certificate's key usage - boolean[] usages = cert.getKeyUsage(); - if (usages != null && !usages[6]) { - return false; - } - - // check certificate's SKID and CRL's AKID - AuthorityKeyIdentifierExtension akidext = crl.getAuthKeyIdExtension(); - if (akidext != null) { - // the highest priority, matching KID - KeyIdentifier akid = (KeyIdentifier)akidext.get(akidext.KEY_ID); - if (akid != null) { - SubjectKeyIdentifierExtension skidext = - cert.getSubjectKeyIdentifierExtension(); - if (skidext != null) { - KeyIdentifier skid = - (KeyIdentifier)skidext.get(skidext.KEY_ID); - if (!akid.equals(skid)) { - return false; - } - - kidmatched = true; - } - // conservatively, in case of X509 V1 certificate, - // does return false here if no SKID extension. - } - - // the medium priority, matching issuer name/serial number - SerialNumber asn = (SerialNumber)akidext.get(akidext.SERIAL_NUMBER); - GeneralNames anames = (GeneralNames)akidext.get(akidext.AUTH_NAME); - if (asn != null && anames != null) { - X500Name subject = (X500Name)cert.getSubjectDN(); - BigInteger serial = cert.getSerialNumber(); - - if (serial != null && subject != null) { - if (serial.equals(asn.getNumber())) { - return false; - } - - for (GeneralName name : anames.names()) { - GeneralNameInterface gni = name.getName(); - if (subject.equals(gni)) { - return true; - } - } - } - - return false; - } - - if (kidmatched) { - return true; - } - } - - // the last priority, verify the CRL signature with the cert. - X500Principal crlIssuer = crl.getIssuerX500Principal(); - X500Principal certSubject = cert.getSubjectX500Principal(); - if (certSubject != null && certSubject.equals(crlIssuer)) { - try { - crl.verify(cert.getPublicKey(), provider); - return true; - } catch (Exception e) { - // ignore all exceptions. - } - } - - return false; - } - - /** - * An adaptable X509 certificate selector for forward certification path - * building. - */ - private static class AdaptableX509CertSelector extends X509CertSelector { - public AdaptableX509CertSelector() { - super(); - } - - /** - * Decides whether a Certificate should be selected. - * - * For the purpose of compatibility, when a certificate is of - * version 1 and version 2, or the certificate does not include - * a subject key identifier extension, the selection criterion - * of subjectKeyIdentifier will be disabled. - * - * @Override - */ - public boolean match(Certificate cert) { - if (!(cert instanceof X509Certificate)) { - return false; - } - X509Certificate xcert = (X509Certificate)cert; - - if (xcert.getVersion() < 3 || - xcert.getExtensionValue("2.5.29.14") == null) { - // disable the subjectKeyIdentifier criterion - setSubjectKeyIdentifier(null); - } - - return super.match(cert); - } - } } diff --git a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java index d8fbadf199a..a4f83c87bbb 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,9 @@ import javax.security.auth.x500.X500Principal; import sun.security.action.GetBooleanSecurityPropertyAction; import sun.security.util.Debug; +import sun.security.x509.X509CertImpl; + + /** * This class implements the PKIX validation algorithm for certification * paths consisting exclusively of X509Certificates. It uses @@ -162,6 +165,7 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi { debug.println("PKIXCertPathValidator.engineValidate() " + "anchor.getTrustedCert() != null"); } + // if this trust anchor is not worth trying, // we move on to the next one if (!isWorthTrying(trustedCert, firstCert)) { @@ -211,8 +215,10 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi { * worth trying to validate in the chain. */ private boolean isWorthTrying(X509Certificate trustedCert, - X509Certificate firstCert) - { + X509Certificate firstCert) { + + boolean worthy = false; + if (debug != null) { debug.println("PKIXCertPathValidator.isWorthTrying() checking " + "if this trusted cert is worth trying ..."); @@ -222,19 +228,46 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi { return true; } - // the subject of the trusted cert should match the - // issuer of the first cert in the certpath + AdaptableX509CertSelector issuerSelector = + new AdaptableX509CertSelector(); - X500Principal trustedSubject = trustedCert.getSubjectX500Principal(); - if (trustedSubject.equals(firstCert.getIssuerX500Principal())) { - if (debug != null) - debug.println("YES - try this trustedCert"); - return true; - } else { - if (debug != null) - debug.println("NO - don't try this trustedCert"); - return false; + // check trusted certificate's key usage + boolean[] usages = trustedCert.getKeyUsage(); + if (usages != null) { + usages[5] = true; // keyCertSign + issuerSelector.setKeyUsage(usages); } + + // check trusted certificate's subject + issuerSelector.setSubject(firstCert.getIssuerX500Principal()); + + // check the validity period + issuerSelector.setValidityPeriod(firstCert.getNotBefore(), + firstCert.getNotAfter()); + + /* + * Facilitate certification path construction with authority + * key identifier and subject key identifier. + */ + try { + X509CertImpl firstCertImpl = X509CertImpl.toImpl(firstCert); + issuerSelector.parseAuthorityKeyIdentifierExtension( + firstCertImpl.getAuthorityKeyIdentifierExtension()); + + worthy = issuerSelector.match(trustedCert); + } catch (Exception e) { + // It is not worth trying. + } + + if (debug != null) { + if (worthy) { + debug.println("YES - try this trustedCert"); + } else { + debug.println("NO - don't try this trustedCert"); + } + } + + return worthy; } /** diff --git a/jdk/src/share/classes/sun/security/validator/SimpleValidator.java b/jdk/src/share/classes/sun/security/validator/SimpleValidator.java index f825a4d6867..9ad04b8773e 100644 --- a/jdk/src/share/classes/sun/security/validator/SimpleValidator.java +++ b/jdk/src/share/classes/sun/security/validator/SimpleValidator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -156,8 +156,8 @@ public final class SimpleValidator extends Validator { // check certificate algorithm try { - // Algorithm checker don't care about the unresolved critical - // extensions. + // Algorithm checker does not care about the unresolved + // critical extensions. defaultAlgChecker.check(cert, Collections.emptySet()); if (appAlgChecker != null) { appAlgChecker.check(cert, Collections.emptySet()); diff --git a/jdk/src/share/classes/sun/swing/AccumulativeRunnable.java b/jdk/src/share/classes/sun/swing/AccumulativeRunnable.java index 583352918e4..2988521f133 100644 --- a/jdk/src/share/classes/sun/swing/AccumulativeRunnable.java +++ b/jdk/src/share/classes/sun/swing/AccumulativeRunnable.java @@ -120,6 +120,7 @@ public abstract class AccumulativeRunnable implements Runnable { * {@code Runnable} for execution. * @param args the arguments to accumulate */ + @SafeVarargs public final synchronized void add(T... args) { boolean isSubmitted = true; if (arguments == null) { diff --git a/jdk/src/share/classes/sun/tools/jar/Main.java b/jdk/src/share/classes/sun/tools/jar/Main.java index 3b8ea5b95b8..59c758f6cfc 100644 --- a/jdk/src/share/classes/sun/tools/jar/Main.java +++ b/jdk/src/share/classes/sun/tools/jar/Main.java @@ -27,6 +27,7 @@ package sun.tools.jar; import java.io.*; import java.nio.file.Path; +import java.nio.file.Files; import java.util.*; import java.util.zip.*; import java.util.jar.*; @@ -1017,17 +1018,17 @@ class Main { Path jarPath = jarFile.toPath(); Path tmpPath = createTempFileInSameDirectoryAs(jarFile).toPath(); try { - if (update(jarPath.newInputStream(), - tmpPath.newOutputStream(), + if (update(Files.newInputStream(jarPath), + Files.newOutputStream(tmpPath), null, index)) { try { - tmpPath.moveTo(jarPath, REPLACE_EXISTING); + Files.move(tmpPath, jarPath, REPLACE_EXISTING); } catch (IOException e) { throw new IOException(getMsg("error.write.file"), e); } } } finally { - tmpPath.deleteIfExists(); + Files.deleteIfExists(tmpPath); } } diff --git a/jdk/src/share/demo/nio/zipfs/Demo.java b/jdk/src/share/demo/nio/zipfs/Demo.java index fd2ba7311b1..dfe77b877ed 100644 --- a/jdk/src/share/demo/nio/zipfs/Demo.java +++ b/jdk/src/share/demo/nio/zipfs/Demo.java @@ -33,6 +33,7 @@ import java.io.*; import java.nio.*; import java.nio.channels.*; import java.nio.file.*; +import java.nio.file.spi.*; import java.nio.file.attribute.*; import java.net.*; import java.text.DateFormat; @@ -144,78 +145,76 @@ public class Demo { } public static void main(String[] args) throws Throwable { + FileSystemProvider provider = getZipFSProvider(); + if (provider == null) { + System.err.println("ZIP filesystem provider is not installed"); + System.exit(1); + } Action action = Action.valueOf(args[0]); Map env = env = new HashMap<>(); if (action == Action.create) env.put("create", "true"); - if (action == Action.tlist || action == Action.twalk) - env.put("buildDirTree", true); - FileSystem fs = FileSystems.newFileSystem(Paths.get(args[1]), env, null); - - try { - FileSystem fs2; + try (FileSystem fs = provider.newFileSystem(Paths.get(args[1]), env)) { Path path, src, dst; boolean isRename = false; switch (action) { case rename: src = fs.getPath(args[2]); dst = fs.getPath(args[3]); - src.moveTo(dst); + Files.move(src, dst); break; case moveout: src = fs.getPath(args[2]); dst = Paths.get(args[3]); - src.moveTo(dst); + Files.move(src, dst); break; case movein: src = Paths.get(args[2]); dst = fs.getPath(args[3]); - src.moveTo(dst); + Files.move(src, dst); break; case copy: src = fs.getPath(args[2]); dst = fs.getPath(args[3]); - src.copyTo(dst); + Files.copy(src, dst); break; case copyout: src = fs.getPath(args[2]); dst = Paths.get(args[3]); - src.copyTo(dst); + Files.copy(src, dst); break; case copyin: src = Paths.get(args[2]); dst = fs.getPath(args[3]); - src.copyTo(dst); + Files.copy(src, dst); break; case copyin_attrs: src = Paths.get(args[2]); dst = fs.getPath(args[3]); - src.copyTo(dst, COPY_ATTRIBUTES); + Files.copy(src, dst, COPY_ATTRIBUTES); break; case copyout_attrs: src = fs.getPath(args[2]); dst = Paths.get(args[3]); - src.copyTo(dst, COPY_ATTRIBUTES); + Files.copy(src, dst, COPY_ATTRIBUTES); break; case zzmove: - fs2 = FileSystems.newFileSystem(Paths.get(args[2]), env, null); - //sf1.getPath(args[3]).moveTo(fs2.getPath(args[3])); - z2zmove(fs, fs2, args[3]); - fs2.close(); + try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) { + z2zmove(fs, fs2, args[3]); + } break; case zzcopy: - fs2 = FileSystems.newFileSystem(Paths.get(args[2]), env, null); - //sf1.getPath(args[3]).copyTo(fs2.getPath(args[3])); - z2zcopy(fs, fs2, args[3]); - fs2.close(); + try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) { + z2zcopy(fs, fs2, args[3]); + } break; case attrs: for (int i = 2; i < args.length; i++) { path = fs.getPath(args[i]); System.out.println(path); System.out.println( - Attributes.readBasicFileAttributes(path).toString()); + Files.readAttributes(path, BasicFileAttributes.class).toString()); } break; case setmtime: @@ -223,10 +222,10 @@ public class Demo { Date newDatetime = df.parse(args[2]); for (int i = 3; i < args.length; i++) { path = fs.getPath(args[i]); - path.setAttribute("lastModifiedTime", - FileTime.fromMillis(newDatetime.getTime())); + Files.setAttribute(path, "lastModifiedTime", + FileTime.fromMillis(newDatetime.getTime())); System.out.println( - Attributes.readBasicFileAttributes(path).toString()); + Files.readAttributes(path, BasicFileAttributes.class).toString()); } break; case setctime: @@ -234,10 +233,10 @@ public class Demo { newDatetime = df.parse(args[2]); for (int i = 3; i < args.length; i++) { path = fs.getPath(args[i]); - path.setAttribute("creationTime", - FileTime.fromMillis(newDatetime.getTime())); + Files.setAttribute(path, "creationTime", + FileTime.fromMillis(newDatetime.getTime())); System.out.println( - Attributes.readBasicFileAttributes(path).toString()); + Files.readAttributes(path, BasicFileAttributes.class).toString()); } break; case setatime: @@ -245,25 +244,22 @@ public class Demo { newDatetime = df.parse(args[2]); for (int i = 3; i < args.length; i++) { path = fs.getPath(args[i]); - path.setAttribute("lastAccessTime", - FileTime.fromMillis(newDatetime.getTime())); + Files.setAttribute(path, "lastAccessTime", + FileTime.fromMillis(newDatetime.getTime())); System.out.println( - Attributes.readBasicFileAttributes(path).toString()); + Files.readAttributes(path, BasicFileAttributes.class).toString()); } break; case attrsspace: path = fs.getPath("/"); - FileStore fstore = path.getFileStore(); - //System.out.println(fstore.getFileStoreAttributeView(FileStoreSpaceAttributeView.class) - // .readAttributes()); - // or + FileStore fstore = Files.getFileStore(path); System.out.printf("filestore[%s]%n", fstore.name()); System.out.printf(" totalSpace: %d%n", - (Long)fstore.getAttribute("space:totalSpace")); + (Long)fstore.getAttribute("totalSpace")); System.out.printf(" usableSpace: %d%n", - (Long)fstore.getAttribute("space:usableSpace")); + (Long)fstore.getAttribute("usableSpace")); System.out.printf(" unallocSpace: %d%n", - (Long)fstore.getAttribute("space:unallocatedSpace")); + (Long)fstore.getAttribute("unallocatedSpace")); break; case list: case tlist: @@ -293,7 +289,7 @@ public class Demo { break; case delete: for (int i = 2; i < args.length; i++) - fs.getPath(args[i]).delete(); + Files.delete(fs.getPath(args[i])); break; case create: case add: @@ -305,17 +301,19 @@ public class Demo { case lsdir: path = fs.getPath(args[2]); final String fStr = (args.length > 3)?args[3]:""; - DirectoryStream ds = path.newDirectoryStream( + try (DirectoryStream ds = Files.newDirectoryStream(path, new DirectoryStream.Filter() { public boolean accept(Path path) { return path.toString().contains(fStr); } - }); - for (Path p : ds) - System.out.println(p); + })) + { + for (Path p : ds) + System.out.println(p); + } break; case mkdir: - fs.getPath(args[2]).createDirectory(); + Files.createDirectory(fs.getPath(args[2])); break; case mkdirs: mkdirs(fs.getPath(args[2])); @@ -326,14 +324,14 @@ public class Demo { System.out.printf("%n%s%n", path); System.out.println("-------(1)---------"); System.out.println( - Attributes.readBasicFileAttributes(path).toString()); + Files.readAttributes(path, BasicFileAttributes.class).toString()); System.out.println("-------(2)---------"); - Map map = path.readAttributes("zip:*"); - for (Map.Entry e : map.entrySet()) { + Map map = Files.readAttributes(path, "zip:*"); + for (Map.Entry e : map.entrySet()) { System.out.printf(" %s : %s%n", e.getKey(), e.getValue()); } System.out.println("-------(3)---------"); - map = path.readAttributes("size,lastModifiedTime,isDirectory"); + map = Files.readAttributes(path, "size,lastModifiedTime,isDirectory"); for (Map.Entry e : map.entrySet()) { System.out.printf(" %s : %s%n", e.getKey(), e.getValue()); } @@ -349,12 +347,17 @@ public class Demo { } } catch (Exception x) { x.printStackTrace(); - } finally { - if (fs != null) - fs.close(); } } + private static FileSystemProvider getZipFSProvider() { + for (FileSystemProvider provider : FileSystemProvider.installedProviders()) { + if ("jar".equals(provider.getScheme())) + return provider; + } + return null; + } + private static byte[] getBytes(String name) { return name.getBytes(); } @@ -380,7 +383,7 @@ public class Demo { BasicFileAttributes attrs) { indent(); - System.out.printf("%s%n", file.getName().toString()); + System.out.printf("%s%n", file.getFileName().toString()); return FileVisitResult.CONTINUE; } @@ -406,35 +409,35 @@ public class Demo { private static void update(FileSystem fs, String path) throws Throwable{ Path src = FileSystems.getDefault().getPath(path); - if (Boolean.TRUE.equals(src.getAttribute("isDirectory"))) { - DirectoryStream ds = src.newDirectoryStream(); - for (Path child : ds) - update(fs, child.toString()); - ds.close(); + if (Files.isDirectory(src)) { + try (DirectoryStream ds = Files.newDirectoryStream(src)) { + for (Path child : ds) + update(fs, child.toString()); + } } else { Path dst = fs.getPath(path); Path parent = dst.getParent(); - if (parent != null && parent.notExists()) + if (parent != null && Files.notExists(parent)) mkdirs(parent); - src.copyTo(dst, REPLACE_EXISTING); + Files.copy(src, dst, REPLACE_EXISTING); } } private static void extract(FileSystem fs, String path) throws Throwable{ Path src = fs.getPath(path); - if (Boolean.TRUE.equals(src.getAttribute("isDirectory"))) { - DirectoryStream ds = src.newDirectoryStream(); - for (Path child : ds) - extract(fs, child.toString()); - ds.close(); + if (Files.isDirectory(src)) { + try (DirectoryStream ds = Files.newDirectoryStream(src)) { + for (Path child : ds) + extract(fs, child.toString()); + } } else { if (path.startsWith("/")) path = path.substring(1); Path dst = FileSystems.getDefault().getPath(path); Path parent = dst.getParent(); - if (parent.notExists()) + if (Files.notExists(parent)) mkdirs(parent); - src.copyTo(dst, REPLACE_EXISTING); + Files.copy(src, dst, REPLACE_EXISTING); } } @@ -445,21 +448,21 @@ public class Demo { Path srcPath = src.getPath(path); Path dstPath = dst.getPath(path); - if (Boolean.TRUE.equals(srcPath.getAttribute("isDirectory"))) { - if (!dstPath.exists()) { + if (Files.isDirectory(srcPath)) { + if (!Files.exists(dstPath)) { try { mkdirs(dstPath); } catch (FileAlreadyExistsException x) {} } - DirectoryStream ds = srcPath.newDirectoryStream(); - for (Path child : ds) { - z2zcopy(src, dst, - path + (path.endsWith("/")?"":"/") + child.getName()); + try (DirectoryStream ds = Files.newDirectoryStream(srcPath)) { + for (Path child : ds) { + z2zcopy(src, dst, + path + (path.endsWith("/")?"":"/") + child.getFileName()); + } } - ds.close(); } else { //System.out.println("copying..." + path); - srcPath.copyTo(dstPath); + Files.copy(srcPath, dstPath); } } @@ -480,9 +483,9 @@ public class Demo { dst = dstPath.resolve(dst); try { Path parent = dstPath.getParent(); - if (parent != null && parent.notExists()) + if (parent != null && Files.notExists(parent)) mkdirs(parent); - file.moveTo(dst); + Files.move(file, dst); } catch (IOException x) { x.printStackTrace(); } @@ -497,7 +500,7 @@ public class Demo { dst = dstPath.resolve(dst); try { - if (dst.notExists()) + if (Files.notExists(dst)) mkdirs(dst); } catch (IOException x) { x.printStackTrace(); @@ -511,7 +514,7 @@ public class Demo { throws IOException { try { - dir.delete(); + Files.delete(dir); } catch (IOException x) { //x.printStackTrace(); } @@ -525,15 +528,15 @@ public class Demo { path = path.toAbsolutePath(); Path parent = path.getParent(); if (parent != null) { - if (parent.notExists()) + if (Files.notExists(parent)) mkdirs(parent); } - path.createDirectory(); + Files.createDirectory(path); } private static void rmdirs(Path path) throws IOException { while (path != null && path.getNameCount() != 0) { - path.delete(); + Files.delete(path); path = path.getParent(); } } @@ -542,15 +545,15 @@ public class Demo { if (!"/".equals(path.toString())) { System.out.printf(" %s%n", path.toString()); if (verbose) - System.out.println(Attributes.readBasicFileAttributes(path).toString()); + System.out.println(Files.readAttributes(path, BasicFileAttributes.class).toString()); } - if (path.notExists()) + if (Files.notExists(path)) return; - if (Attributes.readBasicFileAttributes(path).isDirectory()) { - DirectoryStream ds = path.newDirectoryStream(); - for (Path child : ds) - list(child, verbose); - ds.close(); + if (Files.isDirectory(path)) { + try (DirectoryStream ds = Files.newDirectoryStream(path)) { + for (Path child : ds) + list(child, verbose); + } } } @@ -561,12 +564,11 @@ public class Demo { // src.toString(), dst.toString()); //streams - InputStream isSrc = src.newInputStream(); - InputStream isDst = dst.newInputStream(); byte[] bufSrc = new byte[8192]; byte[] bufDst = new byte[8192]; - - try { + try (InputStream isSrc = Files.newInputStream(src); + InputStream isDst = Files.newInputStream(dst)) + { int nSrc = 0; while ((nSrc = isSrc.read(bufSrc)) != -1) { int nDst = 0; @@ -588,24 +590,22 @@ public class Demo { nSrc--; } } - } finally { - isSrc.close(); - isDst.close(); } // channels - SeekableByteChannel chSrc = src.newByteChannel(); - SeekableByteChannel chDst = dst.newByteChannel(); - if (chSrc.size() != chDst.size()) { - System.out.printf("src[%s].size=%d, dst[%s].size=%d%n", - chSrc.toString(), chSrc.size(), - chDst.toString(), chDst.size()); - throw new RuntimeException("CHECK FAILED!"); - } - ByteBuffer bbSrc = ByteBuffer.allocate(8192); - ByteBuffer bbDst = ByteBuffer.allocate(8192); - try { + try (SeekableByteChannel chSrc = Files.newByteChannel(src); + SeekableByteChannel chDst = Files.newByteChannel(dst)) + { + if (chSrc.size() != chDst.size()) { + System.out.printf("src[%s].size=%d, dst[%s].size=%d%n", + chSrc.toString(), chSrc.size(), + chDst.toString(), chDst.size()); + throw new RuntimeException("CHECK FAILED!"); + } + ByteBuffer bbSrc = ByteBuffer.allocate(8192); + ByteBuffer bbDst = ByteBuffer.allocate(8192); + int nSrc = 0; while ((nSrc = chSrc.read(bbSrc)) != -1) { int nDst = chDst.read(bbDst); @@ -627,9 +627,6 @@ public class Demo { } } catch (IOException x) { x.printStackTrace(); - } finally { - chSrc.close(); - chDst.close(); } } @@ -641,23 +638,15 @@ public class Demo { openwrite.add(CREATE_NEW); openwrite.add(WRITE); - FileChannel srcFc = src.getFileSystem() - .provider() - .newFileChannel(src, read); - FileChannel dstFc = dst.getFileSystem() - .provider() - .newFileChannel(dst, openwrite); - - try { + try (FileChannel srcFc = src.getFileSystem().provider().newFileChannel(src, read); + FileChannel dstFc = dst.getFileSystem().provider().newFileChannel(dst, openwrite)) + { ByteBuffer bb = ByteBuffer.allocate(8192); while (srcFc.read(bb) >= 0) { bb.flip(); dstFc.write(bb); bb.clear(); } - } finally { - srcFc.close(); - dstFc.close(); } } @@ -669,35 +658,28 @@ public class Demo { openwrite.add(CREATE_NEW); openwrite.add(WRITE); - SeekableByteChannel srcCh = src.newByteChannel(read); - SeekableByteChannel dstCh = dst.newByteChannel(openwrite); - - try { + try (SeekableByteChannel srcCh = Files.newByteChannel(src, read); + SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite)) + { ByteBuffer bb = ByteBuffer.allocate(8192); while (srcCh.read(bb) >= 0) { bb.flip(); dstCh.write(bb); bb.clear(); } - } finally { - srcCh.close(); - dstCh.close(); } } private static void streamCopy(Path src, Path dst) throws IOException { - InputStream isSrc = src.newInputStream(); - OutputStream osDst = dst.newOutputStream(); byte[] buf = new byte[8192]; - try { + try (InputStream isSrc = Files.newInputStream(src); + OutputStream osDst = Files.newOutputStream(dst)) + { int n = 0; while ((n = isSrc.read(buf)) != -1) { osDst.write(buf, 0, n); } - } finally { - isSrc.close(); - osDst.close(); } } } diff --git a/jdk/src/share/demo/nio/zipfs/README.txt b/jdk/src/share/demo/nio/zipfs/README.txt index 9a216e48d70..e147b2900ec 100644 --- a/jdk/src/share/demo/nio/zipfs/README.txt +++ b/jdk/src/share/demo/nio/zipfs/README.txt @@ -5,9 +5,8 @@ The factory methods defined by the java.nio.file.FileSystems class can be used to create a FileSystem, eg: // use file type detection - Map env = Collections.emptyMap(); Path jarfile = Paths.get("foo.jar"); - FileSystem fs = FileSystems.newFileSystem(jarfile, env, null); + FileSystem fs = FileSystems.newFileSystem(jarfile, null); -or diff --git a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributeView.java b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributeView.java index 5c31ebe7ba6..22b183d97a7 100644 --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributeView.java +++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileAttributeView.java @@ -32,11 +32,10 @@ package com.sun.nio.zipfs; -import java.nio.file.attribute.BasicFileAttributeView; -import java.nio.file.attribute.FileAttributeView; -import java.nio.file.attribute.FileTime; +import java.nio.file.attribute.*; import java.io.IOException; import java.util.LinkedHashMap; +import java.util.Map; /* * @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal @@ -122,25 +121,19 @@ public class ZipFileAttributeView implements BasicFileAttributeView "' is unknown or read-only attribute"); } - public Object getAttribute(String attribute, boolean domap) + Map readAttributes(String attributes) throws IOException { ZipFileAttributes zfas = readAttributes(); - if (!domap) { - try { - return attribute(AttrID.valueOf(attribute), zfas); - } catch (IllegalArgumentException x) {} - return null; - } LinkedHashMap map = new LinkedHashMap<>(); - if ("*".equals(attribute)) { + if ("*".equals(attributes)) { for (AttrID id : AttrID.values()) { try { map.put(id.name(), attribute(id, zfas)); } catch (IllegalArgumentException x) {} } } else { - String[] as = attribute.split(","); + String[] as = attributes.split(","); for (String a : as) { try { map.put(a, attribute(AttrID.valueOf(a), zfas)); diff --git a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileStore.java b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileStore.java index 681509719e7..05719072de3 100644 --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileStore.java +++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileStore.java @@ -32,14 +32,13 @@ package com.sun.nio.zipfs; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.FileStore; import java.nio.file.FileSystems; import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileAttributeView; import java.nio.file.attribute.FileStoreAttributeView; -import java.nio.file.attribute.FileStoreSpaceAttributeView; -import java.nio.file.attribute.FileStoreSpaceAttributes; -import java.nio.file.attribute.Attributes; import java.nio.file.attribute.BasicFileAttributeView; import java.util.Formatter; @@ -87,71 +86,61 @@ public class ZipFileStore extends FileStore { public V getFileStoreAttributeView(Class type) { if (type == null) throw new NullPointerException(); - if (type == FileStoreSpaceAttributeView.class) - return (V) new ZipFileStoreAttributeView(this); - return null; + return (V)null; + } + + @Override + public long getTotalSpace() throws IOException { + return new ZipFileStoreAttributes(this).totalSpace(); + } + + @Override + public long getUsableSpace() throws IOException { + return new ZipFileStoreAttributes(this).usableSpace(); + } + + @Override + public long getUnallocatedSpace() throws IOException { + return new ZipFileStoreAttributes(this).unallocatedSpace(); } @Override public Object getAttribute(String attribute) throws IOException { - if (attribute.equals("space:totalSpace")) - return new ZipFileStoreAttributeView(this).readAttributes().totalSpace(); - if (attribute.equals("space:usableSpace")) - return new ZipFileStoreAttributeView(this).readAttributes().usableSpace(); - if (attribute.equals("space:unallocatedSpace")) - return new ZipFileStoreAttributeView(this).readAttributes().unallocatedSpace(); + if (attribute.equals("totalSpace")) + return getTotalSpace(); + if (attribute.equals("usableSpace")) + return getUsableSpace(); + if (attribute.equals("unallocatedSpace")) + return getUnallocatedSpace(); throw new UnsupportedOperationException("does not support the given attribute"); } - private static class ZipFileStoreAttributeView implements FileStoreSpaceAttributeView { + private static class ZipFileStoreAttributes { + final FileStore fstore; + final long size; - private final ZipFileStore fileStore; - - public ZipFileStoreAttributeView(ZipFileStore fileStore) { - this.fileStore = fileStore; + public ZipFileStoreAttributes(ZipFileStore fileStore) + throws IOException + { + Path path = FileSystems.getDefault().getPath(fileStore.name()); + this.size = Files.size(path); + this.fstore = Files.getFileStore(path); } - @Override - public String name() { - return "space"; + public long totalSpace() { + return size; } - @Override - public FileStoreSpaceAttributes readAttributes() throws IOException { - final String file = fileStore.name(); - Path path = FileSystems.getDefault().getPath(file); - final long size = Attributes.readBasicFileAttributes(path).size(); - final FileStore fstore = path.getFileStore(); - final FileStoreSpaceAttributes fstoreAttrs = - Attributes.readFileStoreSpaceAttributes(fstore); - return new FileStoreSpaceAttributes() { - public long totalSpace() { - return size; - } + public long usableSpace() throws IOException { + if (!fstore.isReadOnly()) + return fstore.getUsableSpace(); + return 0; + } - public long usableSpace() { - if (!fstore.isReadOnly()) - return fstoreAttrs.usableSpace(); - return 0; - } - - public long unallocatedSpace() { - if (!fstore.isReadOnly()) - return fstoreAttrs.unallocatedSpace(); - return 0; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - Formatter fm = new Formatter(sb); - fm.format("FileStoreSpaceAttributes[%s]%n", file); - fm.format(" totalSpace: %d%n", totalSpace()); - fm.format(" usableSpace: %d%n", usableSpace()); - fm.format(" unallocSpace: %d%n", unallocatedSpace()); - fm.close(); - return sb.toString(); - } - }; + public long unallocatedSpace() throws IOException { + if (!fstore.isReadOnly()) + return fstore.getUnallocatedSpace(); + return 0; } } } diff --git a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java index 1cd59db8bc1..40afd8afb84 100644 --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java +++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java @@ -101,24 +101,25 @@ public class ZipFileSystem extends FileSystem { this.provider = provider; this.zfpath = zfpath; - if (zfpath.notExists()) { + if (Files.notExists(zfpath)) { if (createNew) { - OutputStream os = zfpath.newOutputStream(CREATE_NEW, WRITE); - new END().write(os, 0); - os.close(); + try (OutputStream os = Files.newOutputStream(zfpath, CREATE_NEW, WRITE)) { + new END().write(os, 0); + } } else { throw new FileSystemNotFoundException(zfpath.toString()); } } - zfpath.checkAccess(AccessMode.READ); // sm and existence check + // sm and existence check + zfpath.getFileSystem().provider().checkAccess(zfpath, AccessMode.READ); try { - zfpath.checkAccess(AccessMode.WRITE); + zfpath.getFileSystem().provider().checkAccess(zfpath, AccessMode.WRITE); } catch (AccessDeniedException x) { this.readOnly = true; } this.zc = ZipCoder.get(nameEncoding); this.defaultdir = new ZipPath(this, getBytes(defaultDir)); - this.ch = zfpath.newByteChannel(READ); + this.ch = Files.newByteChannel(zfpath, READ); this.cen = initCEN(); } @@ -159,9 +160,22 @@ public class ZipFileSystem extends FileSystem { } @Override - public ZipPath getPath(String path) { - if (path.length() == 0) - throw new InvalidPathException(path, "path should not be empty"); + public ZipPath getPath(String first, String... more) { + String path; + if (more.length == 0) { + path = first; + } else { + StringBuilder sb = new StringBuilder(); + sb.append(first); + for (String segment: more) { + if (segment.length() > 0) { + if (sb.length() > 0) + sb.append('/'); + sb.append(segment); + } + } + path = sb.toString(); + } return new ZipPath(this, getBytes(path)); } @@ -268,16 +282,22 @@ public class ZipFileSystem extends FileSystem { def.end(); } + IOException ioe = null; synchronized (tmppaths) { for (Path p: tmppaths) { try { - p.deleteIfExists(); + Files.deleteIfExists(p); } catch (IOException x) { - x.printStackTrace(); + if (ioe == null) + ioe = x; + else + ioe.addSuppressed(x); } } } - provider.removeFileSystem(zfpath); + provider.removeFileSystem(zfpath, this); + if (ioe != null) + throw ioe; } ZipFileAttributes getFileAttributes(byte[] path) @@ -444,7 +464,7 @@ public class ZipFileSystem extends FileSystem { u.bytes = Arrays.copyOf(eSrc.bytes, eSrc.bytes.length); else if (eSrc.file != null) { u.file = getTempPathForEntry(null); - eSrc.file.copyTo(u.file, REPLACE_EXISTING); + Files.copy(eSrc.file, u.file, REPLACE_EXISTING); } } } @@ -778,7 +798,8 @@ public class ZipFileSystem extends FileSystem { fch.close(); if (forWrite) { u.mtime = System.currentTimeMillis(); - u.size = Attributes.readBasicFileAttributes(u.file).size(); + u.size = Files.size(u.file); + update(u); } else { if (!isFCH) // if this is a new fch for reading @@ -805,13 +826,8 @@ public class ZipFileSystem extends FileSystem { if (path != null) { Entry e = getEntry0(path); if (e != null) { - InputStream is = newInputStream(path); - OutputStream os = tmpPath.newOutputStream(WRITE); - try { - copyStream(is, os); - } finally { - is.close(); - os.close(); + try (InputStream is = newInputStream(path)) { + Files.copy(is, tmpPath, REPLACE_EXISTING); } } } @@ -819,7 +835,7 @@ public class ZipFileSystem extends FileSystem { } private void removeTempPathForEntry(Path path) throws IOException { - path.delete(); + Files.delete(path); tmppaths.remove(path); } @@ -1073,11 +1089,11 @@ public class ZipFileSystem extends FileSystem { // shared key. consumer guarantees the "writeLock" before use it. private final IndexNode LOOKUPKEY = IndexNode.keyOf(null); - private void updateDelete(Entry e) { + private void updateDelete(IndexNode inode) { beginWrite(); try { - removeFromTree(e); - inodes.remove(e); + removeFromTree(inode); + inodes.remove(inode); hasUpdate = true; } finally { endWrite(); @@ -1158,7 +1174,7 @@ public class ZipFileSystem extends FileSystem { for (ExChannelCloser ecc : exChClosers) { if (ecc.streams.isEmpty()) { ecc.ch.close(); - ecc.path.delete(); + Files.delete(ecc.path); exChClosers.remove(ecc); } } @@ -1166,7 +1182,7 @@ public class ZipFileSystem extends FileSystem { if (!hasUpdate) return; Path tmpFile = createTempFileInSameDirectoryAs(zfpath); - OutputStream os = tmpFile.newOutputStream(WRITE); + OutputStream os = Files.newOutputStream(tmpFile, WRITE); ArrayList elist = new ArrayList<>(inodes.size()); long written = 0; byte[] buf = new byte[8192]; @@ -1191,26 +1207,26 @@ public class ZipFileSystem extends FileSystem { os.write(e.bytes); // already written += e.bytes.length; } else if (e.file != null) { // tmp file - InputStream is = e.file.newInputStream(); - int n; - if (e.type == Entry.NEW) { // deflated already - while ((n = is.read(buf)) != -1) { - os.write(buf, 0, n); - written += n; + try (InputStream is = Files.newInputStream(e.file)) { + int n; + if (e.type == Entry.NEW) { // deflated already + while ((n = is.read(buf)) != -1) { + os.write(buf, 0, n); + written += n; + } + } else if (e.type == Entry.FILECH) { + // the data are not deflated, use ZEOS + try (OutputStream os2 = new EntryOutputStream(e, os)) { + while ((n = is.read(buf)) != -1) { + os2.write(buf, 0, n); + } + } + written += e.csize; + if ((e.flag & FLAG_DATADESCR) != 0) + written += e.writeEXT(os); } - } else if (e.type == Entry.FILECH) { - // the data are not deflated, use ZEOS - OutputStream os2 = new EntryOutputStream(e, os); - while ((n = is.read(buf)) != -1) { - os2.write(buf, 0, n); - } - os2.close(); - written += e.csize; - if ((e.flag & FLAG_DATADESCR) != 0) - written += e.writeEXT(os); } - is.close(); - e.file.delete(); + Files.delete(e.file); tmppaths.remove(e.file); } else { // dir, 0-length data @@ -1257,15 +1273,15 @@ public class ZipFileSystem extends FileSystem { createTempFileInSameDirectoryAs(zfpath), ch, streams); - zfpath.moveTo(ecc.path, REPLACE_EXISTING); + Files.move(zfpath, ecc.path, REPLACE_EXISTING); exChClosers.add(ecc); streams = Collections.synchronizedSet(new HashSet()); } else { ch.close(); - zfpath.delete(); + Files.delete(zfpath); } - tmpFile.moveTo(zfpath, REPLACE_EXISTING); + Files.move(tmpFile, zfpath, REPLACE_EXISTING); hasUpdate = false; // clear /* if (isOpen) { @@ -1304,16 +1320,17 @@ public class ZipFileSystem extends FileSystem { throws IOException { checkWritable(); - Entry e = getEntry0(path); - if (e == null) { + + IndexNode inode = getInode(path); + if (inode == null) { if (path != null && path.length == 0) throw new ZipException("root directory can't not be delete"); if (failIfNotExists) throw new NoSuchFileException(getString(path)); } else { - if (e.isDir() && e.child != null) + if (inode.isDir() && inode.child != null) throw new DirectoryNotEmptyException(getString(path)); - updateDelete(e); + updateDelete(inode); } } @@ -1343,7 +1360,7 @@ public class ZipFileSystem extends FileSystem { OutputStream os; if (useTempFile) { e.file = getTempPathForEntry(null); - os = e.file.newOutputStream(WRITE); + os = Files.newOutputStream(e.file, WRITE); } else { os = new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192); } @@ -1359,12 +1376,12 @@ public class ZipFileSystem extends FileSystem { if (e.bytes != null) eis = new ByteArrayInputStream(e.bytes); else if (e.file != null) - eis = e.file.newInputStream(); + eis = Files.newInputStream(e.file); else throw new ZipException("update entry data is missing"); } else if (e.type == Entry.FILECH) { // FILECH result is un-compressed. - eis = e.file.newInputStream(); + eis = Files.newInputStream(e.file); // TBD: wrap to hook close() // streams.add(eis); return eis; diff --git a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystemProvider.java b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystemProvider.java index cf39b07cae7..60c8fed9291 100644 --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystemProvider.java +++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystemProvider.java @@ -31,23 +31,18 @@ package com.sun.nio.zipfs; -import java.io.IOException; -import java.nio.channels.FileChannel; -import java.nio.file.FileRef; -import java.nio.file.FileSystem; -import java.nio.file.FileSystemNotFoundException; -import java.nio.file.FileSystemAlreadyExistsException; -import java.nio.file.OpenOption; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.ProviderMismatchException; -import java.nio.file.attribute.FileAttribute; +import java.io.*; +import java.nio.channels.*; +import java.nio.file.*; +import java.nio.file.DirectoryStream.Filter; +import java.nio.file.attribute.*; import java.nio.file.spi.FileSystemProvider; import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.concurrent.ExecutorService; /* * @@ -87,28 +82,25 @@ public class ZipFileSystemProvider extends FileSystemProvider { public FileSystem newFileSystem(URI uri, Map env) throws IOException { - return newFileSystem(uriToPath(uri), env); + return newFileSystem(uriToPath(uri), env, true); } @Override - public FileSystem newFileSystem(FileRef file, Map env) + public FileSystem newFileSystem(Path path, Map env) throws IOException { - if (!(file instanceof Path)) - throw new UnsupportedOperationException(); - Path path = (Path)file; if (!path.toUri().getScheme().equalsIgnoreCase("file")) { throw new UnsupportedOperationException(); } - return newFileSystem(path, env); + return newFileSystem(path, env, false); } - private FileSystem newFileSystem(Path path, Map env) + private FileSystem newFileSystem(Path path, Map env, boolean checkIfFSExists) throws IOException { synchronized(filesystems) { Path realPath = null; - if (path.exists()) { + if (checkIfFSExists && Files.exists(path)) { realPath = path.toRealPath(true); if (filesystems.containsKey(realPath)) throw new FileSystemAlreadyExistsException(); @@ -116,7 +108,8 @@ public class ZipFileSystemProvider extends FileSystemProvider { ZipFileSystem zipfs = new ZipFileSystem(this, path, env); if (realPath == null) realPath = path.toRealPath(true); - filesystems.put(realPath, zipfs); + if (!filesystems.containsKey(realPath)) + filesystems.put(realPath, zipfs); return zipfs; } } @@ -133,18 +126,6 @@ public class ZipFileSystemProvider extends FileSystemProvider { return getFileSystem(uri).getPath(spec.substring(sep + 1)); } - @Override - public FileChannel newFileChannel(Path path, - Set options, - FileAttribute... attrs) - throws IOException - { - if (path == null) - throw new NullPointerException("path is null"); - if (path instanceof ZipPath) - return ((ZipPath)path).newFileChannel(options, attrs); - throw new ProviderMismatchException(); - } @Override public FileSystem getFileSystem(URI uri) { @@ -161,9 +142,155 @@ public class ZipFileSystemProvider extends FileSystemProvider { } } - void removeFileSystem(Path zfpath) throws IOException { + // Checks that the given file is a UnixPath + static final ZipPath toZipPath(Path path) { + if (path == null) + throw new NullPointerException(); + if (!(path instanceof ZipPath)) + throw new ProviderMismatchException(); + return (ZipPath)path; + } + + @Override + public void checkAccess(Path path, AccessMode... modes) throws IOException { + toZipPath(path).checkAccess(modes); + } + + @Override + public void copy(Path src, Path target, CopyOption... options) + throws IOException + { + toZipPath(src).copy(toZipPath(target), options); + } + + @Override + public void createDirectory(Path path, FileAttribute... attrs) + throws IOException + { + toZipPath(path).createDirectory(attrs); + } + + @Override + public final void delete(Path path) throws IOException { + toZipPath(path).delete(); + } + + @Override + @SuppressWarnings("unchecked") + public V + getFileAttributeView(Path path, Class type, LinkOption... options) + { + return (V)ZipFileAttributeView.get(toZipPath(path), type); + } + + @Override + public FileStore getFileStore(Path path) throws IOException { + return toZipPath(path).getFileStore(); + } + + @Override + public boolean isHidden(Path path) { + return toZipPath(path).isHidden(); + } + + @Override + public boolean isSameFile(Path path, Path other) throws IOException { + return toZipPath(path).isSameFile(other); + } + + @Override + public void move(Path src, Path target, CopyOption... options) + throws IOException + { + toZipPath(src).move(toZipPath(target), options); + } + + @Override + public AsynchronousFileChannel newAsynchronousFileChannel(Path path, + Set options, + ExecutorService exec, + FileAttribute... attrs) + throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public SeekableByteChannel newByteChannel(Path path, + Set options, + FileAttribute... attrs) + throws IOException + { + return toZipPath(path).newByteChannel(options, attrs); + } + + @Override + public DirectoryStream newDirectoryStream( + Path path, Filter filter) throws IOException + { + return toZipPath(path).newDirectoryStream(filter); + } + + @Override + public FileChannel newFileChannel(Path path, + Set options, + FileAttribute... attrs) + throws IOException + { + return toZipPath(path).newFileChannel(options, attrs); + } + + @Override + public InputStream newInputStream(Path path, OpenOption... options) + throws IOException + { + return toZipPath(path).newInputStream(options); + } + + @Override + public OutputStream newOutputStream(Path path, OpenOption... options) + throws IOException + { + return toZipPath(path).newOutputStream(options); + } + + @Override + public A + readAttributes(Path path, Class type, LinkOption... options) + throws IOException + { + if (type == BasicFileAttributes.class || type == ZipFileAttributes.class) + return (A)toZipPath(path).getAttributes(); + return null; + } + + @Override + public Map + readAttributes(Path path, String attribute, LinkOption... options) + throws IOException + { + return toZipPath(path).readAttributes(attribute, options); + } + + @Override + public Path readSymbolicLink(Path link) throws IOException { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public void setAttribute(Path path, String attribute, + Object value, LinkOption... options) + throws IOException + { + toZipPath(path).setAttribute(attribute, value, options); + } + + ////////////////////////////////////////////////////////////// + void removeFileSystem(Path zfpath, ZipFileSystem zfs) throws IOException { synchronized (filesystems) { - filesystems.remove(zfpath.toRealPath(true)); + zfpath = zfpath.toRealPath(true); + if (filesystems.get(zfpath) == zfs) + filesystems.remove(zfpath); } } } diff --git a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java index f1617db40d2..b03ba2929eb 100644 --- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java +++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java @@ -31,29 +31,23 @@ package com.sun.nio.zipfs; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; import java.net.URI; -import java.nio.channels.FileChannel; -import java.nio.channels.SeekableByteChannel; +import java.nio.channels.*; import java.nio.file.*; import java.nio.file.DirectoryStream.Filter; -import java.nio.file.attribute.BasicFileAttributeView; -import java.nio.file.attribute.FileAttribute; -import java.nio.file.attribute.FileAttributeView; -import java.nio.file.attribute.FileTime; +import java.nio.file.attribute.*; import java.util.*; import static java.nio.file.StandardOpenOption.*; import static java.nio.file.StandardCopyOption.*; + /** * * @author Xueming Shen, Rajendra Gutupalli,Jaya Hangal */ -public class ZipPath extends Path { +public class ZipPath implements Path { private final ZipFileSystem zfs; private final byte[] path; @@ -82,7 +76,7 @@ public class ZipPath extends Path { } @Override - public Path getName() { + public Path getFileName() { initOffsets(); int count = offsets.length; if (count == 0) @@ -162,8 +156,7 @@ public class ZipPath extends Path { return realPath; } - @Override - public boolean isHidden() { + boolean isHidden() { return false; } @@ -230,7 +223,7 @@ public class ZipPath extends Path { public Path relativize(Path other) { final ZipPath o = checkPath(other); if (o.equals(this)) - return null; + return new ZipPath(getFileSystem(), new byte[0], true); if (/* this.getFileSystem() != o.getFileSystem() || */ this.isAbsolute() != o.isAbsolute()) { throw new IllegalArgumentException(); @@ -272,13 +265,11 @@ public class ZipPath extends Path { @Override public boolean isAbsolute() { - return (this.path[0] == '/'); + return (this.path.length > 0 && path[0] == '/'); } @Override public ZipPath resolve(Path other) { - if (other == null) - return this; final ZipPath o = checkPath(other); if (o.isAbsolute()) return o; @@ -297,39 +288,70 @@ public class ZipPath extends Path { } @Override - public ZipPath resolve(String other) { - return resolve(getFileSystem().getPath(other)); + public Path resolveSibling(Path other) { + if (other == null) + throw new NullPointerException(); + Path parent = getParent(); + return (parent == null) ? other : parent.resolve(other); } @Override public boolean startsWith(Path other) { final ZipPath o = checkPath(other); - if (o.isAbsolute() != this.isAbsolute()) + if (o.isAbsolute() != this.isAbsolute() || + o.path.length > this.path.length) return false; - final int oCount = o.getNameCount(); - if (getNameCount() < oCount) - return false; - for (int i = 0; i < oCount; i++) { - if (!o.getName(i).equals(getName(i))) + int olast = o.path.length; + for (int i = 0; i < olast; i++) { + if (o.path[i] != this.path[i]) return false; } - return true; + olast--; + return o.path.length == this.path.length || + o.path[olast] == '/' || + this.path[olast + 1] == '/'; } @Override public boolean endsWith(Path other) { final ZipPath o = checkPath(other); - if (o.isAbsolute()) - return this.isAbsolute() ? this.equals(o) : false; - int i = o.getNameCount(); - int j = this.getNameCount(); - if (j < i) + int olast = o.path.length - 1; + if (olast > 0 && o.path[olast] == '/') + olast--; + int last = this.path.length - 1; + if (last > 0 && this.path[last] == '/') + last--; + if (olast == -1) // o.path.length == 0 + return last == -1; + if ((o.isAbsolute() &&(!this.isAbsolute() || olast != last)) || + (last < olast)) return false; - for (--i, --j; i >= 0; i--, j--) { - if (!o.getName(i).equals(this.getName(j))) + for (; olast >= 0; olast--, last--) { + if (o.path[olast] != this.path[last]) return false; } - return true; + return o.path[olast + 1] == '/' || + last == -1 || this.path[last] == '/'; + } + + @Override + public ZipPath resolve(String other) { + return resolve(getFileSystem().getPath(other)); + } + + @Override + public final Path resolveSibling(String other) { + return resolveSibling(getFileSystem().getPath(other)); + } + + @Override + public final boolean startsWith(String other) { + return startsWith(getFileSystem().getPath(other)); + } + + @Override + public final boolean endsWith(String other) { + return endsWith(getFileSystem().getPath(other)); } @Override @@ -337,8 +359,6 @@ public class ZipPath extends Path { byte[] resolved = getResolved(); if (resolved == path) // no change return this; - if (resolved.length == 0) - return null; return new ZipPath(zfs, resolved, true); } @@ -548,198 +568,6 @@ public class ZipPath extends Path { return len1 - len2; } - @Override - public Path createSymbolicLink( - Path target, FileAttribute... attrs) throws IOException { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public Path createLink( - Path existing) throws IOException { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public Path readSymbolicLink() throws IOException { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public Path createDirectory(FileAttribute... attrs) - throws IOException - { - zfs.createDirectory(getResolvedPath(), attrs); - return this; - } - - public final Path createFile(FileAttribute... attrs) - throws IOException - { - OutputStream os = newOutputStream(CREATE_NEW, WRITE); - try { - os.close(); - } catch (IOException x) {} - return this; - } - - @Override - public InputStream newInputStream(OpenOption... options) - throws IOException { - if (options.length > 0) { - for (OpenOption opt : options) { - if (opt != READ) - throw new UnsupportedOperationException("'" + opt + "' not allowed"); - } - } - return zfs.newInputStream(getResolvedPath()); - } - - private static final DirectoryStream.Filter acceptAllFilter = - new DirectoryStream.Filter<>() { - @Override public boolean accept(Path entry) { return true; } - }; - - @Override - public final DirectoryStream newDirectoryStream() throws IOException { - return newDirectoryStream(acceptAllFilter); - } - - @Override - public DirectoryStream newDirectoryStream(Filter filter) - throws IOException - { - return new ZipDirectoryStream(this, filter); - } - - @Override - public final DirectoryStream newDirectoryStream(String glob) - throws IOException - { - // avoid creating a matcher if all entries are required. - if (glob.equals("*")) - return newDirectoryStream(); - - // create a matcher and return a filter that uses it. - final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob); - DirectoryStream.Filter filter = new DirectoryStream.Filter<>() { - @Override - public boolean accept(Path entry) { - return matcher.matches(entry.getName()); - } - }; - return newDirectoryStream(filter); - } - - @Override - public final void delete() throws IOException { - zfs.deleteFile(getResolvedPath(), true); - } - - @Override - public final void deleteIfExists() throws IOException { - zfs.deleteFile(getResolvedPath(), false); - } - - ZipFileAttributes getAttributes() throws IOException - { - ZipFileAttributes zfas = zfs.getFileAttributes(getResolvedPath()); - if (zfas == null) - throw new NoSuchFileException(toString()); - return zfas; - } - - @Override - @SuppressWarnings("unchecked") - public V getFileAttributeView(Class type, - LinkOption... options) - { - return (V)ZipFileAttributeView.get(this, type); - } - - @Override - public void setAttribute(String attribute, - Object value, - LinkOption... options) - throws IOException - { - String type = null; - String attr = null; - int colonPos = attribute.indexOf(':'); - if (colonPos == -1) { - type = "basic"; - attr = attribute; - } else { - type = attribute.substring(0, colonPos++); - attr = attribute.substring(colonPos); - } - ZipFileAttributeView view = ZipFileAttributeView.get(this, type); - if (view == null) - throw new UnsupportedOperationException("view <" + view + "> is not supported"); - view.setAttribute(attr, value); - } - - void setTimes(FileTime mtime, FileTime atime, FileTime ctime) - throws IOException - { - zfs.setTimes(getResolvedPath(), mtime, atime, ctime); - } - - private Object getAttributesImpl(String attribute, boolean domap) - throws IOException - { - String view = null; - String attr = null; - int colonPos = attribute.indexOf(':'); - if (colonPos == -1) { - view = "basic"; - attr = attribute; - } else { - view = attribute.substring(0, colonPos++); - attr = attribute.substring(colonPos); - } - ZipFileAttributeView zfv = ZipFileAttributeView.get(this, view); - if (zfv == null) { - throw new UnsupportedOperationException("view not supported"); - } - return zfv.getAttribute(attr, domap); - } - - @Override - public Object getAttribute(String attribute, LinkOption... options) - throws IOException - { - return getAttributesImpl(attribute, false); - } - - @Override - public Map readAttributes(String attribute, LinkOption... options) - throws IOException - { - return (Map)getAttributesImpl(attribute, true); - } - - @Override - public FileStore getFileStore() throws IOException { - // each ZipFileSystem only has one root (as requested for now) - if (exists()) - return zfs.getFileStore(this); - throw new NoSuchFileException(zfs.getString(path)); - } - - @Override - public boolean isSameFile(Path other) throws IOException { - if (this.equals(other)) - return true; - if (other == null || - this.getFileSystem() != other.getFileSystem()) - return false; - this.checkAccess(); - other.checkAccess(); - return Arrays.equals(this.getResolvedPath(), - ((ZipPath)other).getResolvedPath()); - } - public WatchKey register( WatchService watcher, WatchEvent.Kind[] events, @@ -755,6 +583,11 @@ public class ZipPath extends Path { return register(watcher, events, new WatchEvent.Modifier[0]); } + @Override + public final File toFile() { + throw new UnsupportedOperationException(); + } + @Override public Iterator iterator() { return new Iterator<>() { @@ -783,9 +616,115 @@ public class ZipPath extends Path { }; } - @Override - public SeekableByteChannel newByteChannel(Set options, - FileAttribute... attrs) + ///////////////////////////////////////////////////////////////////// + + + void createDirectory(FileAttribute... attrs) + throws IOException + { + zfs.createDirectory(getResolvedPath(), attrs); + } + + InputStream newInputStream(OpenOption... options) throws IOException + { + if (options.length > 0) { + for (OpenOption opt : options) { + if (opt != READ) + throw new UnsupportedOperationException("'" + opt + "' not allowed"); + } + } + return zfs.newInputStream(getResolvedPath()); + } + + DirectoryStream newDirectoryStream(Filter filter) + throws IOException + { + return new ZipDirectoryStream(this, filter); + } + + void delete() throws IOException { + zfs.deleteFile(getResolvedPath(), true); + } + + void deleteIfExists() throws IOException { + zfs.deleteFile(getResolvedPath(), false); + } + + ZipFileAttributes getAttributes() throws IOException + { + ZipFileAttributes zfas = zfs.getFileAttributes(getResolvedPath()); + if (zfas == null) + throw new NoSuchFileException(toString()); + return zfas; + } + + void setAttribute(String attribute, Object value, LinkOption... options) + throws IOException + { + String type = null; + String attr = null; + int colonPos = attribute.indexOf(':'); + if (colonPos == -1) { + type = "basic"; + attr = attribute; + } else { + type = attribute.substring(0, colonPos++); + attr = attribute.substring(colonPos); + } + ZipFileAttributeView view = ZipFileAttributeView.get(this, type); + if (view == null) + throw new UnsupportedOperationException("view <" + view + "> is not supported"); + view.setAttribute(attr, value); + } + + void setTimes(FileTime mtime, FileTime atime, FileTime ctime) + throws IOException + { + zfs.setTimes(getResolvedPath(), mtime, atime, ctime); + } + + Map readAttributes(String attributes, LinkOption... options) + throws IOException + + { + String view = null; + String attrs = null; + int colonPos = attributes.indexOf(':'); + if (colonPos == -1) { + view = "basic"; + attrs = attributes; + } else { + view = attributes.substring(0, colonPos++); + attrs = attributes.substring(colonPos); + } + ZipFileAttributeView zfv = ZipFileAttributeView.get(this, view); + if (zfv == null) { + throw new UnsupportedOperationException("view not supported"); + } + return zfv.readAttributes(attrs); + } + + FileStore getFileStore() throws IOException { + // each ZipFileSystem only has one root (as requested for now) + if (exists()) + return zfs.getFileStore(this); + throw new NoSuchFileException(zfs.getString(path)); + } + + boolean isSameFile(Path other) throws IOException { + if (this.equals(other)) + return true; + if (other == null || + this.getFileSystem() != other.getFileSystem()) + return false; + this.checkAccess(); + ((ZipPath)other).checkAccess(); + return Arrays.equals(this.getResolvedPath(), + ((ZipPath)other).getResolvedPath()); + } + + SeekableByteChannel newByteChannel(Set options, + FileAttribute... attrs) throws IOException { return zfs.newByteChannel(getResolvedPath(), options, attrs); @@ -799,16 +738,7 @@ public class ZipPath extends Path { return zfs.newFileChannel(getResolvedPath(), options, attrs); } - @Override - public SeekableByteChannel newByteChannel(OpenOption... options) - throws IOException { - Set set = new HashSet<>(options.length); - Collections.addAll(set, options); - return newByteChannel(set); - } - - @Override - public void checkAccess(AccessMode... modes) throws IOException { + void checkAccess(AccessMode... modes) throws IOException { boolean w = false; boolean x = false; for (AccessMode mode : modes) { @@ -834,11 +764,9 @@ public class ZipPath extends Path { } if (x) throw new AccessDeniedException(toString()); - } - @Override - public boolean exists() { + boolean exists() { if (path.length == 1 && path[0] == '/') return true; try { @@ -847,15 +775,7 @@ public class ZipPath extends Path { return false; } - @Override - public boolean notExists() { - return !exists(); - } - - - @Override - public OutputStream newOutputStream(OpenOption... options) - throws IOException + OutputStream newOutputStream(OpenOption... options) throws IOException { if (options.length == 0) return zfs.newOutputStream(getResolvedPath(), @@ -863,42 +783,32 @@ public class ZipPath extends Path { return zfs.newOutputStream(getResolvedPath(), options); } - @Override - public Path moveTo(Path target, CopyOption... options) + void move(ZipPath target, CopyOption... options) throws IOException { - if (this.zfs.provider() == target.getFileSystem().provider() && - this.zfs.getZipFile().isSameFile(((ZipPath)target).zfs.getZipFile())) + if (Files.isSameFile(this.zfs.getZipFile(), target.zfs.getZipFile())) { zfs.copyFile(true, - getResolvedPath(), - ((ZipPath)target).getResolvedPath(), + getResolvedPath(), target.getResolvedPath(), options); } else { copyToTarget(target, options); delete(); } - return target; } - @Override - public Path copyTo(Path target, CopyOption... options) + void copy(ZipPath target, CopyOption... options) throws IOException { - if (this.zfs.provider() == target.getFileSystem().provider() && - this.zfs.getZipFile().isSameFile(((ZipPath)target).zfs.getZipFile())) - { + if (Files.isSameFile(this.zfs.getZipFile(), target.zfs.getZipFile())) zfs.copyFile(false, - getResolvedPath(), - ((ZipPath)target).getResolvedPath(), + getResolvedPath(), target.getResolvedPath(), options); - } else { + else copyToTarget(target, options); - } - return target; } - private void copyToTarget(Path target, CopyOption... options) + private void copyToTarget(ZipPath target, CopyOption... options) throws IOException { boolean replaceExisting = false; @@ -948,7 +858,7 @@ public class ZipPath extends Path { } if (copyAttrs) { BasicFileAttributeView view = - target.getFileAttributeView(BasicFileAttributeView.class); + ZipFileAttributeView.get(target, BasicFileAttributeView.class); try { view.setTimes(zfas.lastModifiedTime(), zfas.lastAccessTime(), diff --git a/jdk/src/share/demo/zipfs b/jdk/src/share/demo/zipfs deleted file mode 100644 index fd2ba7311b1..00000000000 --- a/jdk/src/share/demo/zipfs +++ /dev/null @@ -1,703 +0,0 @@ -/* - * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import java.io.*; -import java.nio.*; -import java.nio.channels.*; -import java.nio.file.*; -import java.nio.file.attribute.*; -import java.net.*; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.*; - -import static java.nio.file.StandardOpenOption.*; -import static java.nio.file.StandardCopyOption.*; - -/* - * ZipFileSystem usage demo - * - * java Demo action ZipfileName [...] - * - * @author Xueming Shen - */ - -public class Demo { - - static enum Action { - rename, // - // rename entry src to dst inside zipfile - - movein, // - // move an external src file into zipfile - // as entry dst - - moveout, // - // move a zipfile entry src out to dst - - copy, // - // copy entry src to dst inside zipfile - - copyin, // - // copy an external src file into zipfile - // as entry dst - - copyin_attrs, // - // copy an external src file into zipfile - // as entry dst, with attributes (timestamp) - - copyout, // - // copy zipfile entry src" out to file dst - - copyout_attrs, // - - zzmove, // - // move entry path/dir from zfsrc to zfdst - - zzcopy, // - // copy path from zipfile zfsrc to zipfile - // zfdst - - attrs, // - // printout the attributes of entry path - - attrsspace, // - // printout the storespace attrs of entry path - - setmtime, // - // set the lastModifiedTime of entry path - - setatime, // - setctime, // - - lsdir, // - // list dir's direct child files/dirs - - mkdir, // - - mkdirs, // - - rmdirs, // - - list, // - // recursively list all entries of dir - // via DirectoryStream - - tlist, // - // list with buildDirTree=true - - vlist, // - // recursively verbose list all entries of - // dir via DirectoryStream - - walk, // - // recursively walk all entries of dir - // via Files.walkFileTree - - twalk, // - // walk with buildDirTree=true - - extract, // - - update, // - - delete, // - - add, // - - create, // - // create a new zipfile if it doesn't exit - // and then add the file(s) into it. - - attrs2, // - // test different ways to print attrs - - prof, - } - - public static void main(String[] args) throws Throwable { - - Action action = Action.valueOf(args[0]); - Map env = env = new HashMap<>(); - if (action == Action.create) - env.put("create", "true"); - if (action == Action.tlist || action == Action.twalk) - env.put("buildDirTree", true); - FileSystem fs = FileSystems.newFileSystem(Paths.get(args[1]), env, null); - - try { - FileSystem fs2; - Path path, src, dst; - boolean isRename = false; - switch (action) { - case rename: - src = fs.getPath(args[2]); - dst = fs.getPath(args[3]); - src.moveTo(dst); - break; - case moveout: - src = fs.getPath(args[2]); - dst = Paths.get(args[3]); - src.moveTo(dst); - break; - case movein: - src = Paths.get(args[2]); - dst = fs.getPath(args[3]); - src.moveTo(dst); - break; - case copy: - src = fs.getPath(args[2]); - dst = fs.getPath(args[3]); - src.copyTo(dst); - break; - case copyout: - src = fs.getPath(args[2]); - dst = Paths.get(args[3]); - src.copyTo(dst); - break; - case copyin: - src = Paths.get(args[2]); - dst = fs.getPath(args[3]); - src.copyTo(dst); - break; - case copyin_attrs: - src = Paths.get(args[2]); - dst = fs.getPath(args[3]); - src.copyTo(dst, COPY_ATTRIBUTES); - break; - case copyout_attrs: - src = fs.getPath(args[2]); - dst = Paths.get(args[3]); - src.copyTo(dst, COPY_ATTRIBUTES); - break; - case zzmove: - fs2 = FileSystems.newFileSystem(Paths.get(args[2]), env, null); - //sf1.getPath(args[3]).moveTo(fs2.getPath(args[3])); - z2zmove(fs, fs2, args[3]); - fs2.close(); - break; - case zzcopy: - fs2 = FileSystems.newFileSystem(Paths.get(args[2]), env, null); - //sf1.getPath(args[3]).copyTo(fs2.getPath(args[3])); - z2zcopy(fs, fs2, args[3]); - fs2.close(); - break; - case attrs: - for (int i = 2; i < args.length; i++) { - path = fs.getPath(args[i]); - System.out.println(path); - System.out.println( - Attributes.readBasicFileAttributes(path).toString()); - } - break; - case setmtime: - DateFormat df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss"); - Date newDatetime = df.parse(args[2]); - for (int i = 3; i < args.length; i++) { - path = fs.getPath(args[i]); - path.setAttribute("lastModifiedTime", - FileTime.fromMillis(newDatetime.getTime())); - System.out.println( - Attributes.readBasicFileAttributes(path).toString()); - } - break; - case setctime: - df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss"); - newDatetime = df.parse(args[2]); - for (int i = 3; i < args.length; i++) { - path = fs.getPath(args[i]); - path.setAttribute("creationTime", - FileTime.fromMillis(newDatetime.getTime())); - System.out.println( - Attributes.readBasicFileAttributes(path).toString()); - } - break; - case setatime: - df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss"); - newDatetime = df.parse(args[2]); - for (int i = 3; i < args.length; i++) { - path = fs.getPath(args[i]); - path.setAttribute("lastAccessTime", - FileTime.fromMillis(newDatetime.getTime())); - System.out.println( - Attributes.readBasicFileAttributes(path).toString()); - } - break; - case attrsspace: - path = fs.getPath("/"); - FileStore fstore = path.getFileStore(); - //System.out.println(fstore.getFileStoreAttributeView(FileStoreSpaceAttributeView.class) - // .readAttributes()); - // or - System.out.printf("filestore[%s]%n", fstore.name()); - System.out.printf(" totalSpace: %d%n", - (Long)fstore.getAttribute("space:totalSpace")); - System.out.printf(" usableSpace: %d%n", - (Long)fstore.getAttribute("space:usableSpace")); - System.out.printf(" unallocSpace: %d%n", - (Long)fstore.getAttribute("space:unallocatedSpace")); - break; - case list: - case tlist: - if (args.length < 3) - list(fs.getPath("/"), false); - else - list(fs.getPath(args[2]), false); - break; - case vlist: - if (args.length < 3) - list(fs.getPath("/"), true); - else - list(fs.getPath(args[2]), true); - break; - case twalk: - case walk: - walk(fs.getPath((args.length > 2)? args[2] : "/")); - break; - case extract: - if (args.length == 2) { - extract(fs, "/"); - } else { - for (int i = 2; i < args.length; i++) { - extract(fs, args[i]); - } - } - break; - case delete: - for (int i = 2; i < args.length; i++) - fs.getPath(args[i]).delete(); - break; - case create: - case add: - case update: - for (int i = 2; i < args.length; i++) { - update(fs, args[i]); - } - break; - case lsdir: - path = fs.getPath(args[2]); - final String fStr = (args.length > 3)?args[3]:""; - DirectoryStream ds = path.newDirectoryStream( - new DirectoryStream.Filter() { - public boolean accept(Path path) { - return path.toString().contains(fStr); - } - }); - for (Path p : ds) - System.out.println(p); - break; - case mkdir: - fs.getPath(args[2]).createDirectory(); - break; - case mkdirs: - mkdirs(fs.getPath(args[2])); - break; - case attrs2: - for (int i = 2; i < args.length; i++) { - path = fs.getPath(args[i]); - System.out.printf("%n%s%n", path); - System.out.println("-------(1)---------"); - System.out.println( - Attributes.readBasicFileAttributes(path).toString()); - System.out.println("-------(2)---------"); - Map map = path.readAttributes("zip:*"); - for (Map.Entry e : map.entrySet()) { - System.out.printf(" %s : %s%n", e.getKey(), e.getValue()); - } - System.out.println("-------(3)---------"); - map = path.readAttributes("size,lastModifiedTime,isDirectory"); - for (Map.Entry e : map.entrySet()) { - System.out.printf(" %s : %s%n", e.getKey(), e.getValue()); - } - } - break; - case prof: - list(fs.getPath("/"), false); - while (true) { - Thread.sleep(10000); - //list(fs.getPath("/"), true); - System.out.println("sleeping..."); - } - } - } catch (Exception x) { - x.printStackTrace(); - } finally { - if (fs != null) - fs.close(); - } - } - - private static byte[] getBytes(String name) { - return name.getBytes(); - } - - private static String getString(byte[] name) { - return new String(name); - } - - private static void walk(Path path) throws IOException - { - Files.walkFileTree( - path, - new SimpleFileVisitor() { - private int indent = 0; - private void indent() { - int n = 0; - while (n++ < indent) - System.out.printf(" "); - } - - @Override - public FileVisitResult visitFile(Path file, - BasicFileAttributes attrs) - { - indent(); - System.out.printf("%s%n", file.getName().toString()); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult preVisitDirectory(Path dir, - BasicFileAttributes attrs) - { - indent(); - System.out.printf("[%s]%n", dir.toString()); - indent += 2; - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, - IOException ioe) - { - indent -= 2; - return FileVisitResult.CONTINUE; - } - }); - } - - private static void update(FileSystem fs, String path) throws Throwable{ - Path src = FileSystems.getDefault().getPath(path); - if (Boolean.TRUE.equals(src.getAttribute("isDirectory"))) { - DirectoryStream ds = src.newDirectoryStream(); - for (Path child : ds) - update(fs, child.toString()); - ds.close(); - } else { - Path dst = fs.getPath(path); - Path parent = dst.getParent(); - if (parent != null && parent.notExists()) - mkdirs(parent); - src.copyTo(dst, REPLACE_EXISTING); - } - } - - private static void extract(FileSystem fs, String path) throws Throwable{ - Path src = fs.getPath(path); - if (Boolean.TRUE.equals(src.getAttribute("isDirectory"))) { - DirectoryStream ds = src.newDirectoryStream(); - for (Path child : ds) - extract(fs, child.toString()); - ds.close(); - } else { - if (path.startsWith("/")) - path = path.substring(1); - Path dst = FileSystems.getDefault().getPath(path); - Path parent = dst.getParent(); - if (parent.notExists()) - mkdirs(parent); - src.copyTo(dst, REPLACE_EXISTING); - } - } - - // use DirectoryStream - private static void z2zcopy(FileSystem src, FileSystem dst, String path) - throws IOException - { - Path srcPath = src.getPath(path); - Path dstPath = dst.getPath(path); - - if (Boolean.TRUE.equals(srcPath.getAttribute("isDirectory"))) { - if (!dstPath.exists()) { - try { - mkdirs(dstPath); - } catch (FileAlreadyExistsException x) {} - } - DirectoryStream ds = srcPath.newDirectoryStream(); - for (Path child : ds) { - z2zcopy(src, dst, - path + (path.endsWith("/")?"":"/") + child.getName()); - } - ds.close(); - } else { - //System.out.println("copying..." + path); - srcPath.copyTo(dstPath); - } - } - - // use TreeWalk to move - private static void z2zmove(FileSystem src, FileSystem dst, String path) - throws IOException - { - final Path srcPath = src.getPath(path).toAbsolutePath(); - final Path dstPath = dst.getPath(path).toAbsolutePath(); - - Files.walkFileTree(srcPath, new SimpleFileVisitor() { - - @Override - public FileVisitResult visitFile(Path file, - BasicFileAttributes attrs) - { - Path dst = srcPath.relativize(file); - dst = dstPath.resolve(dst); - try { - Path parent = dstPath.getParent(); - if (parent != null && parent.notExists()) - mkdirs(parent); - file.moveTo(dst); - } catch (IOException x) { - x.printStackTrace(); - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult preVisitDirectory(Path dir, - BasicFileAttributes attrs) - { - Path dst = srcPath.relativize(dir); - dst = dstPath.resolve(dst); - try { - - if (dst.notExists()) - mkdirs(dst); - } catch (IOException x) { - x.printStackTrace(); - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, - IOException ioe) - throws IOException - { - try { - dir.delete(); - } catch (IOException x) { - //x.printStackTrace(); - } - return FileVisitResult.CONTINUE; - } - }); - - } - - private static void mkdirs(Path path) throws IOException { - path = path.toAbsolutePath(); - Path parent = path.getParent(); - if (parent != null) { - if (parent.notExists()) - mkdirs(parent); - } - path.createDirectory(); - } - - private static void rmdirs(Path path) throws IOException { - while (path != null && path.getNameCount() != 0) { - path.delete(); - path = path.getParent(); - } - } - - private static void list(Path path, boolean verbose ) throws IOException { - if (!"/".equals(path.toString())) { - System.out.printf(" %s%n", path.toString()); - if (verbose) - System.out.println(Attributes.readBasicFileAttributes(path).toString()); - } - if (path.notExists()) - return; - if (Attributes.readBasicFileAttributes(path).isDirectory()) { - DirectoryStream ds = path.newDirectoryStream(); - for (Path child : ds) - list(child, verbose); - ds.close(); - } - } - - // check the content of two paths are equal - private static void checkEqual(Path src, Path dst) throws IOException - { - //System.out.printf("checking <%s> vs <%s>...%n", - // src.toString(), dst.toString()); - - //streams - InputStream isSrc = src.newInputStream(); - InputStream isDst = dst.newInputStream(); - byte[] bufSrc = new byte[8192]; - byte[] bufDst = new byte[8192]; - - try { - int nSrc = 0; - while ((nSrc = isSrc.read(bufSrc)) != -1) { - int nDst = 0; - while (nDst < nSrc) { - int n = isDst.read(bufDst, nDst, nSrc - nDst); - if (n == -1) { - System.out.printf("checking <%s> vs <%s>...%n", - src.toString(), dst.toString()); - throw new RuntimeException("CHECK FAILED!"); - } - nDst += n; - } - while (--nSrc >= 0) { - if (bufSrc[nSrc] != bufDst[nSrc]) { - System.out.printf("checking <%s> vs <%s>...%n", - src.toString(), dst.toString()); - throw new RuntimeException("CHECK FAILED!"); - } - nSrc--; - } - } - } finally { - isSrc.close(); - isDst.close(); - } - - // channels - SeekableByteChannel chSrc = src.newByteChannel(); - SeekableByteChannel chDst = dst.newByteChannel(); - if (chSrc.size() != chDst.size()) { - System.out.printf("src[%s].size=%d, dst[%s].size=%d%n", - chSrc.toString(), chSrc.size(), - chDst.toString(), chDst.size()); - throw new RuntimeException("CHECK FAILED!"); - } - ByteBuffer bbSrc = ByteBuffer.allocate(8192); - ByteBuffer bbDst = ByteBuffer.allocate(8192); - - try { - int nSrc = 0; - while ((nSrc = chSrc.read(bbSrc)) != -1) { - int nDst = chDst.read(bbDst); - if (nSrc != nDst) { - System.out.printf("checking <%s> vs <%s>...%n", - src.toString(), dst.toString()); - throw new RuntimeException("CHECK FAILED!"); - } - while (--nSrc >= 0) { - if (bbSrc.get(nSrc) != bbDst.get(nSrc)) { - System.out.printf("checking <%s> vs <%s>...%n", - src.toString(), dst.toString()); - throw new RuntimeException("CHECK FAILED!"); - } - nSrc--; - } - bbSrc.flip(); - bbDst.flip(); - } - } catch (IOException x) { - x.printStackTrace(); - } finally { - chSrc.close(); - chDst.close(); - } - } - - private static void fchCopy(Path src, Path dst) throws IOException - { - Set read = new HashSet<>(); - read.add(READ); - Set openwrite = new HashSet<>(); - openwrite.add(CREATE_NEW); - openwrite.add(WRITE); - - FileChannel srcFc = src.getFileSystem() - .provider() - .newFileChannel(src, read); - FileChannel dstFc = dst.getFileSystem() - .provider() - .newFileChannel(dst, openwrite); - - try { - ByteBuffer bb = ByteBuffer.allocate(8192); - while (srcFc.read(bb) >= 0) { - bb.flip(); - dstFc.write(bb); - bb.clear(); - } - } finally { - srcFc.close(); - dstFc.close(); - } - } - - private static void chCopy(Path src, Path dst) throws IOException - { - Set read = new HashSet<>(); - read.add(READ); - Set openwrite = new HashSet<>(); - openwrite.add(CREATE_NEW); - openwrite.add(WRITE); - - SeekableByteChannel srcCh = src.newByteChannel(read); - SeekableByteChannel dstCh = dst.newByteChannel(openwrite); - - try { - ByteBuffer bb = ByteBuffer.allocate(8192); - while (srcCh.read(bb) >= 0) { - bb.flip(); - dstCh.write(bb); - bb.clear(); - } - } finally { - srcCh.close(); - dstCh.close(); - } - } - - private static void streamCopy(Path src, Path dst) throws IOException - { - InputStream isSrc = src.newInputStream(); - OutputStream osDst = dst.newOutputStream(); - byte[] buf = new byte[8192]; - try { - int n = 0; - while ((n = isSrc.read(buf)) != -1) { - osDst.write(buf, 0, n); - } - } finally { - isSrc.close(); - osDst.close(); - } - } -} diff --git a/jdk/src/share/native/java/io/io_util.c b/jdk/src/share/native/java/io/io_util.c index 4689ef72afa..68a24bbab53 100644 --- a/jdk/src/share/native/java/io/io_util.c +++ b/jdk/src/share/native/java/io/io_util.c @@ -44,7 +44,7 @@ readSingle(JNIEnv *env, jobject this, jfieldID fid) { JNU_ThrowIOException(env, "Stream Closed"); return -1; } - nread = IO_Read(fd, &ret, 1); + nread = (jint)IO_Read(fd, &ret, 1); if (nread == 0) { /* EOF */ return -1; } else if (nread == JVM_IO_ERR) { /* error */ @@ -108,7 +108,7 @@ readBytes(JNIEnv *env, jobject this, jbyteArray bytes, JNU_ThrowIOException(env, "Stream Closed"); nread = -1; } else { - nread = IO_Read(fd, buf, len); + nread = (jint)IO_Read(fd, buf, len); if (nread > 0) { (*env)->SetByteArrayRegion(env, bytes, off, nread, (jbyte *)buf); } else if (nread == JVM_IO_ERR) { @@ -137,9 +137,9 @@ writeSingle(JNIEnv *env, jobject this, jint byte, jboolean append, jfieldID fid) return; } if (append == JNI_TRUE) { - n = IO_Append(fd, &c, 1); + n = (jint)IO_Append(fd, &c, 1); } else { - n = IO_Write(fd, &c, 1); + n = (jint)IO_Write(fd, &c, 1); } if (n == JVM_IO_ERR) { JNU_ThrowIOExceptionWithLastError(env, "Write error"); @@ -190,9 +190,9 @@ writeBytes(JNIEnv *env, jobject this, jbyteArray bytes, break; } if (append == JNI_TRUE) { - n = IO_Append(fd, buf+off, len); + n = (jint)IO_Append(fd, buf+off, len); } else { - n = IO_Write(fd, buf+off, len); + n = (jint)IO_Write(fd, buf+off, len); } if (n == JVM_IO_ERR) { JNU_ThrowIOExceptionWithLastError(env, "Write error"); diff --git a/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp b/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp index 457fb058082..249d2e74ed1 100644 --- a/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp +++ b/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp @@ -38,7 +38,7 @@ extern "C" { /* * Throws an arbitrary Java exception. */ -void ThrowException(JNIEnv *env, char *exceptionName) +void ThrowException(JNIEnv *env, const char *exceptionName) { jclass exceptionClazz = env->FindClass(exceptionName); env->ThrowNew(exceptionClazz, NULL); @@ -89,7 +89,7 @@ JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair // Fill a new ECParams using the supplied OID if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) { /* bad curve OID */ - ThrowException(env, (char *) INVALID_ALGORITHM_PARAMETER_EXCEPTION); + ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION); goto cleanup; } @@ -101,7 +101,7 @@ JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair // Generate the new keypair (using the supplied seed) if (EC_NewKey(ecparams, &privKey, (unsigned char *) pSeedBuffer, jSeedLength, 0) != SECSuccess) { - ThrowException(env, (char *) KEY_EXCEPTION); + ThrowException(env, KEY_EXCEPTION); goto cleanup; } diff --git a/jdk/src/share/native/sun/security/ec/impl/ec.c b/jdk/src/share/native/sun/security/ec/impl/ec.c index 65a9b388e14..11777de8746 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ec.c +++ b/jdk/src/share/native/sun/security/ec/impl/ec.c @@ -51,12 +51,10 @@ * *********************************************************************** */ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "mplogic.h" #include "ec.h" #include "ecl.h" @@ -67,6 +65,7 @@ #include #ifndef _WIN32 +#include #include #endif /* _WIN32 */ @@ -116,7 +115,7 @@ ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2, ECGroup *group = NULL; SECStatus rv = SECFailure; mp_err err = MP_OKAY; - int len; + unsigned int len; #if EC_DEBUG int i; @@ -278,10 +277,6 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey, printf("ec_NewKey called\n"); #endif -#ifndef _WIN32 -int printf(); -#endif /* _WIN32 */ - if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; @@ -361,8 +356,9 @@ int printf(); cleanup: mp_clear(&k); - if (rv) + if (rv) { PORT_FreeArena(arena, PR_TRUE); + } #if EC_DEBUG printf("ec_NewKey returning %s\n", @@ -504,7 +500,7 @@ EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue, int kmflag) ECGroup *group = NULL; SECStatus rv = SECFailure; mp_err err = MP_OKAY; - int len; + unsigned int len; if (!ecParams || !publicValue) { PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -778,7 +774,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, /* In the definition of EC signing, digests are truncated * to the length of n in bits. * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/ - if (digest->len*8 > ecParams->fieldID.size) { + if (digest->len*8 > (unsigned int)ecParams->fieldID.size) { mpl_rsh(&s,&s,digest->len*8 - ecParams->fieldID.size); } @@ -993,7 +989,8 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, /* In the definition of EC signing, digests are truncated * to the length of n in bits. * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/ - if (digest->len*8 > ecParams->fieldID.size) { /* u1 = HASH(M') */ + /* u1 = HASH(M') */ + if (digest->len*8 > (unsigned int)ecParams->fieldID.size) { mpl_rsh(&u1,&u1,digest->len*8- ecParams->fieldID.size); } diff --git a/jdk/src/share/native/sun/security/ec/impl/ec.h b/jdk/src/share/native/sun/security/ec/impl/ec.h index e8d034ca493..f5f3d356e26 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ec.h +++ b/jdk/src/share/native/sun/security/ec/impl/ec.h @@ -57,8 +57,6 @@ #ifndef __ec_h_ #define __ec_h_ -#pragma ident "%Z%%M% %I% %E% SMI" - #define EC_DEBUG 0 #define EC_POINT_FORM_COMPRESSED_Y0 0x02 #define EC_POINT_FORM_COMPRESSED_Y1 0x03 diff --git a/jdk/src/share/native/sun/security/ec/impl/ec2.h b/jdk/src/share/native/sun/security/ec/impl/ec2.h index 6541f039d4c..e297a309218 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ec2.h +++ b/jdk/src/share/native/sun/security/ec/impl/ec2.h @@ -57,8 +57,6 @@ #ifndef _EC2_H #define _EC2_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecl-priv.h" /* Checks if point P(px, py) is at infinity. Uses affine coordinates. */ diff --git a/jdk/src/share/native/sun/security/ec/impl/ec2_163.c b/jdk/src/share/native/sun/security/ec/impl/ec2_163.c index 4aadc4e8d37..c1dc55dea35 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ec2_163.c +++ b/jdk/src/share/native/sun/security/ec/impl/ec2_163.c @@ -56,8 +56,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ec2.h" #include "mp_gf2m.h" #include "mp_gf2m-priv.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/ec2_193.c b/jdk/src/share/native/sun/security/ec/impl/ec2_193.c index ddaf97323f0..aa7f29f0823 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ec2_193.c +++ b/jdk/src/share/native/sun/security/ec/impl/ec2_193.c @@ -56,8 +56,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ec2.h" #include "mp_gf2m.h" #include "mp_gf2m-priv.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/ec2_233.c b/jdk/src/share/native/sun/security/ec/impl/ec2_233.c index 8e81c81ebb5..485b104ce2a 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ec2_233.c +++ b/jdk/src/share/native/sun/security/ec/impl/ec2_233.c @@ -56,8 +56,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ec2.h" #include "mp_gf2m.h" #include "mp_gf2m-priv.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/ec2_aff.c b/jdk/src/share/native/sun/security/ec/impl/ec2_aff.c index 2865b2826d3..f77eba3f499 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ec2_aff.c +++ b/jdk/src/share/native/sun/security/ec/impl/ec2_aff.c @@ -54,8 +54,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ec2.h" #include "mplogic.h" #include "mp_gf2m.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/ec2_mont.c b/jdk/src/share/native/sun/security/ec/impl/ec2_mont.c index 3f5faec42b4..eda921f3ff6 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ec2_mont.c +++ b/jdk/src/share/native/sun/security/ec/impl/ec2_mont.c @@ -56,8 +56,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ec2.h" #include "mplogic.h" #include "mp_gf2m.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/ec_naf.c b/jdk/src/share/native/sun/security/ec/impl/ec_naf.c index 2827d459b1a..e6307f0d108 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ec_naf.c +++ b/jdk/src/share/native/sun/security/ec/impl/ec_naf.c @@ -54,8 +54,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecl-priv.h" /* Returns 2^e as an integer. This is meant to be used for small powers of diff --git a/jdk/src/share/native/sun/security/ec/impl/ecc_impl.h b/jdk/src/share/native/sun/security/ec/impl/ecc_impl.h index 7d50aa199bb..23357ae8c42 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecc_impl.h +++ b/jdk/src/share/native/sun/security/ec/impl/ecc_impl.h @@ -51,15 +51,13 @@ * *********************************************************************** */ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. */ #ifndef _ECC_IMPL_H #define _ECC_IMPL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -82,6 +80,7 @@ typedef enum { B_FALSE, B_TRUE } boolean_t; typedef unsigned char uint8_t; typedef unsigned long ulong_t; typedef enum boolean { B_FALSE, B_TRUE } boolean_t; +#define strdup _strdup /* Replace POSIX name with ISO C++ name */ #endif /* _WIN32 */ #ifndef _KERNEL diff --git a/jdk/src/share/native/sun/security/ec/impl/ecdecode.c b/jdk/src/share/native/sun/security/ec/impl/ecdecode.c index 19c62403c64..826192161ee 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecdecode.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecdecode.c @@ -55,8 +55,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include #ifndef _WIN32 @@ -90,7 +88,7 @@ hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str, { int i = 0; int byteval = 0; - int tmp = strlen(str); + int tmp = (int)strlen(str); if ((tmp % 2) != 0) return NULL; @@ -134,7 +132,8 @@ gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params, /* 2 ['0'+'4'] + MAX_ECKEY_LEN * 2 [x,y] * 2 [hex string] + 1 ['\0'] */ char genenc[3 + 2 * 2 * MAX_ECKEY_LEN]; - if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve)) goto cleanup; + if (((int)name < ECCurve_noName) || (name > ECCurve_pastLastCurve)) + goto cleanup; params->name = name; curveParams = ecCurve_map[params->name]; CHECK_OK(curveParams); diff --git a/jdk/src/share/native/sun/security/ec/impl/ecl-curve.h b/jdk/src/share/native/sun/security/ec/impl/ecl-curve.h index c7683031c4a..865c3d49feb 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecl-curve.h +++ b/jdk/src/share/native/sun/security/ec/impl/ecl-curve.h @@ -57,8 +57,6 @@ #ifndef _ECL_CURVE_H #define _ECL_CURVE_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecl-exp.h" #ifndef _KERNEL #include diff --git a/jdk/src/share/native/sun/security/ec/impl/ecl-exp.h b/jdk/src/share/native/sun/security/ec/impl/ecl-exp.h index 4c7698d7b0c..51ed43fdbc2 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecl-exp.h +++ b/jdk/src/share/native/sun/security/ec/impl/ecl-exp.h @@ -57,8 +57,6 @@ #ifndef _ECL_EXP_H #define _ECL_EXP_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* Curve field type */ typedef enum { ECField_GFp, diff --git a/jdk/src/share/native/sun/security/ec/impl/ecl-priv.h b/jdk/src/share/native/sun/security/ec/impl/ecl-priv.h index 5b744c0917c..6b032eabecc 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecl-priv.h +++ b/jdk/src/share/native/sun/security/ec/impl/ecl-priv.h @@ -58,8 +58,6 @@ #ifndef _ECL_PRIV_H #define _ECL_PRIV_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecl.h" #include "mpi.h" #include "mplogic.h" @@ -90,6 +88,10 @@ s = ACCUM(w); \ cout = CARRYOUT(w); } +/* Handle case when carry-in value is zero */ +#define MP_ADD_CARRY_ZERO(a1, a2, s, cout) \ + MP_ADD_CARRY(a1, a2, s, 0, cout); + #define MP_SUB_BORROW(a1, a2, s, bin, bout) \ { mp_word w; \ w = ((mp_word)(a1)) - (a2) - (bin); \ @@ -111,6 +113,15 @@ s = sum += (cin); \ cout = tmp + (sum < (cin)); } +/* Handle case when carry-in value is zero */ +#define MP_ADD_CARRY_ZERO(a1, a2, s, cout) \ + { mp_digit tmp,sum; \ + tmp = (a1); \ + sum = tmp + (a2); \ + tmp = (sum < tmp); /* detect overflow */ \ + s = sum; \ + cout = tmp; } + #define MP_SUB_BORROW(a1, a2, s, bin, bout) \ { mp_digit tmp; \ tmp = (a1); \ diff --git a/jdk/src/share/native/sun/security/ec/impl/ecl.c b/jdk/src/share/native/sun/security/ec/impl/ecl.c index 3c609ead783..79c5467cf07 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecl.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecl.c @@ -54,8 +54,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "mpi.h" #include "mplogic.h" #include "ecl.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/ecl.h b/jdk/src/share/native/sun/security/ec/impl/ecl.h index d5143ad6673..ab956d89fbc 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecl.h +++ b/jdk/src/share/native/sun/security/ec/impl/ecl.h @@ -57,8 +57,6 @@ #ifndef _ECL_H #define _ECL_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* Although this is not an exported header file, code which uses elliptic * curve point operations will need to include it. */ diff --git a/jdk/src/share/native/sun/security/ec/impl/ecl_curve.c b/jdk/src/share/native/sun/security/ec/impl/ecl_curve.c index f25732a9c46..a253a363f6a 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecl_curve.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecl_curve.c @@ -54,8 +54,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecl.h" #include "ecl-curve.h" #include "ecl-priv.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/ecl_gf.c b/jdk/src/share/native/sun/security/ec/impl/ecl_gf.c index a478b58236f..46b8dff0295 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecl_gf.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecl_gf.c @@ -55,8 +55,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "mpi.h" #include "mp_gf2m.h" #include "ecl-priv.h" @@ -307,7 +305,7 @@ ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r, } #ifndef MPI_AMD64_ADD - MP_ADD_CARRY(a0, r0, r0, 0, carry); + MP_ADD_CARRY_ZERO(a0, r0, r0, carry); MP_ADD_CARRY(a1, r1, r1, carry, carry); MP_ADD_CARRY(a2, r2, r2, carry, carry); #else @@ -394,7 +392,7 @@ ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r, } #ifndef MPI_AMD64_ADD - MP_ADD_CARRY(a0, r0, r0, 0, carry); + MP_ADD_CARRY_ZERO(a0, r0, r0, carry); MP_ADD_CARRY(a1, r1, r1, carry, carry); MP_ADD_CARRY(a2, r2, r2, carry, carry); MP_ADD_CARRY(a3, r3, r3, carry, carry); @@ -491,7 +489,7 @@ ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r, r0 = MP_DIGIT(b,0); } - MP_ADD_CARRY(a0, r0, r0, 0, carry); + MP_ADD_CARRY_ZERO(a0, r0, r0, carry); MP_ADD_CARRY(a1, r1, r1, carry, carry); MP_ADD_CARRY(a2, r2, r2, carry, carry); MP_ADD_CARRY(a3, r3, r3, carry, carry); @@ -572,7 +570,7 @@ ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r, r0 = MP_DIGIT(b,0); } - MP_ADD_CARRY(a0, r0, r0, 0, carry); + MP_ADD_CARRY_ZERO(a0, r0, r0, carry); MP_ADD_CARRY(a1, r1, r1, carry, carry); MP_ADD_CARRY(a2, r2, r2, carry, carry); MP_ADD_CARRY(a3, r3, r3, carry, carry); @@ -675,7 +673,7 @@ ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r, b1 = MP_DIGIT(&meth->irr,1); b0 = MP_DIGIT(&meth->irr,0); #ifndef MPI_AMD64_ADD - MP_ADD_CARRY(b0, r0, r0, 0, borrow); + MP_ADD_CARRY_ZERO(b0, r0, r0, borrow); MP_ADD_CARRY(b1, r1, r1, borrow, borrow); MP_ADD_CARRY(b2, r2, r2, borrow, borrow); #else @@ -766,7 +764,7 @@ ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r, b1 = MP_DIGIT(&meth->irr,1); b0 = MP_DIGIT(&meth->irr,0); #ifndef MPI_AMD64_ADD - MP_ADD_CARRY(b0, r0, r0, 0, borrow); + MP_ADD_CARRY_ZERO(b0, r0, r0, borrow); MP_ADD_CARRY(b1, r1, r1, borrow, borrow); MP_ADD_CARRY(b2, r2, r2, borrow, borrow); MP_ADD_CARRY(b3, r3, r3, borrow, borrow); @@ -850,7 +848,7 @@ ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r, b2 = MP_DIGIT(&meth->irr,2); b1 = MP_DIGIT(&meth->irr,1); b0 = MP_DIGIT(&meth->irr,0); - MP_ADD_CARRY(b0, r0, r0, 0, borrow); + MP_ADD_CARRY_ZERO(b0, r0, r0, borrow); MP_ADD_CARRY(b1, r1, r1, borrow, borrow); MP_ADD_CARRY(b2, r2, r2, borrow, borrow); MP_ADD_CARRY(b3, r3, r3, borrow, borrow); @@ -924,7 +922,7 @@ ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r, b2 = MP_DIGIT(&meth->irr,2); b1 = MP_DIGIT(&meth->irr,1); b0 = MP_DIGIT(&meth->irr,0); - MP_ADD_CARRY(b0, r0, r0, 0, borrow); + MP_ADD_CARRY_ZERO(b0, r0, r0, borrow); MP_ADD_CARRY(b1, r1, r1, borrow, borrow); MP_ADD_CARRY(b2, r2, r2, borrow, borrow); MP_ADD_CARRY(b3, r3, r3, borrow, borrow); diff --git a/jdk/src/share/native/sun/security/ec/impl/ecl_mult.c b/jdk/src/share/native/sun/security/ec/impl/ecl_mult.c index 4393c82fcf3..5c43ae8cf0e 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecl_mult.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecl_mult.c @@ -54,8 +54,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "mpi.h" #include "mplogic.h" #include "ecl.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/ecp.h b/jdk/src/share/native/sun/security/ec/impl/ecp.h index f9d8b01241a..97220f3d39f 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecp.h +++ b/jdk/src/share/native/sun/security/ec/impl/ecp.h @@ -57,8 +57,6 @@ #ifndef _ECP_H #define _ECP_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecl-priv.h" /* Checks if point P(px, py) is at infinity. Uses affine coordinates. */ diff --git a/jdk/src/share/native/sun/security/ec/impl/ecp_192.c b/jdk/src/share/native/sun/security/ec/impl/ecp_192.c index 23f49eadaf9..dcdd9dbe618 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecp_192.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecp_192.c @@ -54,8 +54,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecp.h" #include "mpi.h" #include "mplogic.h" @@ -210,15 +208,15 @@ ec_GFp_nistp192_mod(const mp_int *a, mp_int *r, const GFMethod *meth) /* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */ #ifndef MPI_AMD64_ADD - MP_ADD_CARRY(r0, a3, r0, 0, carry); + MP_ADD_CARRY_ZERO(r0, a3, r0, carry); MP_ADD_CARRY(r1, a3, r1, carry, carry); MP_ADD_CARRY(r2, a4, r2, carry, carry); r3 = carry; - MP_ADD_CARRY(r0, a5, r0, 0, carry); + MP_ADD_CARRY_ZERO(r0, a5, r0, carry); MP_ADD_CARRY(r1, a5, r1, carry, carry); MP_ADD_CARRY(r2, a5, r2, carry, carry); r3 += carry; - MP_ADD_CARRY(r1, a4, r1, 0, carry); + MP_ADD_CARRY_ZERO(r1, a4, r1, carry); MP_ADD_CARRY(r2, 0, r2, carry, carry); r3 += carry; @@ -251,7 +249,7 @@ ec_GFp_nistp192_mod(const mp_int *a, mp_int *r, const GFMethod *meth) /* reduce out the carry */ while (r3) { #ifndef MPI_AMD64_ADD - MP_ADD_CARRY(r0, r3, r0, 0, carry); + MP_ADD_CARRY_ZERO(r0, r3, r0, carry); MP_ADD_CARRY(r1, r3, r1, carry, carry); MP_ADD_CARRY(r2, 0, r2, carry, carry); r3 = carry; @@ -335,7 +333,7 @@ ec_GFp_nistp192_add(const mp_int *a, const mp_int *b, mp_int *r, } #ifndef MPI_AMD64_ADD - MP_ADD_CARRY(a0, r0, r0, 0, carry); + MP_ADD_CARRY_ZERO(a0, r0, r0, carry); MP_ADD_CARRY(a1, r1, r1, carry, carry); MP_ADD_CARRY(a2, r2, r2, carry, carry); #else @@ -357,7 +355,7 @@ ec_GFp_nistp192_add(const mp_int *a, const mp_int *b, mp_int *r, ((r1 == MP_DIGIT_MAX) || ((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) { #ifndef MPI_AMD64_ADD - MP_ADD_CARRY(r0, 1, r0, 0, carry); + MP_ADD_CARRY_ZERO(r0, 1, r0, carry); MP_ADD_CARRY(r1, 1, r1, carry, carry); MP_ADD_CARRY(r2, 0, r2, carry, carry); #else diff --git a/jdk/src/share/native/sun/security/ec/impl/ecp_224.c b/jdk/src/share/native/sun/security/ec/impl/ecp_224.c index 7d802383553..96d775f9e87 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecp_224.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecp_224.c @@ -54,8 +54,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecp.h" #include "mpi.h" #include "mplogic.h" @@ -251,10 +249,10 @@ ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth) +( 0, a6,a5b, 0) -( 0 0, 0|a6b, a6a|a5b ) -( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */ - MP_ADD_CARRY (r1, a3b, r1, 0, carry); + MP_ADD_CARRY_ZERO (r1, a3b, r1, carry); MP_ADD_CARRY (r2, a4 , r2, carry, carry); MP_ADD_CARRY (r3, a5a, r3, carry, carry); - MP_ADD_CARRY (r1, a5b, r1, 0, carry); + MP_ADD_CARRY_ZERO (r1, a5b, r1, carry); MP_ADD_CARRY (r2, a6 , r2, carry, carry); MP_ADD_CARRY (r3, 0, r3, carry, carry); @@ -275,7 +273,7 @@ ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth) r3b = (int)(r3 >>32); while (r3b > 0) { r3 &= 0xffffffff; - MP_ADD_CARRY(r1,((mp_digit)r3b) << 32, r1, 0, carry); + MP_ADD_CARRY_ZERO(r1,((mp_digit)r3b) << 32, r1, carry); if (carry) { MP_ADD_CARRY(r2, 0, r2, carry, carry); MP_ADD_CARRY(r3, 0, r3, carry, carry); @@ -290,7 +288,7 @@ ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth) } while (r3b < 0) { - MP_ADD_CARRY (r0, 1, r0, 0, carry); + MP_ADD_CARRY_ZERO (r0, 1, r0, carry); MP_ADD_CARRY (r1, MP_DIGIT_MAX <<32, r1, carry, carry); MP_ADD_CARRY (r2, MP_DIGIT_MAX, r2, carry, carry); MP_ADD_CARRY (r3, MP_DIGIT_MAX >> 32, r3, carry, carry); diff --git a/jdk/src/share/native/sun/security/ec/impl/ecp_256.c b/jdk/src/share/native/sun/security/ec/impl/ecp_256.c index f8c5720ac85..ef829085663 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecp_256.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecp_256.c @@ -54,8 +54,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecp.h" #include "mpi.h" #include "mplogic.h" @@ -303,32 +301,32 @@ ec_GFp_nistp256_mod(const mp_int *a, mp_int *r, const GFMethod *meth) r0 = MP_DIGIT(a,0); /* sum 1 */ - MP_ADD_CARRY(r1, a5h << 32, r1, 0, carry); + MP_ADD_CARRY_ZERO(r1, a5h << 32, r1, carry); MP_ADD_CARRY(r2, a6, r2, carry, carry); MP_ADD_CARRY(r3, a7, r3, carry, carry); r4 = carry; - MP_ADD_CARRY(r1, a5h << 32, r1, 0, carry); + MP_ADD_CARRY_ZERO(r1, a5h << 32, r1, carry); MP_ADD_CARRY(r2, a6, r2, carry, carry); MP_ADD_CARRY(r3, a7, r3, carry, carry); r4 += carry; /* sum 2 */ - MP_ADD_CARRY(r1, a6l, r1, 0, carry); + MP_ADD_CARRY_ZERO(r1, a6l, r1, carry); MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry); MP_ADD_CARRY(r3, a7h, r3, carry, carry); r4 += carry; - MP_ADD_CARRY(r1, a6l, r1, 0, carry); + MP_ADD_CARRY_ZERO(r1, a6l, r1, carry); MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry); MP_ADD_CARRY(r3, a7h, r3, carry, carry); r4 += carry; /* sum 3 */ - MP_ADD_CARRY(r0, a4, r0, 0, carry); + MP_ADD_CARRY_ZERO(r0, a4, r0, carry); MP_ADD_CARRY(r1, a5l >> 32, r1, carry, carry); MP_ADD_CARRY(r2, 0, r2, carry, carry); MP_ADD_CARRY(r3, a7, r3, carry, carry); r4 += carry; /* sum 4 */ - MP_ADD_CARRY(r0, a4h | a5l, r0, 0, carry); + MP_ADD_CARRY_ZERO(r0, a4h | a5l, r0, carry); MP_ADD_CARRY(r1, a5h|(a6h<<32), r1, carry, carry); MP_ADD_CARRY(r2, a7, r2, carry, carry); MP_ADD_CARRY(r3, a6h | a4l, r3, carry, carry); @@ -362,7 +360,7 @@ ec_GFp_nistp256_mod(const mp_int *a, mp_int *r, const GFMethod *meth) while (r4 > 0) { mp_digit r4_long = r4; mp_digit r4l = (r4_long << 32); - MP_ADD_CARRY(r0, r4_long, r0, 0, carry); + MP_ADD_CARRY_ZERO(r0, r4_long, r0, carry); MP_ADD_CARRY(r1, -r4l, r1, carry, carry); MP_ADD_CARRY(r2, MP_DIGIT_MAX, r2, carry, carry); MP_ADD_CARRY(r3, r4l-r4_long-1,r3, carry, carry); diff --git a/jdk/src/share/native/sun/security/ec/impl/ecp_384.c b/jdk/src/share/native/sun/security/ec/impl/ecp_384.c index c9d9d0f05a2..263fecb888f 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecp_384.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecp_384.c @@ -54,8 +54,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecp.h" #include "mpi.h" #include "mplogic.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/ecp_521.c b/jdk/src/share/native/sun/security/ec/impl/ecp_521.c index b76436a43ed..239b1289372 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecp_521.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecp_521.c @@ -50,12 +50,10 @@ * *********************************************************************** */ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecp.h" #include "mpi.h" #include "mplogic.h" @@ -74,7 +72,7 @@ ec_GFp_nistp521_mod(const mp_int *a, mp_int *r, const GFMethod *meth) { mp_err res = MP_OKAY; int a_bits = mpl_significant_bits(a); - int i; + unsigned int i; /* m1, m2 are statically-allocated mp_int of exactly the size we need */ mp_int m1; diff --git a/jdk/src/share/native/sun/security/ec/impl/ecp_aff.c b/jdk/src/share/native/sun/security/ec/impl/ecp_aff.c index c987a8887d2..a3a97f62570 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecp_aff.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecp_aff.c @@ -59,8 +59,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecp.h" #include "mplogic.h" #ifndef _KERNEL diff --git a/jdk/src/share/native/sun/security/ec/impl/ecp_jac.c b/jdk/src/share/native/sun/security/ec/impl/ecp_jac.c index 2ff3e4d57c8..8b35dae8e99 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecp_jac.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecp_jac.c @@ -59,8 +59,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecp.h" #include "mplogic.h" #ifndef _KERNEL diff --git a/jdk/src/share/native/sun/security/ec/impl/ecp_jm.c b/jdk/src/share/native/sun/security/ec/impl/ecp_jm.c index 572ed062800..b85615be7ad 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecp_jm.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecp_jm.c @@ -54,8 +54,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "ecp.h" #include "ecl-priv.h" #include "mplogic.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/ecp_mont.c b/jdk/src/share/native/sun/security/ec/impl/ecp_mont.c index ff51d90bb88..6519eda7bc0 100644 --- a/jdk/src/share/native/sun/security/ec/impl/ecp_mont.c +++ b/jdk/src/share/native/sun/security/ec/impl/ecp_mont.c @@ -54,8 +54,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* Uses Montgomery reduction for field arithmetic. See mpi/mpmontg.c for * code implementation. */ diff --git a/jdk/src/share/native/sun/security/ec/impl/logtab.h b/jdk/src/share/native/sun/security/ec/impl/logtab.h index bcc13ebb107..f4b40008b4a 100644 --- a/jdk/src/share/native/sun/security/ec/impl/logtab.h +++ b/jdk/src/share/native/sun/security/ec/impl/logtab.h @@ -57,8 +57,6 @@ #ifndef _LOGTAB_H #define _LOGTAB_H -#pragma ident "%Z%%M% %I% %E% SMI" - const float s_logv_2[] = { 0.000000000f, 0.000000000f, 1.000000000f, 0.630929754f, /* 0 1 2 3 */ 0.500000000f, 0.430676558f, 0.386852807f, 0.356207187f, /* 4 5 6 7 */ diff --git a/jdk/src/share/native/sun/security/ec/impl/mp_gf2m-priv.h b/jdk/src/share/native/sun/security/ec/impl/mp_gf2m-priv.h index 7cdacc7751b..889bfd1bed0 100644 --- a/jdk/src/share/native/sun/security/ec/impl/mp_gf2m-priv.h +++ b/jdk/src/share/native/sun/security/ec/impl/mp_gf2m-priv.h @@ -58,8 +58,6 @@ #ifndef _MP_GF2M_PRIV_H_ #define _MP_GF2M_PRIV_H_ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "mpi-priv.h" extern const mp_digit mp_gf2m_sqr_tb[16]; diff --git a/jdk/src/share/native/sun/security/ec/impl/mp_gf2m.c b/jdk/src/share/native/sun/security/ec/impl/mp_gf2m.c index beb798c10b2..2c021c88a24 100644 --- a/jdk/src/share/native/sun/security/ec/impl/mp_gf2m.c +++ b/jdk/src/share/native/sun/security/ec/impl/mp_gf2m.c @@ -55,8 +55,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "mp_gf2m.h" #include "mp_gf2m-priv.h" #include "mplogic.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/mp_gf2m.h b/jdk/src/share/native/sun/security/ec/impl/mp_gf2m.h index dff8094f507..f689ba35358 100644 --- a/jdk/src/share/native/sun/security/ec/impl/mp_gf2m.h +++ b/jdk/src/share/native/sun/security/ec/impl/mp_gf2m.h @@ -58,8 +58,6 @@ #ifndef _MP_GF2M_H_ #define _MP_GF2M_H_ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "mpi.h" mp_err mp_badd(const mp_int *a, const mp_int *b, mp_int *c); diff --git a/jdk/src/share/native/sun/security/ec/impl/mpi-config.h b/jdk/src/share/native/sun/security/ec/impl/mpi-config.h index c892fbecf3c..4c2b22b9f12 100644 --- a/jdk/src/share/native/sun/security/ec/impl/mpi-config.h +++ b/jdk/src/share/native/sun/security/ec/impl/mpi-config.h @@ -57,8 +57,6 @@ #ifndef _MPI_CONFIG_H #define _MPI_CONFIG_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* $Id: mpi-config.h,v 1.5 2004/04/25 15:03:10 gerv%gerv.net Exp $ */ /* diff --git a/jdk/src/share/native/sun/security/ec/impl/mpi-priv.h b/jdk/src/share/native/sun/security/ec/impl/mpi-priv.h index a5fccf153cc..9a80f23d02f 100644 --- a/jdk/src/share/native/sun/security/ec/impl/mpi-priv.h +++ b/jdk/src/share/native/sun/security/ec/impl/mpi-priv.h @@ -63,8 +63,6 @@ #ifndef _MPI_PRIV_H #define _MPI_PRIV_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* $Id: mpi-priv.h,v 1.20 2005/11/22 07:16:43 relyea%netscape.com Exp $ */ #include "mpi.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/mpi.c b/jdk/src/share/native/sun/security/ec/impl/mpi.c index e3558a26e81..a495b998598 100644 --- a/jdk/src/share/native/sun/security/ec/impl/mpi.c +++ b/jdk/src/share/native/sun/security/ec/impl/mpi.c @@ -54,12 +54,10 @@ * *********************************************************************** */ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* $Id: mpi.c,v 1.45 2006/09/29 20:12:21 alexei.volkov.bugs%sun.com Exp $ */ #include "mpi-priv.h" @@ -1148,7 +1146,7 @@ mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c) mp_int s, x; mp_err res; mp_digit d; - int dig, bit; + unsigned int dig, bit; ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); @@ -1523,7 +1521,7 @@ mp_err s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c mp_int s, x, mu; mp_err res; mp_digit d; - int dig, bit; + unsigned int dig, bit; ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); @@ -2057,7 +2055,7 @@ mp_size mp_trailing_zeros(const mp_int *mp) { mp_digit d; mp_size n = 0; - int ix; + unsigned int ix; if (!mp || !MP_DIGITS(mp) || !mp_cmp_z(mp)) return n; @@ -2900,9 +2898,9 @@ void s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count) /* Allocate ni records of nb bytes each, and return a pointer to that */ void *s_mp_alloc(size_t nb, size_t ni, int kmflag) { - mp_int *mp; ++mp_allocs; #ifdef _KERNEL + mp_int *mp; mp = kmem_zalloc(nb * ni, kmflag); if (mp != NULL) FLAG(mp) = kmflag; @@ -3112,7 +3110,7 @@ void s_mp_div_2(mp_int *mp) mp_err s_mp_mul_2(mp_int *mp) { mp_digit *pd; - int ix, used; + unsigned int ix, used; mp_digit kin = 0; /* Shift digits leftward by 1 bit */ @@ -4663,7 +4661,7 @@ char s_mp_todigit(mp_digit val, int r, int low) { char ch; - if(val >= r) + if(val >= (unsigned int)r) return 0; ch = s_dmap_1[val]; @@ -4778,7 +4776,7 @@ mp_err mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxlen) { int ix, pos = 0; - int bytes; + unsigned int bytes; ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG); @@ -4810,7 +4808,7 @@ mp_err mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen) { int ix, pos = 0; - int bytes; + unsigned int bytes; ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG); @@ -4850,7 +4848,7 @@ mp_err mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size length) { int ix, pos = 0; - int bytes; + unsigned int bytes; ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG); diff --git a/jdk/src/share/native/sun/security/ec/impl/mpi.h b/jdk/src/share/native/sun/security/ec/impl/mpi.h index 4933033d571..d80657e5657 100644 --- a/jdk/src/share/native/sun/security/ec/impl/mpi.h +++ b/jdk/src/share/native/sun/security/ec/impl/mpi.h @@ -60,8 +60,6 @@ #ifndef _MPI_H #define _MPI_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* $Id: mpi.h,v 1.22 2004/04/27 23:04:36 gerv%gerv.net Exp $ */ #include "mpi-config.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/mplogic.c b/jdk/src/share/native/sun/security/ec/impl/mplogic.c index 531a682a8e4..8de8306ea9e 100644 --- a/jdk/src/share/native/sun/security/ec/impl/mplogic.c +++ b/jdk/src/share/native/sun/security/ec/impl/mplogic.c @@ -56,8 +56,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* $Id: mplogic.c,v 1.15 2004/04/27 23:04:36 gerv%gerv.net Exp $ */ #include "mpi-priv.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/mplogic.h b/jdk/src/share/native/sun/security/ec/impl/mplogic.h index d384ea7f395..a2f7714bffb 100644 --- a/jdk/src/share/native/sun/security/ec/impl/mplogic.h +++ b/jdk/src/share/native/sun/security/ec/impl/mplogic.h @@ -59,8 +59,6 @@ #ifndef _MPLOGIC_H #define _MPLOGIC_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* $Id: mplogic.h,v 1.7 2004/04/27 23:04:36 gerv%gerv.net Exp $ */ #include "mpi.h" diff --git a/jdk/src/share/native/sun/security/ec/impl/mpmontg.c b/jdk/src/share/native/sun/security/ec/impl/mpmontg.c index a6713751a29..c1762847a5e 100644 --- a/jdk/src/share/native/sun/security/ec/impl/mpmontg.c +++ b/jdk/src/share/native/sun/security/ec/impl/mpmontg.c @@ -56,8 +56,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* $Id: mpmontg.c,v 1.20 2006/08/29 02:41:38 nelson%bolyard.com Exp $ */ /* This file implements moduluar exponentiation using Montgomery's diff --git a/jdk/src/share/native/sun/security/ec/impl/mpprime.h b/jdk/src/share/native/sun/security/ec/impl/mpprime.h index a648b0bbfef..b9012af4b31 100644 --- a/jdk/src/share/native/sun/security/ec/impl/mpprime.h +++ b/jdk/src/share/native/sun/security/ec/impl/mpprime.h @@ -60,8 +60,6 @@ #ifndef _MP_PRIME_H #define _MP_PRIME_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include "mpi.h" extern const int prime_tab_size; /* number of primes available */ diff --git a/jdk/src/share/native/sun/security/ec/impl/oid.c b/jdk/src/share/native/sun/security/ec/impl/oid.c index 9fc2798f418..e5a76992bf9 100644 --- a/jdk/src/share/native/sun/security/ec/impl/oid.c +++ b/jdk/src/share/native/sun/security/ec/impl/oid.c @@ -50,12 +50,10 @@ * *********************************************************************** */ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include #ifndef _WIN32 @@ -433,8 +431,7 @@ SECOidData * SECOID_FindOID(const SECItem *oid) { SECOidData *po; - SECOidData *ret; - int i; + SECOidData *ret = NULL; if (oid->len == 8) { if (oid->data[6] == 0x00) { @@ -454,8 +451,6 @@ SECOID_FindOID(const SECItem *oid) po = &SECG_oids[oid->data[4]]; if (memcmp(oid->data, po->oid.data, 5) == 0) ret = po; - } else { - ret = NULL; } return(ret); } diff --git a/jdk/src/share/native/sun/security/ec/impl/secitem.c b/jdk/src/share/native/sun/security/ec/impl/secitem.c index 45d255fda74..6cfa5dea4b2 100644 --- a/jdk/src/share/native/sun/security/ec/impl/secitem.c +++ b/jdk/src/share/native/sun/security/ec/impl/secitem.c @@ -53,8 +53,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Support routines for SECItem data structure. * diff --git a/jdk/src/share/native/sun/security/ec/impl/secoidt.h b/jdk/src/share/native/sun/security/ec/impl/secoidt.h index b63df8c4e46..ea5da257ad7 100644 --- a/jdk/src/share/native/sun/security/ec/impl/secoidt.h +++ b/jdk/src/share/native/sun/security/ec/impl/secoidt.h @@ -57,8 +57,6 @@ #ifndef _SECOIDT_H_ #define _SECOIDT_H_ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * secoidt.h - public data structures for ASN.1 OID functions * diff --git a/jdk/src/share/sample/nio/file/AclEdit.java b/jdk/src/share/sample/nio/file/AclEdit.java index c0088ca0990..0910e888a70 100644 --- a/jdk/src/share/sample/nio/file/AclEdit.java +++ b/jdk/src/share/sample/nio/file/AclEdit.java @@ -239,7 +239,7 @@ public class AclEdit { // read file's ACL AclFileAttributeView view = - file.getFileAttributeView(AclFileAttributeView.class); + Files.getFileAttributeView(file, AclFileAttributeView.class); if (view == null) { System.err.println("ACLs not supported on this platform"); System.exit(-1); diff --git a/jdk/src/share/sample/nio/file/Chmod.java b/jdk/src/share/sample/nio/file/Chmod.java index ae8feeeae04..7c4d50e93ef 100644 --- a/jdk/src/share/sample/nio/file/Chmod.java +++ b/jdk/src/share/sample/nio/file/Chmod.java @@ -264,11 +264,10 @@ public class Chmod { /** * Changes the permissions of the file using the given Changer. */ - static void chmod(FileRef file, Changer changer) { + static void chmod(Path file, Changer changer) { try { - Set perms = Attributes - .readPosixFileAttributes(file).permissions(); - Attributes.setPosixFilePermissions(file, changer.change(perms)); + Set perms = Files.getPosixFilePermissions(file); + Files.setPosixFilePermissions(file, changer.change(perms)); } catch (IOException x) { System.err.println(x); } @@ -277,7 +276,7 @@ public class Chmod { /** * Changes the permission of each file and directory visited */ - static class TreeVisitor implements FileVisitor { + static class TreeVisitor implements FileVisitor { private final Changer changer; TreeVisitor(Changer changer) { @@ -285,26 +284,26 @@ public class Chmod { } @Override - public FileVisitResult preVisitDirectory(FileRef dir, BasicFileAttributes attrs) { + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { chmod(dir, changer); return CONTINUE; } @Override - public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) { + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { chmod(file, changer); return CONTINUE; } @Override - public FileVisitResult postVisitDirectory(FileRef dir, IOException exc) { + public FileVisitResult postVisitDirectory(Path dir, IOException exc) { if (exc != null) System.err.println("WARNING: " + exc); return CONTINUE; } @Override - public FileVisitResult visitFileFailed(FileRef file, IOException exc) { + public FileVisitResult visitFileFailed(Path file, IOException exc) { System.err.println("WARNING: " + exc); return CONTINUE; } diff --git a/jdk/src/share/sample/nio/file/Copy.java b/jdk/src/share/sample/nio/file/Copy.java index eb3d5a06d03..38062c4b875 100644 --- a/jdk/src/share/sample/nio/file/Copy.java +++ b/jdk/src/share/sample/nio/file/Copy.java @@ -45,7 +45,7 @@ public class Copy { /** * Returns {@code true} if okay to overwrite a file ("cp -i") */ - static boolean okayToOverwrite(FileRef file) { + static boolean okayToOverwrite(Path file) { String answer = System.console().readLine("overwrite %s (yes/no)? ", file); return (answer.equalsIgnoreCase("y") || answer.equalsIgnoreCase("yes")); } @@ -59,9 +59,9 @@ public class Copy { CopyOption[] options = (preserve) ? new CopyOption[] { COPY_ATTRIBUTES, REPLACE_EXISTING } : new CopyOption[] { REPLACE_EXISTING }; - if (!prompt || target.notExists() || okayToOverwrite(target)) { + if (!prompt || Files.notExists(target) || okayToOverwrite(target)) { try { - source.copyTo(target, options); + Files.copy(source, target, options); } catch (IOException x) { System.err.format("Unable to copy: %s: %s%n", source, x); } @@ -93,7 +93,7 @@ public class Copy { Path newdir = target.resolve(source.relativize(dir)); try { - dir.copyTo(newdir, options); + Files.copy(dir, newdir, options); } catch (FileAlreadyExistsException x) { // ignore } catch (IOException x) { @@ -116,8 +116,8 @@ public class Copy { if (exc == null && preserve) { Path newdir = target.resolve(source.relativize(dir)); try { - BasicFileAttributes attrs = Attributes.readBasicFileAttributes(dir); - Attributes.setLastModifiedTime(newdir, attrs.lastModifiedTime()); + FileTime time = Files.getLastModifiedTime(dir); + Files.setLastModifiedTime(newdir, time); } catch (IOException x) { System.err.format("Unable to copy all attributes to: %s: %s%n", newdir, x); } @@ -180,16 +180,11 @@ public class Copy { Path target = Paths.get(args[argi]); // check if target is a directory - boolean isDir = false; - try { - isDir = Attributes.readBasicFileAttributes(target).isDirectory(); - } catch (IOException x) { - // ignore (probably target does not exist) - } + boolean isDir = Files.isDirectory(target); // copy each source file/directory to target for (i=0; i 20) { @@ -66,7 +64,7 @@ public class DiskUsage { } } else { for (String file: args) { - FileStore store = Paths.get(file).getFileStore(); + FileStore store = Files.getFileStore(Paths.get(file)); printFileStore(store); } } diff --git a/jdk/src/share/sample/nio/file/FileType.java b/jdk/src/share/sample/nio/file/FileType.java index c4713f1a532..71451614b07 100644 --- a/jdk/src/share/sample/nio/file/FileType.java +++ b/jdk/src/share/sample/nio/file/FileType.java @@ -30,7 +30,6 @@ */ import java.nio.file.*; -import java.nio.file.attribute.*; import java.io.IOException; public class FileType { @@ -41,10 +40,8 @@ public class FileType { } for (String arg: args) { Path file = Paths.get(arg); - BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file); - String type; - if (attrs.isDirectory()) { + if (Files.isDirectory(file)) { type = "directory"; } else { type = Files.probeContentType(file); diff --git a/jdk/src/share/sample/nio/file/WatchDir.java b/jdk/src/share/sample/nio/file/WatchDir.java index f2017256e9e..33c15dd0c04 100644 --- a/jdk/src/share/sample/nio/file/WatchDir.java +++ b/jdk/src/share/sample/nio/file/WatchDir.java @@ -58,7 +58,7 @@ public class WatchDir { private void register(Path dir) throws IOException { WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); if (trace) { - FileRef prev = keys.get(key); + Path prev = keys.get(key); if (prev == null) { System.out.format("register: %s\n", dir); } else { @@ -147,7 +147,7 @@ public class WatchDir { // register it and its sub-directories if (recursive && (kind == ENTRY_CREATE)) { try { - if (Attributes.readBasicFileAttributes(child, NOFOLLOW_LINKS).isDirectory()) { + if (Files.isDirectory(child, NOFOLLOW_LINKS)) { registerAll(child); } } catch (IOException x) { diff --git a/jdk/src/share/sample/nio/file/Xdd.java b/jdk/src/share/sample/nio/file/Xdd.java index 8796a174049..7551121a924 100644 --- a/jdk/src/share/sample/nio/file/Xdd.java +++ b/jdk/src/share/sample/nio/file/Xdd.java @@ -58,14 +58,14 @@ public class Xdd { Paths.get(args[0]) : Paths.get(args[2]); // check that user defined attributes are supported by the file store - FileStore store = file.getFileStore(); + FileStore store = Files.getFileStore(file); if (!store.supportsFileAttributeView(UserDefinedFileAttributeView.class)) { System.err.format("UserDefinedFileAttributeView not supported on %s\n", store); System.exit(-1); } - UserDefinedFileAttributeView view = file. - getFileAttributeView(UserDefinedFileAttributeView.class); + UserDefinedFileAttributeView view = + Files.getFileAttributeView(file, UserDefinedFileAttributeView.class); // list user defined attributes if (args.length == 1) { diff --git a/jdk/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java b/jdk/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java index 3b1925b8697..8e06835570f 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java +++ b/jdk/src/solaris/classes/sun/nio/fs/GnomeFileTypeDetector.java @@ -25,7 +25,7 @@ package sun.nio.fs; -import java.nio.file.FileRef; +import java.nio.file.Path; import java.io.IOException; import java.security.AccessController; import java.security.PrivilegedAction; @@ -57,7 +57,7 @@ public class GnomeFileTypeDetector } @Override - public String implProbeContentType(FileRef obj) throws IOException { + public String implProbeContentType(Path obj) throws IOException { if (!gioAvailable && !gnomeVfsAvailable) return null; if (!(obj instanceof UnixPath)) diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java index c51fe6b959d..4499a08924c 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java @@ -66,19 +66,6 @@ class LinuxDosFileAttributeView return "dos"; } - @Override - public Object getAttribute(String attribute) throws IOException { - if (attribute.equals(READONLY_NAME)) - return readAttributes().isReadOnly(); - if (attribute.equals(ARCHIVE_NAME)) - return readAttributes().isArchive(); - if (attribute.equals(SYSTEM_NAME)) - return readAttributes().isSystem(); - if (attribute.equals(HIDDEN_NAME)) - return readAttributes().isHidden(); - return super.getAttribute(attribute); - } - @Override public void setAttribute(String attribute, Object value) throws IOException @@ -103,7 +90,7 @@ class LinuxDosFileAttributeView } @Override - public Map readAttributes(String[] attributes) + public Map readAttributes(String[] attributes) throws IOException { AttributesBuilder builder = AttributesBuilder.create(attributes); diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java index 225c5abab35..b8b8c30f936 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java @@ -26,7 +26,6 @@ package sun.nio.fs; import java.nio.file.*; -import java.nio.file.attribute.*; import java.io.IOException; import java.util.*; import java.security.AccessController; @@ -76,39 +75,14 @@ class LinuxFileSystem extends UnixFileSystem { } } - @Override - @SuppressWarnings("unchecked") - public V newFileAttributeView(Class view, - UnixPath file, - LinkOption... options) - { - if (view == DosFileAttributeView.class) - return (V) new LinuxDosFileAttributeView(file, followLinks(options)); - if (view == UserDefinedFileAttributeView.class) - return (V) new LinuxUserDefinedFileAttributeView(file, followLinks(options)); - return super.newFileAttributeView(view, file, options); - } - - @Override - @SuppressWarnings("unchecked") - public DynamicFileAttributeView newFileAttributeView(String name, - UnixPath file, - LinkOption... options) - { - if (name.equals("dos")) - return new LinuxDosFileAttributeView(file, followLinks(options)); - if (name.equals("user")) - return new LinuxUserDefinedFileAttributeView(file, followLinks(options)); - return super.newFileAttributeView(name, file, options); - } // lazy initialization of the list of supported attribute views private static class SupportedFileFileAttributeViewsHolder { static final Set supportedFileAttributeViews = supportedFileAttributeViews(); private static Set supportedFileAttributeViews() { - Set result = new HashSet(); - result.addAll(UnixFileSystem.standardFileAttributeViews()); + Set result = new HashSet<>(); + result.addAll(standardFileAttributeViews()); // additional Linux-specific views result.add("dos"); result.add("user"); @@ -130,7 +104,7 @@ class LinuxFileSystem extends UnixFileSystem { * Returns object to iterate over the mount entries in the given fstab file. */ Iterable getMountEntries(String fstab) { - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); try { long fp = setmntent(fstab.getBytes(), "r".getBytes()); try { @@ -159,10 +133,7 @@ class LinuxFileSystem extends UnixFileSystem { return getMountEntries("/etc/mtab"); } - @Override - FileStore getFileStore(UnixPath path) throws IOException { - return new LinuxFileStore(path); - } + @Override FileStore getFileStore(UnixMountEntry entry) throws IOException { diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java index 1cb2772be30..6659ff5ede4 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java @@ -25,6 +25,10 @@ package sun.nio.fs; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; + /** * Linux implementation of FileSystemProvider */ @@ -38,4 +42,58 @@ public class LinuxFileSystemProvider extends UnixFileSystemProvider { LinuxFileSystem newFileSystem(String dir) { return new LinuxFileSystem(this, dir); } + + @Override + LinuxFileStore getFileStore(UnixPath path) throws IOException { + return new LinuxFileStore(path); + } + + @Override + @SuppressWarnings("unchecked") + public V getFileAttributeView(Path obj, + Class type, + LinkOption... options) + { + if (type == DosFileAttributeView.class) { + return (V) new LinuxDosFileAttributeView(UnixPath.toUnixPath(obj), + followLinks(options)); + } + if (type == UserDefinedFileAttributeView.class) { + return (V) new LinuxUserDefinedFileAttributeView(UnixPath.toUnixPath(obj), + followLinks(options)); + } + return super.getFileAttributeView(obj, type, options); + } + + @Override + public DynamicFileAttributeView getFileAttributeView(Path obj, + String name, + LinkOption... options) + { + if (name.equals("dos")) { + return new LinuxDosFileAttributeView(UnixPath.toUnixPath(obj), + followLinks(options)); + } + if (name.equals("user")) { + return new LinuxUserDefinedFileAttributeView(UnixPath.toUnixPath(obj), + followLinks(options)); + } + return super.getFileAttributeView(obj, name, options); + } + + @Override + @SuppressWarnings("unchecked") + public A readAttributes(Path file, + Class type, + LinkOption... options) + throws IOException + { + if (type == DosFileAttributes.class) { + DosFileAttributeView view = + getFileAttributeView(file, DosFileAttributeView.class, options); + return (A) view.readAttributes(); + } else { + return super.readAttributes(file, type, options); + } + } } diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java index dfe19ea570e..14bfbcc2e1e 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java @@ -63,7 +63,7 @@ class LinuxUserDefinedFileAttributeView // Parses buffer as array of NULL-terminated C strings. private List asList(long address, int size) { - final List list = new ArrayList(); + List list = new ArrayList<>(); int start = 0; int pos = 0; while (pos < size) { diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java index 9127a372d43..bca96756325 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java @@ -102,8 +102,8 @@ class LinuxWatchService // watch descriptor private volatile int wd; - LinuxWatchKey(LinuxWatchService watcher, int ifd, int wd) { - super(watcher); + LinuxWatchKey(UnixPath dir, LinuxWatchService watcher, int ifd, int wd) { + super(dir, watcher); this.ifd = ifd; this.wd = wd; } @@ -266,7 +266,7 @@ class LinuxWatchService // ensure watch descriptor is in map LinuxWatchKey key = wdToKey.get(wd); if (key == null) { - key = new LinuxWatchKey(watcher, ifd, wd); + key = new LinuxWatchKey(dir, watcher, ifd, wd); wdToKey.put(wd, key); } return key; diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java index 285aeca4619..5fa71242b81 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java @@ -198,7 +198,7 @@ class SolarisAclFileAttributeView * Decode the buffer, returning an ACL */ private static List decode(long address, int n) { - ArrayList acl = new ArrayList(n); + ArrayList acl = new ArrayList<>(n); for (int i=0; i aceMask = new HashSet(); + Set aceMask = EnumSet.noneOf(AclEntryPermission.class); if ((mask & ACE_READ_DATA) > 0) aceMask.add(AclEntryPermission.READ_DATA); if ((mask & ACE_WRITE_DATA) > 0) @@ -274,7 +274,7 @@ class SolarisAclFileAttributeView if ((mask & ACE_SYNCHRONIZE) > 0) aceMask.add(AclEntryPermission.SYNCHRONIZE); - HashSet aceFlags = new HashSet(); + Set aceFlags = EnumSet.noneOf(AclEntryFlag.class); if ((flags & ACE_FILE_INHERIT_ACE) > 0) aceFlags.add(AclEntryFlag.FILE_INHERIT); if ((flags & ACE_DIRECTORY_INHERIT_ACE) > 0) diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java index 9618e42812c..516d983c259 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystem.java @@ -26,7 +26,6 @@ package sun.nio.fs; import java.nio.file.*; -import java.nio.file.attribute.*; import java.io.IOException; import java.util.*; import java.security.AccessController; @@ -71,38 +70,14 @@ class SolarisFileSystem extends UnixFileSystem { } } - @Override - @SuppressWarnings("unchecked") - public V newFileAttributeView(Class view, - UnixPath file, LinkOption... options) - { - if (view == AclFileAttributeView.class) - return (V) new SolarisAclFileAttributeView(file, followLinks(options)); - if (view == UserDefinedFileAttributeView.class) { - return(V) new SolarisUserDefinedFileAttributeView(file, followLinks(options)); - } - return super.newFileAttributeView(view, file, options); - } - - @Override - protected DynamicFileAttributeView newFileAttributeView(String name, - UnixPath file, - LinkOption... options) - { - if (name.equals("acl")) - return new SolarisAclFileAttributeView(file, followLinks(options)); - if (name.equals("user")) - return new SolarisUserDefinedFileAttributeView(file, followLinks(options)); - return super.newFileAttributeView(name, file, options); - } // lazy initialization of the list of supported attribute views private static class SupportedFileFileAttributeViewsHolder { static final Set supportedFileAttributeViews = supportedFileAttributeViews(); private static Set supportedFileAttributeViews() { - Set result = new HashSet(); - result.addAll(UnixFileSystem.standardFileAttributeViews()); + Set result = new HashSet<>(); + result.addAll(standardFileAttributeViews()); // additional Solaris-specific views result.add("acl"); result.add("user"); @@ -126,7 +101,7 @@ class SolarisFileSystem extends UnixFileSystem { */ @Override Iterable getMountEntries() { - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); try { UnixPath mnttab = new UnixPath(this, "/etc/mnttab"); long fp = fopen(mnttab, "r"); @@ -147,11 +122,6 @@ class SolarisFileSystem extends UnixFileSystem { return entries; } - @Override - FileStore getFileStore(UnixPath path) throws IOException { - return new SolarisFileStore(path); - } - @Override FileStore getFileStore(UnixMountEntry entry) throws IOException { return new SolarisFileStore(this, entry); diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java index 70f5577fc8b..98c3ae8699c 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java @@ -25,6 +25,10 @@ package sun.nio.fs; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.io.IOException; + /** * Solaris implementation of FileSystemProvider */ @@ -38,4 +42,41 @@ public class SolarisFileSystemProvider extends UnixFileSystemProvider { SolarisFileSystem newFileSystem(String dir) { return new SolarisFileSystem(this, dir); } + + @Override + SolarisFileStore getFileStore(UnixPath path) throws IOException { + return new SolarisFileStore(path); + } + + + @Override + @SuppressWarnings("unchecked") + public V getFileAttributeView(Path obj, + Class type, + LinkOption... options) + { + if (type == AclFileAttributeView.class) { + return (V) new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj), + followLinks(options)); + } + if (type == UserDefinedFileAttributeView.class) { + return(V) new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj), + followLinks(options)); + } + return super.getFileAttributeView(obj, type, options); + } + + @Override + public DynamicFileAttributeView getFileAttributeView(Path obj, + String name, + LinkOption... options) + { + if (name.equals("acl")) + return new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj), + followLinks(options)); + if (name.equals("user")) + return new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj), + followLinks(options)); + return super.getFileAttributeView(obj, name, options); + } } diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java index 60c9da167dc..6148f4109f2 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisUserDefinedFileAttributeView.java @@ -83,7 +83,7 @@ class SolarisUserDefinedFileAttributeView } // read list of extended attributes - final List list = new ArrayList(); + List list = new ArrayList<>(); try { byte[] name; while ((name = readdir(dp)) != null) { diff --git a/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java b/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java index 5b9f98134b6..68296bc34e5 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java +++ b/jdk/src/solaris/classes/sun/nio/fs/SolarisWatchService.java @@ -128,7 +128,6 @@ class SolarisWatchService private class SolarisWatchKey extends AbstractWatchKey implements DirectoryNode { - private final UnixPath dir; private final UnixFileKey fileKey; // pointer to native file_obj object @@ -147,15 +146,14 @@ class SolarisWatchService long object, Set> events) { - super(watcher); - this.dir = dir; + super(dir, watcher); this.fileKey = fileKey; this.object = object; this.events = events; } - UnixPath getFileRef() { - return dir; + UnixPath getDirectory() { + return (UnixPath)watchable(); } UnixFileKey getFileKey() { @@ -487,7 +485,7 @@ class SolarisWatchService */ void processDirectoryEvents(SolarisWatchKey key, int mask) { if ((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) { - registerChildren(key.getFileRef(), key, + registerChildren(key.getDirectory(), key, key.events().contains(StandardWatchEventKind.ENTRY_CREATE)); } } @@ -524,7 +522,7 @@ class SolarisWatchService boolean removed = true; try { UnixFileAttributes - .get(key.getFileRef().resolve(node.name()), false); + .get(key.getDirectory().resolve(node.name()), false); removed = false; } catch (UnixException x) { } @@ -554,14 +552,14 @@ class SolarisWatchService DirectoryStream stream = null; try { - stream = dir.newDirectoryStream(); + stream = Files.newDirectoryStream(dir); } catch (IOException x) { // nothing we can do return; } try { for (Path entry: stream) { - Path name = entry.getName(); + Path name = entry.getFileName(); // skip entry if already registered if (parent.getChild(name) != null) @@ -582,9 +580,9 @@ class SolarisWatchService } // create node - EntryNode node = new EntryNode(object, entry.getName(), parent); + EntryNode node = new EntryNode(object, entry.getFileName(), parent); // tell the parent about it - parent.addChild(entry.getName(), node); + parent.addChild(entry.getFileName(), node); object2Node.put(object, node); } } catch (ConcurrentModificationException x) { diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java b/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java index ecb7e189923..9a666c167ee 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java @@ -237,7 +237,7 @@ class UnixCopyFile { fo = open(target, (O_WRONLY | O_CREAT | - O_TRUNC), + O_EXCL), attrs.mode()); } catch (UnixException x) { x.rethrowAsIOException(target); @@ -435,10 +435,8 @@ class UnixCopyFile { if (targetAttrs.isDirectory() && (x.errno() == EEXIST || x.errno() == ENOTEMPTY)) { - throw new FileAlreadyExistsException( - source.getPathForExecptionMessage(), - target.getPathForExecptionMessage(), - x.getMessage()); + throw new DirectoryNotEmptyException( + target.getPathForExecptionMessage()); } x.rethrowAsIOException(target); } @@ -556,10 +554,8 @@ class UnixCopyFile { if (targetAttrs.isDirectory() && (x.errno() == EEXIST || x.errno() == ENOTEMPTY)) { - throw new FileAlreadyExistsException( - source.getPathForExecptionMessage(), - target.getPathForExecptionMessage(), - x.getMessage()); + throw new DirectoryNotEmptyException( + target.getPathForExecptionMessage()); } x.rethrowAsIOException(target); } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java index 69f3cc52d15..c21a17707a8 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java @@ -148,17 +148,6 @@ class UnixFileAttributeViews { return "posix"; } - @Override - public Object getAttribute(String attribute) throws IOException { - if (attribute.equals(PERMISSIONS_NAME)) - return readAttributes().permissions(); - if (attribute.equals(OWNER_NAME)) - return readAttributes().owner(); - if (attribute.equals(GROUP_NAME)) - return readAttributes().group(); - return super.getAttribute(attribute); - } - @Override @SuppressWarnings("unchecked") public void setAttribute(String attribute, Object value) @@ -195,7 +184,7 @@ class UnixFileAttributeViews { } @Override - public Map readAttributes(String[] attributes) + public Map readAttributes(String[] attributes) throws IOException { AttributesBuilder builder = AttributesBuilder.create(attributes); @@ -307,27 +296,6 @@ class UnixFileAttributeViews { return "unix"; } - @Override - public Object getAttribute(String attribute) throws IOException { - if (attribute.equals(MODE_NAME)) - return readAttributes().mode(); - if (attribute.equals(INO_NAME)) - return readAttributes().ino(); - if (attribute.equals(DEV_NAME)) - return readAttributes().dev(); - if (attribute.equals(RDEV_NAME)) - return readAttributes().rdev(); - if (attribute.equals(NLINK_NAME)) - return readAttributes().nlink(); - if (attribute.equals(UID_NAME)) - return readAttributes().uid(); - if (attribute.equals(GID_NAME)) - return readAttributes().gid(); - if (attribute.equals(CTIME_NAME)) - return readAttributes().ctime(); - return super.getAttribute(attribute); - } - @Override public void setAttribute(String attribute, Object value) throws IOException @@ -348,7 +316,7 @@ class UnixFileAttributeViews { } @Override - public Map readAttributes(String[] attributes) + public Map readAttributes(String[] attributes) throws IOException { AttributesBuilder builder = AttributesBuilder.create(attributes); diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java index b9a81f0315e..966712e0cf1 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributes.java @@ -124,7 +124,7 @@ class UnixFileAttributes @Override public FileTime creationTime() { - return null; + return lastModifiedTime(); } @Override @@ -194,7 +194,7 @@ class UnixFileAttributes @Override public Set permissions() { int bits = (st_mode & UnixConstants.S_IAMB); - HashSet perms = new HashSet(); + HashSet perms = new HashSet<>(); if ((bits & UnixConstants.S_IRUSR) > 0) perms.add(PosixFilePermission.OWNER_READ); diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java index 46e09c6d7b1..080c2c0c2fd 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java @@ -103,28 +103,50 @@ abstract class UnixFileStore return entry.isReadOnly(); } + // uses statvfs to read the file system information + private UnixFileStoreAttributes readAttributes() throws IOException { + try { + return UnixFileStoreAttributes.get(file); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; // keep compile happy + } + } + + @Override + public long getTotalSpace() throws IOException { + UnixFileStoreAttributes attrs = readAttributes(); + return attrs.blockSize() * attrs.totalBlocks(); + } + + @Override + public long getUsableSpace() throws IOException { + UnixFileStoreAttributes attrs = readAttributes(); + return attrs.blockSize() * attrs.availableBlocks(); + } + + @Override + public long getUnallocatedSpace() throws IOException { + UnixFileStoreAttributes attrs = readAttributes(); + return attrs.blockSize() * attrs.freeBlocks(); + } + @Override - @SuppressWarnings("unchecked") public V getFileStoreAttributeView(Class view) { if (view == null) throw new NullPointerException(); - if (view == FileStoreSpaceAttributeView.class) - return (V) new UnixFileStoreSpaceAttributeView(this); return (V) null; } @Override public Object getAttribute(String attribute) throws IOException { - if (attribute.equals("space:totalSpace")) - return new UnixFileStoreSpaceAttributeView(this) - .readAttributes().totalSpace(); - if (attribute.equals("space:usableSpace")) - return new UnixFileStoreSpaceAttributeView(this) - .readAttributes().usableSpace(); - if (attribute.equals("space:unallocatedSpace")) - return new UnixFileStoreSpaceAttributeView(this) - .readAttributes().unallocatedSpace(); + if (attribute.equals("totalSpace")) + return getTotalSpace(); + if (attribute.equals("usableSpace")) + return getUsableSpace(); + if (attribute.equals("unallocatedSpace")) + return getUnallocatedSpace(); throw new UnsupportedOperationException("'" + attribute + "' not recognized"); } @@ -181,50 +203,6 @@ abstract class UnixFileStore return sb.toString(); } - private static class UnixFileStoreSpaceAttributeView - implements FileStoreSpaceAttributeView - { - private final UnixFileStore fs; - - UnixFileStoreSpaceAttributeView(UnixFileStore fs) { - this.fs = fs; - } - - @Override - public String name() { - return "space"; - } - - @Override - public FileStoreSpaceAttributes readAttributes() - throws IOException - { - UnixPath file = fs.file(); - final UnixFileStoreAttributes attrs; - try { - attrs = UnixFileStoreAttributes.get(file); - } catch (UnixException x) { - x.rethrowAsIOException(file); - return null; // keep compile happy - } - - return new FileStoreSpaceAttributes() { - @Override - public long totalSpace() { - return attrs.blockSize() * attrs.totalBlocks(); - } - @Override - public long usableSpace() { - return attrs.blockSize() * attrs.availableBlocks(); - } - @Override - public long unallocatedSpace() { - return attrs.blockSize() * attrs.freeBlocks(); - } - }; - } - } - // -- fstypes.properties -- private static final Object loadLock = new Object(); @@ -277,11 +255,8 @@ abstract class UnixFileStore String fstypes = System.getProperty("java.home") + "/lib/fstypes.properties"; Path file = Paths.get(fstypes); try { - ReadableByteChannel rbc = file.newByteChannel(); - try { + try (ReadableByteChannel rbc = Files.newByteChannel(file)) { result.load(Channels.newReader(rbc, "UTF-8")); - } finally { - rbc.close(); } } catch (IOException x) { } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java index 7068a25fc83..96c6e4a4cce 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java @@ -98,6 +98,10 @@ abstract class UnixFileSystem return false; } + static List standardFileAttributeViews() { + return Arrays.asList("basic", "posix", "unix", "owner"); + } + @Override public final FileSystemProvider provider() { return provider; @@ -168,12 +172,6 @@ abstract class UnixFileSystem */ abstract Iterable getMountEntries(); - /** - * Returns a FileStore to represent the file system where the given file - * reside. - */ - abstract FileStore getFileStore(UnixPath path) throws IOException; - /** * Returns a FileStore to represent the file system for the given mount * mount. @@ -264,7 +262,22 @@ abstract class UnixFileSystem } @Override - public final UnixPath getPath(String path) { + public final Path getPath(String first, String... more) { + String path; + if (more.length == 0) { + path = first; + } else { + StringBuilder sb = new StringBuilder(); + sb.append(first); + for (String segment: more) { + if (segment.length() > 0) { + if (sb.length() > 0) + sb.append('/'); + sb.append(segment); + } + } + path = sb.toString(); + } return new UnixPath(this, path); } @@ -300,77 +313,30 @@ abstract class UnixFileSystem private static final String GLOB_SYNTAX = "glob"; private static final String REGEX_SYNTAX = "regex"; - protected boolean followLinks(LinkOption... options) { - boolean followLinks = true; - for (LinkOption option: options) { - if (option == LinkOption.NOFOLLOW_LINKS) { - followLinks = false; - continue; - } - if (option == null) - throw new NullPointerException(); - throw new AssertionError("Should not get here"); - } - return followLinks; - } - @SuppressWarnings("unchecked") - protected V newFileAttributeView(Class view, - UnixPath file, - LinkOption... options) - { - if (view == null) - throw new NullPointerException(); - boolean followLinks = followLinks(options); - Class c = view; - if (c == BasicFileAttributeView.class) - return (V) UnixFileAttributeViews.createBasicView(file, followLinks); - if (c == PosixFileAttributeView.class) - return (V) UnixFileAttributeViews.createPosixView(file, followLinks); - if (c == FileOwnerAttributeView.class) - return (V) UnixFileAttributeViews.createOwnerView(file, followLinks); - return (V) null; - } - - static List standardFileAttributeViews() { - return Arrays.asList("basic", "posix", "unix", "owner"); - } - - protected DynamicFileAttributeView newFileAttributeView(String name, - UnixPath file, - LinkOption... options) - { - boolean followLinks = followLinks(options); - if (name.equals("basic")) - return UnixFileAttributeViews.createBasicView(file, followLinks); - if (name.equals("posix")) - return UnixFileAttributeViews.createPosixView(file, followLinks); - if (name.equals("unix")) - return UnixFileAttributeViews.createUnixView(file, followLinks); - if (name.equals("owner")) - return UnixFileAttributeViews.createOwnerView(file, followLinks); - return null; - } @Override public final UserPrincipalLookupService getUserPrincipalLookupService() { - return theLookupService; + return LookupService.instance; } - private static final UserPrincipalLookupService theLookupService = - new UserPrincipalLookupService() { - @Override - public UserPrincipal lookupPrincipalByName(String name) - throws IOException - { - return UnixUserPrincipals.lookupUser(name); - } + private static class LookupService { + static final UserPrincipalLookupService instance = + new UserPrincipalLookupService() { + @Override + public UserPrincipal lookupPrincipalByName(String name) + throws IOException + { + return UnixUserPrincipals.lookupUser(name); + } + + @Override + public GroupPrincipal lookupPrincipalByGroupName(String group) + throws IOException + { + return UnixUserPrincipals.lookupGroup(group); + } + }; + } - @Override - public GroupPrincipal lookupPrincipalByGroupName(String group) - throws IOException - { - return UnixUserPrincipals.lookupGroup(group); - } - }; } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java index aae884aa340..8ec672a306b 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java @@ -27,21 +27,25 @@ package sun.nio.fs; import java.nio.file.*; import java.nio.file.attribute.*; -import java.nio.file.spi.FileSystemProvider; import java.nio.channels.*; import java.net.URI; import java.util.concurrent.ExecutorService; import java.io.IOException; +import java.io.FilePermission; import java.util.*; +import java.security.AccessController; import sun.nio.ch.ThreadPool; +import sun.security.util.SecurityConstants; +import static sun.nio.fs.UnixNativeDispatcher.*; +import static sun.nio.fs.UnixConstants.*; /** * Base implementation of FileSystemProvider */ public abstract class UnixFileSystemProvider - extends FileSystemProvider + extends AbstractFileSystemProvider { private static final String USER_DIR = "user.dir"; private final UnixFileSystem theFileSystem; @@ -93,7 +97,7 @@ public abstract class UnixFileSystemProvider return UnixUriUtils.fromUri(theFileSystem, uri); } - protected UnixPath checkPath(Path obj) { + UnixPath checkPath(Path obj) { if (obj == null) throw new NullPointerException(); if (!(obj instanceof UnixPath)) @@ -101,6 +105,76 @@ public abstract class UnixFileSystemProvider return (UnixPath)obj; } + boolean followLinks(LinkOption... options) { + boolean followLinks = true; + for (LinkOption option: options) { + if (option == LinkOption.NOFOLLOW_LINKS) { + followLinks = false; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new AssertionError("Should not get here"); + } + return followLinks; + } + + @Override + @SuppressWarnings("unchecked") + public V getFileAttributeView(Path obj, + Class type, + LinkOption... options) + { + UnixPath file = UnixPath.toUnixPath(obj); + boolean followLinks = followLinks(options); + if (type == BasicFileAttributeView.class) + return (V) UnixFileAttributeViews.createBasicView(file, followLinks); + if (type == PosixFileAttributeView.class) + return (V) UnixFileAttributeViews.createPosixView(file, followLinks); + if (type == FileOwnerAttributeView.class) + return (V) UnixFileAttributeViews.createOwnerView(file, followLinks); + if (type == null) + throw new NullPointerException(); + return (V) null; + } + + @Override + @SuppressWarnings("unchecked") + public A readAttributes(Path file, + Class type, + LinkOption... options) + throws IOException + { + Class view; + if (type == BasicFileAttributes.class) + view = BasicFileAttributeView.class; + else if (type == PosixFileAttributes.class) + view = PosixFileAttributeView.class; + else if (type == null) + throw new NullPointerException(); + else + throw new UnsupportedOperationException(); + return (A) getFileAttributeView(file, view, options).readAttributes(); + } + + @Override + protected DynamicFileAttributeView getFileAttributeView(Path obj, + String name, + LinkOption... options) + { + UnixPath file = UnixPath.toUnixPath(obj); + boolean followLinks = followLinks(options); + if (name.equals("basic")) + return UnixFileAttributeViews.createBasicView(file, followLinks); + if (name.equals("posix")) + return UnixFileAttributeViews.createPosixView(file, followLinks); + if (name.equals("unix")) + return UnixFileAttributeViews.createUnixView(file, followLinks); + if (name.equals("owner")) + return UnixFileAttributeViews.createOwnerView(file, followLinks); + return null; + } + @Override public FileChannel newFileChannel(Path obj, Set options, @@ -136,4 +210,303 @@ public abstract class UnixFileSystemProvider return null; } } + + + @Override + public SeekableByteChannel newByteChannel(Path obj, + Set options, + FileAttribute... attrs) + throws IOException + { + UnixPath file = UnixPath.toUnixPath(obj); + int mode = UnixFileModeAttribute + .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs); + try { + return UnixChannelFactory.newFileChannel(file, options, mode); + } catch (UnixException x) { + x.rethrowAsIOException(file); + return null; // keep compiler happy + } + } + + @Override + boolean implDelete(Path obj, boolean failIfNotExists) throws IOException { + UnixPath file = UnixPath.toUnixPath(obj); + file.checkDelete(); + + // need file attributes to know if file is directory + UnixFileAttributes attrs = null; + try { + attrs = UnixFileAttributes.get(file, false); + if (attrs.isDirectory()) { + rmdir(file); + } else { + unlink(file); + } + return true; + } catch (UnixException x) { + // no-op if file does not exist + if (!failIfNotExists && x.errno() == ENOENT) + return false; + + // DirectoryNotEmptyException if not empty + if (attrs != null && attrs.isDirectory() && + (x.errno() == EEXIST || x.errno() == ENOTEMPTY)) + throw new DirectoryNotEmptyException(file.getPathForExecptionMessage()); + + x.rethrowAsIOException(file); + return false; + } + } + + @Override + public void copy(Path source, Path target, CopyOption... options) + throws IOException + { + UnixCopyFile.copy(UnixPath.toUnixPath(source), + UnixPath.toUnixPath(target), + options); + } + + @Override + public void move(Path source, Path target, CopyOption... options) + throws IOException + { + UnixCopyFile.move(UnixPath.toUnixPath(source), + UnixPath.toUnixPath(target), + options); + } + + @Override + public void checkAccess(Path obj, AccessMode... modes) throws IOException { + UnixPath file = UnixPath.toUnixPath(obj); + boolean e = false; + boolean r = false; + boolean w = false; + boolean x = false; + + if (modes.length == 0) { + e = true; + } else { + for (AccessMode mode: modes) { + switch (mode) { + case READ : r = true; break; + case WRITE : w = true; break; + case EXECUTE : x = true; break; + default: throw new AssertionError("Should not get here"); + } + } + } + + int mode = 0; + if (e || r) { + file.checkRead(); + mode |= (r) ? R_OK : F_OK; + } + if (w) { + file.checkWrite(); + mode |= W_OK; + } + if (x) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // not cached + sm.checkExec(file.getPathForPermissionCheck()); + } + mode |= X_OK; + } + try { + access(file, mode); + } catch (UnixException exc) { + exc.rethrowAsIOException(file); + } + } + + @Override + public boolean isSameFile(Path obj1, Path obj2) throws IOException { + UnixPath file1 = UnixPath.toUnixPath(obj1); + if (file1.equals(obj2)) + return true; + if (obj2 == null) + throw new NullPointerException(); + if (!(obj2 instanceof UnixPath)) + return false; + UnixPath file2 = (UnixPath)obj2; + + // check security manager access to both files + file1.checkRead(); + file2.checkRead(); + + UnixFileAttributes attrs1; + UnixFileAttributes attrs2; + try { + attrs1 = UnixFileAttributes.get(file1, true); + } catch (UnixException x) { + x.rethrowAsIOException(file1); + return false; // keep compiler happy + } + try { + attrs2 = UnixFileAttributes.get(file2, true); + } catch (UnixException x) { + x.rethrowAsIOException(file2); + return false; // keep compiler happy + } + return attrs1.isSameFile(attrs2); + } + + @Override + public boolean isHidden(Path obj) { + UnixPath file = UnixPath.toUnixPath(obj); + file.checkRead(); + UnixPath name = file.getFileName(); + if (name == null) + return false; + return (name.asByteArray()[0] == '.'); + } + + /** + * Returns a FileStore to represent the file system where the given file + * reside. + */ + abstract FileStore getFileStore(UnixPath path) throws IOException; + + @Override + public FileStore getFileStore(Path obj) throws IOException { + UnixPath file = UnixPath.toUnixPath(obj); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); + file.checkRead(); + } + return getFileStore(file); + } + + @Override + public void createDirectory(Path obj, FileAttribute... attrs) + throws IOException + { + UnixPath dir = UnixPath.toUnixPath(obj); + dir.checkWrite(); + + int mode = UnixFileModeAttribute + .toUnixMode(UnixFileModeAttribute.ALL_PERMISSIONS, attrs); + try { + mkdir(dir, mode); + } catch (UnixException x) { + x.rethrowAsIOException(dir); + } + } + + + @Override + public DirectoryStream newDirectoryStream(Path obj, DirectoryStream.Filter filter) + throws IOException + { + UnixPath dir = UnixPath.toUnixPath(obj); + dir.checkRead(); + if (filter == null) + throw new NullPointerException(); + + // can't return SecureDirectoryStream on kernels that don't support + // openat, etc. + if (!supportsAtSysCalls()) { + try { + long ptr = opendir(dir); + return new UnixDirectoryStream(dir, ptr, filter); + } catch (UnixException x) { + if (x.errno() == ENOTDIR) + throw new NotDirectoryException(dir.getPathForExecptionMessage()); + x.rethrowAsIOException(dir); + } + } + + // open directory and dup file descriptor for use by + // opendir/readdir/closedir + int dfd1 = -1; + int dfd2 = -1; + long dp = 0L; + try { + dfd1 = open(dir, O_RDONLY, 0); + dfd2 = dup(dfd1); + dp = fdopendir(dfd1); + } catch (UnixException x) { + if (dfd1 != -1) + UnixNativeDispatcher.close(dfd1); + if (dfd2 != -1) + UnixNativeDispatcher.close(dfd2); + if (x.errno() == UnixConstants.ENOTDIR) + throw new NotDirectoryException(dir.getPathForExecptionMessage()); + x.rethrowAsIOException(dir); + } + return new UnixSecureDirectoryStream(dir, dp, dfd2, filter); + } + + @Override + public void createSymbolicLink(Path obj1, Path obj2, FileAttribute... attrs) + throws IOException + { + UnixPath link = UnixPath.toUnixPath(obj1); + UnixPath target = UnixPath.toUnixPath(obj2); + + // no attributes supported when creating links + if (attrs.length > 0) { + UnixFileModeAttribute.toUnixMode(0, attrs); // may throw NPE or UOE + throw new UnsupportedOperationException("Initial file attributes" + + "not supported when creating symbolic link"); + } + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new LinkPermission("symbolic")); + link.checkWrite(); + } + + // create link + try { + symlink(target.asByteArray(), link); + } catch (UnixException x) { + x.rethrowAsIOException(link); + } + } + + @Override + public void createLink(Path obj1, Path obj2) throws IOException { + UnixPath link = UnixPath.toUnixPath(obj1); + UnixPath existing = UnixPath.toUnixPath(obj2); + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new LinkPermission("hard")); + link.checkWrite(); + existing.checkWrite(); + } + try { + link(existing, link); + } catch (UnixException x) { + x.rethrowAsIOException(link, existing); + } + } + + @Override + public Path readSymbolicLink(Path obj1) throws IOException { + UnixPath link = UnixPath.toUnixPath(obj1); + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + FilePermission perm = new FilePermission(link.getPathForPermissionCheck(), + SecurityConstants.FILE_READLINK_ACTION); + AccessController.checkPermission(perm); + } + try { + byte[] target = readlink(link); + return new UnixPath(link.getFileSystem(), target); + } catch (UnixException x) { + if (x.errno() == UnixConstants.EINVAL) + throw new NotLinkException(link.getPathForExecptionMessage()); + x.rethrowAsIOException(link); + return null; // keep compiler happy + } + } } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java index 1667263c222..9ec49b8d37a 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java @@ -27,15 +27,11 @@ package sun.nio.fs; import java.nio.*; import java.nio.file.*; -import java.nio.file.attribute.*; import java.nio.charset.*; -import java.nio.channels.*; -import java.security.AccessController; import java.io.*; import java.net.URI; import java.util.*; import java.lang.ref.SoftReference; -import sun.security.util.SecurityConstants; import static sun.nio.fs.UnixNativeDispatcher.*; import static sun.nio.fs.UnixConstants.*; @@ -79,8 +75,6 @@ class UnixPath // removes redundant slashes and check input for invalid characters static String normalizeAndCheck(String input) { int n = input.length(); - if (n == 0) - throw new InvalidPathException(input, "Path is empty"); char prevChar = 0; for (int i=0; i < n; i++) { char c = input.charAt(i); @@ -174,7 +168,13 @@ class UnixPath if (getFileSystem().needToResolveAgainstDefaultDirectory()) { return resolve(getFileSystem().defaultDirectory(), path); } else { - return path; + if (!isEmpty()) { + return path; + } else { + // empty path case will access current directory + byte[] here = { '.' }; + return here; + } } } @@ -193,7 +193,7 @@ class UnixPath } // Checks that the given file is a UnixPath - private UnixPath checkPath(FileRef obj) { + static UnixPath toUnixPath(Path obj) { if (obj == null) throw new NullPointerException(); if (!(obj instanceof UnixPath)) @@ -209,12 +209,17 @@ class UnixPath // count names count = 0; index = 0; - while (index < path.length) { - byte c = path[index++]; - if (c != '/') { - count++; - while (index < path.length && path[index] != '/') - index++; + if (isEmpty()) { + // empty path has one name + count = 1; + } else { + while (index < path.length) { + byte c = path[index++]; + if (c != '/') { + count++; + while (index < path.length && path[index] != '/') + index++; + } } } @@ -239,6 +244,16 @@ class UnixPath } } + // returns {@code true} if this path is an empty path + private boolean isEmpty() { + return path.length == 0; + } + + // returns an empty path + private UnixPath emptyPath() { + return new UnixPath(getFileSystem(), new byte[0]); + } + @Override public UnixFileSystem getFileSystem() { return fs; @@ -246,7 +261,7 @@ class UnixPath @Override public UnixPath getRoot() { - if (path[0] == '/') { + if (path.length > 0 && path[0] == '/') { return getFileSystem().rootDirectory(); } else { return null; @@ -254,14 +269,17 @@ class UnixPath } @Override - public UnixPath getName() { + public UnixPath getFileName() { initOffsets(); int count = offsets.length; - if (count == 0) - return null; // no elements so no name - if (count == 1 && path[0] != '/') + // no elements so no name + if (count == 0) + return null; + + // one name element and no root component + if (count == 1 && path.length > 0 && path[0] != '/') return this; int lastOffset = offsets[count-1]; @@ -349,57 +367,58 @@ class UnixPath @Override public boolean isAbsolute() { - return (path[0] == '/'); + return (path.length > 0 && path[0] == '/'); } // Resolve child against given base private static byte[] resolve(byte[] base, byte[] child) { - if (child[0] == '/') + int baseLength = base.length; + int childLength = child.length; + if (childLength == 0) + return base; + if (baseLength == 0 || child[0] == '/') return child; byte[] result; - if (base.length == 1 && base[0] == '/') { - result = new byte[child.length + 1]; + if (baseLength == 1 && base[0] == '/') { + result = new byte[childLength + 1]; result[0] = '/'; - System.arraycopy(child, 0, result, 1, child.length); + System.arraycopy(child, 0, result, 1, childLength); } else { - result = new byte[base.length + 1 + child.length]; - System.arraycopy(base, 0, result, 0, base.length); + result = new byte[baseLength + 1 + childLength]; + System.arraycopy(base, 0, result, 0, baseLength); result[base.length] = '/'; - System.arraycopy(child, 0, result, base.length+1, child.length); + System.arraycopy(child, 0, result, baseLength+1, childLength); } return result; } @Override public UnixPath resolve(Path obj) { - if (obj == null) - return this; - byte[] other = checkPath(obj).path; - if (other[0] == '/') + byte[] other = toUnixPath(obj).path; + if (other.length > 0 && other[0] == '/') return ((UnixPath)obj); byte[] result = resolve(path, other); return new UnixPath(getFileSystem(), result); } - @Override - public UnixPath resolve(String other) { - return resolve(new UnixPath(getFileSystem(), other)); - } - UnixPath resolve(byte[] other) { return resolve(new UnixPath(getFileSystem(), other)); } @Override public UnixPath relativize(Path obj) { - UnixPath other = checkPath(obj); + UnixPath other = toUnixPath(obj); if (other.equals(this)) - return null; + return emptyPath(); // can only relativize paths of the same type if (this.isAbsolute() != other.isAbsolute()) throw new IllegalArgumentException("'other' is different type of Path"); + // this path is the empty path + if (this.isEmpty()) + return other; + int bn = this.getNameCount(); int cn = other.getNameCount(); @@ -419,14 +438,27 @@ class UnixPath if (dotdots == 0) return remainder; + // other is the empty path + boolean isOtherEmpty = other.isEmpty(); + // result is a "../" for each remaining name in base - // followed by the remaining names in other - byte[] result = new byte[dotdots*3 + remainder.path.length]; + // followed by the remaining names in other. If the remainder is + // the empty path then we don't add the final trailing slash. + int len = dotdots*3 + remainder.path.length; + if (isOtherEmpty) { + assert remainder.isEmpty(); + len--; + } + byte[] result = new byte[len]; int pos = 0; while (dotdots > 0) { result[pos++] = (byte)'.'; result[pos++] = (byte)'.'; - result[pos++] = (byte)'/'; + if (isOtherEmpty) { + if (dotdots > 1) result[pos++] = (byte)'/'; + } else { + result[pos++] = (byte)'/'; + } dotdots--; } System.arraycopy(remainder.path, 0, result, pos, remainder.path.length); @@ -457,7 +489,7 @@ class UnixPath int[] size = new int[count]; // length of name int remaining = count; // number of names remaining boolean hasDotDot = false; // has at least one .. - boolean isAbsolute = path[0] == '/'; + boolean isAbsolute = isAbsolute(); // first pass: // 1. compute length of names @@ -542,7 +574,7 @@ class UnixPath // corner case - all names removed if (remaining == 0) { - return isAbsolute ? getFileSystem().rootDirectory() : null; + return isAbsolute ? getFileSystem().rootDirectory() : emptyPath(); } // compute length of result @@ -574,7 +606,7 @@ class UnixPath @Override public boolean startsWith(Path other) { - UnixPath that = checkPath(other); + UnixPath that = toUnixPath(other); // other path is longer if (that.path.length > path.length) @@ -584,8 +616,9 @@ class UnixPath int thatOffsetCount = that.getNameCount(); // other path has no name elements - if (thatOffsetCount == 0 && this.isAbsolute()) - return true; + if (thatOffsetCount == 0 && this.isAbsolute()) { + return that.isEmpty() ? false : true; + } // given path has more elements that this path if (thatOffsetCount > thisOffsetCount) @@ -622,7 +655,7 @@ class UnixPath @Override public boolean endsWith(Path other) { - UnixPath that = checkPath(other); + UnixPath that = toUnixPath(other); int thisLen = path.length; int thatLen = that.path.length; @@ -631,6 +664,10 @@ class UnixPath if (thatLen > thisLen) return false; + // other path is the empty path + if (thisLen > 0 && thatLen == 0) + return false; + // other path is absolute so this path must be absolute if (that.isAbsolute() && !this.isAbsolute()) return false; @@ -721,32 +758,6 @@ class UnixPath return stringValue; } - @Override - public Iterator iterator() { - initOffsets(); - return new Iterator() { - int i = 0; - @Override - public boolean hasNext() { - return (i < offsets.length); - } - @Override - public Path next() { - if (i < offsets.length) { - Path result = getName(i); - i++; - return result; - } else { - throw new NoSuchElementException(); - } - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - // -- file operations -- // package-private @@ -770,7 +781,6 @@ class UnixPath } } - void checkRead() { SecurityManager sm = System.getSecurityManager(); if (sm != null) @@ -789,296 +799,6 @@ class UnixPath sm.checkDelete(getPathForPermissionCheck()); } - @Override - public FileStore getFileStore() - throws IOException - { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); - checkRead(); - } - return getFileSystem().getFileStore(this); - } - - @Override - public void checkAccess(AccessMode... modes) throws IOException { - boolean e = false; - boolean r = false; - boolean w = false; - boolean x = false; - - if (modes.length == 0) { - e = true; - } else { - for (AccessMode mode: modes) { - switch (mode) { - case READ : r = true; break; - case WRITE : w = true; break; - case EXECUTE : x = true; break; - default: throw new AssertionError("Should not get here"); - } - } - } - - int mode = 0; - if (e || r) { - checkRead(); - mode |= (r) ? R_OK : F_OK; - } - if (w) { - checkWrite(); - mode |= W_OK; - } - if (x) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - // not cached - sm.checkExec(getPathForPermissionCheck()); - } - mode |= X_OK; - } - try { - access(this, mode); - } catch (UnixException exc) { - exc.rethrowAsIOException(this); - } - } - - @Override - void implDelete(boolean failIfNotExists) throws IOException { - checkDelete(); - - // need file attributes to know if file is directory - UnixFileAttributes attrs = null; - try { - attrs = UnixFileAttributes.get(this, false); - if (attrs.isDirectory()) { - rmdir(this); - } else { - unlink(this); - } - } catch (UnixException x) { - // no-op if file does not exist - if (!failIfNotExists && x.errno() == ENOENT) - return; - - // DirectoryNotEmptyException if not empty - if (attrs != null && attrs.isDirectory() && - (x.errno() == EEXIST || x.errno() == ENOTEMPTY)) - throw new DirectoryNotEmptyException(getPathForExecptionMessage()); - - x.rethrowAsIOException(this); - } - } - - @Override - public DirectoryStream newDirectoryStream(DirectoryStream.Filter filter) - throws IOException - { - if (filter == null) - throw new NullPointerException(); - checkRead(); - - // can't return SecureDirectoryStream on kernels that don't support - // openat, etc. - if (!supportsAtSysCalls()) { - try { - long ptr = opendir(this); - return new UnixDirectoryStream(this, ptr, filter); - } catch (UnixException x) { - if (x.errno() == ENOTDIR) - throw new NotDirectoryException(getPathForExecptionMessage()); - x.rethrowAsIOException(this); - } - } - - // open directory and dup file descriptor for use by - // opendir/readdir/closedir - int dfd1 = -1; - int dfd2 = -1; - long dp = 0L; - try { - dfd1 = open(this, O_RDONLY, 0); - dfd2 = dup(dfd1); - dp = fdopendir(dfd1); - } catch (UnixException x) { - if (dfd1 != -1) - close(dfd1); - if (dfd2 != -1) - close(dfd2); - if (x.errno() == UnixConstants.ENOTDIR) - throw new NotDirectoryException(getPathForExecptionMessage()); - x.rethrowAsIOException(this); - } - return new UnixSecureDirectoryStream(this, dp, dfd2, filter); - } - - // invoked by AbstractPath#copyTo - @Override - public void implCopyTo(Path obj, CopyOption... options) - throws IOException - { - UnixPath target = (UnixPath)obj; - UnixCopyFile.copy(this, target, options); - } - - @Override - public void implMoveTo(Path obj, CopyOption... options) - throws IOException - { - UnixPath target = (UnixPath)obj; - UnixCopyFile.move(this, target, options); - } - - @Override - @SuppressWarnings("unchecked") - public V - getFileAttributeView(Class type, LinkOption... options) - { - FileAttributeView view = getFileSystem() - .newFileAttributeView(type, this, options); - if (view == null) - return null; - return (V) view; - } - - @Override - public DynamicFileAttributeView getFileAttributeView(String name, - LinkOption... options) - { - return getFileSystem().newFileAttributeView(name, this, options); - } - - @Override - public Path createDirectory(FileAttribute... attrs) - throws IOException - { - checkWrite(); - - int mode = UnixFileModeAttribute - .toUnixMode(UnixFileModeAttribute.ALL_PERMISSIONS, attrs); - try { - mkdir(this, mode); - } catch (UnixException x) { - x.rethrowAsIOException(this); - } - return this; - } - - @Override - public SeekableByteChannel newByteChannel(Set options, - FileAttribute... attrs) - throws IOException - { - int mode = UnixFileModeAttribute - .toUnixMode(UnixFileModeAttribute.ALL_READWRITE, attrs); - try { - return UnixChannelFactory.newFileChannel(this, options, mode); - } catch (UnixException x) { - x.rethrowAsIOException(this); - return null; // keep compiler happy - } - } - - @Override - public boolean isSameFile(Path obj) throws IOException { - if (this.equals(obj)) - return true; - if (!(obj instanceof UnixPath)) // includes null check - return false; - UnixPath other = (UnixPath)obj; - - // check security manager access to both files - this.checkRead(); - other.checkRead(); - - UnixFileAttributes thisAttrs; - UnixFileAttributes otherAttrs; - try { - thisAttrs = UnixFileAttributes.get(this, true); - } catch (UnixException x) { - x.rethrowAsIOException(this); - return false; // keep compiler happy - } - try { - otherAttrs = UnixFileAttributes.get(other, true); - } catch (UnixException x) { - x.rethrowAsIOException(other); - return false; // keep compiler happy - } - return thisAttrs.isSameFile(otherAttrs); - } - - @Override - public Path createSymbolicLink(Path obj, FileAttribute... attrs) - throws IOException - { - UnixPath target = checkPath(obj); - - // no attributes supported when creating links - if (attrs.length > 0) { - UnixFileModeAttribute.toUnixMode(0, attrs); // may throw NPE or UOE - throw new UnsupportedOperationException("Initial file attributes" + - "not supported when creating symbolic link"); - } - - // permission check - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new LinkPermission("symbolic")); - checkWrite(); - } - - // create link - try { - symlink(target.asByteArray(), this); - } catch (UnixException x) { - x.rethrowAsIOException(this); - } - - return this; - } - - @Override - public Path createLink(Path obj) throws IOException { - UnixPath existing = checkPath(obj); - - // permission check - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new LinkPermission("hard")); - this.checkWrite(); - existing.checkWrite(); - } - try { - link(existing, this); - } catch (UnixException x) { - x.rethrowAsIOException(this, existing); - } - return this; - } - - @Override - public Path readSymbolicLink() throws IOException { - // permission check - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - FilePermission perm = new FilePermission(getPathForPermissionCheck(), - SecurityConstants.FILE_READLINK_ACTION); - AccessController.checkPermission(perm); - } - try { - byte[] target = readlink(this); - return new UnixPath(getFileSystem(), target); - } catch (UnixException x) { - if (x.errno() == UnixConstants.EINVAL) - throw new NotLinkException(getPathForExecptionMessage()); - x.rethrowAsIOException(this); - return null; // keep compiler happy - } - } - @Override public UnixPath toAbsolutePath() { if (isAbsolute()) { @@ -1095,7 +815,7 @@ class UnixPath } @Override - public UnixPath toRealPath(boolean resolveLinks) throws IOException { + public Path toRealPath(boolean resolveLinks) throws IOException { checkRead(); UnixPath absolute = toAbsolutePath(); @@ -1112,8 +832,7 @@ class UnixPath // if resolveLinks is false then eliminate "." and also ".." // where the previous element is not a link. - UnixPath root = getFileSystem().rootDirectory(); - UnixPath result = root; + UnixPath result = fs.rootDirectory(); for (int i=0; i + implements SecureDirectoryStream { private final UnixDirectoryStream ds; private final int dfd; @@ -81,6 +81,20 @@ class UnixSecureDirectoryStream return (UnixPath)obj; } + private boolean followLinks(LinkOption... options) { + boolean followLinks = true; + for (LinkOption option: options) { + if (option == LinkOption.NOFOLLOW_LINKS) { + followLinks = false; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new AssertionError("Should not get here"); + } + return followLinks; + } + /** * Opens sub-directory in this directory */ @@ -91,7 +105,7 @@ class UnixSecureDirectoryStream { UnixPath file = getName(obj); UnixPath child = ds.directory().resolve(file); - boolean followLinks = file.getFileSystem().followLinks(options); + boolean followLinks = followLinks(options); // permission check using name resolved against original path of directory SecurityManager sm = System.getSecurityManager(); @@ -302,7 +316,7 @@ class UnixSecureDirectoryStream LinkOption... options) { UnixPath file = getName(obj); - boolean followLinks = file.getFileSystem().followLinks(options); + boolean followLinks = followLinks(options); return getFileAttributeViewImpl(file, type, followLinks); } @@ -336,7 +350,11 @@ class UnixSecureDirectoryStream private void checkWriteAccess() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - ds.directory().resolve(file).checkWrite(); + if (file == null) { + ds.directory().checkWrite(); + } else { + ds.directory().resolve(file).checkWrite(); + } } } diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java b/jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java index d86431efc08..bd1e36a9025 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java @@ -25,8 +25,11 @@ package sun.nio.fs; +import java.nio.file.Path; +import java.io.File; import java.net.URI; import java.net.URISyntaxException; +import java.util.Arrays; /** * Unix specific Path <--> URI conversion @@ -38,7 +41,7 @@ class UnixUriUtils { /** * Converts URI to Path */ - static UnixPath fromUri(UnixFileSystem fs, URI uri) { + static Path fromUri(UnixFileSystem fs, URI uri) { if (!uri.isAbsolute()) throw new IllegalArgumentException("URI is not absolute"); if (uri.isOpaque()) @@ -53,22 +56,41 @@ class UnixUriUtils { if (uri.getQuery() != null) throw new IllegalArgumentException("URI has a query component"); - String path = uri.getPath(); - if (path.equals("")) - throw new IllegalArgumentException("URI path component is empty"); - if (path.endsWith("/") && (path.length() > 1)) { - // "/foo/" --> "/foo", but "/" --> "/" - path = path.substring(0, path.length() - 1); - } + // compatability with java.io.File + if (!uri.toString().startsWith("file:///")) + return new File(uri).toPath(); - // preserve bytes - byte[] result = new byte[path.length()]; - for (int i=0; i 1) + len--; + byte[] result = new byte[len]; + int rlen = 0; + int pos = 0; + while (pos < len) { + char c = p.charAt(pos++); + byte b; + if (c == '%') { + assert (pos+2) <= len; + char c1 = p.charAt(pos++); + char c2 = p.charAt(pos++); + b = (byte)((decode(c1) << 4) | decode(c2)); + if (b == 0) + throw new IllegalArgumentException("Nul character not allowed"); + } else { + assert c < 0x80; + b = (byte)c; + } + result[rlen++] = b; } + if (rlen != result.length) + result = Arrays.copyOf(result, rlen); + return new UnixPath(fs, result); } @@ -86,7 +108,7 @@ class UnixUriUtils { } else { sb.append('%'); sb.append(hexDigits[(c >> 4) & 0x0f]); - sb.append(hexDigits[(c >> 0) & 0x0f]); + sb.append(hexDigits[(c) & 0x0f]); } } @@ -164,6 +186,17 @@ class UnixUriUtils { return false; } + // decode + private static int decode(char c) { + if ((c >= '0') && (c <= '9')) + return c - '0'; + if ((c >= 'a') && (c <= 'f')) + return c - 'a' + 10; + if ((c >= 'A') && (c <= 'F')) + return c - 'A' + 10; + throw new AssertionError(); + } + // digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | // "8" | "9" private static final long L_DIGIT = lowMask('0', '9'); diff --git a/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c b/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c index 5c6a2baee47..d01f09e3c64 100644 --- a/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c +++ b/jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c @@ -55,12 +55,23 @@ #include "sun_nio_fs_UnixNativeDispatcher.h" +/** + * Size of password or group entry when not available via sysconf + */ +#define ENT_BUF_SIZE 1024 + #define RESTARTABLE(_cmd, _result) do { \ do { \ _result = _cmd; \ } while((_result == -1) && (errno == EINTR)); \ } while(0) +#define RESTARTABLE_RETURN_PTR(_cmd, _result) do { \ + do { \ + _result = _cmd; \ + } while((_result == NULL) && (errno == EINTR)); \ +} while(0) + static jfieldID attrs_st_mode; static jfieldID attrs_st_ino; static jfieldID attrs_st_dev; @@ -858,37 +869,41 @@ Java_sun_nio_fs_UnixNativeDispatcher_getpwuid(JNIEnv* env, jclass this, jint uid { jbyteArray result = NULL; int buflen; + char* pwbuf; + /* allocate buffer for password record */ buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX); - if (buflen == -1) { - throwUnixException(env, errno); + if (buflen == -1) + buflen = ENT_BUF_SIZE; + pwbuf = (char*)malloc(buflen); + if (pwbuf == NULL) { + JNU_ThrowOutOfMemoryError(env, "native heap"); } else { - char* pwbuf = (char*)malloc(buflen); - if (pwbuf == NULL) { - JNU_ThrowOutOfMemoryError(env, "native heap"); - } else { - struct passwd pwent; - struct passwd* p; - int res = 0; + struct passwd pwent; + struct passwd* p = NULL; + int res = 0; -#ifdef __solaris__ - p = getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen); -#else - res = getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen, &p); -#endif + errno = 0; + #ifdef __solaris__ + RESTARTABLE_RETURN_PTR(getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen), p); + #else + RESTARTABLE(getpwuid_r((uid_t)uid, &pwent, pwbuf, (size_t)buflen, &p), res); + #endif - if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') { + if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') { + /* not found or error */ + if (errno != 0 && errno != ENOENT) throwUnixException(env, errno); - } else { - jsize len = strlen(p->pw_name); - result = (*env)->NewByteArray(env, len); - if (result != NULL) { - (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(p->pw_name)); - } + } else { + jsize len = strlen(p->pw_name); + result = (*env)->NewByteArray(env, len); + if (result != NULL) { + (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(p->pw_name)); } - free(pwbuf); } + free(pwbuf); } + return result; } @@ -898,36 +913,55 @@ Java_sun_nio_fs_UnixNativeDispatcher_getgrgid(JNIEnv* env, jclass this, jint gid { jbyteArray result = NULL; int buflen; + int retry; + /* initial size of buffer for group record */ buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX); - if (buflen == -1) { - throwUnixException(env, errno); - } else { + if (buflen == -1) + buflen = ENT_BUF_SIZE; + + do { + struct group grent; + struct group* g = NULL; + int res = 0; + char* grbuf = (char*)malloc(buflen); if (grbuf == NULL) { JNU_ThrowOutOfMemoryError(env, "native heap"); - } else { - struct group grent; - struct group* g; - int res = 0; + return NULL; + } -#ifdef __solaris__ - g = getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen); -#else - res = getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen, &g); -#endif - if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') { - throwUnixException(env, errno); - } else { - jsize len = strlen(g->gr_name); - result = (*env)->NewByteArray(env, len); - if (result != NULL) { - (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(g->gr_name)); + errno = 0; + #ifdef __solaris__ + RESTARTABLE_RETURN_PTR(getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen), g); + #else + RESTARTABLE(getgrgid_r((gid_t)gid, &grent, grbuf, (size_t)buflen, &g), res); + #endif + + retry = 0; + if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') { + /* not found or error */ + if (errno != 0 && errno != ENOENT) { + if (errno == ERANGE) { + /* insufficient buffer size so need larger buffer */ + buflen += ENT_BUF_SIZE; + retry = 1; + } else { + throwUnixException(env, errno); } } - free(grbuf); + } else { + jsize len = strlen(g->gr_name); + result = (*env)->NewByteArray(env, len); + if (result != NULL) { + (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)(g->gr_name)); + } } - } + + free(grbuf); + + } while (retry); + return result; } @@ -938,35 +972,36 @@ Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0(JNIEnv* env, jclass this, jint uid = -1; int buflen; char* pwbuf; - struct passwd pwent; - struct passwd* p; - int res = 0; - const char* name = (const char*)jlong_to_ptr(nameAddress); + /* allocate buffer for password record */ buflen = (int)sysconf(_SC_GETPW_R_SIZE_MAX); - if (buflen == -1) { - throwUnixException(env, errno); - return -1; - } + if (buflen == -1) + buflen = ENT_BUF_SIZE; pwbuf = (char*)malloc(buflen); if (pwbuf == NULL) { JNU_ThrowOutOfMemoryError(env, "native heap"); - return -1; - } - -#ifdef __solaris__ - p = getpwnam_r(name, &pwent, pwbuf, (size_t)buflen); -#else - res = getpwnam_r(name, &pwent, pwbuf, (size_t)buflen, &p); -#endif - - if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') { - /* not found or error */ } else { - uid = p->pw_uid; - } + struct passwd pwent; + struct passwd* p = NULL; + int res = 0; + const char* name = (const char*)jlong_to_ptr(nameAddress); - free(pwbuf); + errno = 0; + #ifdef __solaris__ + RESTARTABLE_RETURN_PTR(getpwnam_r(name, &pwent, pwbuf, (size_t)buflen), p); + #else + RESTARTABLE(getpwnam_r(name, &pwent, pwbuf, (size_t)buflen, &p), res); + #endif + + if (res != 0 || p == NULL || p->pw_name == NULL || *(p->pw_name) == '\0') { + /* not found or error */ + if (errno != 0 && errno != ENOENT) + throwUnixException(env, errno); + } else { + uid = p->pw_uid; + } + free(pwbuf); + } return uid; } @@ -976,36 +1011,52 @@ Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0(JNIEnv* env, jclass this, jlong nameAddress) { jint gid = -1; - int buflen; - char* grbuf; - struct group grent; - struct group* g; - int res = 0; - const char* name = (const char*)jlong_to_ptr(nameAddress); + int buflen, retry; + /* initial size of buffer for group record */ buflen = (int)sysconf(_SC_GETGR_R_SIZE_MAX); - if (buflen == -1) { - throwUnixException(env, errno); - return -1; - } - grbuf = (char*)malloc(buflen); - if (grbuf == NULL) { - JNU_ThrowOutOfMemoryError(env, "native heap"); - return -1; - } + if (buflen == -1) + buflen = ENT_BUF_SIZE; -#ifdef __solaris__ - g = getgrnam_r(name, &grent, grbuf, (size_t)buflen); -#else - res = getgrnam_r(name, &grent, grbuf, (size_t)buflen, &g); -#endif + do { + struct group grent; + struct group* g = NULL; + int res = 0; + char *grbuf; + const char* name = (const char*)jlong_to_ptr(nameAddress); - if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') { - /* not found or error */ - } else { - gid = g->gr_gid; - } - free(grbuf); + grbuf = (char*)malloc(buflen); + if (grbuf == NULL) { + JNU_ThrowOutOfMemoryError(env, "native heap"); + return -1; + } + + errno = 0; + #ifdef __solaris__ + RESTARTABLE_RETURN_PTR(getgrnam_r(name, &grent, grbuf, (size_t)buflen), g); + #else + RESTARTABLE(getgrnam_r(name, &grent, grbuf, (size_t)buflen, &g), res); + #endif + + retry = 0; + if (res != 0 || g == NULL || g->gr_name == NULL || *(g->gr_name) == '\0') { + /* not found or error */ + if (errno != 0 && errno != ENOENT) { + if (errno == ERANGE) { + /* insufficient buffer size so need larger buffer */ + buflen += ENT_BUF_SIZE; + retry = 1; + } else { + throwUnixException(env, errno); + } + } + } else { + gid = g->gr_gid; + } + + free(grbuf); + + } while (retry); return gid; } diff --git a/jdk/src/windows/classes/java/net/PlainSocketImpl.java b/jdk/src/windows/classes/java/net/PlainSocketImpl.java index 3a963627425..cc25c39dc72 100644 --- a/jdk/src/windows/classes/java/net/PlainSocketImpl.java +++ b/jdk/src/windows/classes/java/net/PlainSocketImpl.java @@ -138,6 +138,9 @@ class PlainSocketImpl extends AbstractPlainSocketImpl protected synchronized void create(boolean stream) throws IOException { impl.create(stream); + + // set fd to delegate's fd to be compatible with older releases + this.fd = impl.fd; } protected void connect(String host, int port) @@ -166,7 +169,7 @@ class PlainSocketImpl extends AbstractPlainSocketImpl impl.doConnect(address, port, timeout); } - protected synchronized void bind(InetAddress address, int lport) + protected synchronized void bind(InetAddress address, int lport) throws IOException { impl.bind(address, lport); @@ -174,9 +177,13 @@ class PlainSocketImpl extends AbstractPlainSocketImpl protected synchronized void accept(SocketImpl s) throws IOException { // pass in the real impl not the wrapper. - ((PlainSocketImpl)s).impl.address = new InetAddress(); - ((PlainSocketImpl)s).impl.fd = new FileDescriptor(); - impl.accept(((PlainSocketImpl)s).impl); + SocketImpl delegate = ((PlainSocketImpl)s).impl; + delegate.address = new InetAddress(); + delegate.fd = new FileDescriptor(); + impl.accept(delegate); + + // set fd to delegate's fd to be compatible with older releases + s.fd = delegate.fd; } void setFileDescriptor(FileDescriptor fd) { @@ -208,11 +215,21 @@ class PlainSocketImpl extends AbstractPlainSocketImpl } protected void close() throws IOException { - impl.close(); + try { + impl.close(); + } finally { + // set fd to delegate's fd to be compatible with older releases + this.fd = null; + } } void reset() throws IOException { - impl.reset(); + try { + impl.reset(); + } finally { + // set fd to delegate's fd to be compatible with older releases + this.fd = null; + } } protected void shutdownInput() throws IOException { diff --git a/jdk/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java b/jdk/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java index 9d0beb50a13..8c846c1c219 100644 --- a/jdk/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java +++ b/jdk/src/windows/classes/sun/nio/fs/RegistryFileTypeDetector.java @@ -42,12 +42,12 @@ public class RegistryFileTypeDetector } @Override - public String implProbeContentType(FileRef file) throws IOException { + public String implProbeContentType(Path file) throws IOException { if (!(file instanceof Path)) return null; // get file extension - Path name = ((Path)file).getName(); + Path name = file.getFileName(); if (name == null) return null; String filename = name.toString(); diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java index 20beff15474..8a81b87a0ab 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java @@ -166,22 +166,6 @@ class WindowsFileAttributeViews { return "dos"; } - @Override - public Object getAttribute(String attribute) throws IOException { - if (attribute.equals(READONLY_NAME)) - return readAttributes().isReadOnly(); - if (attribute.equals(ARCHIVE_NAME)) - return readAttributes().isArchive(); - if (attribute.equals(SYSTEM_NAME)) - return readAttributes().isSystem(); - if (attribute.equals(HIDDEN_NAME)) - return readAttributes().isHidden(); - // implementation specific - if (attribute.equals(ATTRIBUTES_NAME)) - return readAttributes().attributes(); - return super.getAttribute(attribute); - } - @Override public void setAttribute(String attribute, Object value) throws IOException @@ -206,7 +190,7 @@ class WindowsFileAttributeViews { } @Override - public Map readAttributes(String[] attributes) + public Map readAttributes(String[] attributes) throws IOException { AttributesBuilder builder = AttributesBuilder.create(attributes); diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java index d35752b8ee1..ed3421fb90e 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java @@ -158,7 +158,7 @@ class WindowsFileCopy { if (x.lastError() == ERROR_DIR_NOT_EMPTY || x.lastError() == ERROR_ALREADY_EXISTS) { - throw new FileAlreadyExistsException( + throw new DirectoryNotEmptyException( target.getPathForExceptionMessage()); } } @@ -369,7 +369,7 @@ class WindowsFileCopy { if (x.lastError() == ERROR_DIR_NOT_EMPTY || x.lastError() == ERROR_ALREADY_EXISTS) { - throw new FileAlreadyExistsException( + throw new DirectoryNotEmptyException( target.getPathForExceptionMessage()); } } diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java index 30446bb4ae9..8b3c2fb4b19 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java @@ -117,28 +117,47 @@ class WindowsFileStore return ((volInfo.flags() & FILE_READ_ONLY_VOLUME) != 0); } + // read the free space info + private DiskFreeSpace readDiskFreeSpace() throws IOException { + try { + return GetDiskFreeSpaceEx(root); + } catch (WindowsException x) { + x.rethrowAsIOException(root); + return null; + } + } + + @Override + public long getTotalSpace() throws IOException { + return readDiskFreeSpace().totalNumberOfBytes(); + } + + @Override + public long getUsableSpace() throws IOException { + return readDiskFreeSpace().freeBytesAvailable(); + } + + @Override + public long getUnallocatedSpace() throws IOException { + return readDiskFreeSpace().freeBytesAvailable(); + } + @Override - @SuppressWarnings("unchecked") public V getFileStoreAttributeView(Class type) { if (type == null) throw new NullPointerException(); - if (type == FileStoreSpaceAttributeView.class) - return (V) new WindowsFileStoreAttributeView(this); return (V) null; } @Override public Object getAttribute(String attribute) throws IOException { // standard - if (attribute.equals("space:totalSpace")) - return new WindowsFileStoreAttributeView(this) - .readAttributes().totalSpace(); - if (attribute.equals("space:usableSpace")) - return new WindowsFileStoreAttributeView(this) - .readAttributes().usableSpace(); - if (attribute.equals("space:unallocatedSpace")) - return new WindowsFileStoreAttributeView(this) - .readAttributes().unallocatedSpace(); + if (attribute.equals("totalSpace")) + return getTotalSpace(); + if (attribute.equals("usableSpace")) + return getUsableSpace(); + if (attribute.equals("unallocatedSpace")) + return getUnallocatedSpace(); // windows specific for testing purposes if (attribute.equals("volume:vsn")) return volInfo.volumeSerialNumber(); @@ -202,48 +221,4 @@ class WindowsFileStore sb.append(")"); return sb.toString(); } - - static class WindowsFileStoreAttributeView - implements FileStoreSpaceAttributeView - { - private final WindowsFileStore fs; - - WindowsFileStoreAttributeView(WindowsFileStore fs) { - this.fs = fs; - } - - @Override - public String name() { - return "space"; - } - - @Override - public FileStoreSpaceAttributes readAttributes() - throws IOException - { - // read the free space info - DiskFreeSpace info = null; - try { - info = GetDiskFreeSpaceEx(fs.root); - } catch (WindowsException x) { - x.rethrowAsIOException(fs.root); - } - - final DiskFreeSpace result = info; - return new FileStoreSpaceAttributes() { - @Override - public long totalSpace() { - return result.totalNumberOfBytes(); - } - @Override - public long usableSpace() { - return result.freeBytesAvailable(); - } - @Override - public long unallocatedSpace() { - return result.totalNumberOfFreeBytes(); - } - }; - } - } } diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java index a543623ee4a..59891ec51d5 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystem.java @@ -127,7 +127,7 @@ class WindowsFileSystem } // iterate over roots, ignoring those that the security manager denies - ArrayList result = new ArrayList(); + ArrayList result = new ArrayList<>(); SecurityManager sm = System.getSecurityManager(); for (int i = 0; i <= 25; i++) { // 0->A, 1->B, 2->C... if ((drives & (1 << i)) != 0) { @@ -235,33 +235,50 @@ class WindowsFileSystem } @Override - public Path getPath(String path) { + public final Path getPath(String first, String... more) { + String path; + if (more.length == 0) { + path = first; + } else { + StringBuilder sb = new StringBuilder(); + sb.append(first); + for (String segment: more) { + if (segment.length() > 0) { + if (sb.length() > 0) + sb.append('\\'); + sb.append(segment); + } + } + path = sb.toString(); + } return WindowsPath.parse(this, path); } @Override public UserPrincipalLookupService getUserPrincipalLookupService() { - return theLookupService; + return LookupService.instance; } - private static final UserPrincipalLookupService theLookupService = - new UserPrincipalLookupService() { - @Override - public UserPrincipal lookupPrincipalByName(String name) - throws IOException - { - return WindowsUserPrincipals.lookup(name); - } - @Override - public GroupPrincipal lookupPrincipalByGroupName(String group) - throws IOException - { - UserPrincipal user = WindowsUserPrincipals.lookup(group); - if (!(user instanceof GroupPrincipal)) - throw new UserPrincipalNotFoundException(group); - return (GroupPrincipal)user; - } - }; + private static class LookupService { + static final UserPrincipalLookupService instance = + new UserPrincipalLookupService() { + @Override + public UserPrincipal lookupPrincipalByName(String name) + throws IOException + { + return WindowsUserPrincipals.lookup(name); + } + @Override + public GroupPrincipal lookupPrincipalByGroupName(String group) + throws IOException + { + UserPrincipal user = WindowsUserPrincipals.lookup(group); + if (!(user instanceof GroupPrincipal)) + throw new UserPrincipalNotFoundException(group); + return (GroupPrincipal)user; + } + }; + } @Override public PathMatcher getPathMatcher(String syntaxAndInput) { diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java index 81193d25b9a..6d6a4db89b2 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java @@ -26,19 +26,25 @@ package sun.nio.fs; import java.nio.file.*; -import java.nio.file.spi.*; import java.nio.file.attribute.*; import java.nio.channels.*; import java.net.URI; import java.util.concurrent.ExecutorService; -import java.io.IOException; +import java.io.*; import java.util.*; - +import java.security.AccessController; +import sun.misc.Unsafe; import sun.nio.ch.ThreadPool; +import sun.security.util.SecurityConstants; + +import static sun.nio.fs.WindowsNativeDispatcher.*; +import static sun.nio.fs.WindowsConstants.*; public class WindowsFileSystemProvider - extends FileSystemProvider + extends AbstractFileSystemProvider { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final String USER_DIR = "user.dir"; private final WindowsFileSystem theFileSystem; @@ -143,4 +149,505 @@ public class WindowsFileSystemProvider sd.release(); } } + + private boolean followLinks(LinkOption... options) { + boolean followLinks = true; + for (LinkOption option: options) { + if (option == LinkOption.NOFOLLOW_LINKS) { + followLinks = false; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new AssertionError("Should not get here"); + } + return followLinks; + } + + @Override + @SuppressWarnings("unchecked") + public V + getFileAttributeView(Path obj, Class view, LinkOption... options) + { + WindowsPath file = WindowsPath.toWindowsPath(obj); + if (view == null) + throw new NullPointerException(); + boolean followLinks = followLinks(options); + if (view == BasicFileAttributeView.class) + return (V) WindowsFileAttributeViews.createBasicView(file, followLinks); + if (view == DosFileAttributeView.class) + return (V) WindowsFileAttributeViews.createDosView(file, followLinks); + if (view == AclFileAttributeView.class) + return (V) new WindowsAclFileAttributeView(file, followLinks); + if (view == FileOwnerAttributeView.class) + return (V) new FileOwnerAttributeViewImpl( + new WindowsAclFileAttributeView(file, followLinks)); + if (view == UserDefinedFileAttributeView.class) + return (V) new WindowsUserDefinedFileAttributeView(file, followLinks); + return (V) null; + } + + @Override + @SuppressWarnings("unchecked") + public A readAttributes(Path file, + Class type, + LinkOption... options) + throws IOException + { + Class view; + if (type == BasicFileAttributes.class) + view = BasicFileAttributeView.class; + else if (type == DosFileAttributes.class) + view = DosFileAttributeView.class; + else if (type == null) + throw new NullPointerException(); + else + throw new UnsupportedOperationException(); + return (A) getFileAttributeView(file, view, options).readAttributes(); + } + + @Override + public DynamicFileAttributeView getFileAttributeView(Path obj, String name, LinkOption... options) { + WindowsPath file = WindowsPath.toWindowsPath(obj); + boolean followLinks = followLinks(options); + if (name.equals("basic")) + return WindowsFileAttributeViews.createBasicView(file, followLinks); + if (name.equals("dos")) + return WindowsFileAttributeViews.createDosView(file, followLinks); + if (name.equals("acl")) + return new WindowsAclFileAttributeView(file, followLinks); + if (name.equals("owner")) + return new FileOwnerAttributeViewImpl( + new WindowsAclFileAttributeView(file, followLinks)); + if (name.equals("user")) + return new WindowsUserDefinedFileAttributeView(file, followLinks); + return null; + } + + @Override + public SeekableByteChannel newByteChannel(Path obj, + Set options, + FileAttribute... attrs) + throws IOException + { + WindowsPath file = WindowsPath.toWindowsPath(obj); + WindowsSecurityDescriptor sd = + WindowsSecurityDescriptor.fromAttribute(attrs); + try { + return WindowsChannelFactory + .newFileChannel(file.getPathForWin32Calls(), + file.getPathForPermissionCheck(), + options, + sd.address()); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + return null; // keep compiler happy + } finally { + sd.release(); + } + } + + @Override + boolean implDelete(Path obj, boolean failIfNotExists) throws IOException { + WindowsPath file = WindowsPath.toWindowsPath(obj); + file.checkDelete(); + + WindowsFileAttributes attrs = null; + try { + // need to know if file is a directory or junction + attrs = WindowsFileAttributes.get(file, false); + if (attrs.isDirectory() || attrs.isDirectoryLink()) { + RemoveDirectory(file.getPathForWin32Calls()); + } else { + DeleteFile(file.getPathForWin32Calls()); + } + return true; + } catch (WindowsException x) { + + // no-op if file does not exist + if (!failIfNotExists && + (x.lastError() == ERROR_FILE_NOT_FOUND || + x.lastError() == ERROR_PATH_NOT_FOUND)) return false; + + if (attrs != null && attrs.isDirectory()) { + // ERROR_ALREADY_EXISTS is returned when attempting to delete + // non-empty directory on SAMBA servers. + if (x.lastError() == ERROR_DIR_NOT_EMPTY || + x.lastError() == ERROR_ALREADY_EXISTS) + { + throw new DirectoryNotEmptyException( + file.getPathForExceptionMessage()); + } + } + x.rethrowAsIOException(file); + return false; + } + } + + @Override + public void copy(Path source, Path target, CopyOption... options) + throws IOException + { + WindowsFileCopy.copy(WindowsPath.toWindowsPath(source), + WindowsPath.toWindowsPath(target), + options); + } + + @Override + public void move(Path source, Path target, CopyOption... options) + throws IOException + { + WindowsFileCopy.move(WindowsPath.toWindowsPath(source), + WindowsPath.toWindowsPath(target), + options); + } + + /** + * Returns buffer with SID_AND_ATTRIBUTES structure representing the user + * associated with the current thread access token. + * FIXME - this should be cached. + */ + private static NativeBuffer getUserInfo(WindowsPath file) throws IOException { + try { + long hToken = WindowsSecurity.processTokenWithQueryAccess; + int size = GetTokenInformation(hToken, TokenUser, 0L, 0); + assert size > 0; + + NativeBuffer buffer = NativeBuffers.getNativeBuffer(size); + try { + int newsize = GetTokenInformation(hToken, TokenUser, + buffer.address(), size); + if (newsize != size) + throw new AssertionError(); + return buffer; + } catch (WindowsException x) { + buffer.release(); + throw x; + } + } catch (WindowsException x) { + throw new IOException(x.getMessage()); + } + } + + /** + * Reads the file ACL and return the effective access as ACCESS_MASK + */ + private static int getEffectiveAccess(WindowsPath file) throws IOException { + // read security descriptor continaing ACL (symlinks are followed) + String target = WindowsLinkSupport.getFinalPath(file, true); + NativeBuffer aclBuffer = WindowsAclFileAttributeView + .getFileSecurity(target, DACL_SECURITY_INFORMATION); + + // retrieves DACL from security descriptor + long pAcl = GetSecurityDescriptorDacl(aclBuffer.address()); + + // Use GetEffectiveRightsFromAcl to get effective access to file + try { + NativeBuffer userBuffer = getUserInfo(file); + try { + try { + // SID_AND_ATTRIBUTES->pSid + long pSid = unsafe.getAddress(userBuffer.address()); + long pTrustee = BuildTrusteeWithSid(pSid); + try { + return GetEffectiveRightsFromAcl(pAcl, pTrustee); + } finally { + LocalFree(pTrustee); + } + } catch (WindowsException x) { + throw new IOException("Unable to get effective rights from ACL: " + + x.getMessage()); + } + } finally { + userBuffer.release(); + } + } finally { + aclBuffer.release(); + } + } + + @Override + public void checkAccess(Path obj, AccessMode... modes) throws IOException { + WindowsPath file = WindowsPath.toWindowsPath(obj); + // if no access modes then simply file attributes + if (modes.length == 0) { + file.checkRead(); + try { + WindowsFileAttributes.get(file, true); + } catch (WindowsException exc) { + exc.rethrowAsIOException(file); + } + return; + } + + boolean r = false; + boolean w = false; + boolean x = false; + for (AccessMode mode: modes) { + switch (mode) { + case READ : r = true; break; + case WRITE : w = true; break; + case EXECUTE : x = true; break; + default: throw new AssertionError("Should not get here"); + } + } + + int mask = 0; + if (r) { + file.checkRead(); + mask |= FILE_READ_DATA; + } + if (w) { + file.checkWrite(); + mask |= FILE_WRITE_DATA; + } + if (x) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkExec(file.getPathForPermissionCheck()); + mask |= FILE_EXECUTE; + } + + if ((getEffectiveAccess(file) & mask) == 0) + throw new AccessDeniedException( + file.getPathForExceptionMessage(), null, + "Effective permissions does not allow requested access"); + + // for write access we neeed to check if the DOS readonly attribute + // and if the volume is read-only + if (w) { + try { + WindowsFileAttributes attrs = WindowsFileAttributes.get(file, true); + if (!attrs.isDirectory() && attrs.isReadOnly()) + throw new AccessDeniedException( + file.getPathForExceptionMessage(), null, + "DOS readonly attribute is set"); + } catch (WindowsException exc) { + exc.rethrowAsIOException(file); + } + + if (WindowsFileStore.create(file).isReadOnly()) { + throw new AccessDeniedException( + file.getPathForExceptionMessage(), null, "Read-only file system"); + } + return; + } + } + + @Override + public boolean isSameFile(Path obj1, Path obj2) throws IOException { + WindowsPath file1 = WindowsPath.toWindowsPath(obj1); + if (file1.equals(obj2)) + return true; + if (obj2 == null) + throw new NullPointerException(); + if (!(obj2 instanceof WindowsPath)) + return false; + WindowsPath file2 = (WindowsPath)obj2; + + // check security manager access to both files + file1.checkRead(); + file2.checkRead(); + + // open both files and see if they are the same + long h1 = 0L; + try { + h1 = file1.openForReadAttributeAccess(true); + } catch (WindowsException x) { + x.rethrowAsIOException(file1); + } + try { + WindowsFileAttributes attrs1 = null; + try { + attrs1 = WindowsFileAttributes.readAttributes(h1); + } catch (WindowsException x) { + x.rethrowAsIOException(file1); + } + long h2 = 0L; + try { + h2 = file2.openForReadAttributeAccess(true); + } catch (WindowsException x) { + x.rethrowAsIOException(file2); + } + try { + WindowsFileAttributes attrs2 = null; + try { + attrs2 = WindowsFileAttributes.readAttributes(h2); + } catch (WindowsException x) { + x.rethrowAsIOException(file2); + } + return WindowsFileAttributes.isSameFile(attrs1, attrs2); + } finally { + CloseHandle(h2); + } + } finally { + CloseHandle(h1); + } + } + + @Override + public boolean isHidden(Path obj) throws IOException { + WindowsPath file = WindowsPath.toWindowsPath(obj); + file.checkRead(); + WindowsFileAttributes attrs = null; + try { + attrs = WindowsFileAttributes.get(file, true); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + } + // DOS hidden attribute not meaningful when set on directories + if (attrs.isDirectory()) + return false; + return attrs.isHidden(); + } + + @Override + public FileStore getFileStore(Path obj) throws IOException { + WindowsPath file = WindowsPath.toWindowsPath(obj); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); + file.checkRead(); + } + return WindowsFileStore.create(file); + } + + + @Override + public void createDirectory(Path obj, FileAttribute... attrs) + throws IOException + { + WindowsPath dir = WindowsPath.toWindowsPath(obj); + dir.checkWrite(); + WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.fromAttribute(attrs); + try { + CreateDirectory(dir.getPathForWin32Calls(), sd.address()); + } catch (WindowsException x) { + x.rethrowAsIOException(dir); + } finally { + sd.release(); + } + } + + @Override + public DirectoryStream newDirectoryStream(Path obj, DirectoryStream.Filter filter) + throws IOException + { + WindowsPath dir = WindowsPath.toWindowsPath(obj); + dir.checkRead(); + if (filter == null) + throw new NullPointerException(); + return new WindowsDirectoryStream(dir, filter); + } + + @Override + public void createSymbolicLink(Path obj1, Path obj2, FileAttribute... attrs) + throws IOException + { + WindowsPath link = WindowsPath.toWindowsPath(obj1); + WindowsPath target = WindowsPath.toWindowsPath(obj2); + + if (!link.getFileSystem().supportsLinks()) { + throw new UnsupportedOperationException("Symbolic links not supported " + + "on this operating system"); + } + + // no attributes allowed + if (attrs.length > 0) { + WindowsSecurityDescriptor.fromAttribute(attrs); // may throw NPE or UOE + throw new UnsupportedOperationException("Initial file attributes" + + "not supported when creating symbolic link"); + } + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new LinkPermission("symbolic")); + link.checkWrite(); + } + + /** + * Throw I/O exception for the drive-relative case because Windows + * creates a link with the resolved target for this case. + */ + if (target.type() == WindowsPathType.DRIVE_RELATIVE) { + throw new IOException("Cannot create symbolic link to working directory relative target"); + } + + /* + * Windows treates symbolic links to directories differently than it + * does to other file types. For that reason we need to check if the + * target is a directory (or a directory junction). + */ + WindowsPath resolvedTarget; + if (target.type() == WindowsPathType.RELATIVE) { + WindowsPath parent = link.getParent(); + resolvedTarget = (parent == null) ? target : parent.resolve(target); + } else { + resolvedTarget = link.resolve(target); + } + int flags = 0; + try { + WindowsFileAttributes wattrs = WindowsFileAttributes.get(resolvedTarget, false); + if (wattrs.isDirectory() || wattrs.isDirectoryLink()) + flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; + } catch (WindowsException x) { + // unable to access target so assume target is not a directory + } + + // create the link + try { + CreateSymbolicLink(link.getPathForWin32Calls(), + WindowsPath.addPrefixIfNeeded(target.toString()), + flags); + } catch (WindowsException x) { + if (x.lastError() == ERROR_INVALID_REPARSE_DATA) { + x.rethrowAsIOException(link, target); + } else { + x.rethrowAsIOException(link); + } + } + } + + @Override + public void createLink(Path obj1, Path obj2) throws IOException { + WindowsPath link = WindowsPath.toWindowsPath(obj1); + WindowsPath existing = WindowsPath.toWindowsPath(obj2); + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new LinkPermission("hard")); + link.checkWrite(); + existing.checkWrite(); + } + + // create hard link + try { + CreateHardLink(link.getPathForWin32Calls(), + existing.getPathForWin32Calls()); + } catch (WindowsException x) { + x.rethrowAsIOException(link, existing); + } + } + + @Override + public Path readSymbolicLink(Path obj1) throws IOException { + WindowsPath link = WindowsPath.toWindowsPath(obj1); + WindowsFileSystem fs = link.getFileSystem(); + if (!fs.supportsLinks()) { + throw new UnsupportedOperationException("symbolic links not supported"); + } + + // permission check + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + FilePermission perm = new FilePermission(link.getPathForPermissionCheck(), + SecurityConstants.FILE_READLINK_ACTION); + AccessController.checkPermission(perm); + } + + String target = WindowsLinkSupport.readLink(link); + return WindowsPath.createFromNormalizedPath(fs, target); + } } diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java index 3e79ab43ab6..26c2b26ce8e 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java @@ -27,18 +27,13 @@ package sun.nio.fs; import java.nio.file.*; import java.nio.file.attribute.*; -import java.nio.channels.*; import java.io.*; import java.net.URI; -import java.security.AccessController; import java.util.*; import java.lang.ref.WeakReference; import com.sun.nio.file.ExtendedWatchEventModifier; -import sun.security.util.SecurityConstants; -import sun.misc.Unsafe; - import static sun.nio.fs.WindowsNativeDispatcher.*; import static sun.nio.fs.WindowsConstants.*; @@ -47,7 +42,6 @@ import static sun.nio.fs.WindowsConstants.*; */ class WindowsPath extends AbstractPath { - private static final Unsafe unsafe = Unsafe.getUnsafe(); // The maximum path that does not require long path prefix. On Windows // the maximum path is 260 minus 1 (NUL) but for directories it is 260 @@ -229,6 +223,8 @@ class WindowsPath extends AbstractPath { // Relative path ("foo" for example) if (type == WindowsPathType.RELATIVE) { String defaultDirectory = getFileSystem().defaultDirectory(); + if (isEmpty()) + return defaultDirectory; if (defaultDirectory.endsWith("\\")) { return defaultDirectory + path; } else { @@ -286,7 +282,7 @@ class WindowsPath extends AbstractPath { } // Add long path prefix to path if required - private static String addPrefixIfNeeded(String path) { + static String addPrefixIfNeeded(String path) { if (path.length() > 248) { if (path.startsWith("\\\\")) { path = "\\\\?\\UNC" + path.substring(1, path.length()); @@ -304,10 +300,22 @@ class WindowsPath extends AbstractPath { // -- Path operations -- + private boolean isEmpty() { + return path.length() == 0; + } + + private WindowsPath emptyPath() { + return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", ""); + } + @Override - public Path getName() { + public Path getFileName() { + int len = path.length(); + // represents empty path + if (len == 0) + return this; // represents root component only - if (root.length() == path.length()) + if (root.length() == len) return null; int off = path.lastIndexOf('\\'); if (off < root.length()) @@ -339,6 +347,11 @@ class WindowsPath extends AbstractPath { return new WindowsPath(getFileSystem(), type, root, root); } + // package-private + WindowsPathType type() { + return type; + } + // package-private boolean isUnc() { return type == WindowsPathType.UNC; @@ -355,7 +368,7 @@ class WindowsPath extends AbstractPath { return type == WindowsPathType.ABSOLUTE || type == WindowsPathType.UNC; } - private WindowsPath checkPath(FileRef path) { + static WindowsPath toWindowsPath(Path path) { if (path == null) throw new NullPointerException(); if (!(path instanceof WindowsPath)) { @@ -366,9 +379,9 @@ class WindowsPath extends AbstractPath { @Override public WindowsPath relativize(Path obj) { - WindowsPath other = checkPath(obj); + WindowsPath other = toWindowsPath(obj); if (this.equals(other)) - return null; + return emptyPath(); // can only relativize paths of the same type if (this.type != other.type) @@ -410,7 +423,7 @@ class WindowsPath extends AbstractPath { @Override public Path normalize() { final int count = getNameCount(); - if (count == 0) + if (count == 0 || isEmpty()) return this; boolean[] ignore = new boolean[count]; // true => ignore name @@ -488,7 +501,7 @@ class WindowsPath extends AbstractPath { // corner case - all names removed if (remaining == 0) { - return getRoot(); + return (root.length() == 0) ? emptyPath() : getRoot(); } // re-constitute the path from the remaining names. @@ -497,7 +510,7 @@ class WindowsPath extends AbstractPath { result.append(root); for (int i=0; i list = new ArrayList(); - int start = root.length(); - int off = root.length(); - while (off < path.length()) { - if (path.charAt(off) != '\\') { - off++; - } else { - list.add(start); - start = ++off; + ArrayList list = new ArrayList<>(); + if (isEmpty()) { + // empty path considered to have one name element + list.add(0); + } else { + int start = root.length(); + int off = root.length(); + while (off < path.length()) { + if (path.charAt(off) != '\\') { + off++; + } else { + list.add(start); + start = ++off; + } } + if (start != off) + list.add(start); } - if (start != off) - list.add(start); synchronized (this) { if (offsets == null) offsets = list.toArray(new Integer[list.size()]); @@ -633,11 +646,16 @@ class WindowsPath extends AbstractPath { @Override public boolean startsWith(Path obj) { - WindowsPath other = checkPath(obj); + WindowsPath other = toWindowsPath(obj); // if this path has a root component the given path's root must match - if (!this.root.equalsIgnoreCase(other.root)) + if (!this.root.equalsIgnoreCase(other.root)) { return false; + } + + // empty path starts with itself + if (other.isEmpty()) + return this.isEmpty(); // roots match so compare elements int thisCount = getNameCount(); @@ -657,13 +675,18 @@ class WindowsPath extends AbstractPath { @Override public boolean endsWith(Path obj) { - WindowsPath other = checkPath(obj); + WindowsPath other = toWindowsPath(obj); // other path is longer - if (other.path.length() > path.length()) { + if (other.path.length() > this.path.length()) { return false; } + // empty path ends in itself + if (other.isEmpty()) { + return this.isEmpty(); + } + int thisCount = this.getNameCount(); int otherCount = other.getNameCount(); @@ -742,31 +765,6 @@ class WindowsPath extends AbstractPath { return path; } - @Override - public Iterator iterator() { - return new Iterator() { - private int i = 0; - @Override - public boolean hasNext() { - return (i < getNameCount()); - } - @Override - public Path next() { - if (i < getNameCount()) { - Path result = getName(i); - i++; - return result; - } else { - throw new NoSuchElementException(); - } - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - // -- file operations -- // package-private @@ -805,453 +803,6 @@ class WindowsPath extends AbstractPath { } } - @Override - public FileStore getFileStore() - throws IOException - { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission("getFileStoreAttributes")); - checkRead(); - } - return WindowsFileStore.create(this); - } - - /** - * Returns buffer with SID_AND_ATTRIBUTES structure representing the user - * associated with the current thread access token. - * FIXME - this should be cached. - */ - private NativeBuffer getUserInfo() throws IOException { - try { - long hToken = WindowsSecurity.processTokenWithQueryAccess; - int size = GetTokenInformation(hToken, TokenUser, 0L, 0); - assert size > 0; - - NativeBuffer buffer = NativeBuffers.getNativeBuffer(size); - try { - int newsize = GetTokenInformation(hToken, TokenUser, - buffer.address(), size); - if (newsize != size) - throw new AssertionError(); - return buffer; - } catch (WindowsException x) { - buffer.release(); - throw x; - } - } catch (WindowsException x) { - throw new IOException(x.getMessage()); - } - } - - /** - * Reads the file ACL and return the effective access as ACCESS_MASK - */ - private int getEffectiveAccess() throws IOException { - // read security descriptor continaing ACL (symlinks are followed) - String target = WindowsLinkSupport.getFinalPath(this, true); - NativeBuffer aclBuffer = WindowsAclFileAttributeView - .getFileSecurity(target, DACL_SECURITY_INFORMATION); - - // retrieves DACL from security descriptor - long pAcl = GetSecurityDescriptorDacl(aclBuffer.address()); - - // Use GetEffectiveRightsFromAcl to get effective access to file - try { - NativeBuffer userBuffer = getUserInfo(); - try { - try { - // SID_AND_ATTRIBUTES->pSid - long pSid = unsafe.getAddress(userBuffer.address()); - long pTrustee = BuildTrusteeWithSid(pSid); - try { - return GetEffectiveRightsFromAcl(pAcl, pTrustee); - } finally { - LocalFree(pTrustee); - } - } catch (WindowsException x) { - throw new IOException("Unable to get effective rights from ACL: " + - x.getMessage()); - } - } finally { - userBuffer.release(); - } - } finally { - aclBuffer.release(); - } - } - - @Override - public void checkAccess(AccessMode... modes) throws IOException { - // if no access modes then simply file attributes - if (modes.length == 0) { - checkRead(); - try { - WindowsFileAttributes.get(this, true); - } catch (WindowsException exc) { - exc.rethrowAsIOException(this); - } - return; - } - - boolean r = false; - boolean w = false; - boolean x = false; - for (AccessMode mode: modes) { - switch (mode) { - case READ : r = true; break; - case WRITE : w = true; break; - case EXECUTE : x = true; break; - default: throw new AssertionError("Should not get here"); - } - } - - int mask = 0; - if (r) { - checkRead(); - mask |= FILE_READ_DATA; - } - if (w) { - checkWrite(); - mask |= FILE_WRITE_DATA; - } - if (x) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkExec(getPathForPermissionCheck()); - mask |= FILE_EXECUTE; - } - - if ((getEffectiveAccess() & mask) == 0) - throw new AccessDeniedException( - this.getPathForExceptionMessage(), null, - "Effective permissions does not allow requested access"); - - // for write access we neeed to check if the DOS readonly attribute - // and if the volume is read-only - if (w) { - try { - WindowsFileAttributes attrs = WindowsFileAttributes.get(this, true); - if (!attrs.isDirectory() && attrs.isReadOnly()) - throw new AccessDeniedException( - this.getPathForExceptionMessage(), null, - "DOS readonly attribute is set"); - } catch (WindowsException exc) { - exc.rethrowAsIOException(this); - } - - if (WindowsFileStore.create(this).isReadOnly()) { - throw new AccessDeniedException( - this.getPathForExceptionMessage(), null, "Read-only file system"); - } - return; - } - } - - @Override - void implDelete(boolean failIfNotExists) throws IOException { - checkDelete(); - - WindowsFileAttributes attrs = null; - try { - // need to know if file is a directory or junction - attrs = WindowsFileAttributes.get(this, false); - if (attrs.isDirectory() || attrs.isDirectoryLink()) { - RemoveDirectory(getPathForWin32Calls()); - } else { - DeleteFile(getPathForWin32Calls()); - } - } catch (WindowsException x) { - - // no-op if file does not exist - if (!failIfNotExists && - (x.lastError() == ERROR_FILE_NOT_FOUND || - x.lastError() == ERROR_PATH_NOT_FOUND)) return; - - if (attrs != null && attrs.isDirectory()) { - // ERROR_ALREADY_EXISTS is returned when attempting to delete - // non-empty directory on SAMBA servers. - if (x.lastError() == ERROR_DIR_NOT_EMPTY || - x.lastError() == ERROR_ALREADY_EXISTS) - { - throw new DirectoryNotEmptyException( - getPathForExceptionMessage()); - } - } - x.rethrowAsIOException(this); - } - } - - @Override - public DirectoryStream newDirectoryStream(DirectoryStream.Filter filter) - throws IOException - { - checkRead(); - if (filter == null) - throw new NullPointerException(); - return new WindowsDirectoryStream(this, filter); - } - - @Override - public void implCopyTo(Path obj, CopyOption... options) throws IOException { - WindowsPath target = (WindowsPath)obj; - WindowsFileCopy.copy(this, target, options); - } - - @Override - public void implMoveTo(Path obj, CopyOption... options) throws IOException { - WindowsPath target = (WindowsPath)obj; - WindowsFileCopy.move(this, target, options); - } - - private boolean followLinks(LinkOption... options) { - boolean followLinks = true; - for (LinkOption option: options) { - if (option == LinkOption.NOFOLLOW_LINKS) { - followLinks = false; - continue; - } - if (option == null) - throw new NullPointerException(); - throw new AssertionError("Should not get here"); - } - return followLinks; - } - - @Override - @SuppressWarnings("unchecked") - public V - getFileAttributeView(Class view, LinkOption... options) - { - if (view == null) - throw new NullPointerException(); - boolean followLinks = followLinks(options); - if (view == BasicFileAttributeView.class) - return (V) WindowsFileAttributeViews.createBasicView(this, followLinks); - if (view == DosFileAttributeView.class) - return (V) WindowsFileAttributeViews.createDosView(this, followLinks); - if (view == AclFileAttributeView.class) - return (V) new WindowsAclFileAttributeView(this, followLinks); - if (view == FileOwnerAttributeView.class) - return (V) new FileOwnerAttributeViewImpl( - new WindowsAclFileAttributeView(this, followLinks)); - if (view == UserDefinedFileAttributeView.class) - return (V) new WindowsUserDefinedFileAttributeView(this, followLinks); - return (V) null; - } - - @Override - public DynamicFileAttributeView getFileAttributeView(String name, LinkOption... options) { - boolean followLinks = followLinks(options); - if (name.equals("basic")) - return WindowsFileAttributeViews.createBasicView(this, followLinks); - if (name.equals("dos")) - return WindowsFileAttributeViews.createDosView(this, followLinks); - if (name.equals("acl")) - return new WindowsAclFileAttributeView(this, followLinks); - if (name.equals("owner")) - return new FileOwnerAttributeViewImpl( - new WindowsAclFileAttributeView(this, followLinks)); - if (name.equals("user")) - return new WindowsUserDefinedFileAttributeView(this, followLinks); - return null; - } - - @Override - public WindowsPath createDirectory(FileAttribute... attrs) - throws IOException - { - checkWrite(); - WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.fromAttribute(attrs); - try { - CreateDirectory(getPathForWin32Calls(), sd.address()); - } catch (WindowsException x) { - x.rethrowAsIOException(this); - } finally { - sd.release(); - } - return this; - } - - @Override - public SeekableByteChannel newByteChannel(Set options, - FileAttribute... attrs) - throws IOException - { - WindowsSecurityDescriptor sd = - WindowsSecurityDescriptor.fromAttribute(attrs); - try { - return WindowsChannelFactory - .newFileChannel(getPathForWin32Calls(), - getPathForPermissionCheck(), - options, - sd.address()); - } catch (WindowsException x) { - x.rethrowAsIOException(this); - return null; // keep compiler happy - } finally { - sd.release(); - } - } - - @Override - public boolean isSameFile(Path obj) throws IOException { - if (this.equals(obj)) - return true; - if (!(obj instanceof WindowsPath)) // includes null check - return false; - WindowsPath other = (WindowsPath)obj; - - // check security manager access to both files - this.checkRead(); - other.checkRead(); - - // open both files and see if they are the same - long h1 = 0L; - try { - h1 = this.openForReadAttributeAccess(true); - } catch (WindowsException x) { - x.rethrowAsIOException(this); - } - try { - WindowsFileAttributes attrs1 = null; - try { - attrs1 = WindowsFileAttributes.readAttributes(h1); - } catch (WindowsException x) { - x.rethrowAsIOException(this); - } - long h2 = 0L; - try { - h2 = other.openForReadAttributeAccess(true); - } catch (WindowsException x) { - x.rethrowAsIOException(other); - } - try { - WindowsFileAttributes attrs2 = null; - try { - attrs2 = WindowsFileAttributes.readAttributes(h2); - } catch (WindowsException x) { - x.rethrowAsIOException(other); - } - return WindowsFileAttributes.isSameFile(attrs1, attrs2); - } finally { - CloseHandle(h2); - } - } finally { - CloseHandle(h1); - } - } - - @Override - public WindowsPath createSymbolicLink(Path obj, FileAttribute... attrs) - throws IOException - { - if (!getFileSystem().supportsLinks()) { - throw new UnsupportedOperationException("Symbolic links not supported " - + "on this operating system"); - } - - WindowsPath target = checkPath(obj); - - // no attributes allowed - if (attrs.length > 0) { - WindowsSecurityDescriptor.fromAttribute(attrs); // may throw NPE or UOE - throw new UnsupportedOperationException("Initial file attributes" + - "not supported when creating symbolic link"); - } - - // permission check - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new LinkPermission("symbolic")); - this.checkWrite(); - } - - /** - * Throw I/O exception for the drive-relative case because Windows - * creates a link with the resolved target for this case. - */ - if (target.type == WindowsPathType.DRIVE_RELATIVE) { - throw new IOException("Cannot create symbolic link to working directory relative target"); - } - - /* - * Windows treates symbolic links to directories differently than it - * does to other file types. For that reason we need to check if the - * target is a directory (or a directory junction). - */ - WindowsPath resolvedTarget; - if (target.type == WindowsPathType.RELATIVE) { - WindowsPath parent = getParent(); - resolvedTarget = (parent == null) ? target : parent.resolve(target); - } else { - resolvedTarget = resolve(target); - } - int flags = 0; - try { - WindowsFileAttributes wattrs = WindowsFileAttributes.get(resolvedTarget, false); - if (wattrs.isDirectory() || wattrs.isDirectoryLink()) - flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; - } catch (WindowsException x) { - // unable to access target so assume target is not a directory - } - - // create the link - try { - CreateSymbolicLink(getPathForWin32Calls(), - addPrefixIfNeeded(target.toString()), - flags); - } catch (WindowsException x) { - if (x.lastError() == ERROR_INVALID_REPARSE_DATA) { - x.rethrowAsIOException(this, target); - } else { - x.rethrowAsIOException(this); - } - } - return this; - } - - @Override - public Path createLink(Path obj) throws IOException { - WindowsPath existing = checkPath(obj); - - // permission check - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new LinkPermission("hard")); - this.checkWrite(); - existing.checkWrite(); - } - - // create hard link - try { - CreateHardLink(this.getPathForWin32Calls(), - existing.getPathForWin32Calls()); - } catch (WindowsException x) { - x.rethrowAsIOException(this, existing); - } - - return this; - } - - @Override - public WindowsPath readSymbolicLink() throws IOException { - if (!getFileSystem().supportsLinks()) { - throw new UnsupportedOperationException("symbolic links not supported"); - } - - // permission check - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - FilePermission perm = new FilePermission(getPathForPermissionCheck(), - SecurityConstants.FILE_READLINK_ACTION); - AccessController.checkPermission(perm); - } - - String target = WindowsLinkSupport.readLink(this); - return createFromNormalizedPath(getFileSystem(), target); - } - @Override public URI toUri() { return WindowsUriSupport.toUri(this); @@ -1282,21 +833,6 @@ class WindowsPath extends AbstractPath { return createFromNormalizedPath(getFileSystem(), rp); } - @Override - public boolean isHidden() throws IOException { - checkRead(); - WindowsFileAttributes attrs = null; - try { - attrs = WindowsFileAttributes.get(this, true); - } catch (WindowsException x) { - x.rethrowAsIOException(this); - } - // DOS hidden attribute not meaningful when set on directories - if (attrs.isDirectory()) - return false; - return attrs.isHidden(); - } - @Override public WatchKey register(WatchService watcher, WatchEvent.Kind[] events, diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java b/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java index b985d136f71..e898fd55fd2 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPathParser.java @@ -74,8 +74,6 @@ class WindowsPathParser { * Parses the given input as a Windows path */ static Result parse(String input) { - if (input == null || input.length() == 0) - throw new InvalidPathException(input, "Empty or null path"); return parse(input, true); } @@ -135,7 +133,7 @@ class WindowsPathParser { } } if (off == 0) { - if (isSlash(input.charAt(0))) { + if (len > 0 && isSlash(input.charAt(0))) { type = WindowsPathType.DIRECTORY_RELATIVE; root = "\\"; } else { diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java b/jdk/src/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java index f0c458761ac..7d9464e0ce4 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java @@ -214,7 +214,7 @@ class WindowsSecurityDescriptor { // map flags byte aceFlags = unsafe.getByte(aceAddress + OFFSETOF_FLAGS); - Set flags = new HashSet(); + Set flags = EnumSet.noneOf(AclEntryFlag.class); if ((aceFlags & OBJECT_INHERIT_ACE) != 0) flags.add(AclEntryFlag.FILE_INHERIT); if ((aceFlags & CONTAINER_INHERIT_ACE) != 0) @@ -226,7 +226,7 @@ class WindowsSecurityDescriptor { // map access mask int mask = unsafe.getInt(aceAddress + OFFSETOF_ACCESS_MASK); - Set perms = new HashSet(); + Set perms = EnumSet.noneOf(AclEntryPermission.class); if ((mask & FILE_READ_DATA) > 0) perms.add(AclEntryPermission.READ_DATA); if ((mask & FILE_WRITE_DATA) > 0) @@ -378,7 +378,7 @@ class WindowsSecurityDescriptor { AclInformation aclInfo = GetAclInformation(aclAddress); aceCount = aclInfo.aceCount(); } - ArrayList result = new ArrayList(aceCount); + ArrayList result = new ArrayList<>(aceCount); // decode each of the ACEs to AclEntry objects for (int i=0; i listUsingStreamEnumeration() throws IOException { - List list = new ArrayList(); + List list = new ArrayList<>(); try { FirstStream first = FindFirstStream(file.getPathForWin32Calls()); if (first != null) { @@ -114,7 +114,7 @@ class WindowsUserDefinedFileAttributeView NativeBuffer buffer = null; // result with names of alternative data streams - final List list = new ArrayList(); + final List list = new ArrayList<>(); try { buffer = NativeBuffers.getNativeBuffer(BUFFER_SIZE); @@ -216,7 +216,7 @@ class WindowsUserDefinedFileAttributeView // wrap with channel FileChannel fc = null; try { - Set opts = new HashSet(); + Set opts = new HashSet<>(); opts.add(READ); if (!followLinks) opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT); @@ -243,7 +243,7 @@ class WindowsUserDefinedFileAttributeView // wrap with channel FileChannel fc = null; try { - Set opts = new HashSet(); + Set opts = new HashSet<>(); opts.add(READ); if (!followLinks) opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT); @@ -298,7 +298,7 @@ class WindowsUserDefinedFileAttributeView x.rethrowAsIOException(file); } try { - Set opts = new HashSet(); + Set opts = new HashSet<>(); if (!followLinks) opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT); opts.add(CREATE); diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java b/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java index d86673cf134..53f2fa2af56 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsWatchService.java @@ -106,8 +106,11 @@ class WindowsWatchService // completion key (used to map I/O completion to WatchKey) private int completionKey; - WindowsWatchKey(AbstractWatchService watcher, FileKey fileKey) { - super(watcher); + WindowsWatchKey(Path dir, + AbstractWatchService watcher, + FileKey fileKey) + { + super(dir, watcher); this.fileKey = fileKey; } @@ -405,7 +408,7 @@ class WindowsWatchService WindowsWatchKey watchKey; if (existing == null) { // not registered so create new watch key - watchKey = new WindowsWatchKey(watcher, fk) + watchKey = new WindowsWatchKey(dir, watcher, fk) .init(handle, events, watchSubtree, buffer, countAddress, overlappedAddress, completionKey); // map file key to watch key diff --git a/jdk/src/windows/native/java/io/WinNTFileSystem_md.c b/jdk/src/windows/native/java/io/WinNTFileSystem_md.c index 23ff9e5dfec..566b697eb8f 100644 --- a/jdk/src/windows/native/java/io/WinNTFileSystem_md.c +++ b/jdk/src/windows/native/java/io/WinNTFileSystem_md.c @@ -220,19 +220,19 @@ Java_java_io_WinNTFileSystem_canonicalize0(JNIEnv *env, jobject this, /*we estimate the max length of memory needed as "currentDir. length + pathname.length" */ - int len = wcslen(path); + int len = (int)wcslen(path); len += currentDirLength(path, len); if (len > MAX_PATH_LENGTH - 1) { WCHAR *cp = (WCHAR*)malloc(len * sizeof(WCHAR)); if (cp != NULL) { if (wcanonicalize(path, cp, len) >= 0) { - rv = (*env)->NewString(env, cp, wcslen(cp)); + rv = (*env)->NewString(env, cp, (jsize)wcslen(cp)); } free(cp); } } else if (wcanonicalize(path, canonicalPath, MAX_PATH_LENGTH) >= 0) { - rv = (*env)->NewString(env, canonicalPath, wcslen(canonicalPath)); + rv = (*env)->NewString(env, canonicalPath, (jsize)wcslen(canonicalPath)); } } END_UNICODE_STRING(env, path); if (rv == NULL) { @@ -251,14 +251,14 @@ Java_java_io_WinNTFileSystem_canonicalizeWithPrefix0(JNIEnv *env, jobject this, WCHAR canonicalPath[MAX_PATH_LENGTH]; WITH_UNICODE_STRING(env, canonicalPrefixString, canonicalPrefix) { WITH_UNICODE_STRING(env, pathWithCanonicalPrefixString, pathWithCanonicalPrefix) { - int len = wcslen(canonicalPrefix) + MAX_PATH; + int len = (int)wcslen(canonicalPrefix) + MAX_PATH; if (len > MAX_PATH_LENGTH) { WCHAR *cp = (WCHAR*)malloc(len * sizeof(WCHAR)); if (cp != NULL) { if (wcanonicalizeWithPrefix(canonicalPrefix, pathWithCanonicalPrefix, cp, len) >= 0) { - rv = (*env)->NewString(env, cp, wcslen(cp)); + rv = (*env)->NewString(env, cp, (jsize)wcslen(cp)); } free(cp); } @@ -266,7 +266,7 @@ Java_java_io_WinNTFileSystem_canonicalizeWithPrefix0(JNIEnv *env, jobject this, if (wcanonicalizeWithPrefix(canonicalPrefix, pathWithCanonicalPrefix, canonicalPath, MAX_PATH_LENGTH) >= 0) { - rv = (*env)->NewString(env, canonicalPath, wcslen(canonicalPath)); + rv = (*env)->NewString(env, canonicalPath, (jsize)wcslen(canonicalPath)); } } END_UNICODE_STRING(env, pathWithCanonicalPrefix); } END_UNICODE_STRING(env, canonicalPrefix); @@ -358,7 +358,7 @@ Java_java_io_WinNTFileSystem_getBooleanAttributes(JNIEnv *env, jobject this, } else { /* pagefile.sys is a special case */ if (GetLastError() == ERROR_SHARING_VIOLATION) { rv = java_io_FileSystem_BA_EXISTS; - if ((pathlen = wcslen(pathbuf)) >= SPECIALFILE_NAMELEN && + if ((pathlen = (jint)wcslen(pathbuf)) >= SPECIALFILE_NAMELEN && (_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN, L"pagefile.sys") == 0) || (_wcsicmp(pathbuf + pathlen - SPECIALFILE_NAMELEN, @@ -625,7 +625,7 @@ Java_java_io_WinNTFileSystem_list(JNIEnv *env, jobject this, jobject file) } /* Remove trailing space chars from directory name */ - len = wcslen(search_path); + len = (int)wcslen(search_path); while (search_path[len-1] == ' ') { len--; } @@ -668,7 +668,7 @@ Java_java_io_WinNTFileSystem_list(JNIEnv *env, jobject this, jobject file) || !wcscmp(find_data.cFileName, L"..")) continue; name = (*env)->NewString(env, find_data.cFileName, - wcslen(find_data.cFileName)); + (jsize)wcslen(find_data.cFileName)); if (name == NULL) return NULL; // error; if (len == maxlen) { @@ -819,7 +819,7 @@ Java_java_io_WinNTFileSystem_getDriveDirectory(JNIEnv *env, jobject this, jchar *pf = p; if (p == NULL) return NULL; if (iswalpha(*p) && (p[1] == L':')) p += 2; - ret = (*env)->NewString(env, p, wcslen(p)); + ret = (*env)->NewString(env, p, (jsize)wcslen(p)); free (pf); return ret; } diff --git a/jdk/src/windows/native/java/io/canonicalize_md.c b/jdk/src/windows/native/java/io/canonicalize_md.c index f829ce3371f..e0eadb6b82f 100644 --- a/jdk/src/windows/native/java/io/canonicalize_md.c +++ b/jdk/src/windows/native/java/io/canonicalize_md.c @@ -479,7 +479,7 @@ wcanonicalize(WCHAR *orig_path, WCHAR *result, int size) assert(*src == L'\\'); /* Invariant */ *p = L'\0'; /* Temporarily clear separator */ - if ((pathlen = wcslen(path)) > MAX_PATH - 1) { + if ((pathlen = (int)wcslen(path)) > MAX_PATH - 1) { pathbuf = getPrefixed(path, pathlen); h = FindFirstFileW(pathbuf, &fd); /* Look up prefix */ free(pathbuf); @@ -538,7 +538,7 @@ wcanonicalizeWithPrefix(WCHAR *canonicalPrefix, WCHAR *pathWithCanonicalPrefix, dend = dst + size; /* Don't go to or past here */ - if ((pathlen=wcslen(pathWithCanonicalPrefix)) > MAX_PATH - 1) { + if ((pathlen=(int)wcslen(pathWithCanonicalPrefix)) > MAX_PATH - 1) { pathbuf = getPrefixed(pathWithCanonicalPrefix, pathlen); h = FindFirstFileW(pathbuf, &fd); /* Look up prefix */ free(pathbuf); diff --git a/jdk/src/windows/native/java/io/io_util_md.c b/jdk/src/windows/native/java/io/io_util_md.c index 3b6723eed6b..81a69392096 100644 --- a/jdk/src/windows/native/java/io/io_util_md.c +++ b/jdk/src/windows/native/java/io/io_util_md.c @@ -104,7 +104,7 @@ currentDirLength(const WCHAR* ps, int pathlen) { else return 0; /* invalid drive name. */ dir = currentDir(di); if (dir != NULL){ - dirlen = wcslen(dir); + dirlen = (int)wcslen(dir); free(dir); } return dirlen; @@ -115,7 +115,7 @@ currentDirLength(const WCHAR* ps, int pathlen) { int dirlen = -1; dir = _wgetcwd(NULL, MAX_PATH); if (dir != NULL) { - curDirLenCached = wcslen(dir); + curDirLenCached = (int)wcslen(dir); free(dir); } } @@ -165,7 +165,7 @@ pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE) { int max_path = 248; /* CreateDirectoryW() has the limit of 248 */ WITH_UNICODE_STRING(env, path, ps) { - pathlen = wcslen(ps); + pathlen = (int)wcslen(ps); if (pathlen != 0) { if (pathlen > 2 && (ps[0] == L'\\' && ps[1] == L'\\' || //UNC diff --git a/jdk/src/windows/native/sun/nio/ch/Iocp.c b/jdk/src/windows/native/sun/nio/ch/Iocp.c index d962c166caa..773a870ca2b 100644 --- a/jdk/src/windows/native/sun/nio/ch/Iocp.c +++ b/jdk/src/windows/native/sun/nio/ch/Iocp.c @@ -72,9 +72,10 @@ JNIEXPORT jlong JNICALL Java_sun_nio_ch_Iocp_createIoCompletionPort(JNIEnv* env, jclass this, jlong handle, jlong existingPort, jint completionKey, jint concurrency) { + ULONG_PTR ck = completionKey; HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(handle), (HANDLE)jlong_to_ptr(existingPort), - (DWORD)completionKey, + ck, (DWORD)concurrency); if (port == NULL) { JNU_ThrowIOExceptionWithLastError(env, "CreateIoCompletionPort failed"); @@ -96,7 +97,7 @@ Java_sun_nio_ch_Iocp_getQueuedCompletionStatus(JNIEnv* env, jclass this, jlong completionPort, jobject obj) { DWORD bytesTransferred; - DWORD completionKey; + ULONG_PTR completionKey; OVERLAPPED *lpOverlapped; BOOL res; diff --git a/jdk/src/windows/native/sun/nio/fs/RegistryFileTypeDetector.c b/jdk/src/windows/native/sun/nio/fs/RegistryFileTypeDetector.c index a07718e480d..6d082271015 100644 --- a/jdk/src/windows/native/sun/nio/fs/RegistryFileTypeDetector.c +++ b/jdk/src/windows/native/sun/nio/fs/RegistryFileTypeDetector.c @@ -51,7 +51,7 @@ Java_sun_nio_fs_RegistryFileTypeDetector_queryStringValue(JNIEnv* env, jclass th res = RegQueryValueExW(hKey, lpValueName, NULL, &type, (LPBYTE)&data, &size); if (res == ERROR_SUCCESS) { if (type == REG_SZ) { - jsize len = wcslen((WCHAR*)data); + jsize len = (jsize)wcslen((WCHAR*)data); result = (*env)->NewString(env, (const jchar*)&data, len); } } diff --git a/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c b/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c index 61a63b484e5..d9d8a9d7cb2 100644 --- a/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c +++ b/jdk/src/windows/native/sun/nio/fs/WindowsNativeDispatcher.c @@ -368,7 +368,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstFile0(JNIEnv* env, jclass this, HANDLE handle = FindFirstFileW(lpFileName, &data); if (handle != INVALID_HANDLE_VALUE) { - jstring name = (*env)->NewString(env, data.cFileName, wcslen(data.cFileName)); + jstring name = (*env)->NewString(env, data.cFileName, (jsize)wcslen(data.cFileName)); if (name == NULL) return; (*env)->SetLongField(env, obj, findFirst_handle, ptr_to_jlong(handle)); @@ -401,7 +401,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_FindNextFile(JNIEnv* env, jclass this, WIN32_FIND_DATAW* data = (WIN32_FIND_DATAW*)jlong_to_ptr(dataAddress); if (FindNextFileW(h, data) != 0) { - return (*env)->NewString(env, data->cFileName, wcslen(data->cFileName)); + return (*env)->NewString(env, data->cFileName, (jsize)wcslen(data->cFileName)); } else { if (GetLastError() != ERROR_NO_MORE_FILES) throwWindowsException(env, GetLastError()); @@ -424,7 +424,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_FindFirstStream0(JNIEnv* env, jclass thi handle = (*FindFirstStream_func)(lpFileName, FindStreamInfoStandard, &data, 0); if (handle != INVALID_HANDLE_VALUE) { - jstring name = (*env)->NewString(env, data.cStreamName, wcslen(data.cStreamName)); + jstring name = (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName)); if (name == NULL) return; (*env)->SetLongField(env, obj, findStream_handle, ptr_to_jlong(handle)); @@ -452,7 +452,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_FindNextStream(JNIEnv* env, jclass this, } if ((*FindNextStream_func)(h, &data) != 0) { - return (*env)->NewString(env, data.cStreamName, wcslen(data.cStreamName)); + return (*env)->NewString(env, data.cStreamName, (jsize)wcslen(data.cStreamName)); } else { if (GetLastError() != ERROR_HANDLE_EOF) throwWindowsException(env, GetLastError()); @@ -1224,9 +1224,10 @@ JNIEXPORT jlong JNICALL Java_sun_nio_fs_WindowsNativeDispatcher_CreateIoCompletionPort(JNIEnv* env, jclass this, jlong fileHandle, jlong existingPort, jint completionKey) { + ULONG_PTR ck = completionKey; HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(fileHandle), (HANDLE)jlong_to_ptr(existingPort), - (DWORD)completionKey, + ck, 0); if (port == NULL) { throwWindowsException(env, GetLastError()); @@ -1239,7 +1240,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_GetQueuedCompletionStatus0(JNIEnv* env, jlong completionPort, jobject obj) { DWORD bytesTransferred; - DWORD completionKey; + ULONG_PTR completionKey; OVERLAPPED *lpOverlapped; BOOL res; diff --git a/jdk/test/com/sun/jndi/ldap/LdapName/Case.java b/jdk/test/com/sun/jndi/ldap/LdapName/Case.java index 774d93bdf29..e37b8d9ff86 100644 --- a/jdk/test/com/sun/jndi/ldap/LdapName/Case.java +++ b/jdk/test/com/sun/jndi/ldap/LdapName/Case.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /* * @test * @bug 4278094 diff --git a/jdk/test/com/sun/jndi/ldap/LdapName/EmptyNameSearch.java b/jdk/test/com/sun/jndi/ldap/LdapName/EmptyNameSearch.java new file mode 100644 index 00000000000..8a69abdc82f --- /dev/null +++ b/jdk/test/com/sun/jndi/ldap/LdapName/EmptyNameSearch.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6997561 + * @summary A request for better error handling in JNDI + */ + +import java.net.Socket; +import java.net.ServerSocket; +import java.io.*; +import javax.naming.*; +import javax.naming.directory.*; +import javax.naming.ldap.*; +import java.util.Collections; +import java.util.Hashtable; + +public class EmptyNameSearch { + + public static void main(String[] args) throws Exception { + + // Start the LDAP server + Server s = new Server(); + s.start(); + Thread.sleep(3000); + + // Setup JNDI parameters + Hashtable env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + env.put(Context.PROVIDER_URL, "ldap://localhost:" + s.getPortNumber()); + + try { + + // Create initial context + System.out.println("Client: connecting..."); + DirContext ctx = new InitialDirContext(env); + + System.out.println("Client: performing search..."); + ctx.search(new LdapName(Collections.EMPTY_LIST), "cn=*", null); + ctx.close(); + + // Exit + throw new RuntimeException(); + + } catch (NamingException e) { + System.err.println("Passed: caught the expected Exception - " + e); + + } catch (Exception e) { + System.err.println("Failed: caught an unexpected Exception - " + e); + throw e; + } + } + + static class Server extends Thread { + + private int serverPort = 0; + private byte[] bindResponse = { + 0x30, 0x0C, 0x02, 0x01, 0x01, 0x61, 0x07, 0x0A, + 0x01, 0x00, 0x04, 0x00, 0x04, 0x00 + }; + private byte[] searchResponse = { + 0x30, 0x0C, 0x02, 0x01, 0x02, 0x65, 0x07, 0x0A, + 0x01, 0x02, 0x04, 0x00, 0x04, 0x00 + }; + + Server() { + } + + public int getPortNumber() { + return serverPort; + } + + public void run() { + try { + ServerSocket serverSock = new ServerSocket(0); + serverPort = serverSock.getLocalPort(); + System.out.println("Server: listening on port " + serverPort); + + Socket socket = serverSock.accept(); + System.out.println("Server: connection accepted"); + + InputStream in = socket.getInputStream(); + OutputStream out = socket.getOutputStream(); + + // Read the LDAP BindRequest + System.out.println("Server: reading request..."); + while (in.read() != -1) { + in.skip(in.available()); + break; + } + + // Write an LDAP BindResponse + System.out.println("Server: writing response..."); + out.write(bindResponse); + out.flush(); + + // Read the LDAP SearchRequest + System.out.println("Server: reading request..."); + while (in.read() != -1) { + in.skip(in.available()); + break; + } + + // Write an LDAP SearchResponse + System.out.println("Server: writing response..."); + out.write(searchResponse); + out.flush(); + + in.close(); + out.close(); + socket.close(); + serverSock.close(); + + } catch (IOException e) { + // ignore + } + } + } +} diff --git a/jdk/test/com/sun/jndi/ldap/LdapName/UnescapeTest.java b/jdk/test/com/sun/jndi/ldap/LdapName/UnescapeTest.java index a2f2821dd23..75ded9c80cb 100644 --- a/jdk/test/com/sun/jndi/ldap/LdapName/UnescapeTest.java +++ b/jdk/test/com/sun/jndi/ldap/LdapName/UnescapeTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /* * @test * @bug 4892070 diff --git a/jdk/test/com/sun/jndi/ldap/ReadTimeoutTest.java b/jdk/test/com/sun/jndi/ldap/ReadTimeoutTest.java index bf21c10ad52..b5349da69c2 100644 --- a/jdk/test/com/sun/jndi/ldap/ReadTimeoutTest.java +++ b/jdk/test/com/sun/jndi/ldap/ReadTimeoutTest.java @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /** * @test * @bug 6176036 diff --git a/jdk/test/demo/zipfs/Basic.java b/jdk/test/demo/zipfs/Basic.java index 8341b939273..c0e478bc8f2 100644 --- a/jdk/test/demo/zipfs/Basic.java +++ b/jdk/test/demo/zipfs/Basic.java @@ -48,9 +48,9 @@ public class Basic { if (!found) throw new RuntimeException("'jar' provider not installed"); - // Test: FileSystems#newFileSystem(FileRef) + // Test: FileSystems#newFileSystem(Path) Map env = new HashMap(); - FileSystems.newFileSystem(zipfile, env, null).close(); + FileSystems.newFileSystem(zipfile, null).close(); // Test: FileSystems#newFileSystem(URI) URI uri = new URI("jar", zipfile.toUri().toString(), null); @@ -69,14 +69,11 @@ public class Basic { // Test: DirectoryStream found = false; - DirectoryStream stream = fs.getPath("/").newDirectoryStream(); - try { + try (DirectoryStream stream = Files.newDirectoryStream(fs.getPath("/"))) { for (Path entry: stream) { found = entry.toString().equals("/META-INF/"); if (found) break; } - } finally { - stream.close(); } if (!found) @@ -84,21 +81,21 @@ public class Basic { // Test: copy file from zip file to current (scratch) directory Path source = fs.getPath("/META-INF/services/java.nio.file.spi.FileSystemProvider"); - if (source.exists()) { - Path target = Paths.get(source.getName().toString()); - source.copyTo(target, StandardCopyOption.REPLACE_EXISTING); + if (Files.exists(source)) { + Path target = Paths.get(source.getFileName().toString()); + Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING); try { - long s1 = Attributes.readBasicFileAttributes(source).size(); - long s2 = Attributes.readBasicFileAttributes(target).size(); + long s1 = Files.readAttributes(source, BasicFileAttributes.class).size(); + long s2 = Files.readAttributes(target, BasicFileAttributes.class).size(); if (s2 != s1) throw new RuntimeException("target size != source size"); } finally { - target.delete(); + Files.delete(target); } } // Test: FileStore - FileStore store = fs.getPath("/").getFileStore(); + FileStore store = Files.getFileStore(fs.getPath("/")); if (!store.supportsFileAttributeView("basic")) throw new RuntimeException("BasicFileAttributeView should be supported"); @@ -107,7 +104,7 @@ public class Basic { if (fs.isOpen()) throw new RuntimeException("FileSystem should be closed"); try { - fs.getPath("/missing").checkAccess(AccessMode.READ); + fs.provider().checkAccess(fs.getPath("/missing"), AccessMode.READ); } catch (ClosedFileSystemException x) { } } @@ -125,9 +122,9 @@ public class Basic { public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { - if (dir.getName() != null) { + if (dir.getFileName() != null) { indent(); - System.out.println(dir.getName() + "/"); + System.out.println(dir.getFileName() + "/"); indent++; } return FileVisitResult.CONTINUE; @@ -138,7 +135,7 @@ public class Basic { BasicFileAttributes attrs) { indent(); - System.out.print(file.getName()); + System.out.print(file.getFileName()); if (attrs.isRegularFile()) System.out.format(" (%d)", attrs.size()); System.out.println(); @@ -151,7 +148,7 @@ public class Basic { { if (exc != null) super.postVisitDirectory(dir, exc); - if (dir.getName() != null) + if (dir.getFileName() != null) indent--; return FileVisitResult.CONTINUE; } diff --git a/jdk/test/demo/zipfs/PathOps.java b/jdk/test/demo/zipfs/PathOps.java index 64b78e64ce4..ea097396dbb 100644 --- a/jdk/test/demo/zipfs/PathOps.java +++ b/jdk/test/demo/zipfs/PathOps.java @@ -100,7 +100,7 @@ public class PathOps { PathOps name(String expected) { out.println("check name"); checkPath(); - check(path.getName(), expected); + check(path.getFileName(), expected); return this; } @@ -197,7 +197,7 @@ public class PathOps { try { out.println("check two paths are same"); checkPath(); - check(path.isSameFile(test(target).path()), true); + check(Files.isSameFile(path, test(target).path()), true); } catch (IOException ioe) { fail(); } @@ -252,31 +252,41 @@ public class PathOps { .name("foo"); // startsWith + test("") + .starts("") + .notStarts("/"); test("/") .starts("/") .notStarts("/foo"); test("/foo") .starts("/") .starts("/foo") - .notStarts("/f"); + .notStarts("/f") + .notStarts(""); test("/foo/bar") .starts("/") .starts("/foo") + .starts("/foo/") .starts("/foo/bar") .notStarts("/f") .notStarts("foo") - .notStarts("foo/bar"); + .notStarts("foo/bar") + .notStarts(""); test("foo") .starts("foo") .notStarts("f"); test("foo/bar") .starts("foo") + .starts("foo/") .starts("foo/bar") .notStarts("f") .notStarts("/foo") .notStarts("/foo/bar"); // endsWith + test("") + .ends("") + .notEnds("/"); test("/") .ends("/") .notEnds("foo") @@ -288,14 +298,24 @@ public class PathOps { test("/foo/bar") .ends("bar") .ends("foo/bar") + .ends("foo/bar/") + .ends("/foo/bar") + .notEnds("/bar"); + test("/foo/bar/") + .ends("bar") + .ends("foo/bar") + .ends("foo/bar/") .ends("/foo/bar") .notEnds("/bar"); test("foo") .ends("foo"); test("foo/bar") .ends("bar") + .ends("bar/") + .ends("foo/bar/") .ends("foo/bar"); + // elements test("a/b/c") .element(0,"a") @@ -309,6 +329,8 @@ public class PathOps { .absolute(); test("tmp") .notAbsolute(); + test("") + .notAbsolute(); // resolve test("/tmp") @@ -320,7 +342,7 @@ public class PathOps { // relativize test("/a/b/c") - .relativize("/a/b/c", null) + .relativize("/a/b/c", "") .relativize("/a/b/c/d/e", "d/e") .relativize("/a/x", "../../x"); @@ -332,7 +354,7 @@ public class PathOps { test("/foo") .normalize("/foo"); test(".") - .normalize(null); + .normalize(""); test("..") .normalize(".."); test("/..") @@ -344,7 +366,7 @@ public class PathOps { test("./foo") .normalize("foo"); test("foo/..") - .normalize(null); + .normalize(""); test("../foo") .normalize("../foo"); test("../../foo") @@ -411,13 +433,13 @@ public class PathOps { } try { - path.startsWith(null); + path.startsWith((Path)null); throw new RuntimeException("NullPointerException not thrown"); } catch (NullPointerException npe) { } try { - path.endsWith(null); + path.endsWith((Path)null); throw new RuntimeException("NullPointerException not thrown"); } catch (NullPointerException npe) { } @@ -427,8 +449,7 @@ public class PathOps { public static void main(String[] args) throws Throwable { Path zipfile = Paths.get(args[0]); - Map env = new HashMap(); - fs = FileSystems.newFileSystem(zipfile, env, null); + fs = FileSystems.newFileSystem(zipfile, null); npes(); doPathOpTests(); fs.close(); diff --git a/jdk/test/demo/zipfs/ZipFSTester.java b/jdk/test/demo/zipfs/ZipFSTester.java index d4c5b44007b..14aebbdf685 100644 --- a/jdk/test/demo/zipfs/ZipFSTester.java +++ b/jdk/test/demo/zipfs/ZipFSTester.java @@ -25,6 +25,7 @@ import java.io.*; import java.nio.*; import java.nio.channels.*; import java.nio.file.*; +import java.nio.file.spi.*; import java.nio.file.attribute.*; import java.net.*; import java.util.*; @@ -40,15 +41,13 @@ import static java.nio.file.StandardCopyOption.*; public class ZipFSTester { public static void main(String[] args) throws Throwable { - FileSystem fs = null; - try { - fs = newZipFileSystem(Paths.get(args[0]), new HashMap()); + + try (FileSystem fs = newZipFileSystem(Paths.get(args[0]), + new HashMap())) + { test0(fs); test1(fs); test2(fs); // more tests - } finally { - if (fs != null) - fs.close(); } } @@ -63,17 +62,17 @@ public class ZipFSTester { } for (String pname : list) { Path path = fs.getPath(pname); - if (!path.exists()) + if (!Files.exists(path)) throw new RuntimeException("path existence check failed!"); while ((path = path.getParent()) != null) { - if (!path.exists()) + if (!Files.exists(path)) throw new RuntimeException("parent existence check failed!"); } } } } - static void test1(FileSystem fs) + static void test1(FileSystem fs0) throws Exception { Random rdm = new Random(); @@ -81,16 +80,26 @@ public class ZipFSTester { Path tmpfsPath = getTempPath(); Map env = new HashMap(); env.put("create", "true"); - FileSystem fs0 = newZipFileSystem(tmpfsPath, env); - z2zcopy(fs, fs0, "/", 0); - fs0.close(); // sync to file + try (FileSystem copy = newZipFileSystem(tmpfsPath, env)) { + z2zcopy(fs0, copy, "/", 0); + } + + try (FileSystem fs = newZipFileSystem(tmpfsPath, new HashMap())) { + + FileSystemProvider provider = fs.provider(); + // newFileSystem(path...) should not throw exception + try (FileSystem fsPath = provider.newFileSystem(tmpfsPath, new HashMap())){} + try (FileSystem fsUri = provider.newFileSystem( + new URI("jar", tmpfsPath.toUri().toString(), null), + new HashMap())) + { + throw new RuntimeException("newFileSystem(uri...) does not throw exception"); + } catch (FileSystemAlreadyExistsException fsaee) {} - fs = newZipFileSystem(tmpfsPath, new HashMap()); - try { // prepare a src Path src = getTempPath(); String tmpName = src.toString(); - OutputStream os = src.newOutputStream(); + OutputStream os = Files.newOutputStream(src); byte[] bits = new byte[12345]; rdm.nextBytes(bits); os.write(bits); @@ -98,37 +107,37 @@ public class ZipFSTester { // copyin Path dst = getPathWithParents(fs, tmpName); - src.copyTo(dst); + Files.copy(src, dst); checkEqual(src, dst); // copy Path dst2 = getPathWithParents(fs, "/xyz" + rdm.nextInt(100) + "/efg" + rdm.nextInt(100) + "/foo.class"); - dst.copyTo(dst2); + Files.copy(dst, dst2); //dst.moveTo(dst2); checkEqual(src, dst2); // delete - dst.delete(); - if (dst.exists()) + Files.delete(dst); + if (Files.exists(dst)) throw new RuntimeException("Failed!"); // moveout Path dst3 = Paths.get(tmpName + "_Tmp"); - dst2.moveTo(dst3); + Files.move(dst2, dst3); checkEqual(src, dst3); // delete - if (dst2.exists()) + if (Files.exists(dst2)) throw new RuntimeException("Failed!"); - dst3.delete(); - if (dst3.exists()) + Files.delete(dst3); + if (Files.exists(dst3)) throw new RuntimeException("Failed!"); // newInputStream on dir Path parent = dst2.getParent(); try { - parent.newInputStream(); + Files.newInputStream(parent); throw new RuntimeException("Failed"); } catch (FileSystemException e) { e.printStackTrace(); // expected fse @@ -147,17 +156,15 @@ public class ZipFSTester { Path tmp = Paths.get(tmpName + "_Tmp"); fchCopy(dst, tmp); // out checkEqual(src, tmp); - tmp.delete(); + Files.delete(tmp); // test channels channel(fs, dst); - dst.delete(); - src.delete(); + Files.delete(dst); + Files.delete(src); } finally { - if (fs != null) - fs.close(); - if (tmpfsPath.exists()) - tmpfsPath.delete(); + if (Files.exists(tmpfsPath)) + Files.delete(tmpfsPath); } } @@ -242,7 +249,7 @@ public class ZipFSTester { while (itr.hasNext()) { String path = itr.next(); try { - if (fs2.getPath(path).exists()) { + if (Files.exists(fs2.getPath(path))) { z2zmove(fs2, fs3, path); itr.remove(); } @@ -296,15 +303,16 @@ public class ZipFSTester { fs4.close(); System.out.printf("failed=%d%n", failed); - fs1Path.delete(); - fs2Path.delete(); - fs3Path.delete(); + Files.delete(fs1Path); + Files.delete(fs2Path); + Files.delete(fs3Path); } private static FileSystem newZipFileSystem(Path path, Map env) - throws IOException + throws Exception { - return FileSystems.newFileSystem(path, env, null); + return FileSystems.newFileSystem( + new URI("jar", path.toUri().toString(), null), env, null); } private static Path getTempPath() throws IOException @@ -317,11 +325,11 @@ public class ZipFSTester { private static void list(Path path, List files, List dirs ) throws IOException { - if (Attributes.readBasicFileAttributes(path).isDirectory()) { - DirectoryStream ds = path.newDirectoryStream(); - for (Path child : ds) - list(child, files, dirs); - ds.close(); + if (Files.isDirectory(path)) { + try (DirectoryStream ds = Files.newDirectoryStream(path)) { + for (Path child : ds) + list(child, files, dirs); + } dirs.add(path.toString()); } else { files.add(path.toString()); @@ -335,26 +343,26 @@ public class ZipFSTester { Path srcPath = src.getPath(path); Path dstPath = dst.getPath(path); - if (Boolean.TRUE.equals(srcPath.getAttribute("isDirectory"))) { - if (!dstPath.exists()) { + if (Files.isDirectory(srcPath)) { + if (!Files.exists(dstPath)) { try { mkdirs(dstPath); } catch (FileAlreadyExistsException x) {} } - DirectoryStream ds = srcPath.newDirectoryStream(); - for (Path child : ds) { - z2zcopy(src, dst, - path + (path.endsWith("/")?"":"/") + child.getName(), - method); + try (DirectoryStream ds = Files.newDirectoryStream(srcPath)) { + for (Path child : ds) { + z2zcopy(src, dst, + path + (path.endsWith("/")?"":"/") + child.getFileName(), + method); + } } - ds.close(); } else { try { - if (dstPath.exists()) + if (Files.exists(dstPath)) return; switch (method) { case 0: - srcPath.copyTo(dstPath); + Files.copy(srcPath, dstPath); break; case 1: chCopy(srcPath, dstPath); @@ -374,21 +382,21 @@ public class ZipFSTester { Path srcPath = src.getPath(path); Path dstPath = dst.getPath(path); - if (Boolean.TRUE.equals(srcPath.getAttribute("isDirectory"))) { - if (!dstPath.exists()) + if (Files.isDirectory(srcPath)) { + if (!Files.exists(dstPath)) mkdirs(dstPath); - DirectoryStream ds = srcPath.newDirectoryStream(); - for (Path child : ds) { - z2zmove(src, dst, - path + (path.endsWith("/")?"":"/") + child.getName()); + try (DirectoryStream ds = Files.newDirectoryStream(srcPath)) { + for (Path child : ds) { + z2zmove(src, dst, + path + (path.endsWith("/")?"":"/") + child.getFileName()); + } } - ds.close(); } else { //System.out.println("moving..." + path); Path parent = dstPath.getParent(); - if (parent != null && parent.notExists()) + if (parent != null && Files.notExists(parent)) mkdirs(parent); - srcPath.moveTo(dstPath); + Files.move(srcPath, dstPath); } } @@ -409,7 +417,7 @@ public class ZipFSTester { BasicFileAttributes attrs) { indent(); - System.out.printf("%s%n", file.getName().toString()); + System.out.printf("%s%n", file.getFileName().toString()); return FileVisitResult.CONTINUE; } @@ -435,20 +443,20 @@ public class ZipFSTester { } private static void mkdirs(Path path) throws IOException { - if (path.exists()) + if (Files.exists(path)) return; path = path.toAbsolutePath(); Path parent = path.getParent(); if (parent != null) { - if (parent.notExists()) + if (Files.notExists(parent)) mkdirs(parent); } - path.createDirectory(); + Files.createDirectory(path); } private static void rmdirs(Path path) throws IOException { while (path != null && path.getNameCount() != 0) { - path.delete(); + Files.delete(path); path = path.getParent(); } } @@ -460,12 +468,11 @@ public class ZipFSTester { // src.toString(), dst.toString()); //streams - InputStream isSrc = src.newInputStream(); - InputStream isDst = dst.newInputStream(); byte[] bufSrc = new byte[8192]; byte[] bufDst = new byte[8192]; - - try { + try (InputStream isSrc = Files.newInputStream(src); + InputStream isDst = Files.newInputStream(dst)) + { int nSrc = 0; while ((nSrc = isSrc.read(bufSrc)) != -1) { int nDst = 0; @@ -487,24 +494,21 @@ public class ZipFSTester { nSrc--; } } - } finally { - isSrc.close(); - isDst.close(); } // channels - SeekableByteChannel chSrc = src.newByteChannel(); - SeekableByteChannel chDst = dst.newByteChannel(); - if (chSrc.size() != chDst.size()) { - System.out.printf("src[%s].size=%d, dst[%s].size=%d%n", - chSrc.toString(), chSrc.size(), - chDst.toString(), chDst.size()); - throw new RuntimeException("CHECK FAILED!"); - } - ByteBuffer bbSrc = ByteBuffer.allocate(8192); - ByteBuffer bbDst = ByteBuffer.allocate(8192); + try (SeekableByteChannel chSrc = Files.newByteChannel(src); + SeekableByteChannel chDst = Files.newByteChannel(dst)) + { + if (chSrc.size() != chDst.size()) { + System.out.printf("src[%s].size=%d, dst[%s].size=%d%n", + chSrc.toString(), chSrc.size(), + chDst.toString(), chDst.size()); + throw new RuntimeException("CHECK FAILED!"); + } + ByteBuffer bbSrc = ByteBuffer.allocate(8192); + ByteBuffer bbDst = ByteBuffer.allocate(8192); - try { int nSrc = 0; while ((nSrc = chSrc.read(bbSrc)) != -1) { int nDst = chDst.read(bbDst); @@ -526,9 +530,6 @@ public class ZipFSTester { } } catch (IOException x) { x.printStackTrace(); - } finally { - chSrc.close(); - chDst.close(); } } @@ -540,23 +541,19 @@ public class ZipFSTester { openwrite.add(CREATE_NEW); openwrite.add(WRITE); - FileChannel srcFc = src.getFileSystem() - .provider() - .newFileChannel(src, read); - FileChannel dstFc = dst.getFileSystem() - .provider() - .newFileChannel(dst, openwrite); - - try { + try (FileChannel srcFc = src.getFileSystem() + .provider() + .newFileChannel(src, read); + FileChannel dstFc = dst.getFileSystem() + .provider() + .newFileChannel(dst, openwrite)) + { ByteBuffer bb = ByteBuffer.allocate(8192); while (srcFc.read(bb) >= 0) { bb.flip(); dstFc.write(bb); bb.clear(); } - } finally { - srcFc.close(); - dstFc.close(); } } @@ -568,35 +565,29 @@ public class ZipFSTester { openwrite.add(CREATE_NEW); openwrite.add(WRITE); - SeekableByteChannel srcCh = src.newByteChannel(read); - SeekableByteChannel dstCh = dst.newByteChannel(openwrite); + try (SeekableByteChannel srcCh = Files.newByteChannel(src, read); + SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite)) + { - try { ByteBuffer bb = ByteBuffer.allocate(8192); while (srcCh.read(bb) >= 0) { bb.flip(); dstCh.write(bb); bb.clear(); } - } finally { - srcCh.close(); - dstCh.close(); } } private static void streamCopy(Path src, Path dst) throws IOException { - InputStream isSrc = src.newInputStream(); - OutputStream osDst = dst.newOutputStream(); byte[] buf = new byte[8192]; - try { + try (InputStream isSrc = Files.newInputStream(src); + OutputStream osDst = Files.newOutputStream(dst)) + { int n = 0; while ((n = isSrc.read(buf)) != -1) { osDst.write(buf, 0, n); } - } finally { - isSrc.close(); - osDst.close(); } } @@ -604,31 +595,35 @@ public class ZipFSTester { throws Exception { System.out.println("test ByteChannel..."); - SeekableByteChannel sbc = path.newByteChannel(); Set read = new HashSet<>(); read.add(READ); - System.out.printf(" sbc[0]: pos=%d, size=%d%n", sbc.position(), sbc.size()); - ByteBuffer bb = ByteBuffer.allocate((int)sbc.size()); - int n = sbc.read(bb); - System.out.printf(" sbc[1]: read=%d, pos=%d, size=%d%n", - n, sbc.position(), sbc.size()); - ByteBuffer bb2 = ByteBuffer.allocate((int)sbc.size()); + int n = 0; + ByteBuffer bb = null; + ByteBuffer bb2 = null; int N = 120; - sbc.close(); + + try (SeekableByteChannel sbc = Files.newByteChannel(path)) { + System.out.printf(" sbc[0]: pos=%d, size=%d%n", sbc.position(), sbc.size()); + bb = ByteBuffer.allocate((int)sbc.size()); + n = sbc.read(bb); + System.out.printf(" sbc[1]: read=%d, pos=%d, size=%d%n", + n, sbc.position(), sbc.size()); + bb2 = ByteBuffer.allocate((int)sbc.size()); + } // sbc.position(pos) is not supported in current version // try the FileChannel - sbc = fs.provider().newFileChannel(path, read); - sbc.position(N); - System.out.printf(" sbc[2]: pos=%d, size=%d%n", - sbc.position(), sbc.size()); - bb2.limit(100); - n = sbc.read(bb2); - System.out.printf(" sbc[3]: read=%d, pos=%d, size=%d%n", - n, sbc.position(), sbc.size()); - System.out.printf(" sbc[4]: bb[%d]=%d, bb1[0]=%d%n", - N, bb.get(N) & 0xff, bb2.get(0) & 0xff); - sbc.close(); + try (SeekableByteChannel sbc = fs.provider().newFileChannel(path, read)) { + sbc.position(N); + System.out.printf(" sbc[2]: pos=%d, size=%d%n", + sbc.position(), sbc.size()); + bb2.limit(100); + n = sbc.read(bb2); + System.out.printf(" sbc[3]: read=%d, pos=%d, size=%d%n", + n, sbc.position(), sbc.size()); + System.out.printf(" sbc[4]: bb[%d]=%d, bb1[0]=%d%n", + N, bb.get(N) & 0xff, bb2.get(0) & 0xff); + } } // create parents if does not exist @@ -637,7 +632,7 @@ public class ZipFSTester { { Path path = fs.getPath(name); Path parent = path.getParent(); - if (parent != null && parent.notExists()) + if (parent != null && Files.notExists(parent)) mkdirs(parent); return path; } diff --git a/jdk/test/demo/zipfs/basic.sh b/jdk/test/demo/zipfs/basic.sh index a79cce34b6f..832a75d4fb4 100644 --- a/jdk/test/demo/zipfs/basic.sh +++ b/jdk/test/demo/zipfs/basic.sh @@ -21,7 +21,7 @@ # questions. # # @test -# @bug 6990846 7009092 7009085 +# @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 # @summary Test ZipFileSystem demo # @build Basic PathOps ZipFSTester # @run shell basic.sh diff --git a/jdk/test/java/io/File/IsHidden.java b/jdk/test/java/io/File/IsHidden.java index 9e062fe61e3..d2b43c5b641 100644 --- a/jdk/test/java/io/File/IsHidden.java +++ b/jdk/test/java/io/File/IsHidden.java @@ -27,6 +27,7 @@ */ import java.io.*; +import java.nio.file.Files; import java.nio.file.attribute.DosFileAttributeView; public class IsHidden { @@ -42,7 +43,7 @@ public class IsHidden { } private static void setHidden(File f, boolean value) throws IOException { - f.toPath().getFileAttributeView(DosFileAttributeView.class).setHidden(value); + Files.getFileAttributeView(f.toPath(), DosFileAttributeView.class).setHidden(value); } private static void testWin32() throws Exception { diff --git a/jdk/test/java/io/File/SetAccess.java b/jdk/test/java/io/File/SetAccess.java index bb88ec46258..745deab1f7b 100644 --- a/jdk/test/java/io/File/SetAccess.java +++ b/jdk/test/java/io/File/SetAccess.java @@ -27,6 +27,7 @@ */ import java.io.*; +import java.nio.file.*; import java.nio.file.attribute.*; public class SetAccess { @@ -178,7 +179,7 @@ public class SetAccess { } private static String permission(File f) throws Exception { - PosixFileAttributes attrs = Attributes.readPosixFileAttributes(f.toPath()); + PosixFileAttributes attrs = Files.readAttributes(f.toPath(), PosixFileAttributes.class); String type = attrs.isDirectory() ? "d" : " "; return type + PosixFilePermissions.toString(attrs.permissions()); } diff --git a/jdk/test/java/io/File/SymLinks.java b/jdk/test/java/io/File/SymLinks.java index 36306f98d7a..355b28875d4 100644 --- a/jdk/test/java/io/File/SymLinks.java +++ b/jdk/test/java/io/File/SymLinks.java @@ -27,7 +27,7 @@ */ import java.io.*; -import java.nio.file.Path; +import java.nio.file.*; import java.nio.file.attribute.*; import static java.nio.file.LinkOption.*; @@ -80,39 +80,33 @@ public class SymLinks { if (file != null) file.delete(); if (link2file != null) - link2file.toPath().deleteIfExists(); + Files.deleteIfExists(link2file.toPath()); if (link2link2file != null) - link2link2file.toPath().deleteIfExists(); + Files.deleteIfExists(link2link2file.toPath()); if (dir != null) dir.delete(); if (link2dir != null) - link2dir.toPath().deleteIfExists(); + Files.deleteIfExists(link2dir.toPath()); if (link2link2dir != null) - link2link2dir.toPath().deleteIfExists(); + Files.deleteIfExists(link2link2dir.toPath()); if (link2nobody != null) - link2nobody.toPath().deleteIfExists(); + Files.deleteIfExists(link2nobody.toPath()); if (link2link2nobody != null) - link2link2nobody.toPath().deleteIfExists(); + Files.deleteIfExists(link2link2nobody.toPath()); } /** * Creates a sym link source->target */ static void mklink(File source, File target) throws IOException { - source.toPath().createSymbolicLink(target.toPath()); + Files.createSymbolicLink(source.toPath(), target.toPath()); } /** * Returns true if the "link" exists and is a sym link. */ static boolean isSymLink(File link) { - try { - BasicFileAttributes attrs = - Attributes.readBasicFileAttributes(link.toPath(), NOFOLLOW_LINKS); - return attrs.isSymbolicLink(); - } catch (IOException x) { - return false; - } + return Files.isSymbolicLink(link.toPath()); } /** @@ -120,7 +114,7 @@ public class SymLinks { */ static long lastModifiedOfSymLink(File link) throws IOException { BasicFileAttributes attrs = - Attributes.readBasicFileAttributes(link.toPath(), NOFOLLOW_LINKS); + Files.readAttributes(link.toPath(), BasicFileAttributes.class, NOFOLLOW_LINKS); assertTrue(attrs.isSymbolicLink()); return attrs.lastModifiedTime().toMillis(); } @@ -133,8 +127,8 @@ public class SymLinks { Path link = dir.toPath().resolve("link"); Path target = dir.toPath().resolve("target"); try { - link.createSymbolicLink(target); - link.delete(); + Files.createSymbolicLink(link, target); + Files.delete(link); return true; } catch (UnsupportedOperationException x) { return false; @@ -224,7 +218,7 @@ public class SymLinks { assertTrue(isSymLink(link2nobody)); } finally { - link.toPath().deleteIfExists(); + Files.deleteIfExists(link.toPath()); } header("renameTo"); @@ -287,8 +281,8 @@ public class SymLinks { // on Windows we test with the DOS hidden attribute set if (System.getProperty("os.name").startsWith("Windows")) { - DosFileAttributeView view = file.toPath() - .getFileAttributeView(DosFileAttributeView.class); + DosFileAttributeView view = Files + .getFileAttributeView(file.toPath(), DosFileAttributeView.class); view.setHidden(true); try { assertTrue(file.isHidden()); diff --git a/jdk/test/java/io/FileInputStream/LargeFileAvailable.java b/jdk/test/java/io/FileInputStream/LargeFileAvailable.java index 35c9ce47483..0e33d9a969f 100644 --- a/jdk/test/java/io/FileInputStream/LargeFileAvailable.java +++ b/jdk/test/java/io/FileInputStream/LargeFileAvailable.java @@ -31,6 +31,7 @@ import java.io.*; import java.nio.ByteBuffer; import java.nio.channels.*; +import java.nio.file.Files; import static java.nio.file.StandardOpenOption.*; public class LargeFileAvailable { @@ -85,7 +86,7 @@ public class LargeFileAvailable { // Create a large file as a sparse file if possible File largefile = File.createTempFile("largefile", null); // re-create as a sparse file - largefile.toPath().delete(); + Files.delete(largefile.toPath()); try (FileChannel fc = FileChannel.open(largefile.toPath(), CREATE_NEW, WRITE, SPARSE)) { diff --git a/jdk/test/java/lang/Double/ParseDouble.java b/jdk/test/java/lang/Double/ParseDouble.java index 161177a5faa..669d078c029 100644 --- a/jdk/test/java/lang/Double/ParseDouble.java +++ b/jdk/test/java/lang/Double/ParseDouble.java @@ -23,11 +23,12 @@ /* * @test - * @bug 4160406 4705734 4707389 4826774 4895911 + * @bug 4160406 4705734 4707389 4826774 4895911 4421494 * @summary Test for Double.parseDouble method and acceptance regex */ import java.util.regex.*; +import java.math.BigDecimal; public class ParseDouble { @@ -416,7 +417,15 @@ public class ParseDouble { "0x00100p1", "0x00.100p1", - "0x001.100p1" + "0x001.100p1", + + // Limits + + "1.7976931348623157E308", // Double.MAX_VALUE + "4.9e-324", // Double.MIN_VALUE + "2.2250738585072014e-308", // Double.MIN_NORMAL + + "2.2250738585072012e-308", // near Double.MIN_NORMAL }; static String paddedBadStrings[]; @@ -546,6 +555,32 @@ public class ParseDouble { } + /** + * For each subnormal power of two, test at boundaries of + * region that should convert to that value. + */ + private static void testSubnormalPowers() { + BigDecimal TWO = BigDecimal.valueOf(2); + // An ulp is the same for all subnormal values + BigDecimal ulp_BD = new BigDecimal(Double.MIN_VALUE); + + // Test subnormal powers of two + for(int i = -1074; i <= -1022; i++) { + double d = Math.scalb(1.0, i); + + /* + * The region [d - ulp/2, d + ulp/2] should round to d. + */ + BigDecimal d_BD = new BigDecimal(d); + + BigDecimal lowerBound = d_BD.subtract(ulp_BD.divide(TWO)); + BigDecimal upperBound = d_BD.add(ulp_BD.divide(TWO)); + + double convertedLowerBound = Double.parseDouble(lowerBound.toString()); + double convertedUpperBound = Double.parseDouble(upperBound.toString()); + } + } + public static void main(String[] args) throws Exception { rudimentaryTest(); @@ -558,5 +593,7 @@ public class ParseDouble { testRegex(paddedGoodStrings, false); testRegex(badStrings, true); testRegex(paddedBadStrings, true); + + testSubnormalPowers(); } } diff --git a/jdk/test/java/lang/Runtime/exec/Duped.java b/jdk/test/java/lang/Runtime/exec/Duped.java index c8e7aa9dcb8..2788b77e48c 100644 --- a/jdk/test/java/lang/Runtime/exec/Duped.java +++ b/jdk/test/java/lang/Runtime/exec/Duped.java @@ -38,8 +38,7 @@ public class Duped { public static void main(String args[]) throws Exception { StringBuffer s = new StringBuffer(); int c; - while ((System.in.available() != 0) - && ((c = System.in.read()) != -1)) + while ((c = System.in.read()) != -1) s.append((char)c); System.out.println(s); } diff --git a/jdk/test/java/net/Socks/SocksProxyVersion.java b/jdk/test/java/net/Socks/SocksProxyVersion.java index 19298e59c6b..fe4f1c65b72 100644 --- a/jdk/test/java/net/Socks/SocksProxyVersion.java +++ b/jdk/test/java/net/Socks/SocksProxyVersion.java @@ -36,15 +36,22 @@ import java.io.DataInputStream; import java.io.IOException; public class SocksProxyVersion implements Runnable { - ServerSocket ss; + final ServerSocket ss; volatile boolean failed; public static void main(String[] args) throws Exception { new SocksProxyVersion(); } + @SuppressWarnings("try") public SocksProxyVersion() throws Exception { ss = new ServerSocket(0); + try (ServerSocket socket = ss) { + runTest(); + } + } + + void runTest() throws Exception { int port = ss.getLocalPort(); Thread serverThread = new Thread(this); serverThread.start(); @@ -75,22 +82,21 @@ public class SocksProxyVersion implements Runnable { } public void run() { - try (ss) { - Socket s = ss.accept(); - int version = (s.getInputStream()).read(); - if (version != 4) { - System.out.println("Got " + version + ", expected 4"); - failed = true; + try { + try (Socket s = ss.accept()) { + int version = (s.getInputStream()).read(); + if (version != 4) { + System.out.println("Got " + version + ", expected 4"); + failed = true; + } } - s.close(); - - s = ss.accept(); - version = (s.getInputStream()).read(); - if (version != 5) { - System.out.println("Got " + version + ", expected 5"); - failed = true; + try (Socket s = ss.accept()) { + int version = (s.getInputStream()).read(); + if (version != 5) { + System.out.println("Got " + version + ", expected 5"); + failed = true; + } } - s.close(); } catch (IOException e) { e.printStackTrace(); } diff --git a/jdk/test/java/nio/MappedByteBuffer/Force.java b/jdk/test/java/nio/MappedByteBuffer/Force.java index bd66a31ff21..81f908bacee 100644 --- a/jdk/test/java/nio/MappedByteBuffer/Force.java +++ b/jdk/test/java/nio/MappedByteBuffer/Force.java @@ -37,14 +37,17 @@ public class Force { Random random = new Random(); long filesize = random.nextInt(3*1024*1024); int cut = random.nextInt((int)filesize); - File file = new File("Blah"); - RandomAccessFile raf = new RandomAccessFile(file, "rw"); - raf.setLength(filesize); - FileChannel fc = raf.getChannel(); - MappedByteBuffer buf1 = fc.map( - FileChannel.MapMode.READ_WRITE, cut, filesize-cut); - buf1.force(); - fc.close(); - raf.close(); + File file = File.createTempFile("Blah", null); + file.deleteOnExit(); + try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) { + raf.setLength(filesize); + FileChannel fc = raf.getChannel(); + MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, cut, filesize-cut); + mbb.force(); + } + + // improve chance that mapped buffer will be unmapped + System.gc(); + Thread.sleep(500); } } diff --git a/jdk/test/java/nio/MappedByteBuffer/ZeroMap.java b/jdk/test/java/nio/MappedByteBuffer/ZeroMap.java index f80e72f803d..81cd3532d13 100644 --- a/jdk/test/java/nio/MappedByteBuffer/ZeroMap.java +++ b/jdk/test/java/nio/MappedByteBuffer/ZeroMap.java @@ -37,16 +37,19 @@ public class ZeroMap { Random random = new Random(); long filesize = random.nextInt(1024*1024); int cut = random.nextInt((int)filesize); - File file = new File("Blah"); - RandomAccessFile raf = new RandomAccessFile(file, "rw"); - raf.setLength(filesize); - FileChannel fc = raf.getChannel(); - MappedByteBuffer buf1 = fc.map( - FileChannel.MapMode.READ_WRITE, cut, 0); - buf1.force(); - buf1.load(); - buf1.isLoaded(); - fc.close(); - raf.close(); + File file = File.createTempFile("Blah", null); + file.deleteOnExit(); + try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) { + raf.setLength(filesize); + FileChannel fc = raf.getChannel(); + MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, cut, 0); + mbb.force(); + mbb.load(); + mbb.isLoaded(); + } + + // improve chance that mapped buffer will be unmapped + System.gc(); + Thread.sleep(500); } } diff --git a/jdk/test/java/nio/channels/FileChannel/AtomicAppend.java b/jdk/test/java/nio/channels/FileChannel/AtomicAppend.java index 1420318d5d7..60bd746f123 100644 --- a/jdk/test/java/nio/channels/FileChannel/AtomicAppend.java +++ b/jdk/test/java/nio/channels/FileChannel/AtomicAppend.java @@ -36,6 +36,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; +import java.nio.file.Files; import static java.nio.file.StandardOpenOption.*; public class AtomicAppend { @@ -55,7 +56,7 @@ public class AtomicAppend { if (rand.nextBoolean()) { return new FileOutputStream(file, true); } else { - return file.toPath().newOutputStream(APPEND); + return Files.newOutputStream(file.toPath(), APPEND); } } diff --git a/jdk/test/java/nio/channels/FileChannel/Transfer.java b/jdk/test/java/nio/channels/FileChannel/Transfer.java index f0507b5249f..565f8ff1007 100644 --- a/jdk/test/java/nio/channels/FileChannel/Transfer.java +++ b/jdk/test/java/nio/channels/FileChannel/Transfer.java @@ -276,7 +276,7 @@ public class Transfer { while (fc == null) { sink = File.createTempFile("sink", null); // re-create as a sparse file - sink.toPath().delete(); + sink.delete(); try { fc = FileChannel.open(sink.toPath(), StandardOpenOption.CREATE_NEW, diff --git a/jdk/test/java/nio/channels/FileChannel/Truncate.java b/jdk/test/java/nio/channels/FileChannel/Truncate.java index b0a1ffa0f98..bc81ffb2278 100644 --- a/jdk/test/java/nio/channels/FileChannel/Truncate.java +++ b/jdk/test/java/nio/channels/FileChannel/Truncate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,30 +58,31 @@ public class Truncate { for(int i=0; i<100; i++) { long testSize = generator.nextInt(1000) + 10; initTestFile(blah, testSize); - FileChannel fc = (i < 50) ? - new RandomAccessFile(blah, "rw").getChannel() : - FileChannel.open(blah.toPath(), READ, WRITE); - try (fc) { - if (fc.size() != testSize) - throw new RuntimeException("Size failed"); - long position = generator.nextInt((int)testSize); - fc.position(position); + try (FileChannel fc = (i < 50) ? + new RandomAccessFile(blah, "rw").getChannel() : + FileChannel.open(blah.toPath(), READ, WRITE)) + { + if (fc.size() != testSize) + throw new RuntimeException("Size failed"); - long newSize = generator.nextInt((int)testSize); - fc.truncate(newSize); + long position = generator.nextInt((int)testSize); + fc.position(position); - if (fc.size() != newSize) - throw new RuntimeException("Truncate failed"); + long newSize = generator.nextInt((int)testSize); + fc.truncate(newSize); - if (position > newSize) { - if (fc.position() != newSize) - throw new RuntimeException("Position greater than size"); - } else { - if (fc.position() != position) - throw new RuntimeException("Truncate changed position"); - }; - } + if (fc.size() != newSize) + throw new RuntimeException("Truncate failed"); + + if (position > newSize) { + if (fc.position() != newSize) + throw new RuntimeException("Position greater than size"); + } else { + if (fc.position() != position) + throw new RuntimeException("Truncate changed position"); + }; + } } } @@ -92,24 +93,24 @@ public class Truncate { for (int i=0; i<10; i++) { long testSize = generator.nextInt(1000) + 10; initTestFile(blah, testSize); - FileChannel fc = (i < 5) ? - new FileOutputStream(blah, true).getChannel() : - FileChannel.open(blah.toPath(), APPEND); - try (fc) { - // truncate file - long newSize = generator.nextInt((int)testSize); - fc.truncate(newSize); - if (fc.size() != newSize) - throw new RuntimeException("Truncate failed"); + try (FileChannel fc = (i < 5) ? + new FileOutputStream(blah, true).getChannel() : + FileChannel.open(blah.toPath(), APPEND)) + { + // truncate file + long newSize = generator.nextInt((int)testSize); + fc.truncate(newSize); + if (fc.size() != newSize) + throw new RuntimeException("Truncate failed"); - // write one byte - ByteBuffer buf = ByteBuffer.allocate(1); - buf.put((byte)'x'); - buf.flip(); - fc.write(buf); - if (fc.size() != (newSize+1)) - throw new RuntimeException("Unexpected size"); - } + // write one byte + ByteBuffer buf = ByteBuffer.allocate(1); + buf.put((byte)'x'); + buf.flip(); + fc.write(buf); + if (fc.size() != (newSize+1)) + throw new RuntimeException("Unexpected size"); + } } } diff --git a/jdk/test/java/nio/file/DirectoryStream/Basic.java b/jdk/test/java/nio/file/DirectoryStream/Basic.java index 75d66280147..69f5d18f656 100644 --- a/jdk/test/java/nio/file/DirectoryStream/Basic.java +++ b/jdk/test/java/nio/file/DirectoryStream/Basic.java @@ -28,6 +28,7 @@ */ import java.nio.file.*; +import static java.nio.file.Files.*; import java.util.*; import java.io.IOException; @@ -38,29 +39,26 @@ public class Basic { DirectoryStream stream; // test that directory is empty - stream = dir.newDirectoryStream(); - try { - if (stream.iterator().hasNext()) + try (DirectoryStream ds = newDirectoryStream(dir)) { + if (ds.iterator().hasNext()) throw new RuntimeException("directory not empty"); - } finally { - stream.close(); } // create file in directory final Path foo = Paths.get("foo"); - dir.resolve(foo).createFile(); + createFile(dir.resolve(foo)); // iterate over directory and check there is one entry - stream = dir.newDirectoryStream(); + stream = newDirectoryStream(dir); found = false; try { for (Path entry: stream) { - if (entry.getName().equals(foo)) { + if (entry.getFileName().equals(foo)) { if (found) throw new RuntimeException("entry already found"); found = true; } else { - throw new RuntimeException("entry " + entry.getName() + + throw new RuntimeException("entry " + entry.getFileName() + " not expected"); } } @@ -71,21 +69,18 @@ public class Basic { throw new RuntimeException("entry not found"); // check filtering: f* should match foo - DirectoryStream.Filter filter = new DirectoryStream.Filter() { + DirectoryStream.Filter filter = new DirectoryStream.Filter<>() { private PathMatcher matcher = dir.getFileSystem().getPathMatcher("glob:f*"); public boolean accept(Path file) { return matcher.matches(file); } }; - stream = dir.newDirectoryStream(filter); - try { - for (Path entry: stream) { - if (!entry.getName().equals(foo)) + try (DirectoryStream ds = newDirectoryStream(dir, filter)) { + for (Path entry: ds) { + if (!entry.getFileName().equals(foo)) throw new RuntimeException("entry not expected"); } - } finally { - stream.close(); } // check filtering: z* should not match any files @@ -96,12 +91,9 @@ public class Basic { return matcher.matches(file); } }; - stream = dir.newDirectoryStream(filter); - try { - if (stream.iterator().hasNext()) + try (DirectoryStream ds = newDirectoryStream(dir, filter)) { + if (ds.iterator().hasNext()) throw new RuntimeException("no matching entries expected"); - } finally { - stream.close(); } // check that an IOException thrown by a filter is propagated @@ -110,7 +102,7 @@ public class Basic { throw new java.util.zip.ZipException(); } }; - stream = dir.newDirectoryStream(filter); + stream = newDirectoryStream(dir, filter); try { stream.iterator().hasNext(); throw new RuntimeException("DirectoryIteratorException expected"); @@ -124,7 +116,7 @@ public class Basic { // check that exception or error thrown by filter is not thrown // by newDirectoryStream or iterator method. - stream = dir.newDirectoryStream(new DirectoryStream.Filter() { + stream = newDirectoryStream(dir, new DirectoryStream.Filter() { public boolean accept(Path file) { throw new RuntimeException("Should not be visible"); } @@ -137,13 +129,13 @@ public class Basic { // test NotDirectoryException try { - dir.resolve(foo).newDirectoryStream(); + newDirectoryStream(dir.resolve(foo)); throw new RuntimeException("NotDirectoryException not thrown"); } catch (NotDirectoryException x) { } // test UnsupportedOperationException - stream = dir.newDirectoryStream(); + stream = newDirectoryStream(dir); Iterator i = stream.iterator(); i.next(); try { @@ -153,7 +145,7 @@ public class Basic { } // test IllegalStateException - stream = dir.newDirectoryStream(); + stream = newDirectoryStream(dir); stream.iterator(); try { // attempt to obtain second iterator @@ -163,7 +155,7 @@ public class Basic { } stream.close(); - stream = dir.newDirectoryStream(); + stream = newDirectoryStream(dir); stream.close(); try { // attempt to obtain iterator after stream is closed @@ -173,13 +165,13 @@ public class Basic { } // test that iterator reads to end of stream when closed - stream = dir.newDirectoryStream(); + stream = newDirectoryStream(dir); i = stream.iterator(); stream.close(); while (i.hasNext()) i.next(); - stream = dir.newDirectoryStream(); + stream = newDirectoryStream(dir); i = stream.iterator(); stream.close(); try { diff --git a/jdk/test/java/nio/file/DirectoryStream/DriveLetter.java b/jdk/test/java/nio/file/DirectoryStream/DriveLetter.java index e692a7ec55f..a629a027d39 100644 --- a/jdk/test/java/nio/file/DirectoryStream/DriveLetter.java +++ b/jdk/test/java/nio/file/DirectoryStream/DriveLetter.java @@ -52,16 +52,14 @@ public class DriveLetter { Path expected = Paths.get(drive).resolve(tempFile.getName()); boolean found = false; - DirectoryStream stream = Paths.get(drive).newDirectoryStream(); - try { + Path dir = Paths.get(drive); + try (DirectoryStream stream = Files.newDirectoryStream(dir)) { for (Path file : stream) { if (file.equals(expected)) { found = true; break; } } - } finally { - stream.close(); } if (!found) throw new RuntimeException("Temporary file not found???"); diff --git a/jdk/test/java/nio/file/DirectoryStream/SecureDS.java b/jdk/test/java/nio/file/DirectoryStream/SecureDS.java index e776c8b31ad..fdfcfd9fdfe 100644 --- a/jdk/test/java/nio/file/DirectoryStream/SecureDS.java +++ b/jdk/test/java/nio/file/DirectoryStream/SecureDS.java @@ -28,6 +28,7 @@ */ import java.nio.file.*; +import static java.nio.file.Files.*; import static java.nio.file.StandardOpenOption.*; import static java.nio.file.LinkOption.*; import java.nio.file.attribute.*; @@ -41,7 +42,7 @@ public class SecureDS { public static void main(String[] args) throws IOException { Path dir = TestUtil.createTemporaryDirectory(); try { - DirectoryStream stream = dir.newDirectoryStream(); + DirectoryStream stream = newDirectoryStream(dir); stream.close(); if (!(stream instanceof SecureDirectoryStream)) { System.out.println("SecureDirectoryStream not supported."); @@ -62,28 +63,28 @@ public class SecureDS { // Exercise each of SecureDirectoryStream's method (except move) static void doBasicTests(Path dir) throws IOException { - Path dir1 = dir.resolve("dir1").createDirectory(); + Path dir1 = createDirectory(dir.resolve("dir1")); Path dir2 = dir.resolve("dir2"); // create a file, directory, and two sym links in the directory Path fileEntry = Paths.get("myfile"); - dir1.resolve(fileEntry).createFile(); + createFile(dir1.resolve(fileEntry)); Path dirEntry = Paths.get("mydir"); - dir1.resolve(dirEntry).createDirectory(); + createDirectory(dir1.resolve(dirEntry)); // myfilelink -> myfile Path link1Entry = Paths.get("myfilelink"); if (supportsLinks) - dir1.resolve(link1Entry).createSymbolicLink(fileEntry); + createSymbolicLink(dir1.resolve(link1Entry), fileEntry); // mydirlink -> mydir Path link2Entry = Paths.get("mydirlink"); if (supportsLinks) - dir1.resolve(link2Entry).createSymbolicLink(dirEntry); + createSymbolicLink(dir1.resolve(link2Entry), dirEntry); // open directory and then move it so that it is no longer accessible // via its original path. SecureDirectoryStream stream = - (SecureDirectoryStream)dir1.newDirectoryStream(); - dir1.moveTo(dir2); + (SecureDirectoryStream)newDirectoryStream(dir1); + move(dir1, dir2); // Test: iterate over all entries int count = 0; @@ -138,7 +139,7 @@ public class SecureDS { if (supportsLinks) { stream.newByteChannel(link1Entry, opts).close(); try { - Set mixed = new HashSet(); + Set mixed = new HashSet<>(); mixed.add(READ); mixed.add(NOFOLLOW_LINKS); stream.newByteChannel(link1Entry, mixed).close(); @@ -168,51 +169,48 @@ public class SecureDS { // clean-up stream.close(); - dir2.delete(); + delete(dir2); } // Exercise SecureDirectoryStream's move method static void doMoveTests(Path dir) throws IOException { - Path dir1 = dir.resolve("dir1").createDirectory(); - Path dir2 = dir.resolve("dir2").createDirectory(); + Path dir1 = createDirectory(dir.resolve("dir1")); + Path dir2 = createDirectory(dir.resolve("dir2")); // create dir1/myfile, dir1/mydir, dir1/mylink Path fileEntry = Paths.get("myfile"); - dir1.resolve(fileEntry).createFile(); + createFile(dir1.resolve(fileEntry)); Path dirEntry = Paths.get("mydir"); - dir1.resolve(dirEntry).createDirectory(); + createDirectory(dir1.resolve(dirEntry)); Path linkEntry = Paths.get("mylink"); if (supportsLinks) - dir1.resolve(linkEntry).createSymbolicLink(Paths.get("missing")); + createSymbolicLink(dir1.resolve(linkEntry), Paths.get("missing")); // target name Path target = Paths.get("newfile"); // open stream to both directories SecureDirectoryStream stream1 = - (SecureDirectoryStream)dir1.newDirectoryStream(); + (SecureDirectoryStream)newDirectoryStream(dir1); SecureDirectoryStream stream2 = - (SecureDirectoryStream)dir2.newDirectoryStream(); + (SecureDirectoryStream)newDirectoryStream(dir2); // Test: move dir1/myfile -> dir2/newfile stream1.move(fileEntry, stream2, target); - assertTrue(dir1.resolve(fileEntry).notExists()); - assertTrue(dir2.resolve(target).exists()); + assertTrue(notExists(dir1.resolve(fileEntry))); + assertTrue(exists(dir2.resolve(target))); stream2.deleteFile(target); // Test: move dir1/mydir -> dir2/newfile stream1.move(dirEntry, stream2, target); - assertTrue(dir1.resolve(dirEntry).notExists()); - assertTrue(dir2.resolve(target).exists()); + assertTrue(notExists(dir1.resolve(dirEntry))); + assertTrue(exists(dir2.resolve(target))); stream2.deleteDirectory(target); // Test: move dir1/mylink -> dir2/newfile if (supportsLinks) { stream1.move(linkEntry, stream2, target); - assertTrue(dir2.resolve(target) - .getFileAttributeView(BasicFileAttributeView.class, NOFOLLOW_LINKS) - .readAttributes() - .isSymbolicLink()); + assertTrue(isSymbolicLink(dir2.resolve(target))); stream2.deleteFile(target); } @@ -220,10 +218,10 @@ public class SecureDS { String testDirAsString = System.getProperty("test.dir"); if (testDirAsString != null) { Path testDir = Paths.get(testDirAsString); - if (!dir1.getFileStore().equals(testDir.getFileStore())) { + if (!getFileStore(dir1).equals(getFileStore(testDir))) { SecureDirectoryStream ts = - (SecureDirectoryStream)testDir.newDirectoryStream(); - dir1.resolve(fileEntry).createFile(); + (SecureDirectoryStream)newDirectoryStream(testDir); + createFile(dir1.resolve(fileEntry)); try { stream1.move(fileEntry, ts, target); shouldNotGetHere(); @@ -234,17 +232,17 @@ public class SecureDS { } // clean-up - dir1.delete(); - dir2.delete(); + delete(dir1); + delete(dir2); } // null and ClosedDirectoryStreamException static void miscTests(Path dir) throws IOException { Path file = Paths.get("file"); - dir.resolve(file).createFile(); + createFile(dir.resolve(file)); SecureDirectoryStream stream = - (SecureDirectoryStream)dir.newDirectoryStream(); + (SecureDirectoryStream)newDirectoryStream(dir); // NullPointerException try { @@ -319,7 +317,7 @@ public class SecureDS { } catch (ClosedDirectoryStreamException x) { } // clean-up - dir.resolve(file).delete(); + delete(dir.resolve(file)); } static void assertTrue(boolean b) { diff --git a/jdk/test/java/nio/file/FileStore/Basic.java b/jdk/test/java/nio/file/FileStore/Basic.java index 0b43109d3a0..f49bc6552bb 100644 --- a/jdk/test/java/nio/file/FileStore/Basic.java +++ b/jdk/test/java/nio/file/FileStore/Basic.java @@ -22,18 +22,21 @@ */ /* @test - * @bug 4313887 6873621 6979526 + * @bug 4313887 6873621 6979526 7006126 * @summary Unit test for java.nio.file.FileStore * @library .. */ import java.nio.file.*; import java.nio.file.attribute.*; +import java.io.File; import java.io.IOException; import java.util.*; public class Basic { + static final long G = 1024L * 1024L * 1024L; + public static void main(String[] args) throws IOException { Path dir = TestUtil.createTemporaryDirectory(); try { @@ -48,17 +51,25 @@ public class Basic { throw new RuntimeException("Assertion failed"); } + static void checkWithin1GB(long value1, long value2) { + long diff = Math.abs(value1 - value2); + if (diff > G) + throw new RuntimeException("values differ by more than 1GB"); + } + static void doTests(Path dir) throws IOException { /** * Test: Directory should be on FileStore that is writable */ - assertTrue(!dir.getFileStore().isReadOnly()); + assertTrue(!Files.getFileStore(dir).isReadOnly()); /** * Test: Two files should have the same FileStore */ - FileStore store1 = dir.resolve("foo").createFile().getFileStore(); - FileStore store2 = dir.resolve("bar").createFile().getFileStore(); + Path file1 = Files.createFile(dir.resolve("foo")); + Path file2 = Files.createFile(dir.resolve("bar")); + FileStore store1 = Files.getFileStore(file1); + FileStore store2 = Files.getFileStore(file2); assertTrue(store1.equals(store2)); assertTrue(store2.equals(store1)); assertTrue(store1.hashCode() == store2.hashCode()); @@ -77,6 +88,24 @@ public class Basic { assertTrue(store1.supportsFileAttributeView("user") == store1.supportsFileAttributeView(UserDefinedFileAttributeView.class)); + /** + * Test: Space atributes + */ + File f = file1.toFile(); + long total = f.getTotalSpace(); + long free = f.getFreeSpace(); + long usable = f.getUsableSpace(); + + // check values are "close" + checkWithin1GB(total, store1.getTotalSpace()); + checkWithin1GB(free, store1.getUnallocatedSpace()); + checkWithin1GB(usable, store1.getUsableSpace()); + + // get values by name + checkWithin1GB(total, (Long)store1.getAttribute("totalSpace")); + checkWithin1GB(free, (Long)store1.getAttribute("unallocatedSpace")); + checkWithin1GB(usable, (Long)store1.getAttribute("usableSpace")); + /** * Test: Enumerate all FileStores */ @@ -85,8 +114,10 @@ public class Basic { System.out.format("%s (name=%s type=%s)\n", store, store.name(), store.type()); - // check space attributes - Attributes.readFileStoreSpaceAttributes(store); + // check space attributes are accessible + store.getTotalSpace(); + store.getUnallocatedSpace(); + store.getUsableSpace(); // two distinct FileStores should not be equal assertTrue(!store.equals(prev)); diff --git a/jdk/test/java/nio/file/Files/BytesAndLines.java b/jdk/test/java/nio/file/Files/BytesAndLines.java new file mode 100644 index 00000000000..2833c99cb73 --- /dev/null +++ b/jdk/test/java/nio/file/Files/BytesAndLines.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 7006126 + * @summary Unit test for methods for Files readAllBytes, readAllLines and + * and write methods. + */ + +import java.nio.file.*; +import static java.nio.file.Files.*; +import java.io.*; +import java.util.*; +import java.nio.charset.*; + +public class BytesAndLines { + static final Random rand = new Random(); + + static final Charset US_ASCII = Charset.forName("US-ASCII"); + + public static void main(String[] args) throws IOException { + testReadAndWriteBytes(); + testReadLines(); + testWriteLines(); + } + + /** + * Test readAllBytes(Path) and write(Path, byte[], OpenOption...) + */ + static void testReadAndWriteBytes() throws IOException { + // exercise methods with various sizes + testReadAndWriteBytes(0); + for (int i=0; i<100; i++) { + testReadAndWriteBytes(rand.nextInt(32000)); + } + + // NullPointerException + Path file = Paths.get("foo"); + List lines = Collections.emptyList(); + try { + readAllBytes(null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + write(null, lines, Charset.defaultCharset()); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + write(file, null, Charset.defaultCharset()); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + write(file, lines, null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + write(file, lines, Charset.defaultCharset(), (OpenOption[])null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + OpenOption[] opts = { null }; + write(file, lines, Charset.defaultCharset(), opts); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + } + + + static void testReadAndWriteBytes(int size) throws IOException { + Path path = createTempFile("blah", null); + try { + boolean append = rand.nextBoolean(); + + byte[] b1 = new byte[size]; + rand.nextBytes(b1); + + byte[] b2 = (append) ? new byte[size] : new byte[0]; + rand.nextBytes(b2); + + // write method should create file if it doesn't exist + if (rand.nextBoolean()) + delete(path); + + // write bytes to file + Path target = write(path, b1); + assertTrue(target==path, "Unexpected path"); + assertTrue(size(path) == b1.length, "Unexpected file size"); + + // append bytes to file (might be 0 bytes) + write(path, b2, StandardOpenOption.APPEND); + assertTrue(size(path) == b1.length + b2.length, "Unexpected file size"); + + // read entire file + byte[] read = readAllBytes(path); + + // check bytes are correct + byte[] expected; + if (append) { + expected = new byte[b1.length + b2.length]; + System.arraycopy(b1, 0, expected, 0, b1.length); + System.arraycopy(b2, 0, expected, b1.length, b2.length); + } else { + expected = b1; + } + assertTrue(Arrays.equals(read, expected), + "Bytes read not the same as bytes written"); + } finally { + deleteIfExists(path); + } + } + + /** + * Test readAllLines(Path,Charset) + */ + static void testReadLines() throws IOException { + Path tmpfile = createTempFile("blah", "txt"); + try { + List lines; + + // zero lines + assertTrue(size(tmpfile) == 0, "File should be empty"); + lines = readAllLines(tmpfile, US_ASCII); + assertTrue(lines.isEmpty(), "No line expected"); + + // one line + byte[] hi = { (byte)'h', (byte)'i' }; + write(tmpfile, hi); + lines = readAllLines(tmpfile, US_ASCII); + assertTrue(lines.size() == 1, "One line expected"); + assertTrue(lines.get(0).equals("hi"), "'Hi' expected"); + + // two lines using platform's line separator + List expected = Arrays.asList("hi", "there"); + write(tmpfile, expected, US_ASCII); + assertTrue(size(tmpfile) > 0, "File is empty"); + lines = readAllLines(tmpfile, US_ASCII); + assertTrue(lines.equals(expected), "Unexpected lines"); + + // MalformedInputException + byte[] bad = { (byte)0xff, (byte)0xff }; + write(tmpfile, bad); + try { + readAllLines(tmpfile, US_ASCII); + throw new RuntimeException("MalformedInputException expected"); + } catch (MalformedInputException ignore) { } + + + // NullPointerException + try { + readAllLines(null, US_ASCII); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + readAllLines(tmpfile, null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + + } finally { + delete(tmpfile); + } + } + + /** + * Test write(Path,Iterable,Charset,OpenOption...) + */ + static void testWriteLines() throws IOException { + Path tmpfile = createTempFile("blah", "txt"); + try { + // write method should create file if it doesn't exist + if (rand.nextBoolean()) + delete(tmpfile); + + // zero lines + Path result = write(tmpfile, Collections.emptyList(), US_ASCII); + assert(size(tmpfile) == 0); + assert(result == tmpfile); + + // two lines + List lines = Arrays.asList("hi", "there"); + write(tmpfile, lines, US_ASCII); + List actual = readAllLines(tmpfile, US_ASCII); + assertTrue(actual.equals(lines), "Unexpected lines"); + + // append two lines + write(tmpfile, lines, US_ASCII, StandardOpenOption.APPEND); + List expected = new ArrayList(); + expected.addAll(lines); + expected.addAll(lines); + assertTrue(expected.size() == 4, "List should have 4 elements"); + actual = readAllLines(tmpfile, US_ASCII); + assertTrue(actual.equals(expected), "Unexpected lines"); + + // UnmappableCharacterException + try { + String s = "\u00A0\u00A1"; + write(tmpfile, Arrays.asList(s), US_ASCII); + throw new RuntimeException("UnmappableCharacterException expected"); + } catch (UnmappableCharacterException ignore) { } + + // NullPointerException + try { + write(null, lines, US_ASCII); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + write(tmpfile, null, US_ASCII); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + write(tmpfile, lines, null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + write(tmpfile, lines, US_ASCII, (OpenOption[])null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + OpenOption[] opts = { (OpenOption)null }; + write(tmpfile, lines, US_ASCII, opts); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + + } finally { + delete(tmpfile); + } + + } + + static void assertTrue(boolean expr, String errmsg) { + if (!expr) + throw new RuntimeException(errmsg); + } +} diff --git a/jdk/test/java/nio/file/Path/CheckPermissions.java b/jdk/test/java/nio/file/Files/CheckPermissions.java similarity index 70% rename from jdk/test/java/nio/file/Path/CheckPermissions.java rename to jdk/test/java/nio/file/Files/CheckPermissions.java index 9996ac7490f..8137a358d42 100644 --- a/jdk/test/java/nio/file/Path/CheckPermissions.java +++ b/jdk/test/java/nio/file/Files/CheckPermissions.java @@ -22,8 +22,8 @@ */ /* @test - * @bug 6866804 - * @summary Unit test for java.nio.file.Path + * @bug 6866804 7006126 + * @summary Unit test for java.nio.file.Files * @library .. * @build CheckPermissions * @run main/othervm CheckPermissions @@ -31,6 +31,8 @@ import java.nio.ByteBuffer; import java.nio.file.*; +import static java.nio.file.Files.*; +import static java.nio.file.StandardOpenOption.*; import java.nio.file.attribute.*; import java.nio.channels.SeekableByteChannel; import java.security.Permission; @@ -45,12 +47,12 @@ import java.util.*; public class CheckPermissions { static class Checks { - private List permissionsChecked = new ArrayList(); - private Set propertiesChecked = new HashSet(); - private List readsChecked = new ArrayList(); - private List writesChecked = new ArrayList(); - private List deletesChecked = new ArrayList(); - private List execsChecked = new ArrayList(); + private List permissionsChecked = new ArrayList<>(); + private Set propertiesChecked = new HashSet<>(); + private List readsChecked = new ArrayList<>(); + private List writesChecked = new ArrayList<>(); + private List deletesChecked = new ArrayList<>(); + private List execsChecked = new ArrayList<>(); List permissionsChecked() { return permissionsChecked; } Set propertiesChecked() { return propertiesChecked; } @@ -78,7 +80,7 @@ public class CheckPermissions { if (type.isInstance(perm) && perm.getName().equals(name)) return; } - throw new RuntimeException(type.getName() + "\"" + name + "\") not checked"); + throw new RuntimeException(type.getName() + "(\"" + name + "\") not checked"); } static void assertCheckPropertyAccess(String key) { @@ -103,6 +105,17 @@ public class CheckPermissions { assertChecked(file, myChecks.get().writesChecked()); } + static void assertCheckWriteToDirectory(Path dir) { + String s = dir.toString(); + List list = myChecks.get().writesChecked(); + for (String f: list) { + if (f.startsWith(s)) { + return; + } + } + throw new RuntimeException("Access not checked"); + } + static void assertCheckDelete(Path file) { assertChecked(file, myChecks.get().deletesChecked()); } @@ -197,215 +210,240 @@ public class CheckPermissions { } public static void main(String[] args) throws IOException { - Path dir = Paths.get(System.getProperty("test.dir", ".")); - Path file = dir.resolve("file1234").createFile(); + final Path testdir = Paths.get(System.getProperty("test.dir", ".")).toAbsolutePath(); + final Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir")); + + Path file = createFile(testdir.resolve("file1234")); try { LoggingSecurityManager.install(); - // -- checkAccess -- + // -- check access -- prepare(); - file.checkAccess(); + exists(file); assertCheckRead(file); prepare(); - file.checkAccess(AccessMode.READ); + isReadable(file); assertCheckRead(file); prepare(); - file.checkAccess(AccessMode.WRITE); + isWritable(file); assertCheckWrite(file); prepare(); - try { - file.checkAccess(AccessMode.EXECUTE); - } catch (AccessDeniedException x) { } + isExecutable(file); assertCheckExec(file); - prepare(); - try { - file.checkAccess(AccessMode.READ, AccessMode.WRITE, AccessMode.EXECUTE); - } catch (AccessDeniedException x) { } - assertCheckRead(file); - assertCheckWrite(file); - assertCheckExec(file); + // -- copy -- - // -- copyTo -- - - Path target = dir.resolve("target1234"); + Path target = testdir.resolve("target1234"); prepare(); - file.copyTo(target); + copy(file, target); try { assertCheckRead(file); assertCheckWrite(target); } finally { - target.delete(); + delete(target); } - if (TestUtil.supportsLinks(dir)) { - Path link = dir.resolve("link1234").createSymbolicLink(file); + if (TestUtil.supportsLinks(testdir)) { + Path link = testdir.resolve("link1234"); + createSymbolicLink(link, file); try { prepare(); - link.copyTo(target, LinkOption.NOFOLLOW_LINKS); + copy(link, target, LinkOption.NOFOLLOW_LINKS); try { assertCheckRead(link); assertCheckWrite(target); assertCheckPermission(LinkPermission.class, "symbolic"); } finally { - target.delete(); + delete(target); } } finally { - link.delete(); + delete(link); } } // -- createDirectory -- - Path subdir = dir.resolve("subdir1234"); + Path subdir = testdir.resolve("subdir1234"); prepare(); - subdir.createDirectory(); + createDirectory(subdir); try { assertCheckWrite(subdir); } finally { - subdir.delete(); + delete(subdir); } // -- createFile -- - Path fileToCreate = dir.resolve("file7890"); + Path fileToCreate = testdir.resolve("file7890"); prepare(); + createFile(fileToCreate); try { - fileToCreate.createFile(); assertCheckWrite(fileToCreate); } finally { - fileToCreate.delete(); + delete(fileToCreate); } // -- createSymbolicLink -- - if (TestUtil.supportsLinks(dir)) { + if (TestUtil.supportsLinks(testdir)) { prepare(); - Path link = dir.resolve("link1234").createSymbolicLink(file); + Path link = testdir.resolve("link1234"); + createSymbolicLink(link, file); try { assertCheckWrite(link); assertCheckPermission(LinkPermission.class, "symbolic"); } finally { - link.delete(); + delete(link); } } + // -- createLink -- + + if (TestUtil.supportsLinks(testdir)) { + prepare(); + Path link = testdir.resolve("entry234"); + createLink(link, file); + try { + assertCheckWrite(link); + assertCheckPermission(LinkPermission.class, "hard"); + } finally { + delete(link); + } + } + + // -- createTempFile -- + + prepare(); + Path tmpfile1 = createTempFile("foo", null); + try { + assertCheckWriteToDirectory(tmpdir); + } finally { + delete(tmpfile1); + } + prepare(); + Path tmpfile2 = createTempFile(testdir, "foo", ".tmp"); + try { + assertCheckWriteToDirectory(testdir); + } finally { + delete(tmpfile2); + } + + // -- createTempDirectory -- + + prepare(); + Path tmpdir1 = createTempDirectory("foo"); + try { + assertCheckWriteToDirectory(tmpdir); + } finally { + delete(tmpdir1); + } + prepare(); + Path tmpdir2 = createTempDirectory(testdir, "foo"); + try { + assertCheckWriteToDirectory(testdir); + } finally { + delete(tmpdir2); + } + // -- delete/deleteIfExists -- - Path fileToDelete = dir.resolve("file7890"); + Path fileToDelete = testdir.resolve("file7890"); - fileToDelete.createFile(); + createFile(fileToDelete); prepare(); - fileToDelete.delete(); + delete(fileToDelete); assertCheckDelete(fileToDelete); - fileToDelete.createFile(); + createFile(fileToDelete); prepare(); - fileToDelete.deleteIfExists(); + deleteIfExists(fileToDelete); // file exists + assertCheckDelete(fileToDelete); + + prepare(); + deleteIfExists(fileToDelete); // file does not exist assertCheckDelete(fileToDelete); // -- exists/notExists -- prepare(); - file.exists(); + exists(file); assertCheckRead(file); prepare(); - file.notExists(); + notExists(file); assertCheckRead(file); // -- getFileStore -- prepare(); - file.getFileStore(); + getFileStore(file); assertCheckRead(file); assertCheckPermission(RuntimePermission.class, "getFileStoreAttributes"); // -- isSameFile -- prepare(); - file.isSameFile(dir); + isSameFile(file, testdir); assertCheckRead(file); - assertCheckRead(dir); + assertCheckRead(testdir); - // -- moveTo -- + // -- move -- - Path target2 = dir.resolve("target1234"); + Path target2 = testdir.resolve("target1234"); prepare(); - file.moveTo(target2); + move(file, target2); try { assertCheckWrite(file); assertCheckWrite(target2); } finally { // restore file - target2.moveTo(file); + move(target2, file); } // -- newByteChannel -- - SeekableByteChannel sbc; - prepare(); - sbc = file.newByteChannel(); - try { + try (SeekableByteChannel sbc = newByteChannel(file)) { assertCheckRead(file); - } finally { - sbc.close(); } prepare(); - sbc = file.newByteChannel(StandardOpenOption.WRITE); - try { + try (SeekableByteChannel sbc = newByteChannel(file, WRITE)) { assertCheckWrite(file); - } finally { - sbc.close(); } prepare(); - sbc = file.newByteChannel(StandardOpenOption.READ, StandardOpenOption.WRITE); - try { + try (SeekableByteChannel sbc = newByteChannel(file, READ, WRITE)) { assertCheckRead(file); assertCheckWrite(file); - } finally { - sbc.close(); } prepare(); - sbc = file.newByteChannel(StandardOpenOption.DELETE_ON_CLOSE); - try { + try (SeekableByteChannel sbc = newByteChannel(file, DELETE_ON_CLOSE)) { assertCheckRead(file); assertCheckDelete(file); - } finally { - sbc.close(); } - file.createFile(); // restore file + createFile(file); // restore file // -- newInputStream/newOutptuStream -- prepare(); - InputStream in = file.newInputStream(); - try { + try (InputStream in = newInputStream(file)) { assertCheckRead(file); - } finally { - in.close(); } prepare(); - OutputStream out = file.newOutputStream(); - try { + try (OutputStream out = newOutputStream(file)) { assertCheckWrite(file); - } finally { - out.close(); } // -- newDirectoryStream -- prepare(); - DirectoryStream stream = dir.newDirectoryStream(); - try { - assertCheckRead(dir); + try (DirectoryStream stream = newDirectoryStream(testdir)) { + assertCheckRead(testdir); if (stream instanceof SecureDirectoryStream) { Path entry; @@ -413,63 +451,57 @@ public class CheckPermissions { (SecureDirectoryStream)stream; // newByteChannel - entry = file.getName(); + entry = file.getFileName(); prepare(); - sbc = sds.newByteChannel(entry, EnumSet.of(StandardOpenOption.READ)); - try { + try (SeekableByteChannel sbc = sds.newByteChannel(entry, EnumSet.of(READ))) { assertCheckRead(file); - } finally { - sbc.close(); } prepare(); - sbc = sds.newByteChannel(entry, EnumSet.of(StandardOpenOption.WRITE)); - try { + try (SeekableByteChannel sbc = sds.newByteChannel(entry, EnumSet.of(WRITE))) { assertCheckWrite(file); - } finally { - sbc.close(); } // deleteFile - entry = file.getName(); + entry = file.getFileName(); prepare(); sds.deleteFile(entry); assertCheckDelete(file); - dir.resolve(entry).createFile(); // restore file + createFile(testdir.resolve(entry)); // restore file // deleteDirectory entry = Paths.get("subdir1234"); - dir.resolve(entry).createDirectory(); + createDirectory(testdir.resolve(entry)); prepare(); sds.deleteDirectory(entry); - assertCheckDelete(dir.resolve(entry)); + assertCheckDelete(testdir.resolve(entry)); // move entry = Paths.get("tempname1234"); prepare(); - sds.move(file.getName(), sds, entry); + sds.move(file.getFileName(), sds, entry); assertCheckWrite(file); - assertCheckWrite(dir.resolve(entry)); - sds.move(entry, sds, file.getName()); // restore file + assertCheckWrite(testdir.resolve(entry)); + sds.move(entry, sds, file.getFileName()); // restore file // newDirectoryStream entry = Paths.get("subdir1234"); - dir.resolve(entry).createDirectory(); + createDirectory(testdir.resolve(entry)); try { prepare(); sds.newDirectoryStream(entry).close(); - assertCheckRead(dir.resolve(entry)); + assertCheckRead(testdir.resolve(entry)); } finally { - dir.resolve(entry).delete(); + delete(testdir.resolve(entry)); } // getFileAttributeView to access attributes of directory testBasicFileAttributeView(sds - .getFileAttributeView(BasicFileAttributeView.class), dir); + .getFileAttributeView(BasicFileAttributeView.class), testdir); testPosixFileAttributeView(sds - .getFileAttributeView(PosixFileAttributeView.class), dir); + .getFileAttributeView(PosixFileAttributeView.class), testdir); // getFileAttributeView to access attributes of entry - entry = file.getName(); + entry = file.getFileName(); testBasicFileAttributeView(sds .getFileAttributeView(entry, BasicFileAttributeView.class), file); testPosixFileAttributeView(sds @@ -478,15 +510,12 @@ public class CheckPermissions { } else { System.out.println("SecureDirectoryStream not tested"); } - - } finally { - stream.close(); } // -- toAbsolutePath -- prepare(); - file.getName().toAbsolutePath(); + file.getFileName().toAbsolutePath(); assertCheckPropertyAccess("user.dir"); // -- toRealPath -- @@ -509,41 +538,38 @@ public class CheckPermissions { // -- register -- - WatchService watcher = FileSystems.getDefault().newWatchService(); - try { + try (WatchService watcher = FileSystems.getDefault().newWatchService()) { prepare(); - dir.register(watcher, StandardWatchEventKind.ENTRY_DELETE); - assertCheckRead(dir); - } finally { - watcher.close(); + testdir.register(watcher, StandardWatchEventKind.ENTRY_DELETE); + assertCheckRead(testdir); } // -- getAttribute/setAttribute/readAttributes -- prepare(); - file.getAttribute("size"); + getAttribute(file, "size"); assertCheckRead(file); prepare(); - file.setAttribute("lastModifiedTime", + setAttribute(file, "lastModifiedTime", FileTime.fromMillis(System.currentTimeMillis())); assertCheckWrite(file); prepare(); - file.readAttributes("*"); + readAttributes(file, "*"); assertCheckRead(file); // -- BasicFileAttributeView -- - testBasicFileAttributeView(file - .getFileAttributeView(BasicFileAttributeView.class), file); + testBasicFileAttributeView( + getFileAttributeView(file, BasicFileAttributeView.class), file); // -- PosixFileAttributeView -- { PosixFileAttributeView view = - file.getFileAttributeView(PosixFileAttributeView.class); + getFileAttributeView(file, PosixFileAttributeView.class); if (view != null && - file.getFileStore().supportsFileAttributeView(PosixFileAttributeView.class)) + getFileStore(file).supportsFileAttributeView(PosixFileAttributeView.class)) { testPosixFileAttributeView(view, file); } else { @@ -555,9 +581,9 @@ public class CheckPermissions { { DosFileAttributeView view = - file.getFileAttributeView(DosFileAttributeView.class); + getFileAttributeView(file, DosFileAttributeView.class); if (view != null && - file.getFileStore().supportsFileAttributeView(DosFileAttributeView.class)) + getFileStore(file).supportsFileAttributeView(DosFileAttributeView.class)) { prepare(); view.readAttributes(); @@ -587,9 +613,9 @@ public class CheckPermissions { { FileOwnerAttributeView view = - file.getFileAttributeView(FileOwnerAttributeView.class); + getFileAttributeView(file, FileOwnerAttributeView.class); if (view != null && - file.getFileStore().supportsFileAttributeView(FileOwnerAttributeView.class)) + getFileStore(file).supportsFileAttributeView(FileOwnerAttributeView.class)) { prepare(); UserPrincipal owner = view.getOwner(); @@ -610,9 +636,9 @@ public class CheckPermissions { { UserDefinedFileAttributeView view = - file.getFileAttributeView(UserDefinedFileAttributeView.class); + getFileAttributeView(file, UserDefinedFileAttributeView.class); if (view != null && - file.getFileStore().supportsFileAttributeView(UserDefinedFileAttributeView.class)) + getFileStore(file).supportsFileAttributeView(UserDefinedFileAttributeView.class)) { prepare(); view.write("test", ByteBuffer.wrap(new byte[100])); @@ -651,9 +677,9 @@ public class CheckPermissions { // -- AclFileAttributeView -- { AclFileAttributeView view = - file.getFileAttributeView(AclFileAttributeView.class); + getFileAttributeView(file, AclFileAttributeView.class); if (view != null && - file.getFileStore().supportsFileAttributeView(AclFileAttributeView.class)) + getFileStore(file).supportsFileAttributeView(AclFileAttributeView.class)) { prepare(); List acl = view.getAcl(); @@ -672,7 +698,7 @@ public class CheckPermissions { UserPrincipalLookupService lookupService = FileSystems.getDefault().getUserPrincipalLookupService(); - UserPrincipal owner = Attributes.getOwner(file); + UserPrincipal owner = getOwner(file); prepare(); lookupService.lookupPrincipalByName(owner.getName()); @@ -680,7 +706,7 @@ public class CheckPermissions { "lookupUserInformation"); try { - UserPrincipal group = Attributes.readPosixFileAttributes(file).group(); + UserPrincipal group = readAttributes(file, PosixFileAttributes.class).group(); prepare(); lookupService.lookupPrincipalByGroupName(group.getName()); assertCheckPermission(RuntimePermission.class, @@ -691,7 +717,7 @@ public class CheckPermissions { } finally { - file.deleteIfExists(); + deleteIfExists(file); } } } diff --git a/jdk/test/java/nio/file/Path/CopyAndMove.java b/jdk/test/java/nio/file/Files/CopyAndMove.java similarity index 63% rename from jdk/test/java/nio/file/Path/CopyAndMove.java rename to jdk/test/java/nio/file/Files/CopyAndMove.java index 17e3cab38e0..c0d2ba6dd8f 100644 --- a/jdk/test/java/nio/file/Path/CopyAndMove.java +++ b/jdk/test/java/nio/file/Files/CopyAndMove.java @@ -22,8 +22,8 @@ */ /* @test - * @bug 4313887 6838333 6917021 - * @summary Unit test for java.nio.file.Path copyTo/moveTo methods + * @bug 4313887 6838333 6917021 7006126 + * @summary Unit test for java.nio.file.Files copy and move methods * @library .. * @build CopyAndMove PassThroughFileSystem * @run main/othervm CopyAndMove @@ -31,6 +31,7 @@ import java.nio.ByteBuffer; import java.nio.file.*; +import static java.nio.file.Files.*; import static java.nio.file.StandardCopyOption.*; import static java.nio.file.LinkOption.*; import java.nio.file.attribute.*; @@ -44,9 +45,10 @@ public class CopyAndMove { public static void main(String[] args) throws Exception { Path dir1 = TestUtil.createTemporaryDirectory(); try { + // Same directory - doCopyTests(dir1, dir1, TestUtil.supportsLinks(dir1)); - doMoveTests(dir1, dir1, TestUtil.supportsLinks(dir1)); + testCopyFileToFile(dir1, dir1, TestUtil.supportsLinks(dir1)); + testMove(dir1, dir1, TestUtil.supportsLinks(dir1)); // Different directories. Use test.dir if possible as it might be // a different volume/file system and so improve test coverage. @@ -55,16 +57,20 @@ public class CopyAndMove { try { boolean testSymbolicLinks = TestUtil.supportsLinks(dir1) && TestUtil.supportsLinks(dir2); - doCopyTests(dir1, dir2, testSymbolicLinks); - doMoveTests(dir1, dir2, testSymbolicLinks); + testCopyFileToFile(dir1, dir2, testSymbolicLinks); + testMove(dir1, dir2, testSymbolicLinks); } finally { TestUtil.removeAll(dir2); } // Target is location associated with custom provider Path dir3 = PassThroughFileSystem.create().getPath(dir1.toString()); - doCopyTests(dir1, dir3, false); - doMoveTests(dir1, dir3, false); + testCopyFileToFile(dir1, dir3, false); + testMove(dir1, dir3, false); + + // Test copy(InputStream,Path) and copy(Path,OutputStream) + testCopyInputStreamToFile(); + testCopyFileToOuputStream(); } finally { TestUtil.removeAll(dir1); @@ -121,9 +127,9 @@ public class CopyAndMove { static Map readUserDefinedFileAttributes(Path file) throws IOException { - UserDefinedFileAttributeView view = file - .getFileAttributeView(UserDefinedFileAttributeView.class); - Map result = new HashMap(); + UserDefinedFileAttributeView view = + getFileAttributeView(file, UserDefinedFileAttributeView.class); + Map result = new HashMap<>(); for (String name: view.list()) { int size = view.size(name); ByteBuffer bb = ByteBuffer.allocate(size); @@ -148,15 +154,15 @@ public class CopyAndMove { // get file attributes of source file String os = System.getProperty("os.name"); if (os.equals("SunOS") || os.equals("Linux")) { - posixAttributes = Attributes.readPosixFileAttributes(source, NOFOLLOW_LINKS); + posixAttributes = readAttributes(source, PosixFileAttributes.class, NOFOLLOW_LINKS); basicAttributes = posixAttributes; } if (os.startsWith("Windows")) { - dosAttributes = Attributes.readDosFileAttributes(source, NOFOLLOW_LINKS); + dosAttributes = readAttributes(source, DosFileAttributes.class, NOFOLLOW_LINKS); basicAttributes = dosAttributes; } if (basicAttributes == null) - basicAttributes = Attributes.readBasicFileAttributes(source, NOFOLLOW_LINKS); + basicAttributes = readAttributes(source, BasicFileAttributes.class, NOFOLLOW_LINKS); // hash file contents if regular file int hash = (basicAttributes.isRegularFile()) ? computeHash(source) : 0; @@ -164,20 +170,21 @@ public class CopyAndMove { // record link target if symbolic link Path linkTarget = null; if (basicAttributes.isSymbolicLink()) - linkTarget = source.readSymbolicLink(); + linkTarget = readSymbolicLink(source); // read named attributes if available (and file is not a sym link) if (!basicAttributes.isSymbolicLink() && - source.getFileStore().supportsFileAttributeView("xattr")) + getFileStore(source).supportsFileAttributeView("xattr")) { namedAttributes = readUserDefinedFileAttributes(source); } // move file - source.moveTo(target, options); + Path result = move(source, target, options); + assertTrue(result == target); // verify source does not exist - assertTrue(source.notExists()); + assertTrue(notExists(source)); // verify file contents if (basicAttributes.isRegularFile()) { @@ -187,13 +194,13 @@ public class CopyAndMove { // verify link target if (basicAttributes.isSymbolicLink()) { - if (!target.readSymbolicLink().equals(linkTarget)) + if (!readSymbolicLink(target).equals(linkTarget)) throw new RuntimeException("Failed to verify move of symbolic link"); } // verify basic attributes checkBasicAttributes(basicAttributes, - Attributes.readBasicFileAttributes(target, NOFOLLOW_LINKS)); + readAttributes(target, BasicFileAttributes.class, NOFOLLOW_LINKS)); // verify other attributes when same provider if (source.getFileSystem().provider() == target.getFileSystem().provider()) { @@ -201,18 +208,19 @@ public class CopyAndMove { // verify POSIX attributes if (posixAttributes != null && !basicAttributes.isSymbolicLink()) { checkPosixAttributes(posixAttributes, - Attributes.readPosixFileAttributes(target, NOFOLLOW_LINKS)); + readAttributes(target, PosixFileAttributes.class, NOFOLLOW_LINKS)); } // verify DOS attributes if (dosAttributes != null && !basicAttributes.isSymbolicLink()) { - checkDosAttributes(dosAttributes, - Attributes.readDosFileAttributes(target, NOFOLLOW_LINKS)); + DosFileAttributes attrs = + readAttributes(target, DosFileAttributes.class, NOFOLLOW_LINKS); + checkDosAttributes(dosAttributes, attrs); } // verify named attributes if (namedAttributes != null && - target.getFileStore().supportsFileAttributeView("xattr")) + getFileStore(target).supportsFileAttributeView("xattr")) { checkUserDefinedFileAttributes(namedAttributes, readUserDefinedFileAttributes(target)); @@ -221,14 +229,14 @@ public class CopyAndMove { } /** - * Tests all possible ways to invoke moveTo + * Tests all possible ways to invoke move */ - static void doMoveTests(Path dir1, Path dir2, boolean supportsLinks) + static void testMove(Path dir1, Path dir2, boolean supportsLinks) throws IOException { Path source, target, entry; - boolean sameDevice = dir1.getFileStore().equals(dir2.getFileStore()); + boolean sameDevice = getFileStore(dir1).equals(getFileStore(dir2)); // -- regular file -- @@ -238,27 +246,28 @@ public class CopyAndMove { source = createSourceFile(dir1); target = getTargetFile(dir2); moveAndVerify(source, target); - target.delete(); + delete(target); /** * Test: move regular file, target exists */ source = createSourceFile(dir1); - target = getTargetFile(dir2).createFile(); + target = getTargetFile(dir2); + createFile(target); try { moveAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - target.delete(); - target.createDirectory(); + delete(target); + createDirectory(target); try { moveAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: move regular file, target does not exist @@ -266,38 +275,42 @@ public class CopyAndMove { source = createSourceFile(dir1); target = getTargetFile(dir2); moveAndVerify(source, target, REPLACE_EXISTING); - target.delete(); + delete(target); /** * Test: move regular file, target exists */ source = createSourceFile(dir1); - target = getTargetFile(dir2).createFile(); + target = getTargetFile(dir2); + createFile(target); moveAndVerify(source, target, REPLACE_EXISTING); - target.delete(); + delete(target); /** * Test: move regular file, target exists and is empty directory */ source = createSourceFile(dir1); - target = getTargetFile(dir2).createDirectory(); + target = getTargetFile(dir2); + createDirectory(target); moveAndVerify(source, target, REPLACE_EXISTING); - target.delete(); + delete(target); /** * Test: move regular file, target exists and is non-empty directory */ source = createSourceFile(dir1); - target = getTargetFile(dir2).createDirectory(); - entry = target.resolve("foo").createFile(); + target = getTargetFile(dir2); + createDirectory(target); + entry = target.resolve("foo"); + createFile(entry); try { moveAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - entry.delete(); - source.delete(); - target.delete(); + delete(entry); + delete(source); + delete(target); /** * Test atomic move of regular file (same file store) @@ -305,7 +318,7 @@ public class CopyAndMove { source = createSourceFile(dir1); target = getTargetFile(dir1); moveAndVerify(source, target, ATOMIC_MOVE); - target.delete(); + delete(target); /** * Test atomic move of regular file (different file store) @@ -318,7 +331,7 @@ public class CopyAndMove { throw new RuntimeException("AtomicMoveNotSupportedException expected"); } catch (AtomicMoveNotSupportedException x) { } - source.delete(); + delete(source); } // -- directories -- @@ -329,27 +342,28 @@ public class CopyAndMove { source = createSourceDirectory(dir1); target = getTargetFile(dir2); moveAndVerify(source, target); - target.delete(); + delete(target); /** * Test: move empty directory, target exists */ source = createSourceDirectory(dir1); - target = getTargetFile(dir2).createFile(); + target = getTargetFile(dir2); + createFile(target); try { moveAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - target.delete(); - target.createDirectory(); + delete(target); + createDirectory(target); try { moveAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: move empty directory, target does not exist @@ -357,74 +371,78 @@ public class CopyAndMove { source = createSourceDirectory(dir1); target = getTargetFile(dir2); moveAndVerify(source, target, REPLACE_EXISTING); - target.delete(); + delete(target); /** * Test: move empty directory, target exists */ source = createSourceDirectory(dir1); - target = getTargetFile(dir2).createFile(); + target = getTargetFile(dir2); + createFile(target); moveAndVerify(source, target, REPLACE_EXISTING); - target.delete(); + delete(target); /** * Test: move empty, target exists and is empty directory */ source = createSourceDirectory(dir1); - target = getTargetFile(dir2).createDirectory(); + target = getTargetFile(dir2); + createDirectory(target); moveAndVerify(source, target, REPLACE_EXISTING); - target.delete(); + delete(target); /** * Test: move empty directory, target exists and is non-empty directory */ source = createSourceDirectory(dir1); - target = getTargetFile(dir2).createDirectory(); - entry = target.resolve("foo").createFile(); + target = getTargetFile(dir2); + createDirectory(target); + entry = target.resolve("foo"); + createFile(entry); try { moveAndVerify(source, target, REPLACE_EXISTING); - throw new RuntimeException("FileAlreadyExistsException expected"); - } catch (FileAlreadyExistsException x) { + throw new RuntimeException("DirectoryNotEmptyException expected"); + } catch (DirectoryNotEmptyException x) { } - entry.delete(); - source.delete(); - target.delete(); + delete(entry); + delete(source); + delete(target); /** * Test: move non-empty directory (same file system) */ source = createSourceDirectory(dir1); - source.resolve("foo").createFile(); + createFile(source.resolve("foo")); target = getTargetFile(dir1); moveAndVerify(source, target); - target.resolve("foo").delete(); - target.delete(); + delete(target.resolve("foo")); + delete(target); /** * Test: move non-empty directory (different file store) */ if (!sameDevice) { source = createSourceDirectory(dir1); - source.resolve("foo").createFile(); + createFile(source.resolve("foo")); target = getTargetFile(dir2); try { moveAndVerify(source, target); throw new RuntimeException("IOException expected"); } catch (IOException x) { } - source.resolve("foo").delete(); - source.delete(); + delete(source.resolve("foo")); + delete(source); } /** * Test atomic move of directory (same file store) */ source = createSourceDirectory(dir1); - source.resolve("foo").createFile(); + createFile(source.resolve("foo")); target = getTargetFile(dir1); moveAndVerify(source, target, ATOMIC_MOVE); - target.resolve("foo").delete(); - target.delete(); + delete(target.resolve("foo")); + delete(target); // -- symbolic links -- @@ -433,21 +451,23 @@ public class CopyAndMove { */ if (supportsLinks) { Path tmp = createSourceFile(dir1); - source = dir1.resolve("link").createSymbolicLink(tmp); + source = dir1.resolve("link"); + createSymbolicLink(source, tmp); target = getTargetFile(dir2); moveAndVerify(source, target); - target.delete(); - tmp.delete(); + delete(target); + delete(tmp); } /** * Test: Move symbolic link to directory, target does not exist */ if (supportsLinks) { - source = dir1.resolve("link").createSymbolicLink(dir2); + source = dir1.resolve("link"); + createSymbolicLink(source, dir2); target = getTargetFile(dir2); moveAndVerify(source, target); - target.delete(); + delete(target); } /** @@ -455,72 +475,84 @@ public class CopyAndMove { */ if (supportsLinks) { Path tmp = Paths.get("doesnotexist"); - source = dir1.resolve("link").createSymbolicLink(tmp); + source = dir1.resolve("link"); + createSymbolicLink(source, tmp); target = getTargetFile(dir2); moveAndVerify(source, target); - target.delete(); + delete(target); } /** * Test: Move symbolic link, target exists */ if (supportsLinks) { - source = dir1.resolve("link").createSymbolicLink(dir2); - target = getTargetFile(dir2).createFile(); + source = dir1.resolve("link"); + createSymbolicLink(source, dir2); + target = getTargetFile(dir2); + createFile(target); try { moveAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - source.delete(); - target.delete(); + delete(source); + delete(target); } /** * Test: Move regular file, target exists */ if (supportsLinks) { - source = dir1.resolve("link").createSymbolicLink(dir2); - target = getTargetFile(dir2).createFile(); + source = dir1.resolve("link"); + createSymbolicLink(source, dir2); + target = getTargetFile(dir2); + createFile(target); moveAndVerify(source, target, REPLACE_EXISTING); - target.delete(); + delete(target); } /** * Test: move symbolic link, target exists and is empty directory */ if (supportsLinks) { - source = dir1.resolve("link").createSymbolicLink(dir2); - target = getTargetFile(dir2).createDirectory(); + source = dir1.resolve("link"); + createSymbolicLink(source, dir2); + target = getTargetFile(dir2); + createDirectory(target); moveAndVerify(source, target, REPLACE_EXISTING); - target.delete(); + delete(target); } /** * Test: symbolic link, target exists and is non-empty directory */ if (supportsLinks) { - source = dir1.resolve("link").createSymbolicLink(dir2); - target = getTargetFile(dir2).createDirectory(); - entry = target.resolve("foo").createFile(); + source = dir1.resolve("link"); + createSymbolicLink(source, dir2); + target = getTargetFile(dir2); + createDirectory(target); + entry = target.resolve("foo"); + createFile(entry); try { moveAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - entry.delete(); - source.delete(); - target.delete(); + delete(entry); + delete(source); + delete(target); } /** * Test atomic move of symbolic link (same file store) */ if (supportsLinks) { - source = dir1.resolve("link").createSymbolicLink(dir1); - target = getTargetFile(dir2).createFile(); + source = dir1.resolve("link"); + createSymbolicLink(source, dir1); + target = getTargetFile(dir2); + createFile(target); moveAndVerify(source, target, REPLACE_EXISTING); - target.delete(); + delete(target); } // -- misc. tests -- @@ -531,19 +563,23 @@ public class CopyAndMove { source = createSourceFile(dir1); target = getTargetFile(dir2); try { - source.moveTo(null); + move(null, target); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } try { - source.moveTo(target, (CopyOption[])null); + move(source, null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + try { + move(source, target, (CopyOption[])null); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } try { CopyOption[] opts = { REPLACE_EXISTING, null }; - source.moveTo(target, opts); + move(source, target, opts); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } - source.delete(); + delete(source); /** * Test UOE @@ -551,19 +587,20 @@ public class CopyAndMove { source = createSourceFile(dir1); target = getTargetFile(dir2); try { - source.moveTo(target, new CopyOption() { }); + move(source, target, new CopyOption() { }); } catch (UnsupportedOperationException x) { } try { - source.moveTo(target, REPLACE_EXISTING, new CopyOption() { }); + move(source, target, REPLACE_EXISTING, new CopyOption() { }); } catch (UnsupportedOperationException x) { } - source.delete(); + delete(source); } // copy source to target with verification static void copyAndVerify(Path source, Path target, CopyOption... options) throws IOException { - source.copyTo(target, options); + Path result = copy(source, target, options); + assertTrue(result == target); // get attributes of source and target file to verify copy boolean followLinks = true; @@ -577,8 +614,8 @@ public class CopyAndMove { if (opt == COPY_ATTRIBUTES) copyAttributes = true; } - BasicFileAttributes basicAttributes = Attributes - .readBasicFileAttributes(source, linkOptions); + BasicFileAttributes basicAttributes = + readAttributes(source, BasicFileAttributes.class, linkOptions); // check hash if regular file if (basicAttributes.isRegularFile()) @@ -586,12 +623,12 @@ public class CopyAndMove { // check link target if symbolic link if (basicAttributes.isSymbolicLink()) - assert( source.readSymbolicLink().equals(target.readSymbolicLink())); + assert(readSymbolicLink(source).equals(readSymbolicLink(target))); // check that attributes are copied if (copyAttributes && followLinks) { checkBasicAttributes(basicAttributes, - Attributes.readBasicFileAttributes(source, linkOptions)); + readAttributes(source, BasicFileAttributes.class, linkOptions)); // verify other attributes when same provider if (source.getFileSystem().provider() == target.getFileSystem().provider()) { @@ -600,21 +637,21 @@ public class CopyAndMove { String os = System.getProperty("os.name"); if (os.equals("SunOS") || os.equals("Linux")) { checkPosixAttributes( - Attributes.readPosixFileAttributes(source, linkOptions), - Attributes.readPosixFileAttributes(target, linkOptions)); + readAttributes(source, PosixFileAttributes.class, linkOptions), + readAttributes(target, PosixFileAttributes.class, linkOptions)); } // check DOS attributes are copied if (os.startsWith("Windows")) { checkDosAttributes( - Attributes.readDosFileAttributes(source, linkOptions), - Attributes.readDosFileAttributes(target, linkOptions)); + readAttributes(source, DosFileAttributes.class, linkOptions), + readAttributes(target, DosFileAttributes.class, linkOptions)); } // check named attributes are copied if (followLinks && - source.getFileStore().supportsFileAttributeView("xattr") && - target.getFileStore().supportsFileAttributeView("xattr")) + getFileStore(source).supportsFileAttributeView("xattr") && + getFileStore(target).supportsFileAttributeView("xattr")) { checkUserDefinedFileAttributes(readUserDefinedFileAttributes(source), readUserDefinedFileAttributes(target)); @@ -624,9 +661,9 @@ public class CopyAndMove { } /** - * Tests all possible ways to invoke copyTo + * Tests all possible ways to invoke copy to copy a file to a file */ - static void doCopyTests(Path dir1, Path dir2, boolean supportsLinks) + static void testCopyFileToFile(Path dir1, Path dir2, boolean supportsLinks) throws IOException { Path source, target, link, entry; @@ -639,28 +676,29 @@ public class CopyAndMove { source = createSourceFile(dir1); target = getTargetFile(dir2); copyAndVerify(source, target); - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: copy regular file, target exists */ source = createSourceFile(dir1); - target = getTargetFile(dir2).createFile(); + target = getTargetFile(dir2); + createFile(target); try { copyAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - target.delete(); - target.createDirectory(); + delete(target); + createDirectory(target); try { copyAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: copy regular file, target does not exist @@ -668,41 +706,45 @@ public class CopyAndMove { source = createSourceFile(dir1); target = getTargetFile(dir2); copyAndVerify(source, target, REPLACE_EXISTING); - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: copy regular file, target exists */ source = createSourceFile(dir1); - target = getTargetFile(dir2).createFile(); + target = getTargetFile(dir2); + createFile(target); copyAndVerify(source, target, REPLACE_EXISTING); - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: copy regular file, target exists and is empty directory */ source = createSourceFile(dir1); - target = getTargetFile(dir2).createDirectory(); + target = getTargetFile(dir2); + createDirectory(target); copyAndVerify(source, target, REPLACE_EXISTING); - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: copy regular file, target exists and is non-empty directory */ source = createSourceFile(dir1); - target = getTargetFile(dir2).createDirectory(); - entry = target.resolve("foo").createFile(); + target = getTargetFile(dir2); + createDirectory(target); + entry = target.resolve("foo"); + createFile(entry); try { copyAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - entry.delete(); - source.delete(); - target.delete(); + delete(entry); + delete(source); + delete(target); /** * Test: copy regular file + attributes @@ -710,8 +752,8 @@ public class CopyAndMove { source = createSourceFile(dir1); target = getTargetFile(dir2); copyAndVerify(source, target, COPY_ATTRIBUTES); - source.delete(); - target.delete(); + delete(source); + delete(target); // -- directory -- @@ -722,28 +764,29 @@ public class CopyAndMove { source = createSourceDirectory(dir1); target = getTargetFile(dir2); copyAndVerify(source, target); - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: copy directory, target exists */ source = createSourceDirectory(dir1); - target = getTargetFile(dir2).createFile(); + target = getTargetFile(dir2); + createFile(target); try { copyAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - target.delete(); - target.createDirectory(); + delete(target); + createDirectory(target); try { copyAndVerify(source, target); throw new RuntimeException("FileAlreadyExistsException expected"); } catch (FileAlreadyExistsException x) { } - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: copy directory, target does not exist @@ -751,41 +794,45 @@ public class CopyAndMove { source = createSourceDirectory(dir1); target = getTargetFile(dir2); copyAndVerify(source, target, REPLACE_EXISTING); - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: copy directory, target exists */ source = createSourceDirectory(dir1); - target = getTargetFile(dir2).createFile(); + target = getTargetFile(dir2); + createFile(target); copyAndVerify(source, target, REPLACE_EXISTING); - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: copy directory, target exists and is empty directory */ source = createSourceDirectory(dir1); - target = getTargetFile(dir2).createDirectory(); + target = getTargetFile(dir2); + createDirectory(target); copyAndVerify(source, target, REPLACE_EXISTING); - source.delete(); - target.delete(); + delete(source); + delete(target); /** * Test: copy directory, target exists and is non-empty directory */ source = createSourceDirectory(dir1); - target = getTargetFile(dir2).createDirectory(); - entry = target.resolve("foo").createFile(); + target = getTargetFile(dir2); + createDirectory(target); + entry = target.resolve("foo"); + createFile(entry); try { copyAndVerify(source, target, REPLACE_EXISTING); - throw new RuntimeException("FileAlreadyExistsException expected"); - } catch (FileAlreadyExistsException x) { + throw new RuntimeException("DirectoryNotEmptyException expected"); + } catch (DirectoryNotEmptyException x) { } - entry.delete(); - source.delete(); - target.delete(); + delete(entry); + delete(source); + delete(target); /* * Test: copy directory + attributes @@ -793,8 +840,8 @@ public class CopyAndMove { source = createSourceDirectory(dir1); target = getTargetFile(dir2); copyAndVerify(source, target, COPY_ATTRIBUTES); - source.delete(); - target.delete(); + delete(source); + delete(target); // -- symbolic links -- @@ -803,11 +850,12 @@ public class CopyAndMove { */ if (supportsLinks) { source = createSourceFile(dir1); - link = dir1.resolve("link").createSymbolicLink(source); + link = dir1.resolve("link"); + createSymbolicLink(link, source); target = getTargetFile(dir2); copyAndVerify(link, target); - link.delete(); - source.delete(); + delete(link); + delete(source); } /** @@ -815,34 +863,38 @@ public class CopyAndMove { */ if (supportsLinks) { source = createSourceFile(dir1); - link = dir1.resolve("link").createSymbolicLink(source); + link = dir1.resolve("link"); + createSymbolicLink(link, source); target = getTargetFile(dir2); copyAndVerify(link, target, NOFOLLOW_LINKS); - link.delete(); - source.delete(); + delete(link); + delete(source); } /** * Test: Copy link (to directory) */ if (supportsLinks) { - source = dir1.resolve("mydir").createDirectory(); - link = dir1.resolve("link").createSymbolicLink(source); + source = dir1.resolve("mydir"); + createDirectory(source); + link = dir1.resolve("link"); + createSymbolicLink(link, source); target = getTargetFile(dir2); copyAndVerify(link, target, NOFOLLOW_LINKS); - link.delete(); - source.delete(); + delete(link); + delete(source); } /** * Test: Copy broken link */ if (supportsLinks) { - assertTrue(source.notExists()); - link = dir1.resolve("link").createSymbolicLink(source); + assertTrue(notExists(source)); + link = dir1.resolve("link"); + createSymbolicLink(link, source); target = getTargetFile(dir2); copyAndVerify(link, target, NOFOLLOW_LINKS); - link.delete(); + delete(link); } /** @@ -852,10 +904,11 @@ public class CopyAndMove { System.getProperty("os.name").startsWith("Windows")) { Path unc = Paths.get("\\\\rialto\\share\\file"); - link = dir1.resolve("link").createSymbolicLink(unc); + link = dir1.resolve("link"); + createSymbolicLink(link, unc); target = getTargetFile(dir2); copyAndVerify(link, target, NOFOLLOW_LINKS); - link.delete(); + delete(link); } // -- misc. tests -- @@ -866,19 +919,19 @@ public class CopyAndMove { source = createSourceFile(dir1); target = getTargetFile(dir2); try { - source.copyTo(null); + copy(source, null); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } try { - source.copyTo(target, (CopyOption[])null); + copy(source, target, (CopyOption[])null); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } try { CopyOption[] opts = { REPLACE_EXISTING, null }; - source.copyTo(target, opts); + copy(source, target, opts); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } - source.delete(); + delete(source); /** * Test UOE @@ -886,14 +939,154 @@ public class CopyAndMove { source = createSourceFile(dir1); target = getTargetFile(dir2); try { - source.copyTo(target, new CopyOption() { }); + copy(source, target, new CopyOption() { }); } catch (UnsupportedOperationException x) { } try { - source.copyTo(target, REPLACE_EXISTING, new CopyOption() { }); + copy(source, target, REPLACE_EXISTING, new CopyOption() { }); } catch (UnsupportedOperationException x) { } - source.delete(); + delete(source); } + /** + * Test copy from an input stream to a file + */ + static void testCopyInputStreamToFile() throws IOException { + testCopyInputStreamToFile(0); + for (int i=0; i<100; i++) { + testCopyInputStreamToFile(rand.nextInt(32000)); + } + + // FileAlreadyExistsException + Path target = createTempFile("blah", null); + try { + InputStream in = new ByteArrayInputStream(new byte[0]); + try { + copy(in, target); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException ignore) { } + } finally { + delete(target); + } + Path tmpdir = createTempDirectory("blah"); + try { + if (TestUtil.supportsLinks(tmpdir)) { + Path link = createSymbolicLink(tmpdir.resolve("link"), + tmpdir.resolve("target")); + try { + InputStream in = new ByteArrayInputStream(new byte[0]); + try { + copy(in, link); + throw new RuntimeException("FileAlreadyExistsException expected"); + } catch (FileAlreadyExistsException ignore) { } + } finally { + delete(link); + } + } + } finally { + delete(tmpdir); + } + + + // nulls + try { + copy((InputStream)null, target); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + copy(new ByteArrayInputStream(new byte[0]), (Path)null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + } + + static void testCopyInputStreamToFile(int size) throws IOException { + Path tmpdir = createTempDirectory("blah"); + Path source = tmpdir.resolve("source"); + Path target = tmpdir.resolve("target"); + try { + boolean testReplaceExisting = rand.nextBoolean(); + + // create source file + byte[] b = new byte[size]; + rand.nextBytes(b); + write(source, b); + + // target file might already exist + if (testReplaceExisting && rand.nextBoolean()) { + write(target, new byte[rand.nextInt(512)]); + } + + // copy from stream to file + InputStream in = new FileInputStream(source.toFile()); + try { + long n; + if (testReplaceExisting) { + n = copy(in, target, StandardCopyOption.REPLACE_EXISTING); + } else { + n = copy(in, target); + } + assertTrue(in.read() == -1); // EOF + assertTrue(n == size); + assertTrue(size(target) == size); + } finally { + in.close(); + } + + // check file + byte[] read = readAllBytes(target); + assertTrue(Arrays.equals(read, b)); + + } finally { + deleteIfExists(source); + deleteIfExists(target); + delete(tmpdir); + } + } + + /** + * Test copy from file to output stream + */ + static void testCopyFileToOuputStream() throws IOException { + testCopyFileToOuputStream(0); + for (int i=0; i<100; i++) { + testCopyFileToOuputStream(rand.nextInt(32000)); + } + + // nulls + try { + copy((Path)null, new ByteArrayOutputStream()); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + Path source = createTempFile("blah", null); + delete(source); + copy(source, (OutputStream)null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + } + + static void testCopyFileToOuputStream(int size) throws IOException { + Path source = createTempFile("blah", null); + try { + byte[] b = new byte[size]; + rand.nextBytes(b); + write(source, b); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + long n = copy(source, out); + assertTrue(n == size); + assertTrue(out.size() == size); + + byte[] read = out.toByteArray(); + assertTrue(Arrays.equals(read, b)); + + // check output stream is open + out.write(0); + assertTrue(out.size() == size+1); + } finally { + delete(source); + } + } static void assertTrue(boolean value) { if (!value) @@ -904,8 +1097,7 @@ public class CopyAndMove { static int computeHash(Path file) throws IOException { int h = 0; - InputStream in = file.newInputStream(); - try { + try (InputStream in = newInputStream(file)) { byte[] buf = new byte[1024]; int n; do { @@ -914,8 +1106,6 @@ public class CopyAndMove { h = 31*h + (buf[i] & 0xff); } } while (n > 0); - } finally { - in.close(); } return h; } @@ -923,14 +1113,12 @@ public class CopyAndMove { // create file of random size in given directory static Path createSourceFile(Path dir) throws IOException { String name = "source" + Integer.toString(rand.nextInt()); - Path file = dir.resolve(name).createFile(); + Path file = dir.resolve(name); + createFile(file); byte[] bytes = new byte[rand.nextInt(128*1024)]; rand.nextBytes(bytes); - OutputStream out = file.newOutputStream(); - try { + try (OutputStream out = newOutputStream(file)) { out.write(bytes); - } finally { - out.close(); } randomizeAttributes(file); return file; @@ -939,7 +1127,8 @@ public class CopyAndMove { // create directory in the given directory static Path createSourceDirectory(Path dir) throws IOException { String name = "sourcedir" + Integer.toString(rand.nextInt()); - Path subdir = dir.resolve(name).createDirectory(); + Path subdir = dir.resolve(name); + createDirectory(subdir); randomizeAttributes(subdir); return subdir; } @@ -949,12 +1138,11 @@ public class CopyAndMove { String os = System.getProperty("os.name"); boolean isWindows = os.startsWith("Windows"); boolean isUnix = os.equals("SunOS") || os.equals("Linux"); - boolean isDirectory = Attributes.readBasicFileAttributes(file, NOFOLLOW_LINKS) - .isDirectory(); + boolean isDirectory = isDirectory(file, NOFOLLOW_LINKS); if (isUnix) { - Set perms = Attributes - .readPosixFileAttributes(file, NOFOLLOW_LINKS).permissions(); + Set perms = + getPosixFilePermissions(file, NOFOLLOW_LINKS); PosixFilePermission[] toChange = { PosixFilePermission.GROUP_READ, PosixFilePermission.GROUP_WRITE, @@ -970,25 +1158,25 @@ public class CopyAndMove { perms.remove(perm); } } - Attributes.setPosixFilePermissions(file, perms); + setPosixFilePermissions(file, perms); } if (isWindows) { - DosFileAttributeView view = file - .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS); + DosFileAttributeView view = + getFileAttributeView(file, DosFileAttributeView.class, NOFOLLOW_LINKS); // only set or unset the hidden attribute view.setHidden(heads()); } boolean addUserDefinedFileAttributes = heads() && - file.getFileStore().supportsFileAttributeView("xattr"); + getFileStore(file).supportsFileAttributeView("xattr"); // remove this when copying a direcory copies its named streams if (isWindows && isDirectory) addUserDefinedFileAttributes = false; if (addUserDefinedFileAttributes) { - UserDefinedFileAttributeView view = file - .getFileAttributeView(UserDefinedFileAttributeView.class); + UserDefinedFileAttributeView view = + getFileAttributeView(file, UserDefinedFileAttributeView.class); int n = rand.nextInt(16); while (n > 0) { byte[] value = new byte[1 + rand.nextInt(100)]; diff --git a/jdk/test/java/nio/file/Path/DeleteOnClose.java b/jdk/test/java/nio/file/Files/DeleteOnClose.java similarity index 73% rename from jdk/test/java/nio/file/Path/DeleteOnClose.java rename to jdk/test/java/nio/file/Files/DeleteOnClose.java index 506c848f627..9b50a30b0be 100644 --- a/jdk/test/java/nio/file/Path/DeleteOnClose.java +++ b/jdk/test/java/nio/file/Files/DeleteOnClose.java @@ -31,44 +31,43 @@ public class DeleteOnClose { public static void main(String[] args) throws IOException { // open file but do not close it. Its existance will be checked by // the calling script. - Paths.get(args[0]).newByteChannel(READ, WRITE, DELETE_ON_CLOSE); + Files.newByteChannel(Paths.get(args[0]), READ, WRITE, DELETE_ON_CLOSE); // check temporary file has been deleted after closing it - Path file = File.createTempFile("blah", "tmp").toPath(); - file.newByteChannel(READ, WRITE, DELETE_ON_CLOSE).close(); - if (file.exists()) + Path file = Files.createTempFile("blah", "tmp"); + Files.newByteChannel(file, READ, WRITE, DELETE_ON_CLOSE).close(); + if (Files.exists(file)) throw new RuntimeException("Temporary file was not deleted"); - Path dir = TestUtil.createTemporaryDirectory(); + Path dir = Files.createTempDirectory("blah"); try { // check that DELETE_ON_CLOSE fails when file is a sym link if (TestUtil.supportsLinks(dir)) { - file = dir.resolve("foo").createFile(); - Path link = dir.resolve("link").createSymbolicLink(file); + file = dir.resolve("foo"); + Files.createFile(file); + Path link = dir.resolve("link"); + Files.createSymbolicLink(link, file); try { - link.newByteChannel(READ, WRITE, DELETE_ON_CLOSE); + Files.newByteChannel(link, READ, WRITE, DELETE_ON_CLOSE); throw new RuntimeException("IOException expected"); } catch (IOException ignore) { } } // check that DELETE_ON_CLOSE works with files created via open // directories - DirectoryStream stream = dir.newDirectoryStream(); - try { + try (DirectoryStream stream = Files.newDirectoryStream(dir)) { if (stream instanceof SecureDirectoryStream) { - SecureDirectoryStream secure = (SecureDirectoryStream)stream; + SecureDirectoryStream secure = (SecureDirectoryStream)stream; file = Paths.get("foo"); - Set opts = new HashSet(); + Set opts = new HashSet<>(); opts.add(WRITE); opts.add(DELETE_ON_CLOSE); secure.newByteChannel(file, opts).close(); - if (dir.resolve(file).exists()) + if (Files.exists(dir.resolve(file))) throw new RuntimeException("File not deleted"); } - } finally { - stream.close(); } } finally { TestUtil.removeAll(dir); diff --git a/jdk/test/java/nio/file/Path/FileAttributes.java b/jdk/test/java/nio/file/Files/FileAttributes.java similarity index 51% rename from jdk/test/java/nio/file/Path/FileAttributes.java rename to jdk/test/java/nio/file/Files/FileAttributes.java index 5300beb77f5..bd799dc6b1e 100644 --- a/jdk/test/java/nio/file/Path/FileAttributes.java +++ b/jdk/test/java/nio/file/Files/FileAttributes.java @@ -23,7 +23,7 @@ /* @test * @bug 4313887 6838333 - * @summary Unit test for java.nio.file.Path + * @summary Unit test for java.nio.file.Files * @library .. */ @@ -59,43 +59,43 @@ public class FileAttributes { } // Exercise getAttribute/setAttribute/readAttributes on basic attributes - static void checkBasicAttributes(FileRef file, BasicFileAttributes attrs) + static void checkBasicAttributes(Path file, BasicFileAttributes attrs) throws IOException { // getAttribute - checkEqual(attrs.size(), file.getAttribute("size")); - checkEqual(attrs.lastModifiedTime(), file.getAttribute("basic:lastModifiedTime")); - checkEqual(attrs.lastAccessTime(), file.getAttribute("lastAccessTime")); - checkEqual(attrs.creationTime(), file.getAttribute("basic:creationTime")); - assertTrue((Boolean)file.getAttribute("isRegularFile")); - assertTrue(!(Boolean)file.getAttribute("basic:isDirectory")); - assertTrue(!(Boolean)file.getAttribute("isSymbolicLink")); - assertTrue(!(Boolean)file.getAttribute("basic:isOther")); - checkEqual(attrs.fileKey(), file.getAttribute("basic:fileKey")); + checkEqual(attrs.size(), Files.getAttribute(file, "size")); + checkEqual(attrs.lastModifiedTime(), Files.getAttribute(file, "basic:lastModifiedTime")); + checkEqual(attrs.lastAccessTime(), Files.getAttribute(file, "lastAccessTime")); + checkEqual(attrs.creationTime(), Files.getAttribute(file, "basic:creationTime")); + assertTrue((Boolean)Files.getAttribute(file, "isRegularFile")); + assertTrue(!(Boolean)Files.getAttribute(file, "basic:isDirectory")); + assertTrue(!(Boolean)Files.getAttribute(file, "isSymbolicLink")); + assertTrue(!(Boolean)Files.getAttribute(file, "basic:isOther")); + checkEqual(attrs.fileKey(), Files.getAttribute(file, "basic:fileKey")); // setAttribute FileTime modTime = attrs.lastModifiedTime(); - file.setAttribute("basic:lastModifiedTime", FileTime.fromMillis(0L)); - checkEqual(Attributes.readBasicFileAttributes(file).lastModifiedTime(), + Files.setAttribute(file, "basic:lastModifiedTime", FileTime.fromMillis(0L)); + checkEqual(Files.getLastModifiedTime(file), FileTime.fromMillis(0L)); - file.setAttribute("lastModifiedTime", modTime); - checkEqual(Attributes.readBasicFileAttributes(file).lastModifiedTime(), modTime); + Files.setAttribute(file, "lastModifiedTime", modTime); + checkEqual(Files.getLastModifiedTime(file), modTime); - Map map; - map = file.readAttributes("*"); + Map map; + map = Files.readAttributes(file, "*"); assertTrue(map.size() >= 9); checkEqual(attrs.isRegularFile(), map.get("isRegularFile")); // check one - map = file.readAttributes("basic:*"); + map = Files.readAttributes(file, "basic:*"); assertTrue(map.size() >= 9); checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime")); // check one - map = file.readAttributes("size,lastModifiedTime"); + map = Files.readAttributes(file, "size,lastModifiedTime"); assertTrue(map.size() == 2); checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime")); - map = file.readAttributes( + map = Files.readAttributes(file, "basic:lastModifiedTime,lastAccessTime,ShouldNotExist"); assertTrue(map.size() == 2); checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime")); @@ -103,110 +103,110 @@ public class FileAttributes { } // Exercise getAttribute/setAttribute/readAttributes on posix attributes - static void checkPosixAttributes(FileRef file, PosixFileAttributes attrs) + static void checkPosixAttributes(Path file, PosixFileAttributes attrs) throws IOException { checkBasicAttributes(file, attrs); // getAttribute - checkEqual(attrs.permissions(), file.getAttribute("posix:permissions")); - checkEqual(attrs.owner(), file.getAttribute("posix:owner")); - checkEqual(attrs.group(), file.getAttribute("posix:group")); + checkEqual(attrs.permissions(), Files.getAttribute(file, "posix:permissions")); + checkEqual(attrs.owner(), Files.getAttribute(file, "posix:owner")); + checkEqual(attrs.group(), Files.getAttribute(file, "posix:group")); // setAttribute Set orig = attrs.permissions(); - Set newPerms = new HashSet(orig); + Set newPerms = new HashSet<>(orig); newPerms.remove(PosixFilePermission.OTHERS_READ); newPerms.remove(PosixFilePermission.OTHERS_WRITE); newPerms.remove(PosixFilePermission.OTHERS_EXECUTE); - file.setAttribute("posix:permissions", newPerms); - checkEqual(Attributes.readPosixFileAttributes(file).permissions(), newPerms); - file.setAttribute("posix:permissions", orig); - checkEqual(Attributes.readPosixFileAttributes(file).permissions(), orig); - file.setAttribute("posix:owner", attrs.owner()); - file.setAttribute("posix:group", attrs.group()); + Files.setAttribute(file, "posix:permissions", newPerms); + checkEqual(Files.getPosixFilePermissions(file), newPerms); + Files.setAttribute(file, "posix:permissions", orig); + checkEqual(Files.getPosixFilePermissions(file), orig); + Files.setAttribute(file, "posix:owner", attrs.owner()); + Files.setAttribute(file, "posix:group", attrs.group()); // readAttributes - Map map; - map = file.readAttributes("posix:*"); + Map map; + map = Files.readAttributes(file, "posix:*"); assertTrue(map.size() >= 12); checkEqual(attrs.permissions(), map.get("permissions")); // check one - map = file.readAttributes("posix:size,owner,ShouldNotExist"); + map = Files.readAttributes(file, "posix:size,owner,ShouldNotExist"); assertTrue(map.size() == 2); checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.owner(), map.get("owner")); } // Exercise getAttribute/readAttributes on unix attributes - static void checkUnixAttributes(FileRef file) throws IOException { + static void checkUnixAttributes(Path file) throws IOException { // getAttribute - int mode = (Integer)file.getAttribute("unix:mode"); - long ino = (Long)file.getAttribute("unix:ino"); - long dev = (Long)file.getAttribute("unix:dev"); - long rdev = (Long)file.getAttribute("unix:rdev"); - int nlink = (Integer)file.getAttribute("unix:nlink"); - int uid = (Integer)file.getAttribute("unix:uid"); - int gid = (Integer)file.getAttribute("unix:gid"); - FileTime ctime = (FileTime)file.getAttribute("unix:ctime"); + int mode = (Integer)Files.getAttribute(file, "unix:mode"); + long ino = (Long)Files.getAttribute(file, "unix:ino"); + long dev = (Long)Files.getAttribute(file, "unix:dev"); + long rdev = (Long)Files.getAttribute(file, "unix:rdev"); + int nlink = (Integer)Files.getAttribute(file, "unix:nlink"); + int uid = (Integer)Files.getAttribute(file, "unix:uid"); + int gid = (Integer)Files.getAttribute(file, "unix:gid"); + FileTime ctime = (FileTime)Files.getAttribute(file, "unix:ctime"); // readAttributes - Map map; - map = file.readAttributes("unix:*"); + Map map; + map = Files.readAttributes(file, "unix:*"); assertTrue(map.size() >= 20); - map = file.readAttributes("unix:size,uid,gid,ShouldNotExist"); + map = Files.readAttributes(file, "unix:size,uid,gid,ShouldNotExist"); assertTrue(map.size() == 3); checkEqual(map.get("size"), - Attributes.readBasicFileAttributes(file).size()); + Files.readAttributes(file, BasicFileAttributes.class).size()); } // Exercise getAttribute/setAttribute on dos attributes - static void checkDosAttributes(FileRef file, DosFileAttributes attrs) + static void checkDosAttributes(Path file, DosFileAttributes attrs) throws IOException { checkBasicAttributes(file, attrs); // getAttribute - checkEqual(attrs.isReadOnly(), file.getAttribute("dos:readonly")); - checkEqual(attrs.isHidden(), file.getAttribute("dos:hidden")); - checkEqual(attrs.isSystem(), file.getAttribute("dos:system")); - checkEqual(attrs.isArchive(), file.getAttribute("dos:archive")); + checkEqual(attrs.isReadOnly(), Files.getAttribute(file, "dos:readonly")); + checkEqual(attrs.isHidden(), Files.getAttribute(file, "dos:hidden")); + checkEqual(attrs.isSystem(), Files.getAttribute(file, "dos:system")); + checkEqual(attrs.isArchive(), Files.getAttribute(file, "dos:archive")); // setAttribute boolean value; value = attrs.isReadOnly(); - file.setAttribute("dos:readonly", !value); - checkEqual(Attributes.readDosFileAttributes(file).isReadOnly(), !value); - file.setAttribute("dos:readonly", value); - checkEqual(Attributes.readDosFileAttributes(file).isReadOnly(), value); + Files.setAttribute(file, "dos:readonly", !value); + checkEqual(Files.readAttributes(file, DosFileAttributes.class).isReadOnly(), !value); + Files.setAttribute(file, "dos:readonly", value); + checkEqual(Files.readAttributes(file, DosFileAttributes.class).isReadOnly(), value); value = attrs.isHidden(); - file.setAttribute("dos:hidden", !value); - checkEqual(Attributes.readDosFileAttributes(file).isHidden(), !value); - file.setAttribute("dos:hidden", value); - checkEqual(Attributes.readDosFileAttributes(file).isHidden(), value); + Files.setAttribute(file, "dos:hidden", !value); + checkEqual(Files.readAttributes(file, DosFileAttributes.class).isHidden(), !value); + Files.setAttribute(file, "dos:hidden", value); + checkEqual(Files.readAttributes(file, DosFileAttributes.class).isHidden(), value); value = attrs.isSystem(); - file.setAttribute("dos:system", !value); - checkEqual(Attributes.readDosFileAttributes(file).isSystem(), !value); - file.setAttribute("dos:system", value); - checkEqual(Attributes.readDosFileAttributes(file).isSystem(), value); + Files.setAttribute(file, "dos:system", !value); + checkEqual(Files.readAttributes(file, DosFileAttributes.class).isSystem(), !value); + Files.setAttribute(file, "dos:system", value); + checkEqual(Files.readAttributes(file, DosFileAttributes.class).isSystem(), value); value = attrs.isArchive(); - file.setAttribute("dos:archive", !value); - checkEqual(Attributes.readDosFileAttributes(file).isArchive(), !value); - file.setAttribute("dos:archive", value); - checkEqual(Attributes.readDosFileAttributes(file).isArchive(), value); + Files.setAttribute(file, "dos:archive", !value); + checkEqual(Files.readAttributes(file, DosFileAttributes.class).isArchive(), !value); + Files.setAttribute(file, "dos:archive", value); + checkEqual(Files.readAttributes(file, DosFileAttributes.class).isArchive(), value); // readAttributes - Map map; - map = file.readAttributes("dos:*"); + Map map; + map = Files.readAttributes(file, "dos:*"); assertTrue(map.size() >= 13); checkEqual(attrs.isReadOnly(), map.get("readonly")); // check one - map = file.readAttributes("dos:size,hidden,ShouldNotExist"); + map = Files.readAttributes(file, "dos:size,hidden,ShouldNotExist"); assertTrue(map.size() == 2); checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.isHidden(), map.get("hidden")); @@ -215,40 +215,41 @@ public class FileAttributes { static void miscTests(Path file) throws IOException { // NPE tests try { - file.getAttribute(null); + Files.getAttribute(file, null); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException npe) { } try { - file.getAttribute("isRegularFile", (LinkOption[])null); + Files.getAttribute(file, "isRegularFile", (LinkOption[])null); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException npe) { } try { - file.setAttribute(null, 0L); + Files.setAttribute(file, null, 0L); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException npe) { } } static void doTests(Path dir) throws IOException { - Path file = dir.resolve("foo").createFile(); - FileStore store = file.getFileStore(); + Path file = dir.resolve("foo"); + Files.createFile(file); + FileStore store = Files.getFileStore(file); try { checkBasicAttributes(file, - Attributes.readBasicFileAttributes(file)); + Files.readAttributes(file, BasicFileAttributes.class)); if (store.supportsFileAttributeView("posix")) checkPosixAttributes(file, - Attributes.readPosixFileAttributes(file)); + Files.readAttributes(file, PosixFileAttributes.class)); if (store.supportsFileAttributeView("unix")) checkUnixAttributes(file); if (store.supportsFileAttributeView("dos")) checkDosAttributes(file, - Attributes.readDosFileAttributes(file)); + Files.readAttributes(file, DosFileAttributes.class)); miscTests(file); } finally { - file.delete(); + Files.delete(file); } } diff --git a/jdk/test/java/nio/file/Path/InterruptCopy.java b/jdk/test/java/nio/file/Files/InterruptCopy.java similarity index 90% rename from jdk/test/java/nio/file/Path/InterruptCopy.java rename to jdk/test/java/nio/file/Files/InterruptCopy.java index 11be5a2e198..1502d9e824e 100644 --- a/jdk/test/java/nio/file/Path/InterruptCopy.java +++ b/jdk/test/java/nio/file/Files/InterruptCopy.java @@ -29,7 +29,6 @@ */ import java.nio.file.*; -import java.nio.file.attribute.Attributes; import java.io.*; import java.util.concurrent.*; import com.sun.nio.file.ExtendedCopyOption; @@ -43,10 +42,9 @@ public class InterruptCopy { public static void main(String[] args) throws Exception { Path dir = TestUtil.createTemporaryDirectory(); try { - FileStore store = dir.getFileStore(); + FileStore store = Files.getFileStore(dir); System.out.format("Checking space (%s)\n", store); - long usableSpace = Attributes - .readFileStoreSpaceAttributes(store).usableSpace(); + long usableSpace = store.getUsableSpace(); if (usableSpace < 2*FILE_SIZE_TO_COPY) { System.out.println("Insufficient disk space to run test."); return; @@ -66,14 +64,11 @@ public class InterruptCopy { System.out.println("Creating source file..."); byte[] buf = new byte[32*1024]; long total = 0; - OutputStream out = source.newOutputStream(); - try { + try (OutputStream out = Files.newOutputStream(source)) { do { out.write(buf); total += buf.length; } while (total < FILE_SIZE_TO_COPY); - } finally { - out.close(); } System.out.println("Source file created."); @@ -89,7 +84,7 @@ public class InterruptCopy { System.out.println("Copying file..."); try { long start = System.currentTimeMillis(); - source.copyTo(target, ExtendedCopyOption.INTERRUPTIBLE); + Files.copy(source, target, ExtendedCopyOption.INTERRUPTIBLE); long duration = System.currentTimeMillis() - start; if (duration > DURATION_MAX_IN_MS) throw new RuntimeException("Copy was not interrupted"); @@ -109,7 +104,7 @@ public class InterruptCopy { Future result = pool.submit(new Callable() { public Void call() throws IOException { System.out.println("Copying file..."); - source.copyTo(target, ExtendedCopyOption.INTERRUPTIBLE, + Files.copy(source, target, ExtendedCopyOption.INTERRUPTIBLE, StandardCopyOption.REPLACE_EXISTING); return null; } diff --git a/jdk/test/java/nio/file/Path/Links.java b/jdk/test/java/nio/file/Files/Links.java similarity index 72% rename from jdk/test/java/nio/file/Path/Links.java rename to jdk/test/java/nio/file/Files/Links.java index ced18e1cd28..0c19a0c92b5 100644 --- a/jdk/test/java/nio/file/Path/Links.java +++ b/jdk/test/java/nio/file/Files/Links.java @@ -23,7 +23,7 @@ /* @test * @bug 4313887 6838333 6863864 - * @summary Unit test for java.nio.file.Path createSymbolicLink, + * @summary Unit test for java.nio.file.Files createSymbolicLink, * readSymbolicLink, and createLink methods * @library .. * @build Links @@ -52,8 +52,8 @@ public class Links { // Check if sym links are supported try { - link.createSymbolicLink(Paths.get("foo")); - link.delete(); + Files.createSymbolicLink(link, Paths.get("foo")); + Files.delete(link); } catch (UnsupportedOperationException x) { // sym links not supported return; @@ -70,11 +70,11 @@ public class Links { String[] targets = (isWindows) ? windowsTargets : otherTargets; for (String s: targets) { Path target = Paths.get(s); - link.createSymbolicLink(target); + Files.createSymbolicLink(link, target); try { - assertTrue(link.readSymbolicLink().equals(target)); + assertTrue(Files.readSymbolicLink(link).equals(target)); } finally { - link.delete(); + Files.delete(link); } } @@ -82,57 +82,54 @@ public class Links { Path mydir = dir.resolve("mydir"); Path myfile = mydir.resolve("myfile"); try { - mydir.createDirectory(); - myfile.createFile(); + Files.createDirectory(mydir); + Files.createFile(myfile); // link -> "mydir" - link.createSymbolicLink(mydir.getName()); - assertTrue(link.readSymbolicLink().equals(mydir.getName())); + Files.createSymbolicLink(link, mydir.getFileName()); + assertTrue(Files.readSymbolicLink(link).equals(mydir.getFileName())); // Test access to directory via link - DirectoryStream stream = link.newDirectoryStream(); - try { + try (DirectoryStream stream = Files.newDirectoryStream(link)) { boolean found = false; for (Path entry: stream) { - if (entry.getName().equals(myfile.getName())) { + if (entry.getFileName().equals(myfile.getFileName())) { found = true; break; } } assertTrue(found); - } finally { - stream.close(); } // Test link2 -> link -> mydir final Path link2 = dir.resolve("link2"); - Path target2 = link.getName(); - link2.createSymbolicLink(target2); + Path target2 = link.getFileName(); + Files.createSymbolicLink(link2, target2); try { - assertTrue(link2.readSymbolicLink().equals(target2)); - link2.newDirectoryStream().close(); + assertTrue(Files.readSymbolicLink(link2).equals(target2)); + Files.newDirectoryStream(link2).close(); } finally { - link2.delete(); + Files.delete(link2); } // Remove mydir and re-create link2 before re-creating mydir // (This is a useful test on Windows to ensure that creating a // sym link to a directory sym link creates the right type of link). - myfile.delete(); - mydir.delete(); - link2.createSymbolicLink(target2); + Files.delete(myfile); + Files.delete(mydir); + Files.createSymbolicLink(link2, target2); try { - assertTrue(link2.readSymbolicLink().equals(target2)); - mydir.createDirectory(); - link2.newDirectoryStream().close(); + assertTrue(Files.readSymbolicLink(link2).equals(target2)); + Files.createDirectory(mydir); + Files.newDirectoryStream(link2).close(); } finally { - link2.delete(); + Files.delete(link2); } } finally { - myfile.deleteIfExists(); - mydir.deleteIfExists(); - link.deleteIfExists(); + Files.deleteIfExists(myfile); + Files.deleteIfExists(mydir); + Files.deleteIfExists(link); } } @@ -140,11 +137,12 @@ public class Links { * Exercise createLink method */ static void testHardLinks(Path dir) throws IOException { - Path foo = dir.resolve("foo").createFile(); + Path foo = dir.resolve("foo"); + Files.createFile(foo); try { - Path bar; + Path bar = dir.resolve("bar"); try { - bar = dir.resolve("bar").createLink(foo); + Files.createLink(bar, foo); } catch (UnsupportedOperationException x) { return; } catch (IOException x) { @@ -152,18 +150,16 @@ public class Links { return; } try { - Object key1 = Attributes - .readBasicFileAttributes(foo).fileKey(); - Object key2 = Attributes - .readBasicFileAttributes(bar).fileKey(); + Object key1 = Files.readAttributes(foo, BasicFileAttributes.class).fileKey(); + Object key2 = Files.readAttributes(bar, BasicFileAttributes.class).fileKey(); assertTrue((key1 == null) || (key1.equals(key2))); } finally { - bar.delete(); + Files.delete(bar); } } finally { - foo.delete(); + Files.delete(foo); } } diff --git a/jdk/test/java/nio/file/Files/Misc.java b/jdk/test/java/nio/file/Files/Misc.java index 621b95981ff..1ff9d0af190 100644 --- a/jdk/test/java/nio/file/Files/Misc.java +++ b/jdk/test/java/nio/file/Files/Misc.java @@ -22,122 +22,335 @@ */ /* @test - * @bug 4313887 6838333 6865748 - * @summary Unit test for java.nio.file.Files for miscellenous cases not - * covered by other tests + * @bug 4313887 6838333 + * @summary Unit test for miscellenous methods in java.nio.file.Files * @library .. */ import java.nio.file.*; -import java.nio.file.attribute.Attributes; -import java.nio.file.attribute.BasicFileAttributes; +import static java.nio.file.Files.*; +import static java.nio.file.LinkOption.*; +import java.nio.file.attribute.*; import java.io.IOException; import java.util.*; public class Misc { - static void npeExpected() { - throw new RuntimeException("NullPointerException expected"); - } - public static void main(String[] args) throws IOException { - - // -- Files.createDirectories -- - Path dir = TestUtil.createTemporaryDirectory(); try { - // no-op - Files.createDirectories(dir); + testCreateDirectories(dir); + testIsHidden(dir); + testIsSameFile(dir); + testFileTypeMethods(dir); + testAccessMethods(dir); + } finally { + TestUtil.removeAll(dir); + } + } - // create one directory - Path subdir = dir.resolve("a"); - Files.createDirectories(subdir); - if (!subdir.exists()) - throw new RuntimeException("directory not created"); + /** + * Tests createDirectories + */ + static void testCreateDirectories(Path tmpdir) throws IOException { + // a no-op + createDirectories(tmpdir); - // create parents - subdir = subdir.resolve("b/c/d"); - Files.createDirectories(subdir); - if (!subdir.exists()) - throw new RuntimeException("directory not created"); + // create one directory + Path subdir = tmpdir.resolve("a"); + createDirectories(subdir); + assertTrue(exists(subdir)); - // existing file is not a directory - Path file = dir.resolve("x").createFile(); + // create parents + subdir = subdir.resolve("b/c/d"); + createDirectories(subdir); + assertTrue(exists(subdir)); + + // existing file is not a directory + Path file = createFile(tmpdir.resolve("x")); + try { + createDirectories(file); + throw new RuntimeException("failure expected"); + } catch (FileAlreadyExistsException x) { } + try { + createDirectories(file.resolve("y")); + throw new RuntimeException("failure expected"); + } catch (IOException x) { } + } + + /** + * Tests isHidden + */ + static void testIsHidden(Path tmpdir) throws IOException { + assertTrue(!isHidden(tmpdir)); + + Path file = tmpdir.resolve(".foo"); + if (System.getProperty("os.name").startsWith("Windows")) { + createFile(file); try { - Files.createDirectories(file); - throw new RuntimeException("failure expected"); - } catch (FileAlreadyExistsException x) { } + setAttribute(file, "dos:hidden", true); + try { + assertTrue(isHidden(file)); + } finally { + setAttribute(file, "dos:hidden", false); + } + } finally { + delete(file); + } + } else { + assertTrue(isHidden(file)); + } + } + + /** + * Tests isSameFile + */ + static void testIsSameFile(Path tmpdir) throws IOException { + Path thisFile = tmpdir.resolve("thisFile"); + Path thatFile = tmpdir.resolve("thatFile"); + + /** + * Test: isSameFile for self + */ + assertTrue(isSameFile(thisFile, thisFile)); + + /** + * Test: Neither files exist + */ + try { + isSameFile(thisFile, thatFile); + throw new RuntimeException("IOException not thrown"); + } catch (IOException x) { + } + try { + isSameFile(thatFile, thisFile); + throw new RuntimeException("IOException not thrown"); + } catch (IOException x) { + } + + createFile(thisFile); + try { + /** + * Test: One file exists + */ try { - Files.createDirectories(file.resolve("y")); - throw new RuntimeException("failure expected"); - } catch (IOException x) { } + isSameFile(thisFile, thatFile); + throw new RuntimeException("IOException not thrown"); + } catch (IOException x) { + } + try { + isSameFile(thatFile, thisFile); + throw new RuntimeException("IOException not thrown"); + } catch (IOException x) { + } + + /** + * Test: Both file exists + */ + createFile(thatFile); + try { + assertTrue(!isSameFile(thisFile, thatFile)); + assertTrue(!isSameFile(thatFile, thisFile)); + } finally { + delete(thatFile); + } + + /** + * Test: Symbolic links + */ + if (TestUtil.supportsLinks(tmpdir)) { + createSymbolicLink(thatFile, thisFile); + try { + assertTrue(isSameFile(thisFile, thatFile)); + assertTrue(isSameFile(thatFile, thisFile)); + } finally { + TestUtil.deleteUnchecked(thatFile); + } + } + } finally { + delete(thisFile); + } + + // nulls + try { + isSameFile(thisFile, null); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + try { + isSameFile(null, thatFile); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException ignore) { } + } + + /** + * Exercise isRegularFile, isDirectory, isSymbolicLink + */ + static void testFileTypeMethods(Path tmpdir) throws IOException { + assertTrue(!isRegularFile(tmpdir)); + assertTrue(!isRegularFile(tmpdir, NOFOLLOW_LINKS)); + assertTrue(isDirectory(tmpdir)); + assertTrue(isDirectory(tmpdir, NOFOLLOW_LINKS)); + assertTrue(!isSymbolicLink(tmpdir)); + + Path file = createFile(tmpdir.resolve("foo")); + try { + assertTrue(isRegularFile(file)); + assertTrue(isRegularFile(file, NOFOLLOW_LINKS)); + assertTrue(!isDirectory(file)); + assertTrue(!isDirectory(file, NOFOLLOW_LINKS)); + assertTrue(!isSymbolicLink(file)); + + if (TestUtil.supportsLinks(tmpdir)) { + Path link = tmpdir.resolve("link"); + + createSymbolicLink(link, tmpdir); + try { + assertTrue(!isRegularFile(link)); + assertTrue(!isRegularFile(link, NOFOLLOW_LINKS)); + assertTrue(isDirectory(link)); + assertTrue(!isDirectory(link, NOFOLLOW_LINKS)); + assertTrue(isSymbolicLink(link)); + } finally { + delete(link); + } + + createSymbolicLink(link, file); + try { + assertTrue(isRegularFile(link)); + assertTrue(!isRegularFile(link, NOFOLLOW_LINKS)); + assertTrue(!isDirectory(link)); + assertTrue(!isDirectory(link, NOFOLLOW_LINKS)); + assertTrue(isSymbolicLink(link)); + } finally { + delete(link); + } + + createLink(link, file); + try { + assertTrue(isRegularFile(link)); + assertTrue(isRegularFile(link, NOFOLLOW_LINKS)); + assertTrue(!isDirectory(link)); + assertTrue(!isDirectory(link, NOFOLLOW_LINKS)); + assertTrue(!isSymbolicLink(link)); + } finally { + delete(link); + } + } } finally { - TestUtil.removeAll(dir); + delete(file); } + } - // --- NullPointerException -- + /** + * Exercise isReadbale, isWritable, isExecutable, exists, notExists + */ + static void testAccessMethods(Path tmpdir) throws IOException { + // should return false when file does not exist + Path doesNotExist = tmpdir.resolve("doesNotExist"); + assertTrue(!isReadable(doesNotExist)); + assertTrue(!isWritable(doesNotExist)); + assertTrue(!isExecutable(doesNotExist)); + assertTrue(!exists(doesNotExist)); + assertTrue(notExists(doesNotExist)); + Path file = createFile(tmpdir.resolve("foo")); try { - Files.probeContentType(null); - npeExpected(); - } catch (NullPointerException e) { - } - try { - Files.walkFileTree(null, EnumSet.noneOf(FileVisitOption.class), - Integer.MAX_VALUE, new SimpleFileVisitor(){}); - npeExpected(); - } catch (NullPointerException e) { - } - try { - Files.walkFileTree(Paths.get("."), null, Integer.MAX_VALUE, - new SimpleFileVisitor(){}); - npeExpected(); - } catch (NullPointerException e) { - } - try { - Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class), - -1, new SimpleFileVisitor(){}); - throw new RuntimeException("IllegalArgumentExpected expected"); - } catch (IllegalArgumentException e) { - } - try { - Set opts = new HashSet(1); - opts.add(null); - Files.walkFileTree(Paths.get("."), opts, Integer.MAX_VALUE, - new SimpleFileVisitor(){}); - npeExpected(); - } catch (NullPointerException e) { - } - try { - Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class), - Integer.MAX_VALUE, null); - npeExpected(); - } catch (NullPointerException e) { - } + // files exist + assertTrue(isReadable(file)); + assertTrue(isWritable(file)); + assertTrue(exists(file)); + assertTrue(!notExists(file)); + assertTrue(isReadable(tmpdir)); + assertTrue(isWritable(tmpdir)); + assertTrue(exists(tmpdir)); + assertTrue(!notExists(tmpdir)); - SimpleFileVisitor visitor = new SimpleFileVisitor() { }; - boolean ranTheGauntlet = false; - BasicFileAttributes attrs = Attributes.readBasicFileAttributes(Paths.get(".")); - try { visitor.preVisitDirectory(null, attrs); - } catch (NullPointerException x0) { - try { visitor.preVisitDirectory(dir, null); - } catch (NullPointerException x1) { - try { visitor.visitFile(null, attrs); - } catch (NullPointerException x2) { - try { visitor.visitFile(dir, null); - } catch (NullPointerException x3) { - try { visitor.visitFileFailed(null, new IOException()); - } catch (NullPointerException x4) { - try { visitor.visitFileFailed(dir, null); - } catch (NullPointerException x5) { - try { visitor.postVisitDirectory(null, new IOException()); - } catch (NullPointerException x6) { - // if we get here then all visit* methods threw NPE as expected - ranTheGauntlet = true; - }}}}}}} - if (!ranTheGauntlet) - throw new RuntimeException("A visit method did not throw NPE"); + // sym link exists + if (TestUtil.supportsLinks(tmpdir)) { + Path link = tmpdir.resolve("link"); + + createSymbolicLink(link, file); + try { + assertTrue(isReadable(link)); + assertTrue(isWritable(link)); + assertTrue(exists(link)); + assertTrue(!notExists(link)); + } finally { + delete(link); + } + + createSymbolicLink(link, doesNotExist); + try { + assertTrue(!isReadable(link)); + assertTrue(!isWritable(link)); + assertTrue(!exists(link)); + assertTrue(exists(link, NOFOLLOW_LINKS)); + assertTrue(notExists(link)); + assertTrue(!notExists(link, NOFOLLOW_LINKS)); + } finally { + delete(link); + } + } + + /** + * Test: Edit ACL to deny WRITE and EXECUTE + */ + if (getFileStore(file).supportsFileAttributeView("acl")) { + AclFileAttributeView view = + getFileAttributeView(file, AclFileAttributeView.class); + UserPrincipal owner = view.getOwner(); + List acl = view.getAcl(); + + // Insert entry to deny WRITE and EXECUTE + AclEntry entry = AclEntry.newBuilder() + .setType(AclEntryType.DENY) + .setPrincipal(owner) + .setPermissions(AclEntryPermission.WRITE_DATA, + AclEntryPermission.EXECUTE) + .build(); + acl.add(0, entry); + view.setAcl(acl); + try { + assertTrue(!isWritable(file)); + assertTrue(!isExecutable(file)); + } finally { + // Restore ACL + acl.remove(0); + view.setAcl(acl); + } + } + + /** + * Test: Windows DOS read-only attribute + */ + if (System.getProperty("os.name").startsWith("Windows")) { + setAttribute(file, "dos:readonly", true); + try { + assertTrue(!isWritable(file)); + } finally { + setAttribute(file, "dos:readonly", false); + } + + // Read-only attribute does not make direcory read-only + DosFileAttributeView view = + getFileAttributeView(tmpdir, DosFileAttributeView.class); + boolean save = view.readAttributes().isReadOnly(); + view.setReadOnly(true); + try { + assertTrue(isWritable(file)); + } finally { + view.setReadOnly(save); + } + } + } finally { + delete(file); + } + } + + static void assertTrue(boolean okay) { + if (!okay) + throw new RuntimeException("Assertion Failed"); } } diff --git a/jdk/test/java/nio/file/Path/PassThroughFileSystem.java b/jdk/test/java/nio/file/Files/PassThroughFileSystem.java similarity index 74% rename from jdk/test/java/nio/file/Path/PassThroughFileSystem.java rename to jdk/test/java/nio/file/Files/PassThroughFileSystem.java index 4e77d12aba3..31345a8bf36 100644 --- a/jdk/test/java/nio/file/Path/PassThroughFileSystem.java +++ b/jdk/test/java/nio/file/Files/PassThroughFileSystem.java @@ -54,6 +54,14 @@ class PassThroughFileSystem extends FileSystem { return provider.newFileSystem(uri, env); } + static Path unwrap(Path wrapper) { + if (wrapper == null) + throw new NullPointerException(); + if (!(wrapper instanceof PassThroughPath)) + throw new ProviderMismatchException(); + return ((PassThroughPath)wrapper).delegate; + } + @Override public FileSystemProvider provider() { return provider; @@ -117,8 +125,8 @@ class PassThroughFileSystem extends FileSystem { } @Override - public Path getPath(String path) { - return new PassThroughPath(this, delegate.getPath(path)); + public Path getPath(String first, String... more) { + return new PassThroughPath(this, delegate.getPath(first, more)); } @Override @@ -127,7 +135,7 @@ class PassThroughFileSystem extends FileSystem { return new PathMatcher() { @Override public boolean matches(Path path) { - return matcher.matches(PassThroughPath.unwrap(path)); + return matcher.matches(unwrap(path)); } }; } @@ -199,9 +207,154 @@ class PassThroughFileSystem extends FileSystem { uri.getSchemeSpecificPart()); return new PassThroughPath(delegate, delegate.provider().getPath(uri)); } + + @Override + public void setAttribute(Path file, String attribute, Object value, LinkOption... options) + throws IOException + { + Files.setAttribute(unwrap(file), attribute, value, options); + } + + @Override + public Map readAttributes(Path file, String attributes, LinkOption... options) + throws IOException + { + return Files.readAttributes(unwrap(file), attributes, options); + } + + @Override + public V getFileAttributeView(Path file, + Class type, + LinkOption... options) + { + return Files.getFileAttributeView(unwrap(file), type, options); + } + + @Override + public A readAttributes(Path file, + Class type, + LinkOption... options) + throws IOException + { + return Files.readAttributes(unwrap(file), type, options); + } + + @Override + public void delete(Path file) throws IOException { + Files.delete(unwrap(file)); + } + + @Override + public void createSymbolicLink(Path link, Path target, FileAttribute... attrs) + throws IOException + { + Files.createSymbolicLink(unwrap(link), unwrap(target), attrs); + } + + @Override + public void createLink(Path link, Path existing) throws IOException { + Files.createLink(unwrap(link), unwrap(existing)); + } + + @Override + public Path readSymbolicLink(Path link) throws IOException { + Path target = Files.readSymbolicLink(unwrap(link)); + return new PassThroughPath(delegate, target); + } + + + @Override + public void copy(Path source, Path target, CopyOption... options) throws IOException { + Files.copy(unwrap(source), unwrap(target), options); + } + + @Override + public void move(Path source, Path target, CopyOption... options) throws IOException { + Files.move(unwrap(source), unwrap(target), options); + } + + private DirectoryStream wrap(final DirectoryStream stream) { + return new DirectoryStream() { + @Override + public Iterator iterator() { + final Iterator itr = stream.iterator(); + return new Iterator() { + @Override + public boolean hasNext() { + return itr.hasNext(); + } + @Override + public Path next() { + return new PassThroughPath(delegate, itr.next()); + } + @Override + public void remove() { + itr.remove(); + } + }; + } + @Override + public void close() throws IOException { + stream.close(); + } + }; + } + + @Override + public DirectoryStream newDirectoryStream(Path dir, DirectoryStream.Filter filter) + throws IOException + { + return wrap(Files.newDirectoryStream(dir, filter)); + } + + @Override + public void createDirectory(Path dir, FileAttribute... attrs) + throws IOException + { + Files.createDirectory(unwrap(dir), attrs); + } + + @Override + public SeekableByteChannel newByteChannel(Path file, + Set options, + FileAttribute... attrs) + throws IOException + { + return Files.newByteChannel(unwrap(file), options, attrs); + } + + + @Override + public boolean isHidden(Path file) throws IOException { + return Files.isHidden(unwrap(file)); + } + + @Override + public FileStore getFileStore(Path file) throws IOException { + return Files.getFileStore(unwrap(file)); + } + + @Override + public boolean isSameFile(Path file, Path other) throws IOException { + return Files.isSameFile(unwrap(file), unwrap(other)); + } + + @Override + public void checkAccess(Path file, AccessMode... modes) + throws IOException + { + // hack + if (modes.length == 0) { + if (Files.exists(unwrap(file))) + return; + else + throw new NoSuchFileException(file.toString()); + } + throw new RuntimeException("not implemented yet"); + } } - static class PassThroughPath extends Path { + static class PassThroughPath implements Path { private final FileSystem fs; private final Path delegate; @@ -214,12 +367,6 @@ class PassThroughFileSystem extends FileSystem { return (path != null) ? new PassThroughPath(fs, path) : null; } - static Path unwrap(Path wrapper) { - if (!(wrapper instanceof PassThroughPath)) - throw new ProviderMismatchException(); - return ((PassThroughPath)wrapper).delegate; - } - @Override public FileSystem getFileSystem() { return fs; @@ -235,12 +382,6 @@ class PassThroughFileSystem extends FileSystem { return wrap(delegate.getRoot()); } - - @Override - public Path getName() { - return wrap(delegate.getName()); - } - @Override public Path getParent() { return wrap(delegate.getParent()); @@ -251,6 +392,11 @@ class PassThroughFileSystem extends FileSystem { return delegate.getNameCount(); } + @Override + public Path getFileName() { + return wrap(delegate.getFileName()); + } + @Override public Path getName(int index) { return wrap(delegate.getName(index)); @@ -266,11 +412,21 @@ class PassThroughFileSystem extends FileSystem { return delegate.startsWith(unwrap(other)); } + @Override + public boolean startsWith(String other) { + return delegate.startsWith(other); + } + @Override public boolean endsWith(Path other) { return delegate.endsWith(unwrap(other)); } + @Override + public boolean endsWith(String other) { + return delegate.endsWith(other); + } + @Override public Path normalize() { return wrap(delegate.normalize()); @@ -286,68 +442,36 @@ class PassThroughFileSystem extends FileSystem { return wrap(delegate.resolve(other)); } + @Override + public Path resolveSibling(Path other) { + return wrap(delegate.resolveSibling(unwrap(other))); + } + + @Override + public Path resolveSibling(String other) { + return wrap(delegate.resolveSibling(other)); + } + @Override public Path relativize(Path other) { return wrap(delegate.relativize(unwrap(other))); } @Override - public void setAttribute(String attribute, Object value, LinkOption... options) - throws IOException - { - delegate.setAttribute(attribute, value, options); + public boolean equals(Object other) { + if (!(other instanceof PassThroughPath)) + return false; + return delegate.equals(unwrap((PassThroughPath)other)); } @Override - public Object getAttribute(String attribute, LinkOption... options) - throws IOException - { - // assume that unwrapped objects aren't exposed - return delegate.getAttribute(attribute, options); + public int hashCode() { + return delegate.hashCode(); } @Override - public Map readAttributes(String attributes, LinkOption... options) - throws IOException - { - // assume that unwrapped objects aren't exposed - return delegate.readAttributes(attributes, options); - } - - @Override - public V getFileAttributeView(Class type, - LinkOption... options) - { - return delegate.getFileAttributeView(type, options); - } - - @Override - public void delete() throws IOException { - delegate.delete(); - } - - @Override - public void deleteIfExists() throws IOException { - delegate.deleteIfExists(); - } - - @Override - public Path createSymbolicLink(Path target, FileAttribute... attrs) - throws IOException - { - delegate.createSymbolicLink(unwrap(target), attrs); - return this; - } - - @Override - public Path createLink(Path existing) throws IOException { - delegate.createLink(unwrap(existing)); - return this; - } - - @Override - public Path readSymbolicLink() throws IOException { - return wrap(delegate.readSymbolicLink()); + public String toString() { + return delegate.toString(); } @Override @@ -367,143 +491,10 @@ class PassThroughFileSystem extends FileSystem { } @Override - public Path copyTo(Path target, CopyOption... options) throws IOException { - return wrap(delegate.copyTo(unwrap(target), options)); + public File toFile() { + return delegate.toFile(); } - @Override - public Path moveTo(Path target, CopyOption... options) throws IOException { - return wrap(delegate.copyTo(unwrap(target), options)); - } - - private DirectoryStream wrap(final DirectoryStream stream) { - return new DirectoryStream() { - @Override - public Iterator iterator() { - final Iterator itr = stream.iterator(); - return new Iterator() { - @Override - public boolean hasNext() { - return itr.hasNext(); - } - @Override - public Path next() { - return wrap(itr.next()); - } - @Override - public void remove() { - itr.remove(); - } - }; - } - @Override - public void close() throws IOException { - stream.close(); - } - }; - } - - @Override - public DirectoryStream newDirectoryStream() throws IOException { - return wrap(delegate.newDirectoryStream()); - } - - @Override - public DirectoryStream newDirectoryStream(String glob) - throws IOException - { - return wrap(delegate.newDirectoryStream(glob)); - } - - @Override - public DirectoryStream newDirectoryStream(DirectoryStream.Filter filter) - throws IOException - { - return wrap(delegate.newDirectoryStream(filter)); - } - - @Override - public Path createFile(FileAttribute... attrs) throws IOException { - delegate.createFile(attrs); - return this; - } - - @Override - public Path createDirectory(FileAttribute... attrs) - throws IOException - { - delegate.createDirectory(attrs); - return this; - } - - @Override - public SeekableByteChannel newByteChannel(Set options, - FileAttribute... attrs) - throws IOException - { - return delegate.newByteChannel(options, attrs); - } - - @Override - public SeekableByteChannel newByteChannel(OpenOption... options) - throws IOException - { - return delegate.newByteChannel(options); - } - - @Override - public InputStream newInputStream(OpenOption... options) throws IOException { - return delegate.newInputStream(); - } - - @Override - public OutputStream newOutputStream(OpenOption... options) - throws IOException - { - return delegate.newOutputStream(options); - } - - @Override - public boolean isHidden() throws IOException { - return delegate.isHidden(); - } - - @Override - public void checkAccess(AccessMode... modes) throws IOException { - delegate.checkAccess(modes); - } - - @Override - public boolean exists() { - return delegate.exists(); - } - - @Override - public boolean notExists() { - return delegate.notExists(); - } - - @Override - public FileStore getFileStore() throws IOException { - return delegate.getFileStore(); - } - - @Override - public WatchKey register(WatchService watcher, - WatchEvent.Kind[] events, - WatchEvent.Modifier... modifiers) - { - throw new UnsupportedOperationException(); - } - - @Override - public WatchKey register(WatchService watcher, - WatchEvent.Kind... events) - { - throw new UnsupportedOperationException(); - } - - @Override public Iterator iterator() { final Iterator itr = delegate.iterator(); @@ -529,26 +520,18 @@ class PassThroughFileSystem extends FileSystem { } @Override - public boolean isSameFile(Path other) throws IOException { - return delegate.isSameFile(unwrap(other)); - } - - - @Override - public boolean equals(Object other) { - if (!(other instanceof PassThroughPath)) - return false; - return delegate.equals(unwrap((PassThroughPath)other)); + public WatchKey register(WatchService watcher, + WatchEvent.Kind[] events, + WatchEvent.Modifier... modifiers) + { + throw new UnsupportedOperationException(); } @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public String toString() { - return delegate.toString(); + public WatchKey register(WatchService watcher, + WatchEvent.Kind... events) + { + throw new UnsupportedOperationException(); } } } diff --git a/jdk/test/java/nio/file/Path/SBC.java b/jdk/test/java/nio/file/Files/SBC.java similarity index 74% rename from jdk/test/java/nio/file/Path/SBC.java rename to jdk/test/java/nio/file/Files/SBC.java index 8a5501b3549..6dcf1a92fc0 100644 --- a/jdk/test/java/nio/file/Path/SBC.java +++ b/jdk/test/java/nio/file/Files/SBC.java @@ -23,7 +23,7 @@ /* @test * @bug 4313887 - * @summary Unit test for java.nio.file.Path.newByteChannel + * @summary Unit test for java.nio.file.Files.newByteChannel * @library .. */ @@ -75,24 +75,24 @@ public class SBC { // CREATE try { // create file (no existing file) - file.newByteChannel(CREATE, WRITE).close(); - if (file.notExists()) + Files.newByteChannel(file, CREATE, WRITE).close(); + if (Files.notExists(file)) throw new RuntimeException("File not created"); // create file (existing file) - file.newByteChannel(CREATE, WRITE).close(); + Files.newByteChannel(file, CREATE, WRITE).close(); // create file where existing file is a sym link if (supportsLinks) { - Path link = dir.resolve("link").createSymbolicLink(file); + Path link = Files.createSymbolicLink(dir.resolve("link"), file); try { // file already exists - link.newByteChannel(CREATE, WRITE).close(); + Files.newByteChannel(link, CREATE, WRITE).close(); // file does not exist - file.delete(); - link.newByteChannel(CREATE, WRITE).close(); - if (file.notExists()) + Files.delete(file); + Files.newByteChannel(link, CREATE, WRITE).close(); + if (Files.notExists(file)) throw new RuntimeException("File not created"); } finally { @@ -107,14 +107,14 @@ public class SBC { // CREATE_NEW try { // create file - file.newByteChannel(CREATE_NEW, WRITE).close(); - if (file.notExists()) + Files.newByteChannel(file, CREATE_NEW, WRITE).close(); + if (Files.notExists(file)) throw new RuntimeException("File not created"); // create should fail try { SeekableByteChannel sbc = - file.newByteChannel(CREATE_NEW, WRITE); + Files.newByteChannel(file, CREATE_NEW, WRITE); sbc.close(); throw new RuntimeException("FileAlreadyExistsException not thrown"); } catch (FileAlreadyExistsException x) { } @@ -123,12 +123,12 @@ public class SBC { if (supportsLinks) { Path link = dir.resolve("link"); Path target = dir.resolve("thisDoesNotExist"); - link.createSymbolicLink(target); + Files.createSymbolicLink(link, target); try { try { SeekableByteChannel sbc = - file.newByteChannel(CREATE_NEW, WRITE); + Files.newByteChannel(file, CREATE_NEW, WRITE); sbc.close(); throw new RuntimeException("FileAlreadyExistsException not thrown"); } catch (FileAlreadyExistsException x) { } @@ -145,17 +145,13 @@ public class SBC { // CREATE_NEW + SPARSE try { - SeekableByteChannel sbc = file - .newByteChannel(CREATE_NEW, WRITE, SPARSE); - try { + try (SeekableByteChannel sbc = Files.newByteChannel(file, CREATE_NEW, WRITE, SPARSE)) { final long hole = 2L * 1024L * 1024L * 1024L; sbc.position(hole); write(sbc, "hello"); long size = sbc.size(); if (size != (hole + 5)) throw new RuntimeException("Unexpected size"); - } finally { - sbc.close(); } } finally { TestUtil.deleteUnchecked(file); @@ -167,33 +163,23 @@ public class SBC { Path file = dir.resolve("foo"); try { // "hello there" should be written to file - SeekableByteChannel sbc = file - .newByteChannel(CREATE_NEW, WRITE, APPEND); - try { + try (SeekableByteChannel sbc = Files.newByteChannel(file, CREATE_NEW, WRITE, APPEND)) { write(sbc, "hello "); sbc.position(0L); write(sbc, "there"); - } finally { - sbc.close(); } // check file - Scanner s = new Scanner(file); - try { + try (Scanner s = new Scanner(file)) { String line = s.nextLine(); if (!line.equals("hello there")) throw new RuntimeException("Unexpected file contents"); - } finally { - s.close(); } // check that read is not allowed - sbc = file.newByteChannel(APPEND); - try { + try (SeekableByteChannel sbc = Files.newByteChannel(file, APPEND)) { sbc.read(ByteBuffer.allocate(100)); } catch (NonReadableChannelException x) { - } finally { - sbc.close(); } } finally { // clean-up @@ -205,40 +191,27 @@ public class SBC { static void truncateExistingTests(Path dir) throws Exception { Path file = dir.resolve("foo"); try { - SeekableByteChannel sbc = - file.newByteChannel(CREATE_NEW, WRITE); - try { + try (SeekableByteChannel sbc = Files.newByteChannel(file, CREATE_NEW, WRITE)) { write(sbc, "Have a nice day!"); - } finally { - sbc.close(); } // re-open with truncate option // write short message and check - sbc = file.newByteChannel(WRITE, TRUNCATE_EXISTING); - try { + try (SeekableByteChannel sbc = Files.newByteChannel(file, WRITE, TRUNCATE_EXISTING)) { write(sbc, "Hello there!"); - } finally { - sbc.close(); } - Scanner s = new Scanner(file); - try { + try (Scanner s = new Scanner(file)) { String line = s.nextLine(); if (!line.equals("Hello there!")) throw new RuntimeException("Unexpected file contents"); - } finally { - s.close(); } // re-open with create + truncate option // check file is of size 0L - sbc = file.newByteChannel(WRITE, CREATE, TRUNCATE_EXISTING); - try { + try (SeekableByteChannel sbc = Files.newByteChannel(file, WRITE, CREATE, TRUNCATE_EXISTING)) { long size = ((FileChannel)sbc).size(); if (size != 0L) throw new RuntimeException("File not truncated"); - } finally { - sbc.close(); } } finally { @@ -252,14 +225,15 @@ public class SBC { static void noFollowLinksTests(Path dir) throws Exception { if (!supportsLinks) return; - Path file = dir.resolve("foo").createFile(); + Path file = Files.createFile(dir.resolve("foo")); try { // ln -s foo link - Path link = dir.resolve("link").createSymbolicLink(file); + Path link = dir.resolve("link"); + Files.createSymbolicLink(link, file); // open with NOFOLLOW_LINKS option try { - link.newByteChannel(READ, LinkOption.NOFOLLOW_LINKS); + Files.newByteChannel(link, READ, LinkOption.NOFOLLOW_LINKS); throw new RuntimeException(); } catch (IOException x) { } finally { @@ -276,9 +250,7 @@ public class SBC { static void sizeTruncatePositionTests(Path dir) throws Exception { Path file = dir.resolve("foo"); try { - SeekableByteChannel sbc = file - .newByteChannel(CREATE_NEW, READ, WRITE); - try { + try (SeekableByteChannel sbc = Files.newByteChannel(file, CREATE_NEW, READ, WRITE)) { if (sbc.size() != 0L) throw new RuntimeException("Unexpected size"); @@ -300,8 +272,6 @@ public class SBC { throw new RuntimeException("Unexpected size"); if (sbc.position() != 2L) throw new RuntimeException("Unexpected position"); - } finally { - sbc.close(); } } finally { TestUtil.deleteUnchecked(file); @@ -311,76 +281,63 @@ public class SBC { // Windows specific options for the use by applications that really want // to use legacy DOS sharing options static void dosSharingOptionTests(Path dir) throws Exception { - Path file = dir.resolve("foo").createFile(); + Path file = Files.createFile(dir.resolve("foo")); try { - SeekableByteChannel ch; - // no sharing - ch = file.newByteChannel(READ, - NOSHARE_READ, NOSHARE_WRITE, NOSHARE_DELETE); - try { + try (SeekableByteChannel ch = Files.newByteChannel(file, READ, NOSHARE_READ, + NOSHARE_WRITE, NOSHARE_DELETE)) + { try { - file.newByteChannel(READ); + Files.newByteChannel(file, READ); throw new RuntimeException("Sharing violation expected"); } catch (IOException ignore) { } try { - file.newByteChannel(WRITE); + Files.newByteChannel(file, WRITE); throw new RuntimeException("Sharing violation expected"); } catch (IOException ignore) { } try { - file.delete(); + Files.delete(file); throw new RuntimeException("Sharing violation expected"); } catch (IOException ignore) { } - } finally { - ch.close(); } // read allowed - ch = file.newByteChannel(READ, NOSHARE_WRITE, NOSHARE_DELETE); - try { - file.newByteChannel(READ).close(); + try (SeekableByteChannel ch = Files.newByteChannel(file, READ, NOSHARE_WRITE, NOSHARE_DELETE)) { + Files.newByteChannel(file, READ).close(); try { - file.newByteChannel(WRITE); + Files.newByteChannel(file, WRITE); throw new RuntimeException("Sharing violation expected"); } catch (IOException ignore) { } try { - file.delete(); + Files.delete(file); throw new RuntimeException("Sharing violation expected"); } catch (IOException ignore) { } - } finally { - ch.close(); } // write allowed - ch = file.newByteChannel(READ, NOSHARE_READ, NOSHARE_DELETE); - try { + try (SeekableByteChannel ch = Files.newByteChannel(file, READ, NOSHARE_READ, NOSHARE_DELETE)) { try { - file.newByteChannel(READ); + Files.newByteChannel(file, READ); throw new RuntimeException("Sharing violation expected"); } catch (IOException ignore) { } - file.newByteChannel(WRITE).close(); + Files.newByteChannel(file, WRITE).close(); try { - file.delete(); + Files.delete(file); throw new RuntimeException("Sharing violation expected"); } catch (IOException ignore) { } - } finally { - ch.close(); } // delete allowed - ch = file.newByteChannel(READ, NOSHARE_READ, NOSHARE_WRITE); - try { + try (SeekableByteChannel ch = Files.newByteChannel(file, READ, NOSHARE_READ, NOSHARE_WRITE)) { try { - file.newByteChannel(READ); + Files.newByteChannel(file, READ); throw new RuntimeException("Sharing violation expected"); } catch (IOException ignore) { } try { - file.newByteChannel(WRITE); + Files.newByteChannel(file, WRITE); throw new RuntimeException("Sharing violation expected"); } catch (IOException ignore) { } - file.delete(); - } finally { - ch.close(); + Files.delete(file); } } finally { @@ -393,12 +350,12 @@ public class SBC { Path file = dir.resolve("bad"); try { - file.newByteChannel(READ, APPEND); + Files.newByteChannel(file, READ, APPEND); throw new RuntimeException("IllegalArgumentException expected"); } catch (IllegalArgumentException x) { } try { - file.newByteChannel(WRITE, APPEND, TRUNCATE_EXISTING); + Files.newByteChannel(file, WRITE, APPEND, TRUNCATE_EXISTING); throw new RuntimeException("IllegalArgumentException expected"); } catch (IllegalArgumentException x) { } } @@ -409,11 +366,11 @@ public class SBC { OpenOption badOption = new OpenOption() { }; try { - file.newByteChannel(badOption); + Files.newByteChannel(file, badOption); throw new RuntimeException("UnsupportedOperationException expected"); } catch (UnsupportedOperationException e) { } try { - file.newByteChannel(READ, WRITE, badOption); + Files.newByteChannel(file, READ, WRITE, badOption); throw new RuntimeException("UnsupportedOperationException expected"); } catch (UnsupportedOperationException e) { } } @@ -423,39 +380,45 @@ public class SBC { Path file = dir.resolve("foo"); try { - file.newByteChannel((OpenOption[])null); + OpenOption[] opts = { READ, null }; + Files.newByteChannel((Path)null, opts); + throw new RuntimeException("NullPointerException expected"); + } catch (NullPointerException x) { } + + try { + Files.newByteChannel(file, (OpenOption[])null); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } try { OpenOption[] opts = { READ, null }; - file.newByteChannel(opts); + Files.newByteChannel(file, opts); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } try { - file.newByteChannel((Set)null); + Files.newByteChannel(file, (Set)null); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } try { - Set opts = new HashSet(); + Set opts = new HashSet<>(); opts.add(READ); opts.add(null); - file.newByteChannel(opts); + Files.newByteChannel(file, opts); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } try { EnumSet opts = EnumSet.of(READ); - file.newByteChannel(opts, (FileAttribute[])null); + Files.newByteChannel(file, opts, (FileAttribute[])null); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } try { EnumSet opts = EnumSet.of(READ); FileAttribute[] attrs = { null }; - file.newByteChannel(opts, attrs); + Files.newByteChannel(file, opts, attrs); throw new RuntimeException("NullPointerException expected"); } catch (NullPointerException x) { } } diff --git a/jdk/test/java/nio/file/Files/TemporaryFiles.java b/jdk/test/java/nio/file/Files/TemporaryFiles.java new file mode 100644 index 00000000000..3c1087e4e53 --- /dev/null +++ b/jdk/test/java/nio/file/Files/TemporaryFiles.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 4313887 6838333 7006126 + * @summary Unit test for Files.createTempXXX + * @library .. + */ + +import java.nio.file.*; +import static java.nio.file.StandardOpenOption.*; +import java.nio.file.attribute.*; +import java.io.IOException; +import java.util.Set; + +public class TemporaryFiles { + + static void checkInDirectory(Path file, Path dir) { + if (dir == null) + dir = Paths.get(System.getProperty("java.io.tmpdir")); + if (!file.getParent().equals(dir)) + throw new RuntimeException("Not in expected directory"); + } + + static void testTempFile(String prefix, String suffix, Path dir) + throws IOException + { + Path file = (dir == null) ? + Files.createTempFile(prefix, suffix) : + Files.createTempFile(dir, prefix, suffix); + try { + // check file name + String name = file.getFileName().toString(); + if (prefix != null && !name.startsWith(prefix)) + throw new RuntimeException("Should start with " + prefix); + if (suffix == null && !name.endsWith(".tmp")) + throw new RuntimeException("Should end with .tmp"); + if (suffix != null && !name.endsWith(suffix)) + throw new RuntimeException("Should end with " + suffix); + + // check file is in expected directory + checkInDirectory(file, dir); + + // check that file can be opened for reading and writing + Files.newByteChannel(file, READ).close(); + Files.newByteChannel(file, WRITE).close(); + Files.newByteChannel(file, READ,WRITE).close(); + + // check file permissions are 0600 or more secure + if (Files.getFileStore(file).supportsFileAttributeView("posix")) { + Set perms = Files.getPosixFilePermissions(file); + perms.remove(PosixFilePermission.OWNER_READ); + perms.remove(PosixFilePermission.OWNER_WRITE); + if (!perms.isEmpty()) + throw new RuntimeException("Temporary file is not secure"); + } + } finally { + Files.delete(file); + } + } + + static void testTempFile(String prefix, String suffix) + throws IOException + { + testTempFile(prefix, suffix, null); + } + + static void testTempDirectory(String prefix, Path dir) throws IOException { + Path subdir = (dir == null) ? + Files.createTempDirectory(prefix) : + Files.createTempDirectory(dir, prefix); + try { + // check file name + String name = subdir.getFileName().toString(); + if (prefix != null && !name.startsWith(prefix)) + throw new RuntimeException("Should start with " + prefix); + + // check directory is in expected directory + checkInDirectory(subdir, dir); + + // check directory is empty + DirectoryStream stream = Files.newDirectoryStream(subdir); + try { + if (stream.iterator().hasNext()) + throw new RuntimeException("Tempory directory not empty"); + } finally { + stream.close(); + } + + // check that we can create file in directory + Path file = Files.createFile(subdir.resolve("foo")); + try { + Files.newByteChannel(file, READ,WRITE).close(); + } finally { + Files.delete(file); + } + + // check file permissions are 0700 or more secure + if (Files.getFileStore(subdir).supportsFileAttributeView("posix")) { + Set perms = Files.getPosixFilePermissions(subdir); + perms.remove(PosixFilePermission.OWNER_READ); + perms.remove(PosixFilePermission.OWNER_WRITE); + perms.remove(PosixFilePermission.OWNER_EXECUTE); + if (!perms.isEmpty()) + throw new RuntimeException("Temporary directory is not secure"); + } + } finally { + Files.delete(subdir); + } + } + + static void testTempDirectory(String prefix) throws IOException { + testTempDirectory(prefix, null); + } + + static void testInvalidFileTemp(String prefix, String suffix) throws IOException { + try { + Path file = Files.createTempFile(prefix, suffix); + Files.delete(file); + throw new RuntimeException("IllegalArgumentException expected"); + } catch (IllegalArgumentException expected) { } + } + + public static void main(String[] args) throws IOException { + // temporary-file directory + testTempFile("blah", ".dat"); + testTempFile("blah", null); + testTempFile(null, ".dat"); + testTempFile(null, null); + testTempDirectory("blah"); + testTempDirectory(null); + + // a given directory + Path dir = Files.createTempDirectory("tmpdir"); + try { + testTempFile("blah", ".dat", dir); + testTempFile("blah", null, dir); + testTempFile(null, ".dat", dir); + testTempFile(null, null, dir); + testTempDirectory("blah", dir); + testTempDirectory(null, dir); + } finally { + Files.delete(dir); + } + + // invalid prefix and suffix + testInvalidFileTemp("../blah", null); + testInvalidFileTemp("dir/blah", null); + testInvalidFileTemp("blah", ".dat/foo"); + } +} diff --git a/jdk/test/java/nio/file/Path/delete_on_close.sh b/jdk/test/java/nio/file/Files/delete_on_close.sh similarity index 100% rename from jdk/test/java/nio/file/Path/delete_on_close.sh rename to jdk/test/java/nio/file/Files/delete_on_close.sh diff --git a/jdk/test/java/nio/file/Files/ContentType.java b/jdk/test/java/nio/file/Files/probeContentType/Basic.java similarity index 85% rename from jdk/test/java/nio/file/Files/ContentType.java rename to jdk/test/java/nio/file/Files/probeContentType/Basic.java index 33a0aeb6e14..ce692121d1c 100644 --- a/jdk/test/java/nio/file/Files/ContentType.java +++ b/jdk/test/java/nio/file/Files/probeContentType/Basic.java @@ -24,9 +24,9 @@ /* @test * @bug 4313887 * @summary Unit test for probeContentType method - * @library .. - * @build ContentType SimpleFileTypeDetector - * @run main/othervm ContentType + * @library ../.. + * @build Basic SimpleFileTypeDetector + * @run main/othervm Basic */ import java.nio.file.*; @@ -36,22 +36,19 @@ import java.io.*; * Uses Files.probeContentType to probe html file and custom file type. */ -public class ContentType { +public class Basic { static Path createHtmlFile() throws IOException { - Path file = File.createTempFile("foo", ".html").toPath(); - OutputStream out = file.newOutputStream(); - try { + Path file = Files.createTempFile("foo", ".html"); + try (OutputStream out = Files.newOutputStream(file)) { out.write("foo".getBytes()); - } finally { - out.close(); } return file; } static Path createGrapeFile() throws IOException { - return File.createTempFile("red", ".grape").toPath(); + return Files.createTempFile("red", ".grape"); } public static void main(String[] args) throws IOException { @@ -67,7 +64,7 @@ public class ContentType { throw new RuntimeException("Unexpected type: " + type); } } finally { - file.delete(); + Files.delete(file); } // exercise custom file type detector @@ -79,7 +76,7 @@ public class ContentType { if (!type.equals("grape/unknown")) throw new RuntimeException("Unexpected type: " + type); } finally { - file.delete(); + Files.delete(file); } } diff --git a/jdk/test/java/nio/file/Files/ForceLoad.java b/jdk/test/java/nio/file/Files/probeContentType/ForceLoad.java similarity index 100% rename from jdk/test/java/nio/file/Files/ForceLoad.java rename to jdk/test/java/nio/file/Files/probeContentType/ForceLoad.java diff --git a/jdk/test/java/nio/file/Files/META-INF/services/java.nio.file.spi.FileTypeDetector b/jdk/test/java/nio/file/Files/probeContentType/META-INF/services/java.nio.file.spi.FileTypeDetector similarity index 100% rename from jdk/test/java/nio/file/Files/META-INF/services/java.nio.file.spi.FileTypeDetector rename to jdk/test/java/nio/file/Files/probeContentType/META-INF/services/java.nio.file.spi.FileTypeDetector diff --git a/jdk/test/java/nio/file/Files/SimpleFileTypeDetector.java b/jdk/test/java/nio/file/Files/probeContentType/SimpleFileTypeDetector.java similarity index 81% rename from jdk/test/java/nio/file/Files/SimpleFileTypeDetector.java rename to jdk/test/java/nio/file/Files/probeContentType/SimpleFileTypeDetector.java index 590d9a474c1..a6b0e76ecd8 100644 --- a/jdk/test/java/nio/file/Files/SimpleFileTypeDetector.java +++ b/jdk/test/java/nio/file/Files/probeContentType/SimpleFileTypeDetector.java @@ -30,18 +30,9 @@ public class SimpleFileTypeDetector extends FileTypeDetector { public SimpleFileTypeDetector() { } - public String probeContentType(FileRef file) throws IOException { - + public String probeContentType(Path file) throws IOException { System.out.println("probe " + file + "..."); - - if (file instanceof Path) { - String name = ((Path)file).toString(); - if (name.endsWith(".grape")) { - return "grape/unknown"; - } - } - - // unknown - return null; + String name = file.toString(); + return name.endsWith(".grape") ? "grape/unknown" : null; } } diff --git a/jdk/test/java/nio/file/Files/CreateFileTree.java b/jdk/test/java/nio/file/Files/walkFileTree/CreateFileTree.java similarity index 81% rename from jdk/test/java/nio/file/Files/CreateFileTree.java rename to jdk/test/java/nio/file/Files/walkFileTree/CreateFileTree.java index 1ff7aa6e91b..c00f058152d 100644 --- a/jdk/test/java/nio/file/Files/CreateFileTree.java +++ b/jdk/test/java/nio/file/Files/walkFileTree/CreateFileTree.java @@ -34,21 +34,8 @@ public class CreateFileTree { static final Random rand = new Random(); - public static Path createTemporaryDirectory() throws IOException { - Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir")); - Path dir; - do { - dir = tmpdir.resolve("name" + rand.nextInt()); - } while (dir.exists()); - dir.createDirectory(); - return dir; - } - public static void main(String[] args) throws IOException { - Path top = createTemporaryDirectory(); - if (!top.isAbsolute()) - top = top.toAbsolutePath(); - + Path top = Files.createTempDirectory("tree"); List dirs = new ArrayList(); // create tree @@ -61,7 +48,7 @@ public class CreateFileTree { int r = Math.min((total-n), (1+rand.nextInt(3))); for (int i=0; i(){}); + npeExpected(); + } catch (NullPointerException e) { + } + try { + Files.walkFileTree(Paths.get("."), null, Integer.MAX_VALUE, + new SimpleFileVisitor(){}); + npeExpected(); + } catch (NullPointerException e) { + } + try { + Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class), + -1, new SimpleFileVisitor(){}); + throw new RuntimeException("IllegalArgumentExpected expected"); + } catch (IllegalArgumentException e) { + } + try { + Set opts = new HashSet<>(1); + opts.add(null); + Files.walkFileTree(Paths.get("."), opts, Integer.MAX_VALUE, + new SimpleFileVisitor(){}); + npeExpected(); + } catch (NullPointerException e) { + } + try { + Files.walkFileTree(Paths.get("."), EnumSet.noneOf(FileVisitOption.class), + Integer.MAX_VALUE, null); + npeExpected(); + } catch (NullPointerException e) { + } + + SimpleFileVisitor visitor = new SimpleFileVisitor() { }; + boolean ranTheGauntlet = false; + Path dir = Paths.get("."); + BasicFileAttributes attrs = Files.readAttributes(dir, BasicFileAttributes.class); + + try { visitor.preVisitDirectory(null, attrs); + } catch (NullPointerException x0) { + try { visitor.preVisitDirectory(dir, null); + } catch (NullPointerException x1) { + try { visitor.visitFile(null, attrs); + } catch (NullPointerException x2) { + try { visitor.visitFile(dir, null); + } catch (NullPointerException x3) { + try { visitor.visitFileFailed(null, new IOException()); + } catch (NullPointerException x4) { + try { visitor.visitFileFailed(dir, null); + } catch (NullPointerException x5) { + try { visitor.postVisitDirectory(null, new IOException()); + } catch (NullPointerException x6) { + // if we get here then all visit* methods threw NPE as expected + ranTheGauntlet = true; + }}}}}}} + if (!ranTheGauntlet) + throw new RuntimeException("A visit method did not throw NPE"); + } +} diff --git a/jdk/test/java/nio/file/Files/PrintFileTree.java b/jdk/test/java/nio/file/Files/walkFileTree/PrintFileTree.java similarity index 89% rename from jdk/test/java/nio/file/Files/PrintFileTree.java rename to jdk/test/java/nio/file/Files/walkFileTree/PrintFileTree.java index 41ddb95a317..83d554dc689 100644 --- a/jdk/test/java/nio/file/Files/PrintFileTree.java +++ b/jdk/test/java/nio/file/Files/walkFileTree/PrintFileTree.java @@ -55,20 +55,20 @@ public class PrintFileTree { options.add(FileVisitOption.FOLLOW_LINKS); final boolean reportCycles = printCycles; - Files.walkFileTree(dir, options, Integer.MAX_VALUE, new FileVisitor() { + Files.walkFileTree(dir, options, Integer.MAX_VALUE, new FileVisitor() { @Override - public FileVisitResult preVisitDirectory(FileRef dir, BasicFileAttributes attrs) { + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { System.out.println(dir); return FileVisitResult.CONTINUE; } @Override - public FileVisitResult visitFile(FileRef file, BasicFileAttributes attrs) { + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { if (!attrs.isDirectory() || reportCycles) System.out.println(file); return FileVisitResult.CONTINUE; } @Override - public FileVisitResult postVisitDirectory(FileRef dir, IOException exc) + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { if (exc != null) @@ -76,7 +76,7 @@ public class PrintFileTree { return FileVisitResult.CONTINUE; } @Override - public FileVisitResult visitFileFailed(FileRef file, IOException exc) + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { if (reportCycles && (exc instanceof FileSystemLoopException)) { diff --git a/jdk/test/java/nio/file/Files/SkipSiblings.java b/jdk/test/java/nio/file/Files/walkFileTree/SkipSiblings.java similarity index 100% rename from jdk/test/java/nio/file/Files/SkipSiblings.java rename to jdk/test/java/nio/file/Files/walkFileTree/SkipSiblings.java diff --git a/jdk/test/java/nio/file/Files/TerminateWalk.java b/jdk/test/java/nio/file/Files/walkFileTree/TerminateWalk.java similarity index 100% rename from jdk/test/java/nio/file/Files/TerminateWalk.java rename to jdk/test/java/nio/file/Files/walkFileTree/TerminateWalk.java diff --git a/jdk/test/java/nio/file/Files/WalkWithSecurity.java b/jdk/test/java/nio/file/Files/walkFileTree/WalkWithSecurity.java similarity index 94% rename from jdk/test/java/nio/file/Files/WalkWithSecurity.java rename to jdk/test/java/nio/file/Files/walkFileTree/WalkWithSecurity.java index 2a1f67f492e..91e61c476be 100644 --- a/jdk/test/java/nio/file/Files/WalkWithSecurity.java +++ b/jdk/test/java/nio/file/Files/walkFileTree/WalkWithSecurity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,14 +47,11 @@ public class WalkWithSecurity { Path dir = Paths.get(testSrc); // Sanity check the environment - if (Paths.get(here).isSameFile(dir)) + if (Files.isSameFile(Paths.get(here), dir)) throw new RuntimeException("Working directory cannot be " + dir); - DirectoryStream stream = dir.newDirectoryStream(); - try { + try (DirectoryStream stream = Files.newDirectoryStream(dir)) { if (!stream.iterator().hasNext()) throw new RuntimeException(testSrc + " is empty"); - } finally { - stream.close(); } // Install security manager with the given policy file diff --git a/jdk/test/java/nio/file/Files/denyAll.policy b/jdk/test/java/nio/file/Files/walkFileTree/denyAll.policy similarity index 100% rename from jdk/test/java/nio/file/Files/denyAll.policy rename to jdk/test/java/nio/file/Files/walkFileTree/denyAll.policy diff --git a/jdk/test/java/nio/file/Files/grantAll.policy b/jdk/test/java/nio/file/Files/walkFileTree/grantAll.policy similarity index 100% rename from jdk/test/java/nio/file/Files/grantAll.policy rename to jdk/test/java/nio/file/Files/walkFileTree/grantAll.policy diff --git a/jdk/test/java/nio/file/Files/grantTopOnly.policy b/jdk/test/java/nio/file/Files/walkFileTree/grantTopOnly.policy similarity index 100% rename from jdk/test/java/nio/file/Files/grantTopOnly.policy rename to jdk/test/java/nio/file/Files/walkFileTree/grantTopOnly.policy diff --git a/jdk/test/java/nio/file/Files/walk_file_tree.sh b/jdk/test/java/nio/file/Files/walkFileTree/walk_file_tree.sh similarity index 100% rename from jdk/test/java/nio/file/Files/walk_file_tree.sh rename to jdk/test/java/nio/file/Files/walkFileTree/walk_file_tree.sh diff --git a/jdk/test/java/nio/file/Path/Misc.java b/jdk/test/java/nio/file/Path/Misc.java index dba06f1dd06..b2bf03e3510 100644 --- a/jdk/test/java/nio/file/Path/Misc.java +++ b/jdk/test/java/nio/file/Path/Misc.java @@ -22,17 +22,13 @@ */ /* @test - * @bug 4313887 6838333 6867101 - * @summary Unit test for java.nio.file.Path for miscellenous methods not - * covered by other tests + * @bug 4313887 6838333 + * @summary Unit test for miscellenous java.nio.file.Path methods * @library .. */ import java.nio.file.*; -import static java.nio.file.LinkOption.*; -import java.nio.file.attribute.*; import java.io.*; -import java.util.*; public class Misc { static final boolean isWindows = @@ -45,22 +41,14 @@ public class Misc { supportsLinks = TestUtil.supportsLinks(dir); // equals and hashCode methods - equalsAndHashCode(); + testEqualsAndHashCode(); - // checkAccess method - checkAccessTests(dir); - - // getFileAttributeView methods - getFileAttributeViewTests(dir); + // toFile method + testToFile(dir); // toRealPath method - toRealPathTests(dir); + testToRealPath(dir); - // isSameFile method - isSameFileTests(dir); - - // isHidden method - isHiddenTests(dir); } finally { TestUtil.removeAll(dir); @@ -70,8 +58,7 @@ public class Misc { /** * Exercise equals and hashCode methods */ - static void equalsAndHashCode() { - + static void testEqualsAndHashCode() { Path thisFile = Paths.get("this"); Path thatFile = Paths.get("that"); @@ -93,172 +80,25 @@ public class Misc { } /** - * Exercise checkAccess method + * Exercise toFile method */ - static void checkAccessTests(Path dir) throws IOException { - final Path file = dir.resolve("foo").createFile(); - - /** - * Test: This directory should readable and writable - */ - dir.checkAccess(); - dir.checkAccess(AccessMode.READ); - dir.checkAccess(AccessMode.WRITE); - dir.checkAccess(AccessMode.READ, AccessMode.WRITE); - - /** - * Test: Check access to all files in all root directories. - * (A useful test on Windows for special files such as pagefile.sys) - */ - for (Path root: FileSystems.getDefault().getRootDirectories()) { - DirectoryStream stream; - try { - stream = root.newDirectoryStream(); - } catch (IOException x) { - continue; // skip root directories that aren't accessible - } - try { - for (Path entry: stream) { - try { - entry.checkAccess(); - } catch (AccessDeniedException ignore) { } - } - } finally { - stream.close(); - } - } - - /** - * Test: File does not exist - */ - Path doesNotExist = dir.resolve("thisDoesNotExists"); - try { - doesNotExist.checkAccess(); - throw new RuntimeException("NoSuchFileException expected"); - } catch (NoSuchFileException x) { - } - try { - doesNotExist.checkAccess(AccessMode.READ); - throw new RuntimeException("NoSuchFileException expected"); - } catch (NoSuchFileException x) { - } - try { - doesNotExist.checkAccess(AccessMode.WRITE); - throw new RuntimeException("NoSuchFileException expected"); - } catch (NoSuchFileException x) { - } - try { - doesNotExist.checkAccess(AccessMode.EXECUTE); - throw new RuntimeException("NoSuchFileException expected"); - } catch (NoSuchFileException x) { - } - - /** - * Test: Edit ACL to deny WRITE and EXECUTE - */ - AclFileAttributeView view = file - .getFileAttributeView(AclFileAttributeView.class); - if (view != null && - file.getFileStore().supportsFileAttributeView("acl")) - { - UserPrincipal owner = view.getOwner(); - List acl = view.getAcl(); - - // Insert entry to deny WRITE and EXECUTE - AclEntry entry = AclEntry.newBuilder() - .setType(AclEntryType.DENY) - .setPrincipal(owner) - .setPermissions(AclEntryPermission.WRITE_DATA, - AclEntryPermission.EXECUTE) - .build(); - acl.add(0, entry); - view.setAcl(acl); - - try { - file.checkAccess(AccessMode.WRITE); - throw new RuntimeException("AccessDeniedException expected"); - } catch (AccessDeniedException x) { - } - - try { - file.checkAccess(AccessMode.EXECUTE); - throw new RuntimeException("AccessDeniedException expected"); - } catch (AccessDeniedException x) { - } - - - // Restore ACL - acl.remove(0); - view.setAcl(acl); - } - - /** - * Test: Windows DOS read-only attribute - */ - if (isWindows) { - DosFileAttributeView dview = - file.getFileAttributeView(DosFileAttributeView.class); - dview.setReadOnly(true); - try { - file.checkAccess(AccessMode.WRITE); - throw new RuntimeException("AccessDeniedException expected"); - } catch (AccessDeniedException x) { - } - dview.setReadOnly(false); - - // Read-only attribute does not make direcory read-only - dview = dir.getFileAttributeView(DosFileAttributeView.class); - boolean save = dview.readAttributes().isReadOnly(); - dview.setReadOnly(true); - dir.checkAccess(AccessMode.WRITE); - dview.setReadOnly(save); - } - - /** - * Test: null - */ - try { - file.checkAccess((AccessMode)null); - throw new RuntimeException("NullPointerException expected"); - } catch (NullPointerException ignore) { } - - // clean-up - file.delete(); + static void testToFile(Path dir) throws IOException { + File d = dir.toFile(); + assertTrue(d.toString().equals(dir.toString())); + assertTrue(d.toPath().equals(dir)); } - /** - * Exercise getFileAttributeFile methods - */ - static void getFileAttributeViewTests(Path dir) { - assertTrue(dir.getFileAttributeView(BasicFileAttributeView.class) - instanceof BasicFileAttributeView); - assertTrue(dir.getFileAttributeView(BasicFileAttributeView.class, NOFOLLOW_LINKS) - instanceof BasicFileAttributeView); - assertTrue(dir.getFileAttributeView(BogusFileAttributeView.class) == null); - try { - dir.getFileAttributeView((Class)null); - } catch (NullPointerException ignore) { } - try { - dir.getFileAttributeView(BasicFileAttributeView.class, (LinkOption[])null); - } catch (NullPointerException ignore) { } - try { - dir.getFileAttributeView(BasicFileAttributeView.class, (LinkOption)null); - } catch (NullPointerException ignore) { } - - } - interface BogusFileAttributeView extends FileAttributeView { } - /** * Exercise toRealPath method */ - static void toRealPathTests(Path dir) throws IOException { - final Path file = dir.resolve("foo").createFile(); + static void testToRealPath(Path dir) throws IOException { + final Path file = Files.createFile(dir.resolve("foo")); final Path link = dir.resolve("link"); /** - * Test: toRealPath(true) will access same file as toRealPath(false) + * Test: totRealPath(true) will access same file as toRealPath(false) */ - assertTrue(file.toRealPath(true).isSameFile(file.toRealPath(false))); + assertTrue(Files.isSameFile(file.toRealPath(true), file.toRealPath(false))); /** * Test: toRealPath should fail if file does not exist @@ -279,29 +119,27 @@ public class Misc { * Test: toRealPath(true) should resolve links */ if (supportsLinks) { - link.createSymbolicLink(file.toAbsolutePath()); + Files.createSymbolicLink(link, file.toAbsolutePath()); assertTrue(link.toRealPath(true).equals(file.toRealPath(true))); - link.delete(); + Files.delete(link); } - /** * Test: toRealPath(false) should not resolve links */ if (supportsLinks) { - link.createSymbolicLink(file.toAbsolutePath()); - assertTrue(link.toRealPath(false).getName().equals(link.getName())); - link.delete(); + Files.createSymbolicLink(link, file.toAbsolutePath()); + assertTrue(link.toRealPath(false).getFileName().equals(link.getFileName())); + Files.delete(link); } /** * Test: toRealPath(false) with broken link */ if (supportsLinks) { - Path broken = dir.resolve("doesNotExist"); - link.createSymbolicLink(broken); - assertTrue(link.toRealPath(false).getName().equals(link.getName())); - link.delete(); + Path broken = Files.createSymbolicLink(link, doesNotExist); + assertTrue(link.toRealPath(false).getFileName().equals(link.getFileName())); + Files.delete(link); } /** @@ -314,105 +152,13 @@ public class Misc { * Test: toRealPath should eliminate ".." when it doesn't follow a * symbolic link */ - Path subdir = dir.resolve("subdir").createDirectory(); + Path subdir = Files.createDirectory(dir.resolve("subdir")); assertTrue(subdir.resolve("..").toRealPath(true).equals(dir.toRealPath(true))); assertTrue(subdir.resolve("..").toRealPath(false).equals(dir.toRealPath(false))); - subdir.delete(); + Files.delete(subdir); // clean-up - file.delete(); - } - - /** - * Exercise isSameFile method - */ - static void isSameFileTests(Path dir) throws IOException { - Path thisFile = dir.resolve("thisFile"); - Path thatFile = dir.resolve("thatFile"); - - /** - * Test: isSameFile for self and null - */ - assertTrue(thisFile.isSameFile(thisFile)); - assertTrue(!thisFile.isSameFile(null)); - - /** - * Test: Neither files exist - */ - try { - thisFile.isSameFile(thatFile); - throw new RuntimeException("IOException not thrown"); - } catch (IOException x) { - } - try { - thatFile.isSameFile(thisFile); - throw new RuntimeException("IOException not thrown"); - } catch (IOException x) { - } - - thisFile.createFile(); - try { - /** - * Test: One file exists - */ - try { - thisFile.isSameFile(thatFile); - throw new RuntimeException("IOException not thrown"); - } catch (IOException x) { - } - try { - thatFile.isSameFile(thisFile); - throw new RuntimeException("IOException not thrown"); - } catch (IOException x) { - } - - thatFile.createFile(); - - /** - * Test: Both file exists - */ - try { - assertTrue(!thisFile.isSameFile(thatFile)); - assertTrue(!thatFile.isSameFile(thisFile)); - } finally { - TestUtil.deleteUnchecked(thatFile); - } - - /** - * Test: Symbolic links - */ - if (supportsLinks) { - thatFile.createSymbolicLink(thisFile); - try { - assertTrue(thisFile.isSameFile(thatFile)); - assertTrue(thatFile.isSameFile(thisFile)); - } finally { - TestUtil.deleteUnchecked(thatFile); - } - } - } finally { - thisFile.delete(); - } - } - - /** - * Exercise isHidden method - */ - static void isHiddenTests(Path dir) throws IOException { - assertTrue(!dir.isHidden()); - - Path file = dir.resolve(".foo"); - if (isWindows) { - file.createFile(); - try { - file.setAttribute("dos:hidden", true); - assertTrue(file.isHidden()); - } finally { - file.delete(); - } - } else { - assertTrue(file.isHidden()); - } + Files.delete(file); } static void assertTrue(boolean okay) { diff --git a/jdk/test/java/nio/file/Path/PathOps.java b/jdk/test/java/nio/file/Path/PathOps.java index fcc02e61a44..00264201201 100644 --- a/jdk/test/java/nio/file/Path/PathOps.java +++ b/jdk/test/java/nio/file/Path/PathOps.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6838333 6925932 + * @bug 4313887 6838333 6925932 7006126 * @summary Unit test for java.nio.file.Path path operations */ @@ -36,15 +36,15 @@ public class PathOps { private Path path; private Exception exc; - private PathOps(String s) { + private PathOps(String first, String... more) { out.println(); - input = s; + input = first; try { - path = FileSystems.getDefault().getPath(s); - out.format("%s -> %s", s, path); + path = FileSystems.getDefault().getPath(first, more); + out.format("%s -> %s", first, path); } catch (Exception x) { exc = x; - out.format("%s -> %s", s, x); + out.format("%s -> %s", first, x); } out.println(); } @@ -97,7 +97,7 @@ public class PathOps { PathOps name(String expected) { out.println("check name"); checkPath(); - check(path.getName(), expected); + check(path.getFileName(), expected); return this; } @@ -168,6 +168,13 @@ public class PathOps { return this; } + PathOps resolveSibling(String other, String expected) { + out.format("test resolveSibling %s\n", other); + checkPath(); + check(path.resolveSibling(other), expected); + return this; + } + PathOps relativize(String other, String expected) { out.format("test relativize %s\n", other); checkPath(); @@ -198,8 +205,8 @@ public class PathOps { return this; } - static PathOps test(String s) { - return new PathOps(s); + static PathOps test(String first, String... more) { + return new PathOps(first, more); } // -- PathOpss -- @@ -213,6 +220,26 @@ public class PathOps { static void doWindowsTests() { header("Windows specific tests"); + // construction + test("C:\\") + .string("C:\\"); + test("C:\\", "") + .string("C:\\"); + test("C:\\", "foo") + .string("C:\\foo"); + test("C:\\", "\\foo") + .string("C:\\foo"); + test("C:\\", "foo\\") + .string("C:\\foo"); + test("foo", "bar", "gus") + .string("foo\\bar\\gus"); + test("") + .string(""); + test("", "C:\\") + .string("C:\\"); + test("", "foo", "", "bar", "", "\\gus") + .string("foo\\bar\\gus"); + // all components present test("C:\\a\\b\\c") .root("C:\\") @@ -252,17 +279,23 @@ public class PathOps { .root(null) .parent(null) .name("foo"); + test("") + .root(null) + .parent(null) + .name(""); // startsWith test("C:\\") .starts("C:\\") .starts("c:\\") .notStarts("C") - .notStarts("C:"); + .notStarts("C:") + .notStarts(""); test("C:") .starts("C:") .starts("c:") - .notStarts("C"); + .notStarts("C") + .notStarts(""); test("\\") .starts("\\"); test("C:\\foo\\bar") @@ -273,7 +306,8 @@ public class PathOps { .starts("C:\\Foo\\Bar") .notStarts("C:") .notStarts("C") - .notStarts("C:foo"); + .notStarts("C:foo") + .notStarts(""); test("\\foo\\bar") .starts("\\") .starts("\\foo") @@ -281,26 +315,35 @@ public class PathOps { .starts("\\foo\\bar") .starts("\\fOo\\BaR") .notStarts("foo") - .notStarts("foo\\bar"); + .notStarts("foo\\bar") + .notStarts(""); test("foo\\bar") .starts("foo") .starts("foo\\bar") - .notStarts("\\"); + .notStarts("\\") + .notStarts(""); test("\\\\server\\share") .starts("\\\\server\\share") .starts("\\\\server\\share\\") + .notStarts("\\") + .notStarts(""); + test("") + .starts("") .notStarts("\\"); // endsWith test("C:\\") .ends("C:\\") .ends("c:\\") - .notEnds("\\"); + .notEnds("\\") + .notEnds(""); test("C:") .ends("C:") - .ends("c:"); + .ends("c:") + .notEnds(""); test("\\") - .ends("\\"); + .ends("\\") + .notEnds(""); test("C:\\foo\\bar") .ends("bar") .ends("BAR") @@ -309,7 +352,8 @@ public class PathOps { .ends("C:\\foo\\bar") .ends("c:\\foO\\baR") .notEnds("r") - .notEnds("\\foo\\bar"); + .notEnds("\\foo\\bar") + .notEnds(""); test("\\foo\\bar") .ends("bar") .ends("BaR") @@ -317,17 +361,23 @@ public class PathOps { .ends("foO\\baR") .ends("\\foo\\bar") .ends("\\Foo\\Bar") - .notEnds("oo\\bar"); + .notEnds("oo\\bar") + .notEnds(""); test("foo\\bar") .ends("bar") .ends("BAR") .ends("foo\\bar") .ends("Foo\\Bar") - .notEnds("ar"); + .notEnds("ar") + .notEnds(""); test("\\\\server\\share") .ends("\\\\server\\share") .ends("\\\\server\\share\\") .notEnds("shared") + .notEnds("\\") + .notEnds(""); + test("") + .ends("") .notEnds("\\"); // elements @@ -338,6 +388,8 @@ public class PathOps { test("foo.bar\\gus.alice") .element(0, "foo.bar") .element(1, "gus.alice"); + test("") + .element(0, ""); // subpath test("C:\\foo") @@ -355,6 +407,8 @@ public class PathOps { .subpath(2, 3, "gus"); test("\\\\server\\share\\foo") .subpath(0, 1, "foo"); + test("") + .subpath(0, 1, ""); // isAbsolute test("foo").notAbsolute(); @@ -362,6 +416,7 @@ public class PathOps { test("C:\\").absolute(); test("C:\\abc").absolute(); test("\\\\server\\share\\").absolute(); + test("").notAbsolute(); // resolve test("C:\\") @@ -369,42 +424,99 @@ public class PathOps { .resolve("D:\\bar", "D:\\bar") .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar") .resolve("C:foo", "C:\\foo") - .resolve("D:foo", "D:foo"); + .resolve("D:foo", "D:foo") + .resolve("", "C:\\"); test("\\") .resolve("foo", "\\foo") .resolve("D:bar", "D:bar") .resolve("C:\\bar", "C:\\bar") .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar") - .resolve("\\foo", "\\foo"); + .resolve("\\foo", "\\foo") + .resolve("", "\\"); test("\\foo") .resolve("bar", "\\foo\\bar") .resolve("D:bar", "D:bar") .resolve("C:\\bar", "C:\\bar") .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar") - .resolve("\\bar", "\\bar"); + .resolve("\\bar", "\\bar") + .resolve("", "\\foo"); test("foo") .resolve("bar", "foo\\bar") .resolve("D:\\bar", "D:\\bar") .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar") .resolve("C:bar", "C:bar") - .resolve("D:foo", "D:foo"); + .resolve("D:foo", "D:foo") + .resolve("", "foo"); test("C:") - .resolve("foo", "C:foo"); + .resolve("foo", "C:foo") + .resolve("", "C:"); test("\\\\server\\share\\foo") .resolve("bar", "\\\\server\\share\\foo\\bar") .resolve("\\bar", "\\\\server\\share\\bar") .resolve("D:\\bar", "D:\\bar") .resolve("\\\\other\\share\\bar", "\\\\other\\share\\bar") - .resolve("D:bar", "D:bar"); + .resolve("D:bar", "D:bar") + .resolve("", "\\\\server\\share\\foo"); + test("") + .resolve("", "") + .resolve("foo", "foo") + .resolve("C:\\", "C:\\") + .resolve("C:foo", "C:foo") + .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar"); + + // resolveSibling + test("foo") + .resolveSibling("bar", "bar") + .resolveSibling("D:\\bar", "D:\\bar") + .resolveSibling("\\\\server\\share\\bar", "\\\\server\\share\\bar") + .resolveSibling("C:bar", "C:bar") + .resolveSibling("D:foo", "D:foo") + .resolveSibling("", ""); + test("foo\\bar") + .resolveSibling("gus", "foo\\gus") + .resolveSibling("D:\\bar", "D:\\bar") + .resolveSibling("\\\\server\\share\\bar", "\\\\server\\share\\bar") + .resolveSibling("C:bar", "C:bar") + .resolveSibling("D:foo", "D:foo") + .resolveSibling("", "foo"); + test("C:\\foo") + .resolveSibling("gus", "C:\\gus") + .resolveSibling("D:\\bar", "D:\\bar") + .resolveSibling("\\\\server\\share\\bar", "\\\\server\\share\\bar") + .resolveSibling("C:bar", "C:\\bar") + .resolveSibling("D:foo", "D:foo") + .resolveSibling("", "C:\\"); + test("C:\\foo\\bar") + .resolveSibling("gus", "C:\\foo\\gus") + .resolveSibling("D:\\bar", "D:\\bar") + .resolveSibling("\\\\server\\share\\bar", "\\\\server\\share\\bar") + .resolveSibling("C:bar", "C:\\foo\\bar") + .resolveSibling("D:foo", "D:foo") + .resolveSibling("", "C:\\foo"); + test("\\\\server\\share\\foo") + .resolveSibling("bar", "\\\\server\\share\\bar") + .resolveSibling("\\bar", "\\\\server\\share\\bar") + .resolveSibling("D:\\bar", "D:\\bar") + .resolveSibling("\\\\other\\share\\bar", "\\\\other\\share\\bar") + .resolveSibling("D:bar", "D:bar") + .resolveSibling("", "\\\\server\\share\\"); + test("") + .resolveSibling("", "") + .resolveSibling("foo", "foo") + .resolveSibling("C:\\", "C:\\"); // relativize test("foo\\bar") - .relativize("foo\\bar", null) + .relativize("foo\\bar", "") .relativize("foo", ".."); test("C:\\a\\b\\c") - .relativize("C:\\a", "..\\.."); + .relativize("C:\\a", "..\\..") + .relativize("C:\\a\\b\\c", ""); test("\\\\server\\share\\foo") - .relativize("\\\\server\\share\\bar", "..\\bar"); + .relativize("\\\\server\\share\\bar", "..\\bar") + .relativize("\\\\server\\share\\foo", ""); + test("") + .relativize("", ""); // normalize test("C:\\") @@ -436,7 +548,7 @@ public class PathOps { test("foo\\.") .normalize("foo"); test("foo\\..") - .normalize(null); + .normalize(""); test("C:\\foo") .normalize("C:\\foo"); test("C:\\foo\\.") @@ -478,7 +590,7 @@ public class PathOps { test("\\..\\foo") .normalize("\\foo"); test(".") - .normalize(null); + .normalize(""); test("..") .normalize(".."); test("\\..\\..") @@ -493,6 +605,8 @@ public class PathOps { .normalize("foo"); test(".\\foo\\.\\bar\\.\\gus\\..\\.\\..") .normalize("foo"); + test("") + .normalize(""); // UNC corner cases test("\\\\server\\share\\") @@ -557,6 +671,26 @@ public class PathOps { static void doUnixTests() { header("Unix specific tests"); + // construction + test("/") + .string("/"); + test("/", "") + .string("/"); + test("/", "foo") + .string("/foo"); + test("/", "/foo") + .string("/foo"); + test("/", "foo/") + .string("/foo"); + test("foo", "bar", "gus") + .string("foo/bar/gus"); + test("") + .string(""); + test("", "/") + .string("/"); + test("", "foo", "", "bar", "", "/gus") + .string("foo/bar/gus"); + // all components test("/a/b/c") .root("/") @@ -580,10 +714,15 @@ public class PathOps { .root(null) .parent(null) .name("foo"); + test("") + .root(null) + .parent(null) + .name(""); // startsWith test("/") .starts("/") + .notStarts("") .notStarts("/foo"); test("/foo") .starts("/") @@ -598,6 +737,7 @@ public class PathOps { .notStarts("foo/bar"); test("foo") .starts("foo") + .notStarts("") .notStarts("f"); test("foo/bar") .starts("foo") @@ -605,10 +745,14 @@ public class PathOps { .notStarts("f") .notStarts("/foo") .notStarts("/foo/bar"); + test("") + .starts("") + .notStarts("/"); // endsWith test("/") .ends("/") + .notEnds("") .notEnds("foo") .notEnds("/foo"); test("/foo") @@ -625,6 +769,7 @@ public class PathOps { .notEnds("o/bar"); test("foo") .ends("foo") + .notEnds("") .notEnds("oo") .notEnds("oola"); test("foo/bar") @@ -642,12 +787,47 @@ public class PathOps { .notEnds("r/gus") .notEnds("barack/gus") .notEnds("bar/gust"); + test("") + .ends("") + .notEnds("/"); // elements test("a/b/c") - .element(0,"a") - .element(1,"b") - .element(2,"c"); + .element(0, "a") + .element(1, "b") + .element(2, "c"); + test("") + .element(0, ""); + + // subpath + test("/foo") + .subpath(0, 1, "foo"); + test("foo") + .subpath(0, 1, "foo"); + test("/foo/bar") + .subpath(0, 1, "foo") + .subpath(1, 2, "bar") + .subpath(0, 2, "foo/bar"); + test("foo/bar") + .subpath(0, 1, "foo") + .subpath(1, 2, "bar") + .subpath(0, 2, "foo/bar"); + test("/foo/bar/gus") + .subpath(0, 1, "foo") + .subpath(1, 2, "bar") + .subpath(2, 3, "gus") + .subpath(0, 2, "foo/bar") + .subpath(1, 3, "bar/gus") + .subpath(0, 3, "foo/bar/gus"); + test("foo/bar/gus") + .subpath(0, 1, "foo") + .subpath(1, 2, "bar") + .subpath(2, 3, "gus") + .subpath(0, 2, "foo/bar") + .subpath(1, 3, "bar/gus") + .subpath(0, 3, "foo/bar/gus"); + test("") + .subpath(0, 1, ""); // isAbsolute test("/") @@ -656,20 +836,61 @@ public class PathOps { .absolute(); test("tmp") .notAbsolute(); + test("") + .notAbsolute(); + // resolve test("/tmp") .resolve("foo", "/tmp/foo") - .resolve("/foo", "/foo"); + .resolve("/foo", "/foo") + .resolve("", "/tmp"); test("tmp") .resolve("foo", "tmp/foo") + .resolve("/foo", "/foo") + .resolve("", "tmp"); + test("") + .resolve("", "") + .resolve("foo", "foo") .resolve("/foo", "/foo"); + // resolveSibling + test("foo") + .resolveSibling("bar", "bar") + .resolveSibling("/bar", "/bar") + .resolveSibling("", ""); + test("foo/bar") + .resolveSibling("gus", "foo/gus") + .resolveSibling("/gus", "/gus") + .resolveSibling("", "foo"); + test("/foo") + .resolveSibling("gus", "/gus") + .resolveSibling("/gus", "/gus") + .resolveSibling("", "/"); + test("/foo/bar") + .resolveSibling("gus", "/foo/gus") + .resolveSibling("/gus", "/gus") + .resolveSibling("", "/foo"); + test("") + .resolveSibling("foo", "foo") + .resolveSibling("/foo", "/foo") + .resolve("", ""); + // relativize test("/a/b/c") - .relativize("/a/b/c", null) + .relativize("/a/b/c", "") .relativize("/a/b/c/d/e", "d/e") - .relativize("/a/x", "../../x"); + .relativize("/a/x", "../../x") + .relativize("/x", "../../../x"); + test("a/b/c") + .relativize("a/b/c/d", "d") + .relativize("a/x", "../../x") + .relativize("x", "../../../x") + .relativize("", "../../.."); + test("") + .relativize("a", "a") + .relativize("a/b/c", "a/b/c") + .relativize("", ""); // normalize test("/") @@ -679,7 +900,7 @@ public class PathOps { test("/foo") .normalize("/foo"); test(".") - .normalize(null); + .normalize(""); test("..") .normalize(".."); test("/..") @@ -691,7 +912,7 @@ public class PathOps { test("./foo") .normalize("foo"); test("foo/..") - .normalize(null); + .normalize(""); test("../foo") .normalize("../foo"); test("../../foo") @@ -717,7 +938,7 @@ public class PathOps { test("//bar\u0000") .invalid(); - // normalization + // normalization of input test("//foo//bar") .string("/foo/bar") .root("/") @@ -749,13 +970,13 @@ public class PathOps { } try { - path.startsWith(null); + path.startsWith((Path)null); throw new RuntimeException("NullPointerException not thrown"); } catch (NullPointerException npe) { } try { - path.endsWith(null); + path.endsWith((Path)null); throw new RuntimeException("NullPointerException not thrown"); } catch (NullPointerException npe) { } diff --git a/jdk/test/java/nio/file/Path/TemporaryFiles.java b/jdk/test/java/nio/file/Path/TemporaryFiles.java deleted file mode 100644 index e7603bf630e..00000000000 --- a/jdk/test/java/nio/file/Path/TemporaryFiles.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * @bug 4313887 6838333 - * @summary Unit test for File.createTemporaryXXX (to be be moved to test/java/io/File) - * @library .. - */ - -import java.nio.file.*; -import static java.nio.file.StandardOpenOption.*; -import java.nio.file.attribute.*; -import java.io.File; -import java.io.IOException; -import java.util.Set; - -public class TemporaryFiles { - - static void checkInTempDirectory(Path file) { - Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir")); - if (!file.getParent().equals(tmpdir)) - throw new RuntimeException("Not in temporary directory"); - } - - static void checkFile(Path file) throws IOException { - // check file is in temporary directory - checkInTempDirectory(file); - - // check that file can be opened for reading and writing - file.newByteChannel(READ).close(); - file.newByteChannel(WRITE).close(); - file.newByteChannel(READ,WRITE).close(); - - // check file permissions are 0600 or more secure - if (file.getFileStore().supportsFileAttributeView("posix")) { - Set perms = Attributes - .readPosixFileAttributes(file).permissions(); - perms.remove(PosixFilePermission.OWNER_READ); - perms.remove(PosixFilePermission.OWNER_WRITE); - if (!perms.isEmpty()) - throw new RuntimeException("Temporary file is not secure"); - } - } - - static void checkDirectory(Path dir) throws IOException { - // check directory is in temporary directory - checkInTempDirectory(dir); - - // check directory is empty - DirectoryStream stream = dir.newDirectoryStream(); - try { - if (stream.iterator().hasNext()) - throw new RuntimeException("Tempory directory not empty"); - } finally { - stream.close(); - } - - // check file permissions are 0700 or more secure - if (dir.getFileStore().supportsFileAttributeView("posix")) { - Set perms = Attributes - .readPosixFileAttributes(dir).permissions(); - perms.remove(PosixFilePermission.OWNER_READ); - perms.remove(PosixFilePermission.OWNER_WRITE); - perms.remove(PosixFilePermission.OWNER_EXECUTE); - if (!perms.isEmpty()) - throw new RuntimeException("Temporary directory is not secure"); - } - } - - public static void main(String[] args) throws IOException { - Path file = File.createTemporaryFile("blah", null).toPath(); - try { - checkFile(file); - } finally { - TestUtil.deleteUnchecked(file); - } - } -} diff --git a/jdk/test/java/nio/file/Path/UriImportExport.java b/jdk/test/java/nio/file/Path/UriImportExport.java index c6a9dbf23f4..1db4d85d19e 100644 --- a/jdk/test/java/nio/file/Path/UriImportExport.java +++ b/jdk/test/java/nio/file/Path/UriImportExport.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 7003155 * @summary Unit test for java.nio.file.Path */ @@ -36,42 +36,105 @@ public class UriImportExport { static final PrintStream log = System.out; static int failures = 0; - static void test(String fn, String expected) { + /** + * Test Path -> URI -> Path + */ + static void testPath(String s) { + Path path = Paths.get(s); + log.println(path); + URI uri = path.toUri(); + log.println(" --> " + uri); + Path result = Paths.get(uri); + log.println(" --> " + result); + if (!result.equals(path.toAbsolutePath())) { + log.println("FAIL: Expected " + path + ", got " + result); + failures++; + } log.println(); - Path p = Paths.get(fn); - log.println(p); - URI u = p.toUri(); - log.println(" --> " + u); - if (expected != null && !(u.toString().equals(expected))) { - log.println("FAIL: Expected " + expected); - failures++; - return; - } - Path q = Paths.get(u); - log.println(" --> " + q); - if (!p.toAbsolutePath().equals(q)) { - log.println("FAIL: Expected " + p + ", got " + q); - failures++; - return; - } } - static void test(String fn) { - test(fn, null); + /** + * Test Path -> (expected) URI -> Path + */ + static void testPath(String s, String expectedUri) { + Path path = Paths.get(s); + log.println(path); + URI uri = path.toUri(); + log.println(" --> " + uri); + if (!uri.toString().equals(expectedUri)) { + log.println("FAILED: Expected " + expectedUri + ", got " + uri); + failures++; + return; + } + Path result = Paths.get(uri); + log.println(" --> " + result); + if (!result.equals(path.toAbsolutePath())) { + log.println("FAIL: Expected " + path + ", got " + result); + failures++; + } + log.println(); + } + + /** + * Test URI -> Path -> URI + */ + static void testUri(String s) throws Exception { + URI uri = URI.create(s); + log.println(uri); + Path path = Paths.get(uri); + log.println(" --> " + path); + URI result = path.toUri(); + log.println(" --> " + result); + if (!result.equals(uri)) { + log.println("FAIL: Expected " + uri + ", got " + result); + failures++; + } + log.println(); + } + + /** + * Test URI -> Path fails with IllegalArgumentException + */ + static void testBadUri(String s) throws Exception { + URI uri = URI.create(s); + log.println(uri); + try { + Path path = Paths.get(uri); + log.format(" --> %s FAIL: Expected IllegalArgumentException\n", path); + failures++; + } catch (IllegalArgumentException expected) { + log.println(" --> IllegalArgumentException (expected)"); + } + log.println(); } public static void main(String[] args) throws Exception { - test("foo"); - test("/foo"); - test("/foo bar"); + testBadUri("file:foo"); + testBadUri("file:/foo?q"); + testBadUri("file:/foo#f"); String osname = System.getProperty("os.name"); if (osname.startsWith("Windows")) { - test("C:\\foo"); - test("C:foo"); - test("\\\\rialto.dublin.com\\share\\"); - test("\\\\fe80--203-baff-fe5a-749ds1.ipv6-literal.net\\share\\missing", + testPath("C:\\doesnotexist"); + testPath("C:doesnotexist"); + testPath("\\\\server.nowhere.oracle.com\\share\\"); + testPath("\\\\fe80--203-baff-fe5a-749ds1.ipv6-literal.net\\share\\missing", "file://[fe80::203:baff:fe5a:749d%1]/share/missing"); + } else { + testPath("doesnotexist"); + testPath("/doesnotexist"); + testPath("/does not exist"); + testUri("file:///"); + testUri("file:///foo/bar/doesnotexist"); + testUri("file:/foo/bar/doesnotexist"); + + // file:///foo/bar/\u0440\u0443\u0441\u0441\u043A\u0438\u0439 (Russian) + testUri("file:///foo/bar/%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9"); + + // invalid + testBadUri("file:foo"); + testBadUri("file://server/foo"); + testBadUri("file:///foo%00"); } if (failures > 0) diff --git a/jdk/test/java/nio/file/TestUtil.java b/jdk/test/java/nio/file/TestUtil.java index b0fdd2a1f9d..f77d8f1adb3 100644 --- a/jdk/test/java/nio/file/TestUtil.java +++ b/jdk/test/java/nio/file/TestUtil.java @@ -31,17 +31,12 @@ public class TestUtil { } static Path createTemporaryDirectory(String where) throws IOException { - Path top = FileSystems.getDefault().getPath(where); - Random r = new Random(); - Path dir; - do { - dir = top.resolve("name" + r.nextInt()); - } while (dir.exists()); - return dir.createDirectory(); + Path dir = FileSystems.getDefault().getPath(where); + return Files.createTempDirectory(dir, "name"); } static Path createTemporaryDirectory() throws IOException { - return createTemporaryDirectory(System.getProperty("java.io.tmpdir")); + return Files.createTempDirectory("name"); } static void removeAll(Path dir) throws IOException { @@ -53,7 +48,7 @@ public class TestUtil { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { try { - file.delete(); + Files.delete(file); } catch (IOException x) { System.err.format("Unable to delete %s: %s\n", file, x); } @@ -62,7 +57,7 @@ public class TestUtil { @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) { try { - dir.delete(); + Files.delete(dir); } catch (IOException x) { System.err.format("Unable to delete %s: %s\n", dir, x); } @@ -78,7 +73,7 @@ public class TestUtil { static void deleteUnchecked(Path file) { try { - file.delete(); + Files.delete(file); } catch (IOException exc) { System.err.format("Unable to delete %s: %s\n", file, exc); } @@ -99,7 +94,7 @@ public class TestUtil { String name = sb.toString(); do { dir = dir.resolve(name).resolve("."); - dir.createDirectory(); + Files.createDirectory(dir); } while (dir.toString().length() < 2048); return dir; } @@ -111,8 +106,8 @@ public class TestUtil { Path link = dir.resolve("testlink"); Path target = dir.resolve("testtarget"); try { - link.createSymbolicLink(target); - link.delete(); + Files.createSymbolicLink(link, target); + Files.delete(link); return true; } catch (UnsupportedOperationException x) { return false; diff --git a/jdk/test/java/nio/file/WatchService/Basic.java b/jdk/test/java/nio/file/WatchService/Basic.java index 104781410ae..2869a519f37 100644 --- a/jdk/test/java/nio/file/WatchService/Basic.java +++ b/jdk/test/java/nio/file/WatchService/Basic.java @@ -41,8 +41,9 @@ import java.util.concurrent.TimeUnit; public class Basic { - static void createFile(Path file) throws IOException { - file.newOutputStream().close(); + static void checkKey(WatchKey key, Path dir) { + if (!key.isValid()) + throw new RuntimeException("Key is not valid"); } static void takeExpectedKey(WatchService watcher, WatchKey expected) { @@ -80,19 +81,19 @@ public class Basic { FileSystem fs = FileSystems.getDefault(); Path name = fs.getPath("foo"); - WatchService watcher = fs.newWatchService(); - try { + try (WatchService watcher = fs.newWatchService()) { // --- ENTRY_CREATE --- // register for event System.out.format("register %s for ENTRY_CREATE\n", dir); WatchKey myKey = dir.register(watcher, new WatchEvent.Kind[]{ ENTRY_CREATE }); + checkKey(myKey, dir); // create file Path file = dir.resolve("foo"); System.out.format("create %s\n", file); - createFile(file); + Files.createFile(file); // remove key and check that we got the ENTRY_CREATE event takeExpectedKey(watcher, myKey); @@ -112,9 +113,10 @@ public class Basic { new WatchEvent.Kind[]{ ENTRY_DELETE }); if (deleteKey != myKey) throw new RuntimeException("register did not return existing key"); + checkKey(deleteKey, dir); System.out.format("delete %s\n", file); - file.delete(); + Files.delete(file); takeExpectedKey(watcher, myKey); checkExpectedEvent(myKey.pollEvents(), StandardWatchEventKind.ENTRY_DELETE, name); @@ -126,7 +128,7 @@ public class Basic { System.out.println("OKAY"); // create the file for the next test - createFile(file); + Files.createFile(file); // --- ENTRY_MODIFY --- @@ -135,13 +137,11 @@ public class Basic { new WatchEvent.Kind[]{ ENTRY_MODIFY }); if (newKey != myKey) throw new RuntimeException("register did not return existing key"); + checkKey(newKey, dir); System.out.format("update: %s\n", file); - OutputStream out = file.newOutputStream(StandardOpenOption.APPEND); - try { + try (OutputStream out = Files.newOutputStream(file, StandardOpenOption.APPEND)) { out.write("I am a small file".getBytes("UTF-8")); - } finally { - out.close(); } // remove key and check that we got the ENTRY_MODIFY event @@ -151,10 +151,7 @@ public class Basic { System.out.println("OKAY"); // done - file.delete(); - - } finally { - watcher.close(); + Files.delete(file); } } @@ -164,12 +161,12 @@ public class Basic { static void testCancel(Path dir) throws IOException { System.out.println("-- Cancel --"); - WatchService watcher = FileSystems.getDefault().newWatchService(); - try { + try (WatchService watcher = FileSystems.getDefault().newWatchService()) { System.out.format("register %s for events\n", dir); WatchKey myKey = dir.register(watcher, new WatchEvent.Kind[]{ ENTRY_CREATE }); + checkKey(myKey, dir); System.out.println("cancel key"); myKey.cancel(); @@ -177,7 +174,7 @@ public class Basic { // create a file in the directory Path file = dir.resolve("mars"); System.out.format("create: %s\n", file); - createFile(file); + Files.createFile(file); // poll for keys - there will be none System.out.println("poll..."); @@ -190,12 +187,9 @@ public class Basic { } // done - file.delete(); + Files.delete(file); System.out.println("OKAY"); - - } finally { - watcher.close(); } } @@ -206,17 +200,16 @@ public class Basic { static void testAutomaticCancel(Path dir) throws IOException { System.out.println("-- Automatic Cancel --"); - Path subdir = dir.resolve("bar").createDirectory(); + Path subdir = Files.createDirectory(dir.resolve("bar")); - WatchService watcher = FileSystems.getDefault().newWatchService(); - try { + try (WatchService watcher = FileSystems.getDefault().newWatchService()) { System.out.format("register %s for events\n", subdir); WatchKey myKey = subdir.register(watcher, new WatchEvent.Kind[]{ ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY }); System.out.format("delete: %s\n", subdir); - subdir.delete(); + Files.delete(subdir); takeExpectedKey(watcher, myKey); System.out.println("reset key"); @@ -227,8 +220,6 @@ public class Basic { System.out.println("OKAY"); - } finally { - watcher.close(); } } @@ -411,7 +402,7 @@ public class Basic { // create gus1 Path file1 = dir.resolve(name1); System.out.format("create %s\n", file1); - createFile(file1); + Files.createFile(file1); // register with both watch services (different events) System.out.println("register for different events"); @@ -426,7 +417,7 @@ public class Basic { // create gus2 Path file2 = dir.resolve(name2); System.out.format("create %s\n", file2); - createFile(file2); + Files.createFile(file2); // check that key1 got ENTRY_CREATE takeExpectedKey(watcher1, key1); @@ -439,7 +430,7 @@ public class Basic { throw new RuntimeException("key not expected"); // delete gus1 - file1.delete(); + Files.delete(file1); // check that key2 got ENTRY_DELETE takeExpectedKey(watcher2, key2); @@ -462,7 +453,7 @@ public class Basic { // create file and key2 should be queued System.out.format("create %s\n", file1); - createFile(file1); + Files.createFile(file1); takeExpectedKey(watcher2, key2); checkExpectedEvent(key2.pollEvents(), StandardWatchEventKind.ENTRY_CREATE, name1); diff --git a/jdk/test/java/nio/file/WatchService/FileTreeModifier.java b/jdk/test/java/nio/file/WatchService/FileTreeModifier.java index 01db8b97a40..cde17db1124 100644 --- a/jdk/test/java/nio/file/WatchService/FileTreeModifier.java +++ b/jdk/test/java/nio/file/WatchService/FileTreeModifier.java @@ -62,10 +62,7 @@ public class FileTreeModifier { WatchService watcher = fs.newWatchService(); // create directories - Path subdir = top - .resolve("a").createDirectory() - .resolve("b").createDirectory() - .resolve("c").createDirectory(); + Path subdir = Files.createDirectories(top.resolve("a").resolve("b").resolve("c")); // Test ENTRY_CREATE with FILE_TREE modifier. @@ -73,7 +70,7 @@ public class FileTreeModifier { new WatchEvent.Kind[]{ ENTRY_CREATE }, FILE_TREE); // create file in a/b/c and check we get create event - Path file = subdir.resolve("foo").createFile(); + Path file = Files.createFile(subdir.resolve("foo")); checkExpectedEvent(watcher, ENTRY_CREATE, top.relativize(file)); key.reset(); @@ -85,7 +82,7 @@ public class FileTreeModifier { throw new RuntimeException("Existing key not returned"); // delete a/b/c/foo and check we get delete event - file.delete(); + Files.delete(file); checkExpectedEvent(watcher, ENTRY_DELETE, top.relativize(file)); key.reset(); @@ -96,19 +93,20 @@ public class FileTreeModifier { throw new RuntimeException("Existing key not returned"); // create a/b/c/foo - file.createFile(); + Files.createFile(file); // check that key is not queued + WatchKey nextKey; try { - k = watcher.poll(3, TimeUnit.SECONDS); + nextKey = watcher.poll(3, TimeUnit.SECONDS); } catch (InterruptedException e) { throw new RuntimeException(); } - if (k != null) + if (nextKey != null) throw new RuntimeException("WatchKey not expected to be polled"); // create bar and check we get create event - file = top.resolve("bar").createFile(); + file = Files.createFile(top.resolve("bar")); checkExpectedEvent(watcher, ENTRY_CREATE, top.relativize(file)); key.reset(); @@ -121,11 +119,8 @@ public class FileTreeModifier { throw new RuntimeException("Existing key not returned"); // modify bar and check we get modify event - OutputStream out = file.newOutputStream(); - try { + try (OutputStream out = Files.newOutputStream(file)) { out.write("Double shot expresso please".getBytes("UTF-8")); - } finally { - out.close(); } checkExpectedEvent(watcher, ENTRY_MODIFY, top.relativize(file)); key.reset(); diff --git a/jdk/test/java/nio/file/WatchService/LotsOfEvents.java b/jdk/test/java/nio/file/WatchService/LotsOfEvents.java index c19e7d50a0a..96fb4d81783 100644 --- a/jdk/test/java/nio/file/WatchService/LotsOfEvents.java +++ b/jdk/test/java/nio/file/WatchService/LotsOfEvents.java @@ -55,15 +55,14 @@ public class LotsOfEvents { static void testOverflowEvent(Path dir) throws IOException, InterruptedException { - WatchService watcher = dir.getFileSystem().newWatchService(); - try { + try (WatchService watcher = dir.getFileSystem().newWatchService()) { dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE); // create a lot of files int n = 1024; Path[] files = new Path[n]; for (int i=0; i modified = new HashSet(); + Set modified = new HashSet<>(); for (WatchEvent event: key.pollEvents()) { WatchEvent.Kind kind = event.kind(); Path file = (kind == OVERFLOW) ? null : (Path)event.context(); @@ -188,9 +184,6 @@ public class LotsOfEvents { key = watcher.poll(2, TimeUnit.SECONDS); } } - - } finally { - watcher.close(); } } @@ -200,20 +193,17 @@ public class LotsOfEvents { this.file = file; } void create() throws IOException { - if (file.notExists()) - file.createFile(); + if (Files.notExists(file)) + Files.createFile(file); } void deleteIfExists() throws IOException { - file.deleteIfExists(); + Files.deleteIfExists(file); } void modifyIfExists() throws IOException { - if (file.exists()) { - OutputStream out = file.newOutputStream(StandardOpenOption.APPEND); - try { + if (Files.exists(file)) { + try (OutputStream out = Files.newOutputStream(file, StandardOpenOption.APPEND)) { out.write("message".getBytes()); - } finally { - out.close(); } } } diff --git a/jdk/test/java/nio/file/WatchService/SensitivityModifier.java b/jdk/test/java/nio/file/WatchService/SensitivityModifier.java index 63b26f9d51f..47ff2b69bcf 100644 --- a/jdk/test/java/nio/file/WatchService/SensitivityModifier.java +++ b/jdk/test/java/nio/file/WatchService/SensitivityModifier.java @@ -51,6 +51,7 @@ public class SensitivityModifier { } } + @SuppressWarnings("unchecked") static void doTest(Path top) throws Exception { FileSystem fs = top.getFileSystem(); WatchService watcher = fs.newWatchService(); @@ -61,11 +62,11 @@ public class SensitivityModifier { Path[] dirs = new Path[nDirs]; Path[] files = new Path[nFiles]; for (int i=0; i)event).context(); - if (!name.equals(file.getName())) + if (!name.equals(file.getFileName())) throw new RuntimeException("Unexpected context: " + name); System.out.println("Event OK"); diff --git a/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java index 03a0e48e783..bc32699cbfa 100644 --- a/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java @@ -47,11 +47,11 @@ public class Basic { // sanity check read and writing ACL static void testReadWrite(Path dir) throws IOException { Path file = dir.resolve("foo"); - if (file.notExists()) - file.createFile(); + if (Files.notExists(file)) + Files.createFile(file); - AclFileAttributeView view = file - .getFileAttributeView(AclFileAttributeView.class); + AclFileAttributeView view = + Files.getFileAttributeView(file, AclFileAttributeView.class); // print existing ACL List acl = view.getAcl(); @@ -79,7 +79,7 @@ public class Basic { } // if PosixFileAttributeView then repeat test with OWNER@ - if (file.getFileStore().supportsFileAttributeView("posix")) { + if (Files.getFileStore(file).supportsFileAttributeView("posix")) { owner = file.getFileSystem().getUserPrincipalLookupService() .lookupPrincipalByName("OWNER@"); entry = AclEntry.newBuilder(entry).setPrincipal(owner).build(); @@ -115,7 +115,8 @@ public class Basic { // sanity check create a file or directory with initial ACL static void testCreateFile(Path dir) throws IOException { - UserPrincipal user = Attributes.getOwner(dir); + UserPrincipal user = Files.getOwner(dir); + AclFileAttributeView view; // create file with initial ACL System.out.println("-- create file with initial ACL --"); @@ -127,8 +128,9 @@ public class Basic { .setPermissions(SYNCHRONIZE, READ_DATA, WRITE_DATA, READ_ATTRIBUTES, READ_ACL, WRITE_ATTRIBUTES, DELETE) .build()); - file.createFile(asAclAttribute(fileAcl)); - assertEquals(Attributes.getAcl(file), fileAcl); + Files.createFile(file, asAclAttribute(fileAcl)); + view = Files.getFileAttributeView(file, AclFileAttributeView.class); + assertEquals(view.getAcl(), fileAcl); // create directory with initial ACL System.out.println("-- create directory with initial ACL --"); @@ -142,17 +144,18 @@ public class Basic { AclEntry.newBuilder(fileAcl.get(0)) .setFlags(FILE_INHERIT) .build()); - subdir.createDirectory(asAclAttribute(dirAcl)); - assertEquals(Attributes.getAcl(subdir), dirAcl); + Files.createDirectory(subdir, asAclAttribute(dirAcl)); + view = Files.getFileAttributeView(subdir, AclFileAttributeView.class); + assertEquals(view.getAcl(), dirAcl); } public static void main(String[] args) throws IOException { // use work directory rather than system temporary directory to // improve chances that ACLs are supported - Path dir = Paths.get("./work" + new Random().nextInt()) - .createDirectory(); + Path dir = Paths.get("./work" + new Random().nextInt()); + Files.createDirectory(dir); try { - if (!dir.getFileStore().supportsFileAttributeView("acl")) { + if (!Files.getFileStore(dir).supportsFileAttributeView("acl")) { System.out.println("ACLs not supported - test skipped!"); return; } diff --git a/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java index c2cb23a4ff6..794a42c1c46 100644 --- a/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java @@ -43,7 +43,7 @@ public class Basic { static void checkAttributesOfDirectory(Path dir) throws IOException { - BasicFileAttributes attrs = Attributes.readBasicFileAttributes(dir); + BasicFileAttributes attrs = Files.readAttributes(dir, BasicFileAttributes.class); check(attrs.isDirectory(), "is a directory"); check(!attrs.isRegularFile(), "is not a regular file"); check(!attrs.isSymbolicLink(), "is not a link"); @@ -58,7 +58,7 @@ public class Basic { static void checkAttributesOfFile(Path dir, Path file) throws IOException { - BasicFileAttributes attrs = Attributes.readBasicFileAttributes(file); + BasicFileAttributes attrs = Files.readAttributes(file, BasicFileAttributes.class); check(attrs.isRegularFile(), "is a regular file"); check(!attrs.isDirectory(), "is not a directory"); check(!attrs.isSymbolicLink(), "is not a link"); @@ -73,8 +73,8 @@ public class Basic { // copy last-modified time and file create time from directory to file, // re-read attribtues, and check they match BasicFileAttributeView view = - file.getFileAttributeView(BasicFileAttributeView.class); - BasicFileAttributes dirAttrs = Attributes.readBasicFileAttributes(dir); + Files.getFileAttributeView(file, BasicFileAttributeView.class); + BasicFileAttributes dirAttrs = Files.readAttributes(dir, BasicFileAttributes.class); view.setTimes(dirAttrs.lastModifiedTime(), null, null); if (dirAttrs.creationTime() != null) { view.setTimes(null, null, dirAttrs.creationTime()); @@ -95,8 +95,8 @@ public class Basic { static void checkAttributesOfLink(Path link) throws IOException { - BasicFileAttributes attrs = Attributes - .readBasicFileAttributes(link, LinkOption.NOFOLLOW_LINKS); + BasicFileAttributes attrs = + Files.readAttributes(link, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS); check(attrs.isSymbolicLink(), "is a link"); check(!attrs.isDirectory(), "is a directory"); check(!attrs.isRegularFile(), "is not a regular file"); @@ -108,11 +108,8 @@ public class Basic { { // create file Path file = dir.resolve("foo"); - OutputStream out = file.newOutputStream(); - try { + try (OutputStream out = Files.newOutputStream(file)) { out.write("this is not an empty file".getBytes("UTF-8")); - } finally { - out.close(); } // check attributes of directory and file @@ -122,7 +119,7 @@ public class Basic { // symbolic links may be supported Path link = dir.resolve("link"); try { - link.createSymbolicLink( file ); + Files.createSymbolicLink(link, file); } catch (UnsupportedOperationException x) { return; } catch (IOException x) { diff --git a/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java index bac02d22dfc..702c95050cc 100644 --- a/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java @@ -74,27 +74,25 @@ public class Basic { static void readWriteTests(Path dir) throws IOException { // create "foo" and test that we can read/write each FAT attribute - Path file = dir.resolve("foo"); - file.createFile(); + Path file = Files.createFile(dir.resolve("foo")); try { - testAttributes(file - .getFileAttributeView(DosFileAttributeView.class)); + testAttributes(Files.getFileAttributeView(file, DosFileAttributeView.class)); // Following tests use a symbolic link so skip if not supported if (!TestUtil.supportsLinks(dir)) return; - Path link = dir.resolve("link").createSymbolicLink(file); + Path link = dir.resolve("link"); + Files.createSymbolicLink(link, file); // test following links - testAttributes(link - .getFileAttributeView(DosFileAttributeView.class)); + testAttributes(Files.getFileAttributeView(link, DosFileAttributeView.class)); // test not following links try { try { - testAttributes(link - .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS)); + testAttributes(Files + .getFileAttributeView(link, DosFileAttributeView.class, NOFOLLOW_LINKS)); } catch (IOException x) { // access to link attributes not supported return; @@ -103,32 +101,32 @@ public class Basic { // set all attributes on link // run test on target of link (which leaves them all un-set) // check that attributes of link remain all set - setAll(link - .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS), true); - testAttributes(link - .getFileAttributeView(DosFileAttributeView.class)); - DosFileAttributes attrs = Attributes.readDosFileAttributes(link, NOFOLLOW_LINKS); + setAll(Files + .getFileAttributeView(link, DosFileAttributeView.class, NOFOLLOW_LINKS), true); + testAttributes(Files + .getFileAttributeView(link, DosFileAttributeView.class)); + DosFileAttributes attrs = + Files.getFileAttributeView(link, DosFileAttributeView.class, NOFOLLOW_LINKS) + .readAttributes(); check(attrs.isReadOnly()); check(attrs.isHidden()); check(attrs.isArchive()); check(attrs.isSystem()); - setAll(link - .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS), false); + setAll(Files + .getFileAttributeView(link, DosFileAttributeView.class, NOFOLLOW_LINKS), false); // set all attributes on target // run test on link (which leaves them all un-set) // check that attributes of target remain all set - setAll(link - .getFileAttributeView(DosFileAttributeView.class), true); - testAttributes(link - .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS)); - attrs = Attributes.readDosFileAttributes(link); + setAll(Files.getFileAttributeView(link, DosFileAttributeView.class), true); + testAttributes(Files + .getFileAttributeView(link, DosFileAttributeView.class, NOFOLLOW_LINKS)); + attrs = Files.getFileAttributeView(link, DosFileAttributeView.class).readAttributes(); check(attrs.isReadOnly()); check(attrs.isHidden()); check(attrs.isArchive()); check(attrs.isSystem()); - setAll(link - .getFileAttributeView(DosFileAttributeView.class), false); + setAll(Files.getFileAttributeView(link, DosFileAttributeView.class), false); } finally { TestUtil.deleteUnchecked(link); } @@ -143,7 +141,7 @@ public class Basic { try { // skip test if DOS file attributes not supported - if (!dir.getFileStore().supportsFileAttributeView("dos")) { + if (!Files.getFileStore(dir).supportsFileAttributeView("dos")) { System.out.println("DOS file attribute not supported."); return; } diff --git a/jdk/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java deleted file mode 100644 index 8307bac54bb..00000000000 --- a/jdk/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * @bug 4313887 6838333 - * @summary Unit test for java.nio.file.attribute.FileStoreAttributeView - * @library ../.. - */ - -import java.nio.file.*; -import java.nio.file.attribute.*; -import java.io.File; -import java.io.IOException; -import java.util.*; - -/** - * Simple unit test for FileStoreAttributeView that checks that the disk space - * attribtues are "close" to the equivalent values reported by java.io.File. - */ - -public class Basic { - - static final long K = 1024L; - static final long G = 1024L * 1024L * 1024L; - - /** - * Print out the disk space information for the given file system - */ - static void printFileStore(FileStore fs) throws IOException { - FileStoreSpaceAttributeView view = - fs.getFileStoreAttributeView(FileStoreSpaceAttributeView.class); - FileStoreSpaceAttributes attrs = view.readAttributes(); - - long total = attrs.totalSpace() / K; - long used = (attrs.totalSpace() - attrs.unallocatedSpace()) / K; - long avail = attrs.usableSpace() / K; - - String s = fs.toString(); - if (s.length() > 20) { - System.out.println(s); - s = ""; - } - System.out.format("%-20s %12d %12d %12d\n", s, total, used, avail); - } - - /** - * Check that two values are within 1GB of each other - */ - static void checkWithin1GB(long value1, long value2) { - long diff = Math.abs(value1 - value2); - if (diff > G) - throw new RuntimeException("values differ by more than 1GB"); - } - - /** - * Check disk space on the file system of the given file - */ - static void checkSpace(Path file) throws IOException { - System.out.println(" -- check space -- "); - System.out.println(file); - - FileStore fs = file.getFileStore(); - System.out.format("Filesystem: %s\n", fs); - - // get values reported by java.io.File - File f = new File(file.toString()); - long total = f.getTotalSpace(); - long free = f.getFreeSpace(); - long usable = f.getUsableSpace(); - System.out.println("java.io.File"); - System.out.format(" Total: %d\n", total); - System.out.format(" Free: %d\n", free); - System.out.format(" Usable: %d\n", usable); - - // get values reported by the FileStoreSpaceAttributeView - FileStoreSpaceAttributes attrs = fs - .getFileStoreAttributeView(FileStoreSpaceAttributeView.class) - .readAttributes(); - System.out.println("java.nio.file.FileStoreSpaceAttributeView:"); - System.out.format(" Total: %d\n", attrs.totalSpace()); - System.out.format(" Free: %d\n", attrs.unallocatedSpace()); - System.out.format(" Usable: %d\n", attrs.usableSpace()); - - // check values are "close" - checkWithin1GB(total, attrs.totalSpace()); - checkWithin1GB(free, attrs.unallocatedSpace()); - checkWithin1GB(usable, attrs.usableSpace()); - - // get values by name - checkWithin1GB(total, (Long)fs.getAttribute("space:totalSpace")); - checkWithin1GB(free, (Long)fs.getAttribute("space:unallocatedSpace")); - checkWithin1GB(usable, (Long)fs.getAttribute("space:usableSpace")); - } - - public static void main(String[] args) throws IOException { - // print out the disk space information for all file systems - FileSystem fs = FileSystems.getDefault(); - for (FileStore store: fs.getFileStores()) { - printFileStore(store); - } - - Path dir = TestUtil.createTemporaryDirectory(); - try { - // check space using directory - checkSpace(dir); - - // check space using file - Path file = dir.resolve("foo").createFile(); - checkSpace(file); - - } finally { - TestUtil.removeAll(dir); - } - } -} diff --git a/jdk/test/java/nio/file/attribute/FileTime/Basic.java b/jdk/test/java/nio/file/attribute/FileTime/Basic.java index 2a79a1a6d7e..f907c00f871 100644 --- a/jdk/test/java/nio/file/attribute/FileTime/Basic.java +++ b/jdk/test/java/nio/file/attribute/FileTime/Basic.java @@ -29,13 +29,16 @@ import java.nio.file.attribute.FileTime; import java.util.concurrent.TimeUnit; import static java.util.concurrent.TimeUnit.*; -import java.io.IOException; +import java.util.Random; public class Basic { - public static void main(String[] args) throws IOException { + static final Random rand = new Random(); + + public static void main(String[] args) { long now = System.currentTimeMillis(); long tomorrowInDays = TimeUnit.DAYS.convert(now, MILLISECONDS) + 1; + long yesterdayInDays = TimeUnit.DAYS.convert(now, MILLISECONDS) - 1; // equals eq(now, MILLISECONDS, now, MILLISECONDS); @@ -50,6 +53,29 @@ public class Basic { cmp(now, MILLISECONDS, now+1234, MILLISECONDS, -1); cmp(tomorrowInDays, DAYS, now, MILLISECONDS, 1); cmp(now, MILLISECONDS, tomorrowInDays, DAYS, -1); + cmp(yesterdayInDays, DAYS, now, MILLISECONDS, -1); + cmp(now, MILLISECONDS, yesterdayInDays, DAYS, 1); + cmp(yesterdayInDays, DAYS, now, MILLISECONDS, -1); + cmp(Long.MAX_VALUE, DAYS, Long.MAX_VALUE, NANOSECONDS, 1); + cmp(Long.MAX_VALUE, DAYS, Long.MIN_VALUE, NANOSECONDS, 1); + cmp(Long.MIN_VALUE, DAYS, Long.MIN_VALUE, NANOSECONDS, -1); + cmp(Long.MIN_VALUE, DAYS, Long.MAX_VALUE, NANOSECONDS, -1); + + // to(TimeUnit) + to(MILLISECONDS.convert(1, DAYS) - 1, MILLISECONDS); + to(MILLISECONDS.convert(1, DAYS) + 0, MILLISECONDS); + to(MILLISECONDS.convert(1, DAYS) + 1, MILLISECONDS); + to(1, MILLISECONDS); + to(0, MILLISECONDS); + to(1, MILLISECONDS); + to(MILLISECONDS.convert(-1, DAYS) - 1, MILLISECONDS); + to(MILLISECONDS.convert(-1, DAYS) + 0, MILLISECONDS); + to(MILLISECONDS.convert(-1, DAYS) + 1, MILLISECONDS); + for (TimeUnit unit: TimeUnit.values()) { + for (int i=0; i<100; i++) { to(rand.nextLong(), unit); } + to(Long.MIN_VALUE, unit); + to(Long.MAX_VALUE, unit); + } // toString ts(1L, DAYS, "1970-01-02T00:00:00Z"); @@ -59,6 +85,8 @@ public class Basic { ts(1L, MILLISECONDS, "1970-01-01T00:00:00.001Z"); ts(1L, MICROSECONDS, "1970-01-01T00:00:00.000001Z"); ts(1L, NANOSECONDS, "1970-01-01T00:00:00.000000001Z"); + ts(999999999L, NANOSECONDS, "1970-01-01T00:00:00.999999999Z"); + ts(9999999999L, NANOSECONDS, "1970-01-01T00:00:09.999999999Z"); ts(-1L, DAYS, "1969-12-31T00:00:00Z"); ts(-1L, HOURS, "1969-12-31T23:00:00Z"); @@ -67,6 +95,8 @@ public class Basic { ts(-1L, MILLISECONDS, "1969-12-31T23:59:59.999Z"); ts(-1L, MICROSECONDS, "1969-12-31T23:59:59.999999Z"); ts(-1L, NANOSECONDS, "1969-12-31T23:59:59.999999999Z"); + ts(-999999999L, NANOSECONDS, "1969-12-31T23:59:59.000000001Z"); + ts(-9999999999L, NANOSECONDS, "1969-12-31T23:59:50.000000001Z"); ts(-62135596799999L, MILLISECONDS, "0001-01-01T00:00:00.001Z"); ts(-62135596800000L, MILLISECONDS, "0001-01-01T00:00:00Z"); @@ -114,9 +144,24 @@ public class Basic { throw new RuntimeException("should not be equal"); } - static void ts(long v, TimeUnit y, String expected) { - String s = FileTime.from(v, y).toString(); - if (!s.equals(expected)) - throw new RuntimeException("unexpected format"); + static void to(long v, TimeUnit unit) { + FileTime t = FileTime.from(v, unit); + for (TimeUnit u: TimeUnit.values()) { + long result = t.to(u); + long expected = u.convert(v, unit); + if (result != expected) { + throw new RuntimeException("unexpected result"); + } + } + } + + static void ts(long v, TimeUnit unit, String expected) { + String result = FileTime.from(v, unit).toString(); + if (!result.equals(expected)) { + System.err.format("FileTime.from(%d, %s).toString() failed\n", v, unit); + System.err.format("Expected: %s\n", expected); + System.err.format(" Got: %s\n", result); + throw new RuntimeException(); + } } } diff --git a/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java index f3ff3584964..7d948b9bd3e 100644 --- a/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java @@ -49,9 +49,8 @@ public class Basic { Set perms = PosixFilePermissions.fromString(mode); // change permissions and re-read them. - Attributes.setPosixFilePermissions(file, perms); - Set current = Attributes - .readPosixFileAttributes(file).permissions(); + Files.setPosixFilePermissions(file, perms); + Set current = Files.getPosixFilePermissions(file); if (!current.equals(perms)) { throw new RuntimeException("Actual permissions: " + PosixFilePermissions.toString(current) + ", expected: " + @@ -59,8 +58,8 @@ public class Basic { } // repeat test using setAttribute/getAttribute - file.setAttribute("posix:permissions", perms); - current = (Set)file.getAttribute("posix:permissions"); + Files.setAttribute(file, "posix:permissions", perms); + current = (Set)Files.getAttribute(file, "posix:permissions"); if (!current.equals(perms)) { throw new RuntimeException("Actual permissions: " + PosixFilePermissions.toString(current) + ", expected: " + @@ -97,25 +96,25 @@ public class Basic { FileAttribute> attr = PosixFilePermissions.asFileAttribute(requested); System.out.format("create file with mode: %s\n", mode); - file.createFile(attr); + Files.createFile(file, attr); try { - checkSecure(requested, file - .getFileAttributeView(PosixFileAttributeView.class) - .readAttributes() - .permissions()); + checkSecure(requested, + Files.getFileAttributeView(file, PosixFileAttributeView.class) + .readAttributes() + .permissions()); } finally { - file.delete(); + Files.delete(file); } System.out.format("create directory with mode: %s\n", mode); - file.createDirectory(attr); + Files.createDirectory(file, attr); try { - checkSecure(requested, file - .getFileAttributeView(PosixFileAttributeView.class) - .readAttributes() - .permissions()); + checkSecure(requested, + Files.getFileAttributeView(file, PosixFileAttributeView.class) + .readAttributes() + .permissions()); } finally { - file.delete(); + Files.delete(file); } } @@ -130,11 +129,11 @@ public class Basic { // create file and test updating and reading its permissions Path file = dir.resolve("foo"); System.out.format("create %s\n", file); - file.createFile(); + Files.createFile(file); try { // get initial permissions so that we can restore them later - PosixFileAttributeView view = file - .getFileAttributeView(PosixFileAttributeView.class); + PosixFileAttributeView view = + Files.getFileAttributeView(file, PosixFileAttributeView.class); Set save = view.readAttributes() .permissions(); @@ -165,7 +164,7 @@ public class Basic { view.setPermissions(save); } } finally { - file.delete(); + Files.delete(file); } // create link (to file that doesn't exist) and test reading of @@ -173,15 +172,18 @@ public class Basic { if (TestUtil.supportsLinks(dir)) { Path link = dir.resolve("link"); System.out.format("create link %s\n", link); - link.createSymbolicLink(file); + Files.createSymbolicLink(link, file); try { - PosixFileAttributes attrs = Attributes - .readPosixFileAttributes(link, NOFOLLOW_LINKS); + PosixFileAttributes attrs = + Files.getFileAttributeView(link, + PosixFileAttributeView.class, + NOFOLLOW_LINKS) + .readAttributes(); if (!attrs.isSymbolicLink()) { throw new RuntimeException("not a link"); } } finally { - link.delete(); + Files.delete(link); } } @@ -235,12 +237,12 @@ public class Basic { Path file = dir.resolve("gus"); System.out.format("create %s\n", file); - file.createFile(); + Files.createFile(file); try { // read attributes of directory to get owner/group - PosixFileAttributeView view = file - .getFileAttributeView(PosixFileAttributeView.class); + PosixFileAttributeView view = + Files.getFileAttributeView(file, PosixFileAttributeView.class); PosixFileAttributes attrs = view.readAttributes(); // set to existing owner/group @@ -248,13 +250,13 @@ public class Basic { view.setGroup(attrs.group()); // repeat test using set/getAttribute - UserPrincipal owner = (UserPrincipal)file.getAttribute("posix:owner"); - file.setAttribute("posix:owner", owner); - UserPrincipal group = (UserPrincipal)file.getAttribute("posix:group"); - file.setAttribute("posix:group", group); + UserPrincipal owner = (UserPrincipal)Files.getAttribute(file, "posix:owner"); + Files.setAttribute(file, "posix:owner", owner); + UserPrincipal group = (UserPrincipal)Files.getAttribute(file, "posix:group"); + Files.setAttribute(file, "posix:group", group); } finally { - file.delete(); + Files.delete(file); } System.out.println("OKAY"); @@ -272,7 +274,7 @@ public class Basic { .getUserPrincipalLookupService(); // read attributes of directory to get owner/group - PosixFileAttributes attrs = Attributes.readPosixFileAttributes(dir); + PosixFileAttributes attrs = Files.readAttributes(dir, PosixFileAttributes.class); // lookup owner and check it matches file's owner System.out.format("lookup: %s\n", attrs.owner().getName()); @@ -322,8 +324,8 @@ public class Basic { { System.out.println("-- Exceptions --"); - PosixFileAttributeView view = dir - .getFileAttributeView(PosixFileAttributeView.class); + PosixFileAttributeView view = + Files.getFileAttributeView(dir,PosixFileAttributeView.class); // NullPointerException try { @@ -355,7 +357,7 @@ public class Basic { } catch (NullPointerException x) { } try { - Set perms = new HashSet(); + Set perms = new HashSet<>(); perms.add(null); view.setPermissions(perms); throw new RuntimeException("NullPointerException not thrown"); @@ -377,7 +379,7 @@ public class Basic { public static void main(String[] args) throws IOException { Path dir = TestUtil.createTemporaryDirectory(); try { - if (!dir.getFileStore().supportsFileAttributeView("posix")) { + if (!Files.getFileStore(dir).supportsFileAttributeView("posix")) { System.out.println("PosixFileAttributeView not supported"); return; } diff --git a/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java index c6a807a45ec..a6af4192234 100644 --- a/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java @@ -79,8 +79,8 @@ public class Basic { } static void test(Path file, LinkOption... options) throws IOException { - final UserDefinedFileAttributeView view = file - .getFileAttributeView(UserDefinedFileAttributeView.class, options); + final UserDefinedFileAttributeView view = + Files.getFileAttributeView(file, UserDefinedFileAttributeView.class, options); ByteBuffer buf = rand.nextBoolean() ? ByteBuffer.allocate(100) : ByteBuffer.allocateDirect(100); @@ -131,24 +131,24 @@ public class Basic { // Test: dynamic access String name = "user:" + ATTR_NAME; byte[] valueAsBytes = ATTR_VALUE.getBytes(); - file.setAttribute(name, valueAsBytes); - byte[] actualAsBytes = (byte[])file.getAttribute(name); + Files.setAttribute(file, name, valueAsBytes); + byte[] actualAsBytes = (byte[])Files.getAttribute(file, name); if (!Arrays.equals(valueAsBytes, actualAsBytes)) throw new RuntimeException("Unexpected attribute value"); - Map map = file.readAttributes(name); + Map map = Files.readAttributes(file, name); if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME))) throw new RuntimeException("Unexpected attribute value"); - map = file.readAttributes("user:*"); + map = Files.readAttributes(file, "user:*"); if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME))) throw new RuntimeException("Unexpected attribute value"); - map = file.readAttributes("user:DoesNotExist"); + map = Files.readAttributes(file, "user:DoesNotExist"); if (!map.isEmpty()) throw new RuntimeException("Map expected to be empty"); } static void miscTests(final Path file) throws IOException { - final UserDefinedFileAttributeView view = file - .getFileAttributeView(UserDefinedFileAttributeView.class); + final UserDefinedFileAttributeView view = + Files.getFileAttributeView(file, UserDefinedFileAttributeView.class); view.write(ATTR_NAME, ByteBuffer.wrap(ATTR_VALUE.getBytes())); // NullPointerException @@ -180,31 +180,31 @@ public class Basic { }}); expectNullPointerException(new Task() { public void run() throws IOException { - file.getAttribute(null); + Files.getAttribute(file, null); }}); expectNullPointerException(new Task() { public void run() throws IOException { - file.getAttribute("user:" + ATTR_NAME, (LinkOption[])null); + Files.getAttribute(file, "user:" + ATTR_NAME, (LinkOption[])null); }}); expectNullPointerException(new Task() { public void run() throws IOException { - file.setAttribute("user:" + ATTR_NAME, null); + Files.setAttribute(file, "user:" + ATTR_NAME, null); }}); expectNullPointerException(new Task() { public void run() throws IOException { - file.setAttribute(null, new byte[0]); + Files.setAttribute(file, null, new byte[0]); }}); expectNullPointerException(new Task() { public void run() throws IOException { - file.setAttribute("user: " + ATTR_NAME, new byte[0], (LinkOption[])null); + Files.setAttribute(file, "user: " + ATTR_NAME, new byte[0], (LinkOption[])null); }}); expectNullPointerException(new Task() { public void run() throws IOException { - file.readAttributes((String)null); + Files.readAttributes(file, (String)null); }}); expectNullPointerException(new Task() { public void run() throws IOException { - file.readAttributes("*", (LinkOption[])null); + Files.readAttributes(file, "*", (LinkOption[])null); }}); // Read-only buffer @@ -229,46 +229,50 @@ public class Basic { // create temporary directory to run tests Path dir = TestUtil.createTemporaryDirectory(); try { - if (!dir.getFileStore().supportsFileAttributeView("user")) { + if (!Files.getFileStore(dir).supportsFileAttributeView("user")) { System.out.println("UserDefinedFileAttributeView not supported - skip test"); return; } // test access to user defined attributes of regular file - Path file = dir.resolve("foo.html").createFile(); + Path file = dir.resolve("foo.html"); + Files.createFile(file); try { test(file); } finally { - file.delete(); + Files.delete(file); } - // test access to user define attributes of directory - file = dir.resolve("foo").createDirectory(); + // test access to user defined attributes of directory + Path subdir = dir.resolve("foo"); + Files.createDirectory(subdir); try { - test(file); + test(subdir); } finally { - file.delete(); + Files.delete(subdir); } // test access to user defined attributes of sym link if (TestUtil.supportsLinks(dir)) { Path target = dir.resolve("doesnotexist"); - Path link = dir.resolve("link").createSymbolicLink(target); + Path link = dir.resolve("link"); + Files.createSymbolicLink(link, target); try { test(link, NOFOLLOW_LINKS); } catch (IOException x) { // access to attributes of sym link may not be supported } finally { - link.delete(); + Files.delete(link); } } // misc. tests try { - file = dir.resolve("foo.txt").createFile(); + file = dir.resolve("foo.txt"); + Files.createFile(file); miscTests(dir); } finally { - file.delete(); + Files.delete(file); } } finally { diff --git a/jdk/test/java/nio/file/spi/SetDefaultProvider.java b/jdk/test/java/nio/file/spi/SetDefaultProvider.java index 7852edb717d..e21be72985a 100644 --- a/jdk/test/java/nio/file/spi/SetDefaultProvider.java +++ b/jdk/test/java/nio/file/spi/SetDefaultProvider.java @@ -22,14 +22,13 @@ */ /* @test - * @bug 4313887 + * @bug 4313887 7006126 * @summary Unit test for java.nio.file.spi.FileSystemProvider * @build TestProvider SetDefaultProvider * @run main/othervm -Djava.nio.file.spi.DefaultFileSystemProvider=TestProvider SetDefaultProvider */ import java.nio.file.*; -import java.nio.file.spi.*; public class SetDefaultProvider { public static void main(String[] args) throws Exception { diff --git a/jdk/test/java/nio/file/spi/TestProvider.java b/jdk/test/java/nio/file/spi/TestProvider.java index 248b568858f..a604b6dfe7e 100644 --- a/jdk/test/java/nio/file/spi/TestProvider.java +++ b/jdk/test/java/nio/file/spi/TestProvider.java @@ -24,6 +24,7 @@ import java.nio.file.spi.FileSystemProvider; import java.nio.file.*; import java.nio.file.attribute.*; +import java.nio.channels.SeekableByteChannel; import java.net.URI; import java.util.*; import java.io.IOException; @@ -34,7 +35,6 @@ public class TestProvider extends FileSystemProvider { public TestProvider(FileSystemProvider defaultProvider) { theFileSystem = new TestFileSystem(this); - } @Override @@ -57,6 +57,124 @@ public class TestProvider extends FileSystemProvider { throw new RuntimeException("not implemented"); } + @Override + public void setAttribute(Path file, String attribute, Object value, + LinkOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public Map readAttributes(Path file, String attributes, + LinkOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public A readAttributes(Path file, + Class type, + LinkOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public V getFileAttributeView(Path file, + Class type, + LinkOption... options) + { + throw new RuntimeException("not implemented"); + } + + + @Override + public void delete(Path file) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public void createSymbolicLink(Path link, Path target, FileAttribute... attrs) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public void createLink(Path link, Path existing) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public Path readSymbolicLink(Path link) throws IOException { + throw new RuntimeException("not implemented"); + } + + + @Override + public void copy(Path source, Path target, CopyOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public void move(Path source, Path target, CopyOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public DirectoryStream newDirectoryStream(Path dir, + DirectoryStream.Filter filter) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public void createDirectory(Path dir, FileAttribute... attrs) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public SeekableByteChannel newByteChannel(Path file, + Set options, + FileAttribute... attrs) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + + @Override + public boolean isHidden(Path file) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public FileStore getFileStore(Path file) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public boolean isSameFile(Path file, Path other) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public void checkAccess(Path file, AccessMode... modes) + throws IOException + { + throw new RuntimeException("not implemented"); + } + static class TestFileSystem extends FileSystem { private final TestProvider provider; @@ -105,7 +223,7 @@ public class TestProvider extends FileSystemProvider { } @Override - public Path getPath(String path) { + public Path getPath(String first, String... more) { throw new RuntimeException("not implemented"); } @@ -124,5 +242,4 @@ public class TestProvider extends FileSystemProvider { throw new RuntimeException("not implemented"); } } - } diff --git a/jdk/test/java/util/Arrays/Sorting.java b/jdk/test/java/util/Arrays/Sorting.java index a2c4ed98e04..9eac7989e12 100644 --- a/jdk/test/java/util/Arrays/Sorting.java +++ b/jdk/test/java/util/Arrays/Sorting.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6880672 6896573 6899694 6976036 + * @bug 6880672 6896573 6899694 6976036 7013585 7018258 * @summary Exercise Arrays.sort * @build Sorting * @run main Sorting -shortrun @@ -66,7 +66,7 @@ public class Sorting { } long end = System.currentTimeMillis(); - out.format("\nPASSED in %d sec.\n", Math.round((end - start) / 1E3)); + out.format("PASSED in %d sec.\n", Math.round((end - start) / 1E3)); } private static void testAndCheck(int[] lengths, long[] randoms) { @@ -78,46 +78,19 @@ public class Sorting { testEmptyAndNullFloatArray(); testEmptyAndNullDoubleArray(); - for (long random : randoms) { - reset(random); - + for (int length : lengths) { + testMergeSort(length); + testAndCheckRange(length); + testAndCheckSubArray(length); + } + for (long seed : randoms) { for (int length : lengths) { - testAndCheckWithInsertionSort(length, random); - } - reset(random); - - for (int length : lengths) { - testAndCheckWithCheckSum(length, random); - } - reset(random); - - for (int length : lengths) { - testAndCheckWithScrambling(length, random); - } - reset(random); - - for (int length : lengths) { - testAndCheckFloat(length, random); - } - reset(random); - - for (int length : lengths) { - testAndCheckDouble(length, random); - } - reset(random); - - for (int length : lengths) { - testAndCheckRange(length, random); - } - reset(random); - - for (int length : lengths) { - testAndCheckSubArray(length, random); - } - reset(random); - - for (int length : lengths) { - testStable(length, random); + testAndCheckWithInsertionSort(length, new MyRandom(seed)); + testAndCheckWithCheckSum(length, new MyRandom(seed)); + testAndCheckWithScrambling(length, new MyRandom(seed)); + testAndCheckFloat(length, new MyRandom(seed)); + testAndCheckDouble(length, new MyRandom(seed)); + testStable(length, new MyRandom(seed)); } } } @@ -255,7 +228,7 @@ public class Sorting { failed("Arrays.sort(double[]) shouldn't catch null array"); } - private static void testAndCheckSubArray(int length, long random) { + private static void testAndCheckSubArray(int length) { ourDescription = "Check sorting of subarray"; int[] golden = new int[length]; boolean newLine = false; @@ -282,7 +255,7 @@ public class Sorting { } } - private static void testAndCheckRange(int length, long random) { + private static void testAndCheckRange(int length) { ourDescription = "Check range check"; int[] golden = new int[length]; @@ -300,15 +273,16 @@ public class Sorting { out.println(); } - private static void testStable(int length, long random) { + private static void testStable(int length, MyRandom random) { ourDescription = "Check if sorting is stable"; - Pair[] a = build(length); + Pair[] a = build(length, random); - out.println("Test 'stable': " + "random = " + random + + out.println("Test 'stable': " + "random = " + random.getSeed() + ", length = " + length); Arrays.sort(a); checkSorted(a); checkStable(a); + out.println(); } private static void checkSorted(Pair[] a) { @@ -342,11 +316,11 @@ public class Sorting { } } - private static Pair[] build(int length) { + private static Pair[] build(int length, Random random) { Pair[] a = new Pair[length * 4]; for (int i = 0; i < a.length; ) { - int key = ourRandom.nextInt(); + int key = random.nextInt(); a[i++] = new Pair(key, 1); a[i++] = new Pair(key, 2); a[i++] = new Pair(key, 3); @@ -389,7 +363,7 @@ public class Sorting { } - private static void testAndCheckWithInsertionSort(int length, long random) { + private static void testAndCheckWithInsertionSort(int length, MyRandom random) { if (length > 1000) { return; } @@ -398,13 +372,13 @@ public class Sorting { for (int m = 1; m < 2 * length; m *= 2) { for (UnsortedBuilder builder : UnsortedBuilder.values()) { - builder.build(golden, m); + builder.build(golden, m, random); int[] test = golden.clone(); for (TypeConverter converter : TypeConverter.values()) { - out.println("Test 'insertion sort': " + converter + " " + - builder + "random = " + random + ", length = " + - length + ", m = " + m); + out.println("Test 'insertion sort': " + converter + + " " + builder + "random = " + random.getSeed() + + ", length = " + length + ", m = " + m); Object convertedGolden = converter.convert(golden); Object convertedTest1 = converter.convert(test); Object convertedTest2 = converter.convert(test); @@ -417,19 +391,44 @@ public class Sorting { out.println(); } - private static void testAndCheckWithCheckSum(int length, long random) { + private static void testMergeSort(int length) { + if (length < 1000) { + return; + } + ourDescription = "Check merge sorting"; + int[] golden = new int[length]; + int period = 67; // java.util.DualPivotQuicksort.MAX_RUN_COUNT + + for (int m = period - 2; m <= period + 2; m++) { + for (MergeBuilder builder : MergeBuilder.values()) { + builder.build(golden, m); + int[] test = golden.clone(); + + for (TypeConverter converter : TypeConverter.values()) { + out.println("Test 'merge sort': " + converter + " " + + builder + "length = " + length + ", m = " + m); + Object convertedGolden = converter.convert(golden); + sort(convertedGolden); + checkSorted(convertedGolden); + } + } + } + out.println(); + } + + private static void testAndCheckWithCheckSum(int length, MyRandom random) { ourDescription = "Check sorting with check sum"; int[] golden = new int[length]; for (int m = 1; m < 2 * length; m *= 2) { for (UnsortedBuilder builder : UnsortedBuilder.values()) { - builder.build(golden, m); + builder.build(golden, m, random); int[] test = golden.clone(); for (TypeConverter converter : TypeConverter.values()) { - out.println("Test 'check sum': " + converter + " " + - builder + "random = " + random + ", length = " + - length + ", m = " + m); + out.println("Test 'check sum': " + converter + + " " + builder + "random = " + random.getSeed() + + ", length = " + length + ", m = " + m); Object convertedGolden = converter.convert(golden); Object convertedTest = converter.convert(test); sort(convertedTest); @@ -440,7 +439,7 @@ public class Sorting { out.println(); } - private static void testAndCheckWithScrambling(int length, long random) { + private static void testAndCheckWithScrambling(int length, MyRandom random) { ourDescription = "Check sorting with scrambling"; int[] golden = new int[length]; @@ -451,12 +450,12 @@ public class Sorting { for (SortedBuilder builder : SortedBuilder.values()) { builder.build(golden, m); int[] test = golden.clone(); - scramble(test); + scramble(test, random); for (TypeConverter converter : TypeConverter.values()) { - out.println("Test 'scrambling': " + converter + " " + - builder + "random = " + random + ", length = " + - length + ", m = " + m); + out.println("Test 'scrambling': " + converter + + " " + builder + "random = " + random.getSeed() + + ", length = " + length + ", m = " + m); Object convertedGolden = converter.convert(golden); Object convertedTest = converter.convert(test); sort(convertedTest); @@ -467,7 +466,7 @@ public class Sorting { out.println(); } - private static void testAndCheckFloat(int length, long random) { + private static void testAndCheckFloat(int length, MyRandom random) { ourDescription = "Check float sorting"; float[] golden = new float[length]; final int MAX = 10; @@ -485,13 +484,12 @@ public class Sorting { continue; } for (FloatBuilder builder : FloatBuilder.values()) { - out.println("Test 'float': random = " + random + - ", length = " + length + ", a = " + a + - ", g = " + g + ", z = " + z + ", n = " + n + - ", p = " + p); - builder.build(golden, a, g, z, n, p); + out.println("Test 'float': random = " + random.getSeed() + + ", length = " + length + ", a = " + a + ", g = " + + g + ", z = " + z + ", n = " + n + ", p = " + p); + builder.build(golden, a, g, z, n, p, random); float[] test = golden.clone(); - scramble(test); + scramble(test, random); sort(test); compare(test, golden, a, n, g); } @@ -506,7 +504,7 @@ public class Sorting { } } - private static void testAndCheckDouble(int length, long random) { + private static void testAndCheckDouble(int length, MyRandom random) { ourDescription = "Check double sorting"; double[] golden = new double[length]; final int MAX = 10; @@ -524,12 +522,12 @@ public class Sorting { continue; } for (DoubleBuilder builder : DoubleBuilder.values()) { - out.println("Test 'double': random = " + random + + out.println("Test 'double': random = " + random.getSeed() + ", length = " + length + ", a = " + a + ", g = " + g + ", z = " + z + ", n = " + n + ", p = " + p); - builder.build(golden, a, g, z, n, p); + builder.build(golden, a, g, z, n, p, random); double[] test = golden.clone(); - scramble(test); + scramble(test, random); sort(test); compare(test, golden, a, n, g); } @@ -546,31 +544,37 @@ public class Sorting { private static void prepareSubArray(int[] a, int fromIndex, int toIndex, int m) { for (int i = 0; i < fromIndex; i++) { - a[i] = 0xBABA; - } - for (int i = fromIndex; i < toIndex; i++) { - a[i] = -i + m; - } - for (int i = toIndex; i < a.length; i++) { a[i] = 0xDEDA; } - } + int middle = (fromIndex + toIndex) >>> 1; + int k = 0; - private static void scramble(int[] a) { - for (int i = 0; i < a.length * 7; i++) { - swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length)); + for (int i = fromIndex; i < middle; i++) { + a[i] = k++; + } + for (int i = middle; i < toIndex; i++) { + a[i] = k--; + } + for (int i = toIndex; i < a.length; i++) { + a[i] = 0xBABA; } } - private static void scramble(float[] a) { + private static void scramble(int[] a, Random random) { for (int i = 0; i < a.length * 7; i++) { - swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length)); + swap(a, random.nextInt(a.length), random.nextInt(a.length)); } } - private static void scramble(double[] a) { + private static void scramble(float[] a, Random random) { for (int i = 0; i < a.length * 7; i++) { - swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length)); + swap(a, random.nextInt(a.length), random.nextInt(a.length)); + } + } + + private static void scramble(double[] a, Random random) { + for (int i = 0; i < a.length * 7; i++) { + swap(a, random.nextInt(a.length), random.nextInt(a.length)); } } @@ -683,10 +687,10 @@ public class Sorting { private static enum FloatBuilder { SIMPLE { - void build(float[] x, int a, int g, int z, int n, int p) { + void build(float[] x, int a, int g, int z, int n, int p, Random random) { int fromIndex = 0; - float negativeValue = -ourRandom.nextFloat(); - float positiveValue = ourRandom.nextFloat(); + float negativeValue = -random.nextFloat(); + float positiveValue = random.nextFloat(); writeValue(x, negativeValue, fromIndex, n); fromIndex += n; @@ -704,15 +708,15 @@ public class Sorting { } }; - abstract void build(float[] x, int a, int g, int z, int n, int p); + abstract void build(float[] x, int a, int g, int z, int n, int p, Random random); } private static enum DoubleBuilder { SIMPLE { - void build(double[] x, int a, int g, int z, int n, int p) { + void build(double[] x, int a, int g, int z, int n, int p, Random random) { int fromIndex = 0; - double negativeValue = -ourRandom.nextFloat(); - double positiveValue = ourRandom.nextFloat(); + double negativeValue = -random.nextFloat(); + double positiveValue = random.nextFloat(); writeValue(x, negativeValue, fromIndex, n); fromIndex += n; @@ -730,7 +734,7 @@ public class Sorting { } }; - abstract void build(double[] x, int a, int g, int z, int n, int p); + abstract void build(double[] x, int a, int g, int z, int n, int p, Random random); } private static void writeValue(float[] a, float value, int fromIndex, int count) { @@ -806,7 +810,6 @@ public class Sorting { } } }, - ORGAN_PIPES { void build(int[] a, int m) { int i = 0; @@ -835,37 +838,85 @@ public class Sorting { } } + private static enum MergeBuilder { + ASCENDING { + void build(int[] a, int m) { + int period = a.length / m; + int v = 1, i = 0; + + for (int k = 0; k < m; k++) { + v = 1; + for (int p = 0; p < period; p++) { + a[i++] = v++; + } + } + for (int j = i; j < a.length - 1; j++) { + a[j] = v++; + } + a[a.length - 1] = 0; + } + }, + DESCENDING { + void build(int[] a, int m) { + int period = a.length / m; + int v = -1, i = 0; + + for (int k = 0; k < m; k++) { + v = -1; + for (int p = 0; p < period; p++) { + a[i++] = v--; + } + } + for (int j = i; j < a.length - 1; j++) { + a[j] = v--; + } + a[a.length - 1] = 0; + } + }; + + abstract void build(int[] a, int m); + + @Override public String toString() { + String name = name(); + + for (int i = name.length(); i < 12; i++) { + name += " "; + } + return name; + } + } + private static enum UnsortedBuilder { RANDOM { - void build(int[] a, int m) { + void build(int[] a, int m, Random random) { for (int i = 0; i < a.length; i++) { - a[i] = ourRandom.nextInt(); + a[i] = random.nextInt(); } } }, ASCENDING { - void build(int[] a, int m) { + void build(int[] a, int m, Random random) { for (int i = 0; i < a.length; i++) { a[i] = m + i; } } }, DESCENDING { - void build(int[] a, int m) { + void build(int[] a, int m, Random random) { for (int i = 0; i < a.length; i++) { a[i] = a.length - m - i; } } }, ALL_EQUAL { - void build(int[] a, int m) { + void build(int[] a, int m, Random random) { for (int i = 0; i < a.length; i++) { a[i] = m; } } }, SAW { - void build(int[] a, int m) { + void build(int[] a, int m, Random random) { int incCount = 1; int decCount = a.length; int i = 0; @@ -891,21 +942,21 @@ public class Sorting { } }, REPEATED { - void build(int[] a, int m) { + void build(int[] a, int m, Random random) { for (int i = 0; i < a.length; i++) { a[i] = i % m; } } }, DUPLICATED { - void build(int[] a, int m) { + void build(int[] a, int m, Random random) { for (int i = 0; i < a.length; i++) { - a[i] = ourRandom.nextInt(m); + a[i] = random.nextInt(m); } } }, ORGAN_PIPES { - void build(int[] a, int m) { + void build(int[] a, int m, Random random) { int middle = a.length / (m + 1); for (int i = 0; i < middle; i++) { @@ -917,28 +968,29 @@ public class Sorting { } }, STAGGER { - void build(int[] a, int m) { + void build(int[] a, int m, Random random) { for (int i = 0; i < a.length; i++) { a[i] = (i * m + i) % a.length; } } }, PLATEAU { - void build(int[] a, int m) { + void build(int[] a, int m, Random random) { for (int i = 0; i < a.length; i++) { a[i] = Math.min(i, m); } } }, SHUFFLE { - void build(int[] a, int m) { + void build(int[] a, int m, Random random) { + int x = 0, y = 0; for (int i = 0; i < a.length; i++) { - a[i] = ourRandom.nextBoolean() ? (ourFirst += 2) : (ourSecond += 2); + a[i] = random.nextBoolean() ? (x += 2) : (y += 2); } } }; - abstract void build(int[] a, int m); + abstract void build(int[] a, int m, Random random); @Override public String toString() { String name = name(); @@ -1518,9 +1570,9 @@ public class Sorting { private static void checkSubArray(Integer[] a, int fromIndex, int toIndex, int m) { for (int i = 0; i < fromIndex; i++) { - if (a[i].intValue() != 0xBABA) { + if (a[i].intValue() != 0xDEDA) { failed("Range sort changes left element on position " + i + - ": " + a[i] + ", must be " + 0xBABA); + ": " + a[i] + ", must be " + 0xDEDA); } } @@ -1531,18 +1583,18 @@ public class Sorting { } for (int i = toIndex; i < a.length; i++) { - if (a[i].intValue() != 0xDEDA) { + if (a[i].intValue() != 0xBABA) { failed("Range sort changes right element on position " + i + - ": " + a[i] + ", must be " + 0xDEDA); + ": " + a[i] + ", must be " + 0xBABA); } } } private static void checkSubArray(int[] a, int fromIndex, int toIndex, int m) { for (int i = 0; i < fromIndex; i++) { - if (a[i] != 0xBABA) { + if (a[i] != 0xDEDA) { failed("Range sort changes left element on position " + i + - ": " + a[i] + ", must be " + 0xBABA); + ": " + a[i] + ", must be " + 0xDEDA); } } @@ -1553,18 +1605,18 @@ public class Sorting { } for (int i = toIndex; i < a.length; i++) { - if (a[i] != 0xDEDA) { + if (a[i] != 0xBABA) { failed("Range sort changes right element on position " + i + - ": " + a[i] + ", must be " + 0xDEDA); + ": " + a[i] + ", must be " + 0xBABA); } } } private static void checkSubArray(byte[] a, int fromIndex, int toIndex, int m) { for (int i = 0; i < fromIndex; i++) { - if (a[i] != (byte) 0xBABA) { + if (a[i] != (byte) 0xDEDA) { failed("Range sort changes left element on position " + i + - ": " + a[i] + ", must be " + 0xBABA); + ": " + a[i] + ", must be " + 0xDEDA); } } @@ -1575,18 +1627,18 @@ public class Sorting { } for (int i = toIndex; i < a.length; i++) { - if (a[i] != (byte) 0xDEDA) { + if (a[i] != (byte) 0xBABA) { failed("Range sort changes right element on position " + i + - ": " + a[i] + ", must be " + 0xDEDA); + ": " + a[i] + ", must be " + 0xBABA); } } } private static void checkSubArray(long[] a, int fromIndex, int toIndex, int m) { for (int i = 0; i < fromIndex; i++) { - if (a[i] != (long) 0xBABA) { + if (a[i] != (long) 0xDEDA) { failed("Range sort changes left element on position " + i + - ": " + a[i] + ", must be " + 0xBABA); + ": " + a[i] + ", must be " + 0xDEDA); } } @@ -1597,18 +1649,18 @@ public class Sorting { } for (int i = toIndex; i < a.length; i++) { - if (a[i] != (long) 0xDEDA) { + if (a[i] != (long) 0xBABA) { failed("Range sort changes right element on position " + i + - ": " + a[i] + ", must be " + 0xDEDA); + ": " + a[i] + ", must be " + 0xBABA); } } } private static void checkSubArray(char[] a, int fromIndex, int toIndex, int m) { for (int i = 0; i < fromIndex; i++) { - if (a[i] != (char) 0xBABA) { + if (a[i] != (char) 0xDEDA) { failed("Range sort changes left element on position " + i + - ": " + a[i] + ", must be " + 0xBABA); + ": " + a[i] + ", must be " + 0xDEDA); } } @@ -1619,18 +1671,18 @@ public class Sorting { } for (int i = toIndex; i < a.length; i++) { - if (a[i] != (char) 0xDEDA) { + if (a[i] != (char) 0xBABA) { failed("Range sort changes right element on position " + i + - ": " + a[i] + ", must be " + 0xDEDA); + ": " + a[i] + ", must be " + 0xBABA); } } } private static void checkSubArray(short[] a, int fromIndex, int toIndex, int m) { for (int i = 0; i < fromIndex; i++) { - if (a[i] != (short) 0xBABA) { + if (a[i] != (short) 0xDEDA) { failed("Range sort changes left element on position " + i + - ": " + a[i] + ", must be " + 0xBABA); + ": " + a[i] + ", must be " + 0xDEDA); } } @@ -1641,18 +1693,18 @@ public class Sorting { } for (int i = toIndex; i < a.length; i++) { - if (a[i] != (short) 0xDEDA) { + if (a[i] != (short) 0xBABA) { failed("Range sort changes right element on position " + i + - ": " + a[i] + ", must be " + 0xDEDA); + ": " + a[i] + ", must be " + 0xBABA); } } } private static void checkSubArray(float[] a, int fromIndex, int toIndex, int m) { for (int i = 0; i < fromIndex; i++) { - if (a[i] != (float) 0xBABA) { + if (a[i] != (float) 0xDEDA) { failed("Range sort changes left element on position " + i + - ": " + a[i] + ", must be " + 0xBABA); + ": " + a[i] + ", must be " + 0xDEDA); } } @@ -1663,18 +1715,18 @@ public class Sorting { } for (int i = toIndex; i < a.length; i++) { - if (a[i] != (float) 0xDEDA) { + if (a[i] != (float) 0xBABA) { failed("Range sort changes right element on position " + i + - ": " + a[i] + ", must be " + 0xDEDA); + ": " + a[i] + ", must be " + 0xBABA); } } } private static void checkSubArray(double[] a, int fromIndex, int toIndex, int m) { for (int i = 0; i < fromIndex; i++) { - if (a[i] != (double) 0xBABA) { + if (a[i] != (double) 0xDEDA) { failed("Range sort changes left element on position " + i + - ": " + a[i] + ", must be " + 0xBABA); + ": " + a[i] + ", must be " + 0xDEDA); } } @@ -1685,9 +1737,9 @@ public class Sorting { } for (int i = toIndex; i < a.length; i++) { - if (a[i] != (double) 0xDEDA) { + if (a[i] != (double) 0xBABA) { failed("Range sort changes right element on position " + i + - ": " + a[i] + ", must be " + 0xDEDA); + ": " + a[i] + ", must be " + 0xBABA); } } } @@ -1947,18 +1999,6 @@ public class Sorting { } } - private static void prepareRandom(int[] a) { - for (int i = 0; i < a.length; i++) { - a[i] = ourRandom.nextInt(); - } - } - - private static void reset(long seed) { - ourRandom = new Random(seed); - ourFirst = 0; - ourSecond = 0; - } - private static void outArray(Object[] a) { for (int i = 0; i < a.length; i++) { out.print(a[i] + " "); @@ -1987,8 +2027,18 @@ public class Sorting { out.println(); } - private static int ourFirst; - private static int ourSecond; - private static Random ourRandom; + private static class MyRandom extends Random { + MyRandom(long seed) { + super(seed); + mySeed = seed; + } + + long getSeed() { + return mySeed; + } + + private long mySeed; + } + private static String ourDescription; } diff --git a/jdk/test/java/util/Objects/BasicObjectsTest.java b/jdk/test/java/util/Objects/BasicObjectsTest.java index 7584d2cffc2..bf025a8ad2c 100644 --- a/jdk/test/java/util/Objects/BasicObjectsTest.java +++ b/jdk/test/java/util/Objects/BasicObjectsTest.java @@ -164,7 +164,7 @@ public class BasicObjectsTest { // Test 1-arg variant try { - s = Objects.nonNull("pants"); + s = Objects.requireNonNull("pants"); if (s != "pants") { System.err.printf("1-arg non-null failed to return its arg"); errors++; @@ -175,7 +175,7 @@ public class BasicObjectsTest { } try { - s = Objects.nonNull(null); + s = Objects.requireNonNull(null); System.err.printf("1-arg nonNull failed to throw NPE"); errors++; } catch (NullPointerException e) { @@ -184,7 +184,7 @@ public class BasicObjectsTest { // Test 2-arg variant try { - s = Objects.nonNull("pants", "trousers"); + s = Objects.requireNonNull("pants", "trousers"); if (s != "pants") { System.err.printf("2-arg nonNull failed to return its arg"); errors++; @@ -195,7 +195,7 @@ public class BasicObjectsTest { } try { - s = Objects.nonNull(null, "pantaloons"); + s = Objects.requireNonNull(null, "pantaloons"); System.err.printf("2-arg nonNull failed to throw NPE"); errors++; } catch (NullPointerException e) { diff --git a/jdk/test/java/util/regex/RegExTest.java b/jdk/test/java/util/regex/RegExTest.java index 0e8470c4c11..e323066c3a2 100644 --- a/jdk/test/java/util/regex/RegExTest.java +++ b/jdk/test/java/util/regex/RegExTest.java @@ -32,7 +32,7 @@ * 4872664 4803179 4892980 4900747 4945394 4938995 4979006 4994840 4997476 * 5013885 5003322 4988891 5098443 5110268 6173522 4829857 5027748 6376940 * 6358731 6178785 6284152 6231989 6497148 6486934 6233084 6504326 6635133 - * 6350801 6676425 6878475 6919132 6931676 6948903 + * 6350801 6676425 6878475 6919132 6931676 6948903 7014645 */ import java.util.regex.*; @@ -136,6 +136,7 @@ public class RegExTest { namedGroupCaptureTest(); nonBmpClassComplementTest(); unicodePropertiesTest(); + unicodeHexNotationTest(); if (failure) throw new RuntimeException("Failure in the RE handling."); else @@ -161,18 +162,19 @@ public class RegExTest { private static void check(Matcher m, String result, boolean expected) { m.find(); - if (m.group().equals(result)) - failCount += (expected) ? 0 : 1; - else - failCount += (expected) ? 1 : 0; + if (m.group().equals(result) != expected) + failCount++; } private static void check(Pattern p, String s, boolean expected) { - Matcher matcher = p.matcher(s); - if (matcher.find()) - failCount += (expected) ? 0 : 1; - else - failCount += (expected) ? 1 : 0; + if (p.matcher(s).find() != expected) + failCount++; + } + + private static void check(String p, String s, boolean expected) { + Matcher matcher = Pattern.compile(p).matcher(s); + if (matcher.find() != expected) + failCount++; } private static void check(String p, char c, boolean expected) { @@ -3614,4 +3616,45 @@ public class RegExTest { } report("unicodeProperties"); } + + private static void unicodeHexNotationTest() throws Exception { + + // negative + checkExpectedFail("\\x{-23}"); + checkExpectedFail("\\x{110000}"); + checkExpectedFail("\\x{}"); + checkExpectedFail("\\x{AB[ef]"); + + // codepoint + check("^\\x{1033c}$", "\uD800\uDF3C", true); + check("^\\xF0\\x90\\x8C\\xBC$", "\uD800\uDF3C", false); + check("^\\x{D800}\\x{DF3c}+$", "\uD800\uDF3C", false); + check("^\\xF0\\x90\\x8C\\xBC$", "\uD800\uDF3C", false); + + // in class + check("^[\\x{D800}\\x{DF3c}]+$", "\uD800\uDF3C", false); + check("^[\\xF0\\x90\\x8C\\xBC]+$", "\uD800\uDF3C", false); + check("^[\\x{D800}\\x{DF3C}]+$", "\uD800\uDF3C", false); + check("^[\\x{DF3C}\\x{D800}]+$", "\uD800\uDF3C", false); + check("^[\\x{D800}\\x{DF3C}]+$", "\uDF3C\uD800", true); + check("^[\\x{DF3C}\\x{D800}]+$", "\uDF3C\uD800", true); + + for (int cp = 0; cp <= 0x10FFFF; cp++) { + String s = "A" + new String(Character.toChars(cp)) + "B"; + String hexUTF16 = (cp <= 0xFFFF)? String.format("\\u%04x", cp) + : String.format("\\u%04x\\u%04x", + (int) Character.toChars(cp)[0], + (int) Character.toChars(cp)[1]); + String hexCodePoint = "\\x{" + Integer.toHexString(cp) + "}"; + if (!Pattern.matches("A" + hexUTF16 + "B", s)) + failCount++; + if (!Pattern.matches("A[" + hexUTF16 + "]B", s)) + failCount++; + if (!Pattern.matches("A" + hexCodePoint + "B", s)) + failCount++; + if (!Pattern.matches("A[" + hexCodePoint + "]B", s)) + failCount++; + } + report("unicodeHexNotation"); + } } diff --git a/jdk/test/javax/script/CauseExceptionTest.java b/jdk/test/javax/script/CauseExceptionTest.java index 535717609e9..f1ff708bc1e 100644 --- a/jdk/test/javax/script/CauseExceptionTest.java +++ b/jdk/test/javax/script/CauseExceptionTest.java @@ -34,6 +34,10 @@ public class CauseExceptionTest { public static void main(String[] args) throws ScriptException, NoSuchMethodException { ScriptEngineManager sem = new ScriptEngineManager(); ScriptEngine engine = sem.getEngineByName("js"); + if (engine == null) { + System.out.println("Warning: No js engine found; test vacuously passes."); + return; + } engine.eval("function hello_world() { println('hello world'); throw 'out of here'; } "); Invocable invocable = (Invocable) engine; try { diff --git a/jdk/test/javax/script/StringWriterPrintTest.java b/jdk/test/javax/script/StringWriterPrintTest.java index 65b401ce637..42345791878 100644 --- a/jdk/test/javax/script/StringWriterPrintTest.java +++ b/jdk/test/javax/script/StringWriterPrintTest.java @@ -34,6 +34,10 @@ public class StringWriterPrintTest { public static void main(String[] args) throws ScriptException { ScriptEngineManager sem = new ScriptEngineManager(); ScriptEngine engine = sem.getEngineByName("js"); + if (engine == null) { + System.out.println("Warning: No js engine found; test vacuously passes."); + return; + } StringWriter sw = new StringWriter(); engine.eval("print(\"hello world 1\\n\")"); engine.getContext().setWriter(sw); diff --git a/jdk/test/javax/script/UnescapedBracketRegExTest.java b/jdk/test/javax/script/UnescapedBracketRegExTest.java index d444ec74aaa..f2a807065f7 100644 --- a/jdk/test/javax/script/UnescapedBracketRegExTest.java +++ b/jdk/test/javax/script/UnescapedBracketRegExTest.java @@ -34,6 +34,10 @@ public class UnescapedBracketRegExTest { public static void main(String[] args) throws ScriptException { ScriptEngineManager sem = new ScriptEngineManager(); ScriptEngine engine = sem.getEngineByName("js"); + if (engine == null) { + System.out.println("Warning: No js engine found; test vacuously passes."); + return; + } // the following throws exception engine.eval("var x = /[a-zA-Z+/=]/;"); } diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/Basic.java b/jdk/test/sun/misc/JarIndex/metaInfFilenames/Basic.java new file mode 100644 index 00000000000..27b1f3f51d7 --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/Basic.java @@ -0,0 +1,464 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6887710 + * @summary Verify the impact of sun.misc.JarIndex.metaInfFilenames on Service loaders + * @run main/othervm Basic + */ + +import java.io.IOException; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Iterator; +import java.util.ServiceLoader; +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +/** + * Verifies the impact of sun.misc.JarIndex.metaInfFilenames on service loaders + * (sun.misc.Service & java.util.ServiceLoader), as well as finding resources + * through Class.getResouce. + * + * 1) Compile the test sources: + * jarA: + * META-INF/services/my.happy.land + * com/message/spi/MessageService.java + * a/A.java + * jarB: + * META-INF/JAVA2.DS + * META-INF/services/no.name.service + * b/B.java + * jarC: + * META-INF/fonts.mf + * META-INF/fonts/Company-corporate.ttf + * META-INF/fonts/kidpr.ttf + * META-INF/services/com.message.spi.MessageService + * my/impl/StandardMessageService.java + * + * 2) Build three jar files a.jar, b.jar, c.jar + * + * 3) Create an index in a.jar (jar -i a.jar b.jar c.jar) + * with sun.misc.JarIndex.metaInfFilenames=true + * + * 4) Start a HTTP server serving out the three jars. + * + * The test then tries to locate services/resources within the jars using + * URLClassLoader. Each request to the HTTP server is recorded to ensure + * only the correct amount of requests are being made. + * + * Note: Needs jdk/lib/tools.jar in the classpath to compile and run. + */ + +public class Basic { + static final String slash = File.separator; + static final String[] testSources = { + "jarA" + slash + "a" + slash + "A.java", + "jarA" + slash + "com" + slash + "message" + slash + "spi" + slash + "MessageService.java", + "jarB" + slash + "b" + slash + "B.java", + "jarC" + slash + "my" + slash + "impl" + slash + "StandardMessageService.java"}; + + static final String testSrc = System.getProperty("test.src"); + static final String testSrcDir = testSrc != null ? testSrc : "."; + static final String testClasses = System.getProperty("test.classes"); + static final String testClassesDir = testClasses != null ? testClasses : "."; + + static JarHttpServer httpServer; + + public static void main(String[] args) throws Exception { + + // Set global url cache to false so that we can track every jar request. + (new URL("http://localhost/")).openConnection().setDefaultUseCaches(false); + + buildTest(); + + try { + httpServer = new JarHttpServer(testClassesDir); + httpServer.start(); + + doTest(httpServer.getAddress()); + + } catch (IOException ioe) { + ioe.printStackTrace(); + } finally { + if (httpServer != null) { httpServer.stop(2); } + } + } + + static void buildTest() { + /* compile the source that will be used to generate the jars */ + for (int i=0; i */ + static void jar(String... args) { + debug("Running: jar " + Arrays.toString(args)); + sun.tools.jar.Main jar = new sun.tools.jar.Main(System.out, System.err, "jar"); + if (!jar.run(args)) { + throw new RuntimeException("jar failed: args=" + Arrays.toString(args)); + } + } + + /* run javac */ + static void compile(String... args) { + debug("Running: javac " + Arrays.toString(args)); + com.sun.tools.javac.main.Main compiler = new com.sun.tools.javac.main.Main("javac"); + if (compiler.compile(args) != 0) { + throw new RuntimeException("javac failed: args=" + Arrays.toString(args)); + } + } + + static String jar; + static { + String javaHome = System.getProperty("java.home"); + if (javaHome.endsWith("jre")) { + int index = javaHome.lastIndexOf(slash); + if (index != -1) + javaHome = javaHome.substring(0, index); + } + + jar = javaHome + slash+ "bin" + slash + "jar"; + } + + /* create the index */ + static void createIndex(String workingDir) { + // ProcessBuilder is used so that the current directory can be set + // to the directory that directly contains the jars. + debug("Running jar to create the index"); + ProcessBuilder pb = new ProcessBuilder( + jar, "-J-Dsun.misc.JarIndex.metaInfFilenames=true", "-i", "a.jar", "b.jar", "c.jar"); + pb.directory(new File(workingDir)); + //pd.inheritIO(); + try { + Process p = pb.start(); + if(p.waitFor() != 0) + throw new RuntimeException("jar indexing failed"); + + if(debug && p != null) { + String line = null; + BufferedReader reader = + new BufferedReader(new InputStreamReader(p.getInputStream())); + while((line = reader.readLine()) != null) + debug(line); + reader = new BufferedReader(new InputStreamReader(p.getErrorStream())); + while((line = reader.readLine()) != null) + debug(line); + } + } catch(InterruptedException ie) { throw new RuntimeException(ie); + } catch(IOException e) { throw new RuntimeException(e); } + } + + static final boolean debug = true; + + static void debug(Object message) { if (debug) System.out.println(message); } + + /* service define in c.jar */ + static final String messageService = "com.message.spi.MessageService"; + + /* a service that is not defined in any of the jars */ + static final String unknownService = "java.lang.Object"; + + static void doTest(InetSocketAddress serverAddress) throws IOException { + URL baseURL = new URL("http://localhost:" + serverAddress.getPort() + "/"); + + int failed = 0; + + // Tests using sun.misc.Service + if (!sunMiscServiceTest(baseURL, messageService, true, false, true)) { + System.out.println("Test: sun.misc.Service looking for " + messageService + ", failed"); + failed++; + } + if (!sunMiscServiceTest(baseURL, unknownService, false, false, false)) { + System.out.println("Test: sun.misc.Service looking for " + unknownService + " failed"); + failed++; + } + + // Tests using java.util.SerivceLoader + if (!javaUtilServiceLoaderTest(baseURL, messageService, true, false, true)) { + System.out.println("Test: sun.misc.Service looking for " + messageService + ", failed"); + failed++; + } + if (!javaUtilServiceLoaderTest(baseURL, unknownService, false, false, false)) { + System.out.println("Test: sun.misc.Service looking for " + unknownService + " failed"); + failed++; + } + + // Tests using java.lang.Class (similar to the FontManager in javafx) + if (!klassLoader(baseURL, "/META-INF/fonts.mf", true, false, true)) { + System.out.println("Test: klassLoader looking for /META-INF/fonts.mf failed"); + failed++; + } + if (!klassLoader(baseURL, "/META-INF/unknown.mf", false, false, false)) { + System.out.println("Test: klassLoader looking for /META-INF/unknown.mf failed"); + failed++; + } + + if (failed > 0) + throw new RuntimeException("Failed: " + failed + " tests"); + } + + static boolean sunMiscServiceTest(URL baseURL, + String serviceClass, + boolean expectToFind, + boolean expectbDotJar, + boolean expectcDotJar) throws IOException { + debug("----------------------------------"); + debug("Running test with sun.misc.Service looking for " + serviceClass); + URLClassLoader loader = getLoader(baseURL); + httpServer.reset(); + + Class messageServiceClass = null; + try { + messageServiceClass = loader.loadClass(serviceClass); + } catch (ClassNotFoundException cnfe) { + System.err.println(cnfe); + throw new RuntimeException("Error in test: " + cnfe); + } + + Iterator> iterator = sun.misc.Service.providers(messageServiceClass, loader); + if (expectToFind && !iterator.hasNext()) { + debug(messageServiceClass + " NOT found."); + return false; + } + + while (iterator.hasNext()) { + debug("found " + iterator.next() + " " + messageService); + } + + debug("HttpServer: " + httpServer); + + if (!expectbDotJar && httpServer.bDotJar > 0) { + debug("Unexpeced request sent to the httpserver for b.jar"); + return false; + } + if (!expectcDotJar && httpServer.cDotJar > 0) { + debug("Unexpeced request sent to the httpserver for c.jar"); + return false; + } + + return true; + } + + static boolean javaUtilServiceLoaderTest(URL baseURL, + String serviceClass, + boolean expectToFind, + boolean expectbDotJar, + boolean expectcDotJar) throws IOException { + debug("----------------------------------"); + debug("Running test with java.util.ServiceLoader looking for " + serviceClass); + URLClassLoader loader = getLoader(baseURL); + httpServer.reset(); + + Class messageServiceClass = null; + try { + messageServiceClass = loader.loadClass(serviceClass); + } catch (ClassNotFoundException cnfe) { + System.err.println(cnfe); + throw new RuntimeException("Error in test: " + cnfe); + } + + Iterator> iterator = (ServiceLoader.load(messageServiceClass, loader)).iterator(); + if (expectToFind && !iterator.hasNext()) { + debug(messageServiceClass + " NOT found."); + return false; + } + + while (iterator.hasNext()) { + debug("found " + iterator.next() + " " + messageService); + } + + debug("HttpServer: " + httpServer); + + if (!expectbDotJar && httpServer.bDotJar > 0) { + debug("Unexpeced request sent to the httpserver for b.jar"); + return false; + } + if (!expectcDotJar && httpServer.cDotJar > 0) { + debug("Unexpeced request sent to the httpserver for c.jar"); + return false; + } + + return true; + } + + /* Tries to find a resource in a similar way to the font manager in javafx + * com.sun.javafx.scene.text.FontManager */ + static boolean klassLoader(URL baseURL, + String resource, + boolean expectToFind, + boolean expectbDotJar, + boolean expectcDotJar) throws IOException { + debug("----------------------------------"); + debug("Running test looking for " + resource); + URLClassLoader loader = getLoader(baseURL); + httpServer.reset(); + + Class ADotAKlass = null; + try { + ADotAKlass = loader.loadClass("a.A"); + } catch (ClassNotFoundException cnfe) { + System.err.println(cnfe); + throw new RuntimeException("Error in test: " + cnfe); + } + + URL u = ADotAKlass.getResource(resource); + if (expectToFind && u == null) { + System.out.println("Expected to find " + resource + " but didn't"); + return false; + } + + debug("HttpServer: " + httpServer); + + if (!expectbDotJar && httpServer.bDotJar > 0) { + debug("Unexpeced request sent to the httpserver for b.jar"); + return false; + } + if (!expectcDotJar && httpServer.cDotJar > 0) { + debug("Unexpeced request sent to the httpserver for c.jar"); + return false; + } + + return true; + } + + static URLClassLoader getLoader(URL baseURL) throws IOException { + ClassLoader loader = Basic.class.getClassLoader(); + + while (loader.getParent() != null) + loader = loader.getParent(); + + return new URLClassLoader( new URL[]{ + new URL(baseURL, "a.jar"), + new URL(baseURL, "b.jar"), + new URL(baseURL, "c.jar")}, loader ); + } + + /** + * HTTP Server to server the jar files. + */ + static class JarHttpServer implements HttpHandler { + final String docsDir; + final HttpServer httpServer; + int aDotJar, bDotJar, cDotJar; + + JarHttpServer(String docsDir) throws IOException { + this.docsDir = docsDir; + + httpServer = HttpServer.create(new InetSocketAddress(0), 0); + httpServer.createContext("/", this); + } + + void start() throws IOException { + httpServer.start(); + } + + void stop(int delay) { + httpServer.stop(delay); + } + + InetSocketAddress getAddress() { + return httpServer.getAddress(); + } + + void reset() { + aDotJar = bDotJar = cDotJar = 0; + } + + @Override + public String toString() { + return "aDotJar=" + aDotJar + ", bDotJar=" + bDotJar + ", cDotJar=" + cDotJar; + } + + public void handle(HttpExchange t) throws IOException { + InputStream is = t.getRequestBody(); + Headers map = t.getRequestHeaders(); + Headers rmap = t.getResponseHeaders(); + URI uri = t.getRequestURI(); + + debug("Server: received request for " + uri); + String path = uri.getPath(); + if (path.endsWith("a.jar")) + aDotJar++; + else if (path.endsWith("b.jar")) + bDotJar++; + else if (path.endsWith("c.jar")) + cDotJar++; + else + System.out.println("Unexpected resource request" + path); + + while (is.read() != -1); + is.close(); + + File file = new File(docsDir, path); + if (!file.exists()) + throw new RuntimeException("Error: request for " + file); + long clen = file.length(); + t.sendResponseHeaders (200, clen); + OutputStream os = t.getResponseBody(); + FileInputStream fis = new FileInputStream(file); + try { + byte[] buf = new byte [16 * 1024]; + int len; + while ((len=fis.read(buf)) != -1) { + os.write (buf, 0, len); + } + } catch (IOException e) { + e.printStackTrace(); + } + fis.close(); + os.close(); + } + } +} diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarA/META-INF/services/my.happy.land b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarA/META-INF/services/my.happy.land new file mode 100644 index 00000000000..c109150a938 --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarA/META-INF/services/my.happy.land @@ -0,0 +1,23 @@ +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +# The contents of this file do not matter. It exists +# simply to have a service defined in META-INF/services. diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarA/a/A.java b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarA/a/A.java new file mode 100644 index 00000000000..e22921b7cef --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarA/a/A.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package a; + +public class A { + public static void hello() throws Exception { + System.out.println("Hello from a.A"); + } +} diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarA/com/message/spi/MessageService.java b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarA/com/message/spi/MessageService.java new file mode 100644 index 00000000000..5030191791c --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarA/com/message/spi/MessageService.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.message.spi; + +public interface MessageService { + String message(); +} diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarB/META-INF/JAVA2.DS b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarB/META-INF/JAVA2.DS new file mode 100644 index 00000000000..17f1906ccd0 --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarB/META-INF/JAVA2.DS @@ -0,0 +1,23 @@ +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +# The contents of this file do not matter. It exists +# simply to have a file under META-INF. diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarB/META-INF/services/no.name.service b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarB/META-INF/services/no.name.service new file mode 100644 index 00000000000..6c23e062166 --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarB/META-INF/services/no.name.service @@ -0,0 +1,23 @@ +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +# The contents of this file do not matter. It exists +# simply to have a service defined in META-INF/services. diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarB/b/B.java b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarB/b/B.java new file mode 100644 index 00000000000..a977889e4d8 --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarB/b/B.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package b; + +public class B { + public static void hello() { + System.out.println("Hello from b.B"); + } +} diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/fonts.mf b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/fonts.mf new file mode 100644 index 00000000000..11fd7cef264 --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/fonts.mf @@ -0,0 +1,23 @@ +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +corporate=/fonts/Company-corporate.ttf +crazy-looking=/fonts/kidpr.ttf diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/fonts/Company-corporate.ttf b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/fonts/Company-corporate.ttf new file mode 100644 index 00000000000..b21dd812254 --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/fonts/Company-corporate.ttf @@ -0,0 +1,22 @@ +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +This is not a real font. diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/fonts/kidpr.ttf b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/fonts/kidpr.ttf new file mode 100644 index 00000000000..b21dd812254 --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/fonts/kidpr.ttf @@ -0,0 +1,22 @@ +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +This is not a real font. diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/services/com.message.spi.MessageService b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/services/com.message.spi.MessageService new file mode 100644 index 00000000000..1d36cb068cc --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/META-INF/services/com.message.spi.MessageService @@ -0,0 +1,22 @@ +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +my.impl.StandardMessageService diff --git a/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/my/impl/StandardMessageService.java b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/my/impl/StandardMessageService.java new file mode 100644 index 00000000000..f16b295b0de --- /dev/null +++ b/jdk/test/sun/misc/JarIndex/metaInfFilenames/jarC/my/impl/StandardMessageService.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package my.impl; + +public class StandardMessageService implements com.message.spi.MessageService { + @Override + public String message() { + return "This is a message from the standard message service"; + } +} diff --git a/jdk/test/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java b/jdk/test/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java index ba49c6564b7..d91ce78db4b 100644 --- a/jdk/test/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java +++ b/jdk/test/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as diff --git a/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorEndEntity.java b/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorEndEntity.java index 05e7cc5ad2c..725ed6b5d99 100644 --- a/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorEndEntity.java +++ b/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorEndEntity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,10 @@ /** * @test * - * @bug 6861062 - * @summary Disable MD2 support + * @bug 6861062 7011497 + * @summary Disable MD2 support. + * New CertPathValidatorException.BasicReason enum constant for + * constrained algorithm. * * @author Xuelei Fan */ @@ -35,6 +37,7 @@ import java.net.SocketException; import java.util.*; import java.security.Security; import java.security.cert.*; +import java.security.cert.CertPathValidatorException.*; public class CPValidatorEndEntity { @@ -329,6 +332,13 @@ public class CPValidatorEndEntity { intermediate_SHA1withRSA_1024_1024); throw new Exception("expected algorithm disabled exception"); } catch (CertPathValidatorException cpve) { + // we may get ClassCastException here + BasicReason reason = (BasicReason)cpve.getReason(); + if (reason != BasicReason.ALGORITHM_CONSTRAINED) { + throw new Exception( + "Expect to get ALGORITHM_CONSTRAINED CPVE", cpve); + } + System.out.println("Get the expected exception " + cpve); } @@ -337,6 +347,13 @@ public class CPValidatorEndEntity { intermediate_SHA1withRSA_512_1024); throw new Exception("expected algorithm disabled exception"); } catch (CertPathValidatorException cpve) { + // we may get ClassCastException here + BasicReason reason = (BasicReason)cpve.getReason(); + if (reason != BasicReason.ALGORITHM_CONSTRAINED) { + throw new Exception( + "Expect to get ALGORITHM_CONSTRAINED CPVE", cpve); + } + System.out.println("Get the expected exception " + cpve); } } diff --git a/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorIntermediate.java b/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorIntermediate.java index 871afe35483..6b4f3cdc126 100644 --- a/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorIntermediate.java +++ b/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorIntermediate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,10 @@ /** * @test * - * @bug 6861062 + * @bug 6861062 7011497 * @summary Disable MD2 support + * new CertPathValidatorException.BasicReason enum constant for + * constrained algorithm * * @author Xuelei Fan */ @@ -35,6 +37,7 @@ import java.net.SocketException; import java.util.*; import java.security.Security; import java.security.cert.*; +import java.security.cert.CertPathValidatorException.*; public class CPValidatorIntermediate { @@ -223,6 +226,13 @@ public class CPValidatorIntermediate { validate(intermediate_MD2withRSA_1024_1024); throw new Exception("expected algorithm disabled exception"); } catch (CertPathValidatorException cpve) { + // we may get ClassCastException here + BasicReason reason = (BasicReason)cpve.getReason(); + if (reason != BasicReason.ALGORITHM_CONSTRAINED) { + throw new Exception( + "Expect to get ALGORITHM_CONSTRAINED CPVE", cpve); + } + System.out.println("Get the expected exception " + cpve); } @@ -230,6 +240,13 @@ public class CPValidatorIntermediate { validate(intermediate_MD2withRSA_1024_512); throw new Exception("expected algorithm disabled exception"); } catch (CertPathValidatorException cpve) { + // we may get ClassCastException here + BasicReason reason = (BasicReason)cpve.getReason(); + if (reason != BasicReason.ALGORITHM_CONSTRAINED) { + throw new Exception( + "Expect to get ALGORITHM_CONSTRAINED CPVE", cpve); + } + System.out.println("Get the expected exception " + cpve); } } diff --git a/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java b/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java index 94f7f288a1c..e1a70002073 100644 --- a/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java +++ b/jdk/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,10 @@ /** * @test * - * @bug 6861062 + * @bug 6861062 7011497 * @summary Disable MD2 support + * new CertPathValidatorException.BasicReason enum constant for + * constrained algorithm * * @author Xuelei Fan */ @@ -35,6 +37,7 @@ import java.net.SocketException; import java.util.*; import java.security.Security; import java.security.cert.*; +import java.security.cert.CertPathValidatorException.*; public class CPValidatorTrustAnchor { @@ -142,6 +145,13 @@ public class CPValidatorTrustAnchor { validate(trustAnchor_MD2withRSA_2048); throw new Exception("expected algorithm disabled exception"); } catch (CertPathValidatorException cpve) { + // we may get ClassCastException here + BasicReason reason = (BasicReason)cpve.getReason(); + if (reason != BasicReason.ALGORITHM_CONSTRAINED) { + throw new Exception( + "Expect to get ALGORITHM_CONSTRAINED CPVE", cpve); + } + System.out.println("Get the expected exception " + cpve); } } diff --git a/jdk/test/tools/launcher/Arrrghs.java b/jdk/test/tools/launcher/Arrrghs.java index de3dbe20112..1db933833ea 100644 --- a/jdk/test/tools/launcher/Arrrghs.java +++ b/jdk/test/tools/launcher/Arrrghs.java @@ -24,7 +24,7 @@ /** * @test * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938 - * 6894719 + * 6894719 6968053 * @summary Argument parsing validation. * @compile -XDignore.symbol.file Arrrghs.java TestHelper.java * @run main Arrrghs @@ -250,13 +250,11 @@ public class Arrrghs { TestHelper.createJar("MIA", new File("some.jar"), new File("Foo"), (String[])null); tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar"); - tr.contains("Error: Could not find main class MIA"); - tr.contains("java.lang.NoClassDefFoundError: MIA"); + tr.contains("Error: Could not find or load main class MIA"); System.out.println(tr); // use classpath to check tr = TestHelper.doExec(TestHelper.javaCmd, "-cp", "some.jar", "MIA"); - tr.contains("Error: Could not find main class MIA"); - tr.contains("java.lang.NoClassDefFoundError: MIA"); + tr.contains("Error: Could not find or load main class MIA"); System.out.println(tr); // incorrect method access @@ -305,12 +303,12 @@ public class Arrrghs { // amongst a potpourri of kindred main methods, is the right one chosen ? TestHelper.createJar(new File("some.jar"), new File("Foo"), - "void main(Object[] args){}", - "int main(Float[] args){return 1;}", - "private void main() {}", - "private static void main(int x) {}", - "public int main(int argc, String[] argv) {return 1;}", - "public static void main(String[] args) {System.out.println(\"THE_CHOSEN_ONE\");}"); + "void main(Object[] args){}", + "int main(Float[] args){return 1;}", + "private void main() {}", + "private static void main(int x) {}", + "public int main(int argc, String[] argv) {return 1;}", + "public static void main(String[] args) {System.out.println(\"THE_CHOSEN_ONE\");}"); tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar"); tr.contains("THE_CHOSEN_ONE"); System.out.println(tr); @@ -326,6 +324,30 @@ public class Arrrghs { tr.checkPositive(); System.out.println(tr); } + // tests 6968053, ie. we turn on the -Xdiag (for now) flag and check if + // the suppressed stack traces are exposed. + static void runDiagOptionTests() throws FileNotFoundException { + TestHelper.TestResult tr = null; + // a missing class + TestHelper.createJar("MIA", new File("some.jar"), new File("Foo"), + (String[])null); + tr = TestHelper.doExec(TestHelper.javaCmd, "-Xdiag", "-jar", "some.jar"); + tr.contains("Error: Could not find or load main class MIA"); + tr.contains("java.lang.ClassNotFoundException: MIA"); + System.out.println(tr); + + // use classpath to check + tr = TestHelper.doExec(TestHelper.javaCmd, "-Xdiag", "-cp", "some.jar", "MIA"); + tr.contains("Error: Could not find or load main class MIA"); + tr.contains("java.lang.ClassNotFoundException: MIA"); + System.out.println(tr); + + // a missing class on the classpath + tr = TestHelper.doExec(TestHelper.javaCmd, "-Xdiag", "NonExistentClass"); + tr.contains("Error: Could not find or load main class NonExistentClass"); + tr.contains("java.lang.ClassNotFoundException: NonExistentClass"); + System.out.println(tr); + } static void test6894719() { // test both arguments to ensure they exist @@ -352,6 +374,7 @@ public class Arrrghs { runBasicErrorMessageTests(); runMainMethodTests(); test6894719(); + runDiagOptionTests(); if (TestHelper.testExitValue > 0) { System.out.println("Total of " + TestHelper.testExitValue + " failed"); System.exit(1);