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 |
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 |
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 } |