< prev index next >

src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java

Print this page




 340                 }
 341                 task.command = task.listModuleDeps(CommandOption.LIST_DEPS);
 342             }
 343         },
 344         new Option(false, CommandOption.LIST_REDUCED_DEPS) {
 345             void process(JdepsTask task, String opt, String arg) throws BadArgs {
 346                 if (task.command != null) {
 347                     throw new BadArgs("err.command.set", task.command, opt);
 348                 }
 349                 task.command = task.listModuleDeps(CommandOption.LIST_REDUCED_DEPS);
 350             }
 351         },
 352         new Option(false, CommandOption.PRINT_MODULE_DEPS) {
 353             void process(JdepsTask task, String opt, String arg) throws BadArgs {
 354                 if (task.command != null) {
 355                     throw new BadArgs("err.command.set", task.command, opt);
 356                 }
 357                 task.command = task.listModuleDeps(CommandOption.PRINT_MODULE_DEPS);
 358             }
 359         },





 360 
 361         // ---- Target filtering options ----
 362         new Option(true, "-p", "-package", "--package") {
 363             void process(JdepsTask task, String opt, String arg) {
 364                 task.options.packageNames.add(arg);
 365             }
 366         },
 367         new Option(true, "-e", "-regex", "--regex") {
 368             void process(JdepsTask task, String opt, String arg) {
 369                 task.options.regex = Pattern.compile(arg);
 370             }
 371         },
 372         new Option(true, "--require") {
 373             void process(JdepsTask task, String opt, String arg) {
 374                 task.options.requires.add(arg);
 375                 task.options.addmods.add(arg);
 376             }
 377         },
 378         new Option(true, "-f", "-filter") {
 379             void process(JdepsTask task, String opt, String arg) {


 384                           "-filter:archive", "-filter:module",
 385                           "-filter:none") {
 386             void process(JdepsTask task, String opt, String arg) {
 387                 switch (opt) {
 388                     case "-filter:package":
 389                         task.options.filterSamePackage = true;
 390                         task.options.filterSameArchive = false;
 391                         break;
 392                     case "-filter:archive":
 393                     case "-filter:module":
 394                         task.options.filterSameArchive = true;
 395                         task.options.filterSamePackage = false;
 396                         break;
 397                     case "-filter:none":
 398                         task.options.filterSameArchive = false;
 399                         task.options.filterSamePackage = false;
 400                         break;
 401                 }
 402             }
 403         },





 404 
 405         // ---- Source filtering options ----
 406         new Option(true, "-include") {
 407             void process(JdepsTask task, String opt, String arg) throws BadArgs {
 408                 task.options.includePattern = Pattern.compile(arg);
 409             }
 410         },
 411 
 412         new Option(false, "-P", "-profile") {
 413             void process(JdepsTask task, String opt, String arg) throws BadArgs {
 414                 task.options.showProfile = true;
 415             }
 416         },
 417 
 418         new Option(false, "-R", "-recursive") {
 419             void process(JdepsTask task, String opt, String arg) {
 420                 task.options.depth = 0;
 421                 // turn off filtering
 422                 task.options.filterSameArchive = false;
 423                 task.options.filterSamePackage = false;


 594     private AnalyzeDeps analyzeDeps() throws BadArgs {
 595         return options.inverse ? new InverseAnalyzeDeps()
 596                                : new AnalyzeDeps();
 597     }
 598 
 599     private GenDotFile genDotFile(Path dir) throws BadArgs {
 600         if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) {
 601             throw new BadArgs("err.invalid.path", dir.toString());
 602         }
 603         return new GenDotFile(dir);
 604     }
 605 
 606     private GenModuleInfo genModuleInfo(Path dir, boolean openModule) throws BadArgs {
 607         if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) {
 608             throw new BadArgs("err.invalid.path", dir.toString());
 609         }
 610         return new GenModuleInfo(dir, openModule);
 611     }
 612 
 613     private ListModuleDeps listModuleDeps(CommandOption option) throws BadArgs {





 614         switch (option) {
 615             case LIST_DEPS:
 616                 return new ListModuleDeps(option, true, false);
 617             case LIST_REDUCED_DEPS:
 618                 return new ListModuleDeps(option, true, true);
 619             case PRINT_MODULE_DEPS:
 620                 return new ListModuleDeps(option, false, true, ",");
 621             default:
 622                 throw new IllegalArgumentException(option.toString());
 623         }
 624     }
 625 
 626     private CheckModuleDeps checkModuleDeps(Set<String> mods) throws BadArgs {
 627         return new CheckModuleDeps(mods);
 628     }
 629 
 630     abstract class Command {
 631         final CommandOption option;
 632         protected Command(CommandOption option) {
 633             this.option = option;


 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);
 676         }
 677 
 678         @Override
 679         boolean checkOptions() {
 680             if (options.findJDKInternals) {
 681                 // cannot set any filter, -verbose and -summary option
 682                 if (options.showSummary || options.verbose != null) {
 683                     reportError("err.invalid.options", "-summary or -verbose",
 684                                 "-jdkinternals");
 685                     return false;
 686                 }
 687                 if (options.hasFilter()) {
 688                     reportError("err.invalid.options", "--package, --regex, --require",
 689                                 "-jdkinternals");
 690                     return false;
 691                 }
 692             }
 693             if (options.showSummary) {
 694                 // -summary cannot use with -verbose option
 695                 if (options.verbose != null) {
 696                     reportError("err.invalid.options", "-v, -verbose", "-s, -summary");
 697                     return false;
 698                 }
 699             }
 700 
 701             if (!inputArgs.isEmpty() && !options.rootModules.isEmpty()) {
 702                 reportError("err.invalid.arg.for.option", "-m");
 703             }
 704             if (inputArgs.isEmpty() && !options.hasSourcePath()) {
 705                 showHelp();
 706                 return false;
 707             }
 708             return true;
 709         }
 710 
 711         /*
 712          * Default is to show package-level dependencies
 713          */
 714         Type getAnalyzerType() {
 715             if (options.showSummary)
 716                 return Type.SUMMARY;
 717 
 718             if (options.findJDKInternals)
 719                 return Type.CLASS;
 720 
 721             // default to package-level verbose
 722            return options.verbose != null ? options.verbose : PACKAGE;
 723         }
 724 
 725         @Override
 726         boolean run(JdepsConfiguration config) throws IOException {
 727             Type type = getAnalyzerType();
 728             // default to package-level verbose
 729             JdepsWriter writer = new SimpleWriter(log,
 730                                                   type,
 731                                                   options.showProfile,
 732                                                   options.showModule);
 733 
 734             return run(config, writer, type);
 735         }
 736 
 737         boolean run(JdepsConfiguration config, JdepsWriter writer, Type type)
 738             throws IOException


 908                              .filter(cn -> toPackageName(cn).isEmpty())
 909                              .findFirst();
 910 
 911                     if (classInUnnamedPackage.isPresent()) {
 912                         if (classInUnnamedPackage.get().equals("module-info.class")) {
 913                             reportError("err.genmoduleinfo.not.jarfile", arg);
 914                         } else {
 915                             reportError("err.genmoduleinfo.unnamed.package", arg);
 916                         }
 917                         return false;
 918                     }
 919                 }
 920             }
 921 
 922             ModuleInfoBuilder builder
 923                  = new ModuleInfoBuilder(config, inputArgs, dir, openModule);
 924             boolean ok = builder.run();
 925 
 926             if (!ok && !options.nowarning) {
 927                 reportError("err.missing.dependences");
 928                 builder.visitMissingDeps(
 929                         (origin, originArchive, target, targetArchive) -> {
 930                             if (builder.notFound(targetArchive))
 931                                 log.format("   %-50s -> %-50s %s%n",
 932                                     origin, target, targetArchive.getName());
 933                         });
 934             }
 935             return ok;
 936         }
 937 
 938         private String toPackageName(String name) {
 939             int i = name.lastIndexOf('/');
 940             return i > 0 ? name.replace('/', '.').substring(0, i) : "";
 941         }
 942     }
 943 
 944     class CheckModuleDeps extends Command {
 945         final Set<String> modules;
 946         CheckModuleDeps(Set<String> mods) {
 947             super(CommandOption.CHECK_MODULES);
 948             this.modules = mods;
 949         }
 950 
 951         @Override
 952         boolean checkOptions() {
 953             if (!inputArgs.isEmpty()) {


 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) {
 996                 reportError("err.invalid.options", "-summary or -verbose",
 997                             option);
 998                 return false;
 999             }
1000             if (options.findJDKInternals) {
1001                 reportError("err.invalid.options", "-jdkinternals",
1002                             option);



1003                 return false;
1004             }
1005 
1006             if (!inputArgs.isEmpty() && !options.rootModules.isEmpty()) {
1007                 reportError("err.invalid.arg.for.option", "-m");
1008             }
1009             if (inputArgs.isEmpty() && !options.hasSourcePath()) {
1010                 showHelp();
1011                 return false;
1012             }
1013             return true;
1014         }
1015 
1016         @Override
1017         boolean run(JdepsConfiguration config) throws IOException {
1018             return new ModuleExportsAnalyzer(config,
1019                                              dependencyFilter(config),
1020                                              jdkinternals,
1021                                              reduced,
1022                                              log,
1023                                              separator).run();







1024         }
1025     }
1026 
1027 
1028     class GenDotFile extends AnalyzeDeps {
1029         final Path dotOutputDir;
1030         GenDotFile(Path dotOutputDir) {
1031             super(CommandOption.GENERATE_DOT_FILE);
1032 
1033             this.dotOutputDir = dotOutputDir;
1034         }
1035 
1036         @Override
1037         boolean run(JdepsConfiguration config) throws IOException {
1038             if ((options.showSummary || options.verbose == MODULE) &&
1039                 !options.addmods.isEmpty() && inputArgs.isEmpty()) {
1040                 // generate dot graph from the resolved graph from module
1041                 // resolution.  No class dependency analysis is performed.
1042                 return new ModuleDotGraph(config, options.apiOnly)
1043                         .genDotFiles(dotOutputDir);
1044             }
1045 
1046             Type type = getAnalyzerType();
1047             JdepsWriter writer = new DotFileWriter(dotOutputDir,
1048                                                    type,
1049                                                    options.showProfile,
1050                                                    options.showModule,
1051                                                    options.showLabel);
1052             return run(config, writer, type);
1053         }
1054     }
1055 












1056     /**
1057      * Returns a filter used during dependency analysis
1058      */
1059     private JdepsFilter dependencyFilter(JdepsConfiguration config) {
1060         // Filter specified by -filter, -package, -regex, and --require options
1061         JdepsFilter.Builder builder = new JdepsFilter.Builder();
1062 
1063         // source filters
1064         builder.includePattern(options.includePattern);
1065 
1066         // target filters
1067         builder.filter(options.filterSamePackage, options.filterSameArchive);
1068         builder.findJDKInternals(options.findJDKInternals);

1069 
1070         // --require
1071         if (!options.requires.isEmpty()) {
1072             options.requires.stream()
1073                 .forEach(mn -> {
1074                     Module m = config.findModule(mn).get();
1075                     builder.requires(mn, m.packages());
1076                 });
1077         }
1078         // -regex
1079         if (options.regex != null)
1080             builder.regex(options.regex);
1081         // -package
1082         if (!options.packageNames.isEmpty())
1083             builder.packages(options.packageNames);
1084         // -filter
1085         if (options.filterRegex != null)
1086             builder.filter(options.filterRegex);
1087 
1088         return builder.build();


1141 
1142     private void showHelp() {
1143         log.println(getMessage("main.usage", PROGNAME));
1144         for (Option o : recognizedOptions) {
1145             String name = o.aliases[0].substring(1); // there must always be at least one name
1146             name = name.charAt(0) == '-' ? name.substring(1) : name;
1147             if (o.isHidden() || name.startsWith("filter:")) {
1148                 continue;
1149             }
1150             log.println(getMessage("main.opt." + name));
1151         }
1152     }
1153 
1154     private void showVersion(boolean full) {
1155         log.println(version(full ? "full" : "release"));
1156     }
1157 
1158     private String version(String key) {
1159         // key=version:  mm.nn.oo[-milestone]
1160         // key=full:     mm.mm.oo[-milestone]-build
1161         if (ResourceBundleHelper.versionRB == null) {
1162             return System.getProperty("java.version");
1163         }
1164         try {
1165             return ResourceBundleHelper.versionRB.getString(key);
1166         } catch (MissingResourceException e) {
1167             return getMessage("version.unknown", System.getProperty("java.version"));
1168         }
1169     }
1170 
1171     static String getMessage(String key, Object... args) {
1172         try {
1173             return MessageFormat.format(ResourceBundleHelper.bundle.getString(key), args);
1174         } catch (MissingResourceException e) {
1175             throw new InternalError("Missing message: " + key);
1176         }
1177     }
1178 
1179     private static class Options {
1180         boolean help;
1181         boolean version;
1182         boolean fullVersion;
1183         boolean showProfile;
1184         boolean showModule = true;
1185         boolean showSummary;
1186         boolean apiOnly;
1187         boolean showLabel;
1188         boolean findJDKInternals;


1189         boolean nowarning = false;
1190         Analyzer.Type verbose;
1191         // default filter references from same package
1192         boolean filterSamePackage = true;
1193         boolean filterSameArchive = false;
1194         Pattern filterRegex;
1195         String classpath;
1196         int depth = 1;
1197         Set<String> requires = new HashSet<>();
1198         Set<String> packageNames = new HashSet<>();
1199         Pattern regex;             // apply to the dependences
1200         Pattern includePattern;
1201         boolean inverse = false;
1202         boolean compileTimeView = false;
1203         String systemModulePath = System.getProperty("java.home");
1204         String upgradeModulePath;
1205         String modulePath;
1206         Set<String> rootModules = new HashSet<>();
1207         Set<String> addmods = new HashSet<>();
1208         Runtime.Version multiRelease;
1209 
1210         boolean hasSourcePath() {
1211             return !addmods.isEmpty() || includePattern != null;
1212         }
1213 
1214         boolean hasFilter() {
1215             return numFilters() > 0;
1216         }
1217 
1218         int numFilters() {
1219             int count = 0;
1220             if (requires.size() > 0) count++;
1221             if (regex != null) count++;
1222             if (packageNames.size() > 0) count++;
1223             return count;
1224         }
1225     }
1226 
1227     private static class ResourceBundleHelper {

1228         static final ResourceBundle versionRB;
1229         static final ResourceBundle bundle;
1230         static final ResourceBundle jdkinternals;
1231 
1232         static {
1233             Locale locale = Locale.getDefault();
1234             try {
1235                 bundle = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdeps", locale);
1236             } catch (MissingResourceException e) {
1237                 throw new InternalError("Cannot find jdeps resource bundle for locale " + locale);
1238             }
1239             try {
1240                 versionRB = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.version");
1241             } catch (MissingResourceException e) {
1242                 throw new InternalError("version.resource.missing");
1243             }
1244             try {
1245                 jdkinternals = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdkinternals");
1246             } catch (MissingResourceException e) {
1247                 throw new InternalError("Cannot find jdkinternals resource bundle");
1248             }
1249         }















1250     }
1251 
1252     /**
1253      * Returns the recommended replacement API for the given classname;
1254      * or return null if replacement API is not known.
1255      */
1256     private Optional<String> replacementFor(String cn) {
1257         String name = cn;
1258         String value = null;
1259         while (value == null && name != null) {
1260             try {
1261                 value = ResourceBundleHelper.jdkinternals.getString(name);
1262             } catch (MissingResourceException e) {
1263                 // go up one subpackage level
1264                 int i = name.lastIndexOf('.');
1265                 name = i > 0 ? name.substring(0, i) : null;
1266             }
1267         }
1268         return Optional.ofNullable(value);
1269     }
1270 }


 340                 }
 341                 task.command = task.listModuleDeps(CommandOption.LIST_DEPS);
 342             }
 343         },
 344         new Option(false, CommandOption.LIST_REDUCED_DEPS) {
 345             void process(JdepsTask task, String opt, String arg) throws BadArgs {
 346                 if (task.command != null) {
 347                     throw new BadArgs("err.command.set", task.command, opt);
 348                 }
 349                 task.command = task.listModuleDeps(CommandOption.LIST_REDUCED_DEPS);
 350             }
 351         },
 352         new Option(false, CommandOption.PRINT_MODULE_DEPS) {
 353             void process(JdepsTask task, String opt, String arg) throws BadArgs {
 354                 if (task.command != null) {
 355                     throw new BadArgs("err.command.set", task.command, opt);
 356                 }
 357                 task.command = task.listModuleDeps(CommandOption.PRINT_MODULE_DEPS);
 358             }
 359         },
 360         new Option(false, "--ignore-missing-deps") {
 361             void process(JdepsTask task, String opt, String arg) {
 362                 task.options.ignoreMissingDeps = true;
 363             }
 364         },
 365 
 366         // ---- Target filtering options ----
 367         new Option(true, "-p", "-package", "--package") {
 368             void process(JdepsTask task, String opt, String arg) {
 369                 task.options.packageNames.add(arg);
 370             }
 371         },
 372         new Option(true, "-e", "-regex", "--regex") {
 373             void process(JdepsTask task, String opt, String arg) {
 374                 task.options.regex = Pattern.compile(arg);
 375             }
 376         },
 377         new Option(true, "--require") {
 378             void process(JdepsTask task, String opt, String arg) {
 379                 task.options.requires.add(arg);
 380                 task.options.addmods.add(arg);
 381             }
 382         },
 383         new Option(true, "-f", "-filter") {
 384             void process(JdepsTask task, String opt, String arg) {


 389                           "-filter:archive", "-filter:module",
 390                           "-filter:none") {
 391             void process(JdepsTask task, String opt, String arg) {
 392                 switch (opt) {
 393                     case "-filter:package":
 394                         task.options.filterSamePackage = true;
 395                         task.options.filterSameArchive = false;
 396                         break;
 397                     case "-filter:archive":
 398                     case "-filter:module":
 399                         task.options.filterSameArchive = true;
 400                         task.options.filterSamePackage = false;
 401                         break;
 402                     case "-filter:none":
 403                         task.options.filterSameArchive = false;
 404                         task.options.filterSamePackage = false;
 405                         break;
 406                 }
 407             }
 408         },
 409         new Option(false, "--missing-deps") {
 410             void process(JdepsTask task, String opt, String arg) {
 411                 task.options.findMissingDeps = true;
 412             }
 413         },
 414 
 415         // ---- Source filtering options ----
 416         new Option(true, "-include") {
 417             void process(JdepsTask task, String opt, String arg) throws BadArgs {
 418                 task.options.includePattern = Pattern.compile(arg);
 419             }
 420         },
 421 
 422         new Option(false, "-P", "-profile") {
 423             void process(JdepsTask task, String opt, String arg) throws BadArgs {
 424                 task.options.showProfile = true;
 425             }
 426         },
 427 
 428         new Option(false, "-R", "-recursive") {
 429             void process(JdepsTask task, String opt, String arg) {
 430                 task.options.depth = 0;
 431                 // turn off filtering
 432                 task.options.filterSameArchive = false;
 433                 task.options.filterSamePackage = false;


 604     private AnalyzeDeps analyzeDeps() throws BadArgs {
 605         return options.inverse ? new InverseAnalyzeDeps()
 606                                : new AnalyzeDeps();
 607     }
 608 
 609     private GenDotFile genDotFile(Path dir) throws BadArgs {
 610         if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) {
 611             throw new BadArgs("err.invalid.path", dir.toString());
 612         }
 613         return new GenDotFile(dir);
 614     }
 615 
 616     private GenModuleInfo genModuleInfo(Path dir, boolean openModule) throws BadArgs {
 617         if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) {
 618             throw new BadArgs("err.invalid.path", dir.toString());
 619         }
 620         return new GenModuleInfo(dir, openModule);
 621     }
 622 
 623     private ListModuleDeps listModuleDeps(CommandOption option) throws BadArgs {
 624         // no need to record the dependences on the same archive or same package
 625         options.filterSameArchive = true;
 626         options.filterSamePackage = true;
 627         // do transitive dependence analysis
 628         options.depth = 0;
 629         switch (option) {
 630             case LIST_DEPS:
 631                 return new ListModuleDeps(option, true, false);
 632             case LIST_REDUCED_DEPS:
 633                 return new ListModuleDeps(option, true, true);
 634             case PRINT_MODULE_DEPS:
 635                 return new ListModuleDeps(option, false, true, ",");
 636             default:
 637                 throw new IllegalArgumentException(option.toString());
 638         }
 639     }
 640 
 641     private CheckModuleDeps checkModuleDeps(Set<String> mods) throws BadArgs {
 642         return new CheckModuleDeps(mods);
 643     }
 644 
 645     abstract class Command {
 646         final CommandOption option;
 647         protected Command(CommandOption option) {
 648             this.option = option;


 675             return option.toString();
 676         }
 677     }
 678 
 679 
 680     /**
 681      * Analyze dependences
 682      */
 683     class AnalyzeDeps extends Command {
 684         JdepsWriter writer;
 685         AnalyzeDeps() {
 686             this(CommandOption.ANALYZE_DEPS);
 687         }
 688 
 689         AnalyzeDeps(CommandOption option) {
 690             super(option);
 691         }
 692 
 693         @Override
 694         boolean checkOptions() {
 695             if (options.findJDKInternals || options.findMissingDeps) {
 696                 // cannot set any filter, -verbose and -summary option
 697                 if (options.showSummary || options.verbose != null) {
 698                     reportError("err.invalid.options", "-summary or -verbose",
 699                         options.findJDKInternals ? "-jdkinternals" : "--missing-deps");
 700                     return false;
 701                 }
 702                 if (options.hasFilter()) {
 703                     reportError("err.invalid.options", "--package, --regex, --require",
 704                         options.findJDKInternals ? "-jdkinternals" : "--missing-deps");
 705                     return false;
 706                 }
 707             }
 708             if (options.showSummary) {
 709                 // -summary cannot use with -verbose option
 710                 if (options.verbose != null) {
 711                     reportError("err.invalid.options", "-v, -verbose", "-s, -summary");
 712                     return false;
 713                 }
 714             }
 715 
 716             if (!inputArgs.isEmpty() && !options.rootModules.isEmpty()) {
 717                 reportError("err.invalid.arg.for.option", "-m");
 718             }
 719             if (inputArgs.isEmpty() && !options.hasSourcePath()) {
 720                 showHelp();
 721                 return false;
 722             }
 723             return true;
 724         }
 725 
 726         /*
 727          * Default is to show package-level dependencies
 728          */
 729         Type getAnalyzerType() {
 730             if (options.showSummary)
 731                 return Type.SUMMARY;
 732 
 733             if (options.findJDKInternals || options.findMissingDeps)
 734                 return Type.CLASS;
 735 
 736             // default to package-level verbose
 737            return options.verbose != null ? options.verbose : PACKAGE;
 738         }
 739 
 740         @Override
 741         boolean run(JdepsConfiguration config) throws IOException {
 742             Type type = getAnalyzerType();
 743             // default to package-level verbose
 744             JdepsWriter writer = new SimpleWriter(log,
 745                                                   type,
 746                                                   options.showProfile,
 747                                                   options.showModule);
 748 
 749             return run(config, writer, type);
 750         }
 751 
 752         boolean run(JdepsConfiguration config, JdepsWriter writer, Type type)
 753             throws IOException


 923                              .filter(cn -> toPackageName(cn).isEmpty())
 924                              .findFirst();
 925 
 926                     if (classInUnnamedPackage.isPresent()) {
 927                         if (classInUnnamedPackage.get().equals("module-info.class")) {
 928                             reportError("err.genmoduleinfo.not.jarfile", arg);
 929                         } else {
 930                             reportError("err.genmoduleinfo.unnamed.package", arg);
 931                         }
 932                         return false;
 933                     }
 934                 }
 935             }
 936 
 937             ModuleInfoBuilder builder
 938                  = new ModuleInfoBuilder(config, inputArgs, dir, openModule);
 939             boolean ok = builder.run();
 940 
 941             if (!ok && !options.nowarning) {
 942                 reportError("err.missing.dependences");
 943                 builder.visitMissingDeps(new SimpleDepVisitor());





 944             }
 945             return ok;
 946         }
 947 
 948         private String toPackageName(String name) {
 949             int i = name.lastIndexOf('/');
 950             return i > 0 ? name.replace('/', '.').substring(0, i) : "";
 951         }
 952     }
 953 
 954     class CheckModuleDeps extends Command {
 955         final Set<String> modules;
 956         CheckModuleDeps(Set<String> mods) {
 957             super(CommandOption.CHECK_MODULES);
 958             this.modules = mods;
 959         }
 960 
 961         @Override
 962         boolean checkOptions() {
 963             if (!inputArgs.isEmpty()) {


 986         }
 987     }
 988 
 989     class ListModuleDeps extends Command {
 990         final boolean jdkinternals;
 991         final boolean reduced;
 992         final String separator;
 993         ListModuleDeps(CommandOption option, boolean jdkinternals, boolean reduced) {
 994             this(option, jdkinternals, reduced, System.getProperty("line.separator"));
 995         }
 996         ListModuleDeps(CommandOption option, boolean jdkinternals, boolean reduced, String sep) {
 997             super(option);
 998             this.jdkinternals = jdkinternals;
 999             this.reduced = reduced;
1000             this.separator = sep;
1001         }
1002 
1003         @Override
1004         boolean checkOptions() {
1005             if (options.showSummary || options.verbose != null) {
1006                 reportError("err.invalid.options", "-summary or -verbose", option);

1007                 return false;
1008             }
1009             if (options.findJDKInternals) {
1010                 reportError("err.invalid.options", "-jdkinternals", option);
1011                 return false;
1012             }
1013             if (options.findMissingDeps) {
1014                 reportError("err.invalid.options", "--missing-deps", option);
1015                 return false;
1016             }
1017 
1018             if (!inputArgs.isEmpty() && !options.rootModules.isEmpty()) {
1019                 reportError("err.invalid.arg.for.option", "-m");
1020             }
1021             if (inputArgs.isEmpty() && !options.hasSourcePath()) {
1022                 showHelp();
1023                 return false;
1024             }
1025             return true;
1026         }
1027 
1028         @Override
1029         boolean run(JdepsConfiguration config) throws IOException {
1030             ModuleExportsAnalyzer analyzer = new ModuleExportsAnalyzer(config,
1031                                                                        dependencyFilter(config),
1032                                                                        jdkinternals,
1033                                                                        reduced,
1034                                                                        log,
1035                                                                        separator);
1036             boolean ok = analyzer.run(options.depth, options.ignoreMissingDeps);
1037             if (!ok) {
1038                 reportError("err.cant.list.module.deps");
1039                 log.println();
1040                 analyzer.visitMissingDeps(new SimpleDepVisitor());
1041             }
1042             return ok;
1043         }
1044     }
1045 

1046     class GenDotFile extends AnalyzeDeps {
1047         final Path dotOutputDir;
1048         GenDotFile(Path dotOutputDir) {
1049             super(CommandOption.GENERATE_DOT_FILE);
1050 
1051             this.dotOutputDir = dotOutputDir;
1052         }
1053 
1054         @Override
1055         boolean run(JdepsConfiguration config) throws IOException {
1056             if ((options.showSummary || options.verbose == MODULE) &&
1057                 !options.addmods.isEmpty() && inputArgs.isEmpty()) {
1058                 // generate dot graph from the resolved graph from module
1059                 // resolution.  No class dependency analysis is performed.
1060                 return new ModuleDotGraph(config, options.apiOnly)
1061                         .genDotFiles(dotOutputDir);
1062             }
1063 
1064             Type type = getAnalyzerType();
1065             JdepsWriter writer = new DotFileWriter(dotOutputDir,
1066                                                    type,
1067                                                    options.showProfile,
1068                                                    options.showModule,
1069                                                    options.showLabel);
1070             return run(config, writer, type);
1071         }
1072     }
1073 
1074     class SimpleDepVisitor implements Analyzer.Visitor {
1075         private Archive source;
1076         @Override
1077         public void visitDependence(String origin, Archive originArchive, String target, Archive targetArchive) {
1078             if (source != originArchive) {
1079                 source = originArchive;
1080                 log.format("%s%n", originArchive);
1081             }
1082             log.format("   %-50s -> %-50s %s%n", origin, target, targetArchive.getName());
1083         }
1084     }
1085 
1086     /**
1087      * Returns a filter used during dependency analysis
1088      */
1089     private JdepsFilter dependencyFilter(JdepsConfiguration config) {
1090         // Filter specified by -filter, -package, -regex, and --require options
1091         JdepsFilter.Builder builder = new JdepsFilter.Builder();
1092 
1093         // source filters
1094         builder.includePattern(options.includePattern);
1095 
1096         // target filters
1097         builder.filter(options.filterSamePackage, options.filterSameArchive);
1098         builder.findJDKInternals(options.findJDKInternals);
1099         builder.findMissingDeps(options.findMissingDeps);
1100 
1101         // --require
1102         if (!options.requires.isEmpty()) {
1103             options.requires.stream()
1104                 .forEach(mn -> {
1105                     Module m = config.findModule(mn).get();
1106                     builder.requires(mn, m.packages());
1107                 });
1108         }
1109         // -regex
1110         if (options.regex != null)
1111             builder.regex(options.regex);
1112         // -package
1113         if (!options.packageNames.isEmpty())
1114             builder.packages(options.packageNames);
1115         // -filter
1116         if (options.filterRegex != null)
1117             builder.filter(options.filterRegex);
1118 
1119         return builder.build();


1172 
1173     private void showHelp() {
1174         log.println(getMessage("main.usage", PROGNAME));
1175         for (Option o : recognizedOptions) {
1176             String name = o.aliases[0].substring(1); // there must always be at least one name
1177             name = name.charAt(0) == '-' ? name.substring(1) : name;
1178             if (o.isHidden() || name.startsWith("filter:")) {
1179                 continue;
1180             }
1181             log.println(getMessage("main.opt." + name));
1182         }
1183     }
1184 
1185     private void showVersion(boolean full) {
1186         log.println(version(full ? "full" : "release"));
1187     }
1188 
1189     private String version(String key) {
1190         // key=version:  mm.nn.oo[-milestone]
1191         // key=full:     mm.mm.oo[-milestone]-build



1192         try {
1193             return ResourceBundleHelper.getVersion(key);
1194         } catch (MissingResourceException e) {
1195             return getMessage("version.unknown", System.getProperty("java.version"));
1196         }
1197     }
1198 
1199     static String getMessage(String key, Object... args) {
1200         try {
1201             return MessageFormat.format(ResourceBundleHelper.getMessage(key), args);
1202         } catch (MissingResourceException e) {
1203             throw new InternalError("Missing message: " + key);
1204         }
1205     }
1206 
1207     private static class Options {
1208         boolean help;
1209         boolean version;
1210         boolean fullVersion;
1211         boolean showProfile;
1212         boolean showModule = true;
1213         boolean showSummary;
1214         boolean apiOnly;
1215         boolean showLabel;
1216         boolean findJDKInternals;
1217         boolean findMissingDeps;
1218         boolean ignoreMissingDeps;
1219         boolean nowarning = false;
1220         Analyzer.Type verbose;
1221         // default filter references from same package
1222         boolean filterSamePackage = true;
1223         boolean filterSameArchive = false;
1224         Pattern filterRegex;
1225         String classpath;
1226         int depth = 1;
1227         Set<String> requires = new HashSet<>();
1228         Set<String> packageNames = new HashSet<>();
1229         Pattern regex;             // apply to the dependences
1230         Pattern includePattern;
1231         boolean inverse = false;
1232         boolean compileTimeView = false;
1233         String systemModulePath = System.getProperty("java.home");
1234         String upgradeModulePath;
1235         String modulePath;
1236         Set<String> rootModules = new HashSet<>();
1237         Set<String> addmods = new HashSet<>();
1238         Runtime.Version multiRelease;
1239 
1240         boolean hasSourcePath() {
1241             return !addmods.isEmpty() || includePattern != null;
1242         }
1243 
1244         boolean hasFilter() {
1245             return numFilters() > 0;
1246         }
1247 
1248         int numFilters() {
1249             int count = 0;
1250             if (requires.size() > 0) count++;
1251             if (regex != null) count++;
1252             if (packageNames.size() > 0) count++;
1253             return count;
1254         }
1255     }
1256 
1257     private static class ResourceBundleHelper {
1258         static final String LS = System.lineSeparator();
1259         static final ResourceBundle versionRB;
1260         static final ResourceBundle bundle;
1261         static final ResourceBundle jdkinternals;
1262 
1263         static {
1264             Locale locale = Locale.getDefault();
1265             try {
1266                 bundle = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdeps", locale);
1267             } catch (MissingResourceException e) {
1268                 throw new InternalError("Cannot find jdeps resource bundle for locale " + locale);
1269             }
1270             try {
1271                 versionRB = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.version");
1272             } catch (MissingResourceException e) {
1273                 throw new InternalError("version.resource.missing");
1274             }
1275             try {
1276                 jdkinternals = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdkinternals");
1277             } catch (MissingResourceException e) {
1278                 throw new InternalError("Cannot find jdkinternals resource bundle");
1279             }
1280         }
1281 
1282         static String getMessage(String key) {
1283             return bundle.getString(key).replace("\n", LS);
1284         }
1285 
1286         static String getVersion(String key) {
1287             if (ResourceBundleHelper.versionRB == null) {
1288                 return System.getProperty("java.version");
1289             }
1290             return versionRB.getString(key).replace("\n", LS);
1291         }
1292 
1293         static String getSuggestedReplacement(String key) {
1294             return ResourceBundleHelper.jdkinternals.getString(key).replace("\n", LS);
1295         }
1296     }
1297 
1298     /**
1299      * Returns the recommended replacement API for the given classname;
1300      * or return null if replacement API is not known.
1301      */
1302     private Optional<String> replacementFor(String cn) {
1303         String name = cn;
1304         String value = null;
1305         while (value == null && name != null) {
1306             try {
1307                 value = ResourceBundleHelper.getSuggestedReplacement(name);
1308             } catch (MissingResourceException e) {
1309                 // go up one subpackage level
1310                 int i = name.lastIndexOf('.');
1311                 name = i > 0 ? name.substring(0, i) : null;
1312             }
1313         }
1314         return Optional.ofNullable(value);
1315     }
1316 }
< prev index next >