1 /* 2 * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @bug 8173914 8188035 27 * @summary JavaFileManager.setLocationForModule 28 * @modules jdk.compiler/com.sun.tools.javac.api 29 * jdk.compiler/com.sun.tools.javac.main 30 * @library /tools/lib 31 * @build toolbox.JavacTask toolbox.TestRunner toolbox.ToolBox SetLocationForModule 32 * @run main SetLocationForModule 33 */ 34 35 36 import java.io.FileNotFoundException; 37 import java.io.IOException; 38 import java.nio.file.Files; 39 import java.nio.file.Path; 40 import java.nio.file.Paths; 41 import java.util.ArrayList; 42 import java.util.Collections; 43 import java.util.List; 44 import java.util.Objects; 45 import java.util.Set; 46 47 import javax.tools.JavaCompiler; 48 import javax.tools.JavaFileManager; 49 import javax.tools.JavaFileManager.Location; 50 import javax.tools.StandardJavaFileManager; 51 import javax.tools.StandardLocation; 52 import javax.tools.ToolProvider; 53 54 import toolbox.JavacTask; 55 import toolbox.TestRunner; 56 import toolbox.TestRunner.Test; 57 import toolbox.ToolBox; 58 59 public class SetLocationForModule extends TestRunner { 60 main(String... args)61 public static void main(String... args) throws Exception { 62 new SetLocationForModule().runTests(m -> new Object[] { Paths.get(m.getName()) }); 63 } 64 SetLocationForModule()65 public SetLocationForModule() { 66 super(System.err); 67 } 68 69 private final JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); 70 private final ToolBox tb = new ToolBox(); 71 72 @Test testBasic(Path base)73 public void testBasic(Path base) throws IOException { 74 try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) { 75 Location[] locns = { 76 StandardLocation.SOURCE_PATH, 77 StandardLocation.CLASS_PATH, 78 StandardLocation.PLATFORM_CLASS_PATH, 79 }; 80 // set a value 81 Path out = Files.createDirectories(base.resolve("out")); 82 for (Location locn : locns) { 83 checkException("unsupported for location", 84 IllegalArgumentException.class, 85 "location is not an output location or a module-oriented location: " + locn, 86 () -> fm.setLocationForModule(locn, "m", List.of(out))); 87 } 88 } 89 } 90 91 @Test testModulePath(Path base)92 public void testModulePath(Path base) throws IOException { 93 try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) { 94 Path src = base.resolve("src"); 95 Path src_m = src.resolve("m"); 96 tb.writeJavaFiles(src_m, "module m { }"); 97 98 Location locn = StandardLocation.MODULE_PATH; 99 100 Path modules1 = Files.createDirectories(base.resolve("modules1")); 101 new JavacTask(tb) 102 .outdir(modules1) 103 .options("--module-source-path", src.toString()) 104 .files(tb.findJavaFiles(src)) 105 .run(); 106 fm.setLocationFromPaths(locn, List.of(modules1)); 107 108 Location m = fm.getLocationForModule(locn, "m"); 109 checkEqual("default setting", 110 fm.getLocationAsPaths(m), modules1.resolve("m")); 111 112 Path override1 = Files.createDirectories(base.resolve("override1")); 113 fm.setLocationForModule(locn, "m", List.of(override1)); 114 checkEqual("override setting 1", 115 fm.getLocationAsPaths(m), override1); 116 117 checkEqual("override setting 1b", 118 fm.getLocationAsPaths(fm.listLocationsForModules(locn).iterator().next().iterator().next()), 119 override1); 120 121 try (StandardJavaFileManager fm2 = comp.getStandardFileManager(null, null, null)) { 122 fm2.setLocationForModule(locn, "m", List.of(override1)); 123 checkEqual("override setting 2", 124 fm2.getLocationAsPaths(m), override1); 125 126 Location firstLocation = 127 fm2.listLocationsForModules(locn).iterator().next().iterator().next(); 128 129 checkEqual("override setting 2b", 130 fm2.getLocationAsPaths(firstLocation), 131 override1); 132 } 133 134 Path override2 = Files.createDirectories(base.resolve("override2")); 135 fm.setLocationFromPaths(m, List.of(override2)); 136 checkEqual("override setting 3", 137 fm.getLocationAsPaths(m), override2); 138 139 Path modules2 = Files.createDirectories(base.resolve("modules2")); 140 new JavacTask(tb) 141 .outdir(modules2) 142 .options("--module-source-path", src.toString()) 143 .files(tb.findJavaFiles(src)) 144 .run(); 145 fm.setLocationFromPaths(locn, List.of(modules2)); 146 147 m = fm.getLocationForModule(locn, "m"); 148 149 checkEqual("updated setting", 150 fm.getLocationAsPaths(m), modules2.resolve("m")); 151 } 152 } 153 154 @Test testModuleSourcePath(Path base)155 public void testModuleSourcePath(Path base) throws IOException { 156 try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) { 157 158 Location locn = StandardLocation.MODULE_SOURCE_PATH; 159 160 Path src1 = Files.createDirectories(base.resolve("src1")); 161 Path src1_m = src1.resolve("m"); 162 tb.writeJavaFiles(src1_m, "module m { }"); 163 fm.setLocationFromPaths(locn, List.of(src1)); 164 165 Location m = fm.getLocationForModule(locn, "m"); 166 checkEqual("default setting", 167 fm.getLocationAsPaths(m), src1.resolve("m")); 168 169 Path override1 = Files.createDirectories(base.resolve("override1")); 170 tb.writeJavaFiles(override1, "module m { }"); 171 fm.setLocationForModule(locn, "m", List.of(override1)); 172 checkEqual("override setting 1", 173 fm.getLocationAsPaths(m), override1); 174 175 checkEqual("override setting 1b", 176 fm.getLocationAsPaths(fm.listLocationsForModules(locn).iterator().next().iterator().next()), 177 override1); 178 179 Path override2 = Files.createDirectories(base.resolve("override2")); 180 tb.writeJavaFiles(override2, "module m { }"); 181 fm.setLocationFromPaths(m, List.of(override2)); 182 checkEqual("override setting 2", 183 fm.getLocationAsPaths(m), override2); 184 185 Path src2 = Files.createDirectories(base.resolve("src2")); 186 Path src2_m = src2.resolve("m"); 187 tb.writeJavaFiles(src2_m, "module m { }"); 188 fm.setLocationFromPaths(locn, List.of(src2)); 189 190 m = fm.getLocationForModule(locn, "m"); 191 192 checkEqual("updated setting", 193 fm.getLocationAsPaths(m), src2.resolve("m")); 194 } 195 } 196 197 @Test testOutput(Path base)198 public void testOutput(Path base) throws IOException { 199 try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) { 200 Location locn = StandardLocation.CLASS_OUTPUT; 201 202 Path out1 = Files.createDirectories(base.resolve("out1")); 203 fm.setLocationFromPaths(locn, List.of(out1)); 204 205 Location m = fm.getLocationForModule(locn, "m"); 206 checkEqual("default setting", 207 fm.getLocationAsPaths(m), out1.resolve("m")); 208 209 Path override1 = Files.createDirectories(base.resolve("override1")); 210 fm.setLocationForModule(locn, "m", List.of(override1)); 211 checkEqual("override setting 1", 212 fm.getLocationAsPaths(m), override1); 213 214 checkEqual("override setting 1b", 215 fm.getLocationAsPaths(fm.listLocationsForModules(locn).iterator().next().iterator().next()), 216 override1); 217 218 try (StandardJavaFileManager fm2 = comp.getStandardFileManager(null, null, null)) { 219 fm2.setLocationForModule(locn, "m", List.of(override1)); 220 checkEqual("override setting 1", 221 fm2.getLocationAsPaths(m), override1); 222 223 Location firstLocation = 224 fm2.listLocationsForModules(locn).iterator().next().iterator().next(); 225 226 checkEqual("override setting 1b", 227 fm2.getLocationAsPaths(firstLocation), 228 override1); 229 } 230 231 Path override2 = Files.createDirectories(base.resolve("override2")); 232 fm.setLocationFromPaths(m, List.of(override2)); 233 checkEqual("override setting 2", 234 fm.getLocationAsPaths(m), override2); 235 236 Path out2 = Files.createDirectories(base.resolve("out2")); 237 fm.setLocationFromPaths(locn, List.of(out2)); 238 239 m = fm.getLocationForModule(locn, "m"); 240 241 checkEqual("updated setting", 242 fm.getLocationAsPaths(m), out2.resolve("m")); 243 } 244 } 245 246 @Test testOutput_invalid(Path base)247 public void testOutput_invalid(Path base) throws IOException { 248 try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) { 249 Location locn = StandardLocation.CLASS_OUTPUT; 250 // set a top default 251 Path out1 = Files.createDirectories(base.resolve("out1")); 252 fm.setLocationFromPaths(locn, List.of(out1)); 253 // getLocnForModule 254 Location m = fm.getLocationForModule(locn, "m"); 255 checkEqual("default setting", 256 fm.getLocationAsPaths(m), out1.resolve("m")); 257 258 checkException("empty arg list", 259 IllegalArgumentException.class, "empty path for directory", 260 () -> fm.setLocationFromPaths(m, Collections.emptyList())); 261 262 Path out2 = Files.createDirectories(base.resolve("out2")); 263 checkException("empty arg list", 264 IllegalArgumentException.class, "path too long for directory", 265 () -> fm.setLocationFromPaths(m, List.of(out2, out2))); 266 267 Path notExist = base.resolve("notExist"); 268 checkException("not exist", 269 FileNotFoundException.class, notExist + ": does not exist", 270 () -> fm.setLocationFromPaths(m, List.of(notExist))); 271 272 Path file = Files.createFile(base.resolve("file.txt")); 273 checkException("not exist", 274 IOException.class, file + ": not a directory", 275 () -> fm.setLocationFromPaths(m, List.of(file))); 276 } 277 } 278 279 @Test testOutput_nested(Path base)280 public void testOutput_nested(Path base) throws IOException { 281 try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) { 282 Location locn = StandardLocation.CLASS_OUTPUT; 283 284 Path out1 = Files.createDirectories(base.resolve("out1")); 285 fm.setLocationForModule(locn, "m", List.of(out1)); 286 287 Location m = fm.getLocationForModule(locn, "m"); 288 checkEqual("initial setting", 289 fm.getLocationAsPaths(m), out1); 290 291 Path out2 = Files.createDirectories(base.resolve("out2")); 292 checkException("create nested module", 293 UnsupportedOperationException.class, "not supported for CLASS_OUTPUT[m]", 294 () -> fm.setLocationForModule(m, "x", List.of(out2))); 295 } 296 } 297 298 @Test testSystemModules(Path base)299 public void testSystemModules(Path base) throws IOException { 300 try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) { 301 Location locn = StandardLocation.SYSTEM_MODULES; 302 303 Location javaCompiler = fm.getLocationForModule(locn, "java.compiler"); 304 // cannot easily verify default setting: could be jrt: or exploded image 305 306 Path override1 = Files.createDirectories(base.resolve("override1")); 307 fm.setLocationForModule(locn, "java.compiler", List.of(override1)); 308 checkEqual("override setting 1", 309 fm.getLocationAsPaths(javaCompiler), override1); 310 311 checkEqual("override setting 1b", 312 fm.getLocationAsPaths(findLocation(fm, fm.listLocationsForModules(locn), "java.compiler")), 313 override1); 314 315 Path override2 = Files.createDirectories(base.resolve("override2")); 316 fm.setLocationFromPaths(javaCompiler, List.of(override2)); 317 checkEqual("override setting 2", 318 fm.getLocationAsPaths(javaCompiler), override2); 319 } 320 } 321 findLocation(JavaFileManager fm, Iterable<Set<Location>> locations, String moduleName)322 private Location findLocation(JavaFileManager fm, Iterable<Set<Location>> locations, String moduleName) { 323 for (Set<Location> locs : locations) { 324 for (Location loc : locs) { 325 try { 326 if (moduleName.equals(fm.inferModuleName(loc))) { 327 return loc; 328 } 329 } catch (IOException ex) { 330 throw new IllegalStateException(ex); 331 } 332 } 333 } 334 335 throw new IllegalStateException(); 336 } 337 338 @Test testTemplate(Path base)339 public void testTemplate(Path base) { 340 // set a top default 341 // getLocnForModule 342 // set a value 343 // getLocnForModule 344 // reset 345 // getLocationForModule 346 } 347 348 interface RunnableWithException { run()349 public void run() throws Exception; 350 } 351 checkException(String message, Class<? extends Throwable> expectedException, String expectedMessage, RunnableWithException r)352 void checkException(String message, 353 Class<? extends Throwable> expectedException, String expectedMessage, 354 RunnableWithException r) { 355 try { 356 r.run(); 357 error(message + ": expected exception not thrown: " + expectedException); 358 } catch (Exception | Error t) { 359 if (expectedException.isAssignableFrom(t.getClass())) { 360 checkEqual("exception message", 361 t.getMessage(), expectedMessage); 362 363 } else { 364 error(message + ": unexpected exception\n" 365 + "expect: " + expectedException + "\n" 366 + " found: " + t); 367 } 368 } 369 } 370 checkEqual(String message, Iterable<? extends Path> found, Path... expect)371 void checkEqual(String message, Iterable<? extends Path> found, Path... expect) { 372 List<Path> fList = asList(found); 373 List<Path> eList = List.of(expect); 374 if (!Objects.equals(fList, eList)) { 375 error(message + ": lists not equal\n" 376 + "expect: " + eList + "\n" 377 + " found: " + fList); 378 } 379 } 380 checkEqual(String message, String found, String expect)381 void checkEqual(String message, String found, String expect) { 382 if (!Objects.equals(found, expect)) { 383 error(message + ": strings not equal\n" 384 + "expect: " + expect + "\n" 385 + " found: " + found); 386 } 387 } 388 asList(Iterable<? extends Path> a)389 List<Path> asList(Iterable<? extends Path> a) { 390 List<Path> list = new ArrayList<>(); 391 for (Path p : a) { 392 list.add(p); 393 } 394 return list; 395 } 396 } 397 398