8178509: MODULE_SOURCE_PATH: Implement missing methods
authorjjg
Mon, 17 Apr 2017 14:16:07 -0700
changeset 44690 aec722d1b538
parent 44689 53c703004306
child 44691 3f7b878035be
8178509: MODULE_SOURCE_PATH: Implement missing methods 8178493: StandardJavaFileManager: Clarify/document the use of IllegalStateException Reviewed-by: jlahoda
langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
langtools/test/tools/javac/modules/ModuleSourcePathTest.java
langtools/test/tools/lib/toolbox/JavacTask.java
--- a/langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java	Fri Apr 14 17:23:55 2017 -0700
+++ b/langtools/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java	Mon Apr 17 14:16:07 2017 -0700
@@ -364,7 +364,8 @@
      * @return a list of files or {@code null} if this location has no
      * associated search path
      * @throws IllegalStateException if any element of the search path
-     * cannot be converted to a {@linkplain File}.
+     * cannot be converted to a {@linkplain File}, or if the search path
+     * cannot be represented as a simple series of files.
      *
      * @see #setLocation
      * @see Path#toFile
@@ -382,6 +383,8 @@
      * @param location a location
      * @return a list of paths or {@code null} if this location has no
      * associated search path
+     * @throws IllegalStateException if the search path cannot be represented
+     * as a simple series of paths.
      *
      * @see #setLocationFromPaths
      * @since 9
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Fri Apr 14 17:23:55 2017 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Mon Apr 17 14:16:07 2017 -0700
@@ -1349,6 +1349,7 @@
 
     private class ModuleSourcePathLocationHandler extends BasicLocationHandler {
         private ModuleTable moduleTable;
+        private List<Path> paths;
 
         ModuleSourcePathLocationHandler() {
             super(StandardLocation.MODULE_SOURCE_PATH,
@@ -1368,11 +1369,15 @@
             }
 
             Map<String, List<Path>> map = new LinkedHashMap<>();
+            List<Path> noSuffixPaths = new ArrayList<>();
+            boolean anySuffix = false;
             final String MARKER = "*";
             for (String seg: segments) {
                 int markStart = seg.indexOf(MARKER);
                 if (markStart == -1) {
-                    add(map, getPath(seg), null);
+                    Path p = getPath(seg);
+                    add(map, p, null);
+                    noSuffixPaths.add(p);
                 } else {
                     if (markStart == 0 || !isSeparator(seg.charAt(markStart - 1))) {
                         throw new IllegalArgumentException("illegal use of " + MARKER + " in " + seg);
@@ -1387,11 +1392,20 @@
                         throw new IllegalArgumentException("illegal use of " + MARKER + " in " + seg);
                     } else {
                         suffix = getPath(seg.substring(markEnd + 1));
+                        anySuffix = true;
                     }
                     add(map, prefix, suffix);
+                    if (suffix == null) {
+                        noSuffixPaths.add(prefix);
+                    }
                 }
             }
 
+            initModuleTable(map);
+            paths = anySuffix ? null : noSuffixPaths;
+        }
+
+        private void initModuleTable(Map<String, List<Path>> map) {
             moduleTable = new ModuleTable();
             map.forEach((modName, modPath) -> {
                 boolean hasModuleInfo = modPath.stream().anyMatch(checkModuleInfo);
@@ -1509,12 +1523,25 @@
 
         @Override
         Collection<Path> getPaths() {
-            throw new UnsupportedOperationException();
+            if (paths == null) {
+                // This may occur for a complex setting with --module-source-path option
+                // i.e. one that cannot be represented by a simple series of paths.
+                throw new IllegalStateException("paths not available");
+            }
+            return paths;
         }
 
         @Override
         void setPaths(Iterable<? extends Path> files) throws IOException {
-            throw new UnsupportedOperationException();
+            Map<String, List<Path>> map = new LinkedHashMap<>();
+            List<Path> newPaths = new ArrayList<>();
+            for (Path file : files) {
+                add(map, file, null);
+                newPaths.add(file);
+            }
+
+            initModuleTable(map);
+            paths = Collections.unmodifiableList(newPaths);
         }
 
         @Override
--- a/langtools/test/tools/javac/modules/ModuleSourcePathTest.java	Fri Apr 14 17:23:55 2017 -0700
+++ b/langtools/test/tools/javac/modules/ModuleSourcePathTest.java	Mon Apr 17 14:16:07 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,11 +37,18 @@
 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.stream.Stream;
 
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
 import toolbox.JavacTask;
 import toolbox.Task;
 import toolbox.ToolBox;
@@ -442,6 +449,76 @@
         }
     }
 
+    @Test
+    public void setLocation(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src.resolve("m1x"), "module m1x { }", "package a; class A { }");
+        Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        JavaCompiler c = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) {
+            fm.setLocationFromPaths(StandardLocation.MODULE_SOURCE_PATH, List.of(src));
+            new JavacTask(tb)
+                    .options("-XDrawDiagnostics")
+                    .fileManager(fm)
+                    .outdir(modules)
+                    .files(findJavaFiles(src))
+                    .run()
+                    .writeAll();
+
+            checkFiles(modules.resolve("m1x/module-info.class"), modules.resolve("m1x/a/A.class"));
+        }
+    }
+
+    @Test
+    public void getLocation_valid(Path base) throws Exception {
+        Path src1 = base.resolve("src1");
+        tb.writeJavaFiles(src1.resolve("m1x"), "module m1x { }", "package a; class A { }");
+        Path src2 = base.resolve("src2");
+        tb.writeJavaFiles(src1.resolve("m2x"), "module m2x { }", "package b; class B { }");
+
+        JavaCompiler c = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) {
+            fm.setLocationFromPaths(StandardLocation.MODULE_SOURCE_PATH, List.of(src1, src2));
+            checkLocation(fm.getLocationAsPaths(StandardLocation.MODULE_SOURCE_PATH), List.of(src1, src2));
+        }
+    }
+
+    @Test
+    public void getLocation_ISA(Path base) throws Exception {
+        Path src1 = base.resolve("src1");
+        tb.writeJavaFiles(src1.resolve("m1x"), "module m1x { }", "package a; class A { }");
+        Path src2 = base.resolve("src2");
+        tb.writeJavaFiles(src2.resolve("m2x").resolve("extra"), "module m2x { }", "package b; class B { }");
+        Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        String FS = File.separator;
+        String PS = File.pathSeparator;
+        JavaCompiler c = ToolProvider.getSystemJavaCompiler();
+        try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) {
+            fm.handleOption("--module-source-path",
+                    List.of(src1 + PS + src2 + FS + "*" + FS + "extra").iterator());
+
+            try {
+                Iterable<? extends Path> paths = fm.getLocationAsPaths(StandardLocation.MODULE_SOURCE_PATH);
+                out.println("result: " + asList(paths));
+                throw new Exception("expected IllegalStateException not thrown");
+            } catch (IllegalStateException e) {
+                out.println("Exception thrown, as expected: " + e);
+            }
+
+            // even if we can't do getLocation for the MODULE_SOURCE_PATH, we should be able
+            // to do getLocation for the modules, which will additionally confirm the option
+            // was effective as intended.
+            Location locn1 = fm.getLocationForModule(StandardLocation.MODULE_SOURCE_PATH, "m1x");
+            checkLocation(fm.getLocationAsPaths(locn1), List.of(src1.resolve("m1x")));
+            Location locn2 = fm.getLocationForModule(StandardLocation.MODULE_SOURCE_PATH, "m2x");
+            checkLocation(fm.getLocationAsPaths(locn2), List.of(src2.resolve("m2x").resolve("extra")));
+        }
+    }
+
     private void generateModules(Path base, String... paths) throws IOException {
         for (int i = 0; i < paths.length; i++) {
             String moduleName = "m" + i + "x";
@@ -455,8 +532,25 @@
     private void checkFiles(Path... files) throws Exception {
         for (Path file : files) {
             if (!Files.exists(file)) {
-                throw new Exception("File not exists: " + file);
+                throw new Exception("File not found: " + file);
             }
         }
     }
+
+    private void checkLocation(Iterable<? extends Path> locn, List<Path> ref) throws Exception {
+        List<Path> list = asList(locn);
+        if (!list.equals(ref)) {
+            out.println("expect: " + ref);
+            out.println(" found: " + list);
+            throw new Exception("location not as expected");
+        }
+    }
+
+    private <T> List<T> asList(Iterable<? extends T> iter) {
+        List<T> list = new ArrayList<>();
+        for (T item : iter) {
+            list.add(item);
+        }
+        return list;
+    }
 }
--- a/langtools/test/tools/lib/toolbox/JavacTask.java	Fri Apr 14 17:23:55 2017 -0700
+++ b/langtools/test/tools/lib/toolbox/JavacTask.java	Mon Apr 17 14:16:07 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -287,10 +287,13 @@
                     rc = runAPI(direct.pw);
                     break;
                 case CMDLINE:
+                    if (fileManager != null) {
+                        throw new IllegalStateException("file manager set in CMDLINE mode");
+                    }
                     rc = runCommand(direct.pw);
                     break;
                 default:
-                    throw new IllegalStateException();
+                    throw new IllegalStateException("unknown mode " + mode);
             }
         } catch (IOException e) {
             toolBox.out.println("Exception occurred: " + e);