1 /*
2 * Copyright (c) 2012, 2014, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
523 reportError(e.getKey(), e.getArgs());
524 if (e.showUsage()) {
525 log.println(getMessage("main.usage.summary", PROGNAME));
526 }
527 return EXIT_CMDERR;
528 } catch (ResolutionException e) {
529 reportError("err.exception.message", e.getMessage());
530 return EXIT_CMDERR;
531 } catch (IOException e) {
532 e.printStackTrace();
533 return EXIT_CMDERR;
534 } catch (MultiReleaseException e) {
535 reportError(e.getKey(), e.getParams());
536 return EXIT_CMDERR; // could be EXIT_ABNORMAL sometimes
537 } finally {
538 log.flush();
539 }
540 }
541
542 boolean run() throws IOException {
543 try (JdepsConfiguration config = buildConfig(command.allModules())) {
544 if (!options.nowarning) {
545 // detect split packages
546 config.splitPackages().entrySet()
547 .stream()
548 .sorted(Map.Entry.comparingByKey())
549 .forEach(e -> warning("warn.split.package",
550 e.getKey(),
551 e.getValue().stream().collect(joining(" "))));
552 }
553
554 // check if any module specified in --add-modules, --require, and -m is missing
555 options.addmods.stream()
556 .filter(mn -> !config.isValidToken(mn))
557 .forEach(mn -> config.findModule(mn).orElseThrow(() ->
558 new UncheckedBadArgs(new BadArgs("err.module.not.found", mn))));
559
560 return command.run(config);
561 }
562 }
563
564 private JdepsConfiguration buildConfig(boolean allModules) throws IOException {
565 JdepsConfiguration.Builder builder =
566 new JdepsConfiguration.Builder(options.systemModulePath);
567
568 builder.upgradeModulePath(options.upgradeModulePath)
569 .appModulePath(options.modulePath)
570 .addmods(options.addmods);
571
572 if (allModules) {
573 // check all system modules in the image
574 builder.allModules();
575 }
576
577 if (options.classpath != null)
578 builder.addClassPath(options.classpath);
579
580 if (options.multiRelease != null)
581 builder.multiRelease(options.multiRelease);
582
583 // build the root set of archives to be analyzed
584 for (String s : inputArgs) {
585 Path p = Paths.get(s);
586 if (Files.exists(p)) {
587 builder.addRoot(p);
588 } else {
589 warning("warn.invalid.arg", s);
590 }
591 }
592
593 return builder.build();
594 }
595
638 }
639
640 /**
641 * Returns true if the command-line options are all valid;
642 * otherwise, returns false.
643 */
644 abstract boolean checkOptions();
645
646 /**
647 * Do analysis
648 */
649 abstract boolean run(JdepsConfiguration config) throws IOException;
650
651 /**
652 * Includes all modules on system module path and application module path
653 *
654 * When a named module is analyzed, it will analyze the dependences
655 * only. The method should be overridden when this command should
656 * analyze all modules instead.
657 */
658 boolean allModules() {
659 return false;
660 }
661
662 @Override
663 public String toString() {
664 return option.toString();
665 }
666 }
667
668
669 /**
670 * Analyze dependences
671 */
672 class AnalyzeDeps extends Command {
673 JdepsWriter writer;
674 AnalyzeDeps() {
675 this(CommandOption.ANALYZE_DEPS);
676 }
677
678 AnalyzeDeps(CommandOption option) {
679 super(option);
854 .collect(joining(" <- "));
855 }
856
857 /*
858 * Returns a comparator for sorting the inversed path, grouped by
859 * the first module name, then the shortest path and then sort by
860 * the module names of each path
861 */
862 private Comparator<Deque<Archive>> comparator() {
863 return Comparator.<Deque<Archive>, String>
864 comparing(deque -> deque.peekFirst().getName())
865 .thenComparingInt(Deque::size)
866 .thenComparing(this::toInversePath);
867 }
868
869 /*
870 * Returns true if --require is specified so that all modules are
871 * analyzed to find all modules that depend on the modules specified in the
872 * --require option directly and indirectly
873 */
874 public boolean allModules() {
875 return options.requires.size() > 0;
876 }
877 }
878
879
880 class GenModuleInfo extends Command {
881 final Path dir;
882 final boolean openModule;
883 GenModuleInfo(Path dir, boolean openModule) {
884 super(CommandOption.GENERATE_MODULE_INFO);
885 this.dir = dir;
886 this.openModule = openModule;
887 }
888
889 @Override
890 boolean checkOptions() {
891 if (options.classpath != null) {
892 reportError("err.invalid.options", "-classpath",
893 option);
894 return false;
895 }
958 reportError("err.invalid.options", inputArgs, "--check");
959 return false;
960 }
961 return true;
962 }
963
964 @Override
965 boolean run(JdepsConfiguration config) throws IOException {
966 if (!config.initialArchives().isEmpty()) {
967 String list = config.initialArchives().stream()
968 .map(Archive::getPathName).collect(joining(" "));
969 throw new UncheckedBadArgs(new BadArgs("err.invalid.options",
970 list, "--check"));
971 }
972 return new ModuleAnalyzer(config, log, modules).run();
973 }
974
975 /*
976 * Returns true to analyze all modules
977 */
978 public boolean allModules() {
979 return true;
980 }
981 }
982
983 class ListModuleDeps extends Command {
984 final boolean jdkinternals;
985 final boolean reduced;
986 final String separator;
987 ListModuleDeps(CommandOption option, boolean jdkinternals, boolean reduced) {
988 this(option, jdkinternals, reduced, System.getProperty("line.separator"));
989 }
990 ListModuleDeps(CommandOption option, boolean jdkinternals, boolean reduced, String sep) {
991 super(option);
992 this.jdkinternals = jdkinternals;
993 this.reduced = reduced;
994 this.separator = sep;
995 }
996
997 @Override
998 boolean checkOptions() {
999 if (options.showSummary || options.verbose != null) {
|
1 /*
2 * Copyright (c) 2012, 2017, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
523 reportError(e.getKey(), e.getArgs());
524 if (e.showUsage()) {
525 log.println(getMessage("main.usage.summary", PROGNAME));
526 }
527 return EXIT_CMDERR;
528 } catch (ResolutionException e) {
529 reportError("err.exception.message", e.getMessage());
530 return EXIT_CMDERR;
531 } catch (IOException e) {
532 e.printStackTrace();
533 return EXIT_CMDERR;
534 } catch (MultiReleaseException e) {
535 reportError(e.getKey(), e.getParams());
536 return EXIT_CMDERR; // could be EXIT_ABNORMAL sometimes
537 } finally {
538 log.flush();
539 }
540 }
541
542 boolean run() throws IOException {
543 try (JdepsConfiguration config = buildConfig()) {
544 if (!options.nowarning) {
545 // detect split packages
546 config.splitPackages().entrySet()
547 .stream()
548 .sorted(Map.Entry.comparingByKey())
549 .forEach(e -> warning("warn.split.package",
550 e.getKey(),
551 e.getValue().stream().collect(joining(" "))));
552 }
553
554 // check if any module specified in --add-modules, --require, and -m is missing
555 options.addmods.stream()
556 .filter(mn -> !JdepsConfiguration.isToken(mn))
557 .forEach(mn -> config.findModule(mn).orElseThrow(() ->
558 new UncheckedBadArgs(new BadArgs("err.module.not.found", mn))));
559
560 return command.run(config);
561 }
562 }
563
564 private JdepsConfiguration buildConfig() throws IOException {
565 JdepsConfiguration.Builder builder =
566 new JdepsConfiguration.Builder(options.systemModulePath);
567
568 builder.upgradeModulePath(options.upgradeModulePath)
569 .appModulePath(options.modulePath)
570 .addmods(options.addmods)
571 .addmods(command.addModules());
572
573 if (options.classpath != null)
574 builder.addClassPath(options.classpath);
575
576 if (options.multiRelease != null)
577 builder.multiRelease(options.multiRelease);
578
579 // build the root set of archives to be analyzed
580 for (String s : inputArgs) {
581 Path p = Paths.get(s);
582 if (Files.exists(p)) {
583 builder.addRoot(p);
584 } else {
585 warning("warn.invalid.arg", s);
586 }
587 }
588
589 return builder.build();
590 }
591
634 }
635
636 /**
637 * Returns true if the command-line options are all valid;
638 * otherwise, returns false.
639 */
640 abstract boolean checkOptions();
641
642 /**
643 * Do analysis
644 */
645 abstract boolean run(JdepsConfiguration config) throws IOException;
646
647 /**
648 * Includes all modules on system module path and application module path
649 *
650 * When a named module is analyzed, it will analyze the dependences
651 * only. The method should be overridden when this command should
652 * analyze all modules instead.
653 */
654 Set<String> addModules() {
655 return Set.of();
656 }
657
658 @Override
659 public String toString() {
660 return option.toString();
661 }
662 }
663
664
665 /**
666 * Analyze dependences
667 */
668 class AnalyzeDeps extends Command {
669 JdepsWriter writer;
670 AnalyzeDeps() {
671 this(CommandOption.ANALYZE_DEPS);
672 }
673
674 AnalyzeDeps(CommandOption option) {
675 super(option);
850 .collect(joining(" <- "));
851 }
852
853 /*
854 * Returns a comparator for sorting the inversed path, grouped by
855 * the first module name, then the shortest path and then sort by
856 * the module names of each path
857 */
858 private Comparator<Deque<Archive>> comparator() {
859 return Comparator.<Deque<Archive>, String>
860 comparing(deque -> deque.peekFirst().getName())
861 .thenComparingInt(Deque::size)
862 .thenComparing(this::toInversePath);
863 }
864
865 /*
866 * Returns true if --require is specified so that all modules are
867 * analyzed to find all modules that depend on the modules specified in the
868 * --require option directly and indirectly
869 */
870 Set<String> addModules() {
871 return options.requires.size() > 0 ? Set.of("ALL-SYSTEM") : Set.of();
872 }
873 }
874
875
876 class GenModuleInfo extends Command {
877 final Path dir;
878 final boolean openModule;
879 GenModuleInfo(Path dir, boolean openModule) {
880 super(CommandOption.GENERATE_MODULE_INFO);
881 this.dir = dir;
882 this.openModule = openModule;
883 }
884
885 @Override
886 boolean checkOptions() {
887 if (options.classpath != null) {
888 reportError("err.invalid.options", "-classpath",
889 option);
890 return false;
891 }
954 reportError("err.invalid.options", inputArgs, "--check");
955 return false;
956 }
957 return true;
958 }
959
960 @Override
961 boolean run(JdepsConfiguration config) throws IOException {
962 if (!config.initialArchives().isEmpty()) {
963 String list = config.initialArchives().stream()
964 .map(Archive::getPathName).collect(joining(" "));
965 throw new UncheckedBadArgs(new BadArgs("err.invalid.options",
966 list, "--check"));
967 }
968 return new ModuleAnalyzer(config, log, modules).run();
969 }
970
971 /*
972 * Returns true to analyze all modules
973 */
974 Set<String> addModules() {
975 return Set.of("ALL-SYSTEM", "ALL-MODULE-PATH");
976 }
977 }
978
979 class ListModuleDeps extends Command {
980 final boolean jdkinternals;
981 final boolean reduced;
982 final String separator;
983 ListModuleDeps(CommandOption option, boolean jdkinternals, boolean reduced) {
984 this(option, jdkinternals, reduced, System.getProperty("line.separator"));
985 }
986 ListModuleDeps(CommandOption option, boolean jdkinternals, boolean reduced, String sep) {
987 super(option);
988 this.jdkinternals = jdkinternals;
989 this.reduced = reduced;
990 this.separator = sep;
991 }
992
993 @Override
994 boolean checkOptions() {
995 if (options.showSummary || options.verbose != null) {
|