1 /* |
1 /* |
2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
58 import com.sun.tools.javac.model.JavacElements; |
58 import com.sun.tools.javac.model.JavacElements; |
59 import com.sun.tools.javac.util.*; |
59 import com.sun.tools.javac.util.*; |
60 import com.sun.tools.javac.util.DefinedBy.Api; |
60 import com.sun.tools.javac.util.DefinedBy.Api; |
61 |
61 |
62 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; |
62 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; |
|
63 import com.sun.tools.javac.code.Symbol.PackageSymbol; |
|
64 import com.sun.tools.javac.main.Option; |
63 |
65 |
64 /** |
66 /** |
65 * The FilerImplementation class must maintain a number of |
67 * The FilerImplementation class must maintain a number of |
66 * constraints. First, multiple attempts to open the same path within |
68 * constraints. First, multiple attempts to open the same path within |
67 * the same invocation of the tool results in an IOException being |
69 * the same invocation of the tool results in an IOException being |
382 */ |
384 */ |
383 private final Set<Pair<ModuleSymbol, String>> aggregateGeneratedClassNames; |
385 private final Set<Pair<ModuleSymbol, String>> aggregateGeneratedClassNames; |
384 |
386 |
385 private final Set<String> initialClassNames; |
387 private final Set<String> initialClassNames; |
386 |
388 |
|
389 private final String defaultTargetModule; |
|
390 |
387 JavacFiler(Context context) { |
391 JavacFiler(Context context) { |
388 this.context = context; |
392 this.context = context; |
389 fileManager = context.get(JavaFileManager.class); |
393 fileManager = context.get(JavaFileManager.class); |
390 elementUtils = JavacElements.instance(context); |
394 elementUtils = JavacElements.instance(context); |
391 |
395 |
406 aggregateGeneratedSourceNames = new LinkedHashSet<>(); |
410 aggregateGeneratedSourceNames = new LinkedHashSet<>(); |
407 aggregateGeneratedClassNames = new LinkedHashSet<>(); |
411 aggregateGeneratedClassNames = new LinkedHashSet<>(); |
408 initialClassNames = new LinkedHashSet<>(); |
412 initialClassNames = new LinkedHashSet<>(); |
409 |
413 |
410 lint = (Lint.instance(context)).isEnabled(PROCESSING); |
414 lint = (Lint.instance(context)).isEnabled(PROCESSING); |
|
415 |
|
416 Options options = Options.instance(context); |
|
417 |
|
418 defaultTargetModule = options.get(Option.DEFAULT_MODULE_FOR_CREATED_FILES); |
411 } |
419 } |
412 |
420 |
413 @Override @DefinedBy(Api.ANNOTATION_PROCESSING) |
421 @Override @DefinedBy(Api.ANNOTATION_PROCESSING) |
414 public JavaFileObject createSourceFile(CharSequence nameAndModule, |
422 public JavaFileObject createSourceFile(CharSequence nameAndModule, |
415 Element... originatingElements) throws IOException { |
423 Element... originatingElements) throws IOException { |
425 } |
433 } |
426 |
434 |
427 private Pair<ModuleSymbol, String> checkOrInferModule(CharSequence moduleAndPkg) throws FilerException { |
435 private Pair<ModuleSymbol, String> checkOrInferModule(CharSequence moduleAndPkg) throws FilerException { |
428 String moduleAndPkgString = moduleAndPkg.toString(); |
436 String moduleAndPkgString = moduleAndPkg.toString(); |
429 int slash = moduleAndPkgString.indexOf('/'); |
437 int slash = moduleAndPkgString.indexOf('/'); |
430 |
438 String module; |
431 if (slash != (-1)) { |
439 String pkg; |
|
440 |
|
441 if (slash == (-1)) { |
|
442 //module name not specified: |
|
443 int lastDot = moduleAndPkgString.lastIndexOf('.'); |
|
444 String pack = lastDot != (-1) ? moduleAndPkgString.substring(0, lastDot) : ""; |
|
445 ModuleSymbol msym = inferModule(pack); |
|
446 |
|
447 if (msym != null) { |
|
448 return Pair.of(msym, moduleAndPkgString); |
|
449 } |
|
450 |
|
451 if (defaultTargetModule == null) { |
|
452 throw new FilerException("Cannot determine target module."); |
|
453 } |
|
454 |
|
455 module = defaultTargetModule; |
|
456 pkg = moduleAndPkgString; |
|
457 } else { |
432 //module name specified: |
458 //module name specified: |
433 String module = moduleAndPkgString.substring(0, slash); |
459 module = moduleAndPkgString.substring(0, slash); |
434 |
460 pkg = moduleAndPkgString.substring(slash + 1); |
435 ModuleSymbol explicitModule = syms.getModule(names.fromString(module)); |
461 } |
436 |
462 |
437 if (explicitModule == null) { |
463 ModuleSymbol explicitModule = syms.getModule(names.fromString(module)); |
438 throw new FilerException("Module: " + module + " does not exist."); |
464 |
439 } |
465 if (explicitModule == null) { |
440 |
466 throw new FilerException("Module: " + module + " does not exist."); |
441 if (!modules.isRootModule(explicitModule)) { |
467 } |
442 throw new FilerException("Cannot write to the given module!"); |
468 |
443 } |
469 if (!modules.isRootModule(explicitModule)) { |
444 |
470 throw new FilerException("Cannot write to the given module."); |
445 return Pair.of(explicitModule, moduleAndPkgString.substring(slash + 1)); |
471 } |
446 } else { |
472 |
447 if (modules.multiModuleMode) { |
473 return Pair.of(explicitModule, pkg); |
448 throw new FilerException("No module to write to specified!"); |
|
449 } |
|
450 |
|
451 return Pair.of(modules.getDefaultModule(), moduleAndPkgString); |
|
452 } |
|
453 } |
474 } |
454 |
475 |
455 private JavaFileObject createSourceOrClassFile(ModuleSymbol mod, boolean isSourceFile, String name) throws IOException { |
476 private JavaFileObject createSourceOrClassFile(ModuleSymbol mod, boolean isSourceFile, String name) throws IOException { |
456 Assert.checkNonNull(mod); |
477 Assert.checkNonNull(mod); |
457 |
478 |
493 @Override @DefinedBy(Api.ANNOTATION_PROCESSING) |
514 @Override @DefinedBy(Api.ANNOTATION_PROCESSING) |
494 public FileObject createResource(JavaFileManager.Location location, |
515 public FileObject createResource(JavaFileManager.Location location, |
495 CharSequence moduleAndPkg, |
516 CharSequence moduleAndPkg, |
496 CharSequence relativeName, |
517 CharSequence relativeName, |
497 Element... originatingElements) throws IOException { |
518 Element... originatingElements) throws IOException { |
498 Pair<ModuleSymbol, String> moduleAndPackage = checkOrInferModule(moduleAndPkg); |
519 Tuple3<Location, ModuleSymbol, String> locationModuleAndPackage = checkOrInferModule(location, moduleAndPkg, true); |
499 ModuleSymbol msym = moduleAndPackage.fst; |
520 location = locationModuleAndPackage.a; |
500 String pkg = moduleAndPackage.snd; |
521 ModuleSymbol msym = locationModuleAndPackage.b; |
|
522 String pkg = locationModuleAndPackage.c; |
501 |
523 |
502 locationCheck(location); |
524 locationCheck(location); |
503 |
|
504 if (modules.multiModuleMode) { |
|
505 Assert.checkNonNull(msym); |
|
506 location = this.fileManager.getLocationForModule(location, msym.name.toString()); |
|
507 } |
|
508 |
525 |
509 String strPkg = pkg.toString(); |
526 String strPkg = pkg.toString(); |
510 if (strPkg.length() > 0) |
527 if (strPkg.length() > 0) |
511 checkName(strPkg); |
528 checkName(strPkg); |
512 |
529 |
532 |
549 |
533 @Override @DefinedBy(Api.ANNOTATION_PROCESSING) |
550 @Override @DefinedBy(Api.ANNOTATION_PROCESSING) |
534 public FileObject getResource(JavaFileManager.Location location, |
551 public FileObject getResource(JavaFileManager.Location location, |
535 CharSequence moduleAndPkg, |
552 CharSequence moduleAndPkg, |
536 CharSequence relativeName) throws IOException { |
553 CharSequence relativeName) throws IOException { |
537 Pair<ModuleSymbol, String> moduleAndPackage = checkOrInferModule(moduleAndPkg); |
554 Tuple3<Location, ModuleSymbol, String> locationModuleAndPackage = checkOrInferModule(location, moduleAndPkg, false); |
538 ModuleSymbol msym = moduleAndPackage.fst; |
555 location = locationModuleAndPackage.a; |
539 String pkg = moduleAndPackage.snd; |
556 String pkg = locationModuleAndPackage.c; |
540 |
|
541 if (modules.multiModuleMode) { |
|
542 Assert.checkNonNull(msym); |
|
543 location = this.fileManager.getLocationForModule(location, msym.name.toString()); |
|
544 } |
|
545 |
557 |
546 if (pkg.length() > 0) |
558 if (pkg.length() > 0) |
547 checkName(pkg); |
559 checkName(pkg); |
548 |
560 |
549 // TODO: Only support reading resources in selected output |
561 // TODO: Only support reading resources in selected output |
574 } |
586 } |
575 |
587 |
576 // If the path was already opened for writing, throw an exception. |
588 // If the path was already opened for writing, throw an exception. |
577 checkFileReopening(fileObject, false); |
589 checkFileReopening(fileObject, false); |
578 return new FilerInputFileObject(fileObject); |
590 return new FilerInputFileObject(fileObject); |
|
591 } |
|
592 |
|
593 private Tuple3<JavaFileManager.Location, ModuleSymbol, String> checkOrInferModule(JavaFileManager.Location location, |
|
594 CharSequence moduleAndPkg, |
|
595 boolean write) throws IOException { |
|
596 String moduleAndPkgString = moduleAndPkg.toString(); |
|
597 int slash = moduleAndPkgString.indexOf('/'); |
|
598 boolean multiModuleLocation = location.isModuleOrientedLocation() || |
|
599 (modules.multiModuleMode && location.isOutputLocation()); |
|
600 String module; |
|
601 String pkg; |
|
602 |
|
603 if (slash == (-1)) { |
|
604 //module name not specified: |
|
605 if (!multiModuleLocation) { |
|
606 //package oriented location: |
|
607 return new Tuple3<>(location, modules.getDefaultModule(), moduleAndPkgString); |
|
608 } |
|
609 |
|
610 if (location.isOutputLocation()) { |
|
611 ModuleSymbol msym = inferModule(moduleAndPkgString); |
|
612 |
|
613 if (msym != null) { |
|
614 Location moduleLoc = |
|
615 fileManager.getLocationForModule(location, msym.name.toString()); |
|
616 return new Tuple3<>(moduleLoc, msym, moduleAndPkgString); |
|
617 } |
|
618 } |
|
619 |
|
620 if (defaultTargetModule == null) { |
|
621 throw new FilerException("No module specified and the location is either " + |
|
622 "a module-oriented location, or a multi-module " + |
|
623 "output location."); |
|
624 } |
|
625 |
|
626 module = defaultTargetModule; |
|
627 pkg = moduleAndPkgString; |
|
628 } else { |
|
629 //module name specified: |
|
630 module = moduleAndPkgString.substring(0, slash); |
|
631 pkg = moduleAndPkgString.substring(slash + 1); |
|
632 } |
|
633 |
|
634 if (multiModuleLocation) { |
|
635 ModuleSymbol explicitModule = syms.getModule(names.fromString(module)); |
|
636 |
|
637 if (explicitModule == null) { |
|
638 throw new FilerException("Module: " + module + " does not exist."); |
|
639 } |
|
640 |
|
641 if (write && !modules.isRootModule(explicitModule)) { |
|
642 throw new FilerException("Cannot write to the given module."); |
|
643 } |
|
644 |
|
645 Location moduleLoc = fileManager.getLocationForModule(location, module); |
|
646 |
|
647 return new Tuple3<>(moduleLoc, explicitModule, pkg); |
|
648 } else { |
|
649 throw new FilerException("Module specified but the location is neither " + |
|
650 "a module-oriented location, nor a multi-module " + |
|
651 "output location."); |
|
652 } |
|
653 } |
|
654 |
|
655 static final class Tuple3<A, B, C> { |
|
656 final A a; |
|
657 final B b; |
|
658 final C c; |
|
659 |
|
660 public Tuple3(A a, B b, C c) { |
|
661 this.a = a; |
|
662 this.b = b; |
|
663 this.c = c; |
|
664 } |
|
665 } |
|
666 |
|
667 private ModuleSymbol inferModule(String pkg) { |
|
668 if (modules.getDefaultModule() == syms.noModule) |
|
669 return modules.getDefaultModule(); |
|
670 |
|
671 Set<ModuleSymbol> rootModules = modules.getRootModules(); |
|
672 |
|
673 if (rootModules.size() == 1) { |
|
674 return rootModules.iterator().next(); |
|
675 } |
|
676 |
|
677 PackageSymbol pack = elementUtils.getPackageElement(pkg); |
|
678 |
|
679 if (pack != null && pack.modle != syms.unnamedModule) { |
|
680 return pack.modle; |
|
681 } |
|
682 |
|
683 return null; |
579 } |
684 } |
580 |
685 |
581 private void checkName(String name) throws FilerException { |
686 private void checkName(String name) throws FilerException { |
582 checkName(name, false); |
687 checkName(name, false); |
583 } |
688 } |