提交 b977a1ca 编写于 作者: A alanb

7017446: (fs) Updates to file system API (3/2011)

Reviewed-by: sherman
上级 69d4354d
...@@ -1712,10 +1712,10 @@ public final class Files { ...@@ -1712,10 +1712,10 @@ public final class Files {
* @return the {@code path} parameter * @return the {@code path} parameter
* *
* @throws UnsupportedOperationException * @throws UnsupportedOperationException
* if the attribute view is not available or it does not support * if the attribute view is not available
* updating the attribute
* @throws IllegalArgumentException * @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 * inappropriate value
* @throws ClassCastException * @throws ClassCastException
* if the attribute value is not of the expected type or is a * if the attribute value is not of the expected type or is a
...@@ -1776,9 +1776,12 @@ public final class Files { ...@@ -1776,9 +1776,12 @@ public final class Files {
* @param options * @param options
* options indicating how symbolic links are handled * options indicating how symbolic links are handled
* *
* @return the attribute value or {@code null} if the attribute view * @return the attribute value
* is not available or it does not support reading the attribute
* *
* @throws UnsupportedOperationException
* if the attribute view is not available
* @throws IllegalArgumentException
* if the attribute name is not specified or is not recognized
* @throws IOException * @throws IOException
* if an I/O error occurs * if an I/O error occurs
* @throws SecurityException * @throws SecurityException
...@@ -1794,8 +1797,9 @@ public final class Files { ...@@ -1794,8 +1797,9 @@ public final class Files {
{ {
// only one attribute should be read // only one attribute should be read
if (attribute.indexOf('*') >= 0 || attribute.indexOf(',') >= 0) if (attribute.indexOf('*') >= 0 || attribute.indexOf(',') >= 0)
return null; throw new IllegalArgumentException(attribute);
Map<String,Object> map = readAttributes(path, attribute, options); Map<String,Object> map = readAttributes(path, attribute, options);
assert map.size() == 1;
String name; String name;
int pos = attribute.indexOf(':'); int pos = attribute.indexOf(':');
if (pos == -1) { if (pos == -1) {
...@@ -1868,9 +1872,14 @@ public final class Files { ...@@ -1868,9 +1872,14 @@ public final class Files {
* @param options * @param options
* options indicating how symbolic links are handled * options indicating how symbolic links are handled
* *
* @return a map of the attributes returned; may be empty. The map's keys * @return a map of the attributes returned; The map's keys are the
* are the attribute names, its values are the attribute values * 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 * @throws IOException
* if an I/O error occurs * if an I/O error occurs
* @throws SecurityException * @throws SecurityException
......
...@@ -228,6 +228,9 @@ public interface Path ...@@ -228,6 +228,9 @@ public interface Path
* not have a root component and the given path has a root component then * not have a root component and the given path has a root component then
* this path does not start with the given path. * this path does not start with the given path.
* *
* <p> If the given path is associated with a different {@code FileSystem}
* to this path then {@code false} is returned.
*
* @param other * @param other
* the given path * the given path
* *
...@@ -270,6 +273,9 @@ public interface Path ...@@ -270,6 +273,9 @@ public interface Path
* does not have a root component and the given path has a root component * does not have a root component and the given path has a root component
* then this path does not end with the given path. * then this path does not end with the given path.
* *
* <p> If the given path is associated with a different {@code FileSystem}
* to this path then {@code false} is returned.
*
* @param other * @param other
* the given path * the given path
* *
...@@ -283,7 +289,10 @@ public interface Path ...@@ -283,7 +289,10 @@ public interface Path
* the given path string, in exactly the manner specified by the {@link * the given path string, in exactly the manner specified by the {@link
* #endsWith(Path) endsWith(Path)} method. On UNIX for example, the path * #endsWith(Path) endsWith(Path)} method. On UNIX for example, the path
* "{@code foo/bar}" ends with "{@code foo/bar}" and "{@code bar}". It does * "{@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 * @param other
* the given path string * the given path string
...@@ -724,12 +733,18 @@ public interface Path ...@@ -724,12 +733,18 @@ public interface Path
* provider, platform specific. This method does not access the file system * provider, platform specific. This method does not access the file system
* and neither file is required to exist. * and neither file is required to exist.
* *
* <p> 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. * @param other the path compared to this path.
* *
* @return zero if the argument is {@link #equals equal} to this path, a * @return zero if the argument is {@link #equals equal} to this path, a
* value less than zero if this path is lexicographically less than * value less than zero if this path is lexicographically less than
* the argument, or a value greater than zero if this path is * the argument, or a value greater than zero if this path is
* lexicographically greater than the argument * lexicographically greater than the argument
*
* @throws ClassCastException
* if the paths are associated with different providers
*/ */
@Override @Override
int compareTo(Path other); int compareTo(Path other);
...@@ -738,7 +753,7 @@ public interface Path ...@@ -738,7 +753,7 @@ public interface Path
* Tests this path for equality with the given object. * Tests this path for equality with the given object.
* *
* <p> If the given object is not a Path, or is a Path associated with a * <p> 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}.
* *
* <p> Whether or not two path are equal depends on the file system * <p> Whether or not two path are equal depends on the file system
* implementation. In some cases the paths are compared without regard * implementation. In some cases the paths are compared without regard
......
...@@ -146,5 +146,5 @@ public interface WatchKey { ...@@ -146,5 +146,5 @@ public interface WatchKey {
* *
* @return the object for which this watch key was created * @return the object for which this watch key was created
*/ */
//T watchable(); Watchable watchable();
} }
...@@ -216,12 +216,14 @@ public final class FileTime ...@@ -216,12 +216,14 @@ public final class FileTime
* "2009-02-13T23:31:30Z"}, and {@code FileTime.fromMillis(1234567890123L).toString()} * "2009-02-13T23:31:30Z"}, and {@code FileTime.fromMillis(1234567890123L).toString()}
* yields {@code "2009-02-13T23:31:30.123Z"}. * yields {@code "2009-02-13T23:31:30.123Z"}.
* *
* <p> A {@code FileTime} is primarly intended to represent the value of a * <p> A {@code FileTime} is primarily intended to represent the value of a
* file's time stamp. Where used to represent <i>extreme values</i>, where * file's time stamp. Where used to represent <i>extreme values</i>, where
* the year is less than "{@code 0001}" or greater than "{@code 9999}" then * 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 * this method deviates from ISO 8601 in the same manner as the
* negative-signed. If more than four digits then leading zeros are not * <a href="http://www.w3.org/TR/xmlschema-2/#deviantformats">XML Schema
* present. The year before "{@code 0001}" is "{@code -0001}". * language</a>. 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 * @return the string representation of this file time
*/ */
......
...@@ -1037,6 +1037,11 @@ public abstract class FileSystemProvider { ...@@ -1037,6 +1037,11 @@ public abstract class FileSystemProvider {
* @return a map of the attributes returned; may be empty. The map's keys * @return a map of the attributes returned; may be empty. The map's keys
* are the attribute names, its values are the attribute values * 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 * @throws IOException
* If an I/O error occurs * If an I/O error occurs
* @throws SecurityException * @throws SecurityException
...@@ -1064,10 +1069,10 @@ public abstract class FileSystemProvider { ...@@ -1064,10 +1069,10 @@ public abstract class FileSystemProvider {
* options indicating how symbolic links are handled * options indicating how symbolic links are handled
* *
* @throws UnsupportedOperationException * @throws UnsupportedOperationException
* if the attribute view is not available or it does not support * if the attribute view is not available
* updating the attribute
* @throws IllegalArgumentException * @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 * inappropriate value
* @throws ClassCastException * @throws ClassCastException
* If the attribute value is not of the expected type or is a * If the attribute value is not of the expected type or is a
......
...@@ -57,8 +57,8 @@ abstract class AbstractAclFileAttributeView ...@@ -57,8 +57,8 @@ abstract class AbstractAclFileAttributeView
setAcl((List<AclEntry>)value); setAcl((List<AclEntry>)value);
return; return;
} }
throw new UnsupportedOperationException("'" + name() + ":" + throw new IllegalArgumentException("'" + name() + ":" +
attribute + "' not supported"); attribute + "' not recognized");
} }
@Override @Override
...@@ -81,6 +81,8 @@ abstract class AbstractAclFileAttributeView ...@@ -81,6 +81,8 @@ abstract class AbstractAclFileAttributeView
owner = true; owner = true;
continue; continue;
} }
throw new IllegalArgumentException("'" + name() + ":" +
attribute + "' not recognized");
} }
Map<String,Object> result = new HashMap<>(2); Map<String,Object> result = new HashMap<>(2);
if (acl) if (acl)
......
...@@ -46,6 +46,18 @@ abstract class AbstractBasicFileAttributeView ...@@ -46,6 +46,18 @@ abstract class AbstractBasicFileAttributeView
private static final String IS_SYMBOLIC_LINK_NAME = "isSymbolicLink"; private static final String IS_SYMBOLIC_LINK_NAME = "isSymbolicLink";
private static final String IS_OTHER_NAME = "isOther"; private static final String IS_OTHER_NAME = "isOther";
// the names of the basic attributes
static final Set<String> 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() { } protected AbstractBasicFileAttributeView() { }
@Override @Override
...@@ -69,24 +81,26 @@ abstract class AbstractBasicFileAttributeView ...@@ -69,24 +81,26 @@ abstract class AbstractBasicFileAttributeView
setTimes(null, null, (FileTime)value); setTimes(null, null, (FileTime)value);
return; return;
} }
throw new UnsupportedOperationException("'" + attribute + throw new IllegalArgumentException("'" + name() + ":" +
"' is unknown or read-only attribute"); attribute + "' not recognized");
} }
/** /**
* Used to build a map of attribute name/values. * Used to build a map of attribute name/values.
*/ */
static class AttributesBuilder { static class AttributesBuilder {
private Set<String> set = new HashSet<>(); private Set<String> names = new HashSet<>();
private Map<String,Object> map = new HashMap<>(); private Map<String,Object> map = new HashMap<>();
private boolean copyAll; private boolean copyAll;
private AttributesBuilder(String[] attributes) { private AttributesBuilder(Set<String> allowed, String[] requested) {
for (String attribute: attributes) { for (String name: requested) {
if (attribute.equals("*")) { if (name.equals("*")) {
copyAll = true; copyAll = true;
} else { } else {
set.add(attribute); if (!allowed.contains(name))
throw new IllegalArgumentException("'" + name + "' not recognized");
names.add(name);
} }
} }
} }
...@@ -94,21 +108,19 @@ abstract class AbstractBasicFileAttributeView ...@@ -94,21 +108,19 @@ abstract class AbstractBasicFileAttributeView
/** /**
* Creates builder to build up a map of the matching attributes * Creates builder to build up a map of the matching attributes
*/ */
static AttributesBuilder create(String[] attributes) { static AttributesBuilder create(Set<String> allowed, String[] requested) {
return new AttributesBuilder(attributes); return new AttributesBuilder(allowed, requested);
} }
/** /**
* Returns true if the attribute should be returned in the map * Returns true if the attribute should be returned in the map
*/ */
boolean match(String attribute) { boolean match(String name) {
if (copyAll) return copyAll || names.contains(name);
return true;
return set.contains(attribute);
} }
void add(String attribute, Object value) { void add(String name, Object value) {
map.put(attribute, value); map.put(name, value);
} }
/** /**
...@@ -124,7 +136,7 @@ abstract class AbstractBasicFileAttributeView ...@@ -124,7 +136,7 @@ abstract class AbstractBasicFileAttributeView
* Invoked by readAttributes or sub-classes to add all matching basic * Invoked by readAttributes or sub-classes to add all matching basic
* attributes to the builder * attributes to the builder
*/ */
final void addBasicAttributesToBuilder(BasicFileAttributes attrs, final void addRequestedBasicAttributes(BasicFileAttributes attrs,
AttributesBuilder builder) AttributesBuilder builder)
{ {
if (builder.match(SIZE_NAME)) if (builder.match(SIZE_NAME))
...@@ -148,9 +160,12 @@ abstract class AbstractBasicFileAttributeView ...@@ -148,9 +160,12 @@ abstract class AbstractBasicFileAttributeView
} }
@Override @Override
public Map<String,Object> readAttributes(String[] attributes) throws IOException { public Map<String,Object> readAttributes(String[] requested)
AttributesBuilder builder = AttributesBuilder.create(attributes); throws IOException
addBasicAttributesToBuilder(readAttributes(), builder); {
AttributesBuilder builder =
AttributesBuilder.create(basicAttributeNames, requested);
addRequestedBasicAttributes(readAttributes(), builder);
return builder.unmodifiableMap(); return builder.unmodifiableMap();
} }
} }
...@@ -29,7 +29,6 @@ import java.nio.file.*; ...@@ -29,7 +29,6 @@ import java.nio.file.*;
import java.nio.file.spi.FileSystemProvider; import java.nio.file.spi.FileSystemProvider;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.Collections;
/** /**
* Base implementation class of FileSystemProvider * Base implementation class of FileSystemProvider
...@@ -72,6 +71,8 @@ abstract class AbstractFileSystemProvider extends FileSystemProvider { ...@@ -72,6 +71,8 @@ abstract class AbstractFileSystemProvider extends FileSystemProvider {
throws IOException throws IOException
{ {
String[] s = split(attribute); String[] s = split(attribute);
if (s[0].length() == 0)
throw new IllegalArgumentException(attribute);
DynamicFileAttributeView view = getFileAttributeView(file, s[0], options); DynamicFileAttributeView view = getFileAttributeView(file, s[0], options);
if (view == null) if (view == null)
throw new UnsupportedOperationException("View '" + s[0] + "' not available"); throw new UnsupportedOperationException("View '" + s[0] + "' not available");
...@@ -83,9 +84,11 @@ abstract class AbstractFileSystemProvider extends FileSystemProvider { ...@@ -83,9 +84,11 @@ abstract class AbstractFileSystemProvider extends FileSystemProvider {
throws IOException throws IOException
{ {
String[] s = split(attributes); String[] s = split(attributes);
if (s[0].length() == 0)
throw new IllegalArgumentException(attributes);
DynamicFileAttributeView view = getFileAttributeView(file, s[0], options); DynamicFileAttributeView view = getFileAttributeView(file, s[0], options);
if (view == null) if (view == null)
return Collections.emptyMap(); throw new UnsupportedOperationException("View '" + s[0] + "' not available");
return view.readAttributes(s[1].split(",")); return view.readAttributes(s[1].split(","));
} }
......
...@@ -59,22 +59,6 @@ abstract class AbstractUserDefinedFileAttributeView ...@@ -59,22 +59,6 @@ abstract class AbstractUserDefinedFileAttributeView
return "user"; 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 @Override
public final void setAttribute(String attribute, Object value) public final void setAttribute(String attribute, Object value)
throws IOException throws IOException
...@@ -94,12 +78,13 @@ abstract class AbstractUserDefinedFileAttributeView ...@@ -94,12 +78,13 @@ abstract class AbstractUserDefinedFileAttributeView
{ {
// names of attributes to return // names of attributes to return
List<String> names = new ArrayList<>(); List<String> names = new ArrayList<>();
for (String name: attributes) { for (String name: attributes) {
if (name.equals("*")) { if (name.equals("*")) {
names = list(); names = list();
break; break;
} else { } else {
if (name.length() == 0)
throw new IllegalArgumentException();
names.add(name); names.add(name);
} }
} }
...@@ -107,11 +92,12 @@ abstract class AbstractUserDefinedFileAttributeView ...@@ -107,11 +92,12 @@ abstract class AbstractUserDefinedFileAttributeView
// read each value and return in map // read each value and return in map
Map<String,Object> result = new HashMap<>(); Map<String,Object> result = new HashMap<>();
for (String name: names) { for (String name: names) {
Object value = getAttribute(name); int size = size(name);
if (value != null) 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); result.put(name, value);
} }
return result; return result;
} }
} }
...@@ -81,7 +81,8 @@ abstract class AbstractWatchKey implements WatchKey { ...@@ -81,7 +81,8 @@ abstract class AbstractWatchKey implements WatchKey {
/** /**
* Return the original watchable (Path) * Return the original watchable (Path)
*/ */
Path watchable() { @Override
public Path watchable() {
return dir; return dir;
} }
......
...@@ -63,10 +63,10 @@ final class FileOwnerAttributeViewImpl ...@@ -63,10 +63,10 @@ final class FileOwnerAttributeViewImpl
{ {
if (attribute.equals(OWNER_NAME)) { if (attribute.equals(OWNER_NAME)) {
setOwner((UserPrincipal)value); setOwner((UserPrincipal)value);
return; } else {
throw new IllegalArgumentException("'" + name() + ":" +
attribute + "' not recognized");
} }
throw new UnsupportedOperationException("'" + name() + ":" +
attribute + "' not supported");
} }
@Override @Override
...@@ -75,6 +75,9 @@ final class FileOwnerAttributeViewImpl ...@@ -75,6 +75,9 @@ final class FileOwnerAttributeViewImpl
for (String attribute: attributes) { for (String attribute: attributes) {
if (attribute.equals("*") || attribute.equals(OWNER_NAME)) { if (attribute.equals("*") || attribute.equals(OWNER_NAME)) {
result.put(OWNER_NAME, getOwner()); result.put(OWNER_NAME, getOwner());
} else {
throw new IllegalArgumentException("'" + name() + ":" +
attribute + "' not recognized");
} }
} }
return result; return result;
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package sun.nio.fs; package sun.nio.fs;
import java.util.*;
/** /**
* Utility methods * Utility methods
*/ */
...@@ -54,6 +56,28 @@ class Util { ...@@ -54,6 +56,28 @@ class Util {
} }
result[n] = s.substring(last, s.length()); result[n] = s.substring(last, s.length());
return result; return result;
}
/**
* Returns a Set containing the given elements.
*/
static <E> Set<E> newSet(E... elements) {
HashSet<E> 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 <E> Set<E> newSet(Set<E> other, E... elements) {
HashSet<E> set = new HashSet<>(other);
for (E e: elements) {
set.add(e);
}
return set;
} }
} }
...@@ -33,8 +33,7 @@ import java.nio.file.*; ...@@ -33,8 +33,7 @@ import java.nio.file.*;
import static java.nio.file.StandardWatchEventKind.*; import static java.nio.file.StandardWatchEventKind.*;
import static java.nio.file.LinkOption.*; import static java.nio.file.LinkOption.*;
import java.nio.file.attribute.*; import java.nio.file.attribute.*;
import java.io.*; import java.io.IOException;
import java.util.*;
/** /**
* Example to watch a directory (or tree) for changes to files. * Example to watch a directory (or tree) for changes to files.
...@@ -43,9 +42,9 @@ import java.util.*; ...@@ -43,9 +42,9 @@ import java.util.*;
public class WatchDir { public class WatchDir {
private final WatchService watcher; private final WatchService watcher;
private final Map<WatchKey,Path> keys;
private final boolean recursive; private final boolean recursive;
private boolean trace = false; private boolean trace = false;
private int count;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static <T> WatchEvent<T> cast(WatchEvent<?> event) { static <T> WatchEvent<T> cast(WatchEvent<?> event) {
...@@ -57,17 +56,9 @@ public class WatchDir { ...@@ -57,17 +56,9 @@ public class WatchDir {
*/ */
private void register(Path dir) throws IOException { private void register(Path dir) throws IOException {
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
if (trace) { count++;
Path prev = keys.get(key); if (trace)
if (prev == null) {
System.out.format("register: %s\n", dir); 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);
} }
/** /**
...@@ -92,7 +83,6 @@ public class WatchDir { ...@@ -92,7 +83,6 @@ public class WatchDir {
*/ */
WatchDir(Path dir, boolean recursive) throws IOException { WatchDir(Path dir, boolean recursive) throws IOException {
this.watcher = FileSystems.getDefault().newWatchService(); this.watcher = FileSystems.getDefault().newWatchService();
this.keys = new HashMap<WatchKey,Path>();
this.recursive = recursive; this.recursive = recursive;
if (recursive) { if (recursive) {
...@@ -121,12 +111,6 @@ public class WatchDir { ...@@ -121,12 +111,6 @@ public class WatchDir {
return; return;
} }
Path dir = keys.get(key);
if (dir == null) {
System.err.println("WatchKey not recognized!!");
continue;
}
for (WatchEvent<?> event: key.pollEvents()) { for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind kind = event.kind(); WatchEvent.Kind kind = event.kind();
...@@ -138,7 +122,7 @@ public class WatchDir { ...@@ -138,7 +122,7 @@ public class WatchDir {
// Context for directory entry event is the file name of entry // Context for directory entry event is the file name of entry
WatchEvent<Path> ev = cast(event); WatchEvent<Path> ev = cast(event);
Path name = ev.context(); Path name = ev.context();
Path child = dir.resolve(name); Path child = ((Path)key.watchable()).resolve(name);
// print out event // print out event
System.out.format("%s: %s\n", event.kind().name(), child); System.out.format("%s: %s\n", event.kind().name(), child);
...@@ -156,18 +140,16 @@ public class WatchDir { ...@@ -156,18 +140,16 @@ public class WatchDir {
} }
} }
// reset key and remove from set if directory no longer accessible // reset key
boolean valid = key.reset(); boolean valid = key.reset();
if (!valid) { if (!valid) {
keys.remove(key); // directory no longer accessible
count--;
// all directories are inaccessible if (count == 0)
if (keys.isEmpty()) {
break; break;
} }
} }
} }
}
static void usage() { static void usage() {
System.err.println("usage: java WatchDir [-r] dir"); System.err.println("usage: java WatchDir [-r] dir");
......
...@@ -27,6 +27,7 @@ package sun.nio.fs; ...@@ -27,6 +27,7 @@ package sun.nio.fs;
import java.nio.file.attribute.*; import java.nio.file.attribute.*;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.io.IOException; import java.io.IOException;
import sun.misc.Unsafe; import sun.misc.Unsafe;
...@@ -57,6 +58,10 @@ class LinuxDosFileAttributeView ...@@ -57,6 +58,10 @@ class LinuxDosFileAttributeView
private static final int DOS_XATTR_SYSTEM = 0x04; private static final int DOS_XATTR_SYSTEM = 0x04;
private static final int DOS_XATTR_ARCHIVE = 0x20; private static final int DOS_XATTR_ARCHIVE = 0x20;
// the names of the DOS attributes (includes basic)
private static final Set<String> dosAttributeNames =
Util.newSet(basicAttributeNames, READONLY_NAME, ARCHIVE_NAME, SYSTEM_NAME, HIDDEN_NAME);
LinuxDosFileAttributeView(UnixPath file, boolean followLinks) { LinuxDosFileAttributeView(UnixPath file, boolean followLinks) {
super(file, followLinks); super(file, followLinks);
} }
...@@ -93,9 +98,10 @@ class LinuxDosFileAttributeView ...@@ -93,9 +98,10 @@ class LinuxDosFileAttributeView
public Map<String,Object> readAttributes(String[] attributes) public Map<String,Object> readAttributes(String[] attributes)
throws IOException throws IOException
{ {
AttributesBuilder builder = AttributesBuilder.create(attributes); AttributesBuilder builder =
AttributesBuilder.create(dosAttributeNames, attributes);
DosFileAttributes attrs = readAttributes(); DosFileAttributes attrs = readAttributes();
addBasicAttributesToBuilder(attrs, builder); addRequestedBasicAttributes(attrs, builder);
if (builder.match(READONLY_NAME)) if (builder.match(READONLY_NAME))
builder.add(READONLY_NAME, attrs.isReadOnly()); builder.add(READONLY_NAME, attrs.isReadOnly());
if (builder.match(ARCHIVE_NAME)) if (builder.match(ARCHIVE_NAME))
......
...@@ -123,6 +123,10 @@ class UnixFileAttributeViews { ...@@ -123,6 +123,10 @@ class UnixFileAttributeViews {
private static final String OWNER_NAME = "owner"; private static final String OWNER_NAME = "owner";
private static final String GROUP_NAME = "group"; private static final String GROUP_NAME = "group";
// the names of the posix attributes (incudes basic)
static final Set<String> posixAttributeNames =
Util.newSet(basicAttributeNames, PERMISSIONS_NAME, OWNER_NAME, GROUP_NAME);
Posix(UnixPath file, boolean followLinks) { Posix(UnixPath file, boolean followLinks) {
super(file, followLinks); super(file, followLinks);
} }
...@@ -172,9 +176,10 @@ class UnixFileAttributeViews { ...@@ -172,9 +176,10 @@ class UnixFileAttributeViews {
* Invoked by readAttributes or sub-classes to add all matching posix * Invoked by readAttributes or sub-classes to add all matching posix
* attributes to the builder * attributes to the builder
*/ */
final void addPosixAttributesToBuilder(PosixFileAttributes attrs, final void addRequestedPosixAttributes(PosixFileAttributes attrs,
AttributesBuilder builder) AttributesBuilder builder)
{ {
addRequestedBasicAttributes(attrs, builder);
if (builder.match(PERMISSIONS_NAME)) if (builder.match(PERMISSIONS_NAME))
builder.add(PERMISSIONS_NAME, attrs.permissions()); builder.add(PERMISSIONS_NAME, attrs.permissions());
if (builder.match(OWNER_NAME)) if (builder.match(OWNER_NAME))
...@@ -184,13 +189,13 @@ class UnixFileAttributeViews { ...@@ -184,13 +189,13 @@ class UnixFileAttributeViews {
} }
@Override @Override
public Map<String,Object> readAttributes(String[] attributes) public Map<String,Object> readAttributes(String[] requested)
throws IOException throws IOException
{ {
AttributesBuilder builder = AttributesBuilder.create(attributes); AttributesBuilder builder =
AttributesBuilder.create(posixAttributeNames, requested);
PosixFileAttributes attrs = readAttributes(); PosixFileAttributes attrs = readAttributes();
addBasicAttributesToBuilder(attrs, builder); addRequestedPosixAttributes(attrs, builder);
addPosixAttributesToBuilder(attrs, builder);
return builder.unmodifiableMap(); return builder.unmodifiableMap();
} }
...@@ -287,6 +292,12 @@ class UnixFileAttributeViews { ...@@ -287,6 +292,12 @@ class UnixFileAttributeViews {
private static final String GID_NAME = "gid"; private static final String GID_NAME = "gid";
private static final String CTIME_NAME = "ctime"; private static final String CTIME_NAME = "ctime";
// the names of the unix attributes (including posix)
static final Set<String> 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) { Unix(UnixPath file, boolean followLinks) {
super(file, followLinks); super(file, followLinks);
} }
...@@ -316,13 +327,13 @@ class UnixFileAttributeViews { ...@@ -316,13 +327,13 @@ class UnixFileAttributeViews {
} }
@Override @Override
public Map<String,Object> readAttributes(String[] attributes) public Map<String,Object> readAttributes(String[] requested)
throws IOException throws IOException
{ {
AttributesBuilder builder = AttributesBuilder.create(attributes); AttributesBuilder builder =
AttributesBuilder.create(unixAttributeNames, requested);
UnixFileAttributes attrs = readAttributes(); UnixFileAttributes attrs = readAttributes();
addBasicAttributesToBuilder(attrs, builder); addRequestedPosixAttributes(attrs, builder);
addPosixAttributesToBuilder(attrs, builder);
if (builder.match(MODE_NAME)) if (builder.match(MODE_NAME))
builder.add(MODE_NAME, attrs.mode()); builder.add(MODE_NAME, attrs.mode());
if (builder.match(INO_NAME)) if (builder.match(INO_NAME))
......
...@@ -606,7 +606,9 @@ class UnixPath ...@@ -606,7 +606,9 @@ class UnixPath
@Override @Override
public boolean startsWith(Path other) { 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 // other path is longer
if (that.path.length > path.length) if (that.path.length > path.length)
...@@ -655,7 +657,9 @@ class UnixPath ...@@ -655,7 +657,9 @@ class UnixPath
@Override @Override
public boolean endsWith(Path other) { 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 thisLen = path.length;
int thatLen = that.path.length; int thatLen = that.path.length;
......
...@@ -157,6 +157,11 @@ class WindowsFileAttributeViews { ...@@ -157,6 +157,11 @@ class WindowsFileAttributeViews {
private static final String HIDDEN_NAME = "hidden"; private static final String HIDDEN_NAME = "hidden";
private static final String ATTRIBUTES_NAME = "attributes"; private static final String ATTRIBUTES_NAME = "attributes";
// the names of the DOS attribtues (includes basic)
static final Set<String> dosAttributeNames =
Util.newSet(basicAttributeNames,
READONLY_NAME, ARCHIVE_NAME, SYSTEM_NAME, HIDDEN_NAME, ATTRIBUTES_NAME);
Dos(WindowsPath file, boolean followLinks) { Dos(WindowsPath file, boolean followLinks) {
super(file, followLinks); super(file, followLinks);
} }
...@@ -193,9 +198,10 @@ class WindowsFileAttributeViews { ...@@ -193,9 +198,10 @@ class WindowsFileAttributeViews {
public Map<String,Object> readAttributes(String[] attributes) public Map<String,Object> readAttributes(String[] attributes)
throws IOException throws IOException
{ {
AttributesBuilder builder = AttributesBuilder.create(attributes); AttributesBuilder builder =
AttributesBuilder.create(dosAttributeNames, attributes);
WindowsFileAttributes attrs = readAttributes(); WindowsFileAttributes attrs = readAttributes();
addBasicAttributesToBuilder(attrs, builder); addRequestedBasicAttributes(attrs, builder);
if (builder.match(READONLY_NAME)) if (builder.match(READONLY_NAME))
builder.add(READONLY_NAME, attrs.isReadOnly()); builder.add(READONLY_NAME, attrs.isReadOnly());
if (builder.match(ARCHIVE_NAME)) if (builder.match(ARCHIVE_NAME))
......
...@@ -646,7 +646,9 @@ class WindowsPath extends AbstractPath { ...@@ -646,7 +646,9 @@ class WindowsPath extends AbstractPath {
@Override @Override
public boolean startsWith(Path obj) { 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 path has a root component the given path's root must match
if (!this.root.equalsIgnoreCase(other.root)) { if (!this.root.equalsIgnoreCase(other.root)) {
...@@ -675,7 +677,9 @@ class WindowsPath extends AbstractPath { ...@@ -675,7 +677,9 @@ class WindowsPath extends AbstractPath {
@Override @Override
public boolean endsWith(Path obj) { 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 // other path is longer
if (other.path.length() > this.path.length()) { if (other.path.length() > this.path.length()) {
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
*/ */
/* @test /* @test
* @bug 4313887 6838333 * @bug 4313887 6838333 7017446
* @summary Unit test for java.nio.file.Files * @summary Unit test for java.nio.file.Files
* @library .. * @library ..
*/ */
...@@ -94,12 +94,6 @@ public class FileAttributes { ...@@ -94,12 +94,6 @@ public class FileAttributes {
assertTrue(map.size() == 2); assertTrue(map.size() == 2);
checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.size(), map.get("size"));
checkEqual(attrs.lastModifiedTime(), map.get("lastModifiedTime")); 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 // Exercise getAttribute/setAttribute/readAttributes on posix attributes
...@@ -132,7 +126,7 @@ public class FileAttributes { ...@@ -132,7 +126,7 @@ public class FileAttributes {
assertTrue(map.size() >= 12); assertTrue(map.size() >= 12);
checkEqual(attrs.permissions(), map.get("permissions")); // check one 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); assertTrue(map.size() == 2);
checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.size(), map.get("size"));
checkEqual(attrs.owner(), map.get("owner")); checkEqual(attrs.owner(), map.get("owner"));
...@@ -155,7 +149,7 @@ public class FileAttributes { ...@@ -155,7 +149,7 @@ public class FileAttributes {
map = Files.readAttributes(file, "unix:*"); map = Files.readAttributes(file, "unix:*");
assertTrue(map.size() >= 20); 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); assertTrue(map.size() == 3);
checkEqual(map.get("size"), checkEqual(map.get("size"),
Files.readAttributes(file, BasicFileAttributes.class).size()); Files.readAttributes(file, BasicFileAttributes.class).size());
...@@ -206,14 +200,65 @@ public class FileAttributes { ...@@ -206,14 +200,65 @@ public class FileAttributes {
assertTrue(map.size() >= 13); assertTrue(map.size() >= 13);
checkEqual(attrs.isReadOnly(), map.get("readonly")); // check one 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); assertTrue(map.size() == 2);
checkEqual(attrs.size(), map.get("size")); checkEqual(attrs.size(), map.get("size"));
checkEqual(attrs.isHidden(), map.get("hidden")); 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 { 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 { try {
Files.getAttribute(file, null); Files.getAttribute(file, null);
throw new RuntimeException("NullPointerException expected"); throw new RuntimeException("NullPointerException expected");
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
*/ */
/* @test /* @test
* @bug 4313887 6838333 * @bug 4313887 6838333 7017446
* @summary Unit test for java.nio.file.WatchService * @summary Unit test for java.nio.file.WatchService
* @library .. * @library ..
* @run main/timeout=120 Basic * @run main/timeout=120 Basic
...@@ -44,6 +44,8 @@ public class Basic { ...@@ -44,6 +44,8 @@ public class Basic {
static void checkKey(WatchKey key, Path dir) { static void checkKey(WatchKey key, Path dir) {
if (!key.isValid()) if (!key.isValid())
throw new RuntimeException("Key is not valid"); throw new RuntimeException("Key is not valid");
if (key.watchable() != dir)
throw new RuntimeException("Unexpected watchable");
} }
static void takeExpectedKey(WatchService watcher, WatchKey expected) { static void takeExpectedKey(WatchService watcher, WatchKey expected) {
......
...@@ -141,9 +141,6 @@ public class Basic { ...@@ -141,9 +141,6 @@ public class Basic {
map = Files.readAttributes(file, "user:*"); map = Files.readAttributes(file, "user:*");
if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME))) if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME)))
throw new RuntimeException("Unexpected attribute value"); 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 { static void miscTests(final Path file) throws IOException {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册