diff --git a/jdk/src/share/classes/java/nio/file/Files.java b/jdk/src/share/classes/java/nio/file/Files.java index 3e19ca3e515..8b7af13544c 100644 --- a/jdk/src/share/classes/java/nio/file/Files.java +++ b/jdk/src/share/classes/java/nio/file/Files.java @@ -1712,10 +1712,10 @@ public final class Files { * @return the {@code path} parameter * * @throws UnsupportedOperationException - * if the attribute view is not available or it does not support - * updating the attribute + * if the attribute view is not available * @throws IllegalArgumentException - * if the attribute value is of the correct type but has an + * if the attribute name is not specified, or is not recognized, or + * 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 @@ -1776,9 +1776,12 @@ public final class Files { * @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 + * @return the attribute value * + * @throws UnsupportedOperationException + * if the attribute view is not available + * @throws IllegalArgumentException + * if the attribute name is not specified or is not recognized * @throws IOException * if an I/O error occurs * @throws SecurityException @@ -1794,8 +1797,9 @@ public final class Files { { // only one attribute should be read if (attribute.indexOf('*') >= 0 || attribute.indexOf(',') >= 0) - return null; + throw new IllegalArgumentException(attribute); Map map = readAttributes(path, attribute, options); + assert map.size() == 1; String name; int pos = attribute.indexOf(':'); if (pos == -1) { @@ -1868,9 +1872,14 @@ public final class Files { * @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 + * @return a map of the attributes returned; The map's keys are the + * attribute names, its values are the attribute values * + * @throws UnsupportedOperationException + * if the attribute view is not available + * @throws IllegalArgumentException + * if no attributes are specified or an unrecognized attributes is + * specified * @throws IOException * if an I/O error occurs * @throws SecurityException diff --git a/jdk/src/share/classes/java/nio/file/Path.java b/jdk/src/share/classes/java/nio/file/Path.java index 85436b01d9a..618f0226363 100644 --- a/jdk/src/share/classes/java/nio/file/Path.java +++ b/jdk/src/share/classes/java/nio/file/Path.java @@ -228,6 +228,9 @@ public interface Path * not have a root component and the given path has a root component then * this path does not start with the given path. * + *

If the given path is associated with a different {@code FileSystem} + * to this path then {@code false} is returned. + * * @param other * the given path * @@ -270,6 +273,9 @@ public interface Path * does not have a root component and the given path has a root component * then this path does not end with the given path. * + *

If the given path is associated with a different {@code FileSystem} + * to this path then {@code false} is returned. + * * @param other * the given path * @@ -283,7 +289,10 @@ public interface Path * 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}". + * not end with "{@code r}" or "{@code /bar}". Note that trailing separators + * are not taken into account, and so invoking this method on the {@code + * Path}"{@code foo/bar}" with the {@code String} "{@code bar/}" returns + * {@code true}. * * @param other * the given path string @@ -724,12 +733,18 @@ public interface Path * provider, platform specific. This method does not access the file system * and neither file is required to exist. * + *

This method may not be used to compare paths that are associated + * with different file system providers. + * * @param other the path compared to this path. * * @return zero if the argument is {@link #equals equal} to this path, a * value less than zero if this path is lexicographically less than * the argument, or a value greater than zero if this path is * lexicographically greater than the argument + * + * @throws ClassCastException + * if the paths are associated with different providers */ @Override int compareTo(Path other); @@ -738,7 +753,7 @@ public interface Path * Tests this path for equality with the given object. * *

If the given object is not a Path, or is a Path associated with a - * different provider, then this method immediately returns {@code false}. + * different {@code FileSystem}, then this method returns {@code false}. * *

Whether or not two path are equal depends on the file system * implementation. In some cases the paths are compared without regard diff --git a/jdk/src/share/classes/java/nio/file/WatchKey.java b/jdk/src/share/classes/java/nio/file/WatchKey.java index 23897dba454..83403e96a3b 100644 --- a/jdk/src/share/classes/java/nio/file/WatchKey.java +++ b/jdk/src/share/classes/java/nio/file/WatchKey.java @@ -146,5 +146,5 @@ public interface WatchKey { * * @return the object for which this watch key was created */ - //T watchable(); + Watchable watchable(); } 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 6cac437cdce..4e77b0e0172 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/FileTime.java +++ b/jdk/src/share/classes/java/nio/file/attribute/FileTime.java @@ -216,12 +216,14 @@ public final class FileTime * "2009-02-13T23:31:30Z"}, and {@code FileTime.fromMillis(1234567890123L).toString()} * yields {@code "2009-02-13T23:31:30.123Z"}. * - *

A {@code FileTime} is primarly intended to represent the value of a + *

A {@code FileTime} is primarily intended to represent the value of a * file's time stamp. Where used to represent extreme values, where * the year is less than "{@code 0001}" or greater than "{@code 9999}" then - * the year may be expanded to more than four digits and may be - * negative-signed. If more than four digits then leading zeros are not - * present. The year before "{@code 0001}" is "{@code -0001}". + * this method deviates from ISO 8601 in the same manner as the + * XML Schema + * language. That is, the year may be expanded to more than four digits + * and may be negative-signed. If more than four digits then leading zeros + * are not present. The year before "{@code 0001}" is "{@code -0001}". * * @return the string representation of this file time */ 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 ad285bd6ddb..8d43fb93769 100644 --- a/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java +++ b/jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java @@ -1037,6 +1037,11 @@ public abstract class FileSystemProvider { * @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 UnsupportedOperationException + * if the attribute view is not available + * @throws IllegalArgumentException + * if no attributes are specified or an unrecognized attributes is + * specified * @throws IOException * If an I/O error occurs * @throws SecurityException @@ -1064,10 +1069,10 @@ public abstract class FileSystemProvider { * options indicating how symbolic links are handled * * @throws UnsupportedOperationException - * if the attribute view is not available or it does not support - * updating the attribute + * if the attribute view is not available * @throws IllegalArgumentException - * if the attribute value is of the correct type but has an + * if the attribute name is not specified, or is not recognized, or + * 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 diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java index cd1e6c26b8d..33eeb315f43 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractAclFileAttributeView.java @@ -57,8 +57,8 @@ abstract class AbstractAclFileAttributeView setAcl((List)value); return; } - throw new UnsupportedOperationException("'" + name() + ":" + - attribute + "' not supported"); + throw new IllegalArgumentException("'" + name() + ":" + + attribute + "' not recognized"); } @Override @@ -81,6 +81,8 @@ abstract class AbstractAclFileAttributeView owner = true; continue; } + throw new IllegalArgumentException("'" + name() + ":" + + attribute + "' not recognized"); } Map result = new HashMap<>(2); if (acl) diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java index 6383c08edf1..9fa04ee7f8e 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java @@ -46,6 +46,18 @@ abstract class AbstractBasicFileAttributeView private static final String IS_SYMBOLIC_LINK_NAME = "isSymbolicLink"; private static final String IS_OTHER_NAME = "isOther"; + // the names of the basic attributes + static final Set basicAttributeNames = + Util.newSet(SIZE_NAME, + CREATION_TIME_NAME, + LAST_ACCESS_TIME_NAME, + LAST_MODIFIED_TIME_NAME, + FILE_KEY_NAME, + IS_DIRECTORY_NAME, + IS_REGULAR_FILE_NAME, + IS_SYMBOLIC_LINK_NAME, + IS_OTHER_NAME); + protected AbstractBasicFileAttributeView() { } @Override @@ -69,24 +81,26 @@ abstract class AbstractBasicFileAttributeView setTimes(null, null, (FileTime)value); return; } - throw new UnsupportedOperationException("'" + attribute + - "' is unknown or read-only attribute"); + throw new IllegalArgumentException("'" + name() + ":" + + attribute + "' not recognized"); } /** * Used to build a map of attribute name/values. */ static class AttributesBuilder { - private Set set = new HashSet<>(); + private Set names = new HashSet<>(); private Map map = new HashMap<>(); private boolean copyAll; - private AttributesBuilder(String[] attributes) { - for (String attribute: attributes) { - if (attribute.equals("*")) { + private AttributesBuilder(Set allowed, String[] requested) { + for (String name: requested) { + if (name.equals("*")) { copyAll = true; } else { - set.add(attribute); + if (!allowed.contains(name)) + throw new IllegalArgumentException("'" + name + "' not recognized"); + names.add(name); } } } @@ -94,21 +108,19 @@ abstract class AbstractBasicFileAttributeView /** * Creates builder to build up a map of the matching attributes */ - static AttributesBuilder create(String[] attributes) { - return new AttributesBuilder(attributes); + static AttributesBuilder create(Set allowed, String[] requested) { + return new AttributesBuilder(allowed, requested); } /** * Returns true if the attribute should be returned in the map */ - boolean match(String attribute) { - if (copyAll) - return true; - return set.contains(attribute); + boolean match(String name) { + return copyAll || names.contains(name); } - void add(String attribute, Object value) { - map.put(attribute, value); + void add(String name, Object value) { + map.put(name, value); } /** @@ -124,7 +136,7 @@ abstract class AbstractBasicFileAttributeView * Invoked by readAttributes or sub-classes to add all matching basic * attributes to the builder */ - final void addBasicAttributesToBuilder(BasicFileAttributes attrs, + final void addRequestedBasicAttributes(BasicFileAttributes attrs, AttributesBuilder builder) { if (builder.match(SIZE_NAME)) @@ -148,9 +160,12 @@ abstract class AbstractBasicFileAttributeView } @Override - public Map readAttributes(String[] attributes) throws IOException { - AttributesBuilder builder = AttributesBuilder.create(attributes); - addBasicAttributesToBuilder(readAttributes(), builder); + public Map readAttributes(String[] requested) + throws IOException + { + AttributesBuilder builder = + AttributesBuilder.create(basicAttributeNames, requested); + addRequestedBasicAttributes(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 index 95d1cb30931..9e1dc6133ac 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java @@ -29,7 +29,6 @@ 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 @@ -72,6 +71,8 @@ abstract class AbstractFileSystemProvider extends FileSystemProvider { throws IOException { String[] s = split(attribute); + if (s[0].length() == 0) + throw new IllegalArgumentException(attribute); DynamicFileAttributeView view = getFileAttributeView(file, s[0], options); if (view == null) throw new UnsupportedOperationException("View '" + s[0] + "' not available"); @@ -83,9 +84,11 @@ abstract class AbstractFileSystemProvider extends FileSystemProvider { throws IOException { String[] s = split(attributes); + if (s[0].length() == 0) + throw new IllegalArgumentException(attributes); DynamicFileAttributeView view = getFileAttributeView(file, s[0], options); if (view == null) - return Collections.emptyMap(); + throw new UnsupportedOperationException("View '" + s[0] + "' not available"); return view.readAttributes(s[1].split(",")); } diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java b/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java index cf36a09ff0a..8a4f975c4f4 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java @@ -59,22 +59,6 @@ abstract class AbstractUserDefinedFileAttributeView return "user"; } - private Object getAttribute(String attribute) throws IOException { - int size; - try { - size = size(attribute); - } catch (IOException e) { - // not found or some other I/O error - if (list().contains(attribute)) - throw e; - return null; - } - - byte[] buf = new byte[size]; - int n = read(attribute, ByteBuffer.wrap(buf)); - return (n == size) ? buf : Arrays.copyOf(buf, n); - } - @Override public final void setAttribute(String attribute, Object value) throws IOException @@ -94,12 +78,13 @@ abstract class AbstractUserDefinedFileAttributeView { // names of attributes to return List names = new ArrayList<>(); - for (String name: attributes) { if (name.equals("*")) { names = list(); break; } else { + if (name.length() == 0) + throw new IllegalArgumentException(); names.add(name); } } @@ -107,11 +92,12 @@ abstract class AbstractUserDefinedFileAttributeView // read each value and return in map Map result = new HashMap<>(); for (String name: names) { - Object value = getAttribute(name); - if (value != null) - result.put(name, value); + int size = size(name); + byte[] buf = new byte[size]; + int n = read(name, ByteBuffer.wrap(buf)); + byte[] value = (n == size) ? buf : Arrays.copyOf(buf, n); + result.put(name, value); } - return result; } } diff --git a/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java b/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java index 55234ba6528..f083f46313a 100644 --- a/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java +++ b/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java @@ -81,7 +81,8 @@ abstract class AbstractWatchKey implements WatchKey { /** * Return the original watchable (Path) */ - Path watchable() { + @Override + public Path watchable() { return dir; } diff --git a/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java b/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java index aae9bd318c1..5fcb21e264a 100644 --- a/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java +++ b/jdk/src/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java @@ -63,10 +63,10 @@ final class FileOwnerAttributeViewImpl { if (attribute.equals(OWNER_NAME)) { setOwner((UserPrincipal)value); - return; + } else { + throw new IllegalArgumentException("'" + name() + ":" + + attribute + "' not recognized"); } - throw new UnsupportedOperationException("'" + name() + ":" + - attribute + "' not supported"); } @Override @@ -75,6 +75,9 @@ final class FileOwnerAttributeViewImpl for (String attribute: attributes) { if (attribute.equals("*") || attribute.equals(OWNER_NAME)) { result.put(OWNER_NAME, getOwner()); + } else { + throw new IllegalArgumentException("'" + name() + ":" + + attribute + "' not recognized"); } } return result; diff --git a/jdk/src/share/classes/sun/nio/fs/Util.java b/jdk/src/share/classes/sun/nio/fs/Util.java index 6a289058e4b..76287011169 100644 --- a/jdk/src/share/classes/sun/nio/fs/Util.java +++ b/jdk/src/share/classes/sun/nio/fs/Util.java @@ -25,6 +25,8 @@ package sun.nio.fs; +import java.util.*; + /** * Utility methods */ @@ -54,6 +56,28 @@ class Util { } result[n] = s.substring(last, s.length()); return result; + } + /** + * Returns a Set containing the given elements. + */ + static Set newSet(E... elements) { + HashSet set = new HashSet<>(); + for (E e: elements) { + set.add(e); + } + return set; + } + + /** + * Returns a Set containing all the elements of the given Set plus + * the given elements. + */ + static Set newSet(Set other, E... elements) { + HashSet set = new HashSet<>(other); + for (E e: elements) { + set.add(e); + } + return set; } } diff --git a/jdk/src/share/sample/nio/file/WatchDir.java b/jdk/src/share/sample/nio/file/WatchDir.java index 33c15dd0c04..796b728206b 100644 --- a/jdk/src/share/sample/nio/file/WatchDir.java +++ b/jdk/src/share/sample/nio/file/WatchDir.java @@ -33,8 +33,7 @@ import java.nio.file.*; import static java.nio.file.StandardWatchEventKind.*; import static java.nio.file.LinkOption.*; import java.nio.file.attribute.*; -import java.io.*; -import java.util.*; +import java.io.IOException; /** * Example to watch a directory (or tree) for changes to files. @@ -43,9 +42,9 @@ import java.util.*; public class WatchDir { private final WatchService watcher; - private final Map keys; private final boolean recursive; private boolean trace = false; + private int count; @SuppressWarnings("unchecked") static WatchEvent cast(WatchEvent event) { @@ -57,17 +56,9 @@ public class WatchDir { */ private void register(Path dir) throws IOException { WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); - if (trace) { - Path prev = keys.get(key); - if (prev == null) { - System.out.format("register: %s\n", dir); - } else { - if (!dir.equals(prev)) { - System.out.format("update: %s -> %s\n", prev, dir); - } - } - } - keys.put(key, dir); + count++; + if (trace) + System.out.format("register: %s\n", dir); } /** @@ -92,7 +83,6 @@ public class WatchDir { */ WatchDir(Path dir, boolean recursive) throws IOException { this.watcher = FileSystems.getDefault().newWatchService(); - this.keys = new HashMap(); this.recursive = recursive; if (recursive) { @@ -121,12 +111,6 @@ public class WatchDir { return; } - Path dir = keys.get(key); - if (dir == null) { - System.err.println("WatchKey not recognized!!"); - continue; - } - for (WatchEvent event: key.pollEvents()) { WatchEvent.Kind kind = event.kind(); @@ -138,7 +122,7 @@ public class WatchDir { // Context for directory entry event is the file name of entry WatchEvent ev = cast(event); Path name = ev.context(); - Path child = dir.resolve(name); + Path child = ((Path)key.watchable()).resolve(name); // print out event System.out.format("%s: %s\n", event.kind().name(), child); @@ -156,15 +140,13 @@ public class WatchDir { } } - // reset key and remove from set if directory no longer accessible + // reset key boolean valid = key.reset(); if (!valid) { - keys.remove(key); - - // all directories are inaccessible - if (keys.isEmpty()) { + // directory no longer accessible + count--; + if (count == 0) break; - } } } } diff --git a/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java b/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java index 4499a08924c..af0dc1036bd 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java +++ b/jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java @@ -27,6 +27,7 @@ package sun.nio.fs; import java.nio.file.attribute.*; import java.util.Map; +import java.util.Set; import java.io.IOException; import sun.misc.Unsafe; @@ -57,6 +58,10 @@ class LinuxDosFileAttributeView private static final int DOS_XATTR_SYSTEM = 0x04; private static final int DOS_XATTR_ARCHIVE = 0x20; + // the names of the DOS attributes (includes basic) + private static final Set dosAttributeNames = + Util.newSet(basicAttributeNames, READONLY_NAME, ARCHIVE_NAME, SYSTEM_NAME, HIDDEN_NAME); + LinuxDosFileAttributeView(UnixPath file, boolean followLinks) { super(file, followLinks); } @@ -93,9 +98,10 @@ class LinuxDosFileAttributeView public Map readAttributes(String[] attributes) throws IOException { - AttributesBuilder builder = AttributesBuilder.create(attributes); + AttributesBuilder builder = + AttributesBuilder.create(dosAttributeNames, attributes); DosFileAttributes attrs = readAttributes(); - addBasicAttributesToBuilder(attrs, builder); + addRequestedBasicAttributes(attrs, builder); if (builder.match(READONLY_NAME)) builder.add(READONLY_NAME, attrs.isReadOnly()); if (builder.match(ARCHIVE_NAME)) diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java index c21a17707a8..ad0a2a00d12 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java @@ -123,6 +123,10 @@ class UnixFileAttributeViews { private static final String OWNER_NAME = "owner"; private static final String GROUP_NAME = "group"; + // the names of the posix attributes (incudes basic) + static final Set posixAttributeNames = + Util.newSet(basicAttributeNames, PERMISSIONS_NAME, OWNER_NAME, GROUP_NAME); + Posix(UnixPath file, boolean followLinks) { super(file, followLinks); } @@ -172,9 +176,10 @@ class UnixFileAttributeViews { * Invoked by readAttributes or sub-classes to add all matching posix * attributes to the builder */ - final void addPosixAttributesToBuilder(PosixFileAttributes attrs, + final void addRequestedPosixAttributes(PosixFileAttributes attrs, AttributesBuilder builder) { + addRequestedBasicAttributes(attrs, builder); if (builder.match(PERMISSIONS_NAME)) builder.add(PERMISSIONS_NAME, attrs.permissions()); if (builder.match(OWNER_NAME)) @@ -184,13 +189,13 @@ class UnixFileAttributeViews { } @Override - public Map readAttributes(String[] attributes) + public Map readAttributes(String[] requested) throws IOException { - AttributesBuilder builder = AttributesBuilder.create(attributes); + AttributesBuilder builder = + AttributesBuilder.create(posixAttributeNames, requested); PosixFileAttributes attrs = readAttributes(); - addBasicAttributesToBuilder(attrs, builder); - addPosixAttributesToBuilder(attrs, builder); + addRequestedPosixAttributes(attrs, builder); return builder.unmodifiableMap(); } @@ -287,6 +292,12 @@ class UnixFileAttributeViews { private static final String GID_NAME = "gid"; private static final String CTIME_NAME = "ctime"; + // the names of the unix attributes (including posix) + static final Set unixAttributeNames = + Util.newSet(posixAttributeNames, + MODE_NAME, INO_NAME, DEV_NAME, RDEV_NAME, + NLINK_NAME, UID_NAME, GID_NAME, CTIME_NAME); + Unix(UnixPath file, boolean followLinks) { super(file, followLinks); } @@ -316,13 +327,13 @@ class UnixFileAttributeViews { } @Override - public Map readAttributes(String[] attributes) + public Map readAttributes(String[] requested) throws IOException { - AttributesBuilder builder = AttributesBuilder.create(attributes); + AttributesBuilder builder = + AttributesBuilder.create(unixAttributeNames, requested); UnixFileAttributes attrs = readAttributes(); - addBasicAttributesToBuilder(attrs, builder); - addPosixAttributesToBuilder(attrs, builder); + addRequestedPosixAttributes(attrs, builder); if (builder.match(MODE_NAME)) builder.add(MODE_NAME, attrs.mode()); if (builder.match(INO_NAME)) diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java index 9ec49b8d37a..b392b56b7e9 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java @@ -606,7 +606,9 @@ class UnixPath @Override public boolean startsWith(Path other) { - UnixPath that = toUnixPath(other); + if (!(Objects.requireNonNull(other) instanceof UnixPath)) + return false; + UnixPath that = (UnixPath)other; // other path is longer if (that.path.length > path.length) @@ -655,7 +657,9 @@ class UnixPath @Override public boolean endsWith(Path other) { - UnixPath that = toUnixPath(other); + if (!(Objects.requireNonNull(other) instanceof UnixPath)) + return false; + UnixPath that = (UnixPath)other; int thisLen = path.length; int thatLen = that.path.length; diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java index 8a81b87a0ab..67e5be670e0 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java @@ -157,6 +157,11 @@ class WindowsFileAttributeViews { private static final String HIDDEN_NAME = "hidden"; private static final String ATTRIBUTES_NAME = "attributes"; + // the names of the DOS attribtues (includes basic) + static final Set dosAttributeNames = + Util.newSet(basicAttributeNames, + READONLY_NAME, ARCHIVE_NAME, SYSTEM_NAME, HIDDEN_NAME, ATTRIBUTES_NAME); + Dos(WindowsPath file, boolean followLinks) { super(file, followLinks); } @@ -193,9 +198,10 @@ class WindowsFileAttributeViews { public Map readAttributes(String[] attributes) throws IOException { - AttributesBuilder builder = AttributesBuilder.create(attributes); + AttributesBuilder builder = + AttributesBuilder.create(dosAttributeNames, attributes); WindowsFileAttributes attrs = readAttributes(); - addBasicAttributesToBuilder(attrs, builder); + addRequestedBasicAttributes(attrs, builder); if (builder.match(READONLY_NAME)) builder.add(READONLY_NAME, attrs.isReadOnly()); if (builder.match(ARCHIVE_NAME)) diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java index 26c2b26ce8e..eb35de8167e 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java @@ -646,7 +646,9 @@ class WindowsPath extends AbstractPath { @Override public boolean startsWith(Path obj) { - WindowsPath other = toWindowsPath(obj); + if (!(Objects.requireNonNull(obj) instanceof WindowsPath)) + return false; + WindowsPath other = (WindowsPath)obj; // if this path has a root component the given path's root must match if (!this.root.equalsIgnoreCase(other.root)) { @@ -675,7 +677,9 @@ class WindowsPath extends AbstractPath { @Override public boolean endsWith(Path obj) { - WindowsPath other = toWindowsPath(obj); + if (!(Objects.requireNonNull(obj) instanceof WindowsPath)) + return false; + WindowsPath other = (WindowsPath)obj; // other path is longer if (other.path.length() > this.path.length()) { diff --git a/jdk/test/java/nio/file/Files/FileAttributes.java b/jdk/test/java/nio/file/Files/FileAttributes.java index bd799dc6b1e..d8aea7fe3ba 100644 --- a/jdk/test/java/nio/file/Files/FileAttributes.java +++ b/jdk/test/java/nio/file/Files/FileAttributes.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6838333 + * @bug 4313887 6838333 7017446 * @summary Unit test for java.nio.file.Files * @library .. */ @@ -94,12 +94,6 @@ public class FileAttributes { assertTrue(map.size() == 2); checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime")); - - map = Files.readAttributes(file, - "basic:lastModifiedTime,lastAccessTime,ShouldNotExist"); - assertTrue(map.size() == 2); - checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime")); - checkEqual(attrs.lastAccessTime(), map.get("lastAccessTime")); } // Exercise getAttribute/setAttribute/readAttributes on posix attributes @@ -132,7 +126,7 @@ public class FileAttributes { assertTrue(map.size() >= 12); checkEqual(attrs.permissions(), map.get("permissions")); // check one - map = Files.readAttributes(file, "posix:size,owner,ShouldNotExist"); + map = Files.readAttributes(file, "posix:size,owner"); assertTrue(map.size() == 2); checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.owner(), map.get("owner")); @@ -155,7 +149,7 @@ public class FileAttributes { map = Files.readAttributes(file, "unix:*"); assertTrue(map.size() >= 20); - map = Files.readAttributes(file, "unix:size,uid,gid,ShouldNotExist"); + map = Files.readAttributes(file, "unix:size,uid,gid"); assertTrue(map.size() == 3); checkEqual(map.get("size"), Files.readAttributes(file, BasicFileAttributes.class).size()); @@ -206,14 +200,65 @@ public class FileAttributes { assertTrue(map.size() >= 13); checkEqual(attrs.isReadOnly(), map.get("readonly")); // check one - map = Files.readAttributes(file, "dos:size,hidden,ShouldNotExist"); + map = Files.readAttributes(file, "dos:size,hidden"); assertTrue(map.size() == 2); checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.isHidden(), map.get("hidden")); } + static void checkBadSet(Path file, String attribute, Object value) + throws IOException + { + try { + Files.setAttribute(file, attribute, 0); + throw new RuntimeException("IllegalArgumentException expected"); + } catch (IllegalArgumentException ignore) { } + } + + static void checkBadGet(Path file, String attribute) throws IOException { + try { + Files.getAttribute(file, attribute); + throw new RuntimeException("IllegalArgumentException expected"); + } catch (IllegalArgumentException ignore) { } + } + + static void checkBadRead(Path file, String attribute) throws IOException { + try { + Files.readAttributes(file, attribute); + throw new RuntimeException("IllegalArgumentException expected"); + } catch (IllegalArgumentException ignore) { } + } + static void miscTests(Path file) throws IOException { - // NPE tests + // unsupported views + try { + Files.setAttribute(file, "foo:bar", 0); + throw new RuntimeException("UnsupportedOperationException expected"); + } catch (UnsupportedOperationException ignore) { } + try { + Files.getAttribute(file, "foo:bar"); + throw new RuntimeException("UnsupportedOperationException expected"); + } catch (UnsupportedOperationException ignore) { } + try { + Files.readAttributes(file, "foo:*"); + throw new RuntimeException("UnsupportedOperationException expected"); + } catch (UnsupportedOperationException ignore) { } + + // bad args + checkBadSet(file, "", 0); + checkBadSet(file, "basic:", 0); + checkBadSet(file, "basic:foobar", 0); + checkBadGet(file, ""); + checkBadGet(file, "basic:"); + checkBadGet(file, "basic:foobar"); + checkBadGet(file, "basic:size,lastModifiedTime"); + checkBadGet(file, "basic:*"); + checkBadRead(file, ""); + checkBadRead(file, "basic:"); + checkBadRead(file, "basic:foobar"); + checkBadRead(file, "basic:size,foobar"); + + // nulls try { Files.getAttribute(file, null); throw new RuntimeException("NullPointerException expected"); diff --git a/jdk/test/java/nio/file/WatchService/Basic.java b/jdk/test/java/nio/file/WatchService/Basic.java index 2869a519f37..1b4c526dbd8 100644 --- a/jdk/test/java/nio/file/WatchService/Basic.java +++ b/jdk/test/java/nio/file/WatchService/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6838333 + * @bug 4313887 6838333 7017446 * @summary Unit test for java.nio.file.WatchService * @library .. * @run main/timeout=120 Basic @@ -44,6 +44,8 @@ public class Basic { static void checkKey(WatchKey key, Path dir) { if (!key.isValid()) throw new RuntimeException("Key is not valid"); + if (key.watchable() != dir) + throw new RuntimeException("Unexpected watchable"); } static void takeExpectedKey(WatchService watcher, WatchKey expected) { diff --git a/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java b/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java index a6af4192234..c8c07b4d8e4 100644 --- a/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java +++ b/jdk/test/java/nio/file/attribute/UserDefinedFileAttributeView/Basic.java @@ -141,9 +141,6 @@ public class Basic { map = Files.readAttributes(file, "user:*"); if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME))) throw new RuntimeException("Unexpected attribute value"); - 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 {