# HG changeset patch # User jjg # Date 1420584670 28800 # Node ID cd3ea1087d2bdf9e60747356027b924460165041 # Parent 43ed6b2e0e3bd219709276fce66c68e9dfa716ec 8059977: StandardJavaFileManager should support java.nio.file.Path Reviewed-by: jlahoda diff -r 43ed6b2e0e3b -r cd3ea1087d2b langtools/src/java.compiler/share/classes/javax/tools/FileManagerUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/java.compiler/share/classes/javax/tools/FileManagerUtils.java Tue Jan 06 14:51:10 2015 -0800 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, 2015, 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 javax.tools; + +import java.io.File; +import java.nio.file.Path; +import java.util.Iterator; + +/** + * Package-private utility methods to convert between files and paths. + * + * @since 1.9 + */ +class FileManagerUtils { + private FileManagerUtils() { } + + static Iterable asPaths(final Iterable files) { + return () -> new Iterator() { + Iterator iter = files.iterator(); + + @Override + public boolean hasNext() { + return iter.hasNext(); + } + + @Override + public Path next() { + return iter.next().toPath(); + } + }; + } + + static Iterable asFiles(final Iterable paths) { + return () -> new Iterator() { + Iterator iter = paths.iterator(); + + @Override + public boolean hasNext() { + return iter.hasNext(); + } + + @Override + public File next() { + Path p = iter.next(); + try { + return p.toFile(); + } catch (UnsupportedOperationException e) { + throw new IllegalArgumentException(p.toString(), e); + } + } + }; + } +} diff -r 43ed6b2e0e3b -r cd3ea1087d2b langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java --- a/langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java Tue Jan 06 15:46:41 2015 +0000 +++ b/langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java Tue Jan 06 14:51:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015, 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 @@ -27,13 +27,16 @@ import java.io.File; import java.io.IOException; -import java.util.*; +import java.nio.file.Path; +import java.util.Arrays; + +import static javax.tools.FileManagerUtils.*; /** - * File manager based on {@linkplain File java.io.File}. A common way - * to obtain an instance of this class is using {@linkplain - * JavaCompiler#getStandardFileManager - * getStandardFileManager}, for example: + * File manager based on {@linkplain File java.io.File} and {@linkplain Path java.nio.file.Path}. + * + * A common way to obtain an instance of this class is using + * {@linkplain JavaCompiler#getStandardFileManager getStandardFileManager}, for example: * *
  *   JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
@@ -110,7 +113,7 @@
  *     file:///C:/Documents%20and%20Settings/UncleBob/BobsApp/Test.java
  *   
  *   
  • - * jar:///C:/Documents%20and%20Settings/UncleBob/lib/vendorA.jar!com/vendora/LibraryClass.class + * jar:///C:/Documents%20and%20Settings/UncleBob/lib/vendorA.jar!/com/vendora/LibraryClass.class *
  • * * Whereas these are not (reason in parentheses): @@ -120,7 +123,7 @@ * and depend on the current directory) * *
  • - * jar:lib/vendorA.jar!com/vendora/LibraryClass.class + * jar:lib/vendorA.jar!/com/vendora/LibraryClass.class * (the first half of the path depends on the current directory, * whereas the component after ! is legal) *
  • @@ -134,6 +137,10 @@ * * * + *

    All implementations of this interface must support Path objects representing + * files in the {@linkplain java.nio.file.FileSystems#getDefault() default file system.} + * It is recommended that implementations should support Path objects from any filesystem.

    + * * @author Peter von der Ahé * @since 1.6 */ @@ -147,11 +154,12 @@ * @param a a file object * @param b a file object * @return true if the given file objects represent the same - * canonical file or zip file entry; false otherwise + * canonical file, zip file entry or path; false otherwise * * @throws IllegalArgumentException if either of the arguments * were created with another file manager implementation */ + @Override boolean isSameFile(FileObject a, FileObject b); /** @@ -166,6 +174,27 @@ Iterable files); /** + * Returns file objects representing the given paths. + * + *

    The default implementation converts each path to a file and calls + * {@link #getJavaFileObjectsFromFiles getJavaObjectsFromFiles}. + * IllegalArgumentException will be thrown if any of the paths + * cannot be converted to a file. + * + * @param paths a list of paths + * @return a list of file objects + * @throws IllegalArgumentException if the list of paths includes + * a directory or if this file manager does not support any of the + * given paths. + * + * @since 1.9 + */ + default Iterable getJavaFileObjectsFromPaths( + Iterable paths) { + return getJavaFileObjectsFromFiles(asFiles(paths)); + } + + /** * Returns file objects representing the given files. * Convenience method equivalent to: * @@ -183,6 +212,27 @@ Iterable getJavaFileObjects(File... files); /** + * Returns file objects representing the given paths. + * Convenience method equivalent to: + * + *

    +     *     getJavaFileObjectsFromPaths({@linkplain java.util.Arrays#asList Arrays.asList}(paths))
    +     * 
    + * + * @param paths an array of paths + * @return a list of file objects + * @throws IllegalArgumentException if the array of files includes + * a directory + * @throws NullPointerException if the given array contains null + * elements + * + * @since 1.9 + */ + default Iterable getJavaFileObjects(Path... paths) { + return getJavaFileObjectsFromPaths(Arrays.asList(paths)); + } + + /** * Returns file objects representing the given file names. * * @param names a list of file names @@ -211,29 +261,94 @@ Iterable getJavaFileObjects(String... names); /** - * Associates the given path with the given location. Any + * Associates the given search path with the given location. Any * previous value will be discarded. * * @param location a location - * @param path a list of files, if {@code null} use the default - * path for this location + * @param files a list of files, if {@code null} use the default + * search path for this location * @see #getLocation - * @throws IllegalArgumentException if location is an output - * location and path does not contain exactly one element - * @throws IOException if location is an output location and path + * @throws IllegalArgumentException if {@code location} is an output + * location and {@code files} does not contain exactly one element + * @throws IOException if {@code location} is an output location and * does not represent an existing directory */ - void setLocation(Location location, Iterable path) + void setLocation(Location location, Iterable files) throws IOException; /** - * Returns the path associated with the given location. + * Associates the given search path with the given location. Any + * previous value will be discarded. + * + *

    The default implementation converts each path to a file and calls + * {@link #getJavaFileObjectsFromFiles getJavaObjectsFromFiles}. + * IllegalArgumentException will be thrown if any of the paths + * cannot be converted to a file.

    + * + * @param location a location + * @param paths a list of paths, if {@code null} use the default + * search path for this location + * @see #getLocation + * @throws IllegalArgumentException if {@code location} is an output + * location and {@code paths} does not contain exactly one element + * or if this file manager does not support any of the given paths + * @throws IOException if {@code location} is an output location and + * {@code paths} does not represent an existing directory + * + * @since 1.9 + */ + default void setLocationFromPaths(Location location, Iterable paths) + throws IOException { + setLocation(location, asFiles(paths)); + } + + /** + * Returns the search path associated with the given location. * * @param location a location * @return a list of files or {@code null} if this location has no - * associated path + * associated search path + * @throws IllegalStateException if any element of the search path + * cannot be converted to a {@linkplain File}. + * * @see #setLocation + * @see Path#toFile */ Iterable getLocation(Location location); + /** + * Returns the search path associated with the given location. + * + * @param location a location + * @return a list of paths or {@code null} if this location has no + * associated search path + * + * @see #setLocationFromPaths + * @since 1.9 + */ + default Iterable getLocationAsPaths(Location location) { + return asPaths(getLocation(location)); + } + + /** + * Returns the path, if any, underlying this file object (optional operation). + * File objects derived from a {@link java.nio.file.FileSystem FileSystem}, + * including the default file system, typically have a corresponding underlying + * {@link java.nio.file.Path Path} object. In such cases, this method may be + * used to access that object. + * + *

    The default implementation throws {@link UnsupportedOperationException} + * for all files.

    + * + * @param file a file object + * @return a path representing the same underlying file system artifact + * @throws IllegalArgumentException if the file object does not have an underlying path + * @throws UnsupportedOperationException if the operation is not supported by this file manager + * + * @since 1.9 + */ + default Path asPath(FileObject file) { + throw new UnsupportedOperationException(); + } + } diff -r 43ed6b2e0e3b -r cd3ea1087d2b langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java --- a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java Tue Jan 06 15:46:41 2015 +0000 +++ b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java Tue Jan 06 14:51:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, 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 @@ -92,6 +92,10 @@ /** * Returns the Java™ programming language compiler provided * with this platform. + *

    The file manager returned by calling + * {@link JavaCompiler#getStandardFileManager getStandardFileManager} + * on this compiler supports paths provided by any + * {@linkplain java.nio.file.FileSystem filesystem}.

    * @return the compiler provided with this platform or * {@code null} if no compiler is provided */ @@ -105,6 +109,10 @@ /** * Returns the Java™ programming language documentation tool provided * with this platform. + *

    The file manager returned by calling + * {@link DocumentationTool#getStandardFileManager getStandardFileManager} + * on this tool supports paths provided by any + * {@linkplain java.nio.file.FileSystem filesystem}.

    * @return the documentation tool provided with this platform or * {@code null} if no documentation tool is provided */ diff -r 43ed6b2e0e3b -r cd3ea1087d2b langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Tue Jan 06 15:46:41 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Tue Jan 06 14:51:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, 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 @@ -101,7 +101,6 @@ private final Set sourceOrClass = EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS); - protected boolean mmappedIO; protected boolean symbolFileEnabled; protected enum SortFiles implements Comparator { @@ -157,7 +156,6 @@ if (contextUseOptimizedZip) zipFileIndexCache = ZipFileIndexCache.getSharedInstance(); - mmappedIO = options.isSet("mmappedIO"); symbolFileEnabled = !options.isSet("ignore.symbol.file"); String sf = options.get("sortFiles"); @@ -177,10 +175,12 @@ return symbolFileEnabled; } + // used by tests public JavaFileObject getFileForInput(String name) { return getRegularFile(Paths.get(name)); } + // used by tests public JavaFileObject getRegularFile(Path file) { return new RegularFileObject(this, file); } @@ -195,10 +195,10 @@ @Override @DefinedBy(Api.COMPILER) public Iterable getJavaFileObjectsFromStrings(Iterable names) { - ListBuffer files = new ListBuffer<>(); + ListBuffer paths = new ListBuffer<>(); for (String name : names) - files.append(new File(nullCheck(name))); - return getJavaFileObjectsFromFiles(files.toList()); + paths.append(Paths.get(nullCheck(name))); + return getJavaFileObjectsFromPaths(paths.toList()); } @Override @DefinedBy(Api.COMPILER) @@ -873,11 +873,30 @@ } @Override @DefinedBy(Api.COMPILER) + public Iterable getJavaFileObjectsFromPaths( + Iterable paths) + { + ArrayList result; + if (paths instanceof Collection) + result = new ArrayList<>(((Collection)paths).size()); + else + result = new ArrayList<>(); + for (Path p: paths) + result.add(new RegularFileObject(this, nullCheck(p))); + return result; + } + + @Override @DefinedBy(Api.COMPILER) public Iterable getJavaFileObjects(File... files) { return getJavaFileObjectsFromFiles(Arrays.asList(nullCheck(files))); } @Override @DefinedBy(Api.COMPILER) + public Iterable getJavaFileObjects(Path... paths) { + return getJavaFileObjectsFromPaths(Arrays.asList(nullCheck(paths))); + } + + @Override @DefinedBy(Api.COMPILER) public void setLocation(Location location, Iterable searchpath) throws IOException @@ -887,12 +906,22 @@ } @Override @DefinedBy(Api.COMPILER) + public void setLocationFromPaths(Location location, + Iterable searchpath) + throws IOException + { + nullCheck(location); + locations.setLocation(location, nullCheck(searchpath)); + } + + @Override @DefinedBy(Api.COMPILER) public Iterable getLocation(Location location) { nullCheck(location); return asFiles(locations.getLocation(location)); } - private Iterable getLocationAsPaths(Location location) { + @Override @DefinedBy(Api.COMPILER) + public Iterable getLocationAsPaths(Location location) { nullCheck(location); return locations.getLocation(location); } @@ -905,6 +934,14 @@ return locations.getOutputLocation(SOURCE_OUTPUT); } + @Override @DefinedBy(Api.COMPILER) + public Path asPath(FileObject file) { + if (file instanceof RegularFileObject) { + return ((RegularFileObject) file).file; + } else + throw new IllegalArgumentException(file.getName()); + } + /** * Enforces the specification of a "relative" name as used in * {@linkplain #getFileForInput(Location,String,String) @@ -1010,12 +1047,12 @@ @Override public File next() { - return iter.next().toFile(); + try { + return iter.next().toFile(); + } catch (UnsupportedOperationException e) { + throw new IllegalStateException(e); + } } }; } - - private static File asFile(Path path) { - return path == null ? null : path.toFile(); - } } diff -r 43ed6b2e0e3b -r cd3ea1087d2b langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Tue Jan 06 15:46:41 2015 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Tue Jan 06 14:51:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -428,7 +428,7 @@ /** * General purpose implementation for search path locations, such as -sourcepath/SOURCE_PATH and - * -processorPath/ANNOTATION_PROCESS_PATH. All options are treated as equivalent (i.e. aliases.) + * -processorPath/ANNOTATION_PROCESSOR_PATH. All options are treated as equivalent (i.e. aliases.) * The value is an ordered set of files and/or directories. */ private class SimpleLocationHandler extends LocationHandler { diff -r 43ed6b2e0e3b -r cd3ea1087d2b langtools/test/tools/javac/api/file/MyStandardJavaFileManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/api/file/MyStandardJavaFileManager.java Tue Jan 06 14:51:10 2015 -0800 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, 2015, 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. + */ + +import java.io.File; +import java.io.IOException; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + + +class MyStandardJavaFileManager + extends ForwardingJavaFileManager + implements StandardJavaFileManager { + MyStandardJavaFileManager(StandardJavaFileManager delegate) { + super(delegate); + } + + @Override + public Iterable getJavaFileObjectsFromFiles(Iterable files) { + return fileManager.getJavaFileObjectsFromFiles(files); + } + + @Override + public Iterable getJavaFileObjects(File... files) { + return fileManager.getJavaFileObjects(files); + } + + @Override + public Iterable getJavaFileObjectsFromStrings(Iterable names) { + return fileManager.getJavaFileObjectsFromStrings(names); + } + + @Override + public Iterable getJavaFileObjects(String... names) { + return fileManager.getJavaFileObjects(names); + } + + @Override + public void setLocation(JavaFileManager.Location location, Iterable files) throws IOException { + fileManager.setLocation(location, files); + } + + @Override + public Iterable getLocation(JavaFileManager.Location location) { + return fileManager.getLocation(location); + } +} diff -r 43ed6b2e0e3b -r cd3ea1087d2b langtools/test/tools/javac/api/file/SJFM_AsPath.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/api/file/SJFM_AsPath.java Tue Jan 06 14:51:10 2015 -0800 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014, 2015, 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 8059977 + * @summary StandardJavaFileManager should support java.nio.file.Path. + * Test asPath method. + * @build SJFM_TestBase + * @run main SJFM_AsPath + */ + +import java.io.IOException; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +/** + * For those paths which are supported by a file manager, such that + * a file object can encapsulate the path, verify that the underlying + * path can be recovered from the file object. + */ +public class SJFM_AsPath extends SJFM_TestBase { + public static void main(String... args) throws Exception { + new SJFM_AsPath().run(); + } + + @Test + void test_asPath(StandardJavaFileManager fm) throws IOException { + test_asPath(fm, getTestFilePaths()); + test_asPath(fm, getTestZipPaths()); + } + + /** + * Tests the asPath method for a specific file manager and a series + * of paths. + * + * Note: instances of MyStandardJavaFileManager only support + * encapsulating paths for files in the default file system, + * and throw UnsupportedOperationException for asPath. + * + * @param fm the file manager to be tested + * @param paths the paths to be tested + * @throws IOException + */ + void test_asPath(StandardJavaFileManager fm, List paths) throws IOException { + if (!isGetFileObjectsSupported(fm, paths)) + return; + boolean expectException = (fm instanceof MyStandardJavaFileManager); + + Set ref = new HashSet<>(paths); + for (JavaFileObject fo : fm.getJavaFileObjectsFromPaths(paths)) { + try { + Path path = fm.asPath(fo); + if (expectException) + error("expected exception not thrown: " + UnsupportedOperationException.class.getName()); + boolean found = ref.remove(path); + if (!found) { + error("Unexpected path found: " + path + "; expected one of " + ref); + } + } catch (Exception e) { + if (expectException && e instanceof UnsupportedOperationException) + continue; + error("unexpected exception thrown: " + e); + } + } + } +} diff -r 43ed6b2e0e3b -r cd3ea1087d2b langtools/test/tools/javac/api/file/SJFM_GetFileObjects.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/api/file/SJFM_GetFileObjects.java Tue Jan 06 14:51:10 2015 -0800 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2014, 2015, 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 8059977 + * @summary StandardJavaFileManager should support java.nio.file.Path. + * Test getFileObject methods. + * @build SJFM_TestBase + * @run main SJFM_GetFileObjects + */ + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; + +/** + * For those paths supported by a file manager, verify that the paths + * can be encapsulated by file objects, such that the file objects can + * be used by a tool such as javac. + */ +public class SJFM_GetFileObjects extends SJFM_TestBase { + public static void main(String... args) throws Exception { + new SJFM_GetFileObjects().run(); + } + + @Test + void test_getJavaFileObjects(StandardJavaFileManager fm) throws IOException { + test_getJavaFileObjects(fm, getTestFilePaths()); + test_getJavaFileObjects(fm, getTestZipPaths()); + } + + /** + * Tests the getJavaFileObjects method for a specific file manager + * and a series of paths. + * + * Note: instances of MyStandardJavaFileManager only support + * encapsulating paths for files in the default file system. + * + * @param fm the file manager to be tested + * @param paths the paths to be tested + * @throws IOException + */ + void test_getJavaFileObjects(StandardJavaFileManager fm, List paths) throws IOException { + boolean expectException = !isGetFileObjectsSupported(fm, paths); + try { + compile(fm.getJavaFileObjects(paths.toArray(new Path[paths.size()]))); + if (expectException) + error("expected exception not thrown"); + } catch (RuntimeException e) { + if (expectException && e instanceof IllegalArgumentException) + return; + error("unexpected exception thrown: " + e); + } + } + + //---------------------------------------------------------------------------------------------- + + @Test + void test_getJavaFileObjectsFromPaths(StandardJavaFileManager fm) throws IOException { + test_getJavaFileObjectsFromPaths(fm, getTestFilePaths()); + test_getJavaFileObjectsFromPaths(fm, getTestZipPaths()); + } + + /** + * Tests the getJavaFileObjectsFromPaths method for a specific file manager + * and a series of paths. + * + * Note: instances of MyStandardJavaFileManager only support + * encapsulating paths for files in the default file system. + * + * @param fm the file manager to be tested + * @param paths the paths to be tested + * @throws IOException + */ + void test_getJavaFileObjectsFromPaths(StandardJavaFileManager fm, List paths) + throws IOException { + boolean expectException = !isGetFileObjectsSupported(fm, paths); + try { + compile(fm.getJavaFileObjectsFromPaths(paths)); + if (expectException) + error("expected exception not thrown: " + IllegalArgumentException.class.getName()); + } catch (RuntimeException e) { + if (expectException && e instanceof IllegalArgumentException) + return; + error("unexpected exception thrown: " + e); + } + } + + + //---------------------------------------------------------------------------------------------- + + /** + * Compiles a set of files. + * + * @param files the files to be compiled. + * @throws IOException + */ + void compile(Iterable files) throws IOException { + String name = "compile" + (compileCount++); + try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) { + File f = new File(name); + f.mkdirs(); + // use setLocation(Iterable) to avoid relying on setLocationFromPaths + fm.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(f)); + boolean ok = comp.getTask(null, fm, null, null, null, files).call(); + if (!ok) + error(name + ": compilation failed"); + } + } + + int compileCount; +} diff -r 43ed6b2e0e3b -r cd3ea1087d2b langtools/test/tools/javac/api/file/SJFM_IsSameFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/api/file/SJFM_IsSameFile.java Tue Jan 06 14:51:10 2015 -0800 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, 2015, 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 8059977 + * @summary StandardJavaFileManager should support java.nio.file.Path. + * Test isSameFile method. + * @build SJFM_TestBase + * @run main SJFM_IsSameFile + */ + +import java.nio.file.Path; +import java.util.List; +import java.util.concurrent.Callable; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +/** + * For those paths which are supported by a file manager, such that + * a file object can encapsulate the path, verify that the underlying + * paths can be compared. + */ +public class SJFM_IsSameFile extends SJFM_TestBase { + public static void main(String... args) throws Exception { + new SJFM_IsSameFile().run(); + } + + @Test + void test_isSameFile(StandardJavaFileManager fm) throws Exception { + test_isSameFile(fm, () -> getTestFilePaths()); + test_isSameFile(fm, () -> getTestZipPaths()); + } + + /** + * Tests the isSameFile method for a specific file manager + * and a series of paths. + * + * Note: instances of MyStandardJavaFileManager only support + * encapsulating paths for files in the default file system. + * + * @param fm the file manager to be tested + * @param paths a generator for the paths to be tested + * @throws IOException + */ + void test_isSameFile(StandardJavaFileManager fm, Callable> paths) throws Exception { + if (!isGetFileObjectsSupported(fm, paths.call())) + return; + + // use distinct paths and file objects in the following two sets + Iterable setA = fm.getJavaFileObjectsFromPaths(paths.call()); + Iterable setB = fm.getJavaFileObjectsFromPaths(paths.call()); + for (JavaFileObject a : setA) { + for (JavaFileObject b : setB) { + System.err.println("compare: a: " + a); + System.err.println(" b: " + b); + // Use the fileObject getName method to determine the expected result. + // For the files being tested, getName is the absolute path. + boolean expect = a.getName().equals(b.getName()); + boolean actual = fm.isSameFile(a, b); + if (actual != expect) { + error("mismatch: actual:" + (actual ? "same" : "not same") + + ", expect:" + (expect ? "same" : "not same")); + } + } + } + } +} diff -r 43ed6b2e0e3b -r cd3ea1087d2b langtools/test/tools/javac/api/file/SJFM_Locations.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/api/file/SJFM_Locations.java Tue Jan 06 14:51:10 2015 -0800 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2014, 2015, 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 8059977 + * @summary StandardJavaFileManager should support java.nio.file.Path. + * Test get/setLocation methods. + * @build SJFM_TestBase + * @run main SJFM_Locations + */ + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.tools.JavaFileManager; +import javax.tools.StandardJavaFileManager; + +/** + * For those paths which are supported by a file manager, verify + * that setLocation can accept such paths, and that getLocation + * can subsequently return the same paths. + * + * In addition, for files in the default file system, verify + * the combinations of setting a location using files or paths + * and then subsequently getting the location as files or paths. + */ +public class SJFM_Locations extends SJFM_TestBase { + public static void main(String... args) throws Exception { + new SJFM_Locations().run(); + } + + @Test + void test_locations(StandardJavaFileManager fm) throws IOException { + test_setFiles_getFiles(fm, getTestFileDirs()); + test_setFiles_getPaths(fm, getTestFileDirs()); + test_setPaths_getFiles(fm, getTestFilePathDirs()); + test_setPaths_getPaths(fm, getTestFilePathDirs()); +// test_setPaths_getPaths(fm, getTestZipPathDirs()); + } + + void test_setFiles_getFiles(StandardJavaFileManager fm, List inFiles) throws IOException { + System.err.println("test_setFiles_getFiles"); + JavaFileManager.Location l = newLocation(); + fm.setLocation(l, inFiles); + Iterable outFiles = fm.getLocation(l); + compare(inFiles, outFiles); + } + + void test_setFiles_getPaths(StandardJavaFileManager fm, List inFiles) throws IOException { + System.err.println("test_setFiles_getPaths"); + JavaFileManager.Location l = newLocation(); + fm.setLocation(l, inFiles); + Iterable outPaths = fm.getLocationAsPaths(l); + compare(inFiles, outPaths); + } + + void test_setPaths_getFiles(StandardJavaFileManager fm, List inPaths) throws IOException { + System.err.println("test_setPaths_getFiles"); + JavaFileManager.Location l = newLocation(); + fm.setLocationFromPaths(l, inPaths); + Iterable outFiles = fm.getLocation(l); + compare(inPaths, outFiles); + } + + void test_setPaths_getPaths(StandardJavaFileManager fm, List inPaths) throws IOException { + System.err.println("test_setPaths_getPaths"); + JavaFileManager.Location l = newLocation(); + fm.setLocationFromPaths(l, inPaths); + Iterable outPaths = fm.getLocationAsPaths(l); + compare(inPaths, outPaths); + } + + //---------------------------------------------------------------------------------------------- + + /** + * Gets a representative series of directories in the default file system, + * derived from the test.src directory and test.classes path. + * + * @return a list of directories, represented with {@code File} + * @throws IOException + */ + List getTestFileDirs() throws IOException { + return Stream.of("test.src", "test.classes") + .map(s -> System.getProperty(s)) + .flatMap(s -> Stream.of(s.split(File.pathSeparator, 0))) + .filter(s -> !s.isEmpty()) + .map(s -> new File(s)) + .collect(Collectors.toList()); + } + + /** + * Gets a representative series of directories in the default file system, + * derived from the test.src directory and test.classes path. + * + * @return a list of directories, represented with {@code Path} + * @throws IOException + */ + List getTestFilePathDirs() throws IOException { + return Stream.of("test.src", "test.classes") + .map(s -> System.getProperty(s)) + .flatMap(s -> Stream.of(s.split(File.pathSeparator, 0))) + .filter(s -> !s.isEmpty()) + .map(s -> Paths.get(s)) + .collect(Collectors.toList()); + } + + + /** + * Compares two lists of items by comparing their individual string representations. + * + * @param in the first set of items to be compared + * @param out the second set of items to be compared + */ + void compare(Iterable in, Iterable out) { + List ins = toString(in); + List outs = toString(out); + if (!ins.equals(outs)) { + error("mismatch in comparison"); + System.err.println("in:"); + for (String s: ins) System.err.println(s); + System.err.println("out:"); + for (String s: outs) System.err.println(s); + } + } + + List toString(Iterable iter) { + List strings = new ArrayList<>(); + for (Object item: iter) + strings.add(item.toString()); + return strings; + } + + /** + * Create an instance of a location. + * @return a location + */ + JavaFileManager.Location newLocation() { + final String name = "locn" + (count++); + return new JavaFileManager.Location() { + @Override + public String getName() { + return name; + } + + @Override + public boolean isOutputLocation() { + return false; + } + }; + } + + int count = 0; +} diff -r 43ed6b2e0e3b -r cd3ea1087d2b langtools/test/tools/javac/api/file/SJFM_TestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/api/file/SJFM_TestBase.java Tue Jan 06 14:51:10 2015 -0800 @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2014, 2015, 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. + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import javax.tools.JavaCompiler; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +/** + * Base class for unit tests for StandardJavaFileManager. + */ +class SJFM_TestBase { + + /** Shared compiler instance. */ + JavaCompiler comp; + + /** A list of items to be closed when the test is complete. */ + List closeables; + + /** + * Runs a test. This is the primary entry point and should generally be + * called from each test's main method. + * It calls all methods annotated with {@code @Test} with the instances + * of StandardJavaFileManager to be tested. + * + * @throws Exception if the test fails. + */ + void run() throws Exception { + comp = ToolProvider.getSystemJavaCompiler(); + closeables = new ArrayList<>(); + + try (StandardJavaFileManager systemFileManager = comp.getStandardFileManager(null, null, null); + StandardJavaFileManager customFileManager = new MyStandardJavaFileManager(systemFileManager)) { + test(systemFileManager); + test(customFileManager); + } finally { + for (AutoCloseable c: closeables) { + try { + c.close(); + } catch (IOException e) { + error("Exception closing " + c + ": " + e); + } + } + } + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + /** + * Get the file managers to be tested. + * + * Currently, two are provided: + *
      + *
    1. the system-provided file manager + *
    2. a custom file manager, which relies on the default methods provided in the + * StandardJavaFileManager interface + *
    3. + * + * @return the file managers to be tested + */ + List getTestFileManagers() { + StandardJavaFileManager systemFileManager = comp.getStandardFileManager(null, null, null); + StandardJavaFileManager customFileManager = new MyStandardJavaFileManager(systemFileManager); + return Arrays.asList(systemFileManager, customFileManager); + } + + /** + * Tests a specific file manager, by calling all methods annotated + * with {@code @Test} passing this file manager as an argument. + * + * @param fm the file manager to be tested + * @throws Exception if the test fails + */ + void test(StandardJavaFileManager fm) throws Exception { + System.err.println("Testing " + fm); + for (Method m: getClass().getDeclaredMethods()) { + Annotation a = m.getAnnotation(Test.class); + if (a != null) { + try { + System.err.println("Test " + m.getName()); + m.invoke(this, new Object[] { fm }); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + throw (cause instanceof Exception) ? ((Exception) cause) : e; + } + System.err.println(); + } + } + } + + /** Marker annotation for test cases. */ + @Retention(RetentionPolicy.RUNTIME) + @interface Test { } + + /** + * Returns a series of paths for artifacts in the default file system. + * The paths are for the .java files in the test.src directory. + * + * @return a list of paths + * @throws IOException + */ + List getTestFilePaths() throws IOException { + String testSrc = System.getProperty("test.src"); + return Files.list(Paths.get(testSrc)) + .filter(p -> p.getFileName().toString().endsWith(".java")) + .collect(Collectors.toList()); + } + + private FileSystem zipfs; + private List zipPaths; + + /** + * Returns a series of paths for artifacts in a non-default file system. + * A zip file is created containing copies of the .java files in the + * test.src directory. The paths that are returned refer to these files. + * + * @return a list of paths + * @throws IOException + */ + List getTestZipPaths() throws IOException { + if (zipfs == null) { + Path testZip = createSourceZip(); + zipfs = FileSystems.newFileSystem(testZip, null); + closeables.add(zipfs); + zipPaths = Files.list(zipfs.getRootDirectories().iterator().next()) + .filter(p -> p.getFileName().toString().endsWith(".java")) + .collect(Collectors.toList()); + } + return zipPaths; + } + + /** + * Create a zip file containing the contents of the test.src directory. + * + * @return a path for the zip file. + * @throws IOException if there is a problem creating the file + */ + private Path createSourceZip() throws IOException { + Path testSrc = Paths.get(System.getProperty("test.src")); + Path testZip = Paths.get("test.zip"); + try (OutputStream os = Files.newOutputStream(testZip)) { + try (ZipOutputStream zos = new ZipOutputStream(os)) { + Files.list(testSrc) + .filter(p -> p.getFileName().toString().endsWith(".java")) + .forEach(p -> { + try { + zos.putNextEntry(new ZipEntry(p.getFileName().toString())); + zos.write(Files.readAllBytes(p)); + zos.closeEntry(); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }); + } + } + return testZip; + } + + /** + * Tests whether it is expected that a file manager will be able + * to create a series of file objects from a series of paths. + * + * MyStandardJavaFileManager does not support paths referring to + * non-default file systems. + * + * @param fm the file manager to be tested + * @param paths the paths to be tested + * @return + */ + boolean isGetFileObjectsSupported(StandardJavaFileManager fm, List paths) { + return !(fm instanceof MyStandardJavaFileManager + && (paths.get(0).getFileSystem() != FileSystems.getDefault())); + } + + /** + * Report an error. + */ + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + /** Count of errors reported. */ + int errors; + +}