8030090: (fs) Add default methods to Path for derived methods
authorbpb
Tue, 23 Dec 2014 10:09:52 -0800
changeset 28244 1b52033818b1
parent 28243 47080f9ae750
child 28251 957277476d2e
8030090: (fs) Add default methods to Path for derived methods Summary: Use method bodies from sun.nio.fs.AbstractPath as default method implementations in Path. Reviewed-by: alanb
jdk/src/java.base/share/classes/java/nio/file/Path.java
jdk/src/java.base/share/classes/sun/nio/fs/AbstractPath.java
jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java
jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java
--- a/jdk/src/java.base/share/classes/java/nio/file/Path.java	Tue Dec 23 16:30:57 2014 +0000
+++ b/jdk/src/java.base/share/classes/java/nio/file/Path.java	Tue Dec 23 10:09:52 2014 -0800
@@ -29,6 +29,7 @@
 import java.io.IOException;
 import java.net.URI;
 import java.util.Iterator;
+import java.util.NoSuchElementException;
 
 /**
  * An object that may be used to locate a file in a file system. It will
@@ -246,6 +247,12 @@
      * "{@code foo/bar}" starts with "{@code foo}" and "{@code foo/bar}". It
      * does not start with "{@code f}" or "{@code fo}".
      *
+     * @implSpec
+     * The default implementation is equivalent for this path to:
+     * <pre>{@code
+     *     startsWith(getFileSystem().getPath(other));
+     * }</pre>
+     *
      * @param   other
      *          the given path string
      *
@@ -255,7 +262,9 @@
      * @throws  InvalidPathException
      *          If the path string cannot be converted to a Path.
      */
-    boolean startsWith(String other);
+    default boolean startsWith(String other) {
+        return startsWith(getFileSystem().getPath(other));
+    }
 
     /**
      * Tests if this path ends with the given path.
@@ -294,6 +303,12 @@
      * Path}"{@code foo/bar}" with the {@code String} "{@code bar/}" returns
      * {@code true}.
      *
+     * @implSpec
+     * The default implementation is equivalent for this path to:
+     * <pre>{@code
+     *     endsWith(getFileSystem().getPath(other));
+     * }</pre>
+     *
      * @param   other
      *          the given path string
      *
@@ -303,7 +318,9 @@
      * @throws  InvalidPathException
      *          If the path string cannot be converted to a Path.
      */
-    boolean endsWith(String other);
+    default boolean endsWith(String other) {
+        return endsWith(getFileSystem().getPath(other));
+    }
 
     /**
      * Returns a path that is this path with redundant name elements eliminated.
@@ -365,6 +382,12 @@
      * invoking this method with the path string "{@code gus}" will result in
      * the {@code Path} "{@code foo/bar/gus}".
      *
+     * @implSpec
+     * The default implementation is equivalent for this path to:
+     * <pre>{@code
+     *     resolve(getFileSystem().getPath(other));
+     * }</pre>
+     *
      * @param   other
      *          the path string to resolve against this path
      *
@@ -375,7 +398,9 @@
      *
      * @see FileSystem#getPath
      */
-    Path resolve(String other);
+    default Path resolve(String other) {
+        return resolve(getFileSystem().getPath(other));
+    }
 
     /**
      * Resolves the given path against this path's {@link #getParent parent}
@@ -389,6 +414,14 @@
      * returns this path's parent, or where this path doesn't have a parent, the
      * empty path.
      *
+     * @implSpec
+     * The default implementation is equivalent for this path to:
+     * <pre>{@code
+     *     (getParent() == null) ? other : getParent().resolve(other);
+     * }</pre>
+     * unless {@code other == null}, in which case a
+     * {@code NullPointerException} is thrown.
+     *
      * @param   other
      *          the path to resolve against this path's parent
      *
@@ -396,13 +429,24 @@
      *
      * @see #resolve(Path)
      */
-    Path resolveSibling(Path other);
+    default Path resolveSibling(Path other) {
+        if (other == null)
+            throw new NullPointerException();
+        Path parent = getParent();
+        return (parent == null) ? other : parent.resolve(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.
      *
+     * @implSpec
+     * The default implementation is equivalent for this path to:
+     * <pre>{@code
+     *     resolveSibling(getFileSystem().getPath(other));
+     * }</pre>
+     *
      * @param   other
      *          the path string to resolve against this path's parent
      *
@@ -413,7 +457,9 @@
      *
      * @see FileSystem#getPath
      */
-    Path resolveSibling(String other);
+    default Path resolveSibling(String other) {
+        return resolveSibling(getFileSystem().getPath(other));
+    }
 
     /**
      * Constructs a relative path between this path and a given path.
@@ -590,12 +636,28 @@
      * File} object returned by this method is {@link #equals equal} to the
      * original {@code File}.
      *
+     * @implSpec
+     * The default implementation is equivalent for this path to:
+     * <pre>{@code
+     *     new File(toString());
+     * }</pre>
+     * if the {@code FileSystem} which created this {@code Path} is the default
+     * file system; otherwise an {@code UnsupportedOperationException} is
+     * thrown.
+     *
      * @return  a {@code File} object representing this path
      *
      * @throws  UnsupportedOperationException
      *          if this {@code Path} is not associated with the default provider
      */
-    File toFile();
+    default File toFile() {
+        if (getFileSystem() == FileSystems.getDefault()) {
+            return new File(toString());
+        } else {
+            throw new UnsupportedOperationException("Path not associated with "
+                    + "default file system.");
+        }
+    }
 
     // -- watchable --
 
@@ -681,6 +743,13 @@
      *
      *     WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
      * </pre>
+     *
+     * @implSpec
+     * The default implementation is equivalent for this path to:
+     * <pre>{@code
+     *     register(watcher, events, new WatchEvent.Modifier[0]);
+     * }</pre>
+     *
      * @param   watcher
      *          The watch service to which this object is to be registered
      * @param   events
@@ -706,9 +775,10 @@
      *          method is invoked to check read access to the file.
      */
     @Override
-    WatchKey register(WatchService watcher,
-                      WatchEvent.Kind<?>... events)
-        throws IOException;
+    default WatchKey register(WatchService watcher,
+                      WatchEvent.Kind<?>... events) throws IOException {
+        return register(watcher, events, new WatchEvent.Modifier[0]);
+    }
 
     // -- Iterable --
 
@@ -721,10 +791,36 @@
      * is the name of the file or directory denoted by this path. The {@link
      * #getRoot root} component, if present, is not returned by the iterator.
      *
+     * @implSpec
+     * The default implementation returns an {@code Iterator<Path>} which, for
+     * this path, traverses the {@code Path}s returned by
+     * {@code getName(index)}, where {@code index} ranges from zero to
+     * {@code getNameCount() - 1}, inclusive.
+     *
      * @return  an iterator over the name elements of this path.
      */
     @Override
-    Iterator<Path> iterator();
+    default Iterator<Path> iterator() {
+        return new Iterator<Path>() {
+            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();
+                }
+            }
+        };
+    }
 
     // -- compareTo/equals/hashCode --
 
--- a/jdk/src/java.base/share/classes/sun/nio/fs/AbstractPath.java	Tue Dec 23 16:30:57 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2007, 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.io.File;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * Base implementation class of {@code Path}.
- */
-
-abstract class AbstractPath implements Path {
-    protected AbstractPath() { }
-
-    @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
-    public final Path resolve(String other) {
-        return resolve(getFileSystem().getPath(other));
-    }
-
-    @Override
-    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 Path resolveSibling(String other) {
-        return resolveSibling(getFileSystem().getPath(other));
-    }
-
-    @Override
-    public final Iterator<Path> iterator() {
-        return new Iterator<Path>() {
-            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();
-            }
-        };
-    }
-
-    @Override
-    public final File toFile() {
-        return new File(toString());
-    }
-
-    @Override
-    public final WatchKey register(WatchService watcher,
-                                   WatchEvent.Kind<?>... events)
-        throws IOException
-    {
-        return register(watcher, events, new WatchEvent.Modifier[0]);
-    }
-}
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java	Tue Dec 23 16:30:57 2014 +0000
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixPath.java	Tue Dec 23 10:09:52 2014 -0800
@@ -40,9 +40,7 @@
  * Solaris/Linux implementation of java.nio.file.Path
  */
 
-class UnixPath
-    extends AbstractPath
-{
+class UnixPath implements Path {
     private static ThreadLocal<SoftReference<CharsetEncoder>> encoder =
         new ThreadLocal<SoftReference<CharsetEncoder>>();
 
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java	Tue Dec 23 16:30:57 2014 +0000
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java	Tue Dec 23 10:09:52 2014 -0800
@@ -41,7 +41,7 @@
  * Windows implementation of Path
  */
 
-class WindowsPath extends AbstractPath {
+class WindowsPath implements Path {
 
     // 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