src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java
changeset 52650 c16b6cc93272
parent 48543 7067fe4e054e
equal deleted inserted replaced
52649:e00cf18e2593 52650:c16b6cc93272
   355                     throw new BadArgs("err.command.set", task.command, opt);
   355                     throw new BadArgs("err.command.set", task.command, opt);
   356                 }
   356                 }
   357                 task.command = task.listModuleDeps(CommandOption.PRINT_MODULE_DEPS);
   357                 task.command = task.listModuleDeps(CommandOption.PRINT_MODULE_DEPS);
   358             }
   358             }
   359         },
   359         },
       
   360         new Option(false, "--ignore-missing-deps") {
       
   361             void process(JdepsTask task, String opt, String arg) {
       
   362                 task.options.ignoreMissingDeps = true;
       
   363             }
       
   364         },
   360 
   365 
   361         // ---- Target filtering options ----
   366         // ---- Target filtering options ----
   362         new Option(true, "-p", "-package", "--package") {
   367         new Option(true, "-p", "-package", "--package") {
   363             void process(JdepsTask task, String opt, String arg) {
   368             void process(JdepsTask task, String opt, String arg) {
   364                 task.options.packageNames.add(arg);
   369                 task.options.packageNames.add(arg);
   399                         task.options.filterSamePackage = false;
   404                         task.options.filterSamePackage = false;
   400                         break;
   405                         break;
   401                 }
   406                 }
   402             }
   407             }
   403         },
   408         },
       
   409         new Option(false, "--missing-deps") {
       
   410             void process(JdepsTask task, String opt, String arg) {
       
   411                 task.options.findMissingDeps = true;
       
   412             }
       
   413         },
   404 
   414 
   405         // ---- Source filtering options ----
   415         // ---- Source filtering options ----
   406         new Option(true, "-include") {
   416         new Option(true, "-include") {
   407             void process(JdepsTask task, String opt, String arg) throws BadArgs {
   417             void process(JdepsTask task, String opt, String arg) throws BadArgs {
   408                 task.options.includePattern = Pattern.compile(arg);
   418                 task.options.includePattern = Pattern.compile(arg);
   413             void process(JdepsTask task, String opt, String arg) throws BadArgs {
   423             void process(JdepsTask task, String opt, String arg) throws BadArgs {
   414                 task.options.showProfile = true;
   424                 task.options.showProfile = true;
   415             }
   425             }
   416         },
   426         },
   417 
   427 
   418         new Option(false, "-R", "-recursive") {
   428         new Option(false, "-R", "-recursive", "--recursive") {
   419             void process(JdepsTask task, String opt, String arg) {
   429             void process(JdepsTask task, String opt, String arg) throws BadArgs {
   420                 task.options.depth = 0;
   430                 task.options.recursive = Options.RECURSIVE;
   421                 // turn off filtering
   431                 // turn off filtering
   422                 task.options.filterSameArchive = false;
   432                 task.options.filterSameArchive = false;
   423                 task.options.filterSamePackage = false;
   433                 task.options.filterSamePackage = false;
   424             }
   434             }
   425         },
   435         },
   426 
   436         new Option(false, "--no-recursive") {
       
   437             void process(JdepsTask task, String opt, String arg) throws BadArgs {
       
   438                 task.options.recursive = Options.NO_RECURSIVE;
       
   439             }
       
   440         },
   427         new Option(false, "-I", "--inverse") {
   441         new Option(false, "-I", "--inverse") {
   428             void process(JdepsTask task, String opt, String arg) {
   442             void process(JdepsTask task, String opt, String arg) {
   429                 task.options.inverse = true;
   443                 task.options.inverse = true;
   430                 // equivalent to the inverse of compile-time view analysis
   444                 // equivalent to the inverse of compile-time view analysis
   431                 task.options.compileTimeView = true;
   445                 task.options.compileTimeView = true;
   435         },
   449         },
   436 
   450 
   437         new Option(false, "--compile-time") {
   451         new Option(false, "--compile-time") {
   438             void process(JdepsTask task, String opt, String arg) {
   452             void process(JdepsTask task, String opt, String arg) {
   439                 task.options.compileTimeView = true;
   453                 task.options.compileTimeView = true;
       
   454                 task.options.recursive = Options.RECURSIVE;
   440                 task.options.filterSamePackage = true;
   455                 task.options.filterSamePackage = true;
   441                 task.options.filterSameArchive = true;
   456                 task.options.filterSameArchive = true;
   442                 task.options.depth = 0;
       
   443             }
   457             }
   444         },
   458         },
   445 
   459 
   446         new HiddenOption(false, "-fullversion") {
   460         new HiddenOption(false, "-fullversion") {
   447             void process(JdepsTask task, String opt, String arg) {
   461             void process(JdepsTask task, String opt, String arg) {
   609         }
   623         }
   610         return new GenModuleInfo(dir, openModule);
   624         return new GenModuleInfo(dir, openModule);
   611     }
   625     }
   612 
   626 
   613     private ListModuleDeps listModuleDeps(CommandOption option) throws BadArgs {
   627     private ListModuleDeps listModuleDeps(CommandOption option) throws BadArgs {
       
   628         // do transitive dependence analysis unless --no-recursive is set
       
   629         if (options.recursive != Options.NO_RECURSIVE) {
       
   630             options.recursive = Options.RECURSIVE;
       
   631         }
       
   632         // no need to record the dependences on the same archive or same package
       
   633         options.filterSameArchive = true;
       
   634         options.filterSamePackage = true;
   614         switch (option) {
   635         switch (option) {
   615             case LIST_DEPS:
   636             case LIST_DEPS:
   616                 return new ListModuleDeps(option, true, false);
   637                 return new ListModuleDeps(option, true, false);
   617             case LIST_REDUCED_DEPS:
   638             case LIST_REDUCED_DEPS:
   618                 return new ListModuleDeps(option, true, true);
   639                 return new ListModuleDeps(option, true, true);
   675             super(option);
   696             super(option);
   676         }
   697         }
   677 
   698 
   678         @Override
   699         @Override
   679         boolean checkOptions() {
   700         boolean checkOptions() {
   680             if (options.findJDKInternals) {
   701             if (options.findJDKInternals || options.findMissingDeps) {
   681                 // cannot set any filter, -verbose and -summary option
   702                 // cannot set any filter, -verbose and -summary option
   682                 if (options.showSummary || options.verbose != null) {
   703                 if (options.showSummary || options.verbose != null) {
   683                     reportError("err.invalid.options", "-summary or -verbose",
   704                     reportError("err.invalid.options", "-summary or -verbose",
   684                                 "-jdkinternals");
   705                         options.findJDKInternals ? "-jdkinternals" : "--missing-deps");
   685                     return false;
   706                     return false;
   686                 }
   707                 }
   687                 if (options.hasFilter()) {
   708                 if (options.hasFilter()) {
   688                     reportError("err.invalid.options", "--package, --regex, --require",
   709                     reportError("err.invalid.options", "--package, --regex, --require",
   689                                 "-jdkinternals");
   710                         options.findJDKInternals ? "-jdkinternals" : "--missing-deps");
   690                     return false;
   711                     return false;
   691                 }
   712                 }
   692             }
   713             }
   693             if (options.showSummary) {
   714             if (options.showSummary) {
   694                 // -summary cannot use with -verbose option
   715                 // -summary cannot use with -verbose option
   713          */
   734          */
   714         Type getAnalyzerType() {
   735         Type getAnalyzerType() {
   715             if (options.showSummary)
   736             if (options.showSummary)
   716                 return Type.SUMMARY;
   737                 return Type.SUMMARY;
   717 
   738 
   718             if (options.findJDKInternals)
   739             if (options.findJDKInternals || options.findMissingDeps)
   719                 return Type.CLASS;
   740                 return Type.CLASS;
   720 
   741 
   721             // default to package-level verbose
   742             // default to package-level verbose
   722            return options.verbose != null ? options.verbose : PACKAGE;
   743            return options.verbose != null ? options.verbose : PACKAGE;
   723         }
   744         }
   742                                                      dependencyFilter(config),
   763                                                      dependencyFilter(config),
   743                                                      writer,
   764                                                      writer,
   744                                                      type,
   765                                                      type,
   745                                                      options.apiOnly);
   766                                                      options.apiOnly);
   746 
   767 
   747             boolean ok = analyzer.run(options.compileTimeView, options.depth);
   768             boolean ok = analyzer.run(options.compileTimeView, options.depth());
   748 
   769 
   749             // print skipped entries, if any
   770             // print skipped entries, if any
   750             if (!options.nowarning) {
   771             if (!options.nowarning) {
   751                 analyzer.archives()
   772                 analyzer.archives()
   752                     .forEach(archive -> archive.reader()
   773                     .forEach(archive -> archive.reader()
   795         InverseAnalyzeDeps() {
   816         InverseAnalyzeDeps() {
   796         }
   817         }
   797 
   818 
   798         @Override
   819         @Override
   799         boolean checkOptions() {
   820         boolean checkOptions() {
   800             if (options.depth != 1) {
   821             if (options.recursive != -1 || options.depth != -1) {
   801                 reportError("err.invalid.options", "-R", "--inverse");
   822                 reportError("err.invalid.options", "--recursive and --no-recursive", "--inverse");
   802                 return false;
   823                 return false;
   803             }
   824             }
   804 
   825 
   805             if (options.numFilters() == 0) {
   826             if (options.numFilters() == 0) {
   806                 reportError("err.filter.not.specified");
   827                 reportError("err.filter.not.specified");
   923                  = new ModuleInfoBuilder(config, inputArgs, dir, openModule);
   944                  = new ModuleInfoBuilder(config, inputArgs, dir, openModule);
   924             boolean ok = builder.run();
   945             boolean ok = builder.run();
   925 
   946 
   926             if (!ok && !options.nowarning) {
   947             if (!ok && !options.nowarning) {
   927                 reportError("err.missing.dependences");
   948                 reportError("err.missing.dependences");
   928                 builder.visitMissingDeps(
   949                 builder.visitMissingDeps(new SimpleDepVisitor());
   929                         (origin, originArchive, target, targetArchive) -> {
       
   930                             if (builder.notFound(targetArchive))
       
   931                                 log.format("   %-50s -> %-50s %s%n",
       
   932                                     origin, target, targetArchive.getName());
       
   933                         });
       
   934             }
   950             }
   935             return ok;
   951             return ok;
   936         }
   952         }
   937 
   953 
   938         private String toPackageName(String name) {
   954         private String toPackageName(String name) {
   991         }
  1007         }
   992 
  1008 
   993         @Override
  1009         @Override
   994         boolean checkOptions() {
  1010         boolean checkOptions() {
   995             if (options.showSummary || options.verbose != null) {
  1011             if (options.showSummary || options.verbose != null) {
   996                 reportError("err.invalid.options", "-summary or -verbose",
  1012                 reportError("err.invalid.options", "-summary or -verbose", option);
   997                             option);
       
   998                 return false;
  1013                 return false;
   999             }
  1014             }
  1000             if (options.findJDKInternals) {
  1015             if (options.findJDKInternals) {
  1001                 reportError("err.invalid.options", "-jdkinternals",
  1016                 reportError("err.invalid.options", "-jdkinternals", option);
  1002                             option);
  1017                 return false;
       
  1018             }
       
  1019             if (options.findMissingDeps) {
       
  1020                 reportError("err.invalid.options", "--missing-deps", option);
  1003                 return false;
  1021                 return false;
  1004             }
  1022             }
  1005 
  1023 
  1006             if (!inputArgs.isEmpty() && !options.rootModules.isEmpty()) {
  1024             if (!inputArgs.isEmpty() && !options.rootModules.isEmpty()) {
  1007                 reportError("err.invalid.arg.for.option", "-m");
  1025                 reportError("err.invalid.arg.for.option", "-m");
  1013             return true;
  1031             return true;
  1014         }
  1032         }
  1015 
  1033 
  1016         @Override
  1034         @Override
  1017         boolean run(JdepsConfiguration config) throws IOException {
  1035         boolean run(JdepsConfiguration config) throws IOException {
  1018             return new ModuleExportsAnalyzer(config,
  1036             ModuleExportsAnalyzer analyzer = new ModuleExportsAnalyzer(config,
  1019                                              dependencyFilter(config),
  1037                                                                        dependencyFilter(config),
  1020                                              jdkinternals,
  1038                                                                        jdkinternals,
  1021                                              reduced,
  1039                                                                        reduced,
  1022                                              log,
  1040                                                                        log,
  1023                                              separator).run();
  1041                                                                        separator);
  1024         }
  1042             boolean ok = analyzer.run(options.depth(), options.ignoreMissingDeps);
  1025     }
  1043             if (!ok) {
  1026 
  1044                 reportError("err.cant.list.module.deps");
       
  1045                 log.println();
       
  1046                 analyzer.visitMissingDeps(new SimpleDepVisitor());
       
  1047             }
       
  1048             return ok;
       
  1049         }
       
  1050     }
  1027 
  1051 
  1028     class GenDotFile extends AnalyzeDeps {
  1052     class GenDotFile extends AnalyzeDeps {
  1029         final Path dotOutputDir;
  1053         final Path dotOutputDir;
  1030         GenDotFile(Path dotOutputDir) {
  1054         GenDotFile(Path dotOutputDir) {
  1031             super(CommandOption.GENERATE_DOT_FILE);
  1055             super(CommandOption.GENERATE_DOT_FILE);
  1051                                                    options.showLabel);
  1075                                                    options.showLabel);
  1052             return run(config, writer, type);
  1076             return run(config, writer, type);
  1053         }
  1077         }
  1054     }
  1078     }
  1055 
  1079 
       
  1080     class SimpleDepVisitor implements Analyzer.Visitor {
       
  1081         private Archive source;
       
  1082         @Override
       
  1083         public void visitDependence(String origin, Archive originArchive, String target, Archive targetArchive) {
       
  1084             if (source != originArchive) {
       
  1085                 source = originArchive;
       
  1086                 log.format("%s%n", originArchive);
       
  1087             }
       
  1088             log.format("   %-50s -> %-50s %s%n", origin, target, targetArchive.getName());
       
  1089         }
       
  1090     }
       
  1091 
  1056     /**
  1092     /**
  1057      * Returns a filter used during dependency analysis
  1093      * Returns a filter used during dependency analysis
  1058      */
  1094      */
  1059     private JdepsFilter dependencyFilter(JdepsConfiguration config) {
  1095     private JdepsFilter dependencyFilter(JdepsConfiguration config) {
  1060         // Filter specified by -filter, -package, -regex, and --require options
  1096         // Filter specified by -filter, -package, -regex, and --require options
  1064         builder.includePattern(options.includePattern);
  1100         builder.includePattern(options.includePattern);
  1065 
  1101 
  1066         // target filters
  1102         // target filters
  1067         builder.filter(options.filterSamePackage, options.filterSameArchive);
  1103         builder.filter(options.filterSamePackage, options.filterSameArchive);
  1068         builder.findJDKInternals(options.findJDKInternals);
  1104         builder.findJDKInternals(options.findJDKInternals);
       
  1105         builder.findMissingDeps(options.findMissingDeps);
  1069 
  1106 
  1070         // --require
  1107         // --require
  1071         if (!options.requires.isEmpty()) {
  1108         if (!options.requires.isEmpty()) {
  1072             options.requires.stream()
  1109             options.requires.stream()
  1073                 .forEach(mn -> {
  1110                 .forEach(mn -> {
  1156     }
  1193     }
  1157 
  1194 
  1158     private String version(String key) {
  1195     private String version(String key) {
  1159         // key=version:  mm.nn.oo[-milestone]
  1196         // key=version:  mm.nn.oo[-milestone]
  1160         // key=full:     mm.mm.oo[-milestone]-build
  1197         // key=full:     mm.mm.oo[-milestone]-build
  1161         if (ResourceBundleHelper.versionRB == null) {
       
  1162             return System.getProperty("java.version");
       
  1163         }
       
  1164         try {
  1198         try {
  1165             return ResourceBundleHelper.versionRB.getString(key);
  1199             return ResourceBundleHelper.getVersion(key);
  1166         } catch (MissingResourceException e) {
  1200         } catch (MissingResourceException e) {
  1167             return getMessage("version.unknown", System.getProperty("java.version"));
  1201             return getMessage("version.unknown", System.getProperty("java.version"));
  1168         }
  1202         }
  1169     }
  1203     }
  1170 
  1204 
  1171     static String getMessage(String key, Object... args) {
  1205     static String getMessage(String key, Object... args) {
  1172         try {
  1206         try {
  1173             return MessageFormat.format(ResourceBundleHelper.bundle.getString(key), args);
  1207             return MessageFormat.format(ResourceBundleHelper.getMessage(key), args);
  1174         } catch (MissingResourceException e) {
  1208         } catch (MissingResourceException e) {
  1175             throw new InternalError("Missing message: " + key);
  1209             throw new InternalError("Missing message: " + key);
  1176         }
  1210         }
  1177     }
  1211     }
  1178 
  1212 
  1179     private static class Options {
  1213     private static class Options {
       
  1214         static final int NO_RECURSIVE = 0;
       
  1215         static final int RECURSIVE = 1;
  1180         boolean help;
  1216         boolean help;
  1181         boolean version;
  1217         boolean version;
  1182         boolean fullVersion;
  1218         boolean fullVersion;
  1183         boolean showProfile;
  1219         boolean showProfile;
  1184         boolean showModule = true;
  1220         boolean showModule = true;
  1185         boolean showSummary;
  1221         boolean showSummary;
  1186         boolean apiOnly;
  1222         boolean apiOnly;
  1187         boolean showLabel;
  1223         boolean showLabel;
  1188         boolean findJDKInternals;
  1224         boolean findJDKInternals;
       
  1225         boolean findMissingDeps;
       
  1226         boolean ignoreMissingDeps;
  1189         boolean nowarning = false;
  1227         boolean nowarning = false;
  1190         Analyzer.Type verbose;
  1228         Analyzer.Type verbose;
  1191         // default filter references from same package
  1229         // default filter references from same package
  1192         boolean filterSamePackage = true;
  1230         boolean filterSamePackage = true;
  1193         boolean filterSameArchive = false;
  1231         boolean filterSameArchive = false;
  1194         Pattern filterRegex;
  1232         Pattern filterRegex;
  1195         String classpath;
  1233         String classpath;
  1196         int depth = 1;
  1234         int recursive = -1;     // 0: --no-recursive, 1: --recursive
       
  1235         int depth = -1;
  1197         Set<String> requires = new HashSet<>();
  1236         Set<String> requires = new HashSet<>();
  1198         Set<String> packageNames = new HashSet<>();
  1237         Set<String> packageNames = new HashSet<>();
  1199         Pattern regex;             // apply to the dependences
  1238         Pattern regex;             // apply to the dependences
  1200         Pattern includePattern;
  1239         Pattern includePattern;
  1201         boolean inverse = false;
  1240         boolean inverse = false;
  1220             if (requires.size() > 0) count++;
  1259             if (requires.size() > 0) count++;
  1221             if (regex != null) count++;
  1260             if (regex != null) count++;
  1222             if (packageNames.size() > 0) count++;
  1261             if (packageNames.size() > 0) count++;
  1223             return count;
  1262             return count;
  1224         }
  1263         }
       
  1264 
       
  1265         int depth() {
       
  1266             // ignore -depth if --no-recursive is set
       
  1267             if (recursive == NO_RECURSIVE)
       
  1268                 return 1;
       
  1269 
       
  1270             // depth == 0 if recursive
       
  1271             if (recursive == RECURSIVE && depth == -1)
       
  1272                 return 0;
       
  1273 
       
  1274             // default depth is 1 unless specified via -depth option
       
  1275             return depth == -1 ? 1 : depth;
       
  1276         }
  1225     }
  1277     }
  1226 
  1278 
  1227     private static class ResourceBundleHelper {
  1279     private static class ResourceBundleHelper {
       
  1280         static final String LS = System.lineSeparator();
  1228         static final ResourceBundle versionRB;
  1281         static final ResourceBundle versionRB;
  1229         static final ResourceBundle bundle;
  1282         static final ResourceBundle bundle;
  1230         static final ResourceBundle jdkinternals;
  1283         static final ResourceBundle jdkinternals;
  1231 
  1284 
  1232         static {
  1285         static {
  1244             try {
  1297             try {
  1245                 jdkinternals = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdkinternals");
  1298                 jdkinternals = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdkinternals");
  1246             } catch (MissingResourceException e) {
  1299             } catch (MissingResourceException e) {
  1247                 throw new InternalError("Cannot find jdkinternals resource bundle");
  1300                 throw new InternalError("Cannot find jdkinternals resource bundle");
  1248             }
  1301             }
       
  1302         }
       
  1303 
       
  1304         static String getMessage(String key) {
       
  1305             return bundle.getString(key).replace("\n", LS);
       
  1306         }
       
  1307 
       
  1308         static String getVersion(String key) {
       
  1309             if (ResourceBundleHelper.versionRB == null) {
       
  1310                 return System.getProperty("java.version");
       
  1311             }
       
  1312             return versionRB.getString(key).replace("\n", LS);
       
  1313         }
       
  1314 
       
  1315         static String getSuggestedReplacement(String key) {
       
  1316             return ResourceBundleHelper.jdkinternals.getString(key).replace("\n", LS);
  1249         }
  1317         }
  1250     }
  1318     }
  1251 
  1319 
  1252     /**
  1320     /**
  1253      * Returns the recommended replacement API for the given classname;
  1321      * Returns the recommended replacement API for the given classname;
  1256     private Optional<String> replacementFor(String cn) {
  1324     private Optional<String> replacementFor(String cn) {
  1257         String name = cn;
  1325         String name = cn;
  1258         String value = null;
  1326         String value = null;
  1259         while (value == null && name != null) {
  1327         while (value == null && name != null) {
  1260             try {
  1328             try {
  1261                 value = ResourceBundleHelper.jdkinternals.getString(name);
  1329                 value = ResourceBundleHelper.getSuggestedReplacement(name);
  1262             } catch (MissingResourceException e) {
  1330             } catch (MissingResourceException e) {
  1263                 // go up one subpackage level
  1331                 // go up one subpackage level
  1264                 int i = name.lastIndexOf('.');
  1332                 int i = name.lastIndexOf('.');
  1265                 name = i > 0 ? name.substring(0, i) : null;
  1333                 name = i > 0 ? name.substring(0, i) : null;
  1266             }
  1334             }